/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 *
 * Copyright (C) 2006 Antonius Hellmann
 * Copyright (C) 2006-2013 Michael Sevakis
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/

//    Shine is an MP3 encoder
//    Copyright (C) 1999-2000  Gabriel Bouvigne
//
//    This library is free software; you can redistribute it and/or
//    modify it under the terms of the GNU Library General Public
//    License as published by the Free Software Foundation; either
//    version 2 of the License, or (at your option) any later version.
//
//    This library is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//    Library General Public License for more details.

#include <inttypes.h>
#include <stdio.h>

#include "codeclib.h"

CODEC_ENC_HEADER

#if NUM_CORES > 1
#define MP3_ENC_COP
#endif

typedef struct
{
    int   type; /* 0=(MPEG2 - 22.05,24,16kHz) 1=(MPEG1 - 44.1,48,32kHz) */
    int   mode; /* 0=stereo, 1=jstereo, 2=dual, 3=mono  */
    int   bitrate;
    int   padding;
    int   num_bands;
    long  bitr_id;
    int   smpl_id;
} mpeg_t;

/* Side information */
typedef struct
{
    uint32_t part2_3_length;
    int      count1;          /* number of 0-1-quadruples  */
    uint32_t global_gain;
    uint32_t table_select[4];
    uint32_t region_0_1;
    uint32_t address1;
    uint32_t address2;
    uint32_t address3;
    long     quantStep;
    long     additStep;
    uint32_t max_val;
} side_info_t;

typedef struct
{
    side_info_t cod_info[2][2];
    mpeg_t   mpg;
    long     frac_per_frame;
    long     byte_per_frame;
    long     req_byte_per_frame;
    long     slot_lag;
    int      sideinfo_len;
    int      mean_bits;
    int      resv_size;
    int      channels;
    int      granules;
    long     src_samplerate;
    long     samplerate;
    short   *samp_buffer;
    unsigned samp_per_frame;
    int      flush_frames;
    int      delay;
    int      padding;
} config_t;

typedef struct
{
    int      bitpos;   /* current bitpos for writing */
    uint32_t bbuf[362];
} bf_data;

struct huffcodetab
{
    int            len;   /* max. index                  */
    const uint8_t *table; /* pointer to array[len][len]  */
    const uint8_t *hlen;  /* pointer to array[len][len]  */
};

struct huffcodebig
{
    int len;     /* max. index                   */
    int linbits; /* number of linbits            */
    int linmax;  /* max number stored in linbits */
};

#define shft4(x)     (((x) +     8) >>  4)
#define shft9(x)     (((x) +   256) >>  9)
#define shft13(x)    (((x) +  4096) >> 13)
#define shft15(x)    (((x) + 16384) >> 15)
#define shft16(x)    (((x) + 32768) >> 16)
#define shft_n(x, n) ( (x) >> (n))
#define SQRT         724 /* sqrt(2) * 512 */

static config_t  cfg                        IBSS_ATTR;
static short     mfbuf       [2*(1152+512)] IBSS_ATTR
    /* for memcpy and 32-bit access */ MEM_ALIGN_ATTR; /* 6656 Bytes */
static int       sb_data     [2][2][18][32] IBSS_ATTR; /* 9216 Bytes */
static int       mdct_freq   [576]          IBSS_ATTR; /* 2304 Bytes */
static char      mdct_sign   [576]          IBSS_ATTR; /*  576 Bytes */
static short     enc_data    [576]          IBSS_ATTR; /* 1152 Bytes */
static uint32_t  scalefac    [22]           IBSS_ATTR; /*   88 Bytes */
static bf_data   coded_data                 IBSS_ATTR; /* 1448 Bytes */
static uint8_t   band_scale_f[22]           IBSS_ATTR; /*   22 Bytes */

#ifdef MP3_ENC_COP
/* 2-entry circular buffer to pass subband data between threads */
/* 18432 bytes is way too much for IRAM and it must be in coherent RAM */
static int     sb_data_buf[2][2][2][18][32] SHAREDBSS_ATTR
                                            MEM_ALIGN_ATTR;
static int     (*sb_data_cod)[2][2][18][32] IBSS_ATTR; /*    4 Bytes */
static int     (*sb_data_enc)[2][2][18][32] IBSS_ATTR; /*    4 Bytes */
#endif /* MP3_ENC_COP */

static const uint8_t ht_count[2][2][16] ICONST_ATTR =
{ { {  1,  5,  4,  5,  6,  5, 4, 4, 7, 3, 6, 0, 7, 2, 3, 1 },     /* table0 */
    {  1,  5,  5,  7,  5,  8, 7, 9, 5, 7, 7, 9, 7, 9, 9,10 } },   /* hleng0 */
  { { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 },     /* table1 */
    {  4,  5,  5,  6,  5,  6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 } } }; /* hleng1 */

static const uint8_t t1HB[4] ICONST_ATTR =
{ 1, 1, 1, 0 };

static const uint8_t t2HB[9] ICONST_ATTR =
{ 1, 2, 1, 3, 1, 1, 3, 2, 0 };

static const uint8_t t3HB[9] ICONST_ATTR =
{ 3, 2, 1, 1, 1, 1, 3, 2, 0 };

static const uint8_t t5HB[16] ICONST_ATTR =
{ 1, 2, 6, 5, 3, 1, 4, 4, 7, 5, 7, 1, 6, 1, 1, 0 };

static const uint8_t t6HB[16] ICONST_ATTR =
{ 7, 3, 5, 1, 6, 2, 3, 2, 5, 4, 4, 1, 3, 3, 2 ,0 };

static const uint8_t t7HB[36] ICONST_ATTR =
{  1, 2,10,19,16,10, 3, 3, 7,10, 5, 3,11, 4,13,17, 8, 4,
  12,11,18,15,11, 2, 7, 6, 9,14, 3, 1, 6, 4, 5, 3, 2, 0 };

static const uint8_t t8HB[36] ICONST_ATTR =
{  3, 4, 6,18,12, 5, 5, 1, 2,16, 9, 3, 7, 3, 5,14, 7, 3,
  19,17,15,13,10, 4,13, 5, 8,11, 5, 1,12, 4, 4, 1, 1, 0 };

static const uint8_t t9HB[36] ICONST_ATTR =
{  7, 5, 9,14,15, 7, 6, 4, 5, 5, 6, 7, 7, 6, 8, 8, 8, 5,
  15, 6, 9,10, 5, 1,11, 7, 9, 6, 4, 1,14, 4, 6, 2, 6, 0 };

static const uint8_t t10HB[64] ICONST_ATTR =
{ 1, 2,10,23,35,30,12,17, 3, 3, 8,12,18,21,12, 7,
 11, 9,15,21,32,40,19, 6,14,13,22,34,46,23,18, 7,
 20,19,33,47,27,22, 9, 3,31,22,41,26,21,20, 5, 3,
 14,13,10,11,16, 6, 5, 1, 9, 8, 7, 8, 4, 4, 2, 0 };

static const uint8_t t11HB[64] ICONST_ATTR =
{ 3, 4,10,24,34,33,21,15, 5, 3, 4,10,32,17,11,10,
 11, 7,13,18,30,31,20, 5,25,11,19,59,27,18,12, 5,
 35,33,31,58,30,16, 7, 5,28,26,32,19,17,15, 8,14,
 14,12, 9,13,14, 9, 4, 1,11, 4, 6, 6, 6, 3, 2, 0 };

static const uint8_t t12HB[64] ICONST_ATTR =
{ 9, 6,16,33,41,39,38,26, 7, 5, 6, 9,23,16,26,11,
 17, 7,11,14,21,30,10, 7,17,10,15,12,18,28,14, 5,
 32,13,22,19,18,16, 9, 5,40,17,31,29,17,13, 4, 2,
 27,12,11,15,10, 7, 4, 1,27,12, 8,12, 6, 3, 1, 0 };

static const uint8_t t13HB[256] ICONST_ATTR =
{  1,  5, 14, 21, 34, 51, 46, 71, 42, 52, 68, 52, 67, 44, 43, 19,
   3,  4, 12, 19, 31, 26, 44, 33, 31, 24, 32, 24, 31, 35, 22, 14,
  15, 13, 23, 36, 59, 49, 77, 65, 29, 40, 30, 40, 27, 33, 42, 16,
  22, 20, 37, 61, 56, 79, 73, 64, 43, 76, 56, 37, 26, 31, 25, 14,
  35, 16, 60, 57, 97, 75,114, 91, 54, 73, 55, 41, 48, 53, 23, 24,
  58, 27, 50, 96, 76, 70, 93, 84, 77, 58, 79, 29, 74, 49, 41, 17,
  47, 45, 78, 74,115, 94, 90, 79, 69, 83, 71, 50, 59, 38, 36, 15,
  72, 34, 56, 95, 92, 85, 91, 90, 86, 73, 77, 65, 51, 44, 43, 42,
  43, 20, 30, 44, 55, 78, 72, 87, 78, 61, 46, 54, 37, 30, 20, 16,
  53, 25, 41, 37, 44, 59, 54, 81, 66, 76, 57, 54, 37, 18, 39, 11,
  35, 33, 31, 57, 42, 82, 72, 80, 47, 58, 55, 21, 22, 26, 38, 22,
  53, 25, 23, 38, 70, 60, 51, 36, 55, 26, 34, 23, 27, 14,  9,  7,
  34, 32, 28, 39, 49, 75, 30, 52, 48, 40, 52, 28, 18, 17,  9,  5,
  45, 21, 34, 64, 56, 50, 49, 45, 31, 19, 12, 15, 10,  7,  6,  3,
  48, 23, 20, 39, 36, 35, 53, 21, 16, 23, 13, 10,  6,  1,  4,  2,
  16, 15, 17, 27, 25, 20, 29, 11, 17, 12, 16,  8,  1,  1,  0,  1 };

static const uint8_t t15HB[256] ICONST_ATTR =
{  7, 12, 18, 53, 47, 76,124,108, 89,123,108,119,107, 81,122, 63,
  13,  5, 16, 27, 46, 36, 61, 51, 42, 70, 52, 83, 65, 41, 59, 36,
  19, 17, 15, 24, 41, 34, 59, 48, 40, 64, 50, 78, 62, 80, 56, 33,
  29, 28, 25, 43, 39, 63, 55, 93, 76, 59, 93, 72, 54, 75, 50, 29,
  52, 22, 42, 40, 67, 57, 95, 79, 72, 57, 89, 69, 49, 66, 46, 27,
  77, 37, 35, 66, 58, 52, 91, 74, 62, 48, 79, 63, 90, 62, 40, 38,
 125, 32, 60, 56, 50, 92, 78, 65, 55, 87, 71, 51, 73, 51, 70, 30,
 109, 53, 49, 94, 88, 75, 66,122, 91, 73, 56, 42, 64, 44, 21, 25,
  90, 43, 41, 77, 73, 63, 56, 92, 77, 66, 47, 67, 48, 53, 36, 20,
  71, 34, 67, 60, 58, 49, 88, 76, 67,106, 71, 54, 38, 39, 23, 15,
 109, 53, 51, 47, 90, 82, 58, 57, 48, 72, 57, 41, 23, 27, 62,  9,
  86, 42, 40, 37, 70, 64, 52, 43, 70, 55, 42, 25, 29, 18, 11, 11,
 118, 68, 30, 55, 50, 46, 74, 65, 49, 39, 24, 16, 22, 13, 14,  7,
  91, 44, 39, 38, 34, 63, 52, 45, 31, 52, 28, 19, 14,  8,  9,  3,
 123, 60, 58, 53, 47, 43, 32, 22, 37, 24, 17, 12, 15, 10,  2,  1,
  71, 37, 34, 30, 28, 20, 17, 26, 21, 16, 10,  6,  8,  6,  2,  0 };

static const uint16_t t16HB[256] ICONST_ATTR =
{  1,  5, 14, 44, 74, 63,110, 93,172, 149, 138,242, 225, 195, 376, 17,
   3,  4, 12, 20, 35, 62, 53, 47, 83,  75,  68,119, 201, 107, 207,  9,
  15, 13, 23, 38, 67, 58,103, 90,161,  72, 127,117, 110, 209, 206, 16,
  45, 21, 39, 69, 64,114, 99, 87,158, 140, 252,212, 199, 387, 365, 26,
  75, 36, 68, 65,115,101,179,164,155, 264, 246,226, 395, 382, 362,  9,
  66, 30, 59, 56,102,185,173,265,142, 253, 232,400, 388, 378, 445, 16,
 111, 54, 52,100,184,178,160,133,257, 244, 228,217, 385, 366, 715, 10,
  98, 48, 91, 88,165,157,148,261,248, 407, 397,372, 380, 889, 884,  8,
  85, 84, 81,159,156,143,260,249,427, 401, 392,383, 727, 713, 708,  7,
 154, 76, 73,141,131,256,245,426,406, 394, 384,735, 359, 710, 352, 11,
 139,129, 67,125,247,233,229,219,393, 743, 737,720, 885, 882, 439,  4,
 243,120,118,115,227,223,396,746,742, 736, 721,712, 706, 223, 436,  6,
 202,224,222,218,216,389,386,381,364, 888, 443,707, 440, 437,1728,  4,
 747,211,210,208,370,379,734,723,714,1735, 883,877, 876,3459, 865,  2,
 377,369,102,187,726,722,358,711,709, 866,1734,871,3458, 870, 434,  0,
  12, 10,  7, 11, 10, 17, 11,  9, 13,  12,  10,  7,   5,   3,   1,  3 };

static const uint16_t t24HB[256] ICONST_ATTR =
{  15, 13, 46, 80,146,262,248,434,426,669,653,649,621,517,1032, 88,
   14, 12, 21, 38, 71,130,122,216,209,198,327,345,319,297, 279, 42,
   47, 22, 41, 74, 68,128,120,221,207,194,182,340,315,295, 541, 18,
   81, 39, 75, 70,134,125,116,220,204,190,178,325,311,293, 271, 16,
  147, 72, 69,135,127,118,112,210,200,188,352,323,306,285, 540, 14,
  263, 66,129,126,119,114,214,202,192,180,341,317,301,281, 262, 12,
  249,123,121,117,113,215,206,195,185,347,330,308,291,272, 520, 10,
  435,115,111,109,211,203,196,187,353,332,313,298,283,531, 381, 17,
  427,212,208,205,201,193,186,177,169,320,303,286,268,514, 377, 16,
  335,199,197,191,189,181,174,333,321,305,289,275,521,379, 371, 11,
  668,184,183,179,175,344,331,314,304,290,277,530,383,373, 366, 10,
  652,346,171,168,164,318,309,299,287,276,263,513,375,368, 362,  6,
  648,322,316,312,307,302,292,284,269,261,512,376,370,364, 359,  4,
  620,300,296,294,288,282,273,266,515,380,374,369,365,361, 357,  2,
 1033,280,278,274,267,264,259,382,378,372,367,363,360,358, 356,  0,
   43, 20, 19, 17, 15, 13, 11,  9,  7,  6,  4,  7,  5,  3,   1,  3 };

static const uint32_t tab1315[256] ICONST_ATTR =
{ 0x010003,0x050005,0x070006,0x080008,0x090008,0x0a0009,0x0a000a,0x0b000a,
  0x0a000a,0x0b000b,0x0c000b,0x0c000c,0x0d000c,0x0d000c,0x0e000d,0x0e000e,
  0x040005,0x060005,0x080007,0x090008,0x0a0009,0x0a0009,0x0b000a,0x0b000a,
  0x0b000a,0x0b000b,0x0c000b,0x0c000c,0x0d000c,0x0e000c,0x0e000d,0x0e000d,
  0x070006,0x080007,0x090007,0x0a0008,0x0b0009,0x0b0009,0x0c000a,0x0c000a,
  0x0b000a,0x0c000b,0x0c000b,0x0d000c,0x0d000c,0x0e000d,0x0f000d,0x0f000d,
  0x080007,0x090008,0x0a0008,0x0b0009,0x0b0009,0x0c000a,0x0c000a,0x0c000b,
  0x0c000b,0x0d000b,0x0d000c,0x0d000c,0x0d000c,0x0e000d,0x0f000d,0x0f000d,
  0x090008,0x090008,0x0b0009,0x0b0009,0x0c000a,0x0c000a,0x0d000b,0x0d000b,
  0x0c000b,0x0d000b,0x0d000c,0x0e000c,0x0e000c,0x0f000d,0x0f000d,0x10000d,
  0x0a0009,0x0a0009,0x0b0009,0x0c000a,0x0c000a,0x0c000a,0x0d000b,0x0d000b,
  0x0d000b,0x0d000b,0x0e000c,0x0d000c,0x0f000d,0x0f000d,0x10000d,0x10000e,
  0x0a000a,0x0b0009,0x0c000a,0x0c000a,0x0d000a,0x0d000b,0x0d000b,0x0d000b,
  0x0d000b,0x0e000c,0x0e000c,0x0e000c,0x0f000d,0x0f000d,0x10000e,0x10000e,
  0x0b000a,0x0b000a,0x0c000a,0x0d000b,0x0d000b,0x0d000b,0x0e000b,0x0e000c,
  0x0e000c,0x0e000c,0x0f000c,0x0f000c,0x0f000d,0x10000d,0x12000d,0x12000e,
  0x0a000a,0x0a000a,0x0b000a,0x0c000b,0x0c000b,0x0d000b,0x0d000b,0x0e000c,
  0x0e000c,0x0e000c,0x0e000c,0x0f000d,0x0f000d,0x10000e,0x11000e,0x11000e,
  0x0b000a,0x0b000a,0x0c000b,0x0c000b,0x0d000b,0x0d000b,0x0d000c,0x0f000c,
  0x0e000c,0x0f000d,0x0f000d,0x10000d,0x10000d,0x10000e,0x12000e,0x11000e,
  0x0b000b,0x0c000b,0x0c000b,0x0d000b,0x0d000c,0x0e000c,0x0e000c,0x0f000c,
  0x0e000c,0x0f000d,0x10000d,0x0f000d,0x10000d,0x11000e,0x12000f,0x13000e,
  0x0c000b,0x0c000b,0x0c000b,0x0d000b,0x0e000c,0x0e000c,0x0e000c,0x0e000c,
  0x0f000d,0x0f000d,0x0f000d,0x10000d,0x11000e,0x11000e,0x11000e,0x12000f,
  0x0c000c,0x0d000c,0x0d000b,0x0e000c,0x0e000c,0x0f000c,0x0e000d,0x0f000d,
  0x10000d,0x10000d,0x11000d,0x11000d,0x11000e,0x12000e,0x12000f,0x12000f,
  0x0d000c,0x0d000c,0x0e000c,0x0f000c,0x0f000c,0x0f000d,0x10000d,0x10000d,
  0x10000d,0x10000e,0x10000e,0x11000e,0x12000e,0x11000e,0x12000f,0x12000f,
  0x0e000d,0x0e000d,0x0e000d,0x0f000d,0x0f000d,0x0f000d,0x11000d,0x10000d,
  0x10000e,0x13000e,0x11000e,0x11000e,0x11000f,0x13000f,0x12000e,0x12000f,
  0x0d000d,0x0e000d,0x0f000d,0x10000d,0x10000d,0x10000d,0x11000d,0x10000e,
  0x11000e,0x11000e,0x12000e,0x12000e,0x15000f,0x14000f,0x15000f,0x12000f };

static const uint32_t tab01[16] ICONST_ATTR =
{ 0x10004,0x50005,0x50005,0x70006,0x50005,0x80006,0x70006,0x90007,
  0x50005,0x70006,0x70006,0x90007,0x70006,0x90007,0x90007,0xa0008 };

static const uint32_t tab23[ 9] ICONST_ATTR =
{ 0x10002,0x40003,0x70007,0x40004,0x50004,0x70007,0x60006,0x70007,0x80008 };

static const uint32_t tab56[16] ICONST_ATTR =
{ 0x10003,0x40004,0x70006,0x80008,0x40004,0x50004,0x80006,0x90007,
  0x70005,0x80006,0x90007,0xa0008,0x80007,0x80007,0x90008,0xa0009 };

static const uint32_t tab789[36] ICONST_ATTR =
{ 0x100803,0x401004,0x701c06,0x902407,0x902409,0xa0280a,0x401004,0x601005,
  0x801806,0x902807,0x902808,0xa0280a,0x701c05,0x701806,0x902007,0xa02808,
  0xa02809,0xb02c0a,0x802407,0x902807,0xa02808,0xb02c09,0xb02c09,0xb0300a,
  0x802408,0x902408,0xa02809,0xb02c09,0xb0300a,0xc0300b,0x902809,0xa02809,
  0xb02c0a,0xc02c0a,0xc0340b,0xc0340b };

static const uint32_t tabABC[64] ICONST_ATTR =
{ 0x100804,0x401004,0x701806,0x902008,0xa02409,0xa0280a,0xa0240a,0xb0280a,
  0x401004,0x601405,0x801806,0x902007,0xa02809,0xb02809,0xa0240a,0xa0280a,
  0x701806,0x801c06,0x902007,0xa02408,0xb02809,0xc02c0a,0xb02809,0xb0280a,
  0x802007,0x902007,0xa02408,0xb02c08,0xc02809,0xc0300a,0xb0280a,0xc02c0a,
  0x902408,0xa02808,0xb02809,0xc02c09,0xc02c0a,0xc0300a,0xc02c0a,0xc0300b,
  0xa02409,0xb02809,0xc02c0a,0xc0300a,0xd0300a,0xd0340b,0xc0300a,0xd0340b,
  0x902409,0xa02409,0xb02409,0xc0280a,0xc02c0a,0xc0300b,0xd0300b,0xd0300c,
  0xa0240a,0xa0240a,0xb0280a,0xc02c0b,0xc0300b,0xd0300b,0xd0300b,0xd0300c };

static const uint32_t tab1624[256] ICONST_ATTR =
{ 0x010004,0x050005,0x070007,0x090008,0x0a0009,0x0a000a,0x0b000a,0x0b000b,
  0x0c000b,0x0c000c,0x0c000c,0x0d000c,0x0d000c,0x0d000c,0x0e000d,0x0a000a,
  0x040005,0x060006,0x080007,0x090008,0x0a0009,0x0b000a,0x0b000a,0x0b000b,
  0x0c000b,0x0c000b,0x0c000c,0x0d000c,0x0e000c,0x0d000c,0x0e000c,0x0a000a,
  0x070007,0x080007,0x090008,0x0a0009,0x0b0009,0x0b000a,0x0c000a,0x0c000b,
  0x0d000b,0x0c000b,0x0d000b,0x0d000c,0x0d000c,0x0e000c,0x0e000d,0x0b0009,
  0x090008,0x090008,0x0a0009,0x0b0009,0x0b000a,0x0c000a,0x0c000a,0x0c000b,
  0x0d000b,0x0d000b,0x0e000b,0x0e000c,0x0e000c,0x0f000c,0x0f000c,0x0c0009,
  0x0a0009,0x0a0009,0x0b0009,0x0b000a,0x0c000a,0x0c000a,0x0d000a,0x0d000b,
  0x0d000b,0x0e000b,0x0e000c,0x0e000c,0x0f000c,0x0f000c,0x0f000d,0x0b0009,
  0x0a000a,0x0a0009,0x0b000a,0x0b000a,0x0c000a,0x0d000a,0x0d000b,0x0e000b,
  0x0d000b,0x0e000b,0x0e000c,0x0f000c,0x0f000c,0x0f000c,0x10000c,0x0c0009,
  0x0b000a,0x0b000a,0x0b000a,0x0c000a,0x0d000a,0x0d000b,0x0d000b,0x0d000b,
  0x0e000b,0x0e000c,0x0e000c,0x0e000c,0x0f000c,0x0f000c,0x10000d,0x0c0009,
  0x0b000b,0x0b000a,0x0c000a,0x0c000a,0x0d000b,0x0d000b,0x0d000b,0x0e000b,
  0x0e000c,0x0f000c,0x0f000c,0x0f000c,0x0f000c,0x11000d,0x11000d,0x0c000a,
  0x0b000b,0x0c000b,0x0c000b,0x0d000b,0x0d000b,0x0d000b,0x0e000b,0x0e000b,
  0x0f000b,0x0f000c,0x0f000c,0x0f000c,0x10000c,0x10000d,0x10000d,0x0c000a,
  0x0c000b,0x0c000b,0x0c000b,0x0d000b,0x0d000b,0x0e000b,0x0e000b,0x0f000c,
  0x0f000c,0x0f000c,0x0f000c,0x10000c,0x0f000d,0x10000d,0x0f000d,0x0d000a,
  0x0c000c,0x0d000b,0x0c000b,0x0d000b,0x0e000b,0x0e000c,0x0e000c,0x0e000c,
  0x0f000c,0x10000c,0x10000c,0x10000d,0x11000d,0x11000d,0x10000d,0x0c000a,
  0x0d000c,0x0d000c,0x0d000b,0x0d000b,0x0e000b,0x0e000c,0x0f000c,0x10000c,
  0x10000c,0x10000c,0x10000c,0x10000d,0x10000d,0x0f000d,0x10000d,0x0d000a,
  0x0d000c,0x0e000c,0x0e000c,0x0e000c,0x0e000c,0x0f000c,0x0f000c,0x0f000c,
  0x0f000c,0x11000c,0x10000d,0x10000d,0x10000d,0x10000d,0x12000d,0x0d000a,
  0x0f000c,0x0e000c,0x0e000c,0x0e000c,0x0f000c,0x0f000c,0x10000c,0x10000c,
  0x10000d,0x12000d,0x11000d,0x11000d,0x11000d,0x13000d,0x11000d,0x0d000a,
  0x0e000d,0x0f000c,0x0d000c,0x0e000c,0x10000c,0x10000c,0x0f000c,0x10000d,
  0x10000d,0x11000d,0x12000d,0x11000d,0x13000d,0x11000d,0x10000d,0x0d000a,
  0x0a0009,0x0a0009,0x0a0009,0x0b0009,0x0b0009,0x0c0009,0x0c0009,0x0c0009,
  0x0d0009,0x0d0009,0x0d0009,0x0d000a,0x0d000a,0x0d000a,0x0d000a,0x0a0006 };

static const uint8_t t1l[8] ICONST_ATTR =
{ 1,3,2,3,1,4,3,5 };

static const uint8_t t2l[9] ICONST_ATTR =
{ 1,3,6,3,3,5,5,5,6 };

static const uint8_t t3l[9] ICONST_ATTR =
{ 2,2,6,3,2,5,5,5,6 };

static const uint8_t t5l[16] ICONST_ATTR =
{ 1,3,6,7,3,3,6,7,6,6,7,8,7,6,7,8 };

static const uint8_t t6l[16] ICONST_ATTR =
{ 3,3,5,7,3,2,4,5,4,4,5,6,6,5,6,7 };

static const uint8_t t7l[36] ICONST_ATTR =
{ 1, 3, 6, 8, 8, 9, 3, 4, 6, 7, 7, 8, 6, 5, 7, 8, 8, 9,
  7, 7, 8, 9, 9, 9, 7, 7, 8, 9, 9,10, 8, 8, 9,10,10,10 };

static const uint8_t t8l[36] ICONST_ATTR =
{ 2, 3, 6, 8, 8, 9, 3, 2, 4, 8, 8, 8, 6, 4, 6, 8, 8, 9,
  8, 8, 8, 9, 9,10, 8, 7, 8, 9,10,10, 9, 8, 9, 9,11,11 };

static const uint8_t t9l[36] ICONST_ATTR =
{ 3, 3, 5, 6, 8, 9, 3, 3, 4, 5, 6, 8, 4, 4, 5, 6, 7, 8,
  6, 5, 6, 7, 7, 8, 7, 6, 7, 7, 8, 9, 8, 7, 8, 8, 9, 9 };

static const uint8_t t10l[64] ICONST_ATTR =
{ 1, 3, 6, 8, 9, 9, 9,10, 3, 4, 6, 7, 8, 9, 8, 8,
  6, 6, 7, 8, 9,10, 9, 9, 7, 7, 8, 9,10,10, 9,10,
  8, 8, 9,10,10,10,10,10, 9, 9,10,10,11,11,10,11,
  8, 8, 9,10,10,10,11,11, 9, 8, 9,10,10,11,11,11 };

static const uint8_t t11l[64] ICONST_ATTR =
{ 2, 3, 5, 7, 8, 9, 8, 9, 3, 3, 4, 6, 8, 8, 7, 8,
  5, 5, 6, 7, 8, 9, 8, 8, 7, 6, 7, 9, 8,10, 8, 9,
  8, 8, 8, 9, 9,10, 9,10, 8, 8, 9,10,10,11,10,11,
  8, 7, 7, 8, 9,10,10,10, 8, 7, 8, 9,10,10,10,10 };

static const uint8_t t12l[64] ICONST_ATTR =
{ 4, 3, 5, 7, 8, 9, 9, 9, 3, 3, 4, 5, 7, 7, 8, 8,
  5, 4, 5, 6, 7, 8, 7, 8, 6, 5, 6, 6, 7, 8, 8, 8,
  7, 6, 7, 7, 8, 8, 8, 9, 8, 7, 8, 8, 8, 9, 8, 9,
  8, 7, 7, 8, 8, 9, 9,10, 9, 8, 8, 9, 9, 9, 9,10 };

static const uint8_t t13l[256] ICONST_ATTR =
{ 1, 4, 6, 7, 8, 9, 9,10, 9,10,11,11,12,12,13,13,
  3, 4, 6, 7, 8, 8, 9, 9, 9, 9,10,10,11,12,12,12,
  6, 6, 7, 8, 9, 9,10,10, 9,10,10,11,11,12,13,13,
  7, 7, 8, 9, 9,10,10,10,10,11,11,11,11,12,13,13,
  8, 7, 9, 9,10,10,11,11,10,11,11,12,12,13,13,14,
  9, 8, 9,10,10,10,11,11,11,11,12,11,13,13,14,14,
  9, 9,10,10,11,11,11,11,11,12,12,12,13,13,14,14,
 10, 9,10,11,11,11,12,12,12,12,13,13,13,14,16,16,
  9, 8, 9,10,10,11,11,12,12,12,12,13,13,14,15,15,
 10, 9,10,10,11,11,11,13,12,13,13,14,14,14,16,15,
 10,10,10,11,11,12,12,13,12,13,14,13,14,15,16,17,
 11,10,10,11,12,12,12,12,13,13,13,14,15,15,15,16,
 11,11,11,12,12,13,12,13,14,14,15,15,15,16,16,16,
 12,11,12,13,13,13,14,14,14,14,14,15,16,15,16,16,
 13,12,12,13,13,13,15,14,14,17,15,15,15,17,16,16,
 12,12,13,14,14,14,15,14,15,15,16,16,19,18,19,16 };

static const uint8_t t15l[256] ICONST_ATTR =
{ 3, 4, 5, 7, 7, 8, 9, 9, 9,10,10,11,11,11,12,13,
  4, 3, 5, 6, 7, 7, 8, 8, 8, 9, 9,10,10,10,11,11,
  5, 5, 5, 6, 7, 7, 8, 8, 8, 9, 9,10,10,11,11,11,
  6, 6, 6, 7, 7, 8, 8, 9, 9, 9,10,10,10,11,11,11,
  7, 6, 7, 7, 8, 8, 9, 9, 9, 9,10,10,10,11,11,11,
  8, 7, 7, 8, 8, 8, 9, 9, 9, 9,10,10,11,11,11,12,
  9, 7, 8, 8, 8, 9, 9, 9, 9,10,10,10,11,11,12,12,
  9, 8, 8, 9, 9, 9, 9,10,10,10,10,10,11,11,11,12,
  9, 8, 8, 9, 9, 9, 9,10,10,10,10,11,11,12,12,12,
  9, 8, 9, 9, 9, 9,10,10,10,11,11,11,11,12,12,12,
 10, 9, 9, 9,10,10,10,10,10,11,11,11,11,12,13,12,
 10, 9, 9, 9,10,10,10,10,11,11,11,11,12,12,12,13,
 11,10, 9,10,10,10,11,11,11,11,11,11,12,12,13,13,
 11,10,10,10,10,11,11,11,11,12,12,12,12,12,13,13,
 12,11,11,11,11,11,11,11,12,12,12,12,13,13,12,13,
 12,11,11,11,11,11,11,12,12,12,12,12,13,13,13,13 };

static const uint8_t t16l[256] ICONST_ATTR =
{ 1, 4, 6, 8, 9, 9,10,10,11,11,11,12,12,12,13, 9,
  3, 4, 6, 7, 8, 9, 9, 9,10,10,10,11,12,11,12, 8,
  6, 6, 7, 8, 9, 9,10,10,11,10,11,11,11,12,12, 9,
  8, 7, 8, 9, 9,10,10,10,11,11,12,12,12,13,13,10,
  9, 8, 9, 9,10,10,11,11,11,12,12,12,13,13,13, 9,
  9, 8, 9, 9,10,11,11,12,11,12,12,13,13,13,14,10,
 10, 9, 9,10,11,11,11,11,12,12,12,12,13,13,14,10,
 10, 9,10,10,11,11,11,12,12,13,13,13,13,15,15,10,
 10,10,10,11,11,11,12,12,13,13,13,13,14,14,14,10,
 11,10,10,11,11,12,12,13,13,13,13,14,13,14,13,11,
 11,11,10,11,12,12,12,12,13,14,14,14,15,15,14,10,
 12,11,11,11,12,12,13,14,14,14,14,14,14,13,14,11,
 12,12,12,12,12,13,13,13,13,15,14,14,14,14,16,11,
 14,12,12,12,13,13,14,14,14,16,15,15,15,17,15,11,
 13,13,11,12,14,14,13,14,14,15,16,15,17,15,14,11,
  9, 8, 8, 9, 9,10,10,10,11,11,11,11,11,11,11, 8 };

static const uint8_t t24l[256] ICONST_ATTR =
{ 4, 4, 6, 7, 8, 9, 9,10,10,11,11,11,11,11,12, 9,
  4, 4, 5, 6, 7, 8, 8, 9, 9, 9,10,10,10,10,10, 8,
  6, 5, 6, 7, 7, 8, 8, 9, 9, 9, 9,10,10,10,11, 7,
  7, 6, 7, 7, 8, 8, 8, 9, 9, 9, 9,10,10,10,10, 7,
  8, 7, 7, 8, 8, 8, 8, 9, 9, 9,10,10,10,10,11, 7,
  9, 7, 8, 8, 8, 8, 9, 9, 9, 9,10,10,10,10,10, 7,
  9, 8, 8, 8, 8, 9, 9, 9, 9,10,10,10,10,10,11, 7,
 10, 8, 8, 8, 9, 9, 9, 9,10,10,10,10,10,11,11, 8,
 10, 9, 9, 9, 9, 9, 9, 9, 9,10,10,10,10,11,11, 8,
 10, 9, 9, 9, 9, 9, 9,10,10,10,10,10,11,11,11, 8,
 11, 9, 9, 9, 9,10,10,10,10,10,10,11,11,11,11, 8,
 11,10, 9, 9, 9,10,10,10,10,10,10,11,11,11,11, 8,
 11,10,10,10,10,10,10,10,10,10,11,11,11,11,11, 8,
 11,10,10,10,10,10,10,10,11,11,11,11,11,11,11, 8,
 12,10,10,10,10,10,10,11,11,11,11,11,11,11,11, 8,
  8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 4 };

static const struct huffcodetab ht[16] ICONST_ATTR =
{ {  0,  NULL, NULL }, /* Apparently not used */
  {  2,  t1HB,  t1l },
  {  3,  t2HB,  t2l },
  {  3,  t3HB,  t3l },
  {  0,  NULL, NULL }, /* Apparently not used */
  {  4,  t5HB,  t5l },
  {  4,  t6HB,  t6l },
  {  6,  t7HB,  t7l },
  {  6,  t8HB,  t8l },
  {  6,  t9HB,  t9l },
  {  8, t10HB, t10l },
  {  8, t11HB, t11l },
  {  8, t12HB, t12l },
  { 16, t13HB, t13l },
  {  0,  NULL, NULL }, /* Apparently not used */
  { 16, t15HB, t15l } };

static const struct huffcodebig ht_big[16] ICONST_ATTR =
{ { 16,  1,    1 },
  { 16,  2,    3 },
  { 16,  3,    7 },
  { 16,  4,   15 },
  { 16,  6,   63 },
  { 16,  8,  255 },
  { 16, 10, 1023 },
  { 16, 13, 8191 },
  { 16,  4,   15 },
  { 16,  5,   31 },
  { 16,  6,   63 },
  { 16,  7,  127 },
  { 16,  8,  255 },
  { 16,  9,  511 },
  { 16, 11, 2047 },
  { 16, 13, 8191 } };

static const struct
{
  uint32_t region0_cnt;
  uint32_t region1_cnt;
} subdv_table[23] ICONST_ATTR =
{ { 0, 0 }, /*  0 bands */
  { 0, 0 }, /*  1 bands */
  { 0, 0 }, /*  2 bands */
  { 0, 0 }, /*  3 bands */
  { 0, 0 }, /*  4 bands */
  { 0, 1 }, /*  5 bands */
  { 1, 1 }, /*  6 bands */
  { 1, 1 }, /*  7 bands */
  { 1, 2 }, /*  8 bands */
  { 2, 2 }, /*  9 bands */
  { 2, 3 }, /* 10 bands */
  { 2, 3 }, /* 11 bands */
  { 3, 4 }, /* 12 bands */
  { 3, 4 }, /* 13 bands */
  { 3, 4 }, /* 14 bands */
  { 4, 5 }, /* 15 bands */
  { 4, 5 }, /* 16 bands */
  { 4, 6 }, /* 17 bands */
  { 5, 6 }, /* 18 bands */
  { 5, 6 }, /* 19 bands */
  { 5, 7 }, /* 20 bands */
  { 6, 7 }, /* 21 bands */
  { 6, 7 }, /* 22 bands */
};

/* Not ICONST: Appropriate table copied to scalefac */
static const uint32_t sf_band[6][22] =
{
/* Table B.2.b: 22.05 kHz */
{   6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,
  116,140,168,200,238,284,336,396,464,522,576 },
/* Table B.2.c: 24 kHz */
{   6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,
  114,136,162,194,232,278,330,394,464,540,576 },
/* Table B.2.a: 16 kHz */
{   6, 12, 18, 24, 30, 36, 44, 45, 66, 80, 96,
  116,140,168,200,238,248,336,396,464,522,576 },
/* Table B.8.b: 44.1 kHz */
{   4,  8, 12, 16, 20, 24, 30, 36, 44, 52, 62,
   74, 90,110,134,162,196,238,288,342,418,576 },
/* Table B.8.c: 48 kHz */
{   4,  8, 12, 16, 20, 24, 30, 36, 42, 50, 60,
   72, 88,106,128,156,190,230,276,330,384,576 },
/* Table B.8.a: 32 kHz */
{   4,  8, 12, 16, 20, 24, 30, 36, 44, 54, 66,
   82,102,126,156,194,240,296,364,448,550,576 } };

/*  int2idx[i] = sqrt(i*sqrt(i)); */
static const short int2idx[4096] ICONST_ATTR =
{  0,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  6,  6,  7,  7,  8,
   8,  8,  9,  9,  9, 10, 10, 11, 11, 11, 12, 12, 12, 12, 13, 13,
  13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18,
  18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 22, 22, 22, 22,
  23, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26,
  27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30,
  31, 31, 31, 31, 32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 34,
  34, 35, 35, 35, 35, 36, 36, 36, 36, 36, 37, 37, 37, 37, 38, 38,
  38, 38, 38, 39, 39, 39, 39, 40, 40, 40, 40, 40, 41, 41, 41, 41,
  42, 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 44, 44, 45, 45,
  45, 45, 45, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 48, 48, 48,
  48, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51,
  52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 55,
  55, 55, 55, 55, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 58, 58,
  58, 58, 58, 58, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 61, 61,
  61, 61, 61, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 64, 64,
  64, 64, 64, 65, 65, 65, 65, 65, 65, 66, 66, 66, 66, 66, 67, 67,
  67, 67, 67, 68, 68, 68, 68, 68, 68, 69, 69, 69, 69, 69, 70, 70,
  70, 70, 70, 70, 71, 71, 71, 71, 71, 72, 72, 72, 72, 72, 72, 73,
  73, 73, 73, 73, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75,
  76, 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 78, 78, 78, 78, 78,
  78, 79, 79, 79, 79, 79, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81,
  81, 81, 82, 82, 82, 82, 82, 82, 83, 83, 83, 83, 83, 84, 84, 84,
  84, 84, 84, 85, 85, 85, 85, 85, 85, 86, 86, 86, 86, 86, 86, 87,
  87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89,
  89, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 92, 92, 92,
  92, 92, 92, 93, 93, 93, 93, 93, 93, 94, 94, 94, 94, 94, 94, 95,
  95, 95, 95, 95, 95, 96, 96, 96, 96, 96, 96, 97, 97, 97, 97, 97,
  97, 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 99,100,100,
 100,100,100,100,101,101,101,101,101,101,102,102,102,102,102,102,
 103,103,103,103,103,103,104,104,104,104,104,104,104,105,105,105,
 105,105,105,106,106,106,106,106,106,107,107,107,107,107,107,107,
 108,108,108,108,108,108,109,109,109,109,109,109,110,110,110,110,
 110,110,110,111,111,111,111,111,111,112,112,112,112,112,112,112,
 113,113,113,113,113,113,114,114,114,114,114,114,115,115,115,115,
 115,115,115,116,116,116,116,116,116,117,117,117,117,117,117,117,
 118,118,118,118,118,118,118,119,119,119,119,119,119,120,120,120,
 120,120,120,120,121,121,121,121,121,121,122,122,122,122,122,122,
 122,123,123,123,123,123,123,123,124,124,124,124,124,124,125,125,
 125,125,125,125,125,126,126,126,126,126,126,126,127,127,127,127,
 127,127,128,128,128,128,128,128,128,129,129,129,129,129,129,129,
 130,130,130,130,130,130,131,131,131,131,131,131,131,132,132,132,
 132,132,132,132,133,133,133,133,133,133,133,134,134,134,134,134,
 134,134,135,135,135,135,135,135,136,136,136,136,136,136,136,137,
 137,137,137,137,137,137,138,138,138,138,138,138,138,139,139,139,
 139,139,139,139,140,140,140,140,140,140,140,141,141,141,141,141,
 141,141,142,142,142,142,142,142,142,143,143,143,143,143,143,143,
 144,144,144,144,144,144,144,145,145,145,145,145,145,145,146,146,
 146,146,146,146,146,147,147,147,147,147,147,147,148,148,148,148,
 148,148,148,149,149,149,149,149,149,149,150,150,150,150,150,150,
 150,151,151,151,151,151,151,151,152,152,152,152,152,152,152,153,
 153,153,153,153,153,153,154,154,154,154,154,154,154,154,155,155,
 155,155,155,155,155,156,156,156,156,156,156,156,157,157,157,157,
 157,157,157,158,158,158,158,158,158,158,159,159,159,159,159,159,
 159,160,160,160,160,160,160,160,160,161,161,161,161,161,161,161,
 162,162,162,162,162,162,162,163,163,163,163,163,163,163,163,164,
 164,164,164,164,164,164,165,165,165,165,165,165,165,166,166,166,
 166,166,166,166,167,167,167,167,167,167,167,167,168,168,168,168,
 168,168,168,169,169,169,169,169,169,169,169,170,170,170,170,170,
 170,170,171,171,171,171,171,171,171,172,172,172,172,172,172,172,
 172,173,173,173,173,173,173,173,174,174,174,174,174,174,174,174,
 175,175,175,175,175,175,175,176,176,176,176,176,176,176,176,177,
 177,177,177,177,177,177,178,178,178,178,178,178,178,178,179,179,
 179,179,179,179,179,180,180,180,180,180,180,180,180,181,181,181,
 181,181,181,181,182,182,182,182,182,182,182,182,183,183,183,183,
 183,183,183,184,184,184,184,184,184,184,184,185,185,185,185,185,
 185,185,186,186,186,186,186,186,186,186,187,187,187,187,187,187,
 187,187,188,188,188,188,188,188,188,189,189,189,189,189,189,189,
 189,190,190,190,190,190,190,190,190,191,191,191,191,191,191,191,
 192,192,192,192,192,192,192,192,193,193,193,193,193,193,193,193,
 194,194,194,194,194,194,194,195,195,195,195,195,195,195,195,196,
 196,196,196,196,196,196,196,197,197,197,197,197,197,197,197,198,
 198,198,198,198,198,198,199,199,199,199,199,199,199,199,200,200,
 200,200,200,200,200,200,201,201,201,201,201,201,201,201,202,202,
 202,202,202,202,202,202,203,203,203,203,203,203,203,204,204,204,
 204,204,204,204,204,205,205,205,205,205,205,205,205,206,206,206,
 206,206,206,206,206,207,207,207,207,207,207,207,207,208,208,208,
 208,208,208,208,208,209,209,209,209,209,209,209,209,210,210,210,
 210,210,210,210,210,211,211,211,211,211,211,211,211,212,212,212,
 212,212,212,212,212,213,213,213,213,213,213,213,213,214,214,214,
 214,214,214,214,214,215,215,215,215,215,215,215,215,216,216,216,
 216,216,216,216,216,217,217,217,217,217,217,217,217,218,218,218,
 218,218,218,218,218,219,219,219,219,219,219,219,219,220,220,220,
 220,220,220,220,220,221,221,221,221,221,221,221,221,222,222,222,
 222,222,222,222,222,223,223,223,223,223,223,223,223,224,224,224,
 224,224,224,224,224,225,225,225,225,225,225,225,225,226,226,226,
 226,226,226,226,226,227,227,227,227,227,227,227,227,228,228,228,
 228,228,228,228,228,229,229,229,229,229,229,229,229,229,230,230,
 230,230,230,230,230,230,231,231,231,231,231,231,231,231,232,232,
 232,232,232,232,232,232,233,233,233,233,233,233,233,233,234,234,
 234,234,234,234,234,234,234,235,235,235,235,235,235,235,235,236,
 236,236,236,236,236,236,236,237,237,237,237,237,237,237,237,238,
 238,238,238,238,238,238,238,238,239,239,239,239,239,239,239,239,
 240,240,240,240,240,240,240,240,241,241,241,241,241,241,241,241,
 242,242,242,242,242,242,242,242,242,243,243,243,243,243,243,243,
 243,244,244,244,244,244,244,244,244,245,245,245,245,245,245,245,
 245,245,246,246,246,246,246,246,246,246,247,247,247,247,247,247,
 247,247,248,248,248,248,248,248,248,248,248,249,249,249,249,249,
 249,249,249,250,250,250,250,250,250,250,250,250,251,251,251,251,
 251,251,251,251,252,252,252,252,252,252,252,252,253,253,253,253,
 253,253,253,253,253,254,254,254,254,254,254,254,254,255,255,255,
 255,255,255,255,255,255,256,256,256,256,256,256,256,256,257,257,
 257,257,257,257,257,257,257,258,258,258,258,258,258,258,258,259,
 259,259,259,259,259,259,259,259,260,260,260,260,260,260,260,260,
 261,261,261,261,261,261,261,261,261,262,262,262,262,262,262,262,
 262,263,263,263,263,263,263,263,263,263,264,264,264,264,264,264,
 264,264,265,265,265,265,265,265,265,265,265,266,266,266,266,266,
 266,266,266,267,267,267,267,267,267,267,267,267,268,268,268,268,
 268,268,268,268,268,269,269,269,269,269,269,269,269,270,270,270,
 270,270,270,270,270,270,271,271,271,271,271,271,271,271,271,272,
 272,272,272,272,272,272,272,273,273,273,273,273,273,273,273,273,
 274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,
 275,276,276,276,276,276,276,276,276,276,277,277,277,277,277,277,
 277,277,277,278,278,278,278,278,278,278,278,279,279,279,279,279,
 279,279,279,279,280,280,280,280,280,280,280,280,280,281,281,281,
 281,281,281,281,281,282,282,282,282,282,282,282,282,282,283,283,
 283,283,283,283,283,283,283,284,284,284,284,284,284,284,284,284,
 285,285,285,285,285,285,285,285,286,286,286,286,286,286,286,286,
 286,287,287,287,287,287,287,287,287,287,288,288,288,288,288,288,
 288,288,288,289,289,289,289,289,289,289,289,289,290,290,290,290,
 290,290,290,290,291,291,291,291,291,291,291,291,291,292,292,292,
 292,292,292,292,292,292,293,293,293,293,293,293,293,293,293,294,
 294,294,294,294,294,294,294,294,295,295,295,295,295,295,295,295,
 295,296,296,296,296,296,296,296,296,296,297,297,297,297,297,297,
 297,297,297,298,298,298,298,298,298,298,298,299,299,299,299,299,
 299,299,299,299,300,300,300,300,300,300,300,300,300,301,301,301,
 301,301,301,301,301,301,302,302,302,302,302,302,302,302,302,303,
 303,303,303,303,303,303,303,303,304,304,304,304,304,304,304,304,
 304,305,305,305,305,305,305,305,305,305,306,306,306,306,306,306,
 306,306,306,307,307,307,307,307,307,307,307,307,308,308,308,308,
 308,308,308,308,308,309,309,309,309,309,309,309,309,309,310,310,
 310,310,310,310,310,310,310,311,311,311,311,311,311,311,311,311,
 312,312,312,312,312,312,312,312,312,313,313,313,313,313,313,313,
 313,313,314,314,314,314,314,314,314,314,314,315,315,315,315,315,
 315,315,315,315,316,316,316,316,316,316,316,316,316,317,317,317,
 317,317,317,317,317,317,318,318,318,318,318,318,318,318,318,318,
 319,319,319,319,319,319,319,319,319,320,320,320,320,320,320,320,
 320,320,321,321,321,321,321,321,321,321,321,322,322,322,322,322,
 322,322,322,322,323,323,323,323,323,323,323,323,323,324,324,324,
 324,324,324,324,324,324,325,325,325,325,325,325,325,325,325,325,
 326,326,326,326,326,326,326,326,326,327,327,327,327,327,327,327,
 327,327,328,328,328,328,328,328,328,328,328,329,329,329,329,329,
 329,329,329,329,330,330,330,330,330,330,330,330,330,330,331,331,
 331,331,331,331,331,331,331,332,332,332,332,332,332,332,332,332,
 333,333,333,333,333,333,333,333,333,334,334,334,334,334,334,334,
 334,334,335,335,335,335,335,335,335,335,335,335,336,336,336,336,
 336,336,336,336,336,337,337,337,337,337,337,337,337,337,338,338,
 338,338,338,338,338,338,338,338,339,339,339,339,339,339,339,339,
 339,340,340,340,340,340,340,340,340,340,341,341,341,341,341,341,
 341,341,341,341,342,342,342,342,342,342,342,342,342,343,343,343,
 343,343,343,343,343,343,344,344,344,344,344,344,344,344,344,344,
 345,345,345,345,345,345,345,345,345,346,346,346,346,346,346,346,
 346,346,347,347,347,347,347,347,347,347,347,347,348,348,348,348,
 348,348,348,348,348,349,349,349,349,349,349,349,349,349,350,350,
 350,350,350,350,350,350,350,350,351,351,351,351,351,351,351,351,
 351,352,352,352,352,352,352,352,352,352,352,353,353,353,353,353,
 353,353,353,353,354,354,354,354,354,354,354,354,354,355,355,355,
 355,355,355,355,355,355,355,356,356,356,356,356,356,356,356,356,
 357,357,357,357,357,357,357,357,357,357,358,358,358,358,358,358,
 358,358,358,359,359,359,359,359,359,359,359,359,359,360,360,360,
 360,360,360,360,360,360,361,361,361,361,361,361,361,361,361,361,
 362,362,362,362,362,362,362,362,362,363,363,363,363,363,363,363,
 363,363,363,364,364,364,364,364,364,364,364,364,365,365,365,365,
 365,365,365,365,365,365,366,366,366,366,366,366,366,366,366,367,
 367,367,367,367,367,367,367,367,367,368,368,368,368,368,368,368,
 368,368,369,369,369,369,369,369,369,369,369,369,370,370,370,370,
 370,370,370,370,370,370,371,371,371,371,371,371,371,371,371,372,
 372,372,372,372,372,372,372,372,372,373,373,373,373,373,373,373,
 373,373,374,374,374,374,374,374,374,374,374,374,375,375,375,375,
 375,375,375,375,375,375,376,376,376,376,376,376,376,376,376,377,
 377,377,377,377,377,377,377,377,377,378,378,378,378,378,378,378,
 378,378,379,379,379,379,379,379,379,379,379,379,380,380,380,380,
 380,380,380,380,380,380,381,381,381,381,381,381,381,381,381,382,
 382,382,382,382,382,382,382,382,382,383,383,383,383,383,383,383,
 383,383,383,384,384,384,384,384,384,384,384,384,385,385,385,385,
 385,385,385,385,385,385,386,386,386,386,386,386,386,386,386,386,
 387,387,387,387,387,387,387,387,387,387,388,388,388,388,388,388,
 388,388,388,389,389,389,389,389,389,389,389,389,389,390,390,390,
 390,390,390,390,390,390,390,391,391,391,391,391,391,391,391,391,
 391,392,392,392,392,392,392,392,392,392,393,393,393,393,393,393,
 393,393,393,393,394,394,394,394,394,394,394,394,394,394,395,395,
 395,395,395,395,395,395,395,395,396,396,396,396,396,396,396,396,
 396,397,397,397,397,397,397,397,397,397,397,398,398,398,398,398,
 398,398,398,398,398,399,399,399,399,399,399,399,399,399,399,400,
 400,400,400,400,400,400,400,400,400,401,401,401,401,401,401,401,
 401,401,402,402,402,402,402,402,402,402,402,402,403,403,403,403,
 403,403,403,403,403,403,404,404,404,404,404,404,404,404,404,404,
 405,405,405,405,405,405,405,405,405,405,406,406,406,406,406,406,
 406,406,406,406,407,407,407,407,407,407,407,407,407,407,408,408,
 408,408,408,408,408,408,408,408,409,409,409,409,409,409,409,409,
 409,410,410,410,410,410,410,410,410,410,410,411,411,411,411,411,
 411,411,411,411,411,412,412,412,412,412,412,412,412,412,412,413,
 413,413,413,413,413,413,413,413,413,414,414,414,414,414,414,414,
 414,414,414,415,415,415,415,415,415,415,415,415,415,416,416,416,
 416,416,416,416,416,416,416,417,417,417,417,417,417,417,417,417,
 417,418,418,418,418,418,418,418,418,418,418,419,419,419,419,419,
 419,419,419,419,419,420,420,420,420,420,420,420,420,420,420,421,
 421,421,421,421,421,421,421,421,421,422,422,422,422,422,422,422,
 422,422,422,423,423,423,423,423,423,423,423,423,423,424,424,424,
 424,424,424,424,424,424,424,425,425,425,425,425,425,425,425,425,
 425,426,426,426,426,426,426,426,426,426,426,427,427,427,427,427,
 427,427,427,427,427,428,428,428,428,428,428,428,428,428,428,429,
 429,429,429,429,429,429,429,429,429,430,430,430,430,430,430,430,
 430,430,430,431,431,431,431,431,431,431,431,431,431,432,432,432,
 432,432,432,432,432,432,432,433,433,433,433,433,433,433,433,433,
 433,434,434,434,434,434,434,434,434,434,434,435,435,435,435,435,
 435,435,435,435,435,435,436,436,436,436,436,436,436,436,436,436,
 437,437,437,437,437,437,437,437,437,437,438,438,438,438,438,438,
 438,438,438,438,439,439,439,439,439,439,439,439,439,439,440,440,
 440,440,440,440,440,440,440,440,441,441,441,441,441,441,441,441,
 441,441,442,442,442,442,442,442,442,442,442,442,443,443,443,443,
 443,443,443,443,443,443,443,444,444,444,444,444,444,444,444,444,
 444,445,445,445,445,445,445,445,445,445,445,446,446,446,446,446,
 446,446,446,446,446,447,447,447,447,447,447,447,447,447,447,448,
 448,448,448,448,448,448,448,448,448,448,449,449,449,449,449,449,
 449,449,449,449,450,450,450,450,450,450,450,450,450,450,451,451,
 451,451,451,451,451,451,451,451,452,452,452,452,452,452,452,452,
 452,452,453,453,453,453,453,453,453,453,453,453,453,454,454,454,
 454,454,454,454,454,454,454,455,455,455,455,455,455,455,455,455,
 455,456,456,456,456,456,456,456,456,456,456,457,457,457,457,457,
 457,457,457,457,457,457,458,458,458,458,458,458,458,458,458,458,
 459,459,459,459,459,459,459,459,459,459,460,460,460,460,460,460,
 460,460,460,460,460,461,461,461,461,461,461,461,461,461,461,462,
 462,462,462,462,462,462,462,462,462,463,463,463,463,463,463,463,
 463,463,463,463,464,464,464,464,464,464,464,464,464,464,465,465,
 465,465,465,465,465,465,465,465,466,466,466,466,466,466,466,466,
 466,466,466,467,467,467,467,467,467,467,467,467,467,468,468,468,
 468,468,468,468,468,468,468,469,469,469,469,469,469,469,469,469,
 469,469,470,470,470,470,470,470,470,470,470,470,471,471,471,471,
 471,471,471,471,471,471,472,472,472,472,472,472,472,472,472,472,
 472,473,473,473,473,473,473,473,473,473,473,474,474,474,474,474,
 474,474,474,474,474,475,475,475,475,475,475,475,475,475,475,475,
 476,476,476,476,476,476,476,476,476,476,477,477,477,477,477,477,
 477,477,477,477,477,478,478,478,478,478,478,478,478,478,478,479,
 479,479,479,479,479,479,479,479,479,479,480,480,480,480,480,480,
 480,480,480,480,481,481,481,481,481,481,481,481,481,481,482,482,
 482,482,482,482,482,482,482,482,482,483,483,483,483,483,483,483,
 483,483,483,484,484,484,484,484,484,484,484,484,484,484,485,485,
 485,485,485,485,485,485,485,485,486,486,486,486,486,486,486,486,
 486,486,486,487,487,487,487,487,487,487,487,487,487,488,488,488,
 488,488,488,488,488,488,488,488,489,489,489,489,489,489,489,489,
 489,489,490,490,490,490,490,490,490,490,490,490,490,491,491,491,
 491,491,491,491,491,491,491,492,492,492,492,492,492,492,492,492,
 492,492,493,493,493,493,493,493,493,493,493,493,494,494,494,494,
 494,494,494,494,494,494,494,495,495,495,495,495,495,495,495,495,
 495,496,496,496,496,496,496,496,496,496,496,496,497,497,497,497,
 497,497,497,497,497,497,497,498,498,498,498,498,498,498,498,498,
 498,499,499,499,499,499,499,499,499,499,499,499,500,500,500,500,
 500,500,500,500,500,500,501,501,501,501,501,501,501,501,501,501,
 501,502,502,502,502,502,502,502,502,502,502,503,503,503,503,503,
 503,503,503,503,503,503,504,504,504,504,504,504,504,504,504,504,
 504,505,505,505,505,505,505,505,505,505,505,506,506,506,506,506,
 506,506,506,506,506,506,507,507,507,507,507,507,507,507,507,507,
 507,508,508,508,508,508,508,508,508,508,508,509,509,509,509,509,
 509,509,509,509,509,509,510,510,510,510,510,510,510,510,510,510,
 510,511,511,511,511,511,511,511,511,511,511,512,512,512,512,512 };

static const int order[32] ICONST_ATTR =
{ 0, 1, 16, 17, 8, 9, 24, 25, 4, 5, 20, 21, 12, 13, 28, 29,
  2, 3, 18, 19,10,11, 26, 27, 6, 7, 22, 23, 14, 15, 30, 31 };

static const int cx[9] ICONST_ATTR =
{ 16135, 10531,  5604, 15396, -2845,-12551, 14189,  8192, 16384 };

static const int ca[8] ICONST_ATTR =
{-16859,-15458,-10269, -5961, -3099, -1342,  -465,  -121 };

static const int cs[8] ICONST_ATTR =
{ 28098, 28893, 31117, 32221, 32621, 32740, 32765, 32768 };

static const short enwindow[15*20+16] ICONST_ATTR
    __attribute__((aligned(4))) =
{ 0,  65,  593,  1766, 22228, 2115, 611, 62,
  8, 119, 1419, 10564,-11659,-1635,-154, -9, 464,  100,  91, 0,
  0,  69,  604,  1635, 23148, 2363, 643, 62,
  7, 107, 1368, 10449,-12733,-1818,-180,-11, 420,  200, 164, 0,
  0,  72,  608,  1465, 23979, 2600, 671, 63,
  7,  94, 1305, 10265,-13818,-2004,-207,-12, 380,  297, 220, 0,
  0,  76,  606,  1256, 24718, 2825, 693, 63,
  6,  81, 1232, 10016,-14908,-2192,-236,-14, 342,  392, 262, 0,
  0,  78,  597,  1007, 25359, 3033, 712, 63,
  6,  68, 1150,  9706,-15995,-2380,-267,-15, 307,  483, 289, 0,
  0,  80,  580,   719, 25901, 3224, 726, 62,
  6,  54, 1060,  9343,-17072,-2565,-299,-17, 274,  569, 304, 0,
 -1,  82,  555,   391, 26339, 3395, 735, 61,
  5,  40,  963,  8930,-18131,-2747,-332,-19, 242,  650, 307, 0,
 -1,  83,  523,    26, 26672, 3545, 740, 60,
  5,  27,  861,  8474,-19164,-2923,-366,-21, 212,  724, 300, 0,
 -1,  83,  482,  -376, 26900, 3672, 739, 58,
  4,  14,  756,  7981,-20163,-3092,-401,-24, 183,  792, 283, 0,
 -1,  82,  433,  -812, 27022, 3776, 735, 56,
  4,   1,  648,  7456,-21122,-3250,-435,-26, 155,  851, 258, 0,
 -1,  81,  376, -1281, 27038, 3855, 726, 54,
  3, -11,  539,  6907,-22032,-3397,-470,-28, 128,  903, 226, 0,
 -1,  78,  312, -1778, 26951, 3910, 713, 52,
  3, -22,  430,  6338,-22887,-3530,-503,-31, 102,  946, 188, 0,
 -2,  75,  239, -2302, 26761, 3941, 696, 49,
  3, -33,  322,  5757,-23678,-3648,-537,-34,  76,  980, 145, 0,
 -2,  70,  160, -2848, 26472, 3948, 676, 47,
  3, -42,  217,  5167,-24399,-3749,-568,-36,  50, 1004,  99, 0,
 -2,  65,   74, -3412, 26087, 3931, 653, 44,
  2, -51,  115,  4577,-25045,-3830,-599,-39,  25, 1019,  50, 0,

  25610,  3891,  627,   42,-3990, -18, 58, -2,
  21226, 10604, 1860, 1458,  576, 130, 60,  8,
};

static const int win[18][4] ICONST_ATTR =
{ { -3072, -134, -146, 3352 },
  { -2747, -362, -471, 3579 },
  { -2387, -529, -831, 3747 },
  { -2004, -632,-1214, 3850 },
  { -1609, -666,-1609, 3884 },
  { -1214, -632,-2004, 3850 },
  {  -831, -529,-2387, 3747 },
  {  -471, -362,-2747, 3579 },
  {  -146, -134,-3072, 3352 },
  {   134,-3072,-3352, -146 },
  {   362,-2747,-3579, -471 },
  {   529,-2387,-3747, -831 },
  {   632,-2004,-3850,-1214 },
  {   666,-1609,-3884,-1609 },
  {   632,-1214,-3850,-2004 },
  {   529, -831,-3747,-2387 },
  {   362, -471,-3579,-2747 },
  {   134, -146,-3352,-3072 } };

static const long sampr_index[2][3] =
{ { 22050, 24000, 16000 },      /* MPEG 2 */
  { 44100, 48000, 32000 } };    /* MPEG 1 */

static const long bitr_index[2][15] =
{ { 0, 8,16,24,32,40,48,56, 64, 80, 96,112,128,144,160 },    /* MPEG 2 */
  { 0,32,40,48,56,64,80,96,112,128,160,192,224,256,320 } };  /* MPEG 1 */

static const int num_bands[3][15]  =
{ { 0,10,10,10,10,12,14,16,20,22,24,26,28,30,32 },   /* MPEG 2 Stereo */
  { 0,10,10,10,10,10,12,14,18,24,26,28,30,32,32 },   /* MPEG 1 Stereo */
  { 0,10,12,14,18,24,26,28,30,32,32,32,32,32,32 } }; /* MPEG 1&2 Mono */


#ifdef MP3_ENC_COP
/* Initialize the circular buffer pointers */
static inline void sb_data_buf_init(void)
{
    sb_data_cod = &sb_data_buf[0];
    sb_data_enc = &sb_data_buf[1];
}

/* Switch the buffers used by CPU and COP */
static inline void sb_data_buf_swap(void)
{
    typeof (sb_data_cod) t = sb_data_cod;
    sb_data_cod = sb_data_enc;
    sb_data_enc = t;
}
#endif /* MP3_ENC_COP */

static void putbits(uint32_t val, uint32_t nbit)
{
    int new_bitpos = coded_data.bitpos + nbit;
    int ptrpos     = coded_data.bitpos >> 5;

    val = val & (0xffffffff >> (32 - nbit));

    /* data fit in one uint32_t */
    if (((new_bitpos - 1) >> 5) == ptrpos)
    {
        coded_data.bbuf[ptrpos] |= val << ((32 - new_bitpos) & 31);
    }
    else
    {
        coded_data.bbuf[ptrpos  ] |= val >> ((new_bitpos - 32) & 31);
        coded_data.bbuf[ptrpos+1] |= val << ((32 - new_bitpos) & 31);
    }

    coded_data.bitpos = new_bitpos;
}

#define PUTLONG_INIT() \
    uint32_t _cc = 0, _sz = 0

#define putlong_flush() \
    putbits(_cc, _sz)

#define putlong(c, s)  \
    ({ uint32_t _c = (c), _s = (s);                                   \
       if (_s + _sz <= 32) { _cc = (_cc << _s) | _c; _sz += _s;     } \
       else                { putlong_flush(); _cc = _c; _sz = _s; } })

static inline uint32_t encode_header(int padding, long bitr_id)
{
    /*
     * MPEG header layout:
     * AAAAAAAA AAABBCCD EEEEFFGH IIJJKLMM
     * A (31-21) = frame sync
     * B (20-19) = MPEG type
     * C (18-17) = MPEG layer
     * D (16)    = protection bit
     * E (15-12) = bitrate index
     * F (11-10) = samplerate index
     * G (9)     = padding bit
     * H (8)     = private bit
     * I (7-6)   = channel mode
     * J (5-4)   = mode extension (jstereo only)
     * K (3)     = copyright bit
     * L (2)     = original
     * M (1-0)   = emphasis
     */
    return (0xffe00000           )  /* frame sync (AAAAAAAAA AAA) */
         | (0x2             << 19)  /* mp3 type (upper):  1 (BB)  */
         | (cfg.mpg.type    << 19)
         | (0x1             << 17)  /* mp3 layer:        01 (CC)  */
         | (0x1             << 16)  /* mp3 crc:           1 (D)   */
         | (bitr_id         << 12)
         | (cfg.mpg.smpl_id << 10)
         | (padding         <<  9)
         | (cfg.mpg.mode    <<  6)
         | (0x1             <<  2); /* mp3 org:           1 (L)   */
    /* no emphasis (bits 0-1) */
}

static long calc_frame_size(int bitr_id, long *frac)
{
    unsigned long v = bitr_index[cfg.mpg.type][bitr_id];
    v = 576 * 16000 * v / (2 - cfg.mpg.type);
    v /= cfg.samplerate;

    if (frac)
        *frac = v % 64;

    return v / 64;
}

static void encode_side_info(side_info_t si[2][2])
{
    PUTLONG_INIT();

    putbits(encode_header(cfg.mpg.padding, cfg.mpg.bitr_id), 32);

    if (cfg.mpg.type == 1)
    {
        /* MPEG1 */
        if (cfg.channels == 2) putlong(0, 20);
        else                   putlong(0, 18);

        for (int gr = 0; gr < cfg.granules; gr++)
        {
            for (int ch = 0; ch < cfg.channels; ch++)
            {
                side_info_t *gi = &si[gr][ch];

                putlong(gi->part2_3_length + 42, 12); /* add scale_facs array size */
                putlong(gi->address3 >> 1,        9);
                putlong(gi->global_gain,          8);
                putlong(9,                        4); /* set scale_facs compr type */
                putlong(gi->table_select[0],      6);
                putlong(gi->table_select[1],      5);
                putlong(gi->table_select[2],      5);
                putlong(gi->region_0_1,           7);
                putlong(1                  ,      2); /* set scale_facs to 1bit */
                putlong(gi->table_select[3],      1);
            }
        }
    }
    else
    {
        /* MPEG2 */
        if (cfg.channels == 2) putlong(0, 10);
        else                   putlong(0,  9);

        for (int ch = 0; ch < cfg.channels; ch++)
        {
            side_info_t *gi = &si[0][ch];

            putlong(gi->part2_3_length + 42, 12); /* add scale_facs array size */
            putlong(gi->address3 >> 1,        9);
            putlong(gi->global_gain,          8);
            putlong(0xca,                     9); /* set scale_facs compr type */
            putlong(gi->table_select[0],      6);
            putlong(gi->table_select[1],      5);
            putlong(gi->table_select[2],      5);
            putlong(gi->region_0_1     ,      7);
            putlong(1                  ,      1); /* set scale_facs to 1bit */
            putlong(gi->table_select[3],      1);
        }
    }

    putlong_flush();
}

/* Implements the pseudocode of page 98 of the IS */
static int huffman_code(short *ix, char *xr_sign, uint32_t begin, uint32_t end,
                        int table)
{
    if (table == 0)
        return 0;

    PUTLONG_INIT();
    int sumbit = 0;

    #define sign_x xr_sign[i+0]
    #define sign_y xr_sign[i+1]

    if (table > 15)
    {
        /* ESC-table is used */
        uint32_t linbits = ht_big[table - 16].linbits;
        const uint16_t *hffcode = table < 24 ? t16HB : t24HB;
        const uint8_t  *hlen    = table < 24 ? t16l  : t24l;
        uint32_t xl = 0, yl = 0;

        for (uint32_t i = begin; i < end; i += 2)
        {
            int x = ix[i+0];
            int y = ix[i+1];

            if (x > 14) { xl = x - 15;  x = 15; }
            if (y > 14) { yl = y - 15;  y = 15; }

            uint32_t idx  = x * 16 + y;
            uint32_t code = hffcode[idx];
            int      bit  = hlen   [idx];

            if (x)
            {
                if (x > 14)
                {
                    code = (code << linbits) | xl;
                    bit += linbits;
                }

                code = (code << 1) | sign_x;
                bit += 1;
            }

            if (y)
            {
                if (y > 14)
                {
                    if (bit + linbits + 1 > 32)
                    {
                        putlong(code, bit);
                        sumbit += bit;
                        code = bit = 0;
                    }

                    code = (code << linbits) | yl;
                    bit += linbits;
                }

                code = (code << 1) | sign_y;
                bit += 1;
            }

            putlong(code, bit);
            sumbit += bit;
        }
    }
    else
    {
        /* No ESC-words */
        const struct huffcodetab *h = &ht[table];

        for (uint32_t i = begin; i < end; i += 2)
        {
            int x = ix[i+0];
            int y = ix[i+1];

            uint32_t idx  = x * h->len + y;
            uint32_t code = h->table[idx];
            int      bit  = h->hlen [idx];

            if (x)
            {
                code = (code << 1) | sign_x;
                bit += 1;
            }

            if (y)
            {
                code = (code << 1) | sign_y;
                bit += 1;
            }

            putlong(code, bit);
            sumbit += bit;
        }
    }

    putlong_flush();

    return sumbit;
}

static int huffman_cod1(short *ix, char *xr_sign, uint32_t begin,
                        uint32_t end, int tbl)
{
    PUTLONG_INIT();

    #define sgnv xr_sign[i+0]
    #define sgnw xr_sign[i+1]
    #define sgnx xr_sign[i+2]
    #define sgny xr_sign[i+3]

    int sumbit = 0, s = 0, l = 0;
    for (uint32_t i = begin; i < end; i += 4)
    {
        int v = ix[i+0];
        int w = ix[i+1];
        int x = ix[i+2];
        int y = ix[i+3];

        uint32_t p = (v << 3) + (w << 2) + (x << 1) + y;

        switch (p)
        {
        case  0: l=0; s = 0; break;
        case  1: l=1; s =                                           sgny; break;
        case  2: l=1; s =                              sgnx;              break;
        case  3: l=2; s =                             (sgnx << 1) + sgny; break;
        case  4: l=1; s =                sgnw;                            break;
        case  5: l=2; s =               (sgnw << 1)               + sgny; break;
        case  6: l=2; s =               (sgnw << 1) +  sgnx;              break;
        case  7: l=3; s =               (sgnw << 2) + (sgnx << 1) + sgny; break;
        case  8: l=1; s =  sgnv;                                          break;
        case  9: l=2; s = (sgnv << 1)                             + sgny; break;
        case 10: l=2; s = (sgnv << 1)               +  sgnx;              break;
        case 11: l=3; s = (sgnv << 2)               + (sgnx << 1) + sgny; break;
        case 12: l=2; s = (sgnv << 1) +  sgnw;                            break;
        case 13: l=3; s = (sgnv << 2) + (sgnw << 1)               + sgny; break;
        case 14: l=3; s = (sgnv << 2) + (sgnw << 1) +  sgnx;              break;
        case 15: l=4; s = (sgnv << 3) + (sgnw << 2) + (sgnx << 1) + sgny; break;
        }

        uint32_t d = (ht_count[tbl][0][p] << l) + s;
        l = ht_count[tbl][1][p];
        putlong(d, l);
        sumbit += l;
    }

    putlong_flush();

    return sumbit;
}

/* Note the discussion of huffmancodebits() on pages 28 and 29 of the IS,
   as well as the definitions of the side information on pages 26 and 27. */
static void huffman_code_bits(short *ix, char *xr_sign, side_info_t *gi)
{
    int region1 = gi->address1;
    int region2 = gi->address2;
    int bigvals = gi->address3;
    int count1  = bigvals + (gi->count1 << 2);
    int i, v;

    for (i = v = 0; i < 32; i += 2)
        v |= band_scale_f[i >> 1] << (30 - i);

    putbits(v, 32); // store scale_facs (part1)

    for (v = 0; i < 42; i += 2)
        v |= band_scale_f[i >> 1] << (40 - i);

    putbits(v, 10); // store scale_facs (part2)

    int bits = 0;

    if (region1 > 0)
        bits += huffman_code(ix, xr_sign,       0, region1, gi->table_select[0]);

    if (region2 > region1)
        bits += huffman_code(ix, xr_sign, region1, region2, gi->table_select[1]);

    if (bigvals > region2)
        bits += huffman_code(ix, xr_sign, region2, bigvals, gi->table_select[2]);

    if (count1 > bigvals)
        bits += huffman_cod1(ix, xr_sign, bigvals,  count1, gi->table_select[3]);

    int stuff_bits = gi->part2_3_length - bits;

    if (stuff_bits > 0)
    {
        int stuff_words = stuff_bits >> 5;
        int remain_bits = stuff_bits & 31;

        if (remain_bits)
            putbits(~0, remain_bits);

        while (stuff_words--)
            putbits(~0, 32); /* Huffman code tables leed to padding ones */
    }
}

/*************************************************************************/
/* Function: Count the number of bits necessary to code the subregion.   */
/*************************************************************************/
static int count_bit1(short *ix, uint32_t start, uint32_t end, int *bits)
{
    int sum = 0;

    for (uint32_t i = start; i < end; i += 2)
        sum += t1l[4 + ix[i] * 2 + ix[i + 1]];

    *bits = sum;

    return 1; /* this is table1 */
}

static int count_bigv(short *ix, uint32_t start, uint32_t end, int table0,
                      int table1, int *bits)
{
    uint32_t sum = 0, bigv = 0;

    /* ESC-table is used */
    for (uint32_t i = start; i < end; i += 2)
    {
        uint32_t x = ix[i+0];
        uint32_t y = ix[i+1];

        if (x > 14) { x = 15; bigv++; }
        if (y > 14) { y = 15; bigv++; }

        sum += tab1624[x * 16 + y];
    }

    int sum0 = (sum  >>  16)  + bigv * ht_big[table0].linbits;
    int sum1 = (sum & 0xffff) + bigv * ht_big[table1].linbits;

    if (sum0 <= sum1)
    {
        *bits = sum0;
        return table0;
    }
    else
    {
        *bits = sum1;
        return table1;
    }
}

static int find_best_2(short *ix, uint32_t start, uint32_t end,
                       const uint32_t *table, uint32_t len, int *bits)
{
    uint32_t sum = 0;

    for (uint32_t i = start; i < end; i += 2)
        sum += table[ix[i] * len + ix[i + 1]];

    if ((sum & 0xffff) <= (sum >> 16))
    {
        *bits = sum & 0xffff;
        return 1;
    }
    else
    {
        *bits = sum >> 16;
        return 0;
    }
}

static int find_best_3(short *ix, uint32_t start, uint32_t end,
                       const uint32_t *table, uint32_t len, int *bits)
{
    int sum1 = 0;
    int sum2 = 0;
    int sum3 = 0;

    /* avoid overflow in packed additions: 78*13 < 1024 */
    for (uint32_t i = start; i < end;)
    {
        uint32_t j = i + 2*78 > end ? end : i + 2*78;

        uint32_t sum = 0;
        for (; i < j; i += 2)
            sum += table[ix[i] * len + ix[i + 1]];

        sum1 += (sum >> 20);
        sum2 += (sum >> 10) & 0x3ff;
        sum3 += (sum >>  0) & 0x3ff;
    }

    int r = 0;
    if (sum1 > sum2) { sum1 = sum2; r = 1; }
    if (sum1 > sum3) { sum1 = sum3; r = 2; }

    *bits = sum1;

    return r;
}

/***************************************************************************/
/*  Choose the Huffman table that will encode ix[begin..end] with          */
/*  the fewest bits.                                                       */
/*  Note: This code contains knowledge about the sizes and characteristic  */
/*  of the Huffman tables as defined in the IS (Table B.7), and will not   */
/*  work with any arbitrary tables.                                        */
/***************************************************************************/
static int choose_table(short *ix, uint32_t begin, uint32_t end, int *bits)
{
    int max = 0;
    for (uint32_t i = begin; i < end; i++)
    {
        if (ix[i] > max)
            max = ix[i];
    }

    if (max < 16)
    {
        /* tables without linbits */
        /* indx: 0  1  2  3  4  5  6  7  8  9 10 11 12  13 14  15 */
        /*  len: 0, 2, 3, 3, 0, 4, 4, 6, 6, 6, 8, 8, 8, 16, 0, 16 */
        switch (max)
        {
        case 0:  return  0;
        case 1:  return       count_bit1(ix, begin, end,              bits);
        case 2:  return  2 + find_best_2(ix, begin, end,   tab23,  3, bits);
        case 3:  return  5 + find_best_2(ix, begin, end,   tab56,  4, bits);
        case 4:
        case 5:  return  7 + find_best_3(ix, begin, end,  tab789,  6, bits);
        case 6:
        case 7:  return 10 + find_best_3(ix, begin, end,  tabABC,  8, bits);
        default: return 13 + find_best_2(ix, begin, end, tab1315, 16, bits)*2;
        }
    }
    else
    {
        /* tables with linbits */
        max -= 15;

        int table0, table1;

        for (table0 = 0; table0 < 8; table0++)
        {
            if (ht_big[table0].linmax >= max)
                break;
        }

        for (table1 = 8; table1 < 16; table1++)
        {
            if (ht_big[table1].linmax >= max)
                break;
        }

        return 16 + count_bigv(ix, begin, end, table0, table1, bits);
    }
}

/*************************************************************************/
/* Function: Calculation of rzero, count1, address3                      */
/* (Partitions ix into big values, quadruples and zeros).                */
/*************************************************************************/
static int calc_runlen(short *ix, side_info_t *si)
{
    int i = 576;

    while (i -= 2)
    {
        if (*(uint32_t *)&ix[i - 2]) /* !!!! short *ix; !!!!! */
            break;
    }

    si->count1 = 0;

    int sum = 0;
    for ( ; i > 3; i -= 4)
    {
        int v = ix[i-1];
        int w = ix[i-2];
        int x = ix[i-3];
        int y = ix[i-4];

        if ((v | w | x | y) <= 1)
        {
            int p = (y << 3) + (x << 2) + (w << 1) + (v);
            sum += tab01[p];
            si->count1++;
        }
        else
        {
            break;
        }
    }

    si->address3 = i;

    if ((sum >> 16) < (sum & 0xffff))
    {
        si->table_select[3] = 0;
        return sum >> 16;
    }
    else
    {
        si->table_select[3] = 1;
        return sum & 0xffff;
    }
}

/*************************************************************************/
/*   Function: Quantization of the vector xr ( -> ix)                    */
/*************************************************************************/
static int quantize_int(int *xr, short *ix, side_info_t *si)
{
    static const unsigned int frac_pow[] ICONST_ATTR =
        { 0x10000, 0xd745, 0xb505, 0x9838 };

    unsigned s = frac_pow[si->quantStep & 3] >> si->quantStep / 4;

    /* check for possible 'out of range' values */
    if (((si->max_val + 256) >> 8) * s >= (65536 << 8))
        return 0;

    if (((si->max_val + 256) >> 8) * s < (4096 << 8))
    {
        /* all values fit the table size */
        for (int i = 576; i--; )
            ix[i] = int2idx[(xr[i] * s + 0x8000) >> 16];
    }
    else
    {
        /* check each index wether it fits the table */
        for (int i = 576; i--; )
        {
            unsigned idx = (xr[i] * s + 0x08000) >> 16;

            if (idx > 4095) ix[i] = int2idx[(idx + 8) >> 4] << 3;
            else            ix[i] = int2idx[idx];
        }
    }

    return 1;
}

/*************************************************************************/
/* subdivides the bigvalue region which will use separate Huffman tables */
/*************************************************************************/
static void subdivide(side_info_t *si)
{
    if (!si->address3)
    {
        /* no bigvalue region */
        si->region_0_1 = 0;
        si->address1   = 0;
        si->address2   = 0;
    }
    else
    {
        /* Calculate scale factor band index */
        int scfb = 1;
        while (scalefac[scfb] < si->address3)
            scfb++;

        int count0 = subdv_table[scfb].region0_cnt;
        int count1 = subdv_table[scfb].region1_cnt;

        si->region_0_1 = (count0 << 3) | count1;
        si->address1   = scalefac[count0];
        si->address2   = scalefac[count0 + count1 + 1];
    }
}

/*******************************************************************/
/* Count the number of bits necessary to code the bigvalues region */
/*******************************************************************/
static int bigv_bitcount(short *ix, side_info_t *gi)
{
    int b1 = 0, b2 = 0, b3 = 0;

    /* Select huffman code tables for bigvalues regions */
    gi->table_select[0] = 0;
    gi->table_select[1] = 0;
    gi->table_select[2] = 0;

    if (gi->address1 > 0)            /* region0 */
        gi->table_select[0] = choose_table(ix,            0, gi->address1, &b1);

    if (gi->address2 > gi->address1) /* region1 */
        gi->table_select[1] = choose_table(ix, gi->address1, gi->address2, &b2);

    if (gi->address3 > gi->address2) /* region2 */
        gi->table_select[2] = choose_table(ix, gi->address2, gi->address3, &b3);

    return b1 + b2 + b3;
}

static int quantize_and_count_bits(int *xr, short *ix, side_info_t *si)
{
    int bits = 10000;

    if (quantize_int(xr, ix, si))
    {
        bits = calc_runlen(ix, si);      /* rzero,count1,address3  */
        subdivide(si);                   /* bigvalues sfb division */
        bits += bigv_bitcount(ix,si);    /* bit count */
    }

    return bits;
}

/************************************************************************/
/* The code selects the best quantStep for a particular set of scalefacs*/
/************************************************************************/
static int inner_loop(int *xr, int max_bits, side_info_t *si)
{
    int bits;

    while ((bits = quantize_and_count_bits(xr, enc_data, si)) < max_bits - 64)
    {
        if (si->quantStep == 0)
            break;

        if (si->quantStep <= 2)
            si->quantStep  = 0;
        else
            si->quantStep -= 2;
    }

    while (bits > max_bits)
    {
        si->quantStep++;
        bits = quantize_and_count_bits(xr, enc_data, si);
    }

    return bits;
}

static void iteration_loop(int *xr, side_info_t *si, int gr_cnt)
{
    int max_bits = cfg.mean_bits;

    /* distribute reserved bits to remaining granules */
    int tar_bits = max_bits + (cfg.resv_size / gr_cnt & ~7);

    if (tar_bits > max_bits + max_bits / 2)
        tar_bits = max_bits + max_bits / 2;

    si->part2_3_length = inner_loop(xr, tar_bits, si);
    si->global_gain    = si->quantStep + 142 - si->additStep;

    /* unused bits of the reservoir can be used for remaining granules */
    cfg.resv_size += max_bits - si->part2_3_length;

    /* end: distribute the reserved bits to one or two granules */
    if (gr_cnt == 1)
    {
        si->part2_3_length += cfg.resv_size;

        /* mp3 format allows max 12bits for granule length */
        if (si->part2_3_length > 4092)
        {
            int remain = (si->part2_3_length - 4092 + 31) >> 5;
            si->part2_3_length    -= remain << 5;
            si[-1].part2_3_length += remain << 5;

            while (remain--)
                putbits(~0, 32);
        }
    }
}

/* returns sum_j=0^31 a[j]*cos(PI*j*(k+1/2)/32), 0<=k<32 */
#ifdef CPU_COLDFIRE
static void ICODE_ATTR window_subband1_s(const short *wk, int a0[32],
                                         int a1[32])
{
    for (int k = 0; k < 18; k++, wk += 64, a0 += 32, a1 += 32)
    {
        const short *wp = enwindow;
        const short *x1 = wk;
        const short *x2 = x1 - 124;
        int s0, s1, t0, t1;

        for (int i = -15; i < 0; i++)
        {
            asm volatile (
            "movem.l  (%[wp]), %%d0-%%d3                         \n"
            "move.l   (-224*4,%[x2]), %%d4                       \n"
            "mac.w    %%d0u, %%d4u,                       %%acc0 \n"
            "mac.w    %%d0u, %%d4l, (-160*4,%[x2]), %%d4, %%acc1 \n"
            "mac.w    %%d0l, %%d4u,                       %%acc0 \n"
            "mac.w    %%d0l, %%d4l, ( -96*4,%[x2]), %%d4, %%acc1 \n"
            "mac.w    %%d1u, %%d4u,                       %%acc0 \n"
            "mac.w    %%d1u, %%d4l, ( -32*4,%[x2]), %%d4, %%acc1 \n"
            "mac.w    %%d1l, %%d4u,                       %%acc0 \n"
            "mac.w    %%d1l, %%d4l, (  32*4,%[x2]), %%d4, %%acc1 \n"
            "mac.w    %%d2u, %%d4u,                       %%acc0 \n"
            "mac.w    %%d2u, %%d4l, (  96*4,%[x2]), %%d4, %%acc1 \n"
            "mac.w    %%d2l, %%d4u,                       %%acc0 \n"
            "mac.w    %%d2l, %%d4l, ( 160*4,%[x2]), %%d4, %%acc1 \n"
            "mac.w    %%d3u, %%d4u,                       %%acc0 \n"
            "mac.w    %%d3u, %%d4l, ( 224*4,%[x2]), %%d4, %%acc1 \n"
            "mac.w    %%d3l, %%d4u,                       %%acc0 \n"
            "mac.w    %%d3l, %%d4l, ( 224*4,%[x1]), %%d4, %%acc1 \n"
            "mac.w    %%d0u, %%d4u,                       %%acc2 \n"
            "mac.w    %%d0u, %%d4l, ( 160*4,%[x1]), %%d4, %%acc3 \n"
            "mac.w    %%d0l, %%d4u,                       %%acc2 \n"
            "mac.w    %%d0l, %%d4l, (  96*4,%[x1]), %%d4, %%acc3 \n"
            "mac.w    %%d1u, %%d4u,                       %%acc2 \n"
            "mac.w    %%d1u, %%d4l, (  32*4,%[x1]), %%d4, %%acc3 \n"
            "mac.w    %%d1l, %%d4u,                       %%acc2 \n"
            "mac.w    %%d1l, %%d4l, ( -32*4,%[x1]), %%d4, %%acc3 \n"
            "mac.w    %%d2u, %%d4u,                       %%acc2 \n"
            "mac.w    %%d2u, %%d4l, ( -96*4,%[x1]), %%d4, %%acc3 \n"
            "mac.w    %%d2l, %%d4u,                       %%acc2 \n"
            "mac.w    %%d2l, %%d4l, (-160*4,%[x1]), %%d4, %%acc3 \n"
            "mac.w    %%d3u, %%d4u,                       %%acc2 \n"
            "mac.w    %%d3u, %%d4l, (-224*4,%[x1]), %%d4, %%acc3 \n"
            "mac.w    %%d3l, %%d4u,                       %%acc2 \n"
            "mac.w    %%d3l, %%d4l, (-256*4,%[x1]), %%d4, %%acc3 \n"
            "movem.l  (16,%[wp]), %%d0-%%d3                      \n"
            "mac.w    %%d0u, %%d4u,                       %%acc0 \n"
            "mac.w    %%d0u, %%d4l, (-192*4,%[x1]), %%d4, %%acc1 \n"
            "mac.w    %%d0l, %%d4u,                       %%acc0 \n"
            "mac.w    %%d0l, %%d4l, (-128*4,%[x1]), %%d4, %%acc1 \n"
            "mac.w    %%d1u, %%d4u,                       %%acc0 \n"
            "mac.w    %%d1u, %%d4l, ( -64*4,%[x1]), %%d4, %%acc1 \n"
            "mac.w    %%d1l, %%d4u,                       %%acc0 \n"
            "mac.w    %%d1l, %%d4l, (   0*4,%[x1]), %%d4, %%acc1 \n"
            "mac.w    %%d2u, %%d4u,                       %%acc0 \n"
            "mac.w    %%d2u, %%d4l, (  64*4,%[x1]), %%d4, %%acc1 \n"
            "mac.w    %%d2l, %%d4u,                       %%acc0 \n"
            "mac.w    %%d2l, %%d4l, ( 128*4,%[x1]), %%d4, %%acc1 \n"
            "mac.w    %%d3u, %%d4u,                       %%acc0 \n"
            "mac.w    %%d3u, %%d4l, ( 192*4,%[x1]), %%d4, %%acc1 \n"
            "mac.w    %%d3l, %%d4u,                       %%acc0 \n"
            "mac.w    %%d3l, %%d4l, ( 256*4,%[x2]), %%d4, %%acc1 \n"
            "msac.w   %%d0u, %%d4u,                       %%acc2 \n"
            "msac.w   %%d0u, %%d4l, ( 192*4,%[x2]), %%d4, %%acc3 \n"
            "msac.w   %%d0l, %%d4u,                       %%acc2 \n"
            "msac.w   %%d0l, %%d4l, ( 128*4,%[x2]), %%d4, %%acc3 \n"
            "msac.w   %%d1u, %%d4u,                       %%acc2 \n"
            "msac.w   %%d1u, %%d4l, (  64*4,%[x2]), %%d4, %%acc3 \n"
            "msac.w   %%d1l, %%d4u,                       %%acc2 \n"
            "msac.w   %%d1l, %%d4l, (   0*4,%[x2]), %%d4, %%acc3 \n"
            "msac.w   %%d2u, %%d4u,                       %%acc2 \n"
            "msac.w   %%d2u, %%d4l, ( -64*4,%[x2]), %%d4, %%acc3 \n"
            "msac.w   %%d2l, %%d4u,                       %%acc2 \n"
            "msac.w   %%d2l, %%d4l, (-128*4,%[x2]), %%d4, %%acc3 \n"
            "msac.w   %%d3u, %%d4u,                       %%acc2 \n"
            "msac.w   %%d3u, %%d4l, (-192*4,%[x2]), %%d4, %%acc3 \n"
            "msac.w   %%d3l, %%d4u,                       %%acc2 \n"
            "msac.w   %%d3l, %%d4l,                       %%acc3 \n"
            "movclr.l %%acc0, %%d0                               \n"
            "move.l   %%d0, %[s0]                                \n"
            "movclr.l %%acc1, %%d0                               \n"
            "move.l   %%d0, %[s1]                                \n"
            "movclr.l %%acc2, %%d0                               \n"
            "move.l   %%d0, %[t0]                                \n"
            "movclr.l %%acc3, %%d0                               \n"
            "move.l   %%d0, %[t1]                                \n"
            : [x1] "+a" (x1), [x2] "+a" (x2), [s0] "+m" (s0), [t0] "+m" (t0),
                                              [s1] "+m" (s1), [t1] "+m" (t1)
            : [wp] "a" (wp) : "d0", "d1", "d2", "d3", "d4");

            a0[30+i*2] =  shft4(t0)          + shft13(s0) * wp[16];
            a0[31+i*2] = shft13(t0) * wp[17] - shft13(s0) * wp[18];
            a1[30+i*2] =  shft4(t1)          + shft13(s1) * wp[16];
            a1[31+i*2] = shft13(t1) * wp[17] - shft13(s1) * wp[18];
            wp += 20;
            x1 -=  2;
            x2 +=  2;
        }

        asm volatile (
        "move.l   ( -32*4,%[x1]), %%d4                       \n"
        "movem.l  (%[wp]), %%d0-%%d3                         \n"
        "mac.w    %%d0u, %%d4u,                       %%acc0 \n"
        "mac.w    %%d0u, %%d4l, ( -96*4,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d0l, %%d4u,                       %%acc0 \n"
        "mac.w    %%d0l, %%d4l, (-160*4,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d1u, %%d4u,                       %%acc0 \n"
        "mac.w    %%d1u, %%d4l, (-224*4,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d1l, %%d4u,                       %%acc0 \n"
        "mac.w    %%d1l, %%d4l, (  32*4,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d2u, %%d4u,                       %%acc0 \n"
        "mac.w    %%d2u, %%d4l, (  96*4,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d2l, %%d4u,                       %%acc0 \n"
        "mac.w    %%d2l, %%d4l, ( 160*4,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d3u, %%d4u,                       %%acc0 \n"
        "mac.w    %%d3u, %%d4l, ( 224*4,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d3l, %%d4u,                       %%acc0 \n"
        "mac.w    %%d3l, %%d4l, ( -16*4,%[x1]), %%d4, %%acc1 \n"
        "movem.l  (16,%[wp]), %%d0-%%d3                      \n"
        "mac.w    %%d0u, %%d4u,                       %%acc2 \n"
        "mac.w    %%d0u, %%d4l, ( -48*4,%[x1]), %%d4, %%acc3 \n"
        "mac.w    %%d0l, %%d4u,                       %%acc2 \n"
        "mac.w    %%d0l, %%d4l, (  16*4,%[x1]), %%d4, %%acc3 \n"
        "msac.w   %%d0l, %%d4u,                       %%acc2 \n"
        "msac.w   %%d0l, %%d4l, ( -80*4,%[x1]), %%d4, %%acc3 \n"
        "mac.w    %%d1u, %%d4u,                       %%acc2 \n"
        "mac.w    %%d1u, %%d4l, (  48*4,%[x1]), %%d4, %%acc3 \n"
        "mac.w    %%d1u, %%d4u,                       %%acc2 \n"
        "mac.w    %%d1u, %%d4l, (-112*4,%[x1]), %%d4, %%acc3 \n"
        "mac.w    %%d1l, %%d4u,                       %%acc2 \n"
        "mac.w    %%d1l, %%d4l, (  80*4,%[x1]), %%d4, %%acc3 \n"
        "msac.w   %%d1l, %%d4u,                       %%acc2 \n"
        "msac.w   %%d1l, %%d4l, (-144*4,%[x1]), %%d4, %%acc3 \n"
        "mac.w    %%d2u, %%d4u,                       %%acc2 \n"
        "mac.w    %%d2u, %%d4l, ( 112*4,%[x1]), %%d4, %%acc3 \n"
        "mac.w    %%d2u, %%d4u,                       %%acc2 \n"
        "mac.w    %%d2u, %%d4l, (-176*4,%[x1]), %%d4, %%acc3 \n"
        "mac.w    %%d2l, %%d4u,                       %%acc2 \n"
        "mac.w    %%d2l, %%d4l, ( 144*4,%[x1]), %%d4, %%acc3 \n"
        "msac.w   %%d2l, %%d4u,                       %%acc2 \n"
        "msac.w   %%d2l, %%d4l, (-208*4,%[x1]), %%d4, %%acc3 \n"
        "mac.w    %%d3u, %%d4u,                       %%acc2 \n"
        "mac.w    %%d3u, %%d4l, ( 176*4,%[x1]), %%d4, %%acc3 \n"
        "mac.w    %%d3u, %%d4u,                       %%acc2 \n"
        "mac.w    %%d3u, %%d4l, (-240*4,%[x1]), %%d4, %%acc3 \n"
        "mac.w    %%d3l, %%d4u,                       %%acc2 \n"
        "mac.w    %%d3l, %%d4l, ( 208*4,%[x1]), %%d4, %%acc3 \n"
        "msac.w   %%d3l, %%d4u,                       %%acc2 \n"
        "msac.w   %%d3l, %%d4l,                       %%acc3 \n"
        "movclr.l %%acc0, %%d0                               \n"
        "move.l   %%d0, %[s0]                                \n"
        "movclr.l %%acc1, %%d0                               \n"
        "move.l   %%d0, %[s1]                                \n"
        "movclr.l %%acc2, %%d0                               \n"
        "move.l   %%d0, %[t0]                                \n"
        "movclr.l %%acc3, %%d0                               \n"
        "move.l   %%d0, %[t1]                                \n"
        : [x1] "+a" (x1), [s0] "+m" (s0), [t0] "+m" (t0),
                          [s1] "+m" (s1), [t1] "+m" (t1)
        : [wp] "a" (wp) : "d0", "d1", "d2", "d3", "d4");

        int u = shft4(s0 - t0);
        int v = shft4(s0 + t0);
        t0 = a0[14];
        s0 = a0[15] - t0;

        a0[31] = v + t0;   /* A0 */
        a0[30] = u + s0;   /* A1 */
        a0[15] = u - s0;   /* A2 */
        a0[14] = v - t0;   /* A3 */

        u  = shft4(s1 - t1);
        v  = shft4(s1 + t1);
        t1 = a1[14];
        s1 = a1[15] - t1;

        a1[31] = v + t1;   /* A0 */
        a1[30] = u + s1;   /* A1 */
        a1[15] = u - s1;   /* A2 */
        a1[14] = v - t1;   /* A3 */
    }
}

static void ICODE_ATTR window_subband1_m(const short *wk, int a0[32])
{
    for (int k = 0; k < 18; k++, wk += 32, a0 += 32)
    {
        const short *wp = enwindow;
        const short *x1 = wk;
        const short *x2 = x1 - 62;
        int s0, t0;

        for (int i = -15; i < 0; i++)
        {
            asm volatile (
            "movem.l  (%[wp]), %%d0-%%d3                         \n"
            "move.l   (-224*2,%[x2]), %%d4                       \n"
            "mac.w    %%d0u, %%d4u, (-160*2,%[x2]), %%d4, %%acc0 \n"
            "mac.w    %%d0l, %%d4u, ( -96*2,%[x2]), %%d4, %%acc0 \n"
            "mac.w    %%d1u, %%d4u, ( -32*2,%[x2]), %%d4, %%acc0 \n"
            "mac.w    %%d1l, %%d4u, (  32*2,%[x2]), %%d4, %%acc0 \n"
            "mac.w    %%d2u, %%d4u, (  96*2,%[x2]), %%d4, %%acc0 \n"
            "mac.w    %%d2l, %%d4u, ( 160*2,%[x2]), %%d4, %%acc0 \n"
            "mac.w    %%d3u, %%d4u, ( 224*2,%[x2]), %%d4, %%acc0 \n"
            "mac.w    %%d3l, %%d4u, ( 224*2,%[x1]), %%d4, %%acc0 \n"
            "mac.w    %%d0u, %%d4u, ( 160*2,%[x1]), %%d4, %%acc1 \n"
            "mac.w    %%d0l, %%d4u, (  96*2,%[x1]), %%d4, %%acc1 \n"
            "mac.w    %%d1u, %%d4u, (  32*2,%[x1]), %%d4, %%acc1 \n"
            "mac.w    %%d1l, %%d4u, ( -32*2,%[x1]), %%d4, %%acc1 \n"
            "mac.w    %%d2u, %%d4u, ( -96*2,%[x1]), %%d4, %%acc1 \n"
            "mac.w    %%d2l, %%d4u, (-160*2,%[x1]), %%d4, %%acc1 \n"
            "mac.w    %%d3u, %%d4u, (-224*2,%[x1]), %%d4, %%acc1 \n"
            "mac.w    %%d3l, %%d4u, (-256*2,%[x1]), %%d4, %%acc1 \n"
            "movem.l  (16,%[wp]), %%d0-%%d3                      \n"
            "mac.w    %%d0u, %%d4u, (-192*2,%[x1]), %%d4, %%acc0 \n"
            "mac.w    %%d0l, %%d4u, (-128*2,%[x1]), %%d4, %%acc0 \n"
            "mac.w    %%d1u, %%d4u, ( -64*2,%[x1]), %%d4, %%acc0 \n"
            "mac.w    %%d1l, %%d4u, (   0*2,%[x1]), %%d4, %%acc0 \n"
            "mac.w    %%d2u, %%d4u, (  64*2,%[x1]), %%d4, %%acc0 \n"
            "mac.w    %%d2l, %%d4u, ( 128*2,%[x1]), %%d4, %%acc0 \n"
            "mac.w    %%d3u, %%d4u, ( 192*2,%[x1]), %%d4, %%acc0 \n"
            "mac.w    %%d3l, %%d4u, ( 256*2,%[x2]), %%d4, %%acc0 \n"
            "msac.w   %%d0u, %%d4u, ( 192*2,%[x2]), %%d4, %%acc1 \n"
            "msac.w   %%d0l, %%d4u, ( 128*2,%[x2]), %%d4, %%acc1 \n"
            "msac.w   %%d1u, %%d4u, (  64*2,%[x2]), %%d4, %%acc1 \n"
            "msac.w   %%d1l, %%d4u, (   0*2,%[x2]), %%d4, %%acc1 \n"
            "msac.w   %%d2u, %%d4u, ( -64*2,%[x2]), %%d4, %%acc1 \n"
            "msac.w   %%d2l, %%d4u, (-128*2,%[x2]), %%d4, %%acc1 \n"
            "msac.w   %%d3u, %%d4u, (-192*2,%[x2]), %%d4, %%acc1 \n"
            "msac.w   %%d3l, %%d4u,                       %%acc1 \n"
            "movclr.l %%acc0, %%d0                               \n"
            "move.l   %%d0, %[s0]                                \n"
            "movclr.l %%acc1, %%d0                               \n"
            "move.l   %%d0, %[t0]                                \n"
            : [x1] "+a" (x1), [x2] "+a" (x2), [s0] "+m" (s0), [t0] "+m" (t0)
            : [wp] "a" (wp) : "d0", "d1", "d2", "d3", "d4");

            a0[30+i*2] =  shft4(t0)          + shft13(s0) * wp[16];
            a0[31+i*2] = shft13(t0) * wp[17] - shft13(s0) * wp[18];
            wp += 20;
            x1--;
            x2++;
        }

        asm volatile (
        "move.l   ( -32*2,%[x1]), %%d4                       \n"
        "movem.l  (%[wp]), %%d0-%%d3                         \n"
        "mac.w    %%d0u, %%d4u, ( -96*2,%[x1]), %%d4, %%acc0 \n"
        "mac.w    %%d0l, %%d4u, (-160*2,%[x1]), %%d4, %%acc0 \n"
        "mac.w    %%d1u, %%d4u, (-224*2,%[x1]), %%d4, %%acc0 \n"
        "mac.w    %%d1l, %%d4u, (  32*2,%[x1]), %%d4, %%acc0 \n"
        "mac.w    %%d2u, %%d4u, (  96*2,%[x1]), %%d4, %%acc0 \n"
        "mac.w    %%d2l, %%d4u, ( 160*2,%[x1]), %%d4, %%acc0 \n"
        "mac.w    %%d3u, %%d4u, ( 224*2,%[x1]), %%d4, %%acc0 \n"
        "mac.w    %%d3l, %%d4u, ( -16*2,%[x1]), %%d4, %%acc0 \n"
        "movem.l  (16,%[wp]), %%d0-%%d3                      \n"
        "mac.w    %%d0u, %%d4u, ( -48*2,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d0l, %%d4u, (  16*2,%[x1]), %%d4, %%acc1 \n"
        "msac.w   %%d0l, %%d4u, ( -80*2,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d1u, %%d4u, (  48*2,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d1u, %%d4u, (-112*2,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d1l, %%d4u, (  80*2,%[x1]), %%d4, %%acc1 \n"
        "msac.w   %%d1l, %%d4u, (-144*2,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d2u, %%d4u, ( 112*2,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d2u, %%d4u, (-176*2,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d2l, %%d4u, ( 144*2,%[x1]), %%d4, %%acc1 \n"
        "msac.w   %%d2l, %%d4u, (-208*2,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d3u, %%d4u, ( 176*2,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d3u, %%d4u, (-240*2,%[x1]), %%d4, %%acc1 \n"
        "mac.w    %%d3l, %%d4u, ( 208*2,%[x1]), %%d4, %%acc1 \n"
        "msac.w   %%d3l, %%d4u,                       %%acc1 \n"
        "movclr.l %%acc0, %%d0                               \n"
        "move.l   %%d0, %[s0]                                \n"
        "movclr.l %%acc1, %%d0                               \n"
        "move.l   %%d0, %[t0]                                \n"
        : [x1] "+a" (x1), [s0] "+m" (s0), [t0] "+m" (t0)
        : [wp] "a" (wp) : "d0", "d1", "d2", "d3", "d4");

        int u = shft4(s0 - t0);
        int v = shft4(s0 + t0);
        t0 = a0[14];
        s0 = a0[15] - t0;

        a0[31] = v + t0;   /* A0 */
        a0[30] = u + s0;   /* A1 */
        a0[15] = u - s0;   /* A2 */
        a0[14] = v - t0;   /* A3 */
    }
}

#else /* Generic CPU */

static void ICODE_ATTR window_subband1_s_(const short *wk, int a[32])
{
    for (int k = 0; k < 18; k++, wk += 64, a += 32)
    {
        const short *wp = enwindow;
        const short *x1 = wk;
        const short *x2 = x1 - 124;
        int s, t;

        /* x1[-572] .... x1[448] = 1022 */
        /* 18*4*16*32 */
        for (int i = -15; i < 0; i++)
        {
            s  = (int)x2[-224*2] * wp[ 0];  t  = (int)x1[ 224*2] * wp[ 0];
            s += (int)x2[-160*2] * wp[ 1];  t += (int)x1[ 160*2] * wp[ 1];
            s += (int)x2[- 96*2] * wp[ 2];  t += (int)x1[  96*2] * wp[ 2];
            s += (int)x2[- 32*2] * wp[ 3];  t += (int)x1[  32*2] * wp[ 3];
            s += (int)x2[  32*2] * wp[ 4];  t += (int)x1[- 32*2] * wp[ 4];
            s += (int)x2[  96*2] * wp[ 5];  t += (int)x1[- 96*2] * wp[ 5];
            s += (int)x2[ 160*2] * wp[ 6];  t += (int)x1[-160*2] * wp[ 6];
            s += (int)x2[ 224*2] * wp[ 7];  t += (int)x1[-224*2] * wp[ 7];
            s += (int)x1[-256*2] * wp[ 8];  t -= (int)x2[ 256*2] * wp[ 8];
            s += (int)x1[-192*2] * wp[ 9];  t -= (int)x2[ 192*2] * wp[ 9];
            s += (int)x1[-128*2] * wp[10];  t -= (int)x2[ 128*2] * wp[10];
            s += (int)x1[- 64*2] * wp[11];  t -= (int)x2[  64*2] * wp[11];
            s += (int)x1[   0*2] * wp[12];  t -= (int)x2[   0*2] * wp[12];
            s += (int)x1[  64*2] * wp[13];  t -= (int)x2[- 64*2] * wp[13];
            s += (int)x1[ 128*2] * wp[14];  t -= (int)x2[-128*2] * wp[14];
            s += (int)x1[ 192*2] * wp[15];  t -= (int)x2[-192*2] * wp[15];

            a[30+i*2] =  shft4(t)          + shft13(s) * wp[16];
            a[31+i*2] = shft13(t) * wp[17] - shft13(s) * wp[18];
            wp += 20;
            x1 -=  2;
            x2 +=  2;
        }

        t  =  (int)x1[- 16*2]              * wp[ 8];  s  = (int)x1[ -32*2] * wp[0];
        t += ((int)x1[- 48*2] - x1[ 16*2]) * wp[ 9];  s += (int)x1[ -96*2] * wp[1];
        t += ((int)x1[- 80*2] + x1[ 48*2]) * wp[10];  s += (int)x1[-160*2] * wp[2];
        t += ((int)x1[-112*2] - x1[ 80*2]) * wp[11];  s += (int)x1[-224*2] * wp[3];
        t += ((int)x1[-144*2] + x1[112*2]) * wp[12];  s += (int)x1[  32*2] * wp[4];
        t += ((int)x1[-176*2] - x1[144*2]) * wp[13];  s += (int)x1[  96*2] * wp[5];
        t += ((int)x1[-208*2] + x1[176*2]) * wp[14];  s += (int)x1[ 160*2] * wp[6];
        t += ((int)x1[-240*2] - x1[208*2]) * wp[15];  s += (int)x1[ 224*2] * wp[7];

        int u = shft4(s - t);
        int v = shft4(s + t);
        t = a[14];
        s = a[15] - t;

        a[31] = v + t;   /* A0 */
        a[30] = u + s;   /* A1 */
        a[15] = u - s;   /* A2 */
        a[14] = v - t;   /* A3 */
    }
}

static inline void window_subband1_s(const short *wk, int a0[32], int a1[32])
{
    window_subband1_s_(wk    , a0);
    window_subband1_s_(wk + 1, a1);
}

static void ICODE_ATTR window_subband1_m(const short *wk, int a[32])
{
    for (int k = 0; k < 18; k++, wk += 32, a += 32)
    {
        const short *wp = enwindow;
        const short *x1 = wk;
        const short *x2 = x1 - 62;
        int s, t;

        /* x1[-286] .... x1[224] = 511 */
        /* 18*2*16*32 */
        for (int i = -15; i < 0; i++)
        {
            s  = (int)x2[-224] * wp[ 0];  t  = (int)x1[ 224] * wp[ 0];
            s += (int)x2[-160] * wp[ 1];  t += (int)x1[ 160] * wp[ 1];
            s += (int)x2[- 96] * wp[ 2];  t += (int)x1[  96] * wp[ 2];
            s += (int)x2[- 32] * wp[ 3];  t += (int)x1[  32] * wp[ 3];
            s += (int)x2[  32] * wp[ 4];  t += (int)x1[- 32] * wp[ 4];
            s += (int)x2[  96] * wp[ 5];  t += (int)x1[- 96] * wp[ 5];
            s += (int)x2[ 160] * wp[ 6];  t += (int)x1[-160] * wp[ 6];
            s += (int)x2[ 224] * wp[ 7];  t += (int)x1[-224] * wp[ 7];
            s += (int)x1[-256] * wp[ 8];  t -= (int)x2[ 256] * wp[ 8];
            s += (int)x1[-192] * wp[ 9];  t -= (int)x2[ 192] * wp[ 9];
            s += (int)x1[-128] * wp[10];  t -= (int)x2[ 128] * wp[10];
            s += (int)x1[- 64] * wp[11];  t -= (int)x2[  64] * wp[11];
            s += (int)x1[   0] * wp[12];  t -= (int)x2[   0] * wp[12];
            s += (int)x1[  64] * wp[13];  t -= (int)x2[- 64] * wp[13];
            s += (int)x1[ 128] * wp[14];  t -= (int)x2[-128] * wp[14];
            s += (int)x1[ 192] * wp[15];  t -= (int)x2[-192] * wp[15];

            a[30+i*2] =  shft4(t)          + shft13(s) * wp[16];
            a[31+i*2] = shft13(t) * wp[17] - shft13(s) * wp[18];
            wp += 20;
            x1--;
            x2++;
        }

        t  =  (int)x1[- 16]            * wp[ 8];  s  = (int)x1[ -32] * wp[0];
        t += ((int)x1[- 48] - x1[ 16]) * wp[ 9];  s += (int)x1[ -96] * wp[1];
        t += ((int)x1[- 80] + x1[ 48]) * wp[10];  s += (int)x1[-160] * wp[2];
        t += ((int)x1[-112] - x1[ 80]) * wp[11];  s += (int)x1[-224] * wp[3];
        t += ((int)x1[-144] + x1[112]) * wp[12];  s += (int)x1[  32] * wp[4];
        t += ((int)x1[-176] - x1[144]) * wp[13];  s += (int)x1[  96] * wp[5];
        t += ((int)x1[-208] + x1[176]) * wp[14];  s += (int)x1[ 160] * wp[6];
        t += ((int)x1[-240] - x1[208]) * wp[15];  s += (int)x1[ 224] * wp[7];

        int u = shft4(s - t);
        int v = shft4(s + t);
        t = a[14];
        s = a[15] - t;

        a[31] = v + t;   /* A0 */
        a[30] = u + s;   /* A1 */
        a[15] = u - s;   /* A2 */
        a[14] = v - t;   /* A3 */
    }
}
#endif /* CPU */

static void ICODE_ATTR window_subband2_(int a[32])
{
    /* 36864=4*18*16*32 */
    const short * const wp = enwindow + 20 * 15;
    for (int k = 0; k < 18; k++, a += 32)
    {
        int xr;

        xr = a[28] - a[0];  a[0] += a[28];  a[28] = shft9(xr) * wp[-2*20+17];
        xr = a[29] - a[1];  a[1] += a[29];  a[29] = shft9(xr) * wp[-2*20+17];
        xr = a[26] - a[2];  a[2] += a[26];  a[26] = shft9(xr) * wp[-4*20+17];
        xr = a[27] - a[3];  a[3] += a[27];  a[27] = shft9(xr) * wp[-4*20+17];
        xr = a[24] - a[4];  a[4] += a[24];  a[24] = shft9(xr) * wp[-6*20+17];
        xr = a[25] - a[5];  a[5] += a[25];  a[25] = shft9(xr) * wp[-6*20+17];
        xr = a[22] - a[6];  a[6] += a[22];  a[22] = shft9(xr) * SQRT        ;
        xr = a[23] - a[7];  a[7] += a[23];  a[23] = shft9(xr) * SQRT  - a[7];
        a[ 7] -= a[ 6];
        a[22] -= a[ 7];
        a[23] -= a[22];

        xr = a[ 6];  a[ 6] = a[31] - xr;  a[31] = a[31] + xr;
        xr = a[ 7];  a[ 7] = a[30] - xr;  a[30] = a[30] + xr;
        xr = a[22];  a[22] = a[15] - xr;  a[15] = a[15] + xr;
        xr = a[23];  a[23] = a[14] - xr;  a[14] = a[14] + xr;

        xr = a[20] - a[ 8];  a[ 8] += a[20];  a[20] = shft9(xr) * wp[-10*20+17];
        xr = a[21] - a[ 9];  a[ 9] += a[21];  a[21] = shft9(xr) * wp[-10*20+17];
        xr = a[18] - a[10];  a[10] += a[18];  a[18] = shft9(xr) * wp[-12*20+17];
        xr = a[19] - a[11];  a[11] += a[19];  a[19] = shft9(xr) * wp[-12*20+17];
        xr = a[16] - a[12];  a[12] += a[16];  a[16] = shft9(xr) * wp[-14*20+17];
        xr = a[17] - a[13];  a[13] += a[17];  a[17] = shft9(xr) * wp[-14*20+17];
        xr =-a[20] + a[24];  a[20] += a[24];  a[24] = shft9(xr) * wp[-12*20+17];
        xr =-a[21] + a[25];  a[21] += a[25];  a[25] = shft9(xr) * wp[-12*20+17];
        xr = a[ 4] - a[ 8];  a[ 4] += a[ 8];  a[ 8] = shft9(xr) * wp[-12*20+17];
        xr = a[ 5] - a[ 9];  a[ 5] += a[ 9];  a[ 9] = shft9(xr) * wp[-12*20+17];
        xr = a[ 0] - a[12];  a[ 0] += a[12];  a[12] = shft9(xr) * wp[ -4*20+17];
        xr = a[ 1] - a[13];  a[ 1] += a[13];  a[13] = shft9(xr) * wp[ -4*20+17];
        xr = a[16] - a[28];  a[16] += a[28];  a[28] = shft9(xr) * wp[ -4*20+17];
        xr =-a[17] + a[29];  a[17] += a[29];  a[29] = shft9(xr) * wp[ -4*20+17];

        xr = SQRT * shft9(a[ 2] - a[10]);  a[ 2] += a[10];  a[10] = xr;
        xr = SQRT * shft9(a[ 3] - a[11]);  a[ 3] += a[11];  a[11] = xr;
        xr = SQRT * shft9(a[26] - a[18]);  a[18] += a[26];  a[26] = xr - a[18];
        xr = SQRT * shft9(a[27] - a[19]);  a[19] += a[27];  a[27] = xr - a[19];

        xr = a[ 2];  a[19] -= a[ 3];  a[ 3] -= xr;  a[ 2] = a[31] - xr;  a[31] += xr;
        xr = a[ 3];  a[11] -= a[19];  a[18] -= xr;  a[ 3] = a[30] - xr;  a[30] += xr;
        xr = a[18];  a[27] -= a[11];  a[19] -= xr;  a[18] = a[15] - xr;  a[15] += xr;

        xr = a[19];  a[10] -= xr;  a[19] = a[14] - xr;  a[14] += xr;
        xr = a[10];  a[11] -= xr;  a[10] = a[23] - xr;  a[23] += xr;
        xr = a[11];  a[26] -= xr;  a[11] = a[22] - xr;  a[22] += xr;
        xr = a[26];  a[27] -= xr;  a[26] = a[ 7] - xr;  a[ 7] += xr;

        xr = a[27];  a[27] = a[6] - xr;  a[6] += xr;

        xr = SQRT * shft9(a[ 0] - a[ 4]);  a[ 0] += a[ 4];  a[ 4] = xr;
        xr = SQRT * shft9(a[ 1] - a[ 5]);  a[ 1] += a[ 5];  a[ 5] = xr;
        xr = SQRT * shft9(a[16] - a[20]);  a[16] += a[20];  a[20] = xr;
        xr = SQRT * shft9(a[17] - a[21]);  a[17] += a[21];  a[21] = xr;
        xr =-SQRT * shft9(a[ 8] - a[12]);  a[ 8] += a[12];  a[12] = xr - a[ 8];
        xr =-SQRT * shft9(a[ 9] - a[13]);  a[ 9] += a[13];  a[13] = xr - a[ 9];
        xr =-SQRT * shft9(a[25] - a[29]);  a[25] += a[29];  a[29] = xr - a[25];
        xr =-SQRT * shft9(a[24] + a[28]);  a[24] -= a[28];  a[28] = xr - a[24];

        xr = a[24] - a[16]; a[24] = xr;
        xr = a[20] - xr;    a[20] = xr;
        xr = a[28] - xr;    a[28] = xr;

        xr = a[25] - a[17]; a[25] = xr;
        xr = a[21] - xr;    a[21] = xr;
        xr = a[29] - xr;    a[29] = xr;

        xr = a[17] - a[1];  a[17] = xr;
        xr = a[ 9] - xr;    a[ 9] = xr;
        xr = a[25] - xr;    a[25] = xr;
        xr = a[ 5] - xr;    a[ 5] = xr;
        xr = a[21] - xr;    a[21] = xr;
        xr = a[13] - xr;    a[13] = xr;
        xr = a[29] - xr;    a[29] = xr;

        xr = a[ 1] - a[0];  a[ 1] = xr;
        xr = a[16] - xr;    a[16] = xr;
        xr = a[17] - xr;    a[17] = xr;
        xr = a[ 8] - xr;    a[ 8] = xr;
        xr = a[ 9] - xr;    a[ 9] = xr;
        xr = a[24] - xr;    a[24] = xr;
        xr = a[25] - xr;    a[25] = xr;
        xr = a[ 4] - xr;    a[ 4] = xr;
        xr = a[ 5] - xr;    a[ 5] = xr;
        xr = a[20] - xr;    a[20] = xr;
        xr = a[21] - xr;    a[21] = xr;
        xr = a[12] - xr;    a[12] = xr;
        xr = a[13] - xr;    a[13] = xr;
        xr = a[28] - xr;    a[28] = xr;
        xr = a[29] - xr;    a[29] = xr;

        xr = a[ 0];  a[ 0] += a[31];  a[31] -= xr;
        xr = a[ 1];  a[ 1] += a[30];  a[30] -= xr;
        xr = a[16];  a[16] += a[15];  a[15] -= xr;
        xr = a[17];  a[17] += a[14];  a[14] -= xr;
        xr = a[ 8];  a[ 8] += a[23];  a[23] -= xr;
        xr = a[ 9];  a[ 9] += a[22];  a[22] -= xr;
        xr = a[24];  a[24] += a[ 7];  a[ 7] -= xr;
        xr = a[25];  a[25] += a[ 6];  a[ 6] -= xr;
        xr = a[ 4];  a[ 4] += a[27];  a[27] -= xr;
        xr = a[ 5];  a[ 5] += a[26];  a[26] -= xr;
        xr = a[20];  a[20] += a[11];  a[11] -= xr;
        xr = a[21];  a[21] += a[10];  a[10] -= xr;
        xr = a[12];  a[12] += a[19];  a[19] -= xr;
        xr = a[13];  a[13] += a[18];  a[18] -= xr;
        xr = a[28];  a[28] += a[ 3];  a[ 3] -= xr;
        xr = a[29];  a[29] += a[ 2];  a[ 2] -= xr;

        /* Compensate for inversion in the analysis filter */
        if (k & 1)
        {
            for (int band = 1; band < 32; band += 2)
                a[band] *= -1;
        }
    }
}

static inline void window_subband2_m(int a0[32])
{
    window_subband2_(a0);
}

static inline void window_subband2_s(int a0[32], int a1[32])
{
    window_subband2_(a0);
    window_subband2_(a1);
}

static inline void mdct_long(int *out, int *in)
{
    int ct, st;
    int tc1, tc2, tc3, tc4, ts5, ts6, ts7, ts8;
    int ts1, ts2, ts3, ts4, tc5, tc6, tc7, tc8;

    /* 1,2, 5,6, 9,10, 13,14, 17 */
    tc1 = in[17] - in[ 9];
    tc3 = in[15] - in[11];
    tc4 = in[14] - in[12];
    ts5 = in[ 0] + in[ 8];
    ts6 = in[ 1] + in[ 7];
    ts7 = in[ 2] + in[ 6];
    ts8 = in[ 3] + in[ 5];

    out[17] = (ts5 + ts7 - ts8) * cx[8] - (ts6 - in[4]) * cx[8];
    st      = (ts5 + ts7 - ts8) * cx[7] + (ts6 - in[4]) * cx[8];
    ct      = (tc1 - tc3 - tc4) * cx[6];
    out[5]  = ct + st;
    out[6]  = ct - st;

    tc2     = (in[16] - in[10]) * cx[6];
    ts6     =  ts6 * cx[7] + in[4] * cx[8];

    ct      =  tc1 * cx[0] + tc2 + tc3 * cx[1] + tc4 * cx[2];
    st      = -ts5 * cx[4] + ts6 - ts7 * cx[5] + ts8 * cx[3];
    out[1]  = ct + st;
    out[2]  = ct - st;

    ct      =  tc1 * cx[1] - tc2 - tc3 * cx[2] + tc4 * cx[0];
    st      = -ts5 * cx[5] + ts6 - ts7 * cx[3] + ts8 * cx[4];
    out[ 9] = ct + st;
    out[10] = ct - st;

    ct      = tc1 * cx[2] - tc2 + tc3 * cx[0] - tc4 * cx[1];
    st      = ts5 * cx[3] - ts6 + ts7 * cx[4] - ts8 * cx[5];
    out[13] = ct + st;
    out[14] = ct - st;

    ts1 = in[ 8] - in[ 0];
    ts3 = in[ 6] - in[ 2];
    ts4 = in[ 5] - in[ 3];
    tc5 = in[17] + in[ 9];
    tc6 = in[16] + in[10];
    tc7 = in[15] + in[11];
    tc8 = in[14] + in[12];

    out[0]  = (tc5 + tc7 + tc8) * cx[8] + (tc6 + in[13]) * cx[8];
    ct      = (tc5 + tc7 + tc8) * cx[7] - (tc6 + in[13]) * cx[8];
    st      = (ts1 - ts3 + ts4) * cx[6];
    out[11] = ct + st;
    out[12] = ct - st;

    ts2     = (in[7] - in[1]) * cx[6];
    tc6     = in[13] * cx[8] - tc6 * cx[7];

    ct      = tc5 * cx[3] - tc6 + tc7 * cx[4] + tc8 * cx[5];
    st      = ts1 * cx[2] + ts2 + ts3 * cx[0] + ts4 * cx[1];
    out[3]  = ct + st;
    out[4]  = ct - st;

    ct      =-tc5 * cx[5] + tc6 - tc7 * cx[3] - tc8 * cx[4];
    st      = ts1 * cx[1] + ts2 - ts3 * cx[2] - ts4 * cx[0];
    out[7]  = ct + st;
    out[8]  = ct - st;

    ct      =-tc5 * cx[4] + tc6 - tc7 * cx[5] - tc8 * cx[3];
    st      = ts1 * cx[0] - ts2 + ts3 * cx[1] - ts4 * cx[2];
    out[15] = ct + st;
    out[16] = ct - st;
}

static int find_bitrate_index(int type, int bitrate, bool stereo)
{
    if (type == 1 && !stereo && bitrate > 160)
        bitrate = 160;

    return ci->round_value_to_list32(bitrate,
        &bitr_index[type][1], 14, true) + 1;
}

static int find_samplerate_index(long freq, int *mp3_type)
{
    int mpeg = freq >= (32000 + 24000) / 2 ? 1 : 0;
    int i = ci->round_value_to_list32(freq, sampr_index[mpeg], 3, true);
    *mp3_type = mpeg;
    return i;
}

static void mp3_encoder_reset(void)
{
    ci->memset(&cfg.cod_info, 0, sizeof (cfg.cod_info));
    ci->memset(mfbuf        , 0, sizeof (mfbuf       ));
    ci->memset(sb_data      , 0, sizeof (sb_data     ));
    ci->memset(mdct_freq    , 0, sizeof (mdct_freq   ));
    ci->memset(mdct_sign    , 0, sizeof (mdct_sign   ));
    ci->memset(enc_data     , 0, sizeof (enc_data    ));
    ci->memset(&coded_data  , 0, sizeof (coded_data  ));
    ci->memset(band_scale_f , 0, sizeof (band_scale_f));
    cfg.slot_lag = 0;
}

static void mp3_encoder_init(unsigned long sample_rate, int num_channels,
                             unsigned long bitrate)
{
    mp3_encoder_reset();

    const bool stereo  = num_channels > 1;
    cfg.channels       = stereo ? 2 : 1;
    cfg.mpg.mode       = stereo ? 0 : 3; /* 0=stereo, 3=mono */
    cfg.mpg.smpl_id    = find_samplerate_index(sample_rate, &cfg.mpg.type);
    cfg.samplerate     = sampr_index[cfg.mpg.type][cfg.mpg.smpl_id];
    cfg.src_samplerate = sample_rate;
    cfg.mpg.bitr_id    = find_bitrate_index(cfg.mpg.type, bitrate, stereo);
    cfg.mpg.bitrate    = bitr_index[cfg.mpg.type][cfg.mpg.bitr_id];
    cfg.mpg.num_bands  = num_bands[stereo ? cfg.mpg.type : 2][cfg.mpg.bitr_id];

    if (cfg.mpg.type == 1)
    {
        cfg.granules       = 2;
        cfg.samp_per_frame = 1152;
        cfg.flush_frames   = 2;
    }
    else
    {
        cfg.granules       = 1;
        cfg.samp_per_frame = 576;
        cfg.flush_frames   = 3;
    }

    cfg.delay   = 576-16;
    cfg.padding = 3*576+16;

    cfg.samp_buffer = mfbuf + cfg.channels*512;

    ci->memcpy(scalefac, sf_band[cfg.mpg.smpl_id + 3*cfg.mpg.type],
               sizeof (scalefac));

    /* Figure average number of 'bytes' per frame */
    cfg.byte_per_frame = calc_frame_size(cfg.mpg.bitr_id, &cfg.frac_per_frame);
    cfg.sideinfo_len   = 32 + (cfg.mpg.type ? (cfg.channels == 1 ? 136 : 256)
                                            : (cfg.channels == 1 ?  72 : 136));

    cfg.req_byte_per_frame = ALIGN_UP(cfg.byte_per_frame + 1,
                                      sizeof (uint32_t));
}

static void set_scale_facs(int *mdct_freq)
{
    int avrg_freq_val = 0;

    /* calc average of first 256 frequency values */
    for (int i = 0; i < 256; i++)
        avrg_freq_val += mdct_freq[i];

    avrg_freq_val >>= 8;

    /* if max of current band is smaller than average, increase precision */
    /* last band keeps untouched (not scaled) */
    for (unsigned int k = 0, is = 0; is < scalefac[20]; k++)
    {
        int max_freq_val = 0;
        unsigned ie = scalefac[k];

        for (unsigned int i = is; i < ie; i++)
        {
            if (max_freq_val < mdct_freq[i])
                max_freq_val = mdct_freq[i];
        }

        unsigned int s = 0;
        for (; s < 3; s++)
        {
            if ((max_freq_val << s) > avrg_freq_val)
                break;
        }

        band_scale_f[k] = (unsigned char)s;

        for (unsigned int i = is; s && i < ie; i++)
            mdct_freq[i] <<= s;

        is = ie;
    }
}

static inline void window_subband(int gr, int sbd[2][2][18][32])
{
    int *a0 = sbd[0][1-gr][0];

    if (cfg.channels == 1)
    {
        window_subband1_m(mfbuf + 286 + gr*576, a0);
        window_subband2_m(a0);
    }
    else
    {
        int *a1 = sbd[1][1-gr][0];
        window_subband1_s(mfbuf + 572 + gr*1152, a0, a1);
        window_subband2_s(a0, a1);
    }
}

static inline void get_sb_data(int gr)
{
#ifdef MP3_ENC_COP
    ci->memcpy(sb_data[0][1-gr], (*sb_data_enc)[0][1-gr],
               sizeof (sb_data[0][1-gr]));

    if (cfg.channels > 1)
        ci->memcpy(sb_data[1][1-gr], (*sb_data_enc)[1][1-gr],
                   sizeof (sb_data[1][1-gr]));
#else /* !MP3_ENC_COP */
    window_subband(gr, sb_data);
#endif /* MP3_ENC_COP */
}

/* Encode one mp3 frame */
static void ICODE_ATTR compress_frame(void)
{
    coded_data.bitpos = cfg.sideinfo_len; /* leave space for mp3 header */
    ci->memset(coded_data.bbuf, 0, sizeof (coded_data.bbuf));

    if ((cfg.slot_lag += cfg.frac_per_frame) >= 64)
    {
        /* Padding for this frame */
        cfg.slot_lag   -= 64;
        cfg.mpg.padding = 1;
    }
    else
    {
        cfg.mpg.padding = 0;
    }

    cfg.mean_bits = (8 * cfg.byte_per_frame + 8 * cfg.mpg.padding
                       - cfg.sideinfo_len) / cfg.granules / cfg.channels
                       - 42; // reserved for scale_facs

    cfg.resv_size = 0;

    int gr_cnt = cfg.granules * cfg.channels;
    for (int gr = 0; gr < cfg.granules; gr++)
    {
        get_sb_data(gr);

        for (int ch = 0; ch < cfg.channels; ch++, gr_cnt--)
        {
            /* Perform imdct of 18 previous + 18 current subband samples */
            /* for integer precision do this loop again (if neccessary)  */
            int shift = 14 - (cfg.cod_info[gr][ch].additStep >> 2);

            for (int ii = 0; ii < 3; ii++)
            {
                int *mdct = mdct_freq;

                cfg.cod_info[gr][ch].additStep = 4 * (14 - shift);

                for (int band = 0; band < cfg.mpg.num_bands; band++, mdct += 18)
                {
                    int *band0 = sb_data[ch][  gr][0] + order[band];
                    int *band1 = sb_data[ch][1-gr][0] + order[band];
                    int work[18];

                    /* 9216=4*32*9*8 */
                    for (int k = -9; k < 0; k++)
                    {
                        int a = shft_n(band1[(k+9)*32], shift);
                        int b = shft_n(band1[(8-k)*32], shift);
                        int c = shft_n(band0[(k+9)*32], shift);
                        int d = shft_n(band0[(8-k)*32], shift);

                        work[k+ 9] = shft16(a * win[k+ 9][0] +
                                            b * win[k+ 9][1] +
                                            c * win[k+ 9][2] +
                                            d * win[k+ 9][3]);

                        work[k+18] = shft16(c * win[k+18][0] +
                                            d * win[k+18][1] +
                                            a * win[k+18][2] +
                                            b * win[k+18][3]);
                    }

                    /* 7200=4*18*100 */
                    mdct_long(mdct, work);

                    /* Perform aliasing reduction butterfly */
                    if (band != 0)
                    {
                        for (int k = 7; k >= 0; k--)
                        {
                            int bu = shft15(mdct[k]) * ca[k] +
                                     shft15(mdct[-1-k]) * cs[k];
                            int bd = shft15(mdct[k]) * cs[k] -
                                     shft15(mdct[-1-k]) * ca[k];
                            mdct[-1-k] = bu;
                            mdct[ k  ] = bd;
                        }
                    }
                }

                uint32_t max = 0;

                for (int k = 0; k < 576; k++)
                {
                    if (mdct_freq[k] < 0)
                    {
                        mdct_sign[k] = 1; /* negative */
                        mdct_freq[k] = shft13(-mdct_freq[k]);
                    }
                    else
                    {
                        mdct_sign[k] = 0; /* positive */
                        mdct_freq[k] = shft13(mdct_freq[k]);
                    }

                    if (max < (uint32_t)mdct_freq[k])
                        max = (uint32_t)mdct_freq[k];
                }

                cfg.cod_info[gr][ch].max_val = max;

                /* calc new shift for higher integer precision */
                int i = 0;
                while (max < (0x7800u >> i))   i++, shift--;
                while ((max >> i) >= 0x10000u) i++, shift++;
                if (i == 0) break;
                if (shift < 0) shift = 0;
            }

            cfg.cod_info[gr][ch].quantStep +=
                                cfg.cod_info[gr][ch].additStep;

            set_scale_facs(mdct_freq);

            /* bit and noise allocation */
            iteration_loop(mdct_freq, &cfg.cod_info[gr][ch], gr_cnt);

            /* write the frame to the bitstream */
            huffman_code_bits(enc_data, mdct_sign, &cfg.cod_info[gr][ch]);

            cfg.cod_info[gr][ch].quantStep -=
                                cfg.cod_info[gr][ch].additStep;

            if (cfg.granules == 1)
            {
                ci->memcpy(sb_data[ch][0], sb_data[ch][1],
                           sizeof (sb_data[ch][0]));
            }
        }
    }

    /* finish this chunk by adding sideinfo header data */
    coded_data.bitpos = 0;
    encode_side_info(cfg.cod_info);
}

/* Process the PCM data in the encoder's input buffer */
static void mp3_enc_encode_frame(void)
{
#ifdef MP3_ENC_COP
    for (int gr = 0; gr < cfg.granules; gr++)
        window_subband(gr, *sb_data_cod);
#else
    compress_frame();
#endif /* MP3_ENC_COP */

    /* shift out old samples */
    ci->memmove(mfbuf, mfbuf + cfg.channels*cfg.granules*576,
                cfg.channels*2*512);
}

/* Get the last encoded frame */
static size_t ICODE_ATTR mp3_enc_get_frame(uint8_t *outbuf)
{
    long size = cfg.byte_per_frame + cfg.mpg.padding;

#ifdef ROCKBOX_LITTLE_ENDIAN
    /* convert frame to big endian */
    const uint32_t *src = coded_data.bbuf;
    uint32_t *dst = (uint32_t *)outbuf;

    for (long i = 0; i < size; i += sizeof (uint32_t))
        *dst++ = swap32(*src++);
#else
    ci->memcpy(outbuf, coded_data.bbuf, size);
#endif /* ROCKBOX_LITTLE_ENDIAN */

    return size;
}


/*======== Codec section ========*/

/* CRC code lovingly ripped from:
 * github.com/CFR-maniac/lame/blob/master/libmp3lame/VbrTag.c */

/* Lookup table for fast CRC computation
 * See 'crc_update_lookup'
 * Uses the polynomial x^16+x^15+x^2+1 */
static const uint16_t crc16_lookup[256] ICONST_ATTR =
{
    0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
    0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
    0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
    0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
    0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
    0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
    0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
    0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
    0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
    0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
    0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
    0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
    0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
    0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
    0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
    0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
    0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
    0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
    0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
    0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
    0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
    0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
    0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
    0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
    0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
    0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
    0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
    0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
    0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
    0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
    0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
    0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
};

static ssize_t header_size IBSS_ATTR;
static unsigned int mp3_crc16 IBSS_ATTR;

/* fast CRC-16 computation - uses table crc16_lookup 8*/
static inline unsigned int crc_update_lookup(unsigned int value,
                                             unsigned int crc)
{
    unsigned int tmp = crc ^ value;
    crc = (crc >> 8) ^ crc16_lookup[tmp & 0xff];
    return crc & 0xffff;
}

/* Calculate position of 'Info' header */
static int get_info_offset(uint32_t header)
{
    uint32_t type = (header & (0x3 << 19)) >> 19;
    uint32_t mode = (header & (0x3 << 6)) >> 6;

    return type == 3 ? (mode == 3 ? 21 : 36) : (mode == 3 ? 13 : 21);
}

/* Write very basic 'Info' header with delay, padding and a bit of
 * miscellaneous info. */
static bool write_info_header(bool first_encode)
{
    ssize_t size = cfg.byte_per_frame;

    /* By default the MP3 frame header for the info frame is the same as
       unpadded audio frames */
    uint32_t header = encode_header(0, cfg.mpg.bitr_id);

    int i = get_info_offset(header);

    if (i + 8 + 36 > size)
    {
        /* The default frame size too small so find the smallest one that
           may accomodate it by increasing the bit rate for this empty
           MP3 frame */
        int j;
        for (j = cfg.mpg.bitr_id + 1; j < 15; j++)
        {
            size = calc_frame_size(j, NULL);

            if (size >= i + 8 + 36)
                break;
        }

        if (j >= 15)
        {
            /* Shouldn't really happen but... */
            header_size = -1;
            return true;
        }

        header = encode_header(0, j);
        /* Info offset won't change */
    }

    uint8_t frame[size];
    ci->memset(frame, 0, size);

    frame[0] = header >> 24;
    frame[1] = header >> 16;
    frame[2] = header >>  8;
    frame[3] = header >>  0;

    /* 'Info' header (CBR 'Xing') */
    ci->memcpy(&frame[i], "Info", 4);

    /* flags = 0; Info contains no other sections and is 8 bytes */

    /* Just mark the LAMEness to indicate header presence; we're not
       actually _the_ LAME so 'rbshn' is the version we give */
    ci->memcpy(&frame[i + 8], "LAMErbshn", 9);

    /* Fill-in some info about us
     * reference: http://gabriel.mp3-tech.org/mp3infotag.html
     */

    /* Revision + VBR method:
     * [7:4] = Revision (0 ??)
     * [3:0] = VBR method (CBR)
     */
    frame[i + 17] = (0 << 4) | (1 << 0);

    /* If first frame since encoder reset is long gone (not unlikely in
       prerecording), then the delay is long passed and no trimming done
       at the start */
    unsigned int delay = first_encode ? cfg.delay : 0;
    unsigned int padding = cfg.padding;

    /* Delay and padding:
     * [23:12] = delay
     * [11: 0] = padding
     */
    frame[i + 29] = delay >> 4;
    frame[i + 30] = (delay << 4) | (padding >> 8);
    frame[i + 31] = padding;

    /* Misc:
     * [7:6] = source frequency
     * [  5] = unwise settings (of course not :)
     * [4:2] = stereo mode (mono or stereo)
     * [1:0] = noise shaping (who knows, 0)
     */
    uint8_t misc;

    if (cfg.src_samplerate <= 32000)
        misc = (0 << 6);
    else if (cfg.src_samplerate <= 44100)
        misc = (1 << 6);
    else if (cfg.src_samplerate <= 48000)
        misc = (2 << 6);
    else /* > 48000 */
        misc = (3 << 6);

    if (cfg.channels > 1)
        misc |= (1 << 2); /* Stereo */

    frame[i + 32] = misc;

    if (ci->enc_stream_write(frame, size) != size)
    {
        ci->enc_stream_lseek(0, SEEK_SET);
        header_size = -1;
        return false;
    }

    header_size = size;
    return true;
}

static int ICODE_ATTR on_stream_data(struct enc_chunk_data *data)
{
    ssize_t size = data->hdr.size;

    if (header_size > 0)
    {
        /* Header is layed-down; keep running CRC of audio data */
        uint8_t *p = data->data;
        uint8_t *p_end = p + size;

        while (p < p_end)
            mp3_crc16 = crc_update_lookup(*p++, mp3_crc16);
    }

    if (ci->enc_stream_write(data->data, size) != size)
        return -1;

    return 0;
}

static int on_stream_start(struct enc_chunk_file *file)
{
    mp3_crc16 = 0x0000;

    if (!write_info_header(file->hdr.aux0))
        return -1;

    return 0;
}

static int on_stream_end(union enc_chunk_hdr *hdr)
{
    ssize_t size = header_size;

    if (size <= 0)
        return 0; /* No header possible/none yet written */

    /* Update audio CRC and header CRC */
    uint8_t frame[size];

    /* Won't fail this since it could still be useable if some decoder
       plays loose with the CRC info (like Rockbox :) */
    if (ci->enc_stream_lseek(0, SEEK_SET) != 0 ||
        ci->enc_stream_read(frame, size) != size)
        return 0;

    uint32_t header = (frame[0] << 24) | (frame[1] << 16) |
                      (frame[2] <<  8) | (frame[3] <<  0);
    int i = get_info_offset(header); /* Get 'Info' header */

    /* 'Info' header = 8 bytes */

    /* Fill-in audio data CRC16 */

    /* On error, fixing data CRC would require scanning file since it
       has probably dropped something we tried to write and the likely
       reason is that the disk filled; just leave it 0 in that case. */
    if (!hdr->err)
    {
        frame[i + 40] = mp3_crc16 >> 8;
        frame[i + 41] = mp3_crc16;
    }

    /* Fill-in header CRC16 */
    unsigned int hdr_crc16 = 0x0000;
    for (int j = 0; j < i + 42; j++)
        hdr_crc16 = crc_update_lookup(frame[j], hdr_crc16);

    frame[i + 42] = hdr_crc16 >> 8;
    frame[i + 43] = hdr_crc16;

    /* Update file */
    if (ci->enc_stream_lseek(0, SEEK_SET) == 0)
        ci->enc_stream_write(frame, size);

    return 0;
}

#ifdef MP3_ENC_COP
/* Divide encoding duties between CPU and COP -
   CPU does the windowing and COP does the remainder of the encoding */
static const char enc_thread_name[] = { "MP3 enc" };
static enum enc_status
{
    ENC_SB_EMPTY,
    ENC_SB_FULL,
    ENC_QUIT,
} enc_status IBSS_ATTR;
static struct semaphore enc_sema IBSS_ATTR;
static struct semaphore cod_sema IBSS_ATTR;
static unsigned int enc_thread_id;

/* Needs one extra loop to drain sb_data_buf */
#define DRAIN_FRAMES 1

static void enc_thread(void)
{
    while (1)
    {
        ci->semaphore_release(&cod_sema);
        ci->semaphore_wait(&enc_sema, TIMEOUT_BLOCK);

        if (enc_status == ENC_QUIT)
            break;

        compress_frame();
    }
}
#else  /* !MP3_ENC_COP */
/* No encoder delay */
#define DRAIN_FRAMES 0
#endif /* MP3_ENC_COP */

static bool enc_thread_init(void *stack, size_t stack_size)
{
#ifdef MP3_ENC_COP
    enc_status = ENC_SB_EMPTY;
    ci->semaphore_init(&enc_sema, 1, 0);
    ci->semaphore_init(&cod_sema, 1, 0);

    sb_data_buf_init();

    enc_thread_id = ci->create_thread(enc_thread, stack, stack_size,
                                      0, enc_thread_name
                                      IF_PRIO(, PRIORITY_PLAYBACK)
                                      IF_COP(, COP));

    if (enc_thread_id == 0)
        return false;
#endif /* MP3_ENC_COP */

    return true;
    (void)stack; (void)stack_size;
}

static inline void enc_thread_compress_frame(void)
{
#ifdef MP3_ENC_COP
    sb_data_buf_swap();
    ci->semaphore_release(&enc_sema);
#endif /* MP3_ENC_COP */
}

static void enc_thread_stop(void)
{
#ifdef MP3_ENC_COP
    enc_status = ENC_QUIT;
    ci->semaphore_release(&enc_sema);
    ci->thread_wait(enc_thread_id);
#endif /* MP3_ENC_COP */
}

static inline void encode_frame(void)
{
    mp3_enc_encode_frame();
}

static inline bool wait_for_frame(void)
{
#ifdef MP3_ENC_COP
    ci->semaphore_wait(&cod_sema, TIMEOUT_BLOCK);

    if (enc_status == ENC_SB_EMPTY)
    {
        /* Fill subband data buffer before getting frame from COP */
        enc_status = ENC_SB_FULL;
        enc_thread_compress_frame();
        return false;
    }
#endif /* MP3_ENC_COP */

    return true;
}

static inline size_t get_frame(uint8_t *buffer)
{
    return mp3_enc_get_frame(buffer);
}

/* this is the codec entry point */
enum codec_status codec_main(enum codec_entry_call_reason reason)
{
#ifdef CPU_COLDFIRE
    if (reason == CODEC_LOAD)
        asm volatile ("move.l #0, %macsr"); /* integer mode */
#endif
    return CODEC_OK;
    (void)reason;
}

/* this is called for each file to process */
enum codec_status codec_run(void)
{
    /* Encoder thread stack goes on our stack - leave 4k for us
       Will be optimized away when single-threaded */
    uint32_t enc_stack[(DEFAULT_STACK_SIZE+0x1000) / sizeof (uint32_t)];

    if (!enc_thread_init(enc_stack, sizeof (enc_stack))) /* MT only */
        return CODEC_ERROR;

    mp3_encoder_reset();
    uint32_t first = 1;

    /* Needs to do stream finishing steps to flush-out all samples */
    int frames_rem = -1; /* < 0 = indeterminate */

    enum { GETBUF_PCM, GETBUF_ENC } getbuf = GETBUF_PCM;
    struct enc_chunk_data *data = NULL;

    /* main encoding loop */
    while (1)
    {
        intptr_t param;
        long action = ci->get_command(&param);

        if (action != CODEC_ACTION_NULL)
        {
            if (action != CODEC_ACTION_STREAM_FINISH)
                break;

            if (frames_rem < 0)
                frames_rem = cfg.flush_frames + DRAIN_FRAMES;

            /* Reply with required space */
            *(size_t *)param = cfg.req_byte_per_frame;
        }

        /* First, get PCM data; when available, obtain output buffer */
        switch (getbuf)
        {
        case GETBUF_PCM:
            if (LIKELY(frames_rem < 0))
            {
                /* Encoding audio */
                if (!ci->enc_pcmbuf_read(cfg.samp_buffer,
                                         cfg.samp_per_frame))
                    continue;

                ci->enc_pcmbuf_advance(cfg.samp_per_frame);
                encode_frame();
            }
            else if (frames_rem-- > DRAIN_FRAMES)
            {
                /* Flushing encoder */
                ci->memset(cfg.samp_buffer, 0,
                           cfg.samp_per_frame*cfg.channels*2);
                encode_frame();
            }
            /* else Draining remaining buffered data */

            if (!wait_for_frame()) /* MT only */
                break;

            getbuf = GETBUF_ENC;
        case GETBUF_ENC:
            data = ci->enc_encbuf_get_buffer(cfg.req_byte_per_frame);

            if (!data)
                continue;

            data->hdr.aux0 = first;
            first = 0;
            data->hdr.size = get_frame(data->data);

            if (frames_rem)
                enc_thread_compress_frame(); /* MT only */

            data->pcm_count = cfg.samp_per_frame;
            ci->enc_encbuf_finish_buffer();

            getbuf = GETBUF_PCM;
        }

        if (!frames_rem)
            break;
    } /* while */

    enc_thread_stop(); /* MT only */

    return CODEC_OK;
}

/* this is called by recording system */
int enc_callback(enum enc_callback_reason reason, void *params)
{
    if (LIKELY(reason == ENC_CB_STREAM))
    {
        switch (((union enc_chunk_hdr *)params)->type)
        {
        case CHUNK_T_DATA:
            return on_stream_data(params);
        case CHUNK_T_STREAM_START:
            return on_stream_start(params);
        case CHUNK_T_STREAM_END:
            return on_stream_end(params);
        }
    }
    else if (reason == ENC_CB_INPUTS)
    {
        struct enc_inputs *inputs = params;

        mp3_encoder_init(inputs->sample_rate, inputs->num_channels,
                         inputs->config->mp3_enc.bitrate);

        /* Return the actual configuration */
        inputs->enc_sample_rate = cfg.samplerate;
    }

    return 0;
}
