Added FS#2939 Encoder Codec Interface + Codecs by Antonius Hellmann with additional FM Recording support and my modifications


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10789 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/codecs.c b/apps/codecs.c
index c0b4aad..addb8b5 100644
--- a/apps/codecs.c
+++ b/apps/codecs.c
@@ -40,6 +40,7 @@
 #include "mpeg.h"
 #include "buffer.h"
 #include "mp3_playback.h"
+#include "playback.h"
 #include "backlight.h"
 #include "ata.h"
 #include "talk.h"
@@ -208,11 +209,28 @@
     profile_func_exit,
 #endif
 
+#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
+    false,
+    enc_get_inputs,
+    enc_set_parameters,
+    enc_alloc_chunk,
+    enc_free_chunk,
+    enc_wavbuf_near_empty,
+    enc_get_wav_data,
+    &enc_set_header_callback,
+#endif
+
     /* new stuff at the end, sort into place next time
        the API gets incompatible */
 
 };
 
+void codec_get_full_path(char *path, const char *codec_fn)
+{
+    /* Create full codec path */
+    snprintf(path, MAX_PATH-1, ROCKBOX_DIR CODECS_DIR "/%s", codec_fn);
+}
+
 int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap,
                    struct codec_api *api)
 {
@@ -277,15 +295,18 @@
 int codec_load_file(const char *plugin, struct codec_api *api)
 {
     char msgbuf[80];
+    char path[MAX_PATH];
     int fd;
     int rc;
+
+    codec_get_full_path(path, plugin);
     
     /* zero out codec buffer to ensure a properly zeroed bss area */
     memset(codecbuf, 0, CODEC_SIZE);
 
-    fd = open(plugin, O_RDONLY);
+    fd = open(path, O_RDONLY);
     if (fd < 0) {
-        snprintf(msgbuf, sizeof(msgbuf)-1, "Couldn't load codec: %s", plugin);
+        snprintf(msgbuf, sizeof(msgbuf)-1, "Couldn't load codec: %s", path);
         logf("Codec load error:%d", fd);
         gui_syncsplash(HZ*2, true, msgbuf);
         return fd;
diff --git a/apps/codecs.h b/apps/codecs.h
index 9ef67c4..dde376d 100644
--- a/apps/codecs.h
+++ b/apps/codecs.h
@@ -46,6 +46,9 @@
 #include "profile.h"
 #endif
 #if (CONFIG_CODEC == SWCODEC)
+#if !defined(SIMULATOR)
+#include "pcm_record.h"
+#endif
 #include "dsp.h"
 #include "playback.h"
 #endif
@@ -84,7 +87,7 @@
 #define CODEC_MAGIC 0x52434F44 /* RCOD */
 
 /* increase this every time the api struct changes */
-#define CODEC_API_VERSION 8
+#define CODEC_API_VERSION 9
 
 /* update this to latest version if a change to the api struct breaks
    backwards compatibility (and please take the opportunity to sort in any
@@ -284,6 +287,21 @@
     void (*profile_func_enter)(void *this_fn, void *call_site);
     void (*profile_func_exit)(void *this_fn, void *call_site);
 #endif
+ 
+#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
+    bool          enc_codec_loaded;
+    void          (*enc_get_inputs)(int *buffer_size,
+                        int *channels, int *quality);
+    void          (*enc_set_parameters)(int chunk_size, int num_chunks,
+                    int samp_per_chunk, char *head_ptr, int head_size,
+                    int enc_id);
+    unsigned int* (*enc_alloc_chunk)(void);
+    void          (*enc_free_chunk)(void);
+    int           (*enc_wavbuf_near_empty)(void);
+    char*         (*enc_get_wav_data)(int size);
+    void          (**enc_set_header_callback)(void *head_buffer,
+                    int head_size, int num_samples, bool is_file_header);
+#endif
 
     /* new stuff at the end, sort into place next time
        the API gets incompatible */     
@@ -317,6 +335,10 @@
 #endif
 #endif
 
+/* create full codec path from filenames in audio_formats[]
+   assumes buffer size is MAX_PATH */
+void codec_get_full_path(char *path, const char *codec_fn);
+
 /* defined by the codec loader (codec.c) */
 int codec_load_ram(char* codecptr, int size, void* ptr2, int bufwrap,
                    struct codec_api *api);
diff --git a/apps/codecs/Makefile b/apps/codecs/Makefile
index e365698..6e4663b 100644
--- a/apps/codecs/Makefile
+++ b/apps/codecs/Makefile
@@ -58,6 +58,9 @@
 $(OBJDIR)/alac.elf : $(OBJDIR)/alac.o $(BUILDDIR)/libalac.a $(BUILDDIR)/libm4a.a
 $(OBJDIR)/aac.elf : $(OBJDIR)/aac.o $(BUILDDIR)/libfaad.a $(BUILDDIR)/libm4a.a
 $(OBJDIR)/shorten.elf : $(OBJDIR)/shorten.o $(BUILDDIR)/libffmpegFLAC.a
+$(OBJDIR)/mp3_enc.elf: $(OBJDIR)/mp3_enc.o
+$(OBJDIR)/wav_enc.elf: $(OBJDIR)/wav_enc.o
+$(OBJDIR)/wavpack_enc.elf: $(OBJDIR)/wavpack_enc.o $(BUILDDIR)/libwavpack.a
 
 $(OBJDIR)/%.elf :
 	@echo "LD $(notdir $@)"
diff --git a/apps/codecs/SOURCES b/apps/codecs/SOURCES
index 3537457..3bd09b4 100644
--- a/apps/codecs/SOURCES
+++ b/apps/codecs/SOURCES
@@ -1,4 +1,5 @@
 #if CONFIG_CODEC == SWCODEC
+/* decoders */
 vorbis.c
 mpa.c
 flac.c
@@ -13,4 +14,11 @@
 shorten.c
 aiff.c
 sid.c
+#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
+/* encoders */
+mp3_enc.c
+wav_enc.c
+wavpack_enc.c
 #endif
+#endif
+
diff --git a/apps/codecs/mp3_enc.c b/apps/codecs/mp3_enc.c
new file mode 100644
index 0000000..1cd8498
--- /dev/null
+++ b/apps/codecs/mp3_enc.c
@@ -0,0 +1,2860 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Antonius Hellmann
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * 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 "codeclib.h"
+
+#ifndef SIMULATOR
+
+CODEC_HEADER
+
+#define SAMP_PER_FRAME   1152
+#define SAMP_PER_FRAME2   576
+#define HAN_SIZE          512
+#define SBLIMIT            32
+#define WAVE_RIFF_PCM       0
+#define MAX_CHANNELS        2
+#define MAX_GRANULES        2
+#define HTN                34
+
+typedef unsigned  long uint32;
+typedef unsigned short uint16;
+typedef unsigned  char  uint8;
+
+enum e_byte_order { order_unknown, order_bigEndian, order_littleEndian };
+
+#define memcpy      ci->memcpy
+#define memset      ci->memset
+
+typedef struct {
+    int  type; /* 0=(22.05,24,16kHz) 1=(44.1,48,32kHz) */
+    int  mode; /* 0=stereo, 1=jstereo, 2=dual, 3=mono  */
+    int  bitrate;
+    int  padding;
+    long bits_per_frame;
+    long bitrate_index;
+    int  smprate_index;
+} mpeg_t;
+
+/* Side information */
+typedef struct {
+    unsigned part2_3_length;
+    unsigned big_values;
+    int      count1;
+    unsigned global_gain;
+    unsigned table_select[4];
+    unsigned region0_count;
+    unsigned region1_count;
+    unsigned address1;
+    unsigned address2;
+    unsigned address3;
+    long     quantizerStepSize;
+} side_info_t;
+
+typedef struct {
+    enum e_byte_order byte_order;
+    side_info_t       cod_info[2][2];
+    long              frac_per_frame;
+    long              byte_per_frame;
+    long              slot_lag;
+    int               sideinfo_len;
+    int               mean_bits;
+    int               channels;
+    long              samplerate;
+    mpeg_t            mpg;
+} config_t;
+
+typedef struct {
+    int     bitpos;   /* current bitpos for writing */
+    uint32  bbuf[263];
+} BF_Data;
+
+struct huffcodetab {
+  int          xlen;    /*max. x-index+                */
+  int          ylen;    /*max. y-index+                */
+  int          linbits; /*number of linbits            */
+  int          linmax;  /*max number stored in linbits */
+  const uint16 *table;  /*pointer to array[xlen][ylen] */
+  const uint8  *hlen;   /*pointer to array[xlen][ylen] */
+};
+
+/* !!!!!!!! start of IRAM area: do not insert before x_int1 array !!!!!!!!! */
+short     x_int0      [HAN_SIZE]              IBSS_ATTR; //  1024 Bytes
+int       mdct_freq   [2][2][SAMP_PER_FRAME2] IBSS_ATTR; //  9216 Bytes
+short     x_int1      [HAN_SIZE]              IBSS_ATTR; //  1024 Bytes
+/* !!!!!!!!!!!!!!!!!! here you may insert other data !!!!!!!!!!!!!!!!!!!!!! */
+uint8     int2idx     [5000]                  IBSS_ATTR; //  5000 Bytes
+uint16    enc_data    [2][2][SAMP_PER_FRAME2] IBSS_ATTR; //  4608 Bytes
+short     y_int       [64]                    IBSS_ATTR; //   256 Bytes
+int       scalefac    [23]                    IBSS_ATTR; //    92 Bytes
+int       mdct_in     [36]                    IBSS_ATTR; //   144 Bytes
+int       sb_sample   [2][3][18][SBLIMIT]     IBSS_ATTR; // 13824 Bytes
+BF_Data   CodedData                           IBSS_ATTR; //  1040 Bytes
+int       ca_int      [8]                     IBSS_ATTR; //    32 Bytes
+int       cs_int      [8]                     IBSS_ATTR; //    32 Bytes
+int       win_int     [18][36]                IBSS_ATTR; //  2592 Bytes
+short     filter_int  [SBLIMIT][64]           IBSS_ATTR; //  8192 Bytes
+short     enwindow_int[512]                   IBSS_ATTR; //  1024 Bytes
+uint8     ht_count1   [2][2][16]              IBSS_ATTR; //    64 Bytes
+uint16    t1HB        [  4]                   IBSS_ATTR; //   Bytes
+uint16    t2HB        [  9]                   IBSS_ATTR; //   Bytes
+uint16    t3HB        [  9]                   IBSS_ATTR; //   Bytes
+uint16    t5HB        [ 16]                   IBSS_ATTR; //   Bytes
+uint16    t6HB        [ 16]                   IBSS_ATTR; //   Bytes
+uint16    t7HB        [ 36]                   IBSS_ATTR; //   Bytes
+uint16    t8HB        [ 36]                   IBSS_ATTR; //   Bytes
+uint16    t9HB        [ 36]                   IBSS_ATTR; //   Bytes
+uint16    t10HB       [ 64]                   IBSS_ATTR; //   Bytes
+uint16    t11HB       [ 64]                   IBSS_ATTR; //   Bytes
+uint16    t12HB       [ 64]                   IBSS_ATTR; //   Bytes
+uint16    t13HB       [256]                   IBSS_ATTR; //   Bytes
+uint16    t15HB       [256]                   IBSS_ATTR; //   Bytes
+uint16    t16HB       [256]                   IBSS_ATTR; //   Bytes
+uint16    t24HB       [256]                   IBSS_ATTR; //   Bytes
+uint8     t1l         [  4]                   IBSS_ATTR; //   Bytes
+uint8     t2l         [  9]                   IBSS_ATTR; //   Bytes
+uint8     t3l         [  9]                   IBSS_ATTR; //   Bytes
+uint8     t5l         [ 16]                   IBSS_ATTR; //   Bytes
+uint8     t6l         [ 16]                   IBSS_ATTR; //   Bytes
+uint8     t7l         [ 36]                   IBSS_ATTR; //   Bytes
+uint8     t8l         [ 36]                   IBSS_ATTR; //   Bytes
+uint8     t9l         [ 36]                   IBSS_ATTR; //   Bytes
+uint8     t10l        [ 64]                   IBSS_ATTR; //   Bytes
+uint8     t11l        [ 64]                   IBSS_ATTR; //   Bytes
+uint8     t12l        [ 64]                   IBSS_ATTR; //   Bytes
+uint8     t13l        [256]                   IBSS_ATTR; //   Bytes
+uint8     t15l        [256]                   IBSS_ATTR; //   Bytes
+uint8     t16l        [256]                   IBSS_ATTR; //   Bytes
+uint8     t24l        [256]                   IBSS_ATTR; //   Bytes
+struct huffcodetab ht [HTN]                   IBSS_ATTR; //   Bytes
+
+static struct codec_api *ci;
+static    int  enc_channels;
+static short      *x_int[2];
+static config_t         cfg;
+
+static const uint8 ht_count1_const[2][2][16] =
+{ { { 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 uint16  t1HB_const[4]   = {1,1,1,0}; 
+static const uint16  t2HB_const[9]   = {1,2,1,3,1,1,3,2,0};
+static const uint16  t3HB_const[9]   = {3,2,1,1,1,1,3,2,0};
+static const uint16  t5HB_const[16]  = {1,2,6,5,3,1,4,4,7,5,7,1,6,1,1,0};
+static const uint16  t6HB_const[16]  = {7,3,5,1,6,2,3,2,5,4,4,1,3,3,2,0};
+static const uint16  t7HB_const[36]  = {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 uint16  t8HB_const[36]  = {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 uint16  t9HB_const[36]  = {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 uint16 t10HB_const[64]  = {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 uint16 t11HB_const[64]  = {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 uint16 t12HB_const[64]  = {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 uint16 t13HB_const[256] = {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 uint16 t15HB_const[256] = {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 t16HB_const[256] = {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 t24HB_const[256] = {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 uint8 t1l_const[4]    = {1,3,2,3};
+static const uint8 t2l_const[9]    = {1,3,6,3,3,5,5,5,6};
+static const uint8 t3l_const[9]    = {2,2,6,3,2,5,5,5,6};
+static const uint8 t5l_const[16]   = {1,3,6,7,3,3,6,7,6,6,7,8,7,6,7,8};
+static const uint8 t6l_const[16]   = {3,3,5,7,3,2,4,5,4,4,5,6,6,5,6,7};
+static const uint8 t7l_const[36]   = {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 t8l_const[36]   = {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 t9l_const[36]   = {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 t10l_const[64]  = {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 t11l_const[64]  = {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 t12l_const[64]  = {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 t13l_const[256] = {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 t15l_const[256] = {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 t16l_const[256] = {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 t24l_const[256] = {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_const[HTN] =
+{
+{ 0, 0, 0,   0, NULL, NULL},
+{ 2, 2, 0,   0, t1HB,  t1l},
+{ 3, 3, 0,   0, t2HB,  t2l},
+{ 3, 3, 0,   0, t3HB,  t3l},
+{ 0, 0, 0,   0, NULL, NULL},// Apparently not used
+{ 4, 4, 0,   0, t5HB,  t5l},
+{ 4, 4, 0,   0, t6HB,  t6l},
+{ 6, 6, 0,   0, t7HB,  t7l},
+{ 6, 6, 0,   0, t8HB,  t8l},
+{ 6, 6, 0,   0, t9HB,  t9l},
+{ 8, 8, 0,   0,t10HB, t10l},
+{ 8, 8, 0,   0,t11HB, t11l},
+{ 8, 8, 0,   0,t12HB, t12l},
+{16,16, 0,   0,t13HB, t13l},
+{ 0, 0, 0,   0, NULL, NULL},// Apparently not used
+{16,16, 0,   0,t15HB, t15l},
+{16,16, 1,   1,t16HB, t16l},
+{16,16, 2,   3,t16HB, t16l},
+{16,16, 3,   7,t16HB, t16l},
+{16,16, 4,  15,t16HB, t16l},
+{16,16, 6,  63,t16HB, t16l},
+{16,16, 8, 255,t16HB, t16l},
+{16,16,10,1023,t16HB, t16l},
+{16,16,13,8191,t16HB, t16l},
+{16,16, 4,  15,t24HB, t24l},
+{16,16, 5,  31,t24HB, t24l},
+{16,16, 6,  63,t24HB, t24l},
+{16,16, 7, 127,t24HB, t24l},
+{16,16, 8, 255,t24HB, t24l},
+{16,16, 9, 511,t24HB, t24l},
+{16,16,11,2047,t24HB, t24l},
+{16,16,13,8191,t24HB, t24l} };
+
+static const struct
+{
+  unsigned region0_count;
+  unsigned region1_count;
+} subdv_table[23] =
+{ {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 */
+};
+
+/* This is table B.9: coefficients for aliasing reduction */
+static const int ca_int_const[8]  = {0xffffbe25,0xffffc39e,0xffffd7e3,0xffffe8b7,0xfffff3e5,0xfffffac2,0xfffffe2f,0xffffff87};
+static const int cs_int_const[8]  = {0x00006dc2,0x000070dd,0x0000798d,0x00007ddd,0x00007f6d,0x00007fe4,0x00007ffd,0x00008000};
+static const int win_int_const[18][36] = {
+{ 0x0000006b,0x00000121,0x000001a7,0x000001f9,0x00000215,0x000001f9,0x000001a7,0x00000121,0x0000006b,0xffffff8b,0xfffffe87,0xfffffd68,0xfffffc35,0xfffffaf9,0xfffff9bd,0xfffff88b,0xfffff76b,0xfffff667,0xfffff587,0xfffff4d1,0xfffff44b,0xfffff3f8,0xfffff3dd,0xfffff3f8,0xfffff44b,0xfffff4d1,0xfffff587,0xfffff667,0xfffff76b,0xfffff88b,0xfffff9bd,0xfffffaf9,0xfffffc35,0xfffffd68,0xfffffe87,0xffffff8b,},
+{ 0xffffff83,0xfffffe49,0xfffffcf3,0xfffffbc3,0xfffffaf9,0xfffffacb,0xfffffb5a,0xfffffcb0,0xfffffebf,0x0000015e,0x00000451,0x0000074d,0x00000a02,0x00000c23,0x00000d72,0x00000dc4,0x00000d06,0x00000b45,0x000008a6,0x00000565,0x000001cf,0xfffffe3b,0xfffffaf9,0xfffff853,0xfffff67c,0xfffff594,0xfffff59b,0xfffff67a,0xfffff801,0xfffff9f1,0xfffffc01,0xfffffdeb,0xffffff72,0x00000066,0x000000b5,0x00000060,},
+{ 0xffffffab,0xffffffc2,0x000000ec,0x000002e3,0x00000507,0x0000068f,0x000006c7,0x00000545,0x00000214,0xfffffdbc,0xfffff922,0xfffff55d,0xfffff366,0xfffff3dd,0xfffff6d7,0xfffffbd4,0x000001d7,0x000007a2,0x00000bfb,0x00000dfa,0x00000d3e,0x00000a00,0x00000507,0xffffff74,0xfffffa77,0xfffff70d,0xfffff5c4,0xfffff69f,0xfffff922,0xfffffc79,0xffffffb7,0x00000215,0x00000327,0x000002ef,0x000001d7,0x00000085,},
+{ 0x0000008c,0x000001d7,0x00000244,0x000000ec,0xfffffdeb,0xfffffa77,0xfffff85e,0xfffff922,0xfffffd1d,0x00000327,0x000008f3,0x00000bfb,0x00000aa3,0x00000507,0xfffffd11,0xfffff5c4,0xfffff206,0xfffff366,0xfffff971,0x000001d7,0x00000961,0x00000d3e,0x00000c23,0x000006c7,0xffffff7b,0xfffff922,0xfffff600,0xfffff6d7,0xfffffabb,0xffffffab,0x00000387,0x00000507,0x0000042c,0x00000214,0x0000003e,0xffffffb7,},
+{ 0x0000003c,0xffffff4b,0xfffffd28,0xfffffc0d,0xfffffdeb,0x00000283,0x0000070f,0x000007ff,0x000003ad,0xfffffbfd,0xfffff594,0xfffff4ec,0xfffffb2d,0x00000507,0x00000c88,0x00000cd4,0x00000565,0xfffffa91,0xfffff2e0,0xfffff2fa,0xfffffab0,0x00000530,0x00000c23,0x00000ba7,0x00000497,0xfffffbaf,0xfffff650,0xfffff720,0xfffffcb0,0x000002ec,0x00000611,0x00000507,0x000001a2,0xfffffed3,0xfffffe49,0xffffff6e,},
+{ 0xffffff69,0xfffffe87,0x00000022,0x0000039b,0x00000507,0x0000016b,0xfffffad7,0xfffff76b,0xfffffb91,0x000004d7,0x00000b2f,0x0000081a,0xfffffd46,0xfffff3dd,0xfffff490,0xffffff65,0x00000b2f,0x00000d8d,0x00000445,0xfffff76b,0xfffff221,0xfffff8b7,0x00000507,0x00000c50,0x000008d7,0xfffffe87,0xfffff6b3,0xfffff77b,0xfffffedf,0x000005a2,0x00000669,0x00000215,0xfffffdb4,0xfffffced,0xfffffedf,0x0000002f,},
+{ 0xffffffde,0x00000179,0x000002ba,0xffffffd1,0xfffffaf9,0xfffffb29,0x0000024c,0x00000895,0x00000529,0xfffffa5e,0xfffff4d1,0xfffffc65,0x0000094d,0x00000c23,0x00000097,0xfffff3b0,0xfffff4d1,0x00000313,0x00000ddf,0x00000895,0xfffff997,0xfffff273,0xfffffaf9,0x00000885,0x00000b70,0x00000179,0xfffff729,0xfffff7e6,0x00000121,0x00000749,0x0000046f,0xfffffdeb,0xfffffbbb,0xfffffe95,0x00000121,0x0000009b,},
+{ 0x0000009d,0x000000b5,0xfffffd8f,0xfffffc9c,0x00000215,0x00000682,0x000000ff,0xfffff801,0xfffffa27,0x00000662,0x00000a6c,0xfffffe70,0xfffff37f,0xfffffaf9,0x00000ac2,0x00000b04,0xfffffa9b,0xfffff1ea,0xfffffe26,0x00000d06,0x00000873,0xfffff7bf,0xfffff3dd,0x000001a5,0x00000be4,0x00000451,0xfffff7af,0xfffff861,0x00000350,0x00000793,0x000000db,0xfffffaf9,0xfffffd66,0x000001df,0x000001b7,0xffffffec,},
+{ 0x00000006,0xfffffe29,0xffffff56,0x00000414,0x00000215,0xfffffa2d,0xfffffbe5,0x000006de,0x0000067d,0xfffff8eb,0xfffff70d,0x00000671,0x00000b30,0xfffffaf9,0xfffff311,0x00000301,0x00000dfa,0xffffff62,0xfffff1cf,0xfffffe29,0x00000d8e,0x00000414,0xfffff3dd,0xfffffa2d,0x00000a1d,0x000006de,0xfffff845,0xfffff8eb,0x00000545,0x00000671,0xfffffcf8,0xfffffaf9,0x00000149,0x00000301,0xffffffc2,0xffffff62,},
+{ 0xffffff62,0x0000003e,0x00000301,0xfffffeb7,0xfffffaf9,0x00000308,0x00000671,0xfffffabb,0xfffff8eb,0x000007bb,0x000006de,0xfffff5e3,0xfffffa2d,0x00000c23,0x00000414,0xfffff272,0xfffffe29,0x00000e31,0xffffff62,0xfffff206,0x00000301,0x00000cef,0xfffffaf9,0xfffff4d0,0x00000671,0x000008f3,0xfffff8eb,0xfffff983,0x000006de,0x0000041b,0xfffffa2d,0xfffffdeb,0x00000414,0x000000aa,0xfffffe29,0xfffffffa,},
+{ 0x00000014,0x000001b7,0xfffffe21,0xfffffd66,0x00000507,0x000000db,0xfffff86d,0x00000350,0x0000079f,0xfffff7af,0xfffffbaf,0x00000be4,0xfffffe5b,0xfffff3dd,0x00000841,0x00000873,0xfffff2fa,0xfffffe26,0x00000e16,0xfffffa9b,0xfffff4fc,0x00000ac2,0x00000507,0xfffff37f,0x00000190,0x00000a6c,0xfffff99e,0xfffffa27,0x000007ff,0x000000ff,0xfffff97e,0x00000215,0x00000364,0xfffffd8f,0xffffff4b,0x0000009d,},
+{ 0x0000009b,0xfffffedf,0xfffffe95,0x00000445,0xfffffdeb,0xfffffb91,0x00000749,0xfffffedf,0xfffff7e6,0x000008d7,0x00000179,0xfffff490,0x00000885,0x00000507,0xfffff273,0x00000669,0x00000895,0xfffff221,0x00000313,0x00000b2f,0xfffff3b0,0xffffff69,0x00000c23,0xfffff6b3,0xfffffc65,0x00000b2f,0xfffffa5e,0xfffffad7,0x00000895,0xfffffdb4,0xfffffb29,0x00000507,0xffffffd1,0xfffffd46,0x00000179,0x00000022,},
+{ 0xffffffd1,0xfffffedf,0x00000313,0xfffffdb4,0xfffffdeb,0x00000669,0xfffffa5e,0xfffffedf,0x00000885,0xfffff6b3,0x00000179,0x000008d7,0xfffff3b0,0x00000507,0x00000749,0xfffff221,0x00000895,0x00000445,0xfffff273,0x00000b2f,0x0000009b,0xfffff490,0x00000c23,0xfffffd46,0xfffff7e6,0x00000b2f,0xfffffb29,0xfffffb91,0x00000895,0xfffffad7,0xfffffe95,0x00000507,0xfffffc65,0x00000022,0x00000179,0xffffff69,},
+{ 0xffffff6e,0x000001b7,0xfffffed3,0xfffffe5e,0x00000507,0xfffff9ef,0x000002ec,0x00000350,0xfffff720,0x000009b0,0xfffffbaf,0xfffffb69,0x00000ba7,0xfffff3dd,0x00000530,0x00000550,0xfffff2fa,0x00000d20,0xfffffa91,0xfffffa9b,0x00000cd4,0xfffff378,0x00000507,0x000004d3,0xfffff4ec,0x00000a6c,0xfffffbfd,0xfffffc53,0x000007ff,0xfffff8f1,0x00000283,0x00000215,0xfffffc0d,0x000002d8,0xffffff4b,0xffffffc4,},
+{ 0x00000049,0x0000003e,0xfffffdec,0x0000042c,0xfffffaf9,0x00000387,0x00000055,0xfffffabb,0x00000929,0xfffff600,0x000006de,0xffffff7b,0xfffff939,0x00000c23,0xfffff2c2,0x00000961,0xfffffe29,0xfffff971,0x00000c9a,0xfffff206,0x00000a3c,0xfffffd11,0xfffffaf9,0x00000aa3,0xfffff405,0x000008f3,0xfffffcd9,0xfffffd1d,0x000006de,0xfffff85e,0x00000589,0xfffffdeb,0xffffff14,0x00000244,0xfffffe29,0x0000008c,},
+{ 0x00000085,0xfffffe29,0x000002ef,0xfffffcd9,0x00000215,0x00000049,0xfffffc79,0x000006de,0xfffff69f,0x00000a3c,0xfffff70d,0x00000589,0xffffff74,0xfffffaf9,0x00000a00,0xfffff2c2,0x00000dfa,0xfffff405,0x000007a2,0xfffffe29,0xfffffbd4,0x00000929,0xfffff3dd,0x00000c9a,0xfffff55d,0x000006de,0xfffffdbc,0xfffffdec,0x00000545,0xfffff939,0x0000068f,0xfffffaf9,0x000002e3,0xffffff14,0xffffffc2,0x00000055,},
+{ 0xffffffa0,0x000000b5,0xffffff9a,0xffffff72,0x00000215,0xfffffc01,0x0000060f,0xfffff801,0x00000986,0xfffff59b,0x00000a6c,0xfffff67c,0x000007ad,0xfffffaf9,0x000001c5,0x000001cf,0xfffffa9b,0x000008a6,0xfffff4bb,0x00000d06,0xfffff23c,0x00000d72,0xfffff3dd,0x00000a02,0xfffff8b3,0x00000451,0xfffffea2,0xfffffebf,0x00000350,0xfffffb5a,0x00000535,0xfffffaf9,0x0000043d,0xfffffcf3,0x000001b7,0xffffff83,},
+{ 0xffffff8b,0x00000179,0xfffffd68,0x000003cb,0xfffffaf9,0x00000643,0xfffff88b,0x00000895,0xfffff667,0x00000a79,0xfffff4d1,0x00000bb5,0xfffff3f8,0x00000c23,0xfffff3f8,0x00000bb5,0xfffff4d1,0x00000a79,0xfffff667,0x00000895,0xfffff88b,0x00000643,0xfffffaf9,0x000003cb,0xfffffd68,0x00000179,0xffffff8b,0xffffff95,0x00000121,0xfffffe59,0x000001f9,0xfffffdeb,0x000001f9,0xfffffe59,0x00000121,0xffffff95,}};
+
+static const short filter_int_const[SBLIMIT][64] = {
+{  23170, 24279, 25330, 26320, 27246, 28106, 28899, 29622, 30274, 30853, 31357, 31786, 32138, 32413, 32610, 32729, 32767, 32729, 32610, 32413, 32138, 31786, 31357, 30853, 30274, 29622, 28899, 28106, 27246, 26320, 25330, 24279, 23170, 22006, 20788, 19520, 18205, 16846, 15447, 14010, 12540, 11039,  9512,  7962,  6393,  4808,  3212,  1608,     0, -1607, -3211, -4807, -6392, -7961, -9511,-11038,-12539,-14009,-15446,-16845,-18204,-19519,-20787,-22005, },
+{ -23169,-19519,-15446,-11038, -6392, -1607,  3212,  7962, 12540, 16846, 20788, 24279, 27246, 29622, 31357, 32413, 32767, 32413, 31357, 29622, 27246, 24279, 20788, 16846, 12540,  7962,  3212, -1607, -6392,-11038,-15446,-19519,-23169,-26319,-28898,-30852,-32137,-32728,-32609,-31785,-30273,-28105,-25329,-22005,-18204,-14009, -9511, -4807,     0,  4808,  9512, 14010, 18205, 22006, 25330, 28106, 30274, 31786, 32610, 32729, 32138, 30853, 28899, 26320, },
+{ -23169,-28105,-31356,-32728,-32137,-29621,-25329,-19519,-12539, -4807,  3212, 11039, 18205, 24279, 28899, 31786, 32767, 31786, 28899, 24279, 18205, 11039,  3212, -4807,-12539,-19519,-25329,-29621,-32137,-32728,-31356,-28105,-23169,-16845, -9511, -1607,  6393, 14010, 20788, 26320, 30274, 32413, 32610, 30853, 27246, 22006, 15447,  7962,     0, -7961,-15446,-22005,-27245,-30852,-32609,-32412,-30273,-26319,-20787,-14009, -6392,  1608,  9512, 16846, },
+{  23170, 14010,  3212, -7961,-18204,-26319,-31356,-32728,-30273,-24278,-15446, -4807,  6393, 16846, 25330, 30853, 32767, 30853, 25330, 16846,  6393, -4807,-15446,-24278,-30273,-32728,-31356,-26319,-18204, -7961,  3212, 14010, 23170, 29622, 32610, 31786, 27246, 19520,  9512, -1607,-12539,-22005,-28898,-32412,-32137,-28105,-20787,-11038,     0, 11039, 20788, 28106, 32138, 32413, 28899, 22006, 12540,  1608, -9511,-19519,-27245,-31785,-32609,-29621, },
+{  23170, 30853, 32610, 28106, 18205,  4808, -9511,-22005,-30273,-32728,-28898,-19519, -6392,  7962, 20788, 29622, 32767, 29622, 20788,  7962, -6392,-19519,-28898,-32728,-30273,-22005, -9511,  4808, 18205, 28106, 32610, 30853, 23170, 11039, -3211,-16845,-27245,-32412,-31356,-24278,-12539,  1608, 15447, 26320, 32138, 31786, 25330, 14010,     0,-14009,-25329,-31785,-32137,-26319,-15446, -1607, 12540, 24279, 31357, 32413, 27246, 16846,  3212,-11038, },
+{ -23169, -7961,  9512, 24279, 32138, 30853, 20788,  4808,-12539,-26319,-32609,-29621,-18204, -1607, 15447, 28106, 32767, 28106, 15447, -1607,-18204,-29621,-32609,-26319,-12539,  4808, 20788, 30853, 32138, 24279,  9512, -7961,-23169,-31785,-31356,-22005, -6392, 11039, 25330, 32413, 30274, 19520,  3212,-14009,-27245,-32728,-28898,-16845,     0, 16846, 28899, 32729, 27246, 14010, -3211,-19519,-30273,-32412,-25329,-11038,  6393, 22006, 31357, 31786, },
+{ -23169,-32412,-28898,-14009,  6393, 24279, 32610, 28106, 12540, -7961,-25329,-32728,-27245,-11038,  9512, 26320, 32767, 26320,  9512,-11038,-27245,-32728,-25329, -7961, 12540, 28106, 32610, 24279,  6393,-14009,-28898,-32412,-23169, -4807, 15447, 29622, 32138, 22006,  3212,-16845,-30273,-31785,-20787, -1607, 18205, 30853, 31357, 19520,     0,-19519,-31356,-30852,-18204,  1608, 20788, 31786, 30274, 16846, -3211,-22005,-32137,-29621,-15446,  4808, },
+{  23170,  1608,-20787,-32412,-27245, -7961, 15447, 30853, 30274, 14010, -9511,-28105,-32137,-19519,  3212, 24279, 32767, 24279,  3212,-19519,-32137,-28105, -9511, 14010, 30274, 30853, 15447, -7961,-27245,-32412,-20787,  1608, 23170, 32729, 25330,  4808,-18204,-31785,-28898,-11038, 12540, 29622, 31357, 16846, -6392,-26319,-32609,-22005,     0, 22006, 32610, 26320,  6393,-16845,-31356,-29621,-12539, 11039, 28899, 31786, 18205, -4807,-25329,-32728, },
+{  23170, 32729, 20788, -4807,-27245,-31785,-15446, 11039, 30274, 29622,  9512,-16845,-32137,-26319, -3211, 22006, 32767, 22006, -3211,-26319,-32137,-16845,  9512, 29622, 30274, 11039,-15446,-31785,-27245, -4807, 20788, 32729, 23170, -1607,-25329,-32412,-18204,  7962, 28899, 30853, 12540,-14009,-31356,-28105, -6392, 19520, 32610, 24279,     0,-24278,-32609,-19519,  6393, 28106, 31357, 14010,-12539,-30852,-28898, -7961, 18205, 32413, 25330,  1608, },
+{ -23169,  4808, 28899, 29622,  6393,-22005,-32609,-16845, 12540, 31786, 25330, -1607,-27245,-30852, -9511, 19520, 32767, 19520, -9511,-30852,-27245, -1607, 25330, 31786, 12540,-16845,-32609,-22005,  6393, 29622, 28899,  4808,-23169,-32412,-15446, 14010, 32138, 24279, -3211,-28105,-30273, -7961, 20788, 32729, 18205,-11038,-31356,-26319,     0, 26320, 31357, 11039,-18204,-32728,-20787,  7962, 30274, 28106,  3212,-24278,-32137,-14009, 15447, 32413, },
+{ -23169,-31785, -9511, 22006, 32138, 11039,-20787,-32412,-12539, 19520, 32610, 14010,-18204,-32728,-15446, 16846, 32767, 16846,-15446,-32728,-18204, 14010, 32610, 19520,-12539,-32412,-20787, 11039, 32138, 22006, -9511,-31785,-23169,  7962, 31357, 24279, -6392,-30852,-25329,  4808, 30274, 26320, -3211,-29621,-27245,  1608, 28899, 28106,     0,-28105,-28898, -1607, 27246, 29622,  3212,-26319,-30273, -4807, 25330, 30853,  6393,-24278,-31356, -7961, },
+{  23170,-11038,-32609,-16845, 18205, 32413,  9512,-24278,-30273, -1607, 28899, 26320, -6392,-31785,-20787, 14010, 32767, 14010,-20787,-31785, -6392, 26320, 28899, -1607,-30273,-24278,  9512, 32413, 18205,-16845,-32609,-11038, 23170, 30853,  3212,-28105,-27245,  4808, 31357, 22006,-12539,-32728,-15446, 19520, 32138,  7962,-25329,-29621,     0, 29622, 25330, -7961,-32137,-19519, 15447, 32729, 12540,-22005,-31356, -4807, 27246, 28106, -3211,-30852, },
+{  23170, 29622, -3211,-31785,-18204, 19520, 31357,  1608,-30273,-22005, 15447, 32413,  6393,-28105,-25329, 11039, 32767, 11039,-25329,-28105,  6393, 32413, 15447,-22005,-30273,  1608, 31357, 19520,-18204,-31785, -3211, 29622, 23170,-14009,-32609, -7961, 27246, 26320, -9511,-32728,-12539, 24279, 28899, -4807,-32137,-16845, 20788, 30853,     0,-30852,-20787, 16846, 32138,  4808,-28898,-24278, 12540, 32729,  9512,-26319,-27245,  7962, 32610, 14010, },
+{ -23169, 16846, 31357, -1607,-32137,-14009, 25330, 26320,-12539,-32412, -3211, 30853, 18205,-22005,-28898,  7962, 32767,  7962,-28898,-22005, 18205, 30853, -3211,-32412,-12539, 26320, 25330,-14009,-32137, -1607, 31357, 16846,-23169,-28105,  9512, 32729,  6393,-29621,-20787, 19520, 30274, -4807,-32609,-11038, 27246, 24279,-15446,-31785,     0, 31786, 15447,-24278,-27245, 11039, 32610,  4808,-30273,-19519, 20788, 29622, -6392,-32728, -9511, 28106, },
+{ -23169,-26319, 15447, 30853, -6392,-32728, -3211, 31786, 12540,-28105,-20787, 22006, 27246,-14009,-31356,  4808, 32767,  4808,-31356,-14009, 27246, 22006,-20787,-28105, 12540, 31786, -3211,-32728, -6392, 30853, 15447,-26319,-23169, 19520, 28899,-11038,-32137,  1608, 32610,  7962,-30273,-16845, 25330, 24279,-18204,-29621,  9512, 32413,     0,-32412, -9511, 29622, 18205,-24278,-25329, 16846, 30274, -7961,-32609, -1607, 32138, 11039,-28898,-19519, },
+{  23170,-22005,-25329, 19520, 27246,-16845,-28898, 14010, 30274,-11038,-31356,  7962, 32138, -4807,-32609,  1608, 32767,  1608,-32609, -4807, 32138,  7962,-31356,-11038, 30274, 14010,-28898,-16845, 27246, 19520,-25329,-22005, 23170, 24279,-20787,-26319, 18205, 28106,-15446,-29621, 12540, 30853, -9511,-31785,  6393, 32413, -3211,-32728,     0, 32729,  3212,-32412, -6392, 31786,  9512,-30852,-12539, 29622, 15447,-28105,-18204, 26320, 20788,-24278, },
+{  23170, 22006,-25329,-19519, 27246, 16846,-28898,-14009, 30274, 11039,-31356, -7961, 32138,  4808,-32609, -1607, 32767, -1607,-32609,  4808, 32138, -7961,-31356, 11039, 30274,-14009,-28898, 16846, 27246,-19519,-25329, 22006, 23170,-24278,-20787, 26320, 18205,-28105,-15446, 29622, 12540,-30852, -9511, 31786,  6393,-32412, -3211, 32729,     0,-32728,  3212, 32413, -6392,-31785,  9512, 30853,-12539,-29621, 15447, 28106,-18204,-26319, 20788, 24279, },
+{ -23169, 26320, 15447,-30852, -6392, 32729, -3211,-31785, 12540, 28106,-20787,-22005, 27246, 14010,-31356, -4807, 32767, -4807,-31356, 14010, 27246,-22005,-20787, 28106, 12540,-31785, -3211, 32729, -6392,-30852, 15447, 26320,-23169,-19519, 28899, 11039,-32137, -1607, 32610, -7961,-30273, 16846, 25330,-24278,-18204, 29622,  9512,-32412,     0, 32413, -9511,-29621, 18205, 24279,-25329,-16845, 30274,  7962,-32609,  1608, 32138,-11038,-28898, 19520, },
+{ -23169,-16845, 31357,  1608,-32137, 14010, 25330,-26319,-12539, 32413, -3211,-30852, 18205, 22006,-28898, -7961, 32767, -7961,-28898, 22006, 18205,-30852, -3211, 32413,-12539,-26319, 25330, 14010,-32137,  1608, 31357,-16845,-23169, 28106,  9512,-32728,  6393, 29622,-20787,-19519, 30274,  4808,-32609, 11039, 27246,-24278,-15446, 31786,     0,-31785, 15447, 24279,-27245,-11038, 32610, -4807,-30273, 19520, 20788,-29621, -6392, 32729, -9511,-28105, },
+{  23170,-29621, -3211, 31786,-18204,-19519, 31357, -1607,-30273, 22006, 15447,-32412,  6393, 28106,-25329,-11038, 32767,-11038,-25329, 28106,  6393,-32412, 15447, 22006,-30273, -1607, 31357,-19519,-18204, 31786, -3211,-29621, 23170, 14010,-32609,  7962, 27246,-26319, -9511, 32729,-12539,-24278, 28899,  4808,-32137, 16846, 20788,-30852,     0, 30853,-20787,-16845, 32138, -4807,-28898, 24279, 12540,-32728,  9512, 26320,-27245, -7961, 32610,-14009, },
+{  23170, 11039,-32609, 16846, 18205,-32412,  9512, 24279,-30273,  1608, 28899,-26319, -6392, 31786,-20787,-14009, 32767,-14009,-20787, 31786, -6392,-26319, 28899,  1608,-30273, 24279,  9512,-32412, 18205, 16846,-32609, 11039, 23170,-30852,  3212, 28106,-27245, -4807, 31357,-22005,-12539, 32729,-15446,-19519, 32138, -7961,-25329, 29622,     0,-29621, 25330,  7962,-32137, 19520, 15447,-32728, 12540, 22006,-31356,  4808, 27246,-28105, -3211, 30853, },
+{ -23169, 31786, -9511,-22005, 32138,-11038,-20787, 32413,-12539,-19519, 32610,-14009,-18204, 32729,-15446,-16845, 32767,-16845,-15446, 32729,-18204,-14009, 32610,-19519,-12539, 32413,-20787,-11038, 32138,-22005, -9511, 31786,-23169, -7961, 31357,-24278, -6392, 30853,-25329, -4807, 30274,-26319, -3211, 29622,-27245, -1607, 28899,-28105,     0, 28106,-28898,  1608, 27246,-29621,  3212, 26320,-30273,  4808, 25330,-30852,  6393, 24279,-31356,  7962, },
+{ -23169, -4807, 28899,-29621,  6393, 22006,-32609, 16846, 12540,-31785, 25330,  1608,-27245, 30853, -9511,-19519, 32767,-19519, -9511, 30853,-27245,  1608, 25330,-31785, 12540, 16846,-32609, 22006,  6393,-29621, 28899, -4807,-23169, 32413,-15446,-14009, 32138,-24278, -3211, 28106,-30273,  7962, 20788,-32728, 18205, 11039,-31356, 26320,     0,-26319, 31357,-11038,-18204, 32729,-20787, -7961, 30274,-28105,  3212, 24279,-32137, 14010, 15447,-32412, },
+{  23170,-32728, 20788,  4808,-27245, 31786,-15446,-11038, 30274,-29621,  9512, 16846,-32137, 26320, -3211,-22005, 32767,-22005, -3211, 26320,-32137, 16846,  9512,-29621, 30274,-11038,-15446, 31786,-27245,  4808, 20788,-32728, 23170,  1608,-25329, 32413,-18204, -7961, 28899,-30852, 12540, 14010,-31356, 28106, -6392,-19519, 32610,-24278,     0, 24279,-32609, 19520,  6393,-28105, 31357,-14009,-12539, 30853,-28898,  7962, 18205,-32412, 25330, -1607, },
+{  23170, -1607,-20787, 32413,-27245,  7962, 15447,-30852, 30274,-14009, -9511, 28106,-32137, 19520,  3212,-24278, 32767,-24278,  3212, 19520,-32137, 28106, -9511,-14009, 30274,-30852, 15447,  7962,-27245, 32413,-20787, -1607, 23170,-32728, 25330, -4807,-18204, 31786,-28898, 11039, 12540,-29621, 31357,-16845, -6392, 26320,-32609, 22006,     0,-22005, 32610,-26319,  6393, 16846,-31356, 29622,-12539,-11038, 28899,-31785, 18205,  4808,-25329, 32729, },
+{ -23169, 32413,-28898, 14010,  6393,-24278, 32610,-28105, 12540,  7962,-25329, 32729,-27245, 11039,  9512,-26319, 32767,-26319,  9512, 11039,-27245, 32729,-25329,  7962, 12540,-28105, 32610,-24278,  6393, 14010,-28898, 32413,-23169,  4808, 15447,-29621, 32138,-22005,  3212, 16846,-30273, 31786,-20787,  1608, 18205,-30852, 31357,-19519,     0, 19520,-31356, 30853,-18204, -1607, 20788,-31785, 30274,-16845, -3211, 22006,-32137, 29622,-15446, -4807, },
+{ -23169,  7962,  9512,-24278, 32138,-30852, 20788, -4807,-12539, 26320,-32609, 29622,-18204,  1608, 15447,-28105, 32767,-28105, 15447,  1608,-18204, 29622,-32609, 26320,-12539, -4807, 20788,-30852, 32138,-24278,  9512,  7962,-23169, 31786,-31356, 22006, -6392,-11038, 25330,-32412, 30274,-19519,  3212, 14010,-27245, 32729,-28898, 16846,     0,-16845, 28899,-32728, 27246,-14009, -3211, 19520,-30273, 32413,-25329, 11039,  6393,-22005, 31357,-31785, },
+{  23170,-30852, 32610,-28105, 18205, -4807, -9511, 22006,-30273, 32729,-28898, 19520, -6392, -7961, 20788,-29621, 32767,-29621, 20788, -7961, -6392, 19520,-28898, 32729,-30273, 22006, -9511, -4807, 18205,-28105, 32610,-30852, 23170,-11038, -3211, 16846,-27245, 32413,-31356, 24279,-12539, -1607, 15447,-26319, 32138,-31785, 25330,-14009,     0, 14010,-25329, 31786,-32137, 26320,-15446,  1608, 12540,-24278, 31357,-32412, 27246,-16845,  3212, 11039, },
+{  23170,-14009,  3212,  7962,-18204, 26320,-31356, 32729,-30273, 24279,-15446,  4808,  6393,-16845, 25330,-30852, 32767,-30852, 25330,-16845,  6393,  4808,-15446, 24279,-30273, 32729,-31356, 26320,-18204,  7962,  3212,-14009, 23170,-29621, 32610,-31785, 27246,-19519,  9512,  1608,-12539, 22006,-28898, 32413,-32137, 28106,-20787, 11039,     0,-11038, 20788,-28105, 32138,-32412, 28899,-22005, 12540, -1607, -9511, 19520,-27245, 31786,-32609, 29622, },
+{ -23169, 28106,-31356, 32729,-32137, 29622,-25329, 19520,-12539,  4808,  3212,-11038, 18205,-24278, 28899,-31785, 32767,-31785, 28899,-24278, 18205,-11038,  3212,  4808,-12539, 19520,-25329, 29622,-32137, 32729,-31356, 28106,-23169, 16846, -9511,  1608,  6393,-14009, 20788,-26319, 30274,-32412, 32610,-30852, 27246,-22005, 15447, -7961,     0,  7962,-15446, 22006,-27245, 30853,-32609, 32413,-30273, 26320,-20787, 14010, -6392, -1607,  9512,-16845, },
+{ -23169, 19520,-15446, 11039, -6392,  1608,  3212, -7961, 12540,-16845, 20788,-24278, 27246,-29621, 31357,-32412, 32767,-32412, 31357,-29621, 27246,-24278, 20788,-16845, 12540, -7961,  3212,  1608, -6392, 11039,-15446, 19520,-23169, 26320,-28898, 30853,-32137, 32729,-32609, 31786,-30273, 28106,-25329, 22006,-18204, 14010, -9511,  4808,     0, -4807,  9512,-14009, 18205,-22005, 25330,-28105, 30274,-31785, 32610,-32728, 32138,-30852, 28899,-26319, },
+{  23170,-24278, 25330,-26319, 27246,-28105, 28899,-29621, 30274,-30852, 31357,-31785, 32138,-32412, 32610,-32728, 32767,-32728, 32610,-32412, 32138,-31785, 31357,-30852, 30274,-29621, 28899,-28105, 27246,-26319, 25330,-24278, 23170,-22005, 20788,-19519, 18205,-16845, 15447,-14009, 12540,-11038,  9512, -7961,  6393, -4807,  3212, -1607,     0,  1608, -3211,  4808, -6392,  7962, -9511, 11039,-12539, 14010,-15446, 16846,-18204, 19520,-20787, 22006, } };
+
+static const int sfBand[6][23] =
+{
+/* Table B.2.b: 22.05 kHz */
+{0,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 */
+{0,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 */
+{0,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 */
+{0,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 */
+{0,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 */
+{0,4, 8,12,16,20,24,30,36,44,54,66, 82,102,126,156,194,240,296,364,448,550,576} };
+
+static const uint16 enwindow_int_const[512] = {
+0x0000,0x0035,0x01fd,0x066c,0x4948,0x066c,0x01fd,0x0035,0x0000,0x0037,0x01f4,0x05d2,0x493c,0x06f8,0x0204,0x0034,
+0x0000,0x0038,0x01e8,0x052a,0x491a,0x0776,0x0208,0x0032,0x0000,0x0038,0x01d9,0x0474,0x48e1,0x07e7,0x020a,0x0031,
+0x0000,0x0039,0x01c8,0x03b0,0x4892,0x084b,0x0209,0x0030,0x0000,0x0039,0x01b3,0x02de,0x482d,0x08a2,0x0207,0x002e,
+0x0000,0x0039,0x019b,0x01fd,0x47b2,0x08ed,0x0202,0x002c,0x0000,0x0039,0x0180,0x010f,0x4721,0x092b,0x01fc,0x002a,
+0x0000,0x0038,0x0161,0x0011,0x467a,0x095e,0x01f4,0x0028,0x0000,0x0037,0x0140,0xff07,0x45bf,0x0985,0x01eb,0x0026,
+0x0000,0x0036,0x011b,0xfdee,0x44f0,0x09a2,0x01e0,0x0025,0x0000,0x0034,0x00f3,0xfcc8,0x440c,0x09b4,0x01d4,0x0023,
+0x0000,0x0032,0x00c7,0xfb93,0x4315,0x09bb,0x01c6,0x0021,0x0000,0x002f,0x0097,0xfa53,0x420b,0x09ba,0x01b8,0x001f,
+0x0000,0x002c,0x0065,0xf905,0x40f0,0x09af,0x01a9,0x001d,0x0000,0x0029,0x002e,0xf7aa,0x3fc3,0x099b,0x0198,0x001c,
+0x0000,0x0025,0xfff6,0xf643,0x3e85,0x0980,0x0188,0x001a,0xffff,0x0020,0xffb9,0xf4d1,0x3d37,0x095c,0x0176,0x0018,
+0xffff,0x001b,0xff79,0xf354,0x3bda,0x0932,0x0165,0x0017,0xffff,0x0015,0xff36,0xf1cc,0x3a70,0x0901,0x0153,0x0015,
+0xffff,0x000e,0xfeef,0xf03a,0x38f7,0x08ca,0x0141,0x0014,0xffff,0x0007,0xfea6,0xee9f,0x3773,0x088d,0x012f,0x0012,
+0xfffe,0x0000,0xfe5a,0xecfb,0x35e3,0x084b,0x011c,0x0011,0xfffe,0xfff8,0xfe0b,0xeb50,0x3447,0x0804,0x010a,0x0010,
+0xfffe,0xffef,0xfdbb,0xe99d,0x32a3,0x07ba,0x00f8,0x000f,0xfffd,0xffe5,0xfd67,0xe7e4,0x30f6,0x076b,0x00e6,0x000d,
+0xfffd,0xffdb,0xfd12,0xe624,0x2f41,0x071a,0x00d4,0x000c,0xfffd,0xffd0,0xfcbb,0xe461,0x2d86,0x06c6,0x00c3,0x000b,
+0xfffc,0xffc4,0xfc63,0xe299,0x2bc5,0x066f,0x00b2,0x000a,0xfffc,0xffb8,0xfc09,0xe0ce,0x2a00,0x0617,0x00a1,0x0009,
+0xfffb,0xffaa,0xfbaf,0xdf01,0x2836,0x05be,0x0091,0x0009,0xfffb,0xff9d,0xfb54,0xdd33,0x266a,0x0563,0x0081,0x0008,
+0xfffa,0xff8e,0xfaf9,0xdb65,0x249c,0x0508,0x0073,0x0007,0xfff9,0xff80,0xfa9e,0xd997,0x22ce,0x04ad,0x0064,0x0006,
+0xfff8,0xff70,0xfa43,0xd7cb,0x2100,0x0452,0x0057,0x0006,0xfff8,0xff60,0xf9ea,0xd601,0x1f33,0x03f8,0x0049,0x0005,
+0xfff7,0xff4f,0xf992,0xd43c,0x1d68,0x039e,0x003d,0x0005,0xfff6,0xff3e,0xf93b,0xd27b,0x1ba0,0x0346,0x0031,0x0004,
+0xfff5,0xff2d,0xf8e7,0xd0c0,0x19dd,0x02ef,0x0026,0x0004,0xfff4,0xff1b,0xf896,0xcf0b,0x181d,0x029a,0x001c,0x0004,
+0xfff2,0xff09,0xf847,0xcd5e,0x1664,0x0246,0x0012,0x0003,0xfff1,0xfef7,0xf7fd,0xcbba,0x14b1,0x01f6,0x0009,0x0003,
+0xfff0,0xfee5,0xf7b6,0xca1e,0x1306,0x01a7,0x0001,0x0003,0xffef,0xfed2,0xf774,0xc88e,0x1162,0x015b,0xfffa,0x0002,
+0xffed,0xfec0,0xf737,0xc70a,0x0fc7,0x0112,0xfff3,0x0002,0xffec,0xfeae,0xf700,0xc591,0x0e35,0x00cb,0xffec,0x0002,
+0xffea,0xfe9c,0xf6cf,0xc427,0x0cad,0x0088,0xffe6,0x0002,0xffe9,0xfe8b,0xf6a5,0xc2ca,0x0b30,0x0048,0xffe1,0x0002,
+0xffe7,0xfe79,0xf681,0xc17c,0x09be,0x000b,0xffdc,0x0001,0xffe5,0xfe69,0xf666,0xc03e,0x0857,0xffd3,0xffd8,0x0001,
+0xffe4,0xfe58,0xf652,0xbf11,0x06fc,0xff9c,0xffd5,0x0001,0xffe2,0xfe49,0xf647,0xbdf6,0x05ae,0xff6a,0xffd2,0x0001,
+0xffe0,0xfe3b,0xf646,0xbcec,0x046e,0xff3a,0xffcf,0x0001,0xffde,0xfe2d,0xf64d,0xbbf5,0x0339,0xff0e,0xffcd,0x0001,
+0xffdc,0xfe21,0xf65f,0xbb11,0x0213,0xfee6,0xffcb,0x0001,0xffdb,0xfe16,0xf67c,0xba42,0x00fa,0xfec1,0xffca,0x0001,
+0xffd9,0xfe0d,0xf6a3,0xb987,0xfff0,0xfea0,0xffc9,0x0001,0xffd7,0xfe05,0xf6d6,0xb8e0,0xfef2,0xfe81,0xffc8,0x0001,
+0xffd5,0xfdff,0xf714,0xb84f,0xfe04,0xfe66,0xffc8,0x0000,0xffd3,0xfdfa,0xf75f,0xb7d4,0xfd23,0xfe4e,0xffc8,0x0000,
+0xffd1,0xfdf8,0xf7b6,0xb76f,0xfc51,0xfe39,0xffc8,0x0000,0xffd0,0xfdf7,0xf81a,0xb720,0xfb8d,0xfe28,0xffc9,0x0000,
+0xffcf,0xfdf9,0xf88b,0xb6e7,0xfad7,0xfe19,0xffc9,0x0000,0xffcd,0xfdfd,0xf909,0xb6c5,0xfa2f,0xfe0d,0xffca,0x0000,
+};
+
+static const uint8 int2idx_const[5000] = {
+  0,  0,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  4,  5,  5,
+  5,  5,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,  6,  6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  8,  8,  8,  8,
+  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+ 53, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+ 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 76, 76,
+ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 85, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
+ 89, 89, 89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,100,100,100,100,100,100,100,100,100,100,
+100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
+101,101,101,101,101,101,101,101,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,
+102,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,105,105,105,105,105,105,105,105,105,105,105,105,105,
+105,105,105,105,105,105,105,105,105,105,105,105,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
+106,106,106,106,106,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,108,
+108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,114,114,114,114,114,114,114,114,
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
+118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,119,119,119,119,119,119,
+119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
+121,121,121,121,121,121,121,121,121,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,
+122,122,122,122,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,124,124,
+124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,125,125,125,125,125,125,125,
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,126,126,126,126,126,126,126,126,126,126,126,126,
+126,126,126,126,126,126,126,126,126,126,126,126,126,126,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,
+127,127,127,127,127,127,127,127,127,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+128,128,128,128,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,130,
+130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,131,131,131,131,131,131,
+131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,132,132,132,132,132,132,132,132,132,132,132,
+132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
+133,133,133,133,133,133,133,133,133,133,133,133,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,
+134,134,134,134,134,134,134,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,
+135,135,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,137,137,
+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,138,138,138,138,138,138,138,
+138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,139,139,139,139,139,139,139,139,139,139,139,
+139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
+140,140,140,140,140,140,140,140,140,140,140,140,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
+141,141,141,141,141,141,141,141,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,
+142,142,142,142,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,144,
+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,145,145,145,145,145,
+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,146,146,146,146,146,146,146,146,146,
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,147,147,147,147,147,147,147,147,147,147,147,147,
+147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
+148,148,148,148,148,148,148,148,148,148,148,148,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
+149,149,149,149,149,149,149,149,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,
+151,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,153,153,153,
+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,154,154,154,154,154,154,
+154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,155,155,155,155,155,155,155,155,155,
+155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,156,156,156,156,156,156,156,156,156,156,156,156,156,
+156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
+157,157,157,157,157,157,157,157,157,157,157,157,157,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,
+158,158,158,158,158,158,158,158,158,158,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,
+159,159,159,159,159,159,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
+160,160,160,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
+162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,164,164,164,164,164,
+164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,165,165,165,165,165,165,165,165,
+165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,166,166,166,166,166,166,166,166,166,166,166,
+166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,167,167,167,167,167,167,167,167,167,167,167,167,167,167,
+167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
+168,168,168,168,168,168,168,168,168,168,168,168,168,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
+169,169,169,169,169,169,169,169,169,169,169,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,
+170,170,170,170,170,170,170,170,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,
+171,171,171,171,171,171,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
+172,172,172,172,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
+173,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,175,
+175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,176,176,176,
+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,177,177,177,177,177,
+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,178,178,178,178,178,178,178,
+178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,179,179,179,179,179,179,179,179,179,
+179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,180,180,180,180,180,180,180,180,180,180,180,
+180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,181,181,181,181,181,181,181,181,181,181,181,181,181,
+181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
+182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,
+183,183,183,183,183,183,183,183,183,183,183,183,183,183,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
+184,184,184,184,184,184,184,184,184,184,184,184,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
+185,185,185,185,185,185,185,185,185,185,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,
+186,186,186,186,186,186,186,186,186,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,
+187,187,187,187,187,187,187,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
+188,188,188,188,188,188,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
+189,189,189,189,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,
+190,190,190,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
+192,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,194,
+194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,195,195,
+195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,196,196,196,
+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,197,197,197,197,
+197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,198,198,198,198,198,
+198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,199,199,199,199,199,199,
+199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,201,201,201,201,201,201,201,
+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,202,202,202,202,202,202,202,202,
+202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,203,203,203,203,203,203,203,203,203,
+203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,204,204,204,204,204,204,204,204,204,
+204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,205,205,205,205,205,205,205,205,205,205,
+205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,206,206,206,206,206,206,206,206,206,206,206,
+206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,207,207,207,207,207,207,207,207,207,207,207,
+207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,208,208,208,208,208,208,208,208,208,208,208,208,
+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,209,209,209,209,209,209,209,209,209,209,209,209,
+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,210,210,210,210,210,210,210,210,210,210,210,210,
+210,210,210,210,210,210,210,210 };
+
+static const uint16 int3idx[32768] = {
+  0,  0,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,  3,  3,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  4,  4,  4,  5,  5,
+  5,  5,  5,  5,  5,  5,  5,  5,  6,  6,  6,  6,  6,  6,  6,  6,  6,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  7,  8,  8,  8,  8,
+  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+ 53, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+ 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 61, 61, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
+ 65, 65, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 71, 71, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73,
+ 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 76, 76,
+ 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 85, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
+ 89, 89, 89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,100,100,100,100,100,100,100,100,100,100,
+100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,
+101,101,101,101,101,101,101,101,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,
+102,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,104,104,104,104,104,104,
+104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,105,105,105,105,105,105,105,105,105,105,105,105,105,
+105,105,105,105,105,105,105,105,105,105,105,105,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
+106,106,106,106,106,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,108,
+108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,109,109,109,109,109,109,109,109,
+109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
+110,110,110,110,110,110,110,110,110,110,110,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,111,
+111,111,111,111,111,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,112,113,
+113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,114,114,114,114,114,114,114,114,
+114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,114,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
+115,115,115,115,115,115,115,115,115,115,115,115,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
+116,116,116,116,116,116,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,117,
+118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,119,119,119,119,119,119,
+119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,120,120,120,120,120,120,120,120,120,120,120,
+120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,121,
+121,121,121,121,121,121,121,121,121,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,
+122,122,122,122,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,124,124,
+124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,125,125,125,125,125,125,125,
+125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,126,126,126,126,126,126,126,126,126,126,126,126,
+126,126,126,126,126,126,126,126,126,126,126,126,126,126,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,
+127,127,127,127,127,127,127,127,127,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,
+128,128,128,128,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,129,130,
+130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,131,131,131,131,131,131,
+131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,132,132,132,132,132,132,132,132,132,132,132,
+132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
+133,133,133,133,133,133,133,133,133,133,133,133,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,
+134,134,134,134,134,134,134,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,
+135,135,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,137,137,
+137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,138,138,138,138,138,138,138,
+138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,139,139,139,139,139,139,139,139,139,139,139,
+139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,
+140,140,140,140,140,140,140,140,140,140,140,140,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,
+141,141,141,141,141,141,141,141,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,
+142,142,142,142,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,144,
+144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,145,145,145,145,145,
+145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,146,146,146,146,146,146,146,146,146,
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,147,147,147,147,147,147,147,147,147,147,147,147,
+147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
+148,148,148,148,148,148,148,148,148,148,148,148,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,149,
+149,149,149,149,149,149,149,149,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
+150,150,150,150,150,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,
+151,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,153,153,153,
+153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,154,154,154,154,154,154,
+154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,155,155,155,155,155,155,155,155,155,
+155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,155,156,156,156,156,156,156,156,156,156,156,156,156,156,
+156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
+157,157,157,157,157,157,157,157,157,157,157,157,157,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,
+158,158,158,158,158,158,158,158,158,158,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,
+159,159,159,159,159,159,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
+160,160,160,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,161,
+162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,162,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,164,164,164,164,164,
+164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,164,165,165,165,165,165,165,165,165,
+165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,165,166,166,166,166,166,166,166,166,166,166,166,
+166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,166,167,167,167,167,167,167,167,167,167,167,167,167,167,167,
+167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,167,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,
+168,168,168,168,168,168,168,168,168,168,168,168,168,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,169,
+169,169,169,169,169,169,169,169,169,169,169,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,170,
+170,170,170,170,170,170,170,170,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,171,
+171,171,171,171,171,171,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,
+172,172,172,172,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,173,
+173,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,174,175,
+175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,175,176,176,176,
+176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,177,177,177,177,177,
+177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,177,178,178,178,178,178,178,178,
+178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,179,179,179,179,179,179,179,179,179,
+179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,180,180,180,180,180,180,180,180,180,180,180,
+180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,181,181,181,181,181,181,181,181,181,181,181,181,181,
+181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,181,182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,
+182,182,182,182,182,182,182,182,182,182,182,182,182,182,182,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,183,
+183,183,183,183,183,183,183,183,183,183,183,183,183,183,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,184,
+184,184,184,184,184,184,184,184,184,184,184,184,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,185,
+185,185,185,185,185,185,185,185,185,185,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,186,
+186,186,186,186,186,186,186,186,186,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,187,
+187,187,187,187,187,187,187,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,188,
+188,188,188,188,188,188,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,
+189,189,189,189,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,190,
+190,190,190,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
+191,191,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,
+192,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,193,194,
+194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,195,195,
+195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,196,196,196,
+196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,197,197,197,197,
+197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,198,198,198,198,198,
+198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,198,199,199,199,199,199,199,
+199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,200,200,200,200,200,200,200,
+200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,201,201,201,201,201,201,201,
+201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,202,202,202,202,202,202,202,202,
+202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,203,203,203,203,203,203,203,203,203,
+203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,204,204,204,204,204,204,204,204,204,
+204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,205,205,205,205,205,205,205,205,205,205,
+205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,206,206,206,206,206,206,206,206,206,206,206,
+206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,207,207,207,207,207,207,207,207,207,207,207,
+207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,208,208,208,208,208,208,208,208,208,208,208,208,
+208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,208,209,209,209,209,209,209,209,209,209,209,209,209,
+209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,209,210,210,210,210,210,210,210,210,210,210,210,210,
+210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,211,211,211,211,211,211,211,211,211,211,211,211,211,
+211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,212,212,212,212,212,212,212,212,212,212,212,212,212,
+212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,212,213,213,213,213,213,213,213,213,213,213,213,213,213,
+213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,214,214,214,214,214,214,214,214,214,214,214,214,214,
+214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,215,215,215,215,215,215,215,215,215,215,215,215,215,
+215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,215,216,216,216,216,216,216,216,216,216,216,216,216,216,
+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,217,217,217,217,217,217,217,217,217,217,217,217,217,
+217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,217,218,218,218,218,218,218,218,218,218,218,218,218,218,
+218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,218,219,219,219,219,219,219,219,219,219,219,219,219,219,
+219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,219,220,220,220,220,220,220,220,220,220,220,220,220,220,
+220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,221,221,221,221,221,221,221,221,221,221,221,221,221,
+221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,222,222,222,222,222,222,222,222,222,222,222,222,222,
+222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,223,223,223,223,223,223,223,223,223,223,223,223,
+223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,224,224,224,224,224,224,224,224,224,224,224,224,
+224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,225,225,225,225,225,225,225,225,225,225,225,
+225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,226,226,226,226,226,226,226,226,226,226,226,
+226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226,227,227,227,227,227,227,227,227,227,227,227,
+227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,228,228,228,228,228,228,228,228,228,228,
+228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,229,229,229,229,229,229,229,229,229,
+229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,230,230,230,230,230,230,230,230,230,
+230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,231,231,231,231,231,231,231,231,
+231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,231,232,232,232,232,232,232,232,
+232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,233,233,233,233,233,233,233,
+233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233,234,234,234,234,234,234,
+234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,235,235,235,235,235,
+235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,236,236,236,236,
+236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,237,237,237,
+237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,237,238,238,
+238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,238,239,
+239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,
+240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,240,
+240,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,241,
+241,241,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,242,
+242,242,242,242,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,243,
+243,243,243,243,243,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,244,
+244,244,244,244,244,244,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
+245,245,245,245,245,245,245,245,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,246,
+246,246,246,246,246,246,246,246,246,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,247,
+247,247,247,247,247,247,247,247,247,247,247,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,
+248,248,248,248,248,248,248,248,248,248,248,248,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
+249,249,249,249,249,249,249,249,249,249,249,249,249,249,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
+250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,
+251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
+252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,252,253,253,253,253,253,253,253,253,253,253,253,253,253,
+253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,254,254,254,254,254,254,254,254,254,254,254,254,
+254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,256,256,256,256,256,256,256,256,
+256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,257,257,257,257,257,257,
+257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,258,258,258,258,
+258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,258,259,259,
+259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,
+260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,260,
+260,260,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,
+261,261,261,261,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,
+263,263,263,263,263,263,263,263,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,
+264,264,264,264,264,264,264,264,264,264,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,265,
+265,265,265,265,265,265,265,265,265,265,265,265,265,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,
+266,266,266,266,266,266,266,266,266,266,266,266,266,266,266,267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,
+267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,267,268,268,268,268,268,268,268,268,268,268,268,268,268,268,268,
+268,268,268,268,268,268,268,268,268,268,268,268,268,268,268,268,268,268,268,268,269,269,269,269,269,269,269,269,269,269,269,269,
+269,269,269,269,269,269,269,269,269,269,269,269,269,269,269,269,269,269,269,269,269,269,270,270,270,270,270,270,270,270,270,270,
+270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,271,271,271,271,271,271,271,
+271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,271,272,272,272,272,272,
+272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,272,273,273,
+273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,273,
+274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,274,
+274,274,274,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,
+275,275,275,275,275,275,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,276,
+276,276,276,276,276,276,276,276,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,
+277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
+278,278,278,278,278,278,278,278,278,278,278,278,278,278,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,
+279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,
+280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,281,281,281,281,281,281,281,281,281,281,281,281,
+281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,282,282,282,282,282,282,282,282,282,
+282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,283,283,283,283,283,283,
+283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,284,284,284,
+284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,
+285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,
+285,285,285,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,287,287,287,287,287,287,287,287,287,287,287,287,287,287,287,287,287,287,287,287,287,287,287,287,287,287,
+287,287,287,287,287,287,287,287,287,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,288,
+288,288,288,288,288,288,288,288,288,288,288,288,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,
+289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,
+290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,291,291,291,291,291,291,291,291,291,291,291,291,291,
+291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,291,292,292,292,292,292,292,292,292,292,292,
+292,292,292,292,292,292,292,292,292,292,292,292,292,292,292,292,292,292,292,292,292,292,292,292,292,292,293,293,293,293,293,293,
+293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,294,294,294,
+294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,294,
+295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,295,
+295,295,295,295,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,
+296,296,296,296,296,296,296,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,
+297,297,297,297,297,297,297,297,297,297,297,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,
+298,298,298,298,298,298,298,298,298,298,298,298,298,298,298,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,
+299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,299,300,300,300,300,300,300,300,300,300,300,300,300,300,300,
+300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,301,301,301,301,301,301,301,301,301,301,
+301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,301,302,302,302,302,302,302,
+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,303,303,
+303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,
+303,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,
+304,304,304,304,304,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,305,
+305,305,305,305,305,305,305,305,305,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,
+306,306,306,306,306,306,306,306,306,306,306,306,306,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,
+307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,309,309,309,309,309,309,309,309,309,309,309,
+309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,310,310,310,310,310,310,310,
+310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,311,311,311,
+311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,
+311,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,
+312,312,312,312,312,312,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,313,
+313,313,313,313,313,313,313,313,313,313,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
+314,314,314,314,314,314,314,314,314,314,314,314,314,314,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
+315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,316,316,316,316,316,316,316,316,316,316,316,316,316,316,
+316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,316,317,317,317,317,317,317,317,317,317,
+317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,317,318,318,318,318,318,
+318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,318,319,
+319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,319,
+319,319,319,319,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,320,
+320,320,320,320,320,320,320,320,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,
+321,321,321,321,321,321,321,321,321,321,321,321,321,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,
+322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,
+323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,323,324,324,324,324,324,324,324,324,324,324,
+324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,324,325,325,325,325,325,
+325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,325,326,
+326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,
+326,326,326,326,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,327,
+327,327,327,327,327,327,327,327,327,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,
+328,328,328,328,328,328,328,328,328,328,328,328,328,328,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,
+329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,329,330,330,330,330,330,330,330,330,330,330,330,330,330,330,
+330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,331,331,331,331,331,331,331,331,331,
+331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,331,332,332,332,332,
+332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,
+332,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,333,
+333,333,333,333,333,333,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,334,
+334,334,334,334,334,334,334,334,334,334,334,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,
+335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
+336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,337,337,337,337,337,337,337,337,337,337,337,
+337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,338,338,338,338,338,338,
+338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,
+339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,339,
+339,339,339,339,339,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
+340,340,340,340,340,340,340,340,340,340,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,
+341,341,341,341,341,341,341,341,341,341,341,341,341,341,341,342,342,342,342,342,342,342,342,342,342,342,342,342,342,342,342,342,
+342,342,342,342,342,342,342,342,342,342,342,342,342,342,342,342,342,342,342,342,343,343,343,343,343,343,343,343,343,343,343,343,
+343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,344,344,344,344,344,344,
+344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,344,345,
+345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,345,
+345,345,345,345,345,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,
+346,346,346,346,346,346,346,346,346,346,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,
+347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,
+348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,348,349,349,349,349,349,349,349,349,349,349,349,
+349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,350,350,350,350,350,
+350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,350,
+351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,351,
+351,351,351,351,351,351,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,
+352,352,352,352,352,352,352,352,352,352,352,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,
+353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,353,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,
+354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,355,355,355,355,355,355,355,355,355,
+355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,356,356,356,
+356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,356,
+356,356,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,357,
+357,357,357,357,357,357,357,357,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
+358,358,358,358,358,358,358,358,358,358,358,358,358,358,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,
+359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,360,360,360,360,360,360,360,360,360,360,360,360,
+360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,361,361,361,361,361,361,
+361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
+362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,362,
+362,362,362,362,362,362,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,363,
+363,363,363,363,363,363,363,363,363,363,363,363,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,
+364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,365,365,365,365,365,365,365,365,365,365,365,365,365,365,
+365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,365,366,366,366,366,366,366,366,366,
+366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,367,367,
+367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,367,
+367,367,367,367,367,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,368,
+368,368,368,368,368,368,368,368,368,368,368,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,
+369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,369,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,371,371,371,371,371,371,371,371,371,
+371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,371,372,372,
+372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,
+372,372,372,372,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,
+373,373,373,373,373,373,373,373,373,373,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
+374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,
+375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,376,376,376,376,376,376,376,376,376,
+376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,376,377,377,
+377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,
+377,377,377,377,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,
+378,378,378,378,378,378,378,378,378,378,378,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,
+379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,380,380,380,380,380,380,380,380,380,380,380,380,380,380,
+380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,380,381,381,381,381,381,381,381,381,
+381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,382,
+382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,
+382,382,382,382,382,382,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,
+383,383,383,383,383,383,383,383,383,383,383,383,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,
+384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,384,385,385,385,385,385,385,385,385,385,385,385,385,385,
+385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,385,386,386,386,386,386,386,
+386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,
+386,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,387,
+387,387,387,387,387,387,387,387,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,
+388,388,388,388,388,388,388,388,388,388,388,388,388,388,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,
+389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,389,390,390,390,390,390,390,390,390,390,390,390,
+390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,391,391,391,391,
+391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,391,
+391,391,391,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,392,
+392,392,392,392,392,392,392,392,392,392,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,
+393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,393,394,394,394,394,394,394,394,394,394,394,394,394,394,394,394,
+394,394,394,394,394,394,394,394,394,394,394,394,394,394,394,394,394,394,394,394,394,394,394,394,394,395,395,395,395,395,395,395,
+395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,
+396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,396,
+396,396,396,396,396,396,396,397,397,397,397,397,397,397,397,397,397,397,397,397,397,397,397,397,397,397,397,397,397,397,397,397,
+397,397,397,397,397,397,397,397,397,397,397,397,397,397,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,
+398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,399,399,399,399,399,399,399,399,399,399,399,
+399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,399,400,400,400,
+400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,
+400,400,400,400,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,401,
+401,401,401,401,401,401,401,401,401,401,401,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,
+402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,402,403,403,403,403,403,403,403,403,403,403,403,403,403,
+403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,403,404,404,404,404,404,404,
+404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
+404,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,
+405,405,405,405,405,405,405,405,405,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,
+406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,
+407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,407,408,408,408,408,408,408,408,408,
+408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,408,409,
+409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,409,
+409,409,409,409,409,409,409,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,
+410,410,410,410,410,410,410,410,410,410,410,410,410,410,410,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,
+411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,412,412,412,412,412,412,412,412,412,412,
+412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,413,413,
+413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,
+413,413,413,413,413,413,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,414,
+414,414,414,414,414,414,414,414,414,414,414,414,414,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,
+415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,416,416,416,416,416,416,416,416,416,416,416,
+416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,416,417,417,417,
+417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,
+417,417,417,417,417,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,
+418,418,418,418,418,418,418,418,418,418,418,418,418,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,
+419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,419,420,420,420,420,420,420,420,420,420,420,420,
+420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,420,421,421,421,
+421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,421,
+421,421,421,421,421,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
+422,422,422,422,422,422,422,422,422,422,422,422,422,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,
+423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,423,424,424,424,424,424,424,424,424,424,424,424,
+424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,424,425,425,425,
+425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,425,
+425,425,425,425,425,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,426,
+426,426,426,426,426,426,426,426,426,426,426,426,426,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,
+427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,428,428,428,428,428,428,428,428,428,428,428,
+428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,428,429,429,429,
+429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,429,
+429,429,429,429,429,429,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,430,
+430,430,430,430,430,430,430,430,430,430,430,430,430,430,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,
+431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,432,432,432,432,432,432,432,432,432,432,
+432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,433,433,
+433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,433,
+433,433,433,433,433,433,433,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,
+434,434,434,434,434,434,434,434,434,434,434,434,434,434,434,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,
+435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,436,436,436,436,436,436,436,436,
+436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,436,
+437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,437,
+437,437,437,437,437,437,437,437,437,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,
+438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
+439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,440,440,440,440,440,440,
+440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,440,
+440,440,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,
+441,441,441,441,441,441,441,441,441,441,441,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,
+442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,442,443,443,443,443,443,443,443,443,443,443,443,443,443,
+443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,443,444,444,444,444,
+444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,444,
+444,444,444,444,444,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,
+445,445,445,445,445,445,445,445,445,445,445,445,445,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,
+446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,447,447,447,447,447,447,447,447,447,447,
+447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,447,448,
+448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,
+448,448,448,448,448,448,448,448,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,
+449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,449,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,
+450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,450,451,451,451,451,451,451,451,
+451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,
+451,451,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,
+452,452,452,452,452,452,452,452,452,452,452,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,
+453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,454,454,454,454,454,454,454,454,454,454,454,454,
+454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,454,455,455,455,
+455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,
+455,455,455,455,455,455,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,
+456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,
+457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,457,458,458,458,458,458,458,458,458,
+458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,458,
+458,458,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,459,
+459,459,459,459,459,459,459,459,459,459,459,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,461,461,461,461,461,461,461,461,461,461,461,461,
+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,462,462,462,
+462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,462,
+462,462,462,462,462,462,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
+463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,
+464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,464,465,465,465,465,465,465,465,
+465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,465,
+465,465,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,466,
+466,466,466,466,466,466,466,466,466,466,466,466,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,
+467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,467,468,468,468,468,468,468,468,468,468,468,468,
+468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,468,469,469,
+469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,469,
+469,469,469,469,469,469,469,469,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,
+470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,470,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,
+471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,471,472,472,472,472,472,
+472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,472,
+472,472,472,472,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,473,
+473,473,473,473,473,473,473,473,473,473,473,473,473,473,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,
+474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,476,
+476,476,476,476,476,476,476,476,476,476,476,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,
+477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,477,478,478,478,478,478,478,478,478,478,478,478,478,
+478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,479,479,
+479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,479,
+479,479,479,479,479,479,479,479,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,
+480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,480,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
+481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,482,482,482,482,482,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
+482,482,482,482,482,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,
+484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,484,485,485,485,485,485,485,485,
+485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,485,
+485,485,485,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,486,
+486,486,486,486,486,486,486,486,486,486,486,486,486,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,
+487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,487,488,488,488,488,488,488,488,488,488,
+488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,488,
+488,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,489,
+489,489,489,489,489,489,489,489,489,489,489,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,
+490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,490,491,491,491,491,491,491,491,491,491,491,491,
+491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,492,
+492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,492,
+492,492,492,492,492,492,492,492,492,493,493,493,493,493,493,493,493,493,493,493,493,493,493,493,493,493,493,493,493,493,493,493,
+493,493,493,493,493,493,493,493,493,493,493,493,493,493,493,493,493,493,493,494,494,494,494,494,494,494,494,494,494,494,494,494,
+494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,494,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,
+496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,496,497,497,497,497,497,497,497,497,497,497,497,497,497,497,
+497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,497,498,498,498,498,
+498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,498,
+498,498,498,498,498,498,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,
+499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,
+500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,501,501,501,501,501,
+501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,501,
+501,501,501,501,501,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
+502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,
+503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,503,504,504,504,504,504,504,
+504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,504,
+504,504,504,504,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
+505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,
+506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,506,507,507,507,507,507,507,507,
+507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,507,
+507,507,507,507,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,508,
+508,508,508,508,508,508,508,508,508,508,508,508,508,508,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,
+509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,510,510,510,510,510,510,510,
+510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,510,
+510,510,510,510,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,511,
+511,511,511,511,511,511,511,511,511,511,511,511,511,511,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,
+512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,513,513,513,513,513,513,513,
+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
+513,513,513,513,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,514,
+514,514,514,514,514,514,514,514,514,514,514,514,514,514,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,
+515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,515,516,516,516,516,516,516,516,
+516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
+516,516,516,516,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,
+517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,
+518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,519,519,519,519,519,519,
+519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
+519,519,519,519,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,
+520,520,520,520,520,520,520,520,520,520,520,520,520,520,520,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,
+521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,521,522,522,522,522,522,522,
+522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,522,
+522,522,522,522,522,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,
+523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,523,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,
+524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,524,525,525,525,525,525,
+525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,525,
+525,525,525,525,525,525,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,
+526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,526,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,
+527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,528,528,528,528,
+528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,
+528,528,528,528,528,528,528,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,
+529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,529,530,530,530,530,530,530,530,530,530,530,530,530,530,
+530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,530,531,531,
+531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,531,
+531,531,531,531,531,531,531,531,531,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,
+532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,532,533,533,533,533,533,533,533,533,533,533,533,533,
+533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,534,
+534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
+534,534,534,534,534,534,534,534,534,534,534,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,
+535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,536,536,536,536,536,536,536,536,536,536,
+536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
+536,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,537,
+537,537,537,537,537,537,537,537,537,537,537,537,537,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,
+538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,538,539,539,539,539,539,539,539,539,
+539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,539,
+539,539,539,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,
+540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,
+541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,541,542,542,542,542,542,542,
+542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,542,
+542,542,542,542,542,542,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,
+543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,543,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,
+544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,545,545,545,
+545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,545,
+545,545,545,545,545,545,545,545,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,
+546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,546,547,547,547,547,547,547,547,547,547,547,547,547,
+547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,547,
+548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,548,
+548,548,548,548,548,548,548,548,548,548,548,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,
+549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,549,550,550,550,550,550,550,550,550,550,
+550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,550,
+550,550,550,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,
+551,551,551,551,551,551,551,551,551,551,551,551,551,551,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
+552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,553,553,553,553,553,553,
+553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,
+553,553,553,553,553,553,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,
+554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,554,555,555,555,555,555,555,555,555,555,555,555,555,555,555,
+555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,555,556,556,
+556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,556,
+556,556,556,556,556,556,556,556,556,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,558,558,558,558,558,558,558,558,558,558,558,
+558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,
+558,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
+559,559,559,559,559,559,559,559,559,559,559,559,559,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,
+560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,560,561,561,561,561,561,561,561,
+561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,561,
+561,561,561,561,561,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,
+562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,
+563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,563,564,564,564,
+564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,564,
+564,564,564,564,564,564,564,564,564,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,
+565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,565,566,566,566,566,566,566,566,566,566,566,566,
+566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,566,
+566,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,567,
+567,567,567,567,567,567,567,567,567,567,567,567,567,567,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,
+568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,568,569,569,569,569,569,569,
+569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,569,
+569,569,569,569,569,569,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,
+570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,570,571,571,571,571,571,571,571,571,571,571,571,571,571,571,
+571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,571,572,572,
+572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,572,
+572,572,572,572,572,572,572,572,572,572,572,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,573,574,574,574,574,574,574,574,574,574,
+574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,574,
+574,574,574,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,
+575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,575,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,
+576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,577,577,577,577,
+577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
+577,577,577,577,577,577,577,577,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
+578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,579,579,579,579,579,579,579,579,579,579,579,
+579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,579,
+579,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,580,
+580,580,580,580,580,580,580,580,580,580,580,580,580,580,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,
+581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,581,582,582,582,582,582,582,
+582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,582,
+582,582,582,582,582,582,582,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,
+583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,584,584,584,584,584,584,584,584,584,584,584,584,584,
+584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,584,
+585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,
+585,585,585,585,585,585,585,585,585,585,585,585,585,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,
+588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,589,589,589,589,589,589,589,589,589,589,589,589,589,
+589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,589,590,
+590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,
+590,590,590,590,590,590,590,590,590,590,590,590,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
+591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,592,592,592,592,592,592,592,
+592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
+592,592,592,592,592,592,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,
+593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,593,594,594,594,594,594,594,594,594,594,594,594,594,594,594,
+594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,595,
+595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
+595,595,595,595,595,595,595,595,595,595,595,595,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,
+596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,596,597,597,597,597,597,597,597,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,597,597,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,
+598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,599,599,599,599,599,599,599,599,599,599,599,599,599,
+599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,599,
+600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,
+600,600,600,600,600,600,600,600,600,600,600,600,600,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,
+601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,601,602,602,602,602,602,602,
+602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,602,
+602,602,602,602,602,602,602,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,
+603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,603,604,604,604,604,604,604,604,604,604,604,604,604,
+604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,604,
+604,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,605,
+605,605,605,605,605,605,605,605,605,605,605,605,605,605,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
+606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,607,607,607,607,607,
+607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,607,
+607,607,607,607,607,607,607,607,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,
+608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,608,609,609,609,609,609,609,609,609,609,609,609,
+609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,609,
+609,609,609,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,
+610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,610,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,
+611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,611,612,612,612,
+612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,612,
+612,612,612,612,612,612,612,612,612,612,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,
+613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,613,614,614,614,614,614,614,614,614,
+614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,614,
+614,614,614,614,614,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,
+615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,615,616,616,616,616,616,616,616,616,616,616,616,616,616,616,
+616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,
+617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,617,
+617,617,617,617,617,617,617,617,617,617,617,617,617,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,
+618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,618,619,619,619,619,619,
+619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,
+619,619,619,619,619,619,619,619,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,
+620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,621,621,621,621,621,621,621,621,621,621,
+621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,621,
+621,621,621,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,
+622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,622,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,
+623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,623,624,624,
+624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,624,
+624,624,624,624,624,624,624,624,624,624,624,624,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,
+625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,626,626,626,626,626,626,626,
+626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,626,
+626,626,626,626,626,626,626,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,
+627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,627,628,628,628,628,628,628,628,628,628,628,628,
+628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,628,
+628,628,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,
+629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,629,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,
+630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,630,631,631,
+631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,631,
+631,631,631,631,631,631,631,631,631,631,631,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,
+632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,632,633,633,633,633,633,633,633,
+633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,
+633,633,633,633,633,633,633,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,
+634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,635,635,635,635,635,635,635,635,635,635,635,
+635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,635,
+635,635,635,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,
+636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,
+637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,637,638,638,
+638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,638,
+638,638,638,638,638,638,638,638,638,638,638,638,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,
+639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,639,640,640,640,640,640,640,
+640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,
+640,640,640,640,640,640,640,640,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,
+641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,641,642,642,642,642,642,642,642,642,642,642,
+642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,642,
+642,642,642,642,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,
+643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,644,644,644,644,644,644,644,644,644,644,644,644,644,644,
+644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,
+645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,645,
+645,645,645,645,645,645,645,645,645,645,645,645,645,645,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,
+646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,646,647,647,647,
+647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,
+647,647,647,647,647,647,647,647,647,647,647,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,
+648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,648,649,649,649,649,649,649,649,
+649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,649,
+649,649,649,649,649,649,649,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,
+650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,650,651,651,651,651,651,651,651,651,651,651,651,
+651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,651,
+651,651,651,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,
+652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,652,653,653,653,653,653,653,653,653,653,653,653,653,653,653,
+653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,
+654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,654,
+654,654,654,654,654,654,654,654,654,654,654,654,654,654,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,
+655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,655,656,656,656,
+656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,656,
+656,656,656,656,656,656,656,656,656,656,656,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,
+657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,657,658,658,658,658,658,658,658,
+658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,
+658,658,658,658,658,658,658,658,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,
+659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,659,660,660,660,660,660,660,660,660,660,660,
+660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,660,
+660,660,660,660,660,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,
+661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,661,662,662,662,662,662,662,662,662,662,662,662,662,662,
+662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,662,
+662,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,
+663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,
+664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,665,
+665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,665,
+665,665,665,665,665,665,665,665,665,665,665,665,665,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,
+666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,666,667,667,667,667,
+667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,
+667,667,667,667,667,667,667,667,667,667,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,
+668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,668,669,669,669,669,669,669,669,
+669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,669,
+669,669,669,669,669,669,669,669,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,
+670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,670,671,671,671,671,671,671,671,671,671,671,
+671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,671,
+671,671,671,671,671,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,
+672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,672,673,673,673,673,673,673,673,673,673,673,673,673,
+673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,
+673,673,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,
+674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,674,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,
+675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,675,
+676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
+676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,
+677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,678,678,
+678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
+678,678,678,678,678,678,678,678,678,678,678,678,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,
+679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,679,680,680,680,680,680,
+680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,680,
+680,680,680,680,680,680,680,680,680,680,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,
+681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,681,682,682,682,682,682,682,682,
+682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,682,
+682,682,682,682,682,682,682,682,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,
+683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,683,684,684,684,684,684,684,684,684,684,
+684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,684,
+684,684,684,684,684,684,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,
+685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,686,686,686,686,686,686,686,686,686,686,686,
+686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,686,
+686,686,686,686,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,
+687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,687,688,688,688,688,688,688,688,688,688,688,688,688,688,
+688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,
+688,688,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,
+689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,689,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,
+690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,
+691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,
+691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,691,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,
+692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,693,
+693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,
+693,693,693,693,693,693,693,693,693,693,693,693,693,693,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,
+694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,695,695,695,
+695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,695,
+695,695,695,695,695,695,695,695,695,695,695,695,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,
+696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,697,697,697,697,
+697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
+697,697,697,697,697,697,697,697,697,697,697,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,
+698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,698,699,699,699,699,699,699,
+699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,
+699,699,699,699,699,699,699,699,699,699,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,
+700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,700,701,701,701,701,701,701,701,
+701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,
+701,701,701,701,701,701,701,701,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,
+702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,702,703,703,703,703,703,703,703,703,
+703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,
+703,703,703,703,703,703,703,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,
+704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,704,705,705,705,705,705,705,705,705,705,
+705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,
+705,705,705,705,705,705,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,
+706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,706,707,707,707,707,707,707,707,707,707,707,
+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+707,707,707,707,707,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
+708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,709,709,709,709,709,709,709,709,709,709,709,
+709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,
+709,709,709,709,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
+710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,711,711,711,711,711,711,711,711,711,711,711,711,
+711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,
+711,711,711,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,
+712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,712,713,713,713,713,713,713,713,713,713,713,713,713,713,
+713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,
+713,713,713,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,
+714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
+715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
+715,715,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,
+716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,717,717,717,717,717,717,717,717,717,717,717,717,717,717,
+717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,717,
+717,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,
+718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,
+719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,719,
+719,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,
+720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,
+721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,
+721,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,
+722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,
+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,
+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,
+726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,
+726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,726,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,
+727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,727,
+728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,
+728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,
+729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,729,
+730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,
+730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,
+731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,731,
+732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,
+732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,
+733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,733,
+734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,
+734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,734,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,
+735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,
+735,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,
+736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,736,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,
+737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,
+737,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,
+738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
+739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
+739,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,
+740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,741,741,741,741,741,741,741,741,741,741,741,741,741,741,
+741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,741,
+741,741,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,
+742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,742,743,743,743,743,743,743,743,743,743,743,743,743,743,743,
+743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,743,
+743,743,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,
+744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,745,745,745,745,745,745,745,745,745,745,745,745,745,
+745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,745,
+745,745,745,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,
+746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,746,747,747,747,747,747,747,747,747,747,747,747,747,747,
+747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,
+747,747,747,747,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,
+748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,748,749,749,749,749,749,749,749,749,749,749,749,749,
+749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,
+749,749,749,749,749,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,
+750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,751,751,751,751,751,751,751,751,751,751,751,
+751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,
+751,751,751,751,751,751,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,
+752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,752,753,753,753,753,753,753,753,753,753,753,
+753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,
+753,753,753,753,753,753,753,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,
+754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,754,755,755,755,755,755,755,755,755,755,
+755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,
+755,755,755,755,755,755,755,755,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,
+756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,757,757,757,757,757,757,757,757,
+757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,
+757,757,757,757,757,757,757,757,757,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,
+758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,758,759,759,759,759,759,759,
+759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,
+759,759,759,759,759,759,759,759,759,759,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,
+760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,760,761,761,761,761,761,
+761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,
+761,761,761,761,761,761,761,761,761,761,761,761,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,
+762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,762,763,763,763,763,
+763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,
+763,763,763,763,763,763,763,763,763,763,763,763,763,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,
+764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,765,765,
+765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,
+765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,
+766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,767,
+767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,
+767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,767,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,
+768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,
+768,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,
+769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,769,770,770,770,770,770,770,770,770,770,770,770,770,770,770,
+770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,770,
+770,770,770,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,
+771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,772,772,772,772,772,772,772,772,772,772,772,772,
+772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
+772,772,772,772,772,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,
+773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,773,774,774,774,774,774,774,774,774,774,774,
+774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,774,
+774,774,774,774,774,774,774,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,
+775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,776,776,776,776,776,776,776,776,
+776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,776,
+776,776,776,776,776,776,776,776,776,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,
+777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,778,778,778,778,778,778,
+778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,778,
+778,778,778,778,778,778,778,778,778,778,778,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,
+779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,779,780,780,780,780,
+780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,780,
+780,780,780,780,780,780,780,780,780,780,780,780,780,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,
+781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,782,782,
+782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,
+782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,
+783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,
+784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,
+784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,
+785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,785,
+785,785,785,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,
+786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,787,787,787,787,787,787,787,787,787,787,787,787,
+787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,
+787,787,787,787,787,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,
+788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,788,789,789,789,789,789,789,789,789,789,789,
+789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,
+789,789,789,789,789,789,789,789,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,
+790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,790,791,791,791,791,791,791,791,
+791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,791,
+791,791,791,791,791,791,791,791,791,791,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,
+792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,792,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,
+794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,794,795,795,
+795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,
+795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
+796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,796,
+796,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,
+797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,797,798,798,798,798,798,798,798,798,798,798,798,798,798,
+798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,
+798,798,798,798,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,
+799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,799,800,800,800,800,800,800,800,800,800,800,
+800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,800,
+800,800,800,800,800,800,800,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,
+801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,802,802,802,802,802,802,802,
+802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,802,
+802,802,802,802,802,802,802,802,802,802,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,
+803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,803,804,804,804,804,
+804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,804,
+804,804,804,804,804,804,804,804,804,804,804,804,804,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
+805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,806,
+806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,
+806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,806,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,
+807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,807,
+807,807,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,
+808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,808,809,809,809,809,809,809,809,809,809,809,809,809,
+809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,809,
+809,809,809,809,809,809,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,
+810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,811,811,811,811,811,811,811,811,811,
+811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,811,
+811,811,811,811,811,811,811,811,811,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,
+812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,812,813,813,813,813,813,
+813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,813,
+813,813,813,813,813,813,813,813,813,813,813,813,813,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,
+814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,815,815,
+815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,
+815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,
+816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,816,
+816,816,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,
+817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,817,818,818,818,818,818,818,818,818,818,818,818,818,
+818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,
+818,818,818,818,818,818,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,820,820,820,820,820,820,820,820,
+820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,820,
+820,820,820,820,820,820,820,820,820,820,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,
+821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,822,822,822,822,
+822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,822,
+822,822,822,822,822,822,822,822,822,822,822,822,822,822,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,
+823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,823,
+824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,
+824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,825,825,825,825,825,825,825,825,825,825,825,825,825,825,
+825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,825,
+825,825,825,825,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,
+826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,826,827,827,827,827,827,827,827,827,827,827,
+827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,827,
+827,827,827,827,827,827,827,827,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,
+828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,
+830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,830,831,831,
+831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,
+831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,
+832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,
+832,832,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,
+833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,834,834,834,834,834,834,834,834,834,834,834,834,
+834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,834,
+834,834,834,834,834,834,834,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,
+835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,836,836,836,836,836,836,836,
+836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,836,
+836,836,836,836,836,836,836,836,836,836,836,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
+839,839,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,
+840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,840,841,841,841,841,841,841,841,841,841,841,841,841,
+841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,
+841,841,841,841,841,841,841,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,
+842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,843,843,843,843,843,843,843,
+843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,
+843,843,843,843,843,843,843,843,843,843,843,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,
+844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,844,845,845,
+845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,
+845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,845,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,
+846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,
+846,846,846,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,
+847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,848,848,848,848,848,848,848,848,848,848,848,
+848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,
+848,848,848,848,848,848,848,848,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,
+849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,849,850,850,850,850,850,850,
+850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,850,
+850,850,850,850,850,850,850,850,850,850,850,850,850,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,
+851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,851,852,
+852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,
+852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,852,853,853,853,853,853,853,853,853,853,853,853,853,853,853,
+853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,
+853,853,853,853,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,
+854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,854,855,855,855,855,855,855,855,855,855,
+855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,855,
+855,855,855,855,855,855,855,855,855,855,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,
+856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,856,857,857,857,857,
+857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,
+857,857,857,857,857,857,857,857,857,857,857,857,857,857,857,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,
+859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,859,860,860,860,860,860,860,860,860,860,860,860,860,
+860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,860,
+860,860,860,860,860,860,860,861,861,861,861,861,861,861,861,861,861,861,861,861,861,861,861,861,861,861,861,861,861,861,861,861 };
+
+/* forward declarations */
+void encodeSideInfo( side_info_t  si[2][2] );
+void Huffmancodebits( uint16 *ix, int *xr, side_info_t *gi );
+int  HuffmanCode(int table_select, uint16 *ix, int *xr);
+int  HuffmanCount1(unsigned tbl, uint16 *ix, int *xr );
+int  new_choose_table( uint16 ix[SAMP_PER_FRAME2], uint32 begin, uint32 end );
+void putbits(uint32 val, uint32 nbit);
+int  count_bit(uint16 ix[SAMP_PER_FRAME2], uint32 start, uint32 end, uint32 table );
+int  bigv_bitcount(uint16 ix[SAMP_PER_FRAME2], side_info_t *gi);
+void bigv_tab_select( uint16 ix[SAMP_PER_FRAME2], side_info_t *cod_info );
+void subdivide(side_info_t *cod_info);
+void mdct_sub_int(int sb_sample[2][3][18][SBLIMIT], int (*mdct_freq)[2][SAMP_PER_FRAME2]);
+void filter_subband(int s[SBLIMIT], int off, int k);
+
+void putbits(uint32 val, uint32 nbit)
+{
+  int new_bitpos = CodedData.bitpos + nbit;
+  int ptrpos     = CodedData.bitpos >> 5;
+
+  val = val & (0xffffffff >> (32 - nbit));
+
+  /* data fit in one uint32 */
+  if(((new_bitpos - 1) >> 5) == ptrpos)
+    CodedData.bbuf[ptrpos] |= val << ((32 - new_bitpos) & 31);
+  else
+  {
+    CodedData.bbuf[ptrpos  ] |= val >> ((new_bitpos - 32) & 31);
+    CodedData.bbuf[ptrpos+1]  = val << ((32 - new_bitpos) & 31);
+  }
+
+  CodedData.bitpos = new_bitpos;
+}
+
+/* This is called after a frame of audio has been quantized and coded.
+   It will write the encoded audio to the bitstream. Note that from a
+   layer3 encoder's perspective the bit stream is primarily a series
+   of main_data() blocks, with header and side information inserted at
+   the proper locations to maintain framing. See Figure A.7 in the IS */
+void format_bitstream( uint16 enc[2][2][SAMP_PER_FRAME2],
+                      side_info_t side[2][2], int (*xr)[2][SAMP_PER_FRAME2] )
+{
+  int gr, ch;
+
+  encodeSideInfo( side );
+
+  for(gr=0; gr<2; gr++)
+    for(ch=0; ch<cfg.channels; ch++)
+      Huffmancodebits( &enc[gr][ch][0], &xr[gr][ch][0], &side[gr][ch] );
+}
+
+void encodeSideInfo( side_info_t si[2][2] )
+{
+  int gr, ch, header;
+  
+  header  = 0xfff00000;
+  header |= cfg.mpg.type          << 19; /* mp3 type: 1  */
+  header |= 1                         << 17; /* mp3 layer: 1 */
+  header |= 1                         << 16; /* mp3 crc: 1   */
+  header |= cfg.mpg.bitrate_index << 12;
+  header |= cfg.mpg.smprate_index << 10;
+  header |= cfg.mpg.padding       <<  9;
+  header |= cfg.mpg.mode          <<  6;
+  header |= 1                         <<  2; /* mp3 original: 1 */
+
+  putbits( header, 32 );
+  putbits( 0, cfg.channels == 2 ? 20 : 18 );
+
+  for(gr=0; gr<2; gr++)
+    for(ch=0; ch<cfg.channels; ch++)
+    {
+      side_info_t *gi = &si[gr][ch];
+
+      putbits( gi->part2_3_length,    12 );
+      putbits( gi->big_values,         9 );
+      putbits( gi->global_gain,        8 );
+      putbits( gi->table_select[0],   10 );
+      putbits( gi->table_select[1],    5 );
+      putbits( gi->table_select[2],    5 );
+      putbits( gi->region0_count,      4 );
+      putbits( gi->region1_count,      3 );
+      putbits( gi->table_select[3],    3 );
+    }
+}
+
+/* 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. */
+void Huffmancodebits( uint16 *ix, int *xr, side_info_t *gi )
+{
+  int    region1Start;
+  int    region2Start;
+  int    i, bigvalues, count1End;
+  int    stuffingBits;
+  int    bitsWritten = 0;
+  uint32 scalefac_index;
+
+  /* 1: Write the bigvalues */
+  bigvalues       = gi->big_values << 1;
+  scalefac_index  = gi->region0_count + 1;
+  region1Start    = scalefac[ scalefac_index ];
+  scalefac_index += gi->region1_count + 1;
+  region2Start    = scalefac[ scalefac_index ];
+
+  for(i=0; i<region1Start; i+=2)
+    bitsWritten += HuffmanCode(gi->table_select[0], ix+i, xr+i);
+
+  for(   ; i<region2Start; i+=2)
+    bitsWritten += HuffmanCode(gi->table_select[1], ix+i, xr+i);
+
+  for(   ; i<bigvalues; i+=2)
+    bitsWritten += HuffmanCode(gi->table_select[2], ix+i, xr+i);
+
+  /* 2: Write count1 area */
+  count1End = bigvalues + (gi->count1 << 2);
+  for(i=bigvalues; i<count1End; i+=4)
+    bitsWritten += HuffmanCount1(gi->table_select[3], ix+i, xr+i);
+
+  if((stuffingBits = gi->part2_3_length - bitsWritten) != 0)
+  {
+    int stuffingWords = stuffingBits / 32;
+    int remainingBits = stuffingBits % 32;
+
+    if( remainingBits )
+      putbits( ~0, remainingBits );
+
+    /* Due to the nature of the Huffman code tables, we will pad with ones */
+    while( stuffingWords-- )
+      putbits( ~0, 32 );
+
+    bitsWritten += stuffingBits;
+  }
+}
+
+int HuffmanCount1(unsigned tbl, uint16 *ix, int *xr)
+{
+  uint32  dat, p, s;
+  int     len, v, w, x, y;
+  #define signv (xr[0] < 0 ? 1 : 0)
+  #define signw (xr[1] < 0 ? 1 : 0)
+  #define signx (xr[2] < 0 ? 1 : 0)
+  #define signy (xr[3] < 0 ? 1 : 0)
+
+  v = ix[0];
+  w = ix[1];
+  x = ix[2];
+  y = ix[3];
+  p = v + (w << 1) + (x << 2) + (y << 3);
+
+  switch(p)
+  {
+    default: len = 0; s = 0; break;
+    case  1: len = 1; s = signv; break;
+    case  2: len = 1; s =                signw; break;
+    case  3: len = 2; s = (signv << 1) + signw; break;
+    case  4: len = 1; s =                               signx; break;
+    case  5: len = 2; s = (signv << 1)                + signx; break;
+    case  6: len = 2; s =                (signw << 1) + signx; break;
+    case  7: len = 3; s = (signv << 2) + (signw << 1) + signx; break;
+    case  8: len = 1; s =                                              signy; break;
+    case  9: len = 2; s = (signv << 1)                               + signy; break;
+    case 10: len = 2; s =                (signw << 1)                + signy; break;
+    case 11: len = 3; s = (signv << 2) + (signw << 1)                + signy; break;
+    case 12: len = 2; s =                               (signx << 1) + signy; break;
+    case 13: len = 3; s = (signv << 2)                + (signx << 1) + signy; break;
+    case 14: len = 3; s =                (signw << 2) + (signx << 1) + signy; break;
+    case 15: len = 4; s = (signv << 3) + (signw << 2) + (signx << 1) + signy; break;
+  }
+
+  dat = (ht_count1[tbl][0][p] << len) + s;
+  len =  ht_count1[tbl][1][p];
+  putbits( dat, len );
+
+  return len;
+}
+
+/* Implements the pseudocode of page 98 of the IS */
+int HuffmanCode(int table_select, uint16 *ix, int *xr)
+{
+  unsigned int linbitsx, linbitsy, linbits, idx;
+  const struct huffcodetab *h;
+  int          x, y, bit;
+  uint32       code;
+  #define sign_x (xr[0] < 0 ? 1 : 0)
+  #define sign_y (xr[1] < 0 ? 1 : 0)
+
+  if(table_select == 0)
+    return 0;
+
+  x        = ix[0];
+  y        = ix[1];
+  h        = &ht[table_select];
+  linbits  = h->linbits;
+  linbitsx = linbitsy = 0;
+
+  if( table_select > 15 )
+  { /* ESC-table is used */
+    if(x > 14)  { linbitsx = x - 15;  x = 15; }
+    if(y > 14)  { linbitsy = y - 15;  y = 15; }
+
+    idx  = (x * h->ylen) + y;
+    code = h->table[idx];
+    bit  = h->hlen [idx];
+
+    if(x)
+    {
+      if(x > 14)
+      {
+        code = (code << linbits) | linbitsx;
+        bit += linbits;
+      }
+
+      code = (code << 1) | sign_x;
+      bit += 1;
+    }
+
+    if(y)
+    {
+      if(y > 14)
+      {
+        code = (code << linbits) | linbitsy;
+        bit += linbits;
+      }
+
+      code = (code << 1) | sign_y;
+      bit += 1;
+    }
+  }
+  else
+  { /* No ESC-words */
+    idx  = (x * h->ylen) + y;
+    code = h->table[idx];
+    bit  = h->hlen [idx];
+
+    if(x)
+    {
+      code = (code << 1) | sign_x;
+      bit += 1;
+    }
+
+    if(y)
+    {
+      code = (code << 1) | sign_y;
+      bit += 1;
+    }
+  }
+
+  putbits( code, bit );
+  
+  return bit;
+}
+
+/***************************************************************************/
+/*  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.                                        */
+/***************************************************************************/
+int new_choose_table( uint16 ix[SAMP_PER_FRAME2], uint32 begin, uint32 end )
+{
+  uint32 i;
+  int    max, sum0, sum1, table0, table1;
+  
+  for(i=begin,max=0; i<end; i++)
+    if(ix[i] > max)
+      max = ix[i];
+
+  if(!max)
+    return 0;
+  
+  table0 = 0;
+  table1 = 0;
+  
+  if(max <= 15)
+  {
+    /* try tables with no linbits */
+    /* indx: 0  1  2  3  4  5  6  7  8  9 10 11 12  13 14  15 */
+    /* xlen: 0, 2, 3, 3, 0, 4, 4, 6, 6, 6, 8, 8, 8, 16, 0, 16 */
+    for(table0=0; table0<14; table0++)
+      if(ht[table0].xlen > max)
+        break;
+
+    sum0 = count_bit(ix, begin, end, table0);
+      
+    switch( table0 )
+    {
+      case  2: sum1 = count_bit( ix, begin, end, 3 );
+               if(sum1 <= sum0) table0 = 3;  break;
+
+      case  5: sum1 = count_bit( ix, begin, end, 6 );
+               if(sum1 <= sum0) table0 = 6;  break;
+
+      case  7: sum1 = count_bit( ix, begin, end, 8 );
+               if(sum1 <= sum0)  { table0 = 8; sum0 = sum1; }
+               sum1 = count_bit( ix, begin, end, 9 );
+               if(sum1 <= sum0) table0 = 9;  break;
+        
+      case 10: sum1 = count_bit( ix, begin, end, 11 );
+               if(sum1 <= sum0)  { table0 =11; sum0 = sum1; }
+               sum1 = count_bit( ix, begin, end, 12);
+               if(sum1 <= sum0) table0 = 12; break;
+        
+      case 13: sum1 = count_bit( ix, begin, end, 15 );
+               if(sum1 <= sum0) table0 = 15; break;
+    }
+  }
+  else
+  {
+    /* try tables with linbits */
+    max -= 15;
+
+    /* index : 15   16   17   18   19   20   21   22  23  */
+    /* linmax:  0    1    3    7   15   63  255 1023 8191 */
+    for(table0=15; table0<24; table0++)
+      if(ht[table0].linmax >= max)
+        break;
+
+    /* index : 24   25   26   27   28   29   30   31 */
+    /* linmax: 15   31   63  127  255  511 2047 8191 */
+    for(table1=24; table1<32; table1++)
+      if(ht[table1].linmax >= max)
+        break;
+
+    sum0 = count_bit(ix, begin, end, table0);
+    sum1 = count_bit(ix, begin, end, table1);
+
+    if(sum1 < sum0)
+      table0 = table1;
+  }
+  return table0;
+}
+
+/*************************************************************************/
+/* Function: Count the number of bits necessary to code the subregion.   */
+/*************************************************************************/
+int count_bit(uint16 ix[SAMP_PER_FRAME2], uint32 start, uint32 end, uint32 table)
+{
+  uint32       i;
+  int          sum;
+  int          x, y;
+  unsigned     linbits, ylen;
+  const struct huffcodetab *h;
+
+  h    = &ht[table];
+  sum  = 0;
+  ylen = h->ylen;
+
+  if(table > 15)
+  { // ESC-table is used 
+    linbits = h->linbits;
+    for(i=start; i<end; i+=2)
+    {
+      x = ix[i];
+      y = ix[i+1];
+
+      if(x)
+      {
+        if(x > 14) { x = 15; sum += linbits; }
+        sum++;
+      }
+
+      if(y)
+      {
+        if(y > 14) { y = 15; sum += linbits; }
+        sum++;
+      }
+  
+      sum += h->hlen[(x * ylen) + y];
+    }
+  }
+  else
+  { /* No ESC-words */
+    for(i=start; i<end; i+=2)
+    {
+      x = ix[i];
+      y = ix[i+1];
+
+      sum += h->hlen[(x * ylen) + y];
+
+      if(x) sum++;
+      if(y) sum++;
+    }
+  }
+  
+  return sum;
+}
+
+/*************************************************************************/
+/*   Function: Quantization of the vector xr ( -> ix)                    */
+/*************************************************************************/
+int quantize_int(int xr[SAMP_PER_FRAME2], uint16 ix[SAMP_PER_FRAME2], side_info_t *cod_info)
+{
+  uint32 i, ind, step, frac_pow[] = { 0x80000, 0x6ba28, 0x5a828, 0x4c1c0 };
+
+  step = frac_pow[cod_info->quantizerStepSize & 3] >> cod_info->quantizerStepSize / 4;
+
+  for(i=SAMP_PER_FRAME2; i--; )
+  {
+    ind = (abs(xr[i]) * step + 32768) >> 16;
+
+    if(ind < 5000)
+      ix[i] = int2idx[ind];
+    else
+      if(ind < 32768)
+        ix[i] = int3idx[ind];
+      else
+        return 0;
+  }
+
+  return 1;
+}
+
+/*************************************************************************/
+/* Function: Calculation of rzero, count1, big_values                    */
+/* (Partitions ix into big values, quadruples and zeros).                */
+/*************************************************************************/
+int calc_runlen( uint16 ix[SAMP_PER_FRAME2], side_info_t *cod_info )
+{
+  int  p, i, sum0 = 0, sum1 = 0;
+
+  for(i=SAMP_PER_FRAME2; i-=2; )
+    if(ix[i-1] | ix[i-2])
+      break;
+
+  cod_info->count1 = 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)
+    {
+      p = (y) + (x<<1) + (w<<2) + (v<<3);
+
+      sum0 += ht_count1[0][1][p]; /* add table0 hlength */
+      sum1 += ht_count1[1][1][p]; /* add table1 hlength */
+
+      cod_info->count1++;
+    }
+    else break;
+  }
+
+  cod_info->big_values = i >> 1;
+
+  if(sum0 < sum1)
+  {
+    cod_info->table_select[3] = 0;
+    return sum0;
+  }
+  else
+  {
+    cod_info->table_select[3] = 1;
+    return sum1;
+  }
+}
+
+/*************************************************************************/
+/* presumable subdivides the bigvalue region which will use separate Huffman tables */
+/*************************************************************************/
+void subdivide(side_info_t *cod_info)
+{
+  int scfb_anz = 0;
+  int bigvalues_region;
+  int thiscount, index;
+  
+  if( !cod_info->big_values )
+  { /* no big_values region */
+    cod_info->region0_count = 0;
+    cod_info->region1_count = 0;
+  }
+  else
+  {
+    bigvalues_region = 2 * cod_info->big_values;
+    
+    /* Calculate scfb_anz */
+    while( scalefac[scfb_anz] < bigvalues_region )
+      scfb_anz++;
+      
+    cod_info->region0_count = subdv_table[scfb_anz].region0_count;
+    thiscount = cod_info->region0_count;
+    index = thiscount + 1;
+    while(thiscount && (scalefac[index] > bigvalues_region))
+    {
+      thiscount--;
+      index--;
+    }
+    cod_info->region0_count = thiscount;
+    cod_info->region1_count = subdv_table[scfb_anz].region1_count;
+    index = cod_info->region0_count + cod_info->region1_count + 2;
+    thiscount = cod_info->region1_count;
+    while(thiscount && (scalefac[index] > bigvalues_region))
+    {
+      thiscount--;
+      index--;
+    }
+    cod_info->region1_count = thiscount;
+    cod_info->address1 = scalefac[cod_info->region0_count+1];
+    cod_info->address2 = scalefac[cod_info->region0_count+cod_info->region1_count+2];
+    cod_info->address3 = bigvalues_region;
+  }
+}
+
+/*************************************************************************/
+/*   Function: Select huffman code tables for bigvalues regions */
+/*************************************************************************/
+void bigv_tab_select( uint16 ix[SAMP_PER_FRAME2], side_info_t *cod_info )
+{
+  cod_info->table_select[0] = 0;
+  cod_info->table_select[1] = 0;
+  cod_info->table_select[2] = 0;
+  
+  if( cod_info->address1 > 0 )
+    cod_info->table_select[0] = new_choose_table(ix,         0         , cod_info->address1);
+    
+  if( cod_info->address2 > cod_info->address1 )
+    cod_info->table_select[1] = new_choose_table(ix, cod_info->address1, cod_info->address2);
+    
+  if( cod_info->big_values<<1 > cod_info->address2 )
+    cod_info->table_select[2] = new_choose_table(ix, cod_info->address2, cod_info->big_values<<1);
+}
+
+/*************************************************************************/
+/* Function: Count the number of bits necessary to code the bigvalues region */
+/*************************************************************************/
+int bigv_bitcount(uint16 ix[SAMP_PER_FRAME2], side_info_t *gi)
+{
+  int bits = 0;
+  uint32 table;
+
+  if((table=gi->table_select[0]))  /* region0 */
+    bits += count_bit(ix,     0       , gi->address1, table);
+
+  if((table=gi->table_select[1]))  /* region1 */
+    bits += count_bit(ix, gi->address1, gi->address2, table);
+
+  if((table=gi->table_select[2]))  /* region2 */
+    bits += count_bit(ix, gi->address2, gi->address3, table);
+
+  return bits;
+}
+
+int quantcnt;
+
+/* Speed up the outer_loop code which is called by iteration_loop.
+   The outer_loop function precedes the call to the function inner_loop
+   with a call to bin_search gain defined below,
+   which returns a good starting quantizerStepSize. */
+int quantize_and_count_bits(int xr[SAMP_PER_FRAME2], uint16 ix[SAMP_PER_FRAME2], side_info_t *cod_info)
+{
+  int bits = 10000;
+
+  quantcnt++;
+
+  if(quantize_int(xr, ix, cod_info))
+  {
+    bits = calc_runlen(ix, cod_info);        /* rzero,count1,big_values*/
+    subdivide(cod_info);                     /* bigvalues sfb division */
+    bigv_tab_select(ix,cod_info);        /* codebook selection*/
+    bits += bigv_bitcount(ix,cod_info);  /* bit count */
+  }
+
+  return bits;
+}
+
+/******************************************************************************/
+/* The code selects the best quantizerStepSize for a particular set of scalefacs                                                            */
+/******************************************************************************/ 
+int inner_loop_int(int xr[2][2][SAMP_PER_FRAME2], int max_bits, side_info_t *cod_info, int gr, int ch )
+{
+  int   *xrs;  /* int[SAMP_PER_FRAME2] *xr; */
+  uint16 *ix;   /* int[SAMP_PER_FRAME2] *ix; */
+  int   bits;
+
+  xrs = &xr[gr][ch][0];
+  ix  = enc_data[gr][ch];
+
+  while((bits=quantize_and_count_bits(xrs, ix, cod_info)) < max_bits-64)
+  {
+    if(cod_info->quantizerStepSize == 0)
+      break;
+
+    if(cod_info->quantizerStepSize <= 2)
+      cod_info->quantizerStepSize = 0;
+    else
+      cod_info->quantizerStepSize -= 2;
+  }
+
+  while(bits > max_bits)
+  {
+    cod_info->quantizerStepSize++;
+    bits = quantize_and_count_bits(xrs, ix, cod_info);
+  }
+
+  return bits;
+}
+
+/************************************************************************/
+/*  iteration_loop()                                                    */
+/************************************************************************/
+void iteration_loop(int mdct_freq_org[2][2][SAMP_PER_FRAME2], side_info_t cod_info[2][2], int mean_bits)
+{
+  int     max_bits;
+  int     ch, gr;
+  int     ResvSize = 0; /* Layer3 bit reservoir: Described in C.1.5.4.2.2 of the IS */
+  
+  for(gr=2; gr--; )
+  {
+    for(ch=cfg.channels; ch--; )
+    {
+      /* calculation of number of available bit( per granule ) */
+      max_bits = mean_bits / cfg.channels;
+
+      cod_info[gr][ch].big_values      = 0;
+      cod_info[gr][ch].count1          = 0;
+      cod_info[gr][ch].table_select[0] = 0;
+      cod_info[gr][ch].table_select[1] = 0;
+      cod_info[gr][ch].table_select[2] = 0;
+      cod_info[gr][ch].region0_count   = 0;
+      cod_info[gr][ch].region1_count   = 0;
+      cod_info[gr][ch].table_select[3] = 0;
+      cod_info[gr][ch].part2_3_length  = inner_loop_int(mdct_freq_org, max_bits, &cod_info[gr][ch], gr, ch);
+      cod_info[gr][ch].global_gain     = cod_info[gr][ch].quantizerStepSize + 210 - 0x40;
+
+      /* Readjusts the size of the reservoir to reflect the granule's usage */
+      ResvSize += max_bits - cod_info[gr][ch].part2_3_length;
+    }
+  }
+  
+/* Makes sure that the reservoir size is within limits, possibly by adding
+   stuffing bits. Note that stuffing bits are added by increasing a granule's
+   part2_3_length */
+  cod_info[0][0].part2_3_length += ResvSize;
+}
+
+/*-------------------------------------------------------------------*/
+/*   Function: Calculation of the MDCT                               */
+/*   In the case of long blocks ( block_type 0,1,3 ) there are       */
+/*   36 coefficents in the time domain and 18 in the frequency       */
+/*   domain.                                                         */
+/*-------------------------------------------------------------------*/
+
+/* TODO: This MDCT implementation is very crude, and should be replaced by
+   a completely different algorithm. */
+void mdct_int( int *in, int *out )
+{
+  int m, tmp=0;
+  
+  for(m=18; m--; )
+  {
+#ifdef CPU_COLDFIRE
+    { int *wint  = win_int[m];
+      int *indat = in;
+
+      asm volatile(
+      "movem.l (%[indat]), %%d0-%%d7\n"
+      "move.l (%[wint])+, %%a5\n"
+      "mac.l %%d0, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d1, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d2, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d3, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d4, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d5, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d6, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d7, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "movem.l (32,%[indat]), %%d0-%%d7\n"
+      "mac.l %%d0, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d1, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d2, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d3, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d4, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d5, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d6, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d7, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "movem.l (64,%[indat]), %%d0-%%d7\n"
+      "mac.l %%d0, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d1, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d2, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d3, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d4, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d5, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d6, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d7, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "movem.l (96,%[indat]), %%d0-%%d7\n"
+      "mac.l %%d0, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d1, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d2, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d3, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d4, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d5, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d6, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d7, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "movem.l (128,%[indat]), %%d0-%%d3\n"
+      "mac.l %%d0, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d1, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d2, %%a5, (%[wint])+, %%a5, %%acc0\n"
+      "mac.l %%d3, %%a5, %%acc0\n"
+      "movclr.l %%acc0, %[tmp]"
+        : [wint] "+a" (wint), [tmp] "+r" (tmp) : [indat] "a" (indat)
+        : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a5");
+    }
+#else
+    int k;
+    for(k=36,tmp=0; k--; )
+      tmp += in[k] * win_int[m][k];
+#endif
+    out[m] = (tmp + 16384) >> 15;
+  }
+}
+
+
+void mdct_sub_int(int sb_sample[2][3][18][SBLIMIT], int (*mdct_freq)[2][SAMP_PER_FRAME2])
+{
+  int (*mdct_enc)[2][32][18] = (int (*)[2][32][18]) mdct_freq;
+  int ch, gr, band, k, bu, bd;
+  
+  for(gr=0; gr<2; gr++)
+    for(ch=cfg.channels; ch--; )
+    {
+      /* 576=4*16*9: Compensate for inversion in the analysis filter */
+      for(band=33; (band-=2)>0; )
+        for(k=19; (k-=2)>0; )
+          sb_sample[ch][gr+1][k][band] = -sb_sample[ch][gr+1][k][band];
+
+      /* 82944=4*32*648: Perform imdct of 18 previous subband samples + 18 current subband samples */
+      for(band=32; band--; )
+      {
+        for(k=18; k--; )
+        {
+          mdct_in[k]    = sb_sample[ch][ gr ][k][band];
+          mdct_in[k+18] = sb_sample[ch][gr+1][k][band];
+        }
+
+        mdct_int(mdct_in, &mdct_enc[gr][ch][band][0]);
+      }
+
+      /* 1024=4*256: Perform aliasing reduction butterfly*/
+      for(band=31; band--; )
+        for(k=8; k--; )
+        {
+          bu = mdct_enc[gr][ch][band][17-k] * cs_int[k] + mdct_enc[gr][ch][band+1][k]  * ca_int[k];
+          bd = mdct_enc[gr][ch][band+1][k]  * cs_int[k] - mdct_enc[gr][ch][band][17-k] * ca_int[k];
+          mdct_enc[gr][ch][band][17-k] = (bu + 16384) >> 15;
+          mdct_enc[gr][ch][band+1][k]  = (bd + 16384) >> 15;
+        }
+    }
+
+  /* Save latest granule's subband samples to be used in the next mdct call */
+  for(ch=cfg.channels ;ch--; )
+    memcpy(sb_sample[ch][0], sb_sample[ch][2], 18 * 32 * sizeof(int));
+}
+
+void fill_subband(long *buffer, int off)
+{
+  long i, t;
+
+  /* replace 32 oldest left/right samples with 32 new samples */
+  if(enc_channels == 2)
+  {
+    for(i=32; i--; )
+    {
+      t = *buffer++;
+      x_int0[i+off] = (short)(t >> 16);
+      x_int1[i+off] = (short)t;
+    }
+  }
+  else
+  {
+    for(i=32; i--; )
+    {
+      t = *buffer++;
+      x_int0[i+off] = (short)((((t<<16)>>16) + (t>>16)) >> 1);
+    }
+  }
+}
+
+void filter_subband(int s[SBLIMIT], int off, int k)
+{
+  short *enwindow = enwindow_int;
+  int   i, tmp = 0;
+#ifdef CPU_COLDFIRE 
+  int   reg_buff[14]; /* register storage buffer */
+#endif
+
+  /* 36864=72*512: shift samples into proper window positions */
+#ifdef CPU_COLDFIRE
+  { short *xint = &x_int[k][off];
+    short *yint = y_int;
+
+    asm volatile ("movem.l %%d0/%%d2-%%d7/%%a2-%%a7,%0\n" : "=m" (*(int*)reg_buff));
+    asm volatile(
+    "moveq.l #32, %%d0\n"
+    "move.l %%d0, %[i]\n"                 /* set loop counter */
+    "move.l %[xint], %%d0\n"              /* d0 = x_int[k]   */
+    "or.l #0x3ff, %%d0\n"
+    "move.l %%d0, %%mask\n"               /* set address mask */
+    "move.l (%[xint]), %%d4\n"            /* d4 =  x_int[k][off] */
+
+  "loop_start:\n"
+    "movem.l (%[enwindow]), %%d0-%%d3\n"  /* load 4 values */
+    "mac.w %%d0u, %%d4u, (0x080,%[xint])&, %%d5, %%acc0\n"
+    "mac.w %%d0l, %%d5u, (0x100,%[xint])&, %%d6, %%acc0\n"
+    "mac.w %%d1u, %%d6u, (0x180,%[xint])&, %%d7, %%acc0\n"
+    "mac.w %%d1l, %%d7u, (0x200,%[xint])&, %%a2, %%acc0\n"
+    "mac.w %%d2u, %%a2u, (0x280,%[xint])&, %%a3, %%acc0\n"
+    "mac.w %%d2l, %%a3u, (0x300,%[xint])&, %%a4, %%acc0\n"
+    "mac.w %%d3u, %%a4u, (0x380,%[xint])&, %%a5, %%acc0\n"
+    "mac.w %%d3l, %%a5u,                         %%acc0\n"
+
+    "movem.l (16,%[enwindow]), %%d0-%%d3\n" /* load 8 values */
+    "mac.w %%d0u, %%d4l, %%acc1\n"
+    "mac.w %%d0l, %%d5l, %%acc1\n"
+    "mac.w %%d1u, %%d6l, %%acc1\n"
+    "mac.w %%d1l, %%d7l, %%acc1\n"
+    "mac.w %%d2u, %%a2l, %%acc1\n"
+    "mac.w %%d2l, %%a3l, %%acc1\n"
+    "mac.w %%d3u, %%a4l, %%acc1\n"
+    "addq.l #4, %[xint]\n"                  /* xint += 2 */
+    "mac.w %%d3l, %%a5l, (%[xint])&, %%d4, %%acc1\n"
+
+    "movclr.l %%acc0, %%d5\n"
+    "movclr.l %%acc1, %%d6\n"
+    "move.l #262144, %%d7\n"
+    "add.l %%d7, %%d5\n"
+    "add.l %%d7, %%d6\n"
+    "moveq.l #19, %%d7\n"
+    "asr.l %%d7, %%d5\n"
+    "asr.l %%d7, %%d6\n"
+    "move.w %%d5, (%[yint])+\n"
+    "move.w %%d6, (%[yint])+\n"
+
+    "add.l #32, %[enwindow]\n"              /* enwindow += 16 */
+
+    "sub.l #1, %[i]\n"
+    "jbne loop_start\n"
+
+    : [xint] "+a" (xint), [yint] "+a" (yint), [i] "+m" (i)
+    : [enwindow] "a" (enwindow)
+    : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a2", "a3", "a4", "a5");
+
+    asm volatile ("movem.l %0,%%d0/%%d2-%%d7/%%a2-%%a7\n" : : "m" (*(int*)reg_buff));
+  }
+#else
+  for(i=0; i<64; i++)
+  {
+    for(j=0, tmp=0; j<512; j+=64)
+      tmp += (int)x_int[k][(i+j+off)&(HAN_SIZE-1)] * (int)*(enwindow++);
+    y_int[i] = (short)((tmp + (1<<18)) >> 19);
+  }
+#endif
+    
+  /* 147456=72*2048 */
+  for(i=SBLIMIT; i--; ) // SBLIMIT: 32
+  {
+    short *filt = filter_int[i];
+
+#ifdef CPU_COLDFIRE
+    {
+      asm volatile(
+      "move.l (%[yint])+, %%a5\n"
+      "movem.l (%[filt]), %%d0-%%d7\n"
+      "mac.w %%d0u, %%a5u,                   %%acc0\n"
+      "mac.w %%d0l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d1u, %%a5u,                   %%acc0\n"
+      "mac.w %%d1l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d2u, %%a5u,                   %%acc0\n"
+      "mac.w %%d2l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d3u, %%a5u,                   %%acc0\n"
+      "mac.w %%d3l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d4u, %%a5u,                   %%acc0\n"
+      "mac.w %%d4l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d5u, %%a5u,                   %%acc0\n"
+      "mac.w %%d5l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d6u, %%a5u,                   %%acc0\n"
+      "mac.w %%d6l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d7u, %%a5u,                   %%acc0\n"
+      "mac.w %%d7l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "movem.l (32,%[filt]), %%d0-%%d7\n"
+      "mac.w %%d0u, %%a5u,                   %%acc0\n"
+      "mac.w %%d0l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d1u, %%a5u,                   %%acc0\n"
+      "mac.w %%d1l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d2u, %%a5u,                   %%acc0\n"
+      "mac.w %%d2l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d3u, %%a5u,                   %%acc0\n"
+      "mac.w %%d3l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d4u, %%a5u,                   %%acc0\n"
+      "mac.w %%d4l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d5u, %%a5u,                   %%acc0\n"
+      "mac.w %%d5l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d6u, %%a5u,                   %%acc0\n"
+      "mac.w %%d6l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d7u, %%a5u,                   %%acc0\n"
+      "mac.w %%d7l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "movem.l (64,%[filt]), %%d0-%%d7\n"
+      "mac.w %%d0u, %%a5u,                   %%acc0\n"
+      "mac.w %%d0l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d1u, %%a5u,                   %%acc0\n"
+      "mac.w %%d1l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d2u, %%a5u,                   %%acc0\n"
+      "mac.w %%d2l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d3u, %%a5u,                   %%acc0\n"
+      "mac.w %%d3l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d4u, %%a5u,                   %%acc0\n"
+      "mac.w %%d4l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d5u, %%a5u,                   %%acc0\n"
+      "mac.w %%d5l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d6u, %%a5u,                   %%acc0\n"
+      "mac.w %%d6l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d7u, %%a5u,                   %%acc0\n"
+      "mac.w %%d7l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "movem.l (96,%[filt]), %%d0-%%d7\n"
+      "mac.w %%d0u, %%a5u,                   %%acc0\n"
+      "mac.w %%d0l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d1u, %%a5u,                   %%acc0\n"
+      "mac.w %%d1l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d2u, %%a5u,                   %%acc0\n"
+      "mac.w %%d2l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d3u, %%a5u,                   %%acc0\n"
+      "mac.w %%d3l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d4u, %%a5u,                   %%acc0\n"
+      "mac.w %%d4l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d5u, %%a5u,                   %%acc0\n"
+      "mac.w %%d5l, %%a5l, (%[yint])+, %%a5, %%acc0\n"
+      "mac.w %%d6u, %%a5u,                   %%acc0\n"
+      "mac.w %%d6l, %%a5l, (%[yint]) , %%a5, %%acc0\n"
+      "mac.w %%d7u, %%a5u,                   %%acc0\n"
+      "mac.w %%d7l, %%a5l,                   %%acc0\n"
+      "lea.l (-31*4, %[yint]), %[yint]\n" /* wrap yint back to start */
+      "movclr.l %%acc0, %[tmp]"
+      : [tmp] "=r" (tmp) : [filt] "a" (filt), [yint] "a" (y_int)
+      : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a5" );
+    }
+#else
+    for(j=64, tmp=0; j--; )
+      tmp += (long)filt[j] * (long)y_int[j];
+#endif
+    s[i] = (tmp + 16384) >> 15;
+  }
+}
+
+static int find_bitrate_index(int bitrate)
+{
+    static long mpeg1[15] = {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320};
+    int i;
+
+    for(i=0; i<15; i++)
+        if(bitrate == mpeg1[i])
+            return i;
+
+    return -1;
+}
+
+static int find_samplerate_index(long freq)
+{
+    static long mpeg1[3] = {44100, 48000, 32000};
+    int i;
+
+    for(i=0; i<3; i++)
+        if(freq == mpeg1[i])
+            return i;
+
+    return -1;
+}
+
+void init_mp3_encoder_engine(bool stereo, int quality)
+{
+    /* keep in sync with rec_quality_info_afmt in id3.h/.c */
+    static int bitr_s[9] = { 64, 96, 128, 160, 192, 224, 320, 64, 64 };
+    static int bitr_m[9] = { 64, 96, 128, 160, 160, 160, 160, 64, 64 };
+    uint32     avg_byte_per_frame;
+
+    cfg.byte_order        = order_bigEndian;
+    cfg.mpg.type          = 1;
+    cfg.samplerate        = 44100;
+    cfg.channels          = stereo ? 2 : 1;
+    cfg.mpg.mode          = stereo ? 0 : 3; /* 0=stereo, 3=mono */
+    cfg.mpg.bitrate       = stereo ? bitr_s[quality] : bitr_m[quality];
+    cfg.mpg.bitrate_index = find_bitrate_index(cfg.mpg.bitrate);
+    cfg.mpg.smprate_index = find_samplerate_index(cfg.samplerate);
+
+    memset(x_int0      , 0                 , sizeof(x_int0      ));
+    memset(x_int1      , 0                 , sizeof(x_int1      ));
+    memset(y_int       , 0                 , sizeof(y_int       ));
+    memset(mdct_freq   , 0                 , sizeof(mdct_freq   ));
+    memset(enc_data    , 0                 , sizeof(enc_data    ));
+    memset(mdct_in     , 0                 , sizeof(mdct_in     ));
+    memset(sb_sample   , 0                 , sizeof(sb_sample   ));
+    memset(&CodedData  , 0                 , sizeof(CodedData   ));
+    memcpy(scalefac, sfBand[cfg.mpg.smprate_index + 3*cfg.mpg.type], sizeof(scalefac));
+    memcpy(ca_int      , ca_int_const      , sizeof(ca_int      ));
+    memcpy(cs_int      , cs_int_const      , sizeof(cs_int      ));
+    memcpy(win_int     , win_int_const     , sizeof(win_int     ));
+    memcpy(filter_int  , filter_int_const  , sizeof(filter_int  ));
+    memcpy(enwindow_int, enwindow_int_const, sizeof(enwindow_int));
+    memcpy(int2idx     , int2idx_const     , sizeof(int2idx     ));
+    memcpy(ht_count1   , ht_count1_const   , sizeof(ht_count1   ));
+    memcpy( t1HB       , t1HB_const        , sizeof(t1HB        ));
+    memcpy( t2HB       , t2HB_const        , sizeof(t2HB        ));
+    memcpy( t3HB       , t3HB_const        , sizeof(t3HB        ));
+    memcpy( t5HB       , t5HB_const        , sizeof(t5HB        ));
+    memcpy( t6HB       , t6HB_const        , sizeof(t6HB        ));
+    memcpy( t7HB       , t7HB_const        , sizeof(t7HB        ));
+    memcpy( t8HB       , t8HB_const        , sizeof(t8HB        ));
+    memcpy( t9HB       , t9HB_const        , sizeof(t9HB        ));
+    memcpy(t10HB       , t10HB_const       , sizeof(t10HB       ));
+    memcpy(t11HB       , t11HB_const       , sizeof(t11HB       ));
+    memcpy(t12HB       , t12HB_const       , sizeof(t12HB       ));
+    memcpy(t13HB       , t13HB_const       , sizeof(t13HB       ));
+    memcpy(t15HB       , t15HB_const       , sizeof(t15HB       ));
+    memcpy(t16HB       , t16HB_const       , sizeof(t16HB       ));
+    memcpy(t24HB       , t24HB_const       , sizeof(t24HB       ));
+    memcpy( t1l        , t1l_const         , sizeof(t1l         ));
+    memcpy( t2l        , t2l_const         , sizeof(t2l         ));
+    memcpy( t3l        , t3l_const         , sizeof(t3l         ));
+    memcpy( t5l        , t5l_const         , sizeof(t5l         ));
+    memcpy( t6l        , t6l_const         , sizeof(t6l         ));
+    memcpy( t7l        , t7l_const         , sizeof(t7l         ));
+    memcpy( t8l        , t8l_const         , sizeof(t8l         ));
+    memcpy( t9l        , t9l_const         , sizeof(t9l         ));
+    memcpy(t10l        , t10l_const        , sizeof(t10l        ));
+    memcpy(t11l        , t11l_const        , sizeof(t11l        ));
+    memcpy(t12l        , t12l_const        , sizeof(t12l        ));
+    memcpy(t13l        , t13l_const        , sizeof(t13l        ));
+    memcpy(t15l        , t15l_const        , sizeof(t15l        ));
+    memcpy(t16l        , t16l_const        , sizeof(t16l        ));
+    memcpy(t24l        , t24l_const        , sizeof(t24l        ));
+    memcpy(ht          , ht_const          , sizeof(ht          ));
+    
+  /* I don't know, wether this is really necessary */
+    ht[ 0].table =  NULL;  ht[ 0].hlen = NULL;// Apparently not used
+    ht[ 1].table =  t1HB;  ht[ 1].hlen =  t1l;
+    ht[ 2].table =  t2HB;  ht[ 2].hlen =  t2l;
+    ht[ 3].table =  t3HB;  ht[ 3].hlen =  t3l;
+    ht[ 4].table =  NULL;  ht[ 4].hlen = NULL;// Apparently not used
+    ht[ 5].table =  t5HB;  ht[ 5].hlen =  t5l;
+    ht[ 6].table =  t6HB;  ht[ 6].hlen =  t6l;
+    ht[ 7].table =  t7HB;  ht[ 7].hlen =  t7l;
+    ht[ 8].table =  t8HB;  ht[ 8].hlen =  t8l;
+    ht[ 9].table =  t9HB;  ht[ 9].hlen =  t9l;
+    ht[10].table = t10HB;  ht[10].hlen = t10l;
+    ht[11].table = t11HB;  ht[11].hlen = t11l;
+    ht[12].table = t12HB;  ht[12].hlen = t12l;
+    ht[13].table = t13HB;  ht[13].hlen = t13l;
+    ht[14].table =  NULL;  ht[14].hlen = NULL;// Apparently not used
+    ht[15].table = t15HB;  ht[15].hlen = t15l;
+    ht[16].table = t16HB;  ht[16].hlen = t16l;
+    ht[17].table = t16HB;  ht[17].hlen = t16l;
+    ht[18].table = t16HB;  ht[18].hlen = t16l;
+    ht[19].table = t16HB;  ht[19].hlen = t16l;
+    ht[20].table = t16HB;  ht[20].hlen = t16l;
+    ht[21].table = t16HB;  ht[21].hlen = t16l;
+    ht[22].table = t16HB;  ht[22].hlen = t16l;
+    ht[23].table = t16HB;  ht[23].hlen = t16l;
+    ht[24].table = t24HB;  ht[24].hlen = t24l;
+    ht[25].table = t24HB;  ht[25].hlen = t24l;
+    ht[26].table = t24HB;  ht[26].hlen = t24l;
+    ht[27].table = t24HB;  ht[27].hlen = t24l;
+    ht[28].table = t24HB;  ht[28].hlen = t24l;
+    ht[29].table = t24HB;  ht[29].hlen = t24l;
+    ht[30].table = t24HB;  ht[30].hlen = t24l;
+    ht[31].table = t24HB;  ht[31].hlen = t24l;
+    
+    x_int[0] = x_int0;
+    x_int[1] = x_int1;
+    
+#ifndef SIMULATOR
+    if(((long)x_int0 | (long)x_int1) & 0x7ff)
+        return; /* both arrays must be aligned to 0x800 boundary */
+#endif
+    
+    if(cfg.channels == 1)
+        cfg.sideinfo_len = 32 + 136;
+    else
+        cfg.sideinfo_len = 32 + 256;
+    
+    /* Set initial step size */
+    cfg.cod_info[0][0].quantizerStepSize = 0x10;
+    cfg.cod_info[0][1].quantizerStepSize = 0x10;
+    cfg.cod_info[1][0].quantizerStepSize = 0x10;
+    cfg.cod_info[1][1].quantizerStepSize = 0x10;
+    
+    /* Figure average number of 'byte' per frame. */
+    avg_byte_per_frame = (uint32)(SAMP_PER_FRAME * 8000 * cfg.mpg.bitrate) / cfg.samplerate;
+    cfg.byte_per_frame = avg_byte_per_frame / 64;
+    cfg.frac_per_frame = avg_byte_per_frame % 64;
+    cfg.slot_lag       = 0;
+}
+
+/* this is the codec entry point */
+enum codec_status codec_start(struct codec_api* api)
+{
+    int      i, off=0, gr, channel;
+    long     *buffer;
+    int      chunk_size, num_chunks;
+    int      enc_buffer_size;
+    int      enc_quality;
+    uint32   *mp3_chunk_ptr;
+    bool     cpu_boosted = true; /* start boosted */
+
+    /* Generic codec initialisation */
+    ci = api;
+
+    if(ci->enc_get_inputs          == NULL ||
+       ci->enc_set_parameters      == NULL ||
+       ci->enc_alloc_chunk         == NULL ||
+       ci->enc_free_chunk          == NULL ||
+       ci->enc_wavbuf_near_empty   == NULL ||
+       ci->enc_get_wav_data        == NULL ||
+       ci->enc_set_header_callback == NULL )
+        return CODEC_ERROR;
+
+    ci->cpu_boost(true);
+
+    *ci->enc_set_header_callback = NULL;
+    ci->enc_get_inputs(&enc_buffer_size, &enc_channels, &enc_quality);
+
+    init_mp3_encoder_engine(enc_channels == 2, enc_quality);
+
+    /* must be 4byte aligned */
+    chunk_size = (sizeof(long) + cfg.byte_per_frame + 1 + 3) & ~3;
+    num_chunks = enc_buffer_size / chunk_size;
+
+    /* inform the main program about the buffer dimensions */
+    ci->enc_set_parameters(chunk_size, num_chunks, SAMP_PER_FRAME,
+        NULL, 0, AFMT_MPA_L3);
+
+#ifdef CPU_COLDFIRE
+    asm volatile ("move.l #0, %macsr"); /* integer mode */
+#endif
+
+    /* main application waits for this flag during encoder loading */
+    ci->enc_codec_loaded = true;
+
+    /* main encoding loop */
+    while(!ci->stop_codec)
+    {
+        while((buffer = (long*)ci->enc_get_wav_data(SAMP_PER_FRAME*4)) != NULL)
+        {
+            if(ci->stop_codec)
+                break;
+
+            if(ci->enc_wavbuf_near_empty() == 0)
+            {
+                if(!cpu_boosted)
+                {
+                    ci->cpu_boost(true);
+                    cpu_boosted = true;
+                }
+            }
+
+            /* encode one mp3 frame in this loop */
+            CodedData.bitpos  = 0;
+            memset(CodedData.bbuf, 0, sizeof(CodedData.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.mpg.bits_per_frame = 8 * (cfg.byte_per_frame + cfg.mpg.padding);
+            cfg.mean_bits = (cfg.mpg.bits_per_frame - cfg.sideinfo_len) >> 1;
+            
+            /* polyphase filtering */
+            for(gr=0; gr<2; gr++)
+            {
+                for(i=0; i<18; i++)
+                {
+                    fill_subband(buffer, off);
+
+                    for(channel=cfg.channels; channel--; )
+                        filter_subband(&sb_sample[channel][gr+1][i][0], off, channel);
+
+                    buffer += 32;
+                    off = (off + 480) & (HAN_SIZE-1); /* offset is modulo HAN_SIZE */
+                }
+            }
+
+            mdct_sub_int(sb_sample, mdct_freq);
+
+            /* bit and noise allocation */
+            iteration_loop(mdct_freq, cfg.cod_info, cfg.mean_bits);
+
+            /* write the frame to the bitstream */
+            format_bitstream(enc_data, cfg.cod_info, mdct_freq);
+
+            /* allocate mp3 chunk, set chunk size, copy chunk to enc_buffer */
+            mp3_chunk_ptr    = (uint32*)ci->enc_alloc_chunk();
+            mp3_chunk_ptr[0] = (CodedData.bitpos + 7) >> 3;
+            memcpy(&mp3_chunk_ptr[1], CodedData.bbuf, mp3_chunk_ptr[0]);
+            ci->enc_free_chunk();
+            ci->yield();
+        }
+
+        if(ci->enc_wavbuf_near_empty())
+        {
+            if(cpu_boosted)
+            {
+                ci->cpu_boost(false);
+                cpu_boosted = false;
+            }
+        }
+        ci->yield();
+    }
+
+    if(cpu_boosted) /* set initial boost state */
+        ci->cpu_boost(false);
+
+    /* reset parameters to initial state */
+    ci->enc_set_parameters(0, 0, 0, 0, 0, 0);
+
+    /* main application waits for this flag during encoder removing */
+    ci->enc_codec_loaded = false;
+
+    return CODEC_OK;
+}
+#endif
diff --git a/apps/codecs/wav_enc.c b/apps/codecs/wav_enc.c
new file mode 100644
index 0000000..5aabb5d
--- /dev/null
+++ b/apps/codecs/wav_enc.c
@@ -0,0 +1,172 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Antonius Hellmann
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef SIMULATOR
+
+#include "codeclib.h"
+
+CODEC_HEADER
+
+static struct codec_api *ci;
+static    int enc_channels;
+
+#define CHUNK_SIZE 8192
+
+static unsigned char wav_header[44] =
+{'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
+ 0,0,0,1,0,2,0,0x44,0xac,0,0,0x10,0xb1,2,0,4,0,16,0,'d','a','t','a',0,0,0,0};
+
+static unsigned char wav_header_mono[44] =
+{'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
+ 0,0,0,1,0,1,0,0x44,0xac,0,0,0x88,0x58,1,0,2,0,16,0,'d','a','t','a',0,0,0,0};
+
+/* update file header info callback function (called by main application)  */
+void enc_set_header(void *head_buffer,  /* ptr to the file header data     */
+                   int head_size,       /* size of this header data        */
+                   int num_pcm_samples, /* amount of processed pcm samples */
+                   bool is_file_header)
+{
+    int num_file_bytes = num_pcm_samples * 2 * enc_channels;
+
+    if(is_file_header)
+    {
+        /* update file header before file closing */
+        if((int)sizeof(wav_header) < head_size)
+        {
+            /* update wave header size entries: special to WAV format */
+            *(long*)(head_buffer+ 4) = htole32(num_file_bytes + 36);
+            *(long*)(head_buffer+40) = htole32(num_file_bytes);
+        }
+    }
+}
+
+/* main codec entry point */
+enum codec_status codec_start(struct codec_api* api)
+{
+    int            i;
+    long           lr;
+    unsigned long  t;
+    unsigned long  *src;
+    unsigned long  *dst;
+    int            chunk_size, num_chunks, samp_per_chunk;
+    int            enc_buffer_size;
+    int            enc_quality;
+    bool           cpu_boosted = true; /* start boosted */
+
+    ci = api; // copy to global api pointer
+
+    if(ci->enc_get_inputs          == NULL ||
+       ci->enc_set_parameters      == NULL ||
+       ci->enc_alloc_chunk         == NULL ||
+       ci->enc_free_chunk          == NULL ||
+       ci->enc_wavbuf_near_empty   == NULL ||
+       ci->enc_get_wav_data        == NULL ||
+       ci->enc_set_header_callback == NULL )
+        return CODEC_ERROR;
+
+    ci->cpu_boost(true);
+
+    *ci->enc_set_header_callback = enc_set_header;
+    ci->enc_get_inputs(&enc_buffer_size, &enc_channels, &enc_quality);
+
+    /* configure the buffer system */
+    chunk_size     = sizeof(long) + CHUNK_SIZE * enc_channels / 2;
+    num_chunks     = enc_buffer_size / chunk_size;
+    samp_per_chunk = CHUNK_SIZE / 4;
+
+    /* inform the main program about buffer dimensions and other params */
+    ci->enc_set_parameters(chunk_size, num_chunks, samp_per_chunk,
+        (enc_channels == 2) ? wav_header : wav_header_mono,
+        sizeof(wav_header), AFMT_PCM_WAV);
+
+    /* main application waits for this flag during encoder loading */
+    ci->enc_codec_loaded = true;
+
+    /* main encoding loop */
+    while(!ci->stop_codec)
+    {
+        while((src = (unsigned long*)ci->enc_get_wav_data(CHUNK_SIZE)) != NULL)
+        {
+            if(ci->stop_codec)
+                break;
+
+            if(ci->enc_wavbuf_near_empty() == 0)
+            {
+                if(!cpu_boosted)
+                {
+                    ci->cpu_boost(true);
+                    cpu_boosted = true;
+                }
+            }
+
+            dst = (unsigned long*)ci->enc_alloc_chunk();
+            *dst++ = CHUNK_SIZE * enc_channels / 2; /* set size info */
+
+            if(enc_channels == 2)
+            {
+                /* swap byte order & copy to destination */
+                for (i=0; i<CHUNK_SIZE/4; i++)
+                {
+                    t = *src++;
+                    *dst++ = ((t >> 8) & 0xff00ff) | ((t << 8) & 0xff00ff00);
+                }
+            }
+            else
+            {
+                /* mix left/right, swap byte order & copy to destination */
+                for (i=0; i<CHUNK_SIZE/8; i++)
+                {
+                    lr = (long)*src++;
+                    lr = (((lr<<16)>>16) + (lr>>16)) >> 1; /* left+right */
+                    t  = (lr << 16);
+                    lr = (long)*src++;
+                    lr = (((lr<<16)>>16) + (lr>>16)) >> 1; /* left+right */
+                    t |= lr & 0xffff;
+                    *dst++ = ((t >> 8) & 0xff00ff) | ((t << 8) & 0xff00ff00);
+                }
+            }
+
+            ci->enc_free_chunk();
+            ci->yield();
+        }
+
+        if(ci->enc_wavbuf_near_empty())
+        {
+            if(cpu_boosted)
+            {
+                ci->cpu_boost(false);
+                cpu_boosted = false;
+            }
+        }
+
+        ci->yield();
+    }
+
+    if(cpu_boosted) /* set initial boost state */
+        ci->cpu_boost(false);
+
+    /* reset parameters to initial state */
+    ci->enc_set_parameters(0, 0, 0, 0, 0, 0);
+ 
+    /* main application waits for this flag during encoder removing */
+    ci->enc_codec_loaded = false;
+
+    return CODEC_OK;
+}
+#endif
diff --git a/apps/codecs/wavpack_enc.c b/apps/codecs/wavpack_enc.c
new file mode 100644
index 0000000..cde2087
--- /dev/null
+++ b/apps/codecs/wavpack_enc.c
@@ -0,0 +1,230 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Antonius Hellmann
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef SIMULATOR
+
+#include "codeclib.h"
+#include "libwavpack/wavpack.h"
+
+CODEC_HEADER
+
+typedef unsigned  long uint32;
+typedef unsigned short uint16;
+typedef unsigned  char  uint8;
+
+static unsigned char wav_header_ster [46] =
+{33,22,'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
+ 0,0,0,1,0,2,0,0x44,0xac,0,0,0x10,0xb1,2,0,4,0,16,0,'d','a','t','a',0,0,0,0};
+
+static unsigned char wav_header_mono   [46] =
+{33,22,'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',16,
+ 0,0,0,1,0,1,0,0x44,0xac,0,0,0x88,0x58,1,0,2,0,16,0,'d','a','t','a',0,0,0,0};
+
+static struct codec_api *ci;
+static int              enc_channels;
+
+#define CHUNK_SIZE 20000
+
+static long input_buffer[CHUNK_SIZE/2] IBSS_ATTR;
+
+void *memset(void *s, int c, size_t n)
+{
+    return(ci->memset(s,c,n));
+}
+
+void *memcpy(void *dest, const void *src, size_t n)
+{
+    return(ci->memcpy(dest,src,n));
+}
+
+/* update file header info callback function */
+void enc_set_header(void *head_buffer,    /* ptr to the file header data     */
+                    int  head_size,       /* size of this header data        */
+                    int  num_pcm_sampl,   /* amount of processed pcm samples */
+                    bool is_file_header)  /* update file/chunk header        */
+{
+    if(is_file_header)
+    {
+        /* update file header before file closing */
+        if(sizeof(WavpackHeader) + sizeof(wav_header_mono) < (unsigned)head_size)
+        {
+            char* riff_header    = (char*)head_buffer + sizeof(WavpackHeader);
+            char* wv_header      = (char*)head_buffer + sizeof(wav_header_mono);
+            int   num_file_bytes = num_pcm_sampl * 2 * enc_channels;
+            unsigned long ckSize;
+
+            /* RIFF header and WVPK header have to be swapped */
+            /* copy wavpack header to file start position */
+            ci->memcpy(head_buffer, wv_header, sizeof(WavpackHeader));
+            wv_header = head_buffer; /* recalc wavpack header position */
+
+            if(enc_channels == 2)
+                ci->memcpy(riff_header, wav_header_ster, sizeof(wav_header_ster));
+            else
+                ci->memcpy(riff_header, wav_header_mono, sizeof(wav_header_mono));
+
+            /* update the Wavpack header first chunk size & total frame count */
+            ckSize = htole32(((WavpackHeader*)wv_header)->ckSize)
+                   + sizeof(wav_header_mono);
+            ((WavpackHeader*)wv_header)->total_samples = htole32(num_pcm_sampl);
+            ((WavpackHeader*)wv_header)->ckSize        = htole32(ckSize);
+
+            /* update the RIFF WAV header size entries */
+            *(long*)(riff_header+ 6) = htole32(num_file_bytes + 36);
+            *(long*)(riff_header+42) = htole32(num_file_bytes);
+        }
+    }
+    else
+    {
+        /* update timestamp (block_index) */
+        ((WavpackHeader*)head_buffer)->block_index = htole32(num_pcm_sampl);
+    }
+}
+
+
+enum codec_status codec_start(struct codec_api* api)
+{
+    int            i;
+    long           t;
+    uint32         *src;
+    uint32         *dst;
+    int            chunk_size, num_chunks, samp_per_chunk;
+    int            enc_buffer_size;
+    int            enc_quality;
+    WavpackConfig  config;
+    WavpackContext *wpc;
+    bool           cpu_boosted = true; /* start boosted */
+
+    ci = api; // copy to global api pointer
+
+    if(ci->enc_get_inputs          == NULL ||
+       ci->enc_set_parameters      == NULL ||
+       ci->enc_alloc_chunk         == NULL ||
+       ci->enc_free_chunk          == NULL ||
+       ci->enc_wavbuf_near_empty   == NULL ||
+       ci->enc_get_wav_data        == NULL ||
+       ci->enc_set_header_callback == NULL )
+        return CODEC_ERROR;
+
+    ci->cpu_boost(true);
+
+    *ci->enc_set_header_callback = enc_set_header;
+    ci->enc_get_inputs(&enc_buffer_size, &enc_channels, &enc_quality);
+
+    /* configure the buffer system */
+    chunk_size     = sizeof(long) + CHUNK_SIZE * enc_channels / 2;
+    num_chunks     = enc_buffer_size / chunk_size;
+    samp_per_chunk = CHUNK_SIZE / 4;
+
+    /* inform the main program about buffer dimensions and other params */
+    /* add wav_header_mono as place holder to file start position */
+    /* wav header and wvpk header have to be reordered later */
+    ci->enc_set_parameters(chunk_size, num_chunks, samp_per_chunk,
+                           wav_header_mono, sizeof(wav_header_mono),
+                           AFMT_WAVPACK);
+
+    wpc = WavpackOpenFileOutput ();
+
+    memset (&config, 0, sizeof (config));
+    config.bits_per_sample  = 16;
+    config.bytes_per_sample = 2;
+    config.sample_rate      = 44100;
+    config.num_channels     = enc_channels;
+
+    if (!WavpackSetConfiguration (wpc, &config, 1))
+        return CODEC_ERROR;
+
+    /* main application waits for this flag during encoder loading */
+    ci->enc_codec_loaded = true;
+
+    /* main encoding loop */
+    while(!ci->stop_codec)
+    {
+        while((src = (uint32*)ci->enc_get_wav_data(CHUNK_SIZE)) != NULL)
+        {
+            if(ci->stop_codec)
+                break;
+
+            if(ci->enc_wavbuf_near_empty() == 0)
+            {
+                if(!cpu_boosted)
+                {
+                    ci->cpu_boost(true);
+                    cpu_boosted = true;
+                }
+            }
+
+            dst = (uint32*)ci->enc_alloc_chunk() + 1;
+
+            WavpackStartBlock (wpc, (uint8*)dst, (uint8*)dst + CHUNK_SIZE);
+
+            if(enc_channels == 2)
+            {
+                for (i=0; i<CHUNK_SIZE/4; i++)
+                {
+                    t = (long)*src++;
+
+                    input_buffer[2*i + 0] = t >> 16;
+                    input_buffer[2*i + 1] = (short)t;
+                }
+            }
+            else
+            {
+                for (i=0; i<CHUNK_SIZE/4; i++)
+                {
+                    t = (long)*src++;
+                    t = (((t<<16)>>16) + (t>>16)) >> 1; /* left+right */
+
+                    input_buffer[i] = t;
+                }
+            }
+
+            if (!WavpackPackSamples (wpc, input_buffer, CHUNK_SIZE/4))
+                return CODEC_ERROR;
+
+            /* finish the chunk and store chunk size info */
+            dst[-1] = WavpackFinishBlock (wpc);
+
+            ci->enc_free_chunk();
+            ci->yield();
+        }
+
+        if(ci->enc_wavbuf_near_empty())
+        {
+            if(cpu_boosted)
+            {
+                ci->cpu_boost(false);
+                cpu_boosted = false;
+            }
+        }
+        ci->yield();
+    }
+
+    if(cpu_boosted) /* set initial boost state */
+        ci->cpu_boost(false);
+
+    /* reset parameters to initial state */
+    ci->enc_set_parameters(0, 0, 0, 0, 0, 0);
+ 
+    /* main application waits for this flag during encoder removing */
+    ci->enc_codec_loaded = false;
+
+    return CODEC_OK;
+}
+#endif
diff --git a/apps/filetree.c b/apps/filetree.c
index d3ef1e0..9d5109c 100644
--- a/apps/filetree.c
+++ b/apps/filetree.c
@@ -445,9 +445,8 @@
                 {
                     set_file(buf, global_settings.fmr_file, MAX_FILENAME);
                     radio_load_presets(global_settings.fmr_file);
-                    if(get_radio_status() != FMRADIO_PLAYING &&
-                        get_radio_status() != FMRADIO_PAUSED)
-                            radio_screen();
+                    if(!in_radio_screen())
+                        radio_screen();
                 }
                 /*
                  * Preset outside default folder, we can choose such only
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 3d87c0c..5687c81 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -9661,6 +9661,22 @@
     *: "Full Path"
   </voice>
 </phrase>
+<<<<<<< english.lang
+<phrase>
+  id: VOICE_KBIT_PER_SEC
+  desc: spoken only, for file extension
+  user:
+  <source>
+    *: ""
+  </source>
+  <dest>
+    *: ""
+  </dest>
+  <voice>
+    *: "kilobits per second"
+  </voice>
+</phrase>
+=======
 <phrase>
   id: LANG_RECORD_AGC_PRESET
   desc: automatic gain control in record settings
@@ -9778,3 +9794,4 @@
     *: "AGC maximum gain"
   </voice>
 </phrase>
+>>>>>>> 1.267
diff --git a/apps/main_menu.c b/apps/main_menu.c
index 04527f9..4348d52 100644
--- a/apps/main_menu.c
+++ b/apps/main_menu.c
@@ -285,9 +285,31 @@
 
 #ifdef HAVE_RECORDING
 
+static bool rec_menu_recording_screen(void)
+{
+    return recording_screen(false);
+}
+
 static bool recording_settings(void)
 {
-    return recording_menu(false);
+    bool ret;
+#ifdef HAVE_FMRADIO_IN
+    int rec_source = global_settings.rec_source;
+#endif
+
+    ret = recording_menu(false);
+
+#ifdef HAVE_FMRADIO_IN
+    if (rec_source != global_settings.rec_source)
+    {
+        if (rec_source == AUDIO_SRC_FMRADIO)
+            radio_stop();
+        /* If AUDIO_SRC_FMRADIO was selected from something else,
+           the recording screen will start the radio */       
+    }
+#endif
+
+    return ret;
 }
 
 bool rec_menu(void)
@@ -297,7 +319,7 @@
 
     /* recording menu */
     static const struct menu_item items[] = {
-        { ID2P(LANG_RECORDING_MENU),     recording_screen  },
+        { ID2P(LANG_RECORDING_MENU),     rec_menu_recording_screen  },
         { ID2P(LANG_RECORDING_SETTINGS), recording_settings},
     };
 
diff --git a/apps/playback.c b/apps/playback.c
index a37e0ad..d4f3626 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -74,29 +74,18 @@
 #include "misc.h"
 #include "sound.h"
 #include "metadata.h"
-#include "talk.h"
-#ifdef CONFIG_TUNER
-#include "radio.h"
-#endif
 #include "splash.h"
+#include "talk.h"
+
+#ifdef HAVE_RECORDING
+#include "recording.h"
+#endif
 
 static volatile bool audio_codec_loaded;
 static volatile bool voice_codec_loaded;
 static volatile bool playing;
 static volatile bool paused;
 
-#define CODEC_VORBIS   "/.rockbox/codecs/vorbis.codec"
-#define CODEC_MPA_L3   "/.rockbox/codecs/mpa.codec"
-#define CODEC_FLAC     "/.rockbox/codecs/flac.codec"
-#define CODEC_WAV      "/.rockbox/codecs/wav.codec"
-#define CODEC_A52      "/.rockbox/codecs/a52.codec"
-#define CODEC_MPC      "/.rockbox/codecs/mpc.codec"
-#define CODEC_WAVPACK  "/.rockbox/codecs/wavpack.codec"
-#define CODEC_ALAC     "/.rockbox/codecs/alac.codec"
-#define CODEC_AAC      "/.rockbox/codecs/aac.codec"
-#define CODEC_SHN      "/.rockbox/codecs/shorten.codec"
-#define CODEC_AIFF     "/.rockbox/codecs/aiff.codec"
-#define CODEC_SID      "/.rockbox/codecs/sid.codec"
 
 /* default point to start buffer refill */
 #define AUDIO_DEFAULT_WATERMARK      (1024*512)
@@ -133,6 +122,11 @@
 
     Q_CODEC_LOAD,
     Q_CODEC_LOAD_DISK,
+
+#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
+    Q_ENCODER_LOAD_DISK,
+    Q_ENCODER_RECORD,
+#endif
 };
 
 /* As defined in plugins/lib/xxx2wav.h */
@@ -382,7 +376,7 @@
     }
 
     return true;
-}
+} /* voice_pcmbuf_insert_split_callback */
 
 static bool codec_pcmbuf_insert_split_callback(
         const void *ch1, const void *ch2, size_t length)
@@ -444,7 +438,7 @@
     }
 
     return true;
-}
+} /* codec_pcmbuf_insert_split_callback */
 
 static bool voice_pcmbuf_insert_callback(const char *buf, size_t length)
 {
@@ -649,7 +643,7 @@
 
     /* Return the actual amount of data copied to the buffer */
     return copy_n;
-}
+} /* codec_filebuf_callback */
 
 static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
 {
@@ -664,7 +658,9 @@
     while (1)
     {
         if (voice_is_playing)
+        {
             queue_wait_w_tmo(&voice_codec_queue, &ev, 0);
+        }
         else if (playing)
         {
             queue_wait_w_tmo(&voice_codec_queue, &ev, 0);
@@ -679,7 +675,11 @@
                 if (playing)
                     swap_codec();
                 break;
-
+#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
+            case Q_ENCODER_RECORD:
+                swap_codec();
+                break;
+#endif
             case Q_VOICE_STOP:
                 if (voice_is_playing)
                 {
@@ -743,7 +743,7 @@
         return NULL;
 
     return voicebuf;
-}
+} /* voice_request_buffer_callback */
 
 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
 {
@@ -794,7 +794,7 @@
     *realsize = copy_n;
     
     return (char *)&filebuf[buf_ridx];
-}
+} /* codec_request_buffer_callback */
 
 static int get_codec_base_type(int type)
 {
@@ -1531,52 +1531,24 @@
 #endif
 }
 
-static const char *get_codec_path(int codectype) 
+static const char * get_codec_filename(int enc_spec)
 {
-    switch (codectype) {
-        case AFMT_OGG_VORBIS:
-            logf("Codec: Vorbis");
-            return CODEC_VORBIS;
-        case AFMT_MPA_L1:
-        case AFMT_MPA_L2:
-        case AFMT_MPA_L3:
-            logf("Codec: MPA L1/L2/L3");
-            return CODEC_MPA_L3;
-        case AFMT_PCM_WAV:
-            logf("Codec: PCM WAV");
-            return CODEC_WAV;
-        case AFMT_FLAC:
-            logf("Codec: FLAC");
-            return CODEC_FLAC;
-        case AFMT_A52:
-            logf("Codec: A52");
-            return CODEC_A52;
-        case AFMT_MPC:
-            logf("Codec: Musepack");
-            return CODEC_MPC;
-        case AFMT_WAVPACK:
-            logf("Codec: WAVPACK");
-            return CODEC_WAVPACK;
-        case AFMT_ALAC:
-            logf("Codec: ALAC");
-            return CODEC_ALAC;
-        case AFMT_AAC:
-            logf("Codec: AAC");
-            return CODEC_AAC;
-        case AFMT_SHN:
-            logf("Codec: SHN");
-            return CODEC_SHN;
-        case AFMT_AIFF:
-            logf("Codec: PCM AIFF");
-            return CODEC_AIFF;
-        case AFMT_SID:
-            logf("Codec: SID");
-            return CODEC_SID;
-        default:
-            logf("Codec: Unsupported");
-            return NULL;
-    }
-}
+    const char *fname;
+    int type = enc_spec & CODEC_TYPE_MASK;
+    int afmt = enc_spec & CODEC_AFMT_MASK;
+
+    if ((unsigned)afmt >= AFMT_NUM_CODECS)
+        type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
+
+    fname = (type == CODEC_TYPE_DECODER) ?
+        audio_formats[afmt].codec_fn : audio_formats[afmt].codec_enc_fn;
+
+    logf("%s: %d - %s",
+        (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
+        afmt, fname ? fname : "<unknown>");
+
+    return fname;
+} /* get_codec_filename */
 
 static bool loadcodec(bool start_play)
 {
@@ -1585,9 +1557,10 @@
     int rc;
     size_t copy_n;
     int prev_track;
+    char codec_path[MAX_PATH]; /* Full path to codec */
 
-    const char *codec_path = get_codec_path(tracks[track_widx].id3.codectype);
-    if (codec_path == NULL)
+    const char * codec_fn = get_codec_filename(tracks[track_widx].id3.codectype);
+    if (codec_fn == NULL)
         return false;
 
     tracks[track_widx].has_codec = false;
@@ -1603,7 +1576,7 @@
         ci.taginfo_ready = &cur_ti->taginfo_ready;
         ci.curpos = 0;
         playing = true;
-        queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_path);
+        queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_fn);
         return true;
     }
     else
@@ -1625,6 +1598,8 @@
         }
     }
 
+    codec_get_full_path(codec_path, codec_fn);
+
     fd = open(codec_path, O_RDONLY);
     if (fd < 0)
     {
@@ -1973,11 +1948,8 @@
             (playlist_end && ci.stop_codec)?NULL:audio_current_track());
     }
 
-    if (voice_is_playing)
-    {
-        while (voice_is_playing && !queue_empty(&voice_codec_queue))
-            yield();
-    }
+    while (voice_is_playing && !queue_empty(&voice_codec_queue))
+        yield();
     
     filebufused = 0;
     playing = false;
@@ -1998,10 +1970,8 @@
 
 static void audio_play_start(size_t offset)
 {
-#ifdef CONFIG_TUNER
-    /* check if radio is playing */
-    if (get_radio_status() != FMRADIO_OFF)
-        radio_stop();
+#if defined(HAVE_RECORDING) || defined(CONFIG_TUNER)
+    rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
 #endif
 
     /* Wait for any previously playing audio to flush - TODO: Not necessary? */
@@ -2483,6 +2453,20 @@
                 mutex_unlock(&mutex_codecthread);
                 break ;
 
+#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
+            case Q_ENCODER_LOAD_DISK:
+                logf("Encoder load disk");
+                audio_codec_loaded = false;
+                if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
+                    queue_post(&voice_codec_queue, Q_ENCODER_RECORD, NULL);
+                mutex_lock(&mutex_codecthread);
+                current_codec = CODEC_IDX_AUDIO;
+                ci.stop_codec = false;
+                status = codec_load_file((const char *)ev.data, &ci);
+                mutex_unlock(&mutex_codecthread);
+                break;
+#endif
+
 #ifndef SIMULATOR
             case SYS_USB_CONNECTED:
                 queue_clear(&codec_queue);
@@ -2511,8 +2495,6 @@
             case Q_CODEC_LOAD:
                 if (playing) 
                 {
-                    const char *codec_path;
-                    
                     if (ci.new_track || status != CODEC_OK) 
                     {
                         if (!ci.new_track) 
@@ -2523,7 +2505,8 @@
                         
                         if (!load_next_track())
                         {
-                            queue_post(&codec_queue, Q_AUDIO_STOP, 0);
+                            // queue_post(&codec_queue, Q_AUDIO_STOP, 0);
+                            queue_post(&audio_queue, Q_AUDIO_STOP, 0);
                             break;
                         }
                     } 
@@ -2545,12 +2528,12 @@
                         queue_post(&codec_queue, Q_CODEC_LOAD, 0);
                     else
                     {
-                        codec_path = get_codec_path(cur_ti->id3.codectype);
-                        queue_post(&codec_queue,
-                                Q_CODEC_LOAD_DISK, (void *)codec_path);
+                        const char *codec_fn = get_codec_filename(cur_ti->id3.codectype);
+                        queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
+                            (void *)codec_fn);
                     }
                 }
-        }
+        } /* end switch */
     }
 }
 
@@ -2596,6 +2579,37 @@
     filebuflen &= ~3;
 }
 
+void audio_load_encoder(int enc_id)
+{
+#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
+    const char *enc_fn = get_codec_filename(enc_id | CODEC_TYPE_ENCODER);
+    if (!enc_fn)
+        return;
+
+    audio_remove_encoder();
+
+    queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (void *)enc_fn);
+
+    while (!ci.enc_codec_loaded)
+        yield();
+#endif
+    return;
+    (void)enc_id;
+} /* audio_load_encoder */
+
+void audio_remove_encoder(void)
+{
+#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
+    /* force encoder codec unload (if previously loaded) */
+    if (!ci.enc_codec_loaded)
+        return;
+
+    ci.stop_codec = true;
+    while (ci.enc_codec_loaded)
+        yield();
+#endif
+} /* audio_remove_encoder */
+
 static void voice_codec_thread(void)
 {
     while (1)
@@ -2608,13 +2622,13 @@
         voice_remaining = 0;
         voice_getmore = NULL;
 
-        codec_load_file(CODEC_MPA_L3, &ci_voice);
+        codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
 
         logf("Voice codec finished");
-        mutex_unlock(&mutex_codecthread);
         voice_codec_loaded = false;
+        mutex_unlock(&mutex_codecthread);
     }
-}
+} /* voice_codec_thread */
 
 void voice_init(void)
 {
@@ -2642,7 +2656,20 @@
     
     while (!voice_codec_loaded)
         yield();
-}
+} /* voice_init */
+
+void voice_stop(void)
+{
+    /* Messages should not be posted to voice codec queue unless it is the
+       current codec or deadlocks happen. This will be addressed globally soon.
+       -- jhMikeS */
+    if (current_codec != CODEC_IDX_VOICE)
+        return;
+
+    mp3_play_stop();
+    while (voice_is_playing && !queue_empty(&voice_codec_queue))
+        yield();
+} /* voice_stop */
 
 struct mp3entry* audio_current_track(void)
 {
@@ -2803,9 +2830,19 @@
     if (paused)
         ret |= AUDIO_STATUS_PAUSE;
 
+#ifdef HAVE_RECORDING
+    /* Do this here for constitency with mpeg.c version */
+    ret |= pcm_rec_status();
+#endif
+
     return ret;
 }
 
+bool audio_query_poweroff(void)
+{
+    return !(playing && paused);
+}
+
 int audio_get_file_pos(void)
 {
     return 0;
diff --git a/apps/playback.h b/apps/playback.h
index 3e50133..73cd0cc 100644
--- a/apps/playback.h
+++ b/apps/playback.h
@@ -27,8 +27,8 @@
 #include "id3.h"
 #include "mp3data.h"
 
-#define CODEC_IDX_AUDIO  0
-#define CODEC_IDX_VOICE  1
+#define CODEC_IDX_AUDIO     0
+#define CODEC_IDX_VOICE     1
 
 /* Not yet implemented. */
 #define CODEC_SET_AUDIOBUF_WATERMARK    4
@@ -66,6 +66,7 @@
                                                    bool last_track));
 void audio_invalidate_tracks(void);
 void voice_init(void);
+void voice_stop(void);
 
 #if CONFIG_CODEC == SWCODEC /* This #ifdef is better here than gui/gwps.c */
 extern void audio_next_dir(void);
diff --git a/apps/recorder/radio.c b/apps/recorder/radio.c
index c292909..208e7b6 100644
--- a/apps/recorder/radio.c
+++ b/apps/recorder/radio.c
@@ -24,7 +24,6 @@
 #include "mas.h"
 #include "settings.h"
 #include "button.h"
-#include "fmradio.h"
 #include "status.h"
 #include "kernel.h"
 #include "mpeg.h"
@@ -63,17 +62,6 @@
 
 #ifdef CONFIG_TUNER
 
-#if CONFIG_CODEC == SWCODEC
-#ifdef HAVE_UDA1380
-#include "uda1380.h"
-#endif
-#ifdef HAVE_TLV320
-#include "tlv320.h"
-#endif
-
-#include "pcm_record.h"
-#endif
-
 #if CONFIG_KEYPAD == RECORDER_PAD
 #define FM_MENU BUTTON_F1
 #define FM_PRESET BUTTON_F2
@@ -165,6 +153,7 @@
 static int radio_mode = RADIO_SCAN_MODE;
 
 static int radio_status = FMRADIO_OFF;
+static bool in_screen = false;
 
 #define MAX_PRESETS 64
 static bool presets_loaded = false, presets_changed = false;
@@ -239,22 +228,87 @@
     return radio_status;
 }
 
+bool in_radio_screen(void)
+{
+    return in_screen;
+}
+
+/* secret flag for starting paused - prevents unmute */
+#define FMRADIO_START_PAUSED 0x8000
+void radio_start(void)
+{
+    bool start_paused;
+    int mute_timeout;
+
+    if(radio_status == FMRADIO_PLAYING)
+        return;
+
+    start_paused = radio_status & FMRADIO_START_PAUSED;
+    /* clear flag before any yielding */
+    radio_status &= ~FMRADIO_START_PAUSED;
+
+    if(radio_status == FMRADIO_OFF)
+        radio_power(true);
+
+    curr_freq = global_settings.last_frequency * FREQ_STEP + MIN_FREQ;
+
+    radio_set(RADIO_SLEEP, 0); /* wake up the tuner */
+    radio_set(RADIO_FREQUENCY, curr_freq);
+
+    if(radio_status == FMRADIO_OFF)
+    {
+        radio_set(RADIO_IF_MEASUREMENT, 0);
+        radio_set(RADIO_SENSITIVITY, 0);
+        radio_set(RADIO_FORCE_MONO, global_settings.fm_force_mono);
+        mute_timeout = current_tick + 1*HZ;
+    }
+    else
+    {
+        /* paused */
+        mute_timeout = current_tick + 2*HZ;
+    }
+
+    while(!radio_get(RADIO_STEREO) && !radio_get(RADIO_TUNED))
+    {
+        if(TIME_AFTER(current_tick, mute_timeout))
+             break;
+        yield();
+    }
+
+    /* keep radio from sounding initially */
+    if(!start_paused)
+        radio_set(RADIO_MUTE, 0);
+
+    radio_status = FMRADIO_PLAYING;
+} /* radio_start */
+
+void radio_pause(void)
+{
+    if(radio_status == FMRADIO_PAUSED)
+        return;
+
+    if(radio_status == FMRADIO_OFF)
+    {
+        radio_status |= FMRADIO_START_PAUSED;    
+        radio_start();
+    }
+
+    radio_set(RADIO_MUTE, 1);
+    radio_set(RADIO_SLEEP, 1);
+
+    radio_status = FMRADIO_PAUSED;
+} /* radio_pause */
+
 void radio_stop(void)
-{             
+{
+    if(radio_status == FMRADIO_OFF)
+        return;
+
     radio_set(RADIO_MUTE, 1);
     radio_set(RADIO_SLEEP, 1); /* low power mode, if available */
     radio_status = FMRADIO_OFF;
     radio_power(false); /* status update, power off if avail. */
-
-#ifndef SIMULATOR /* SIMULATOR. Catch FMRADIO_OFF status for the sim. */ 
-#if CONFIG_CODEC == SWCODEC
-#ifdef HAVE_TLV320
-    tlv320_set_monitor(false);
-#endif
-    pcm_rec_mux(0); /* Line In */
-#endif
-#endif /* SIMULATOR */
-}
+} /* radio_stop */
 
 bool radio_hardware_present(void)
 {
@@ -297,18 +351,16 @@
             return i;
         if(diff < 0)
             diff = -diff;
-	if(diff < min_diff)
+        if(diff < min_diff)
         {
             preset = i;
-            min_diff = diff;	
+            min_diff = diff;
         }
     }
 
     return preset;
 }
 
-
-
 static void remember_frequency(void)
 {
     global_settings.last_frequency = (curr_freq - MIN_FREQ) / FREQ_STEP;
@@ -366,13 +418,15 @@
 #endif
     bool keep_playing = false;
     bool statusbar = global_settings.statusbar;
-    int mute_timeout = current_tick;
     int button_timeout = current_tick + (2*HZ);
 #ifdef HAS_BUTTONBAR
     struct gui_buttonbar buttonbar;
     gui_buttonbar_init(&buttonbar);
     gui_buttonbar_set_display(&buttonbar, &(screens[SCREEN_MAIN]) );
 #endif
+    /* change status to "in screen" */
+    in_screen = true;
+
     /* always display status bar in radio screen for now */
     global_settings.statusbar = true;
     FOR_NB_SCREENS(i)
@@ -396,80 +450,44 @@
     }
                                        
 #ifndef SIMULATOR
+    if(radio_status == FMRADIO_OFF)    
+        audio_stop();
+
 #if CONFIG_CODEC != SWCODEC
     if(rec_create_directory() > 0)
         have_recorded = true;
-#endif
 
-    if(radio_status == FMRADIO_PLAYING_OUT)
-        radio_status = FMRADIO_PLAYING;
-    else if(radio_status == FMRADIO_PAUSED_OUT)
-        radio_status = FMRADIO_PAUSED;
-
-    if(radio_status == FMRADIO_OFF)    
-        audio_stop();
-        
-#if CONFIG_CODEC != SWCODEC
     audio_init_recording(talk_get_bufsize());
 
     sound_settings_apply();
     /* Yes, we use the D/A for monitoring */
     peak_meter_playback(true);
-    
+
     peak_meter_enabled = true;
 
-    if (global_settings.rec_prerecord_time)
-        talk_buffer_steal(); /* will use the mp3 buffer */
+    rec_set_recording_options(global_settings.rec_frequency,
+                              global_settings.rec_quality,
+                              AUDIO_SRC_LINEIN, 0,
+                              global_settings.rec_channels,
+                              global_settings.rec_editable,
+                              global_settings.rec_prerecord_time);
 
-    audio_set_recording_options(global_settings.rec_frequency,
-                               global_settings.rec_quality,
-                               1, /* Line In */
-                               global_settings.rec_channels,
-                               global_settings.rec_editable,
-                               global_settings.rec_prerecord_time);
-
-    
-#else
-    peak_meter_enabled = false;
-
-#ifdef HAVE_UDA1380
-    uda1380_enable_recording(false);
-    uda1380_set_monitor(true);
-#elif defined(HAVE_TLV320)
-    //tlv320_enable_recording(false);
-    tlv320_set_recvol(23, 23, AUDIO_GAIN_LINEIN); /* 0dB */
-    tlv320_set_monitor(true);
-#endif
-
-    /* Set the input multiplexer to FM */
-    pcm_rec_mux(1);
-#endif
     audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
-                            sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
+            sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
+
+#endif /* CONFIG_CODEC != SWCODEC */
+#endif /* ndef SIMULATOR */
+
+    /* turn on radio */
+#if CONFIG_CODEC == SWCODEC
+    rec_set_source(AUDIO_SRC_FMRADIO, (radio_status == FMRADIO_PAUSED) ?
+                       SRCF_FMRADIO_PAUSED : SRCF_FMRADIO_PLAYING);
+#else
+    if (radio_status == FMRADIO_OFF)
+        radio_start();
 #endif
 
-    curr_freq = global_settings.last_frequency * FREQ_STEP + MIN_FREQ;
-    
-    if(radio_status == FMRADIO_OFF)
-    {
-        radio_power(true);
-        radio_set(RADIO_SLEEP, 0); /* wake up the tuner */
-        radio_set(RADIO_FREQUENCY, curr_freq);
-        radio_set(RADIO_IF_MEASUREMENT, 0);
-        radio_set(RADIO_SENSITIVITY, 0);
-        radio_set(RADIO_FORCE_MONO, global_settings.fm_force_mono);
-        mute_timeout = current_tick + (1*HZ);
-        while( !radio_get(RADIO_STEREO)
-             &&!radio_get(RADIO_TUNED) )
-        {
-            if(TIME_AFTER(current_tick, mute_timeout))
-                 break;
-            yield();
-        }
-        radio_set(RADIO_MUTE, 0);
-        radio_status = FMRADIO_PLAYING;
-    }
-
+    /* I hate this thing with vehement passion (jhMikeS): */
    if(num_presets == 0 && yesno_pop(str(LANG_FM_FIRST_AUTOSCAN)))
         scan_presets();
     
@@ -478,8 +496,8 @@
          radio_mode = RADIO_PRESET_MODE;
 
 #ifdef HAS_BUTTONBAR
-    gui_buttonbar_set(&buttonbar, str(LANG_BUTTONBAR_MENU), str(LANG_FM_BUTTONBAR_PRESETS),
-                  str(LANG_FM_BUTTONBAR_RECORD));
+    gui_buttonbar_set(&buttonbar, str(LANG_BUTTONBAR_MENU),
+        str(LANG_FM_BUTTONBAR_PRESETS), str(LANG_FM_BUTTONBAR_RECORD));
 #endif
 
     cpu_idle_mode(true);
@@ -535,7 +553,7 @@
                 if (lastbutton != FM_STOP_PRE)
                     break;
 #endif
-#ifndef SIMULATOR
+#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
                 if(audio_status() == AUDIO_STATUS_RECORD)
                 {
                     audio_stop();
@@ -548,7 +566,7 @@
                     {
                         if(yesno_pop(str(LANG_FM_SAVE_CHANGES)))
                         {
-					        if(filepreset[0] == '\0')
+                            if(filepreset[0] == '\0')
                                 save_preset_list();
                             else
                                 radio_save_presets();
@@ -577,14 +595,13 @@
 #ifndef SIMULATOR
                 if(audio_status() == AUDIO_STATUS_RECORD)
                 {
-                    audio_new_file(rec_create_filename(buf));
+                    rec_new_file();
                     update_screen = true;
                 }
                 else
                 {
                     have_recorded = true;
-                    talk_buffer_steal(); /* we use the mp3 buffer */
-                    audio_record(rec_create_filename(buf));
+                    rec_record();
                     update_screen = true;
                 }
 #endif
@@ -604,7 +621,7 @@
                     )
                     break;
 #endif
-#ifndef SIMULATOR
+#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
                 if(audio_status() == AUDIO_STATUS_RECORD)
                     audio_stop();
 #endif
@@ -615,7 +632,7 @@
                 {
                     if(yesno_pop(str(LANG_FM_SAVE_CHANGES)))
                     {
-				        if(filepreset[0] == '\0')
+                        if(filepreset[0] == '\0')
                             save_preset_list();
                         else
                             radio_save_presets();
@@ -734,27 +751,11 @@
                   )
                      break;
 #endif
-                if(radio_status != FMRADIO_PLAYING)
-                {
-                     radio_set(RADIO_SLEEP, 0);
-                     radio_set(RADIO_FREQUENCY, curr_freq);
-                     mute_timeout = current_tick + (2*HZ);
-                     while( !radio_get(RADIO_STEREO)
-                          &&!radio_get(RADIO_TUNED) )
-                     {
-                         if(TIME_AFTER(current_tick, mute_timeout))
-                             break;
-                         yield();
-                     }
-                     radio_set(RADIO_MUTE, 0);
-                     radio_status = FMRADIO_PLAYING;
-                }
+                if (radio_status == FMRADIO_PLAYING)
+                    radio_pause();
                 else
-                {
-                     radio_set(RADIO_MUTE, 1);
-                     radio_set(RADIO_SLEEP, 1);
-                     radio_status = FMRADIO_PAUSED;
-                }
+                    radio_start();
+
                 update_screen = true;
                 break;
 #endif
@@ -917,13 +918,17 @@
             if(TIME_AFTER(current_tick, timeout))
             {
                 timeout = current_tick + HZ;
-                
-                stereo = radio_get(RADIO_STEREO) &&
-                    !global_settings.fm_force_mono;
-                if(stereo != last_stereo_status)
+
+                /* keep "mono" from always being displayed when paused */
+                if (radio_status != FMRADIO_PAUSED)
                 {
-                    update_screen = true;
-                    last_stereo_status = stereo;
+                    stereo = radio_get(RADIO_STEREO) &&
+                        !global_settings.fm_force_mono;
+                    if(stereo != last_stereo_status)
+                    {
+                        update_screen = true;
+                        last_stereo_status = stereo;
+                    }
                 }
             }
             
@@ -952,9 +957,6 @@
                 FOR_NB_SCREENS(i)
                     screens[i].puts_scroll(0, top_of_screen + 1, buf);
                 
-                strcat(buf, stereo?str(LANG_CHANNEL_STEREO):
-                                   str(LANG_CHANNEL_MONO));
-
                 snprintf(buf, 128, stereo?str(LANG_CHANNEL_STEREO):
                                           str(LANG_CHANNEL_MONO));
                 FOR_NB_SCREENS(i)
@@ -1005,9 +1007,9 @@
             done = true;
         }
         if (TIME_AFTER(current_tick, button_timeout))
-       	{
-       		cpu_idle_mode(true);
-       	}
+        {
+            cpu_idle_mode(true);
+        }
     } /*while(!done)*/
 
 #ifndef SIMULATOR
@@ -1033,28 +1035,26 @@
 
     sound_settings_apply();
 #endif /* SIMULATOR */
+
     if(keep_playing)
     {
-/* Catch FMRADIO_PLAYING_OUT status for the sim. */ 
+/* Catch FMRADIO_PLAYING status for the sim. */ 
 #ifndef SIMULATOR
 #if CONFIG_CODEC != SWCODEC
         /* Enable the Left and right A/D Converter */
         audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
-                                sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
+                                 sound_default(SOUND_RIGHT_GAIN),
+                                 AUDIO_GAIN_LINEIN);
         mas_codec_writereg(6, 0x4000);
 #endif
 #endif
-        if(radio_status == FMRADIO_PAUSED)
-            radio_status = FMRADIO_PAUSED_OUT;
-        else
-            radio_status = FMRADIO_PLAYING_OUT;
-
     }
     else
     {
-        radio_stop();
 #if CONFIG_CODEC == SWCODEC
-        peak_meter_enabled = true;
+        rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
+#else
+        radio_stop();
 #endif
     }
     
@@ -1062,9 +1062,11 @@
 
     /* restore status bar settings */
     global_settings.statusbar = statusbar;
+
+    in_screen = false;
     
     return have_recorded;
-}
+} /* radio_screen */
 
 void radio_save_presets(void)
 {
@@ -1106,16 +1108,16 @@
 
 /* No Preset in configuration. */
     if(filename[0] == '\0')
-	{
+    {
         filepreset[0] = '\0';
         return;
-	}
+    }
 /* Temporary preset, loaded until player shuts down. */
     else if(filename[0] == '/') 
         strncpy(filepreset, filename, sizeof(filepreset));
 /* Preset from default directory. */
     else
-	    snprintf(filepreset, sizeof(filepreset), "%s/%s.fmr",
+        snprintf(filepreset, sizeof(filepreset), "%s/%s.fmr",
             FMPRESET_PATH, filename);
     
     fd = open(filepreset, O_RDONLY);
@@ -1466,30 +1468,6 @@
     return reload_dir;
 }
 
-#ifndef SIMULATOR
-#if CONFIG_CODEC != SWCODEC
-static bool fm_recording_settings(void)
-{
-    bool ret;
-    
-    ret = recording_menu(true);
-    if(!ret)
-    {
-        if (global_settings.rec_prerecord_time)
-            talk_buffer_steal(); /* will use the mp3 buffer */
-
-        audio_set_recording_options(global_settings.rec_frequency,
-                                   global_settings.rec_quality,
-                                   1, /* Line In */
-                                   global_settings.rec_channels,
-                                   global_settings.rec_editable,
-                                   global_settings.rec_prerecord_time);
-    }
-    return ret;
-}
-#endif
-#endif
-
 char monomode_menu_string[32];
 
 static void create_monomode_menu(void)
@@ -1628,6 +1606,55 @@
     return key;
 }
 
+#ifndef SIMULATOR
+#if defined(HAVE_FMRADIO_IN) || CONFIG_CODEC != SWCODEC
+static bool fm_recording_screen(void)
+{
+    bool ret;
+
+#ifdef HAVE_FMRADIO_IN
+    /* switch recording source to FMRADIO for the duration */
+    int rec_source = global_settings.rec_source;
+    global_settings.rec_source = AUDIO_SRC_FMRADIO;
+
+    /* clearing queue seems to cure a spontaneous abort during record */
+    while (button_get(false) != BUTTON_NONE);
+#endif
+
+    ret = recording_screen(true);
+
+#ifdef HAVE_FMRADIO_IN
+    /* safe to reset as changing sources is prohibited here */
+    global_settings.rec_source = rec_source;
+#endif
+
+    return ret;
+}
+
+static bool fm_recording_settings(void)
+{
+    bool ret = recording_menu(true);
+
+    if (!ret)
+    {
+        rec_set_recording_options(global_settings.rec_frequency,
+                                  global_settings.rec_quality,
+#if CONFIG_CODEC == SWCODEC
+                                  AUDIO_SRC_FMRADIO, SRCF_FMRADIO_PLAYING,
+#else
+                                  AUDIO_SRC_LINEIN, 0,
+#endif
+                                  global_settings.rec_channels,
+                                  global_settings.rec_editable,
+                                  global_settings.rec_prerecord_time);
+    }
+
+    return ret;
+}
+#endif
+#endif /* SIMULATOR */
+
+
 /* main menu of the radio screen */
 bool radio_menu(void)
 {
@@ -1637,24 +1664,27 @@
     static const struct menu_item items[] = {
 /* Add functions not accessible via buttons */
 #ifndef FM_PRESET
-        { ID2P(LANG_FM_BUTTONBAR_PRESETS), handle_radio_presets },
+        { ID2P(LANG_FM_BUTTONBAR_PRESETS), handle_radio_presets  },
 #endif
 #ifndef FM_PRESET_ADD
-        { ID2P(LANG_FM_ADD_PRESET)       , radio_add_preset     },
+        { ID2P(LANG_FM_ADD_PRESET)       , radio_add_preset      },
 #endif
-        { ID2P(LANG_FM_PRESET_LOAD)      , load_preset_list     },
-        { ID2P(LANG_FM_PRESET_SAVE)      , save_preset_list     },
-        { ID2P(LANG_FM_PRESET_CLEAR)     , clear_preset_list    },
+        { ID2P(LANG_FM_PRESET_LOAD)      , load_preset_list      },
+        { ID2P(LANG_FM_PRESET_SAVE)      , save_preset_list      },
+        { ID2P(LANG_FM_PRESET_CLEAR)     , clear_preset_list     },
 
-        { monomode_menu_string           , toggle_mono_mode     },
+        { monomode_menu_string           , toggle_mono_mode      },
 #ifndef FM_MODE
-        { radiomode_menu_string          , toggle_radio_mode    },
+        { radiomode_menu_string          , toggle_radio_mode     },
 #endif
-        { ID2P(LANG_SOUND_SETTINGS)      , sound_menu           },
-#if !defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
-        { ID2P(LANG_RECORDING_SETTINGS)  , fm_recording_settings},
+        { ID2P(LANG_SOUND_SETTINGS)      , sound_menu            },
+#ifndef SIMULATOR
+#if defined(HAVE_FMRADIO_IN) || CONFIG_CODEC != SWCODEC
+        { ID2P(LANG_RECORDING_MENU)      , fm_recording_screen   },
+        { ID2P(LANG_RECORDING_SETTINGS)  , fm_recording_settings },
 #endif
-        { ID2P(LANG_FM_SCAN_PRESETS)     , scan_presets         },
+#endif
+        { ID2P(LANG_FM_SCAN_PRESETS)     , scan_presets          },
     };
 
     create_monomode_menu();
diff --git a/apps/recorder/radio.h b/apps/recorder/radio.h
index 86ce04c..fdf446d 100644
--- a/apps/recorder/radio.h
+++ b/apps/recorder/radio.h
@@ -20,19 +20,19 @@
 #define RADIO_H
 #define FMPRESET_PATH ROCKBOX_DIR "/fmpresets"
 
-#define FMRADIO_OFF     0
-#define FMRADIO_PLAYING 1
-#define FMRADIO_PLAYING_OUT  2
-#define FMRADIO_PAUSED  3
-#define FMRADIO_PAUSED_OUT  4
+#ifndef FMRADIO_H
+#include "fmradio.h"
+#endif
 
 #ifdef CONFIG_TUNER
 void radio_load_presets(char *filename);
 void radio_init(void);
 bool radio_screen(void);
+void radio_start(void);
+void radio_pause(void);
 void radio_stop(void);
 bool radio_hardware_present(void);
-int  get_radio_status(void);
+bool in_radio_screen(void);
 
 #define MAX_FMPRESET_LEN 27
 
diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c
index e6b06d5..080cafc 100644
--- a/apps/recorder/recording.c
+++ b/apps/recorder/recording.c
@@ -24,12 +24,14 @@
 #include <stdlib.h>
 
 #include "system.h"
+#include "power.h"
 #include "lcd.h"
 #include "led.h"
 #include "mpeg.h"
 #include "audio.h"
 #if CONFIG_CODEC == SWCODEC
 #include "pcm_record.h"
+#include "playback.h"
 #endif
 #ifdef HAVE_UDA1380
 #include "uda1380.h"
@@ -37,7 +39,7 @@
 #ifdef HAVE_TLV320
 #include "tlv320.h"
 #endif
-
+#include "recording.h"
 #include "mp3_playback.h"
 #include "mas.h"
 #include "button.h"
@@ -66,6 +68,7 @@
 #include "splash.h"
 #include "screen_access.h"
 #include "action.h"
+#include "radio.h"
 #ifdef HAVE_RECORDING
 
 #define PM_HEIGHT ((LCD_HEIGHT >= 72) ? 2 : 1)
@@ -73,21 +76,6 @@
 bool f2_rec_screen(void);
 bool f3_rec_screen(void);
 
-#define SOURCE_MIC   0
-#define SOURCE_LINE  1
-#ifdef HAVE_SPDIF_IN
-#define SOURCE_SPDIF 2
-#define MAX_SOURCE   SOURCE_SPDIF
-#else
-#define MAX_SOURCE   SOURCE_LINE
-#endif
-
-#if CONFIG_CODEC == SWCODEC
-#define REC_FILE_ENDING ".wav"
-#else
-#define REC_FILE_ENDING ".mp3"
-#endif
-
 #define MAX_FILE_SIZE 0x7F800000 /* 2 GB - 4 MB */
 
 int screen_update = NB_SCREENS;
@@ -102,6 +90,19 @@
     "16kHz"
 };
 
+#if CONFIG_CODEC == SWCODEC
+#define REC_ENCODER_ID(q) \
+    rec_quality_info_afmt[q]
+#define REC_QUALITY_LABEL(q) \
+    (audio_formats[REC_ENCODER_ID(q)].label)
+#define REC_FILE_ENDING(q) \
+    (audio_formats[REC_ENCODER_ID(q)].ext)
+#else
+/* default record file extension for HWCODEC */
+#define REC_QUALITY_LABEL(q)    "MP3"
+#define REC_FILE_ENDING(q)      ".mp3"
+#endif
+
 #ifdef HAVE_AGC
 /* Timing counters:
  * peak_time is incremented every 0.2s, every 2nd run of record screen loop.
@@ -161,13 +162,14 @@
 
 static void set_gain(void)
 {
-    if(global_settings.rec_source == SOURCE_MIC)
+    if(global_settings.rec_source == AUDIO_SRC_MIC)
     {
         audio_set_recording_gain(global_settings.rec_mic_gain,
                                  0, AUDIO_GAIN_MIC);
     }
     else
     {
+        /* AUDIO_SRC_LINEIN, AUDIO_SRC_SPDIF, AUDIO_SRC_FMRADIO */
         audio_set_recording_gain(global_settings.rec_left_gain,
                                  global_settings.rec_right_gain,
                                  AUDIO_GAIN_LINEIN);
@@ -217,12 +219,16 @@
     if (agc_preset == 0)
         return false;
 
-    if (global_settings.rec_source == SOURCE_LINE)
+    switch (global_settings.rec_source)
     {
+    case AUDIO_SRC_LINEIN:
+#ifdef HAVE_FMRADIO_IN
+    case AUDIO_SRC_FMRADIO:
+#endif
         gain_current_l = global_settings.rec_left_gain;
         gain_current_r = global_settings.rec_right_gain;
-    } else
-    {
+        break;
+    default:
         gain_current_l = global_settings.rec_mic_gain;
         gain_current_r = global_settings.rec_mic_gain;
     }
@@ -235,13 +241,16 @@
 {
     int factor = (increment ? 1 : -1);
 
-    if (global_settings.rec_source == SOURCE_LINE)
+    switch (global_settings.rec_source)
     {
+    case AUDIO_SRC_LINEIN:
+#ifdef HAVE_FMRADIO_IN
+    case AUDIO_SRC_FMRADIO:
+#endif
         if(left) global_settings.rec_left_gain += factor;
         if (right) global_settings.rec_right_gain += factor;
-    }
-    else
-    {
+        break;
+    default:
          global_settings.rec_mic_gain += factor;
     }
 }
@@ -443,12 +452,15 @@
 #ifdef HAVE_AGC
     switch(global_settings.rec_source)
     {
-    case SOURCE_MIC:
+    case AUDIO_SRC_MIC:
         if(cursor == 2)
             cursor = 4;
         else if(cursor == 3)
             cursor = 1;
-    case SOURCE_LINE:
+    case AUDIO_SRC_LINEIN:
+#ifdef HAVE_FMRADIO_IN
+    case AUDIO_SRC_FMRADIO:
+#endif
         max_cursor = 5;
         break;
     default:
@@ -458,10 +470,13 @@
 #else
     switch(global_settings.rec_source)
     {
-    case SOURCE_MIC:
+    case AUDIO_SRC_MIC:
         max_cursor = 1;
         break;
-    case SOURCE_LINE:
+    case AUDIO_SRC_LINEIN:
+#ifdef HAVE_FMRADIO_IN
+    case AUDIO_SRC_FMRADIO:
+#endif
         max_cursor = 3;
         break;
     default:
@@ -481,10 +496,13 @@
     else
         strncpy(buffer, rec_base_directory, MAX_PATH);
 
+
 #ifdef CONFIG_RTC 
-    create_datetime_filename(buffer, buffer, "R", REC_FILE_ENDING);
+    create_datetime_filename(buffer, buffer, "R",
+        REC_FILE_ENDING(global_settings.rec_quality));
 #else
-    create_numbered_filename(buffer, buffer, "rec_", REC_FILE_ENDING, 4);
+    create_numbered_filename(buffer, buffer, "rec_",
+        REC_FILE_ENDING(global_settings.rec_quality), 4);
 #endif
     return buffer;
 }
@@ -515,8 +533,190 @@
     return 0;
 }
 
+#if CONFIG_CODEC == SWCODEC && !defined(SIMULATOR)
+/**
+ * Selects an audio source for recording or playback
+ * powers/unpowers related devices.
+ * Here because it calls app code and used only for HAVE_RECORDING atm.
+ * Would like it in pcm_record.c.
+ */
+#if defined(HAVE_UDA1380)
+#define ac_disable_recording uda1380_disable_recording
+#define ac_enable_recording  uda1380_enable_recording
+#define ac_set_monitor       uda1380_set_monitor
+#elif defined(HAVE_TLV320)
+#define ac_disable_recording tlv320_disable_recording
+#define ac_enable_recording  tlv320_enable_recording
+#define ac_set_monitor       tlv320_set_monitor
+#endif
+
+void rec_set_source(int source, int flags)
+{
+    /* Prevent pops from unneeded switching */
+    static int last_source = AUDIO_SRC_PLAYBACK;
+#ifdef HAVE_TLV320
+    static bool last_recording = false;
+#endif
+
+    bool recording = flags & SRCF_RECORDING;
+    /* Default to peakmeter record. */
+    bool pm_playback = false;
+    bool pm_enabled = true;
+
+    /** Do power up/down of associated device(s) **/
+
+#ifdef HAVE_SPDIF_IN
+    if ((source == AUDIO_SRC_SPDIF) != (source == last_source))
+        cpu_boost(source == AUDIO_SRC_SPDIF);
+
+#ifdef HAVE_SPDIF_POWER
+    /* Check if S/PDIF output power should be switched off or on. NOTE: assumes
+       both optical in and out is controlled by the same power source, which is
+       the case on H1x0. */
+    spdif_power_enable((source == AUDIO_SRC_SPDIF) ||
+                       global_settings.spdif_enable);
+#endif
+#endif
+
+#ifdef CONFIG_TUNER
+    /* Switch radio off or on per source and flags. */
+    if (source != AUDIO_SRC_FMRADIO)
+        radio_stop();
+    else if (flags & SRCF_FMRADIO_PAUSED)
+        radio_pause();
+    else
+        radio_start();
+#endif
+
+    switch (source)
+    {
+        default:                        /* playback - no recording */
+            pm_playback = true;
+            if (source == last_source)
+                break;
+            ac_disable_recording();
+            ac_set_monitor(false);
+            pcm_rec_mux(0);             /* line in */
+        break;
+
+        case AUDIO_SRC_MIC:             /* recording only */
+            if (source == last_source)
+                break;
+            ac_enable_recording(true);  /* source mic */
+            pcm_rec_mux(0);             /* line in */
+        break;
+
+        case AUDIO_SRC_LINEIN:          /* recording only */
+            if (source == last_source)
+                break;
+            pcm_rec_mux(0);             /* line in */
+            ac_enable_recording(false); /* source line */
+        break;
+
+#ifdef HAVE_SPDIF_IN
+        case AUDIO_SRC_SPDIF:           /* recording only */
+            if (recording)
+            {
+                /* This was originally done in audio_set_recording_options only */
+#ifdef HAVE_SPDIF_POWER
+                EBU1CONFIG = global_settings.spdif_enable ? (1 << 2) : 0;
+                /* Input source is EBUin1, Feed-through monitoring if desired */
+#else
+                EBU1CONFIG = (1 << 2);
+                /* Input source is EBUin1, Feed-through monitoring */
+#endif
+            }
+
+            if (source != last_source)
+                uda1380_disable_recording();
+        break;
+#endif /* HAVE_SPDIF_IN */
+
+#ifdef HAVE_FMRADIO_IN
+        case AUDIO_SRC_FMRADIO:
+            if (!recording)
+            {
+                audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
+                        sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
+                pm_playback = true;
+                pm_enabled = false;
+            }
+
+            pcm_rec_mux(1);                     /* fm radio */
+
+#ifdef HAVE_UDA1380
+            if (source == last_source)
+                break;
+            /* I2S recording and playback */
+            uda1380_enable_recording(false);    /* source line */
+            uda1380_set_monitor(true);
+#endif
+#ifdef HAVE_TLV320
+            /* I2S recording and analog playback */
+            if (source == last_source && recording == last_recording)
+                break;
+
+            last_recording = recording;
+
+            if (recording)
+                tlv320_enable_recording(false); /* source line */
+            else
+            {
+                tlv320_disable_recording();
+                tlv320_set_monitor(true);       /* analog bypass */
+            }
+#endif
+        break;
+/* #elif defined(CONFIG_TUNER)  */
+/* Have radio but cannot record it */
+/*      case AUDIO_SRC_FMRADIO: */
+/*          break;              */
+#endif /* HAVE_FMRADIO_IN */
+    } /* end switch */
+
+    peak_meter_playback(pm_playback);
+    peak_meter_enabled = pm_enabled;
+
+    last_source = source;
+} /* rec_set_source */
+#endif /* CONFIG_CODEC == SWCODEC && !defined(SIMULATOR) */
+
+/* steal the mp3 buffer then actually set options */
+void rec_set_recording_options(int frequency, int quality,
+                               int source, int source_flags,
+                               int channel_mode, bool editable,
+                               int prerecord_time)
+{
+#if CONFIG_CODEC != SWCODEC
+    if (global_settings.rec_prerecord_time)
+#endif
+        talk_buffer_steal(); /* will use the mp3 buffer */
+
+#if CONFIG_CODEC == SWCODEC
+    rec_set_source(source, source_flags | SRCF_RECORDING);
+#else
+    (void)source_flags;
+#endif
+
+    audio_set_recording_options(frequency, quality, source,
+        channel_mode, editable, prerecord_time);
+}
+
 static char path_buffer[MAX_PATH];
 
+/* steals mp3 buffer, creates unique filename and starts recording */
+void rec_record(void)
+{
+    talk_buffer_steal(); /* we use the mp3 buffer */
+    audio_record(rec_create_filename(path_buffer));
+}
+
+/* creates unique filename and starts recording */
+void rec_new_file(void)
+{
+    audio_new_file(rec_create_filename(path_buffer));
+}
+
 /* used in trigger_listerner and recording_screen */
 static unsigned int last_seconds = 0;
 
@@ -533,16 +733,16 @@
             if((audio_status() & AUDIO_STATUS_RECORD) != AUDIO_STATUS_RECORD)
             {
                 talk_buffer_steal(); /* we use the mp3 buffer */
-                audio_record(rec_create_filename(path_buffer));
-
-                /* give control to mpeg thread so that it can start recording*/
+                rec_record();
+                /* give control to mpeg thread so that it can start
+                   recording */
                 yield(); yield(); yield();
             }
 
             /* if we're already recording this is a retrigger */
             else
             {
-                audio_new_file(rec_create_filename(path_buffer));
+                rec_new_file();
                 /* tell recording_screen to reset the time */
                 last_seconds = 0;
             }
@@ -563,10 +763,9 @@
     }
 }
 
-bool recording_screen(void)
+bool recording_screen(bool no_source)
 {
     long button;
-    long lastbutton = BUTTON_NONE;
     bool done = false;
     char buf[32];
     char buf2[32];
@@ -575,11 +774,19 @@
     bool have_recorded = false;
     unsigned int seconds;
     int hours, minutes;
-    char path_buffer[MAX_PATH];
     char filename[13];
     bool been_in_usb_mode = false;
     int last_audio_stat = -1;
     int audio_stat;
+#ifdef HAVE_FMRADIO_IN
+    /* Radio is left on if:
+     *   1) Is was on at the start and the initial source is FM Radio
+     *   2) 1) and the source was never changed to something else
+     */
+    int radio_status = (global_settings.rec_source != AUDIO_SRC_FMRADIO) ?
+                            FMRADIO_OFF : get_radio_status();
+#endif
+    int talk_menu = global_settings.talk_menu;
 #if CONFIG_LED == LED_REAL
     bool led_state = false;
     int led_countdown = 2;
@@ -608,6 +815,18 @@
     ata_set_led_enabled(false);
 #endif
 
+#if CONFIG_CODEC == SWCODEC
+    audio_stop();
+    voice_stop();
+    /* recording_menu gets messed up: so reset talk_menu */
+    talk_menu = global_settings.talk_menu;
+    global_settings.talk_menu = 0;
+#else
+    /* Yes, we use the D/A for monitoring */
+    peak_meter_enabled = true;
+    peak_meter_playback(true);
+#endif
+
 #ifndef SIMULATOR
     audio_init_recording(talk_get_bufsize());
 #else
@@ -616,44 +835,19 @@
 
     sound_set_volume(global_settings.volume);
 
-#if CONFIG_CODEC == SWCODEC
-    audio_stop();
-    /* Set peak meter to recording mode */
-    peak_meter_playback(false);
-
-#if defined(HAVE_SPDIF_IN) && !defined(SIMULATOR)
-    if (global_settings.rec_source == SOURCE_SPDIF)
-        cpu_boost(true);
-#endif
-
-#else
-    /* Yes, we use the D/A for monitoring */
-    peak_meter_playback(true);
-#endif
-    peak_meter_enabled = true;
 #ifdef HAVE_AGC
     peak_meter_get_peakhold(&peak_l, &peak_r);
 #endif
 
-#if CONFIG_CODEC != SWCODEC
-    if (global_settings.rec_prerecord_time)
-#endif
-        talk_buffer_steal(); /* will use the mp3 buffer */
-
-#if defined(HAVE_SPDIF_POWER) && !defined(SIMULATOR)
-    /* Tell recording whether we want S/PDIF power enabled at all times */
-    audio_set_spdif_power_setting(global_settings.spdif_enable);
-#endif
-
-    audio_set_recording_options(global_settings.rec_frequency,
-                               global_settings.rec_quality,
-                               global_settings.rec_source,
-                               global_settings.rec_channels,
-                               global_settings.rec_editable,
-                               global_settings.rec_prerecord_time);
+    rec_set_recording_options(global_settings.rec_frequency,
+                              global_settings.rec_quality,
+                              global_settings.rec_source,
+                              0,
+                              global_settings.rec_channels,
+                              global_settings.rec_editable,
+                              global_settings.rec_prerecord_time);
 
     set_gain();
-
     settings_apply_trigger();
 
 #ifdef HAVE_AGC
@@ -663,7 +857,7 @@
     agc_preset_str[3] = str(LANG_AGC_DJSET);
     agc_preset_str[4] = str(LANG_AGC_MEDIUM);
     agc_preset_str[5] = str(LANG_AGC_VOICE);
-    if (global_settings.rec_source == SOURCE_MIC) {
+    if (global_settings.rec_source == AUDIO_SRC_MIC) {
         agc_preset = global_settings.rec_agc_preset_mic;
         agc_maxgain = global_settings.rec_agc_maxgain_mic;
     }
@@ -697,11 +891,7 @@
 
     while(!done)
     {
-#if CONFIG_CODEC == SWCODEC        
-        audio_stat = pcm_rec_status();
-#else
         audio_stat = audio_status();
-#endif
         
 #if CONFIG_LED == LED_REAL
 
@@ -794,8 +984,8 @@
                 }
                 else
                 {
-                    peak_meter_playback(true);
 #if CONFIG_CODEC != SWCODEC
+                    peak_meter_playback(true);
                     peak_meter_enabled = false;
 #endif                    
                     done = true;
@@ -815,14 +1005,13 @@
                         /* manual recording */
                         have_recorded = true;
                         talk_buffer_steal(); /* we use the mp3 buffer */
-                        audio_record(rec_create_filename(path_buffer));
+                        rec_record();
                         last_seconds = 0;
-                        if (global_settings.talk_menu)
+                        if (talk_menu)
                         {   /* no voice possible here, but a beep */
                             audio_beep(HZ/2); /* longer beep on start */
                         }
                     }
-
                     /* this is triggered recording */
                     else
                     {
@@ -838,7 +1027,7 @@
                     /*if new file button pressed, start new file */
                     if (button == ACTION_REC_NEWFILE)
                     {
-                        audio_new_file(rec_create_filename(path_buffer));
+                        rec_new_file();
                         last_seconds = 0;
                     }
                     else
@@ -847,7 +1036,7 @@
                         if(audio_stat & AUDIO_STATUS_PAUSE)
                         {
                             audio_resume_recording();
-                            if (global_settings.talk_menu)
+                            if (talk_menu)
                             {   /* no voice possible here, but a beep */
                                 audio_beep(HZ/4); /* short beep on resume */
                             }
@@ -883,7 +1072,7 @@
                         sound_set_volume(global_settings.volume);
                         break;
                     case 1:
-                        if(global_settings.rec_source == SOURCE_MIC)
+                        if(global_settings.rec_source == AUDIO_SRC_MIC)
                         {
                             if(global_settings.rec_mic_gain <
                                sound_max(SOUND_MIC_GAIN))
@@ -913,7 +1102,7 @@
                     case 4:
                         agc_preset = MIN(agc_preset + 1, AGC_MODE_SIZE);
                         agc_enable = (agc_preset != 0);
-                        if (global_settings.rec_source == SOURCE_MIC) {
+                        if (global_settings.rec_source == AUDIO_SRC_MIC) {
                             global_settings.rec_agc_preset_mic = agc_preset;
                             agc_maxgain = global_settings.rec_agc_maxgain_mic;
                         } else {
@@ -922,7 +1111,7 @@
                         }
                         break;
                     case 5:
-                        if (global_settings.rec_source == SOURCE_MIC)
+                        if (global_settings.rec_source == AUDIO_SRC_MIC)
                         {
                             agc_maxgain = MIN(agc_maxgain + 1,
                                               sound_max(SOUND_MIC_GAIN));
@@ -951,7 +1140,7 @@
                         sound_set_volume(global_settings.volume);
                         break;
                     case 1:
-                        if(global_settings.rec_source == SOURCE_MIC)
+                        if(global_settings.rec_source == AUDIO_SRC_MIC)
                         {
                             if(global_settings.rec_mic_gain >
                                sound_min(SOUND_MIC_GAIN))
@@ -981,7 +1170,7 @@
                     case 4:
                         agc_preset = MAX(agc_preset - 1, 0);
                         agc_enable = (agc_preset != 0);
-                        if (global_settings.rec_source == SOURCE_MIC) {
+                        if (global_settings.rec_source == AUDIO_SRC_MIC) {
                             global_settings.rec_agc_preset_mic = agc_preset;
                             agc_maxgain = global_settings.rec_agc_maxgain_mic;
                         } else {
@@ -990,7 +1179,7 @@
                         }
                         break;
                     case 5:
-                        if (global_settings.rec_source == SOURCE_MIC)
+                        if (global_settings.rec_source == AUDIO_SRC_MIC)
                         {
                             agc_maxgain = MAX(agc_maxgain - 1,
                                               sound_min(SOUND_MIC_GAIN));
@@ -1012,49 +1201,73 @@
             case ACTION_STD_MENU:
                 if(audio_stat != AUDIO_STATUS_RECORD)
                 {
+#ifdef HAVE_FMRADIO_IN
+                    const int prev_rec_source = global_settings.rec_source;
+#endif
+
 #if CONFIG_LED == LED_REAL
                     /* led is restored at begin of loop / end of function */
                     led(false);
 #endif
-                    if (recording_menu(false))
+                    if (recording_menu(no_source))
                     {
-                        return SYS_USB_CONNECTED;
-                    }
-                    settings_save();
-
-#if CONFIG_CODEC != SWCODEC
-                    if (global_settings.rec_prerecord_time)
+                        done = true;
+                        been_in_usb_mode = true;
+#ifdef HAVE_FMRADIO_IN
+                        radio_status = FMRADIO_OFF;
 #endif
-                        talk_buffer_steal(); /* will use the mp3 buffer */
+                    }
+                    else
+                    {
+                        settings_save();
 
-                    audio_set_recording_options(global_settings.rec_frequency,
-                                               global_settings.rec_quality,
-                                               global_settings.rec_source,
-                                               global_settings.rec_channels,
-                                               global_settings.rec_editable,
-                                               global_settings.rec_prerecord_time);
+#ifdef HAVE_FMRADIO_IN
+                        /* If input changes away from FM Radio, radio will
+                           remain off when recording screen closes. */
+                        if (global_settings.rec_source != prev_rec_source
+                            && prev_rec_source == AUDIO_SRC_FMRADIO)
+                            radio_status = FMRADIO_OFF;
+#endif
+
+#if CONFIG_CODEC == SWCODEC
+                        /* reinit after submenu exit */
+                        audio_close_recording();
+                        audio_init_recording(talk_get_bufsize());
+#endif
+                        rec_set_recording_options(
+                            global_settings.rec_frequency,
+                            global_settings.rec_quality,
+                            global_settings.rec_source,
+                            0,
+                            global_settings.rec_channels,
+                            global_settings.rec_editable,
+                            global_settings.rec_prerecord_time);
+
 #ifdef HAVE_AGC
-                    if (global_settings.rec_source == SOURCE_MIC) {
-                        agc_preset = global_settings.rec_agc_preset_mic;
-                        agc_maxgain = global_settings.rec_agc_maxgain_mic;
-                    }
-                    else {
-                        agc_preset = global_settings.rec_agc_preset_line;
-                        agc_maxgain = global_settings.rec_agc_maxgain_line;
-                    }
+                        if (global_settings.rec_source == AUDIO_SRC_MIC) {
+                            agc_preset = global_settings.rec_agc_preset_mic;
+                            agc_maxgain = global_settings.rec_agc_maxgain_mic;
+                        }
+                        else {
+                            agc_preset = global_settings.rec_agc_preset_line;
+                            agc_maxgain = global_settings.rec_agc_maxgain_line;
+                        }
 #endif
 
-                    adjust_cursor();
-                    set_gain();
-                    update_countdown = 1; /* Update immediately */
+                        adjust_cursor();
+                        set_gain();
+                        update_countdown = 1; /* Update immediately */
 
-                    FOR_NB_SCREENS(i)
-                    {
-                        screens[i].setfont(FONT_SYSFIXED);
-                        screens[i].setmargins(global_settings.invert_cursor ? 0 : w, 8);
+                        FOR_NB_SCREENS(i)
+                        {
+                            screens[i].setfont(FONT_SYSFIXED);
+                            screens[i].setmargins(
+                                global_settings.invert_cursor ? 0 : w, 8);
+                        }
                     }
                 }
                 break;
+
 #if CONFIG_KEYPAD == RECORDER_PAD
             case ACTION_REC_F2:
                 if(audio_stat != AUDIO_STATUS_RECORD)
@@ -1076,7 +1289,7 @@
             case ACTION_REC_F3:
                 if(audio_stat & AUDIO_STATUS_RECORD)
                 {
-                    audio_new_file(rec_create_filename(path_buffer));
+                    rec_new_file();
                     last_seconds = 0;
                 }
                 else
@@ -1097,7 +1310,7 @@
                     }
                 }
                 break;
-#endif
+#endif /*  CONFIG_KEYPAD == RECORDER_PAD */
 
             case SYS_USB_CONNECTED:
                 /* Only accept USB connection when not recording */
@@ -1106,6 +1319,9 @@
                     default_event_handler(SYS_USB_CONNECTED);
                     done = true;
                     been_in_usb_mode = true;
+#ifdef HAVE_FMRADIO_IN
+                    radio_status = FMRADIO_OFF;
+#endif
                 }
                 break;
                 
@@ -1113,8 +1329,6 @@
                 default_event_handler(button);
                 break;
         }
-        if (button != BUTTON_NONE)
-            lastbutton = button;
 
 #ifdef HAVE_AGC
         peak_read = !peak_read;
@@ -1230,7 +1444,7 @@
                 if (!(global_settings.rec_split_type)
                      || (num_recorded_bytes >= MAX_FILE_SIZE))
                 {
-                    audio_new_file(rec_create_filename(path_buffer));
+                    rec_new_file();
                     last_seconds = 0;
                 }
                 else
@@ -1259,8 +1473,9 @@
                     screens[i].puts(0, filename_offset[i] + PM_HEIGHT + 2, buf);
             }                
 
-            if(global_settings.rec_source == SOURCE_MIC)
-            { 
+            if(global_settings.rec_source == AUDIO_SRC_MIC)
+            {
+                /* Draw MIC recording gain */
                 snprintf(buf, 32, "%s:%s", str(LANG_SYSFONT_RECORDING_GAIN),
                          fmt_gain(SOUND_MIC_GAIN,
                                   global_settings.rec_mic_gain,
@@ -1278,8 +1493,13 @@
                                             PM_HEIGHT + 3, buf);
                 }
             }
-            else if(global_settings.rec_source == SOURCE_LINE)
+            else if(global_settings.rec_source == AUDIO_SRC_LINEIN
+#ifdef HAVE_FMRADIO_IN
+                    || global_settings.rec_source == AUDIO_SRC_FMRADIO
+#endif
+                    )
             {
+                /* Draw LINE or FMRADIO recording gain */
                 snprintf(buf, 32, "%s:%s",
                          str(LANG_SYSFONT_RECORDING_LEFT),
                          fmt_gain(SOUND_LEFT_GAIN,
@@ -1319,14 +1539,23 @@
 
             FOR_NB_SCREENS(i)
             {
-                if (global_settings.rec_source == SOURCE_LINE)
-                    line[i] = 5;
-                else if (global_settings.rec_source == SOURCE_MIC)
-                    line[i] = 4;
-#ifdef HAVE_SPDIF_IN
-                else if (global_settings.rec_source == SOURCE_SPDIF)
-                    line[i] = 3;
+                switch (global_settings.rec_source)
+                {
+                case AUDIO_SRC_LINEIN:
+#ifdef HAVE_FMRADIO_IN
+                case AUDIO_SRC_FMRADIO:
 #endif
+                    line[i] = 5;
+                    break;
+                case AUDIO_SRC_MIC:
+                    line[i] = 4;
+                    break;
+#ifdef HAVE_SPDIF_IN
+                case AUDIO_SRC_SPDIF:
+                    line[i] = 3;
+                    break;
+#endif
+                } /* end switch */
 #ifdef HAVE_AGC
                 if (screens[i].height < h * (2 + filename_offset[i] + PM_HEIGHT + line[i]))
                 {
@@ -1358,7 +1587,7 @@
                 snprintf(buf, 32, "%s: %s",
                          str(LANG_RECORDING_AGC_PRESET),
                          agc_preset_str[agc_preset]);
-            else if (global_settings.rec_source == SOURCE_MIC)
+            else if (global_settings.rec_source == AUDIO_SRC_MIC)
                 snprintf(buf, 32, "%s: %s%s",
                          str(LANG_RECORDING_AGC_PRESET),
                          agc_preset_str[agc_preset],
@@ -1382,8 +1611,12 @@
                     screens[i].puts_style_offset(0, filename_offset[i] + 
                                         PM_HEIGHT + line[i], buf, STYLE_INVERT,0);
             }
-            else if ((global_settings.rec_source == SOURCE_MIC) 
-                    || (global_settings.rec_source == SOURCE_LINE))    
+            else if (global_settings.rec_source == AUDIO_SRC_MIC
+                    || global_settings.rec_source == AUDIO_SRC_LINEIN
+#ifdef HAVE_FMRADIO_IN
+                    || global_settings.rec_source == AUDIO_SRC_FMRADIO
+#endif
+                    )    
             {
                 for(i = 0; i < screen_update; i++) {
                     if (display_agc[i]) {
@@ -1393,7 +1626,7 @@
                 }
             }
             
-            if (global_settings.rec_source == SOURCE_MIC)
+            if (global_settings.rec_source == AUDIO_SRC_MIC)
             {
                 if(agc_maxgain < (global_settings.rec_mic_gain))
                     change_recording_gain(false, true, true);
@@ -1418,7 +1651,7 @@
                                                     filename_offset[i] +
                                                     PM_HEIGHT + 3, true);
 
-                        if(global_settings.rec_source != SOURCE_MIC)
+                        if(global_settings.rec_source != AUDIO_SRC_MIC)
                         {
                             for(i = 0; i < screen_update; i++)
                                 screen_put_cursorxy(&screens[i], 0, 
@@ -1456,14 +1689,14 @@
             }
 /* Can't measure S/PDIF sample rate on Archos yet */
 #if (CONFIG_CODEC != MAS3587F) && defined(HAVE_SPDIF_IN) && !defined(SIMULATOR)
-            if (global_settings.rec_source == SOURCE_SPDIF)
+            if (global_settings.rec_source == AUDIO_SRC_SPDIF)
                 snprintf(spdif_sfreq, 8, "%dHz", audio_get_spdif_sample_rate());
 #else
             (void)spdif_sfreq;
 #endif
             snprintf(buf, 32, "%s %s",
 #if (CONFIG_CODEC != MAS3587F) && defined(HAVE_SPDIF_IN) && !defined(SIMULATOR)
-                     global_settings.rec_source == SOURCE_SPDIF ?
+                     global_settings.rec_source == AUDIO_SRC_SPDIF ?
                      spdif_sfreq :
 #endif
                      freq_str[global_settings.rec_frequency],
@@ -1473,8 +1706,8 @@
 
             for(i = 0; i < screen_update; i++) {
 #ifdef HAVE_AGC
-                if ((global_settings.rec_source == SOURCE_MIC)
-                         || (global_settings.rec_source == SOURCE_LINE))
+                if ((global_settings.rec_source == AUDIO_SRC_MIC)
+                         || (global_settings.rec_source == AUDIO_SRC_LINEIN))
                     screens[i].puts(0, filename_offset[i] + PM_HEIGHT + line[i] + 1, buf);
                 else
 #endif
@@ -1484,6 +1717,14 @@
 #ifdef HAVE_AGC
             hist_time++;
 #endif
+
+#if CONFIG_CODEC == SWCODEC
+            snprintf(buf, 32, "%s",
+                REC_QUALITY_LABEL(global_settings.rec_quality));
+            for(i = 0; i < screen_update; i++)
+                screens[i].puts(0, filename_offset[i] + PM_HEIGHT + 6, buf);
+#endif
+
             for(i = 0; i < screen_update; i++)
             {
                 gui_statusbar_draw(&(statusbars.statusbars[i]), true);
@@ -1506,7 +1747,7 @@
         {
             done = true;
         }
-    }
+    } /* end while(!done) */
 
     
 #if CONFIG_CODEC == SWCODEC        
@@ -1531,18 +1772,26 @@
         }
     }
     
-#if CONFIG_CODEC == SWCODEC        
+#if CONFIG_CODEC == SWCODEC
     audio_stop_recording(); 
     audio_close_recording();
 
-#if defined(HAVE_SPDIF_IN) && !defined(SIMULATOR)
-    if (global_settings.rec_source == SOURCE_SPDIF)
-        cpu_boost(false);
+#ifdef HAVE_FMRADIO_IN
+    if (radio_status != FMRADIO_OFF)
+        /* Restore radio playback - radio_status should be unchanged if started
+           through fm radio screen (barring usb connect) */
+        rec_set_source(AUDIO_SRC_FMRADIO, (radio_status & FMRADIO_PAUSED) ?
+                            SRCF_FMRADIO_PAUSED : SRCF_FMRADIO_PLAYING);
+    else
 #endif
+        /* Go back to playback mode */
+        rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
 
-#else
+    /* restore talk_menu setting */
+    global_settings.talk_menu = talk_menu;
+#else /* !SWCODEC */
     audio_init_playback();
-#endif
+#endif /* CONFIG_CODEC == SWCODEC */
 
     /* make sure the trigger is really turned off */
     peak_meter_trigger(false);
@@ -1560,7 +1809,7 @@
     ata_set_led_enabled(true);
 #endif
     return been_in_usb_mode;
-}
+} /* recording_screen */
 
 #if CONFIG_KEYPAD == RECORDER_PAD
 bool f2_rec_screen(void)
@@ -1680,15 +1929,13 @@
         }
     }
 
-    if (global_settings.rec_prerecord_time)
-        talk_buffer_steal(); /* will use the mp3 buffer */
-
-    audio_set_recording_options(global_settings.rec_frequency,
-                               global_settings.rec_quality,
-                               global_settings.rec_source,
-                               global_settings.rec_channels,
-                               global_settings.rec_editable,
-                               global_settings.rec_prerecord_time);
+    rec_set_recording_options(global_settings.rec_frequency,
+                              global_settings.rec_quality,
+                              global_settings.rec_source,
+                              0,
+                              global_settings.rec_channels,
+                              global_settings.rec_editable,
+                              global_settings.rec_prerecord_time);
 
     set_gain();
     
@@ -1760,7 +2007,7 @@
             case BUTTON_LEFT:
             case BUTTON_F3 | BUTTON_LEFT:
                 global_settings.rec_source++;
-                if(global_settings.rec_source > MAX_SOURCE)
+                if(global_settings.rec_source > AUDIO_SRC_MAX)
                     global_settings.rec_source = 0;
                 used = true;
                 break;
@@ -1782,16 +2029,13 @@
         }
     }
 
-    if (global_settings.rec_prerecord_time)
-        talk_buffer_steal(); /* will use the mp3 buffer */
-
-    audio_set_recording_options(global_settings.rec_frequency,
-                               global_settings.rec_quality,
-                               global_settings.rec_source,
-                               global_settings.rec_channels,
-                               global_settings.rec_editable,
-                               global_settings.rec_prerecord_time);
-                                                              
+    rec_set_recording_options(global_settings.rec_frequency,
+                              global_settings.rec_quality,
+                              global_settings.rec_source,
+                              0,
+                              global_settings.rec_channels,
+                              global_settings.rec_editable,
+                              global_settings.rec_prerecord_time);
 
     set_gain();
 
@@ -1801,7 +2045,7 @@
 
     return false;
 }
-#endif /* #ifdef RECORDER_PAD */
+#endif /* CONFIG_KEYPAD == RECORDER_PAD */
 
 #if CONFIG_CODEC == SWCODEC
 void audio_beep(int duration)
@@ -1831,6 +2075,14 @@
     return 5 * 1024 * 1024;
 }
 
+#if CONFIG_CODEC == SWCODEC
+void rec_set_source(int source, int flags)
+{
+    source = source;
+    flags = flags;
+}
+#endif
+
 void audio_set_recording_options(int frequency, int quality,
                                 int source, int channel_mode,
                                 bool editable, int prerecord_time)
diff --git a/apps/recorder/recording.h b/apps/recorder/recording.h
index 384b34f..aa216e7 100644
--- a/apps/recorder/recording.h
+++ b/apps/recorder/recording.h
@@ -19,8 +19,33 @@
 #ifndef RECORDING_H
 #define RECORDING_H
 
-bool recording_screen(void);
+bool recording_screen(bool no_source);
 char *rec_create_filename(char *buf);
 int rec_create_directory(void);
 
+#if CONFIG_CODEC == SWCODEC
+/* selects an audio source for recording or playback */
+#define SRCF_PLAYBACK         0x0000    /* default */
+#define SRCF_RECORDING        0x1000
+#ifdef CONFIG_TUNER
+/* for AUDIO_SRC_FMRADIO */
+#define SRCF_FMRADIO_PLAYING  0x0000    /* default */
+#define SRCF_FMRADIO_PAUSED   0x2000
+#endif
+void rec_set_source(int source, int flags);
+#endif /* CONFIG_CODEC == SW_CODEC */
+
+/* steals mp3 buffer, sets source and then options */
+/* SRCF_RECORDING is implied */
+void rec_set_recording_options(int frequency, int quality,
+                               int source, int source_flags,
+                               int channel_mode, bool editable,
+                               int prerecord_time);
+
+/* steals mp3 buffer, creates unique filename and starts recording */
+void rec_record(void);
+
+/* creates unique filename and starts recording */
+void rec_new_file(void);
+
 #endif
diff --git a/apps/settings.c b/apps/settings.c
index 49b8f98..acaeedc 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -92,7 +92,7 @@
 #include "dsp.h"
 #endif
 
-#define CONFIG_BLOCK_VERSION 50
+#define CONFIG_BLOCK_VERSION 51
 #define CONFIG_BLOCK_SIZE 512
 #define RTC_BLOCK_SIZE 44
 
@@ -473,11 +473,21 @@
     {1, S_O(rec_split_type), 0, "rec split type", "Split, Stop" },
     {1, S_O(rec_split_method), 0, "rec split method", "Time,Filesize" },
 
-#ifdef HAVE_SPDIF_IN
-    {2, S_O(rec_source), 0 /* 0=mic */, "rec source", "mic,line,spdif" },
+    {
+#if defined(HAVE_SPDIF_IN) || defined(HAVE_FMRADIO_IN)
+        2,
 #else
-    {1, S_O(rec_source), 0 /* 0=mic */, "rec source", "mic,line" },
+        1,
 #endif
+        S_O(rec_source), 0 /* 0=mic */, "rec source",
+        "mic,line"
+#ifdef HAVE_SPDIF_IN
+        ",spdif"
+#endif
+#ifdef HAVE_FMRADIO_IN
+        ",fmradio"
+#endif
+    },
     {5, S_O(rec_prerecord_time), 0, "prerecording time", NULL }, /* 0...30 */
     {1, S_O(rec_directory), 0, /* rec_base_directory */
         "rec directory", REC_BASE_DIR ",current" },
@@ -490,14 +500,21 @@
     {4, S_O(rec_right_gain), 2 /* 0dB */, "rec right gain", NULL }, /* 0...15 */
     {3, S_O(rec_frequency), 0, /* 0=44.1kHz */
         "rec frequency", "44,48,32,22,24,16" },
+    {3, S_O(rec_quality), 5 /* 192 kBit/s max */, "rec quality", NULL },
     {1, S_O(rec_editable), false, "editable recordings", off_on },
-    {3, S_O(rec_quality), 5, "rec quality", NULL },
-#elif defined(HAVE_UDA1380)
+#elif defined(HAVE_UDA1380) || defined(HAVE_TLV320)
+#ifdef HAVE_UDA1380
     {8|SIGNED, S_O(rec_mic_gain), 16 /* 8 dB */, "rec mic gain", NULL }, /* -128...+108 */
+#endif
+#ifdef HAVE_TLV320
+    /* TLV320 only has no mic boost or 20db mic boost */
+    {1, S_O(rec_mic_gain), 0 /* 0 dB */, "rec mic gain", NULL }, /* 0db or 20db */
+#endif
     {8|SIGNED, S_O(rec_left_gain), 0, "rec left gain", NULL }, /* -128...+96 */
     {8|SIGNED, S_O(rec_right_gain), 0, "rec right gain", NULL }, /* -128...+96 */
     {3, S_O(rec_frequency), 0, /* 0=44.1kHz */
         "rec frequency", "44,48,32,22,24,16" },
+    {4, S_O(rec_quality), 4 /* MP3 L3 192 kBit/s */, "rec quality", NULL },
 #endif
 
     /* values for the trigger */
diff --git a/apps/settings.h b/apps/settings.h
index d87bc5e..af0eef5 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -42,6 +42,7 @@
 #define BACKDROP_DIR ROCKBOX_DIR"/backdrops"
 #define REC_BASE_DIR "/recordings"
 #define EQS_DIR ROCKBOX_DIR "/eqs"
+#define CODECS_DIR "/codecs"
 
 #define MAX_FILENAME 20
 
diff --git a/apps/sound_menu.c b/apps/sound_menu.c
index 34ed9af..179951a 100644
--- a/apps/sound_menu.c
+++ b/apps/sound_menu.c
@@ -39,6 +39,12 @@
 #include "talk.h"
 #include "misc.h"
 #include "sound.h"
+#ifdef HAVE_RECORDING
+#include "audio.h"
+#ifdef CONFIG_TUNER
+#include "radio.h"
+#endif
+#endif
 #if CONFIG_CODEC == MAS3587F
 #include "peakmeter.h"
 #include "mas.h"
@@ -290,19 +296,68 @@
 #ifdef HAVE_RECORDING
 static bool recsource(void)
 {
-    static const struct opt_items names[] = {
+    int n_opts = AUDIO_NUM_SOURCES;
+
+    struct opt_items names[AUDIO_NUM_SOURCES] = {
         { STR(LANG_RECORDING_SRC_MIC) },
         { STR(LANG_RECORDING_SRC_LINE) },
 #ifdef HAVE_SPDIF_IN
         { STR(LANG_RECORDING_SRC_DIGITAL) },
 #endif
     };
+
+    /* caveat: assumes it's the last item! */
+#ifdef HAVE_FMRADIO_IN
+    if (radio_hardware_present())
+    {
+        names[AUDIO_SRC_FMRADIO].string = ID2P(LANG_FM_RADIO);
+        names[AUDIO_SRC_FMRADIO].voice_id = LANG_FM_RADIO;
+    }
+    else
+        n_opts--;
+#endif
+
     return set_option(str(LANG_RECORDING_SOURCE),
                       &global_settings.rec_source, INT, names,
-                      sizeof(names)/sizeof(struct opt_items), NULL );
+                      n_opts, NULL );
 }
 
 /* To be removed when we add support for sample rates and channel settings */
+#if CONFIG_CODEC == SWCODEC
+static bool recquality(void)
+{
+    static const struct opt_items names[] = {
+        { "MP3   64 kBit/s", TALK_ID(  64, UNIT_KBIT) },
+        { "MP3   96 kBit/s", TALK_ID(  96, UNIT_KBIT) },
+        { "MP3  128 kBit/s", TALK_ID( 128, UNIT_KBIT) },
+        { "MP3  160 kBit/s", TALK_ID( 160, UNIT_KBIT) },
+        { "MP3  192 kBit/s", TALK_ID( 192, UNIT_KBIT) },
+        { "MP3  224 kBit/s", TALK_ID( 224, UNIT_KBIT) },
+        { "MP3  320 kBit/s", TALK_ID( 320, UNIT_KBIT) },
+        { "WV   900 kBit/s", TALK_ID( 900, UNIT_KBIT) },
+        { "WAV 1411 kBit/s", TALK_ID(1411, UNIT_KBIT) }
+    };
+
+    return set_option(str(LANG_RECORDING_QUALITY),
+                      &global_settings.rec_quality, INT,
+                      names, sizeof (names)/sizeof(struct opt_items),
+                      NULL );
+}
+#elif CONFIG_CODEC == MAS3587F
+static bool recquality(void)
+{
+    return set_int(str(LANG_RECORDING_QUALITY), "", UNIT_INT,
+                   &global_settings.rec_quality, 
+                   NULL, 1, 0, 7, NULL );
+}
+
+static bool receditable(void)
+{
+    return set_bool(str(LANG_RECORDING_EDITABLE),
+                    &global_settings.rec_editable);
+}
+#endif
+
 #ifndef HAVE_UDA1380
 static bool recfrequency(void)
 {
@@ -331,21 +386,6 @@
 }
 #endif
 
-#if CONFIG_CODEC == MAS3587F
-static bool recquality(void)
-{
-    return set_int(str(LANG_RECORDING_QUALITY), "", UNIT_INT,
-                   &global_settings.rec_quality, 
-                   NULL, 1, 0, 7, NULL );
-}
-
-static bool receditable(void)
-{
-    return set_bool(str(LANG_RECORDING_EDITABLE),
-                    &global_settings.rec_editable);
-}
-#endif
-
 static bool rectimesplit(void)
 {
     static const struct opt_items names[] = {
@@ -1011,13 +1051,13 @@
     struct menu_item items[13];
     bool result;
 
-#if CONFIG_CODEC == MAS3587F
+#if CONFIG_CODEC == MAS3587F || CONFIG_CODEC == SWCODEC
     items[i].desc = ID2P(LANG_RECORDING_QUALITY);
     items[i++].function = recquality;
 #endif
+#ifndef HAVE_UDA1380
 /* We don't support frequency selection for UDA1380 yet. Let it just stay at
    the default 44100 Hz. */
-#ifndef HAVE_UDA1380
     items[i].desc = ID2P(LANG_RECORDING_FREQUENCY);
     items[i++].function = recfrequency;
 #endif
diff --git a/apps/status.c b/apps/status.c
index ad4cb72..2a57db0 100644
--- a/apps/status.c
+++ b/apps/status.c
@@ -103,10 +103,10 @@
 #ifdef CONFIG_TUNER
     audio_stat = get_radio_status();
 
-    if(audio_stat == FMRADIO_PLAYING)
+    if(audio_stat & FMRADIO_PLAYING)
        return STATUS_RADIO;
 
-    if(audio_stat == FMRADIO_PAUSED)
+    if(audio_stat & FMRADIO_PAUSED)
        return STATUS_RADIO_PAUSE;
 #endif
     
diff --git a/apps/talk.c b/apps/talk.c
index cf68cdf..21c6f4b 100644
--- a/apps/talk.c
+++ b/apps/talk.c
@@ -554,6 +554,7 @@
     }
 #endif
     reset_state();
+
     return 0;
 }
 
@@ -728,6 +729,7 @@
         VOICE_PIXEL,
         VOICE_PER_SEC,
         VOICE_HERTZ,
+        VOICE_KBIT_PER_SEC,
     };
 
 #if CONFIG_CODEC != SWCODEC
diff --git a/apps/talk.h b/apps/talk.h
index 0dc6996..2f2099a 100644
--- a/apps/talk.h
+++ b/apps/talk.h
@@ -41,6 +41,7 @@
     UNIT_PER_SEC, /* per second */
     UNIT_HERTZ,   /* hertz */
     UNIT_MB,      /* Megabytes */
+    UNIT_KBIT,    /* kilobits per sec */
     UNIT_LAST     /* END MARKER */
 };
 
diff --git a/apps/tree.c b/apps/tree.c
index 4558cd5..2d9b1bf 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -577,7 +577,7 @@
         if (global_settings.rec_startup) {
             /* We fake being in the menu structure by calling
                the appropriate parent when we drop out of each screen */
-            recording_screen();
+            recording_screen(false);
             rec_menu();
             main_menu();
         }
diff --git a/firmware/drivers/power.c b/firmware/drivers/power.c
index 67f34e2..d5b75a1 100644
--- a/firmware/drivers/power.c
+++ b/firmware/drivers/power.c
@@ -38,7 +38,7 @@
 
 static bool powered = false;
 
-bool radio_powered()
+bool radio_powered(void)
 {
     return powered;
 }
diff --git a/firmware/export/audio.h b/firmware/export/audio.h
index 9e3499e..2ee7f89 100644
--- a/firmware/export/audio.h
+++ b/firmware/export/audio.h
@@ -31,6 +31,9 @@
 #define AUDIO_STATUS_PRERECORD 8
 #define AUDIO_STATUS_ERROR 16
 
+#define AUDIO_STATUS_STAYON_FLAGS \
+    (AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE | AUDIO_STATUS_RECORD | AUDIO_)
+
 #define AUDIOERR_DISK_FULL 1
 
 #define AUDIO_GAIN_LINEIN    0
@@ -69,6 +72,7 @@
 void audio_next(void);
 void audio_prev(void);
 int audio_status(void);
+bool audio_query_poweroff(void);
 int audio_track_count(void); /* SWCODEC only */
 void audio_pre_ff_rewind(void); /* SWCODEC only */
 void audio_ff_rewind(long newtime);
@@ -93,14 +97,56 @@
 void audio_pause_recording(void);
 void audio_resume_recording(void);
 void audio_new_file(const char *filename);
+
+/* audio sources */
+enum
+{
+    AUDIO_SRC_PLAYBACK = -1,    /* for audio playback (default) */
+    AUDIO_SRC_MIC,              /* monitor mic */
+    AUDIO_SRC_LINEIN,           /* monitor line in */
+#ifdef HAVE_SPDIF_IN
+    AUDIO_SRC_SPDIF,            /* monitor spdif */
+#endif
+#if defined(HAVE_FMRADIO_IN) || defined(CONFIG_TUNER)
+    AUDIO_SRC_FMRADIO,          /* monitor fm radio */
+#endif
+    /* define new audio sources above this line */
+    AUDIO_SOURCE_LIST_END,
+    /* AUDIO_SRC_FMRADIO must be declared #ifdef CONFIG_TUNER but is not in
+       the list of recordable sources. HAVE_FMRADIO_IN implies CONFIG_TUNER. */
+#if defined(HAVE_FMRADIO_IN) || !defined(CONFIG_TUNER)
+    AUDIO_NUM_SOURCES = AUDIO_SOURCE_LIST_END,
+#else
+    AUDIO_NUM_SOURCES = AUDIO_SOURCE_LIST_END-1,
+#endif
+    AUDIO_SRC_MAX = AUDIO_NUM_SOURCES-1
+};
+
+/* channel modes */
+enum
+{
+    CHN_MODE_MONO = 1,
+    CHN_MODE_STEREO,
+};
 void audio_set_recording_options(int frequency, int quality,
                                 int source, int channel_mode,
                                 bool editable, int prerecord_time);
 void audio_set_recording_gain(int left, int right, int type);
 unsigned long audio_recorded_time(void);
 unsigned long audio_num_recorded_bytes(void);
+#if 0
+#ifdef HAVE_SPDIF_POWER
 void audio_set_spdif_power_setting(bool on);
+#endif
+#endif
 unsigned long audio_get_spdif_sample_rate(void);
+#if CONFIG_CODEC == SWCODEC
+/* audio encoder functions (defined in playback.c) */
+int  audio_get_encoder_id(void);
+void audio_load_encoder(int enc_id);
+void audio_remove_encoder(void);
+#endif /* CONFIG_CODEC == SWCODEC */
+
 
 
 
diff --git a/firmware/export/config-h100.h b/firmware/export/config-h100.h
index c21c8a1..8f93686 100644
--- a/firmware/export/config-h100.h
+++ b/firmware/export/config-h100.h
@@ -135,6 +135,9 @@
 /* Someone with H100 and BDM, please verify if this works. */
 /* #define HAVE_EEPROM */
 
+/* Define this for FM radio input available (not for SIMULATOR) */
+#define HAVE_FMRADIO_IN
+
 #endif /* !SIMULATOR */
 
 /* Define this for S/PDIF input available */
diff --git a/firmware/export/config-h120.h b/firmware/export/config-h120.h
index 5ff567c..4ac4b2b 100644
--- a/firmware/export/config-h120.h
+++ b/firmware/export/config-h120.h
@@ -132,6 +132,9 @@
 /* Define this if the EEPROM chip is used */
 #define HAVE_EEPROM_SETTINGS
 
+/* Define this for FM radio input available (not for SIMULATOR) */
+#define HAVE_FMRADIO_IN
+
 #endif /* !SIMULATOR */
 
 /* Define this for S/PDIF input available */
diff --git a/firmware/export/config-h300.h b/firmware/export/config-h300.h
index d5c54d8..c9c0b04 100644
--- a/firmware/export/config-h300.h
+++ b/firmware/export/config-h300.h
@@ -140,4 +140,7 @@
 /* Define this if there is an EEPROM chip */
 #define HAVE_EEPROM
 
+/* Define this for FM radio input available (not for SIMULATOR) */
+#define HAVE_FMRADIO_IN
+
 #endif /* SIMULATOR */
diff --git a/firmware/export/config-iaudiox5.h b/firmware/export/config-iaudiox5.h
index 8a2ed7a..d5c67c0 100644
--- a/firmware/export/config-iaudiox5.h
+++ b/firmware/export/config-iaudiox5.h
@@ -17,6 +17,7 @@
 
 /* define this if you have access to the quickscreen */
 #define HAVE_QUICKSCREEN
+
 /* define this if you have access to the pitchscreen */
 #define HAVE_PITCHSCREEN
 
@@ -81,6 +82,9 @@
    should be defined as well. */
 #define HAVE_LCD_SLEEP
 
+/* Define this for FM radio input available (not for SIMULATOR) */
+#define HAVE_FMRADIO_IN
+
 /* Define this if you have a Motorola SCF5250 */
 #define CONFIG_CPU MCF5250
 
diff --git a/firmware/export/fmradio.h b/firmware/export/fmradio.h
index 3c55fb7..7311323 100644
--- a/firmware/export/fmradio.h
+++ b/firmware/export/fmradio.h
@@ -20,6 +20,22 @@
 #ifndef FMRADIO_H
 #define FMRADIO_H
 
+/** declare some stuff here so powermgmt.c can properly tell if the radio is
+    actually playing and not just paused. This break in heirarchy is allowed
+    for audio_status(). **/
+
+/* set when radio is playing or paused within fm radio screen */
+#define FMRADIO_OFF         0x0
+#define FMRADIO_PLAYING     0x1
+#define FMRADIO_PAUSED      0x2
+
+/* returns the IN flag */
+#define FMRADIO_IN_SCREEN(s)        ((s) & FMRADIO_IN_FLAG)
+#define FMRADIO_STATUS_PLAYING(s)   ((s) & FMRADIO_PLAYING_OUT)
+#define FMRADIO_STATUS_PAUSED(s)    ((s) & FMRADIO_PAUSED_OUT)
+
+extern int  get_radio_status(void);
+
 extern int fmradio_read(int addr);
 extern void fmradio_set(int addr, int data);
 
diff --git a/firmware/export/id3.h b/firmware/export/id3.h
index 7930cd9..dc58178 100644
--- a/firmware/export/id3.h
+++ b/firmware/export/id3.h
@@ -24,7 +24,6 @@
 #include "file.h"
 
 /* Audio file types. */
-/* NOTE: When adding new audio types, also add to codec_labels[] in id3.c */
 enum {
     AFMT_UNKNOWN = 0,  /* Unknown file format */
 
@@ -46,9 +45,48 @@
 
     /* New formats must be added to the end of this list */
 
-    AFMT_NUM_CODECS
+    AFMT_NUM_CODECS,
+
+#if CONFIG_CODEC == SWCODEC
+    /* masks to decompose parts */
+    CODEC_AFMT_MASK    = 0x0fff,
+    CODEC_TYPE_MASK    = 0x7000,
+
+    /* switch for specifying codec type when requesting a filename */
+    CODEC_TYPE_DECODER = (0 << 12), /* default */
+    CODEC_TYPE_ENCODER = (1 << 12)
+#endif
 };
 
+#if CONFIG_CODEC == SWCODEC
+#define AFMT_ENTRY(label, codec_fname, codec_enc_fname, enc_ext) \
+    { label, codec_fname, codec_enc_fname, enc_ext }
+#else
+#define AFMT_ENTRY(label, codec_fname, codec_enc_fname, enc_ext) \
+    { label }
+#endif
+
+/* record describing the audio format */
+struct afmt_entry
+{
+#if CONFIG_CODEC == SWCODEC
+    char label[8];      /* format label */
+    char *codec_fn;     /* filename of decoder codec */
+    char *codec_enc_fn; /* filename of encoder codec */
+    char *ext;          /* default extension for file (enc only for now) */
+#else
+    char label[4];
+#endif
+};
+
+/* database of labels and codecs. add formats per above enum */
+extern const struct afmt_entry audio_formats[AFMT_NUM_CODECS];
+
+#if CONFIG_CODEC == SWCODEC
+/* recording quality to AFMT_* */
+extern const int rec_quality_info_afmt[9];
+#endif
+
 struct mp3entry {
     char path[MAX_PATH];
     char* title;
diff --git a/firmware/export/pcm_record.h b/firmware/export/pcm_record.h
index 5e2d7b7..b217335 100644
--- a/firmware/export/pcm_record.h
+++ b/firmware/export/pcm_record.h
@@ -20,10 +20,22 @@
 #ifndef PCM_RECORD_H
 #define PCM_RECORD_H
 
+void          enc_set_parameters(int chunk_size, int num_chunks,
+                    int samp_per_chunk, char *head_ptr, int head_size,
+                    int enc_id);
+void          enc_get_inputs(int *buffer_size, int *channels, int *quality);
+unsigned int* enc_alloc_chunk(void);
+void          enc_free_chunk(void);
+int           enc_wavbuf_near_empty(void);
+char*         enc_get_wav_data(int size);
+extern void   (*enc_set_header_callback)(void *head_buffer, int head_size,
+                                int num_pcm_samples, bool is_file_header);
+
 unsigned long pcm_rec_status(void);
 void pcm_rec_init(void);
 void pcm_rec_mux(int source);
-
+int  pcm_rec_current_bitrate(void);
+int  pcm_get_num_unprocessed(void);
 void pcm_rec_get_peaks(int *left, int *right);
 
 /* audio.h contains audio recording functions */
diff --git a/firmware/id3.c b/firmware/id3.c
index 35e0517..3f2ba23 100644
--- a/firmware/id3.c
+++ b/firmware/id3.c
@@ -85,28 +85,59 @@
     "Synthpop"
 };
 
-static const char* const codec_labels[] = {
-  "???",  /* Unknown file format */
-
-  "MP1",  /* MPEG Audio layer 1 */
-  "MP2",  /* MPEG Audio layer 2 */
-  "MP3",  /* MPEG Audio layer 3 */
-
+/* database of audio formats */
+const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
+{
+    /* Unknown file format */
+    AFMT_ENTRY("???",  NULL,            NULL,                NULL  ),
+    /* MPEG Audio layer 1 */
+    AFMT_ENTRY("MP1",  "mpa.codec",     NULL,                NULL  ),
+    /* MPEG Audio layer 2 */
+    AFMT_ENTRY("MP2",  "mpa.codec",     NULL,                NULL  ),
+    /* MPEG Audio layer 3 */
+    AFMT_ENTRY("MP3",  "mpa.codec",     "mp3_enc.codec",     ".mp3"),
 #if CONFIG_CODEC == SWCODEC
-  "WAV",  /* Uncompressed PCM in a WAV file */
-  "Ogg",  /* Ogg Vorbis */
-  "FLAC", /* FLAC */
-  "MPC",  /* Musepack */
-  "AC3",  /* A/52 (aka AC3) audio */
-  "WV",   /* WavPack */
-  "ALAC", /* Apple Lossless Audio Codec */
-  "AAC",  /* Advanced Audio Coding in M4A container */
-  "SHN",  /* Shorten */
-  "AIFF", /* Audio Interchange File Format */
-  "SID",  /* SID File Format */
+    /* Uncompressed PCM in a WAV file */
+    AFMT_ENTRY("WAV",  "wav.codec",     "wav_enc.codec",     ".wav"),
+    /* Ogg Vorbis */
+    AFMT_ENTRY("Ogg",  "vorbis.codec",  NULL,                NULL  ),
+    /* FLAC */
+    AFMT_ENTRY("FLAC", "flac.codec",    NULL,                NULL  ),
+    /* Musepack */
+    AFMT_ENTRY("MPC",  "mpc.codec",     NULL,                NULL  ),
+    /* A/52 (aka AC3) audio */
+    AFMT_ENTRY("AC3",  "a52.codec",     NULL,                NULL  ),
+    /* WavPack */
+    AFMT_ENTRY("WV",   "wavpack.codec", "wavpack_enc.codec", ".wv" ),
+    /* Apple Lossless Audio Codec */
+    AFMT_ENTRY("ALAC", "alac.codec",    NULL,                NULL  ),
+    /* Advanced Audio Coding in M4A container */
+    AFMT_ENTRY("AAC",  "aac.codec",     NULL,                NULL  ),
+    /* Shorten */
+    AFMT_ENTRY("SHN",  "shorten.codec", NULL,                NULL  ),
+    /* Audio Interchange File Format */
+    AFMT_ENTRY("AIFF", "aiff.codec",    NULL,                NULL  ),
+    /* SID File Format */
+    AFMT_ENTRY("SID",  "sid.codec",     NULL,                NULL  ),
 #endif
 };
 
+#if CONFIG_CODEC == SWCODEC
+/* recording quality to AFMT_* */
+const int rec_quality_info_afmt[9] =
+{
+    AFMT_MPA_L3,    /* MPEG L3   64 kBit/s */
+    AFMT_MPA_L3,    /* MPEG L3   96 kBit/s */
+    AFMT_MPA_L3,    /* MPEG L3  128 kBit/s */
+    AFMT_MPA_L3,    /* MPEG L3  160 kBit/s */
+    AFMT_MPA_L3,    /* MPEG L3  192 kBit/s */
+    AFMT_MPA_L3,    /* MPEG L3  224 kBit/s */
+    AFMT_MPA_L3,    /* MPEG L3  320 kBit/s */
+    AFMT_WAVPACK,   /* WavPack  909 kBit/s */
+    AFMT_PCM_WAV,   /* PCM Wav 1411 kBit/s */
+};
+#endif /* SWCODEC */
+
 char* id3_get_genre(const struct mp3entry* id3)
 {
     if( id3->genre_string )
@@ -119,8 +150,8 @@
 
 char* id3_get_codec(const struct mp3entry* id3)
 {
-    if (id3->codectype < sizeof(codec_labels)/sizeof(char*)) {
-        return (char*)codec_labels[id3->codectype];
+    if (id3->codectype < AFMT_NUM_CODECS) {
+        return (char*)audio_formats[id3->codectype].label;
     } else {
         return NULL;
     }
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 7034f38..df0cbba 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -2484,7 +2484,7 @@
 
     DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main);
 
-    if(source == 0) /* Mic */
+    if(source == AUDIO_SRC_MIC)
     {
         /* Copy left channel to right (mono mode) */
         mas_codec_writereg(8, 0x8000);
diff --git a/firmware/pcm_record.c b/firmware/pcm_record.c
index fee2bbd..4e4d5f2 100644
--- a/firmware/pcm_record.c
+++ b/firmware/pcm_record.c
@@ -50,6 +50,8 @@
 #include "lcd.h"
 #include "lcd-remote.h"
 #include "pcm_playback.h"
+#include "sound.h"
+#include "id3.h"
 #include "pcm_record.h"
 
 extern int boost_counter; /* used for boost check */
@@ -57,43 +59,26 @@
 /***************************************************************************/
 
 static bool is_recording;              /* We are recording */
-static bool is_stopping;               /* Are we going to stop */
 static bool is_paused;                 /* We have paused   */
 static bool is_error;                  /* An error has occured */
 
 static unsigned long num_rec_bytes;    /* Num bytes recorded */
 static unsigned long num_file_bytes;   /* Num bytes written to current file */
 static int error_count;                /* Number of DMA errors */
+static unsigned long num_pcm_samples;  /* Num pcm samples written to current file */
 
-static long record_start_time;                  /* Value of current_tick when recording was started */
-static long pause_start_time;                   /* Value of current_tick when pause was started */
-static volatile int buffered_chunks;            /* number of valid chunks in buffer */
-static unsigned int sample_rate; /* Sample rate at time of recording start */
-static int rec_source;           /* Current recording source */
+static long record_start_time;         /* current_tick when recording was started */
+static long pause_start_time;          /* current_tick when pause was started */
+static unsigned int sample_rate;       /* Sample rate at time of recording start */
+static int rec_source;                 /* Current recording source */
 
 static int wav_file;
 static char recording_filename[MAX_PATH];
 
-static bool init_done, close_done, record_done, stop_done, pause_done, resume_done, new_file_done;
+static volatile bool init_done, close_done, record_done;
+static volatile bool stop_done, pause_done, resume_done, new_file_done;
 
-static short peak_left, peak_right;
-
-/***************************************************************************/
-
-/*
-  Some estimates:
-    Normal recording rate: 44100 HZ * 4     = 176 KB/s
-    Total buffer size:     32 MB / 176 KB/s = 181s before writing to disk
-*/
-
-#define CHUNK_SIZE       8192  /* Multiple of 4 */
-#define WRITE_THRESHOLD  250   /* (2 MB) Write when this many chunks (or less) until buffer full */
-
-#define GET_CHUNK(x)     (short*)(&rec_buffer[CHUNK_SIZE*(x)])
-
-static unsigned int rec_buffer_offset;
-static unsigned char *rec_buffer;  /* Circular recording buffer */
-static int num_chunks;             /* Number of chunks available in rec_buffer */
+static int peak_left, peak_right;
 
 #ifdef IAUDIO_X5
 #define SET_IIS_PLAY(x) IIS1CONFIG = (x);
@@ -103,27 +88,71 @@
 #define SET_IIS_REC(x)  IIS1CONFIG = (x);
 #endif
   
-/* 
- Overrun occures when DMA needs to write a new chunk and write_index == read_index 
- Solution to this is to optimize pcmrec_callback, use cpu_boost or save to disk
- more often.
-*/
+/****************************************************************************
+  use 2 circular buffers of same size:
+  rec_buffer=DMA output buffer:    chunks (8192 Bytes) of raw pcm audio data
+  enc_buffer=encoded audio buffer: storage for encoder output data
 
-static int write_index;                /* Current chunk the DMA is writing to */
-static int read_index;                 /* Oldest chunk that is not written to disk */
-static int read2_index;                /* Latest chunk that has not been converted to little endian */
-static long pre_record_ticks;          /* pre-record time expressed in ticks */
-static int pre_record_chunks;          /* pre-record time expressed in chunks */
+  Flow:
+  1. when entering recording_screen DMA feeds the ringbuffer rec_buffer
+  2. if enough pcm data are available the encoder codec does encoding of pcm
+      chunks (4-8192 Bytes) into ringbuffer enc_buffer in codec_thread
+  3. pcmrec_callback detects enc_buffer 'near full' and writes data to disk
+
+  Functions calls:
+  1.main: codec_load_encoder();      start the encoder
+  2.encoder: enc_get_inputs();       get encoder buffsize, mono/stereo, quality
+  3.encoder: enc_set_parameters();   set the encoder parameters (max.chunksize)
+  4.encoder: enc_get_wav_data();     get n bytes of unprocessed pcm data
+  5.encoder: enc_wavbuf_near_empty();if true: reduce cpu_boost
+  6.encoder: enc_alloc_chunk();      get a ptr to next enc chunk
+  7.encoder: <process enc chunk>     compress and store data to enc chunk
+  8.encoder: enc_free_chunk();       inform main about chunk process finished
+  9.encoder: repeat 4. to 8.
+  A.main: enc_set_header_callback(); create the current format header (file)
+****************************************************************************/
+#define NUM_CHUNKS                   256 /* Power of 2 */
+#define CHUNK_SIZE                  8192 /* Power of 2 */
+#define MAX_FEED_SIZE              20000 /* max pcm size passed to encoder */
+#define CHUNK_MASK                 (NUM_CHUNKS * CHUNK_SIZE - 1)
+#define WRITE_THRESHOLD            (44100 * 5 / enc_samp_per_chunk) /* 5sec */
+#define GET_CHUNK(x)               (long*)(&rec_buffer[x])
+#define GET_ENC_CHUNK(x)           (long*)(&enc_buffer[enc_chunk_size*(x)])
+
+static int            audio_enc_id;    /* current encoder id                 */
+static unsigned char *rec_buffer;      /* Circular recording buffer          */
+static unsigned char *enc_buffer;      /* Circular encoding buffer           */
+static unsigned char *enc_head_buffer; /* encoder header buffer              */
+static int            enc_head_size;   /* used size in header buffer         */
+static int            write_pos;       /* Current chunk pos for DMA writing  */
+static int            read_pos;        /* Current chunk pos for encoding     */
+static long           pre_record_ticks;/* pre-record time expressed in ticks */
+static int            enc_wr_index;    /* Current encoding chunk write index */
+static int            enc_rd_index;    /* Current encoding chunk read index  */
+static int            enc_chunk_size;  /* maximum encoder chunk size         */
+static int            enc_num_chunks;  /* number of chunks in ringbuffer     */
+static int            enc_buffer_size; /* encode buffer size                 */
+static int            enc_channels;    /* 1=mono 2=stereo                    */
+static int            enc_quality;     /* mp3: 64,96,128,160,192,320 kBit    */
+static int            enc_samp_per_chunk;/* pcm samples per encoder chunk    */
+static bool           wav_queue_empty; /* all wav chunks processed?          */
+static unsigned long  avrg_bit_rate;   /* average bit rates from chunks      */
+static unsigned long  curr_bit_rate;   /* cumulated bit rates from chunks    */
+static unsigned long  curr_chunk_cnt;  /* number of processed chunks         */
+ 
+void (*enc_set_header_callback)(void *head_buffer, int head_size,
+                                int num_pcm_samples, bool is_file_header);
 
 /***************************************************************************/
 
 static struct event_queue  pcmrec_queue;
-static long                pcmrec_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
+static long                pcmrec_stack[2*DEFAULT_STACK_SIZE/sizeof(long)];
 static const char          pcmrec_thread_name[] = "pcmrec";
 
 static void pcmrec_thread(void);
 static void pcmrec_dma_start(void);
 static void pcmrec_dma_stop(void);
+static void close_wave(void);
 
 /* Event IDs */
 #define PCMREC_INIT         1     /* Enable recording */
@@ -144,10 +173,16 @@
 void pcm_rec_init(void)
 {
     queue_init(&pcmrec_queue);
-    create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack), pcmrec_thread_name);
+    create_thread(pcmrec_thread, pcmrec_stack, sizeof(pcmrec_stack),
+        pcmrec_thread_name);
 }
 
 
+int audio_get_encoder_id(void)
+{
+    return audio_enc_id;
+}
+
 /* Initializes recording:
  * - Set up the UDA1380/TLV320 for recording 
  * - Prepare for DMA transfers
@@ -155,13 +190,14 @@
  
 void audio_init_recording(unsigned int buffer_offset)
 {
-    rec_buffer_offset = buffer_offset;
+    (void)buffer_offset;
+
     init_done = false;
     queue_post(&pcmrec_queue, PCMREC_INIT, 0);
     
     while(!init_done)
         sleep_thread();
-    wake_up_thread();    
+    wake_up_thread();
 }
 
 void audio_close_recording(void)
@@ -171,7 +207,9 @@
     
     while(!close_done)
         sleep_thread();
-    wake_up_thread();    
+    wake_up_thread();
+
+    audio_remove_encoder();
 }
 
 unsigned long pcm_rec_status(void)
@@ -184,10 +222,17 @@
         ret |= AUDIO_STATUS_PAUSE;
     if (is_error)
         ret |= AUDIO_STATUS_ERROR;
+    if (!is_recording && pre_record_ticks && init_done && !close_done)
+        ret |= AUDIO_STATUS_PRERECORD;
 
     return ret;
 }
 
+int pcm_rec_current_bitrate(void)
+{
+    return avrg_bit_rate;
+}
+
 unsigned long audio_recorded_time(void)
 {
     if (is_recording)
@@ -248,6 +293,8 @@
 }
 #endif
 
+#if 0
+/* not needed atm */
 #ifdef HAVE_SPDIF_POWER
 static bool spdif_power_setting;
 
@@ -256,21 +303,18 @@
     spdif_power_setting = on;
 }
 #endif
+#endif
 
 /**
- * Sets the audio source 
+ * Sets recording parameters
  * 
  * This functions starts feeding the CPU with audio data over the I2S bus
- *
- * @param source 0=mic, 1=line-in, 2=spdif
  */
 void audio_set_recording_options(int frequency, int quality,
                                 int source, int channel_mode,
                                 bool editable, int prerecord_time)
 {
     /* TODO: */
-    (void)quality;
-    (void)channel_mode;
     (void)editable;
 
     /* NOTE: Coldfire UDA based recording does not yet support anything other
@@ -278,69 +322,30 @@
      * based recording will overwrite this value with the proper sample rate in
      * audio_record(), and will not be affected by this.
      */
-    frequency = 44100;   
+    frequency        = 44100;
+    enc_quality      = quality;
+    rec_source       = source;
+    enc_channels     = channel_mode == CHN_MODE_MONO ? 1 : 2;
     pre_record_ticks = prerecord_time * HZ;
-    pre_record_chunks = ((frequency * prerecord_time * 4)/CHUNK_SIZE)+1;
-    if(pre_record_chunks >= (num_chunks-250))
-    {
-        /* we can't prerecord more than our buffersize minus treshold to write to disk! */
-        pre_record_chunks = num_chunks-250;
-        /* don't forget to recalculate that time! */
-        pre_record_ticks = ((pre_record_chunks * CHUNK_SIZE)/(4*frequency)) * HZ;
-    }
-    
-    //logf("pcmrec: src=%d", source);
 
-    rec_source = source;
-#ifdef HAVE_SPDIF_POWER
-    /* Check if S/PDIF output power should be switched off or on. NOTE: assumes
-       both optical in and out is controlled by the same power source, which is
-       the case on H1x0. */
-    spdif_power_enable((source == 2) || spdif_power_setting);
-#endif
     switch (source)
     {
-        /* mic */
-        case 0: 
+        case AUDIO_SRC_MIC:
+        case AUDIO_SRC_LINEIN:
+#ifdef HAVE_FMRADIO_IN
+        case AUDIO_SRC_FMRADIO:
+#endif
             /* Generate int. when 6 samples in FIFO, PDIR2 src = IIS1recv */
             DATAINCONTROL = 0xc020;
-            
-#ifdef HAVE_UDA1380            
-            uda1380_enable_recording(true); 
-#endif
-#ifdef HAVE_TLV320
-            tlv320_enable_recording(true);
-#endif            
         break;
 
-        /* line-in */
-        case 1: 
-            /* Generate int. when 6 samples in FIFO, PDIR2 src = IIS1recv */
-            DATAINCONTROL = 0xc020;
-            
-#ifdef HAVE_UDA1380            
-            uda1380_enable_recording(false); 
-#endif
-#ifdef HAVE_TLV320
-            tlv320_enable_recording(false);
-#endif            
-        break;
-#ifdef HAVE_SPDIF_IN        
-        /* SPDIF */
-        case 2:
+#ifdef HAVE_SPDIF_IN
+        case AUDIO_SRC_SPDIF:
             /* Int. when 6 samples in FIFO. PDIR2 source = ebu1RcvData */
             DATAINCONTROL = 0xc038;
-#ifdef HAVE_SPDIF_POWER
-            EBU1CONFIG = spdif_power_setting ? (1 << 2) : 0;
-            /* Input source is EBUin1, Feed-through monitoring if desired */
-#else
-            EBU1CONFIG = (1 << 2);
-            /* Input source is EBUin1, Feed-through monitoring */
-#endif
-            uda1380_disable_recording();
         break;
-#endif
-    }    
+#endif /* HAVE_SPDIF_IN */
+    }
 
     sample_rate = frequency;
 
@@ -349,7 +354,8 @@
     SET_IIS_PLAY(0x800); /* Reset before reprogram */
     
 #ifdef HAVE_SPDIF_IN
-    if (source == 2) {
+    if (source == AUDIO_SRC_SPDIF)
+    {
         /* SCLK2 = Audioclk/4 (can't use EBUin clock), TXSRC = EBU1rcv, 64 bclk/wclk */
         IIS2CONFIG = (6 << 12) | (7 << 8) | (4 << 2);
         /* S/PDIF feed-through already configured */
@@ -367,6 +373,8 @@
     /* SCLK2 follow IIS1 (UDA clock), TXSRC = IIS1rcv, 64 bclk/wclk */
     SET_IIS_PLAY( (8 << 12) | (4 << 8) | (4 << 2) );
 #endif
+
+    audio_load_encoder(rec_quality_info_afmt[quality]);
 }
 
 
@@ -380,10 +388,9 @@
 void audio_set_recording_gain(int left, int right, int type)
 {
     //logf("rcmrec: t=%d l=%d r=%d", type, left, right);
-#ifdef HAVE_UDA1380            
+#if defined(HAVE_UDA1380)
     uda1380_set_recvol(left, right, type);
-#endif
-#ifdef HAVE_TLV320
+#elif defined (HAVE_TLV320)
     tlv320_set_recvol(left, right, type);
 #endif            
 }
@@ -406,7 +413,7 @@
     recording_filename[MAX_PATH - 1] = 0;
 
 #ifdef HAVE_SPDIF_IN
-    if (rec_source == 2)
+    if (rec_source == AUDIO_SRC_SPDIF)
         sample_rate = audio_get_spdif_sample_rate();
 #endif
     
@@ -447,6 +454,7 @@
 
     logf("pcm_stop");
     
+    is_paused = true;  /* fix pcm write ptr at current position */
     stop_done = false;
     queue_post(&pcmrec_queue, PCMREC_STOP, 0);
 
@@ -499,9 +507,9 @@
 void pcm_rec_get_peaks(int *left, int *right)
 {
     if (left)
-        *left = (int)peak_left;
+        *left = peak_left;
     if (right)
-        *right = (int)peak_right;
+        *right = peak_right;
     peak_left = 0;
     peak_right = 0;
 }
@@ -511,7 +519,7 @@
 /***************************************************************************/
 
 /**
- * Process the chunks using read_index and write_index.
+ * Process the chunks
  *
  * This function is called when queue_get_w_tmo times out.
  *
@@ -519,70 +527,24 @@
  * they want to save everything in the buffers to disk.
  *
  */
-
-static void pcmrec_callback(bool flush) ICODE_ATTR;
 static void pcmrec_callback(bool flush)
 {
-    int num_ready, num_free, num_new;
-    short *ptr;    
-    short value;
-    int i, j, w;
+    int  i, num_ready, size_yield;
+    long *enc_chunk, chunk_size;
 
-    w = write_index;
-
-    num_new = w - read2_index;
-    if (num_new < 0)
-        num_new += num_chunks;
-
-    for (i=0; i<num_new; i++)
-    {
-        /* Convert the samples to little-endian so we only have to write later
-           (Less hd-spinning time), also do peak detection while we're at it
-        */
-        ptr = GET_CHUNK(read2_index);
-        for (j=0; j<CHUNK_SIZE/4; j++)
-        {
-            value = *ptr;
-            if(value > peak_left)
-                peak_left = value;
-            else if (-value > peak_left)
-                peak_left = -value;
-
-            *ptr = htole16(value);
-            ptr++;
-
-            value = *ptr;
-            if(value > peak_right)
-                peak_right = value;
-            else if (-value > peak_right)
-                peak_right = -value;
-
-            *ptr = htole16(value);
-            ptr++;
-        }
-
-        if(is_recording && !is_paused) 
-            num_rec_bytes += CHUNK_SIZE;
-        
-        read2_index++;
-        if (read2_index >= num_chunks)
-            read2_index = 0;
-    }
-
-    if ((!is_recording || is_paused) && !flush)
-    {
-        /* not recording = no saving to disk, fake buffer clearing */
-        read_index = write_index;
+    if (!is_recording && !flush)
         return;
-    }
 
-    num_ready = w - read_index;
+    num_ready = enc_wr_index - enc_rd_index;
     if (num_ready < 0)
-        num_ready += num_chunks;
+        num_ready += enc_num_chunks;
 
-    num_free = num_chunks - num_ready;
-    
-    if (num_free <= WRITE_THRESHOLD || flush)
+    /* calculate an estimate of recorded bytes */
+    num_rec_bytes = num_file_bytes + num_ready * /* enc_chunk_size */
+            ((avrg_bit_rate * 1000 / 8 * enc_samp_per_chunk + 22050) / 44100);
+
+    /* near full state reached: less than 5sec remaining space */
+    if (enc_num_chunks - num_ready < WRITE_THRESHOLD || flush)
     {
         bool must_boost = (boost_counter ? false : true);
 
@@ -591,23 +553,41 @@
         if(must_boost)
             cpu_boost(true);
 
+        size_yield = 0;
         for (i=0; i<num_ready; i++)
         {
-            if (write(wav_file, GET_CHUNK(read_index), CHUNK_SIZE) != CHUNK_SIZE)
+            enc_chunk  = GET_ENC_CHUNK(enc_rd_index);
+            chunk_size = *enc_chunk++;
+
+            /* safety net: if size entry got corrupted => limit */
+            if (chunk_size > (long)(enc_chunk_size - sizeof(long)))
+                chunk_size = enc_chunk_size - sizeof(long);
+
+            if (enc_set_header_callback != NULL)
+                enc_set_header_callback(enc_chunk, enc_chunk_size,
+                                              num_pcm_samples, false);
+
+            if (write(wav_file, enc_chunk, chunk_size) != chunk_size)
             {
+                close_wave();
                 if(must_boost)
                     cpu_boost(false);
                 logf("pcmrec: write err");
-                pcmrec_dma_stop();
-                return;
+                is_error = true;
+                break;
             }
-            
-            num_file_bytes += CHUNK_SIZE;
-            
-            read_index++;
-            if (read_index >= num_chunks)
-                read_index = 0;
-            yield();
+
+            num_file_bytes  += chunk_size;
+            num_pcm_samples += enc_samp_per_chunk;
+            size_yield      += chunk_size;
+
+            if (size_yield >= 32768)
+            {   /* yield when 32kB written */
+                size_yield = 0;
+                yield();
+            }
+
+            enc_rd_index = (enc_rd_index + 1) % enc_num_chunks;
         }
 
         if(must_boost)
@@ -623,36 +603,33 @@
 /* Abort dma transfer */
 static void pcmrec_dma_stop(void)
 {
-    DCR1 = 0; 
-    
-    is_error = true;
-    is_recording = false;
-    
+    DCR1 = 0;
+
     error_count++;
-    
+
+    DSR1 = 1;    /* Clear interrupt */
+    IPR |= (1<<15); /* Clear pending interrupt request */
+
     logf("dma1 stopped");
 }
 
 static void pcmrec_dma_start(void)
 {
-    DAR1 = (unsigned long)GET_CHUNK(write_index);    /* Destination address */
-    SAR1 = (unsigned long)&PDIR2;                    /* Source address */
-    BCR1 = CHUNK_SIZE;                               /* Bytes to transfer */
+    DAR1 = (unsigned long)GET_CHUNK(write_pos);  /* Destination address */
+    SAR1 = (unsigned long)&PDIR2;                /* Source address */
+    BCR1 = CHUNK_SIZE;                           /* Bytes to transfer */
 
     /* Start the DMA transfer.. */
-    DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | DMA_START;
-
 #ifdef HAVE_SPDIF_IN
     INTERRUPTCLEAR = 0x03c00000;
 #endif
 
-    /* pre-recording: buffer count */
-    buffered_chunks = 0;
+    /* 16Byte transfers prevents from sporadic errors during cpu_boost() */
+    DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | DMA_DSIZE(3) | DMA_START;
 
     logf("dma1 started");
 }
 
-
 /* DMA1 Interrupt is called when the DMA has finished transfering a chunk */
 void DMA1(void) __attribute__ ((interrupt_handler, section(".icode")));
 void DMA1(void)
@@ -668,62 +645,64 @@
 
         logf("dma1 err: 0x%x", res);
 
-        DAR1 = (unsigned long)GET_CHUNK(write_index);  /* Destination address */
+        DAR1 = (unsigned long)GET_CHUNK(write_pos);  /* Destination address */
         BCR1 = CHUNK_SIZE;
         DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_DINC | DMA_START;
+
+        /* Flush recorded data to disk and stop recording */
+        queue_post(&pcmrec_queue, PCMREC_STOP, NULL);
     } 
 #ifdef HAVE_SPDIF_IN
-    else if ((rec_source == 2) && (INTERRUPTSTAT & 0x01c00000)) /* valnogood, symbolerr, parityerr */
+    else if ((rec_source == AUDIO_SRC_SPDIF) &&
+        (INTERRUPTSTAT & 0x01c00000)) /* valnogood, symbolerr, parityerr */
     {
         INTERRUPTCLEAR = 0x03c00000;
         error_count++;
 
         logf("spdif err");
 
-        if (is_stopping)
-        {
-            DCR1 = 0;   /* Stop DMA transfer */
-            is_stopping = false;
-
-            logf("dma1 stopping");
-        }
-        else
-        {
-            DAR1 = (unsigned long)GET_CHUNK(write_index);  /* Destination address */
-            BCR1 = CHUNK_SIZE;
-        }
+        DAR1 = (unsigned long)GET_CHUNK(write_pos);  /* Destination address */
+        BCR1 = CHUNK_SIZE;
     }
 #endif
     else
     {
-        write_index++;
-        if (write_index >= num_chunks)
-            write_index = 0;
+        long peak_l, peak_r;
+        long *ptr, j;
 
-        /* update number of valid chunks for pre-recording */
-        if(buffered_chunks < num_chunks)
-            buffered_chunks++;
+        ptr = GET_CHUNK(write_pos);
 
-        if (is_stopping)
+        if (!is_paused) /* advance write position */
+            write_pos = (write_pos + CHUNK_SIZE) & CHUNK_MASK;
+
+        DAR1 = (unsigned long)GET_CHUNK(write_pos);  /* Destination address */
+        BCR1 = CHUNK_SIZE;
+
+        peak_l = peak_r = 0;
+
+        /* only peak every 4th sample */
+        for (j=0; j<CHUNK_SIZE/4; j+=4)
         {
-            DCR1 = 0;   /* Stop DMA transfer */
-            is_stopping = false;
+            long value = ptr[j];
+#ifdef ROCKBOX_BIG_ENDIAN
+            if (value > peak_l)       peak_l =  value;
+            else if (-value > peak_l) peak_l = -value;
 
-            logf("dma1 stopping");
-        }
-        else if (write_index == read_index)
-        {
-            DCR1 = 0;   /* Stop DMA transfer */
-            is_recording = false;
+            value <<= 16;
+            if (value > peak_r)       peak_r =  value;
+            else if (-value > peak_r) peak_r = -value;
+#else
+            if (value > peak_r)       peak_r =  value;
+            else if (-value > peak_r) peak_r = -value;
 
-            logf("dma1 overrun");
+            value <<= 16;
+            if (value > peak_l)       peak_l =  value;
+            else if (-value > peak_l) peak_l = -value;
+#endif
+        }
 
-        }
-        else
-        {
-            DAR1 = (unsigned long)GET_CHUNK(write_index);  /* Destination address */
-            BCR1 = CHUNK_SIZE;
-        }
+        peak_left  = (int)(peak_l >> 16);
+        peak_right = (int)(peak_r >> 16);
     }
 
     IPR |= (1<<15); /* Clear pending interrupt request */
@@ -733,15 +712,8 @@
 /* Sets returns 0 if success, -1 on failure */
 static int start_wave(void)
 {
-    unsigned char header[44] = 
-    {
-        'R','I','F','F',0,0,0,0,'W','A','V','E','f','m','t',' ',
-        0x10,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,
-        4,0,0x10,0,'d','a','t','a',0,0,0,0
-    };
-    unsigned long avg_bytes_per_sec;
-    
     wav_file = open(recording_filename, O_RDWR|O_CREAT|O_TRUNC);
+
     if (wav_file < 0)
     {
         wav_file = -1;
@@ -749,19 +721,9 @@
         is_error = true;
         return -1;
     }
-    /* Now set the sample rate field of the WAV header to what it should be */
-    header[24] = (unsigned char)(sample_rate & 0xff);
-    header[25] = (unsigned char)(sample_rate >> 8);
-    header[26] = (unsigned char)(sample_rate >> 16);
-    header[27] = (unsigned char)(sample_rate >> 24);
-    /* And then the average bytes per second field */
-    avg_bytes_per_sec = sample_rate*4; /* Hard coded to 16 bit stereo */
-    header[28] = (unsigned char)(avg_bytes_per_sec & 0xff);
-    header[29] = (unsigned char)(avg_bytes_per_sec >> 8);
-    header[30] = (unsigned char)(avg_bytes_per_sec >> 16);
-    header[31] = (unsigned char)(avg_bytes_per_sec >> 24);
    
-    if (sizeof(header) != write(wav_file, header, sizeof(header)))
+    /* add main file header (enc_head_size=0 for encoders without) */
+    if (enc_head_size != write(wav_file, enc_head_buffer, enc_head_size))
     {
         close(wav_file);
         wav_file = -1;
@@ -776,18 +738,22 @@
 /* Update header and set correct length values */
 static void close_wave(void)
 {
-    long l;
+    unsigned char head[100]; /* assume maximum 100 bytes for file header */
+    int           size_read;
 
     if (wav_file != -1)
     {
-        l = htole32(num_file_bytes + 36);
-        lseek(wav_file, 4, SEEK_SET);
-        write(wav_file, &l, 4);
-    
-        l = htole32(num_file_bytes);
-        lseek(wav_file, 40, SEEK_SET);
-        write(wav_file, &l, 4);
-    
+        /* update header before closing the file (wav+wv encoder will do) */
+        if (enc_set_header_callback != NULL)
+        {
+            lseek(wav_file, 0, SEEK_SET);
+            /* try to read the head size (but we'll accept less) */
+            size_read = read(wav_file, head, sizeof(head));
+
+            enc_set_header_callback(head, size_read, num_pcm_samples, true);
+            lseek(wav_file, 0, SEEK_SET);
+            write(wav_file, head, size_read);
+        }
         close(wav_file);
         wav_file = -1;
     }
@@ -795,8 +761,7 @@
 
 static void pcmrec_start(void)
 {
-    int pre_chunks = pre_record_chunks; /* recalculate every time! */
-    long pre_ticks = pre_record_ticks;   /* recalculate every time! */
+    long max_pre_chunks, pre_ticks, max_pre_ticks;
 
     logf("pcmrec_start");
 
@@ -808,7 +773,7 @@
     }
 
     if (wav_file != -1)
-        close(wav_file);
+        close_wave();
 
     if (start_wave() != 0)
     {
@@ -817,32 +782,29 @@
         return;
     }
 
-    /* pre-recording calculation */
-    if(buffered_chunks < pre_chunks)
-    {
-        /* not enough good chunks available - limit pre-record time */
-        pre_chunks = buffered_chunks;
-        pre_ticks = ((buffered_chunks * CHUNK_SIZE)/(4*sample_rate)) * HZ;
-    }
+    /* calculate maximum available chunks & resulting ticks */
+    max_pre_chunks = (enc_wr_index - enc_rd_index +
+                        enc_num_chunks) % enc_num_chunks;
+    if (max_pre_chunks > enc_num_chunks - WRITE_THRESHOLD)
+        max_pre_chunks = enc_num_chunks - WRITE_THRESHOLD;
+    max_pre_ticks = max_pre_chunks * HZ * enc_samp_per_chunk / 44100;
+
+    /* limit prerecord if not enough data available */
+    pre_ticks = pre_record_ticks > max_pre_ticks ?
+        max_pre_ticks : pre_record_ticks;
+    max_pre_chunks = 44100 * pre_ticks / HZ / enc_samp_per_chunk;
+    enc_rd_index = (enc_wr_index - max_pre_chunks +
+                        enc_num_chunks) % enc_num_chunks;
+
     record_start_time = current_tick - pre_ticks;
 
-    read_index = write_index - pre_chunks;
-    if(read_index < 0)
-    {
-        read_index += num_chunks;
-    }
-
-    peak_left = 0;
-    peak_right = 0;
- 
-    num_rec_bytes = pre_chunks * CHUNK_SIZE;
+    num_rec_bytes = enc_num_chunks * CHUNK_SIZE;
     num_file_bytes = 0;
+    num_pcm_samples = 0;
     pause_start_time = 0;
     
-    is_stopping = false;
     is_paused = false;
     is_recording = true;
-    
     record_done = true;
 }
 
@@ -850,36 +812,24 @@
 {
     logf("pcmrec_stop");
    
-    if (!is_recording)
+    if (is_recording)
     {
-        stop_done = true;
-        return;
-    }
-   
-    if (!is_paused)
-    { 
-        /* wait for recording to finish */
-        is_stopping = true;
-        
-        while (is_stopping && is_recording)
+        /* wait for encoding finish */
+        is_paused = true;
+        while(!wav_queue_empty)
             sleep_thread();
-        wake_up_thread();    
-        
-        is_stopping = false;
+
+        wake_up_thread();
+        is_recording = false;
+
+        /* Flush buffers to file */
+        pcmrec_callback(true);
+        close_wave();
     }
-    
-    is_recording = false;
-    
-    /* Flush buffers to file */
-    pcmrec_callback(true);
 
-    close_wave();
-
+    is_paused = false;
     stop_done = true;
-    
-    /* Finally start dma again for peakmeters and pre-recoding to work. */
-    pcmrec_dma_start();
-    
+
     logf("pcmrec_stop done");
 }
 
@@ -898,7 +848,6 @@
        here is a good approximation when recording to the new file starts 
     */
     record_start_time = current_tick;
-    num_rec_bytes = 0;
     
     if (is_paused)
         pause_start_time = record_start_time;
@@ -908,7 +857,9 @@
     
     close_wave();
 
+    num_rec_bytes = 0;
     num_file_bytes = 0;
+    num_pcm_samples = 0;
     
     /* start the new file */    
     if (start_wave() != 0)
@@ -932,20 +883,8 @@
         return;
     }
     
-    /* Abort DMA transfer and flush to file? */
-        
-    is_stopping = true;        
-    
-    while (is_stopping && is_recording)
-        sleep_thread();
-    wake_up_thread();        
-    
     pause_start_time = current_tick;
-    is_paused = true;    
-    
-    /* Flush what we got in buffers to file */
-    pcmrec_callback(true);
-        
+    is_paused = true;  
     pause_done = true;
     
     logf("pcmrec_pause done");
@@ -973,10 +912,7 @@
         pause_start_time = 0;
     }
     
-    pcmrec_dma_start();
-    
     resume_done = true;
-    
     logf("pcmrec_resume done");
 }
 
@@ -986,50 +922,47 @@
  */
 static void pcmrec_init(void)
 {
-    unsigned long buffer_size;
-
     wav_file = -1;  
-    read_index = 0;
-    read2_index = 0;
-    write_index = 0;
-    pre_record_chunks = 0;
-    pre_record_ticks = 0;
+    read_pos = 0;
+    write_pos = 0;
+    enc_wr_index = 0;
+    enc_rd_index = 0;
+
+    avrg_bit_rate  = 0;
+    curr_bit_rate  = 0;
+    curr_chunk_cnt = 0;
 
     peak_left = 0;
     peak_right = 0;
     
     num_rec_bytes = 0;
     num_file_bytes = 0;
+    num_pcm_samples = 0;
     record_start_time = 0;
     pause_start_time = 0;
-    buffered_chunks = 0;
-    
+
+    close_done = false;
     is_recording = false;
-    is_stopping = false;
     is_paused = false;
     is_error = false;
 
-    rec_buffer = (unsigned char*)(((unsigned long)audiobuf + rec_buffer_offset) & ~3);
-    buffer_size = (long)audiobufend - (long)audiobuf - rec_buffer_offset - 16;
-    
-    logf("buf size: %d kb", buffer_size/1024);
-    
-    num_chunks = buffer_size / CHUNK_SIZE;
+    rec_buffer = (unsigned char*)(((long)audiobuf + 15) & ~15);
+    enc_buffer = rec_buffer + NUM_CHUNKS * CHUNK_SIZE + MAX_FEED_SIZE;
+    /* 8000Bytes at audiobufend */
+    enc_buffer_size = audiobufend - enc_buffer - 8000;
 
-    logf("num_chunks: %d", num_chunks);
+    SET_IIS_PLAY(0x800); /* Stop any playback                              */
+    AUDIOGLOB |= 0x180;  /* IIS1 fifo auto sync = on, PDIR2 auto sync = on */
+    DATAINCONTROL = 0xc000; /* Generate Interrupt when 6 samples in fifo   */
 
-    SET_IIS_PLAY(0x800);            /* Stop any playback                              */
-    AUDIOGLOB |= 0x180;             /* IIS1 fifo auto sync = on, PDIR2 auto sync = on */
-    DATAINCONTROL = 0xc000;         /* Generate Interrupt when 6 samples in fifo      */
-
-    DIVR1 = 55;                     /* DMA1 is mapped into vector 55 in system.c      */
-    DMACONFIG = 1;                  /* DMA0Req = PDOR3, DMA1Req = PDIR2               */
+    DIVR1 = 55;          /* DMA1 is mapped into vector 55 in system.c      */
+    DMACONFIG = 1;       /* DMA0Req = PDOR3, DMA1Req = PDIR2               */
     DMAROUTE = (DMAROUTE & 0xffff00ff) | DMA1_REQ_AUDIO_2;
-    ICR7 = 0x1c;                    /* Enable interrupt at level 7, priority 0 */
-    IMR &= ~(1<<15);                /* bit 15 is DMA1 */
+    ICR7 = 0x1c;         /* Enable interrupt at level 7, priority 0        */
+    IMR &= ~(1<<15);     /* bit 15 is DMA1                                 */
 
 #ifdef HAVE_SPDIF_IN
-    PHASECONFIG = 0x34;             /* Gain = 3*2^13, source = EBUIN */
+    PHASECONFIG = 0x34;  /* Gain = 3*2^13, source = EBUIN                  */
 #endif
     pcmrec_dma_start();
 
@@ -1038,23 +971,16 @@
 
 static void pcmrec_close(void)
 {
-#ifdef HAVE_UDA1380            
-    uda1380_disable_recording();
-#endif
-#ifdef HAVE_TLV320
-    tlv320_disable_recording();
-#endif            
-
-#ifdef HAVE_SPDIF_POWER
-    spdif_power_enable(spdif_power_setting);
-#endif
     DMAROUTE = (DMAROUTE & 0xffff00ff);
     ICR7 = 0x00;     /* Disable interrupt */
     IMR |= (1<<15);  /* bit 15 is DMA1 */
 
+    pcmrec_dma_stop();
+
     /* Reset PDIR2 data flow */
     DATAINCONTROL = 0x200;
     close_done = true;
+    init_done = false;
 }
 
 static void pcmrec_thread(void)
@@ -1064,10 +990,10 @@
     logf("thread pcmrec start");
 
     error_count = 0;
-    
-    while (1)
+
+    while(1)
     {
-        queue_wait_w_tmo(&pcmrec_queue, &ev, HZ / 40);
+        queue_wait_w_tmo(&pcmrec_queue, &ev, HZ / 4);
 
         switch (ev.id)
         {
@@ -1104,8 +1030,9 @@
                 break;
 
             case SYS_USB_CONNECTED:
-                if (!is_recording && !is_stopping)
+                if (!is_recording)
                 {
+                    pcmrec_close();
                     usb_acknowledge(SYS_USB_CONNECTED_ACK);
                     usb_wait_for_disconnect(&pcmrec_queue);
                 }
@@ -1148,3 +1075,102 @@
     /* iAudio x5 */
 #endif
 }
+
+
+/****************************************************************************/
+/*                                                                          */
+/*         following functions will be called by the encoder codec          */
+/*                                                                          */
+/****************************************************************************/
+
+/* pass the encoder buffer pointer/size, mono/stereo, quality to the encoder */
+void enc_get_inputs(int *buffer_size, int *channels, int *quality)
+{
+    *buffer_size = enc_buffer_size;
+    *channels    = enc_channels;
+    *quality     = enc_quality;
+}
+
+/* set the encoder dimensions (called by encoder codec at initialization) */
+void enc_set_parameters(int chunk_size, int num_chunks, int samp_per_chunk,
+                        char *head_ptr, int head_size, int enc_id)
+{
+    /* set read_pos just in front of current write_pos */
+    read_pos = (write_pos - CHUNK_SIZE) & CHUNK_MASK;
+
+    enc_rd_index       = 0;              /* reset */
+    enc_wr_index       = 0;              /* reset */
+    enc_chunk_size     = chunk_size;     /* max chunk size */
+    enc_num_chunks     = num_chunks;     /* total number of chunks */
+    enc_samp_per_chunk = samp_per_chunk; /* pcm samples / encoderchunk */
+    enc_head_buffer    = head_ptr;       /* optional file header data (wav) */
+    enc_head_size      = head_size;      /* optional file header data (wav) */
+    audio_enc_id       = enc_id;         /* AFMT_* id */
+}
+
+/* allocate encoder chunk */
+unsigned int *enc_alloc_chunk(void)
+{
+    return (unsigned int*)(enc_buffer + enc_wr_index * enc_chunk_size);
+}
+
+/* free previously allocated encoder chunk */
+void enc_free_chunk(void)
+{
+    unsigned long *enc_chunk;
+
+    enc_chunk = GET_ENC_CHUNK(enc_wr_index);
+    curr_chunk_cnt++;
+/*  curr_bit_rate += *enc_chunk * 44100 * 8 / (enc_samp_per_chunk * 1000); */
+    curr_bit_rate += *enc_chunk * 441   * 8 / (enc_samp_per_chunk * 10  );
+    avrg_bit_rate  = (curr_bit_rate + curr_chunk_cnt / 2) / curr_chunk_cnt;
+
+    /* advance enc_wr_index to the next chunk */
+    enc_wr_index = (enc_wr_index + 1) % enc_num_chunks;
+
+    /* buffer full: advance enc_rd_index (for prerecording purpose) */
+    if (enc_rd_index == enc_wr_index)
+    {
+        enc_rd_index = (enc_rd_index + 1) % enc_num_chunks;
+    }
+}
+
+/* checks near empty state on wav input buffer */
+int enc_wavbuf_near_empty(void)
+{
+    /* less than 1sec raw data? => unboost encoder */
+    if (((write_pos - read_pos) & CHUNK_MASK) < 44100*4)
+        return 1;
+    else
+        return 0;
+}
+
+/* passes a pointer to next chunk of unprocessed wav data */
+char *enc_get_wav_data(int size)
+{
+    char *ptr;
+    int  avail;
+
+    /* limit the requested pcm data size */
+    if(size > MAX_FEED_SIZE)
+        size = MAX_FEED_SIZE;
+
+    avail = (write_pos - read_pos) & CHUNK_MASK;
+
+    if (avail >= size)
+    {
+        ptr = rec_buffer + read_pos;
+        read_pos = (read_pos + size) & CHUNK_MASK;
+
+        /* ptr must point to continous data at wraparound position */
+        if (read_pos < size)
+            memcpy(rec_buffer + NUM_CHUNKS * CHUNK_SIZE,
+                rec_buffer, read_pos);
+
+        wav_queue_empty = false;
+        return ptr;
+    }
+
+    wav_queue_empty = true;
+    return NULL;
+}
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index 3dd4c60..377c34a 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -424,6 +424,7 @@
  * 1) The USB is connected
  * 2) The charger is connected
  * 3) We are recording, or recording with pause
+ * 4) The radio is playing
  */
 static void handle_auto_poweroff(void)
 {
@@ -442,7 +443,7 @@
 
     if(timeout &&
 #ifdef CONFIG_TUNER
-       (!radio_powered()) &&
+       (!(get_radio_status() & FMRADIO_PLAYING)) &&
 #endif
        !usb_inserted() &&
        ((audio_stat == 0) ||