diff options
-rw-r--r-- | pjmedia/build/pjmedia.dsp | 22 | ||||
-rw-r--r-- | pjmedia/include/pjmedia/conference.h | 2 | ||||
-rw-r--r-- | pjmedia/include/pjmedia/resample.h | 76 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/conference.c | 546 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/file_port.c | 48 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/largefilter.h | 16391 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/resample.c | 562 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/smallfilter.h | 4617 | ||||
-rw-r--r-- | pjsip-apps/src/pjsua/main.c | 4 | ||||
-rw-r--r-- | pjsip/include/pjsua-lib/pjsua.h | 1 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_core.c | 7 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_settings.c | 14 |
12 files changed, 22123 insertions, 167 deletions
diff --git a/pjmedia/build/pjmedia.dsp b/pjmedia/build/pjmedia.dsp index 1475636f..f7bf4024 100644 --- a/pjmedia/build/pjmedia.dsp +++ b/pjmedia/build/pjmedia.dsp @@ -133,6 +133,10 @@ SOURCE=..\src\pjmedia\port.c # End Source File
# Begin Source File
+SOURCE=..\src\pjmedia\resample.c
+# End Source File
+# Begin Source File
+
SOURCE=..\src\pjmedia\rtcp.c
# End Source File
# Begin Source File
@@ -213,6 +217,10 @@ SOURCE=..\include\pjmedia\port.h # End Source File
# Begin Source File
+SOURCE=..\include\pjmedia\resample.h
+# End Source File
+# Begin Source File
+
SOURCE=..\include\pjmedia\rtcp.h
# End Source File
# Begin Source File
@@ -256,7 +264,7 @@ SOURCE=..\include\pjmedia\types.h SOURCE=..\include\pjmedia\wave.h
# End Source File
# End Group
-# Begin Group "PortAudio"
+# Begin Group "PortAudio Files"
# PROP Default_Filter ""
# Begin Source File
@@ -395,5 +403,17 @@ SOURCE=..\src\pjmedia\portaudio\pa_x86_plain_converters.h SOURCE=..\src\pjmedia\portaudio\portaudio.h
# End Source File
# End Group
+# Begin Group "Resample Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\pjmedia\largefilter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\pjmedia\smallfilter.h
+# End Source File
+# End Group
# End Target
# End Project
diff --git a/pjmedia/include/pjmedia/conference.h b/pjmedia/include/pjmedia/conference.h index 775e2ff7..3b850cbd 100644 --- a/pjmedia/include/pjmedia/conference.h +++ b/pjmedia/include/pjmedia/conference.h @@ -45,6 +45,8 @@ typedef struct pjmedia_conf_port_info pjmedia_port_op tx_setting; pjmedia_port_op rx_setting; pj_bool_t *listener; + unsigned clock_rate; + unsigned samples_per_frame; } pjmedia_conf_port_info; diff --git a/pjmedia/include/pjmedia/resample.h b/pjmedia/include/pjmedia/resample.h new file mode 100644 index 00000000..63b3351d --- /dev/null +++ b/pjmedia/include/pjmedia/resample.h @@ -0,0 +1,76 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJMEDIA_RESAMPLE_H__ +#define __PJMEDIA_RESAMPLE_H__ + + + +/** + * @file reample.h + * @brief Sample rate converter. + */ +#include "pjmedia/types.h" + +PJ_BEGIN_DECL + +/** + * Opaque resample session. + */ +typedef struct pjmedia_resample pjmedia_resample; + +/** + * Create a frame based resample session. + * + * @param pool Pool to allocate the structure and buffers. + * @param high_quality If true, then high quality conversion will be + * used, at the expense of more CPU and memory, + * because temporary buffer needs to be created. + * @param large_filter If true, large filter size will be used. + * @param rate_in Clock rate of the input samples. + * @param rate_out Clock rate of the output samples. + * @param samples_per_frame Number of samples per frame in the input. + * @param p_resample Pointer to receive the resample session. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_resample_create(pj_pool_t *pool, + pj_bool_t high_quality, + pj_bool_t large_filter, + unsigned rate_in, + unsigned rate_out, + unsigned samples_per_frame, + pjmedia_resample **p_resample); + + +/** + * Resample a frame. + * + * @param resample The resample session. + * @param input Buffer containing the input samples. + * @param output Buffer to store the output samples. + */ +PJ_DECL(void) pjmedia_resample_run( pjmedia_resample *resample, + const pj_int16_t *input, + pj_int16_t *output ); + + +PJ_END_DECL + +#endif /* __PJMEDIA_RESAMPLE_H__ */ + diff --git a/pjmedia/src/pjmedia/conference.c b/pjmedia/src/pjmedia/conference.c index 39206396..087468c7 100644 --- a/pjmedia/src/pjmedia/conference.c +++ b/pjmedia/src/pjmedia/conference.c @@ -17,11 +17,12 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <pjmedia/conference.h> -#include <pjmedia/silencedet.h> -#include <pjmedia/stream.h> -#include <pjmedia/sound.h> #include <pjmedia/errno.h> #include <pjmedia/port.h> +#include <pjmedia/resample.h> +#include <pjmedia/silencedet.h> +#include <pjmedia/sound.h> +#include <pjmedia/stream.h> #include <pj/assert.h> #include <pj/log.h> #include <pj/pool.h> @@ -39,6 +40,8 @@ #define THIS_FILE "conference.c" #define RX_BUF_COUNT 8 +#define BYTES_PER_SAMPLE 2 + /* * DON'T GET CONFUSED!! * @@ -47,6 +50,9 @@ */ +/** + * This is a port connected to conference bridge. + */ struct conf_port { pj_str_t name; /**< Port name. */ @@ -57,27 +63,62 @@ struct conf_port pj_bool_t *listeners; /**< Array of listeners. */ pjmedia_silence_det *vad; /**< VAD for this port. */ - /* Tx buffer contains the frame to be "transmitted" to this port - * (i.e. for put_frame()). - * We use dual buffer since the port may be accessed by two threads, - * and we don't want to use mutex for synchronization. + /* Shortcut for port info. */ + unsigned clock_rate; /**< Port's clock rate. */ + unsigned samples_per_frame; /**< Port's samples per frame. */ + + /* Resample, for converting clock rate, if they're different. */ + pjmedia_resample *rx_resample; + pjmedia_resample *tx_resample; + + /* RX buffer is temporary buffer to be used when there is mismatch + * between port's sample rate or ptime with conference's sample rate + * or ptime. When both sample rate and ptime of the port match the + * conference settings, this buffer will not be used. + * + * This buffer contains samples at port's clock rate. + * The size of this buffer is the sum between port's samples per frame + * and bridge's samples per frame. */ - pj_int16_t *cur_tx_buf; /**< Buffer for put_frame(). */ - pj_int16_t *tx_buf1; /**< Buffer 1. */ - pj_int16_t *tx_buf2; /**< Buffer 2. */ + pj_int16_t *rx_buf; /**< The RX buffer. */ + unsigned rx_buf_cap; /**< Max size, in samples */ + unsigned rx_buf_count; /**< # of samples in the buf. */ - /* Rx buffers is a special buffer for sound device port (port 0). - * It's not used by other ports. - */ - int rx_write, rx_read; - pj_int16_t *rx_buf[RX_BUF_COUNT]; /**< Buffer */ - - - /* Sum buf is a temporary buffer used to calculate the average signal + /* Mix buf is a temporary buffer used to calculate the average signal * received by this port from all other ports. + * + * This buffer contains samples at bridge's clock rate. + * The size of this buffer is equal to samples per frame of the bridge. + * + * Note that the samples here are unsigned 32bit. */ unsigned sources; /**< Number of sources. */ - pj_uint32_t *sum_buf; /**< Total sum of signal. */ + pj_uint32_t *mix_buf; /**< Total sum of signal. */ + + /* Tx buffer is a temporary buffer to be used when there's mismatch + * between port's clock rate or ptime with conference's sample rate + * or ptime. When both sample rate and ptime of the port match the + * conference's settings, this buffer will not be used. + * + * This buffer contains samples at port's clock rate. + * The size of this buffer is the sum between port's samples per frame + * and bridge's samples per frame. + */ + pj_int16_t *tx_buf; /**< Tx buffer. */ + unsigned tx_buf_cap; /**< Max size, in samples. */ + unsigned tx_buf_count; /**< # of samples in the buffer. */ + + /* Snd buffers is a special buffer for sound device port (port 0). + * It's not used by other ports. + * + * There are multiple numbers of this buffer, because we can not expect + * the mic and speaker thread to run equally after one another. In most + * systems, each thread will run multiple times before the other thread + * gains execution time. For example, in my system, mic thread is called + * three times, then speaker thread is called three times, and so on. + */ + int snd_write_pos, snd_read_pos; + pj_int16_t *snd_buf[RX_BUF_COUNT]; /**< Buffer */ }; @@ -94,10 +135,10 @@ struct pjmedia_conf pj_mutex_t *mutex; /**< Conference mutex. */ struct conf_port **ports; /**< Array of ports. */ pj_uint16_t *uns_buf; /**< Buf for unsigned conversion */ - unsigned sampling_rate; /**< Sampling rate. */ + unsigned clock_rate; /**< Sampling rate. */ unsigned samples_per_frame; /**< Samples per frame. */ unsigned bits_per_sample; /**< Bits per sample. */ - pj_snd_stream_info snd_info; + pj_snd_stream_info snd_info; /**< Sound device parameter. */ }; @@ -119,6 +160,7 @@ static pj_status_t rec_cb( /* in */ void *user_data, */ static pj_status_t create_conf_port( pj_pool_t *pool, pjmedia_conf *conf, + pjmedia_port *port, const pj_str_t *name, struct conf_port **p_conf_port) { @@ -149,26 +191,82 @@ static pj_status_t create_conf_port( pj_pool_t *pool, pjmedia_silence_det_set_adaptive(conf_port->vad, conf->samples_per_frame); + /* Save some port's infos, for convenience. */ + if (port) { + conf_port->port = port; + conf_port->clock_rate = port->info.sample_rate; + conf_port->samples_per_frame = port->info.samples_per_frame; + } else { + conf_port->port = NULL; + conf_port->clock_rate = conf->clock_rate; + conf_port->samples_per_frame = conf->samples_per_frame; + } - /* Create TX buffers. */ - conf_port->tx_buf1 = pj_pool_zalloc(pool, conf->samples_per_frame * - sizeof(conf_port->tx_buf1[0])); - PJ_ASSERT_RETURN(conf_port->tx_buf1, PJ_ENOMEM); + /* If port's clock rate is different than conference's clock rate, + * create a resample sessions. + */ + if (conf_port->clock_rate != conf->clock_rate) { - conf_port->tx_buf2 = pj_pool_zalloc(pool, conf->samples_per_frame * - sizeof(conf_port->tx_buf2[0])); - PJ_ASSERT_RETURN(conf_port->tx_buf2, PJ_ENOMEM); + double factor; - /* Set initial TX buffer */ - conf_port->cur_tx_buf = conf_port->tx_buf1; + factor = 1.0 * conf_port->clock_rate / conf->clock_rate; - /* Create temporary buffer to calculate average signal received by - * this port. + /* Create resample for rx buffer. */ + status = pjmedia_resample_create( pool, + PJ_TRUE, /* High quality */ + PJ_TRUE, /* Large filter */ + conf_port->clock_rate,/* Rate in */ + conf->clock_rate, /* Rate out */ + (unsigned)(conf->samples_per_frame * + factor), + &conf_port->rx_resample); + if (status != PJ_SUCCESS) + return status; + + + /* Create resample for tx buffer. */ + status = pjmedia_resample_create(pool, + PJ_TRUE, /* High quality */ + PJ_TRUE, /* Large filter */ + conf->clock_rate, /* Rate in */ + conf_port->clock_rate, /* Rate out */ + conf->samples_per_frame, + &conf_port->tx_resample); + if (status != PJ_SUCCESS) + return status; + } + + /* + * Initialize rx and tx buffer, only when port's samples per frame or + * port's clock rate is different then the conference bridge settings. */ - conf_port->sum_buf = pj_pool_zalloc(pool, conf->samples_per_frame * - sizeof(conf_port->sum_buf[0])); + if (conf_port->clock_rate != conf->clock_rate || + conf_port->samples_per_frame != conf->samples_per_frame) + { + /* Create RX buffer. */ + conf_port->rx_buf_cap = (unsigned)(conf_port->samples_per_frame + + conf->samples_per_frame * + conf_port->clock_rate * 1.0 / + conf->clock_rate); + conf_port->rx_buf_count = 0; + conf_port->rx_buf = pj_pool_alloc(pool, conf_port->rx_buf_cap * + sizeof(conf_port->rx_buf[0])); + PJ_ASSERT_RETURN(conf_port->rx_buf, PJ_ENOMEM); + + /* Create TX buffer. */ + conf_port->tx_buf_cap = conf_port->rx_buf_cap; + conf_port->tx_buf_count = 0; + conf_port->tx_buf = pj_pool_alloc(pool, conf_port->tx_buf_cap * + sizeof(conf_port->tx_buf[0])); + PJ_ASSERT_RETURN(conf_port->tx_buf, PJ_ENOMEM); + } + + + /* Create mix buffer. */ + conf_port->mix_buf = pj_pool_zalloc(pool, conf->samples_per_frame * + sizeof(conf_port->mix_buf[0])); + PJ_ASSERT_RETURN(conf_port->mix_buf, PJ_ENOMEM); - /* Done */ *p_conf_port = conf_port; @@ -189,7 +287,7 @@ static pj_status_t create_sound_port( pj_pool_t *pool, /* Init default sound device parameters. */ pj_memset(&conf->snd_info, 0, sizeof(conf->snd_info)); - conf->snd_info.samples_per_sec = conf->sampling_rate; + conf->snd_info.samples_per_sec = conf->clock_rate; conf->snd_info.bits_per_sample = conf->bits_per_sample; conf->snd_info.samples_per_frame = conf->samples_per_frame; conf->snd_info.bytes_per_frame = conf->samples_per_frame * @@ -198,21 +296,21 @@ static pj_status_t create_sound_port( pj_pool_t *pool, /* Create port */ - status = create_conf_port(pool, conf, &name, &conf_port); + status = create_conf_port(pool, conf, NULL, &name, &conf_port); if (status != PJ_SUCCESS) goto on_error; /* Sound device has rx buffers. */ for (i=0; i<RX_BUF_COUNT; ++i) { - conf_port->rx_buf[i] = pj_pool_zalloc(pool, conf->samples_per_frame * - sizeof(conf_port->rx_buf[0][0])); - if (conf_port->rx_buf[i] == NULL) { + conf_port->snd_buf[i] = pj_pool_zalloc(pool, conf->samples_per_frame * + sizeof(conf_port->snd_buf[0][0])); + if (conf_port->snd_buf[i] == NULL) { status = PJ_ENOMEM; goto on_error; } } - conf_port->rx_write = 0; - conf_port->rx_read = 0; + conf_port->snd_write_pos = 0; + conf_port->snd_read_pos = 0; /* Set to port zero */ @@ -232,7 +330,7 @@ on_error: */ PJ_DEF(pj_status_t) pjmedia_conf_create( pj_pool_t *pool, unsigned max_ports, - unsigned sampling_rate, + unsigned clock_rate, unsigned samples_per_frame, unsigned bits_per_sample, pjmedia_conf **p_conf ) @@ -240,6 +338,9 @@ PJ_DEF(pj_status_t) pjmedia_conf_create( pj_pool_t *pool, pjmedia_conf *conf; pj_status_t status; + /* Can only accept 16bits per sample, for now.. */ + PJ_ASSERT_RETURN(bits_per_sample == 16, PJ_EINVAL); + PJ_LOG(5,(THIS_FILE, "Creating conference bridge with %d ports", max_ports)); @@ -251,7 +352,7 @@ PJ_DEF(pj_status_t) pjmedia_conf_create( pj_pool_t *pool, PJ_ASSERT_RETURN(conf->ports, PJ_ENOMEM); conf->max_ports = max_ports; - conf->sampling_rate = sampling_rate; + conf->clock_rate = clock_rate; conf->samples_per_frame = samples_per_frame; conf->bits_per_sample = bits_per_sample; @@ -402,15 +503,12 @@ PJ_DEF(pj_status_t) pjmedia_conf_add_port( pjmedia_conf *conf, pj_assert(index != conf->max_ports); /* Create port structure. */ - status = create_conf_port(pool, conf, port_name, &conf_port); + status = create_conf_port(pool, conf, strm_port, port_name, &conf_port); if (status != PJ_SUCCESS) { pj_mutex_unlock(conf->mutex); return status; } - /* Set the port */ - conf_port->port = strm_port; - /* Put the port. */ conf->ports[index] = conf_port; conf->port_cnt++; @@ -634,6 +732,8 @@ PJ_DEF(pj_status_t) pjmedia_conf_get_port_info( pjmedia_conf *conf, info->tx_setting = conf_port->tx_setting; info->rx_setting = conf_port->rx_setting; info->listener = conf_port->listeners; + info->clock_rate = conf_port->clock_rate; + info->samples_per_frame = conf_port->samples_per_frame; return PJ_SUCCESS; } @@ -672,6 +772,214 @@ static pj_int16_t unsigned2pcm(pj_uint32_t uns) return (pj_int16_t)(uns - 32767); } +/* Copy samples */ +PJ_INLINE(void) copy_samples(pj_int16_t *dst, + const pj_int16_t *src, + unsigned count) +{ + unsigned i; + for (i=0; i<count; ++i) + dst[i] = src[i]; +} + +/* Zero samples. */ +PJ_INLINE(void) zero_samples(pj_int16_t *buf, unsigned count) +{ + unsigned i; + for (i=0; i<count; ++i) + buf[i] = 0; +} + + +/* + * Read from port. + */ +static pj_status_t read_port( pjmedia_conf *conf, + struct conf_port *cport, pj_int16_t *frame, + pj_size_t count, pjmedia_frame_type *type ) +{ + + pj_assert(count == conf->samples_per_frame); + + /* If port's samples per frame and sampling rate matches conference + * bridge's settings, get the frame directly from the port. + */ + if (cport->rx_buf_cap == 0) { + pjmedia_frame f; + pj_status_t status; + + f.buf = frame; + f.size = count * BYTES_PER_SAMPLE; + + status = (cport->port->get_frame)(cport->port, &f); + + *type = f.type; + + return status; + + } else { + + /* + * If we don't have enough samples in rx_buf, read from the port + * first. Remember that rx_buf may be in different clock rate! + */ + while (cport->rx_buf_count < count * 1.0 * + cport->clock_rate / conf->clock_rate) { + + pjmedia_frame f; + pj_status_t status; + + f.buf = cport->rx_buf + cport->rx_buf_count; + f.size = cport->samples_per_frame * BYTES_PER_SAMPLE; + + status = pjmedia_port_get_frame(cport->port, &f); + + if (status != PJ_SUCCESS) { + /* Fatal error! */ + return status; + } + + if (f.type != PJMEDIA_FRAME_TYPE_AUDIO) { + zero_samples( cport->rx_buf + cport->rx_buf_count, + cport->samples_per_frame); + } + + cport->rx_buf_count += cport->samples_per_frame; + + pj_assert(cport->rx_buf_count <= cport->rx_buf_cap); + } + + /* + * If port's clock_rate is different, resample. + * Otherwise just copy. + */ + if (cport->clock_rate != conf->clock_rate) { + + unsigned src_count; + + pjmedia_resample_run( cport->rx_resample,cport->rx_buf, frame); + + src_count = (unsigned)(count * 1.0 * cport->clock_rate / + conf->clock_rate); + cport->rx_buf_count -= src_count; + if (cport->rx_buf_count) { + copy_samples(cport->rx_buf, cport->rx_buf+src_count, + cport->rx_buf_count); + } + + } else { + + copy_samples(frame, cport->rx_buf, count); + cport->rx_buf_count -= count; + if (cport->rx_buf_count) { + copy_samples(cport->rx_buf, cport->rx_buf+count, + cport->rx_buf_count); + } + } + } + + return PJ_SUCCESS; +} + + +/* + * Write the mixed signal to the port. + */ +static pj_status_t write_port(pjmedia_conf *conf, struct conf_port *cport, + pj_uint32_t timestamp) +{ + pj_int16_t *buf; + unsigned j; + + /* If port is muted or nobody is transmitting to this port, + * transmit NULL frame. + */ + if (cport->tx_setting == PJMEDIA_PORT_MUTE || cport->sources==0) { + + pjmedia_frame frame; + + frame.type = PJMEDIA_FRAME_TYPE_NONE; + frame.buf = NULL; + frame.size = 0; + + if (cport->port) + pjmedia_port_put_frame(cport->port, &frame); + + return PJ_SUCCESS; + + } else if (cport->tx_setting != PJMEDIA_PORT_ENABLE) { + return PJ_SUCCESS; + } + + /* If there are sources in the mix buffer, convert the mixed samples + * to the mixed samples itself. This is possible because mixed sample + * is 32bit. + */ + buf = (pj_int16_t*)cport->mix_buf; + for (j=0; j<conf->samples_per_frame; ++j) { + buf[j] = unsigned2pcm(cport->mix_buf[j] / cport->sources); + } + + /* If port has the same clock_date and samples_per_frame settings as + * the conference bridge, transmit the frame as is. + */ + if (cport->clock_rate == conf->clock_rate && + cport->samples_per_frame == conf->samples_per_frame) + { + pjmedia_frame frame; + + frame.type = PJMEDIA_FRAME_TYPE_AUDIO; + frame.buf = (pj_int16_t*)cport->mix_buf; + frame.size = conf->samples_per_frame * BYTES_PER_SAMPLE; + frame.timestamp.u64 = timestamp; + + if (cport->port != NULL) + return pjmedia_port_put_frame(cport->port, &frame); + else + return PJ_SUCCESS; + } + + /* If it has different clock_rate, must resample. */ + if (cport->clock_rate != conf->clock_rate) { + + unsigned dst_count; + + pjmedia_resample_run( cport->tx_resample, buf, + cport->tx_buf + cport->tx_buf_count ); + + dst_count = (unsigned)(conf->samples_per_frame * 1.0 * + cport->clock_rate / conf->clock_rate); + cport->tx_buf_count += dst_count; + + } else { + /* Same clock rate. + * Just copy the samples to tx_buffer. + */ + copy_samples( cport->tx_buf + cport->tx_buf_count, + buf, conf->samples_per_frame ); + cport->tx_buf_count += conf->samples_per_frame; + } + + /* Transmit once we have enough frame in the tx_buf. */ + if (cport->tx_buf_count >= cport->samples_per_frame) { + + pjmedia_frame frame; + + frame.type = PJMEDIA_FRAME_TYPE_AUDIO; + frame.buf = cport->tx_buf; + frame.size = cport->samples_per_frame * BYTES_PER_SAMPLE; + frame.timestamp.u64 = timestamp; + + if (cport->port) + return pjmedia_port_put_frame(cport->port, &frame); + else + return PJ_SUCCESS; + } + + return PJ_SUCCESS; +} + + /* * Player callback. */ @@ -681,7 +989,6 @@ static pj_status_t play_cb( /* in */ void *user_data, /* out */ unsigned size) { pjmedia_conf *conf = user_data; - pj_int16_t *output_buf = output; unsigned ci, cj, i, j; PJ_UNUSED_ARG(timestamp); @@ -694,7 +1001,7 @@ static pj_status_t play_cb( /* in */ void *user_data, /* Zero all port's temporary buffers. */ for (i=0, ci=0; i<conf->max_ports && ci < conf->port_cnt; ++i) { struct conf_port *conf_port = conf->ports[i]; - pj_uint32_t *sum_buf; + pj_uint32_t *mix_buf; /* Skip empty slot. */ if (!conf_port) @@ -703,14 +1010,14 @@ static pj_status_t play_cb( /* in */ void *user_data, ++ci; conf_port->sources = 0; - sum_buf = conf_port->sum_buf; + mix_buf = conf_port->mix_buf; for (j=0; j<conf->samples_per_frame; ++j) - sum_buf[j] = 0; + mix_buf[j] = 0; } /* Get frames from all ports, and "mix" the signal - * to sum_buf of all listeners of the port. + * to mix_buf of all listeners of the port. */ for (i=0, ci=0; i<conf->max_ports && ci<conf->port_cnt; ++i) { struct conf_port *conf_port = conf->ports[i]; @@ -732,11 +1039,11 @@ static pj_status_t play_cb( /* in */ void *user_data, * instead. */ if (i==0) { - pj_int16_t *rx_buf; + pj_int16_t *snd_buf; - if (conf_port->rx_read == conf_port->rx_write) { - conf_port->rx_read = - (conf_port->rx_write+RX_BUF_COUNT-RX_BUF_COUNT/2) % + if (conf_port->snd_read_pos == conf_port->snd_write_pos) { + conf_port->snd_read_pos = + (conf_port->snd_write_pos+RX_BUF_COUNT-RX_BUF_COUNT/2) % RX_BUF_COUNT; } @@ -751,28 +1058,31 @@ static pj_status_t play_cb( /* in */ void *user_data, continue; } - rx_buf = conf_port->rx_buf[conf_port->rx_read]; + snd_buf = conf_port->snd_buf[conf_port->snd_read_pos]; for (j=0; j<conf->samples_per_frame; ++j) { - ((pj_int16_t*)output)[j] = rx_buf[j]; + ((pj_int16_t*)output)[j] = snd_buf[j]; } - conf_port->rx_read = (conf_port->rx_read+1) % RX_BUF_COUNT; + conf_port->snd_read_pos = (conf_port->snd_read_pos+1) % RX_BUF_COUNT; } else { - pjmedia_frame frame; - pj_memset(&frame, 0, sizeof(frame)); - frame.buf = output; - frame.size = size; - pjmedia_port_get_frame(conf_port->port, &frame); - - if (frame.type == PJMEDIA_FRAME_TYPE_NONE) + pj_status_t status; + pjmedia_frame_type frame_type; + + status = read_port(conf, conf_port, output, + conf->samples_per_frame, &frame_type); + + if (status != PJ_SUCCESS) { + PJ_LOG(4,(THIS_FILE, "Port %.*s get_frame() returned %d. " + "Port is now disabled", + (int)conf_port->name.slen, + conf_port->name.ptr, + status)); + conf_port->rx_setting = PJMEDIA_PORT_DISABLE; continue; + } } - /* Skip (after receiving the frame) if this port is muted. */ - if (conf_port->rx_setting == PJMEDIA_PORT_MUTE) - continue; - /* Also skip if this port doesn't have listeners. */ if (conf_port->listener_cnt == 0) continue; @@ -793,7 +1103,7 @@ static pj_status_t play_cb( /* in */ void *user_data, ++j) { struct conf_port *listener = conf->ports[j]; - pj_uint32_t *sum_buf; + pj_uint32_t *mix_buf; unsigned k; if (listener == 0) @@ -810,9 +1120,9 @@ static pj_status_t play_cb( /* in */ void *user_data, continue; /* Mix the buffer */ - sum_buf = listener->sum_buf; + mix_buf = listener->mix_buf; for (k=0; k<conf->samples_per_frame; ++k) - sum_buf[k] += (conf->uns_buf[k] * level); + mix_buf[k] += (conf->uns_buf[k] * level); listener->sources += level; } @@ -821,75 +1131,31 @@ static pj_status_t play_cb( /* in */ void *user_data, /* For all ports, calculate avg signal. */ for (i=0, ci=0; i<conf->max_ports && ci<conf->port_cnt; ++i) { struct conf_port *conf_port = conf->ports[i]; - pjmedia_frame frame; - pj_int16_t *target_buf; + pj_status_t status; if (!conf_port) continue; ++ci; - if (conf_port->tx_setting == PJMEDIA_PORT_MUTE) { - frame.type = PJMEDIA_FRAME_TYPE_NONE; - frame.buf = NULL; - frame.size = 0; - - if (conf_port->port) - pjmedia_port_put_frame(conf_port->port, &frame); - + status = write_port( conf, conf_port, timestamp); + if (status != PJ_SUCCESS) { + PJ_LOG(4,(THIS_FILE, "Port %.*s put_frame() returned %d. " + "Port is now disabled", + (int)conf_port->name.slen, + conf_port->name.ptr, + status)); + conf_port->tx_setting = PJMEDIA_PORT_DISABLE; continue; - - } else if (conf_port->tx_setting != PJMEDIA_PORT_ENABLE) { - continue; - } - - target_buf = (conf_port->cur_tx_buf==conf_port->tx_buf1? - conf_port->tx_buf2 : conf_port->tx_buf1); - - if (conf_port->sources) { - for (j=0; j<conf->samples_per_frame; ++j) { - target_buf[j] = unsigned2pcm(conf_port->sum_buf[j] / - conf_port->sources); - } } - - /* Switch buffer. */ - conf_port->cur_tx_buf = target_buf; - - pj_memset(&frame, 0, sizeof(frame)); - if (conf_port->sources) { - - pj_bool_t is_silence = PJ_FALSE; - - /* Apply silence detection. */ -#if 0 - is_silence = pjmedia_silence_det_detect(conf_port->vad, - target_buf, - conf->samples_per_frame, - NULL); -#endif - frame.type = is_silence ? PJMEDIA_FRAME_TYPE_NONE : - PJMEDIA_FRAME_TYPE_AUDIO; - - } else - frame.type = PJMEDIA_FRAME_TYPE_NONE; - - frame.buf = conf_port->cur_tx_buf; - frame.size = conf->samples_per_frame * conf->bits_per_sample / 8; - frame.timestamp.u64 = timestamp; - - if (conf_port->port) - pjmedia_port_put_frame(conf_port->port, &frame); - } /* Return sound playback frame. */ if (conf->ports[0]->sources) { - for (j=0; j<conf->samples_per_frame; ++j) - output_buf[j] = conf->ports[0]->cur_tx_buf[j]; + copy_samples( output, (pj_int16_t*)conf->ports[0]->mix_buf, + conf->samples_per_frame); } else { - for (j=0; j<conf->samples_per_frame; ++j) - output_buf[j] = 0; + zero_samples( output, conf->samples_per_frame ); } pj_mutex_unlock(conf->mutex); @@ -908,7 +1174,7 @@ static pj_status_t rec_cb( /* in */ void *user_data, { pjmedia_conf *conf = user_data; struct conf_port *snd_port = conf->ports[0]; - pj_int16_t *target_rx_buf; + pj_int16_t *target_snd_buf; unsigned i; PJ_UNUSED_ARG(timestamp); @@ -931,29 +1197,17 @@ static pj_status_t rec_cb( /* in */ void *user_data, /* Determine which rx_buffer to fill in */ - target_rx_buf = snd_port->rx_buf[snd_port->rx_write]; + target_snd_buf = snd_port->snd_buf[snd_port->snd_write_pos]; /* Copy samples from audio device to target rx_buffer */ for (i=0; i<conf->samples_per_frame; ++i) { - target_rx_buf[i] = ((pj_int16_t*)input)[i]; + target_snd_buf[i] = ((pj_int16_t*)input)[i]; } /* Switch buffer */ - snd_port->rx_write = (snd_port->rx_write+1)%RX_BUF_COUNT; - - - /* Time for all ports (except sound port) to transmit frames */ - /* - for (i=1; i<conf->max_ports; ++i) { - struct conf_port *conf_port = conf->ports[i]; - pjmedia_frame frame; + snd_port->snd_write_pos = (snd_port->snd_write_pos+1)%RX_BUF_COUNT; - if (!conf_port) - continue; - } - */ - return PJ_SUCCESS; } diff --git a/pjmedia/src/pjmedia/file_port.c b/pjmedia/src/pjmedia/file_port.c index cb8059d3..66022e76 100644 --- a/pjmedia/src/pjmedia/file_port.c +++ b/pjmedia/src/pjmedia/file_port.c @@ -27,7 +27,6 @@ #define SIGNATURE ('F'<<24|'I'<<16|'L'<<8|'E') -#define BUF_SIZE (320*10) struct file_port { @@ -59,15 +58,20 @@ static struct file_port *create_file_port(pj_pool_t *pool) port->base.info.need_info = PJ_FALSE; port->base.info.pt = 0xFF; port->base.info.encoding_name = pj_str("pcm"); - port->base.info.sample_rate = 8000; - port->base.info.bits_per_sample = 16; - port->base.info.samples_per_frame = 160; - port->base.info.bytes_per_frame = 320; port->base.put_frame = &file_put_frame; port->base.get_frame = &file_get_frame; port->base.on_destroy = &file_on_destroy; + + /* Put in default values. + * These will be overriden once the file is read. + */ + port->base.info.sample_rate = 8000; + port->base.info.bits_per_sample = 16; + port->base.info.samples_per_frame = 160; + port->base.info.bytes_per_frame = 320; + return port; } @@ -136,10 +140,8 @@ PJ_DEF(pj_status_t) pjmedia_file_player_port_create( pj_pool_t *pool, if (wave_hdr.fmt_hdr.fmt_tag != 1 || wave_hdr.fmt_hdr.nchan != 1 || - wave_hdr.fmt_hdr.sample_rate != 8000 || - wave_hdr.fmt_hdr.bytes_per_sec != 16000 || - wave_hdr.fmt_hdr.block_align != 2 || - wave_hdr.fmt_hdr.bits_per_sample != 16) + wave_hdr.fmt_hdr.bits_per_sample != 16 || + wave_hdr.fmt_hdr.block_align != 2) { pj_file_close(fd); return PJMEDIA_EWAVEUNSUPP; @@ -167,6 +169,16 @@ PJ_DEF(pj_status_t) pjmedia_file_player_port_create( pj_pool_t *pool, /* Initialize */ file_port->base.user_data = user_data; + /* Update port info. */ + file_port->base.info.sample_rate = wave_hdr.fmt_hdr.sample_rate; + file_port->base.info.bits_per_sample = wave_hdr.fmt_hdr.bits_per_sample; + file_port->base.info.samples_per_frame = file_port->base.info.sample_rate * + 20 / 1000; + file_port->base.info.bytes_per_frame = + file_port->base.info.samples_per_frame * + file_port->base.info.bits_per_sample / 8; + + /* For this version, we only support reading the whole * contents of the file. */ @@ -222,17 +234,19 @@ static pj_status_t file_get_frame(pjmedia_port *this_port, pjmedia_frame *frame) { struct file_port *port = (struct file_port*)this_port; - + unsigned frame_size; pj_assert(port->base.info.signature == SIGNATURE); + frame_size = port->base.info.bytes_per_frame; + /* Copy frame from buffer. */ frame->type = PJMEDIA_FRAME_TYPE_AUDIO; - frame->size = 320; + frame->size = frame_size; frame->timestamp.u64 = 0; - if (port->readpos + 320 <= port->buf + port->bufsize) { - pj_memcpy(frame->buf, port->readpos, 320); - port->readpos += 320; + if (port->readpos + frame_size <= port->buf + port->bufsize) { + pj_memcpy(frame->buf, port->readpos, frame_size); + port->readpos += frame_size; if (port->readpos == port->buf + port->bufsize) port->readpos = port->buf; } else { @@ -240,15 +254,15 @@ static pj_status_t file_get_frame(pjmedia_port *this_port, endread = (port->buf+port->bufsize) - port->readpos; pj_memcpy(frame->buf, port->readpos, endread); - pj_memcpy(((char*)frame->buf)+endread, port->buf, 320-endread); - port->readpos = port->buf + (320-endread); + pj_memcpy(((char*)frame->buf)+endread, port->buf, frame_size-endread); + port->readpos = port->buf + (frame_size - endread); } return PJ_SUCCESS; } /* - * + * Destroy port. */ static pj_status_t file_on_destroy(pjmedia_port *this_port) { diff --git a/pjmedia/src/pjmedia/largefilter.h b/pjmedia/src/pjmedia/largefilter.h new file mode 100644 index 00000000..16c0c3fc --- /dev/null +++ b/pjmedia/src/pjmedia/largefilter.h @@ -0,0 +1,16391 @@ +/* Included by resamplesubs.c */ +#define LARGE_FILTER_NMULT ((HWORD)65) +#define LARGE_FILTER_SCALE 14746 /* Unity-gain scale factor */ +#define LARGE_FILTER_NWING 8192 /* Filter table length */ +static HWORD LARGE_FILTER_IMP[] /* Impulse response */ = { +32767, +32766, +32764, +32761, +32756, +32750, +32743, +32734, +32724, +32713, +32700, +32686, +32671, +32654, +32636, +32617, +32596, +32574, +32551, +32526, +32500, +32473, +32445, +32415, +32383, +32351, +32317, +32282, +32246, +32208, +32169, +32129, +32087, +32044, +32000, +31955, +31908, +31860, +31811, +31760, +31708, +31655, +31601, +31545, +31489, +31431, +31371, +31311, +31249, +31186, +31122, +31056, +30990, +30922, +30853, +30783, +30711, +30639, +30565, +30490, +30414, +30337, +30258, +30179, +30098, +30016, +29933, +29849, +29764, +29677, +29590, +29501, +29411, +29321, +29229, +29136, +29042, +28947, +28851, +28753, +28655, +28556, +28456, +28354, +28252, +28149, +28044, +27939, +27833, +27725, +27617, +27508, +27398, +27287, +27175, +27062, +26948, +26833, +26717, +26601, +26483, +26365, +26246, +26125, +26005, +25883, +25760, +25637, +25512, +25387, +25261, +25135, +25007, +24879, +24750, +24620, +24490, +24358, +24226, +24094, +23960, +23826, +23691, +23556, +23420, +23283, +23146, +23008, +22869, +22730, +22590, +22449, +22308, +22166, +22024, +21881, +21738, +21594, +21449, +21304, +21159, +21013, +20866, +20719, +20572, +20424, +20275, +20127, +19977, +19828, +19678, +19527, +19376, +19225, +19073, +18921, +18769, +18616, +18463, +18310, +18157, +18003, +17849, +17694, +17539, +17384, +17229, +17074, +16918, +16762, +16606, +16450, +16294, +16137, +15980, +15823, +15666, +15509, +15352, +15195, +15037, +14880, +14722, +14564, +14407, +14249, +14091, +13933, +13775, +13618, +13460, +13302, +13144, +12987, +12829, +12671, +12514, +12356, +12199, +12042, +11885, +11728, +11571, +11414, +11257, +11101, +10945, +10789, +10633, +10477, +10322, +10167, +10012, +9857, +9702, +9548, +9394, +9241, +9087, +8934, +8781, +8629, +8477, +8325, +8174, +8023, +7872, +7722, +7572, +7422, +7273, +7124, +6976, +6828, +6681, +6534, +6387, +6241, +6096, +5951, +5806, +5662, +5518, +5375, +5233, +5091, +4949, +4808, +4668, +4528, +4389, +4250, +4112, +3975, +3838, +3702, +3566, +3431, +3297, +3163, +3030, +2898, +2766, +2635, +2505, +2375, +2246, +2118, +1990, +1864, +1738, +1612, +1487, +1364, +1240, +1118, +996, +875, +755, +636, +517, +400, +283, +166, +51, +-63, +-176, +-289, +-401, +-513, +-623, +-733, +-841, +-949, +-1056, +-1162, +-1268, +-1372, +-1476, +-1578, +-1680, +-1781, +-1881, +-1980, +-2078, +-2176, +-2272, +-2367, +-2462, +-2556, +-2648, +-2740, +-2831, +-2921, +-3010, +-3098, +-3185, +-3271, +-3356, +-3441, +-3524, +-3606, +-3688, +-3768, +-3848, +-3926, +-4004, +-4080, +-4156, +-4231, +-4304, +-4377, +-4449, +-4519, +-4589, +-4658, +-4726, +-4792, +-4858, +-4923, +-4987, +-5050, +-5111, +-5172, +-5232, +-5291, +-5349, +-5406, +-5462, +-5517, +-5571, +-5624, +-5675, +-5726, +-5776, +-5825, +-5873, +-5920, +-5966, +-6011, +-6055, +-6098, +-6140, +-6181, +-6222, +-6261, +-6299, +-6336, +-6372, +-6407, +-6441, +-6475, +-6507, +-6538, +-6569, +-6598, +-6626, +-6654, +-6680, +-6706, +-6730, +-6754, +-6777, +-6798, +-6819, +-6839, +-6858, +-6876, +-6893, +-6909, +-6924, +-6938, +-6951, +-6964, +-6975, +-6986, +-6995, +-7004, +-7012, +-7019, +-7025, +-7030, +-7035, +-7038, +-7040, +-7042, +-7043, +-7043, +-7042, +-7040, +-7038, +-7034, +-7030, +-7025, +-7019, +-7012, +-7004, +-6996, +-6986, +-6976, +-6965, +-6954, +-6941, +-6928, +-6914, +-6899, +-6884, +-6867, +-6850, +-6832, +-6814, +-6794, +-6774, +-6753, +-6732, +-6709, +-6686, +-6663, +-6638, +-6613, +-6587, +-6561, +-6534, +-6506, +-6478, +-6448, +-6419, +-6388, +-6357, +-6325, +-6293, +-6260, +-6226, +-6192, +-6157, +-6122, +-6086, +-6049, +-6012, +-5975, +-5936, +-5897, +-5858, +-5818, +-5778, +-5737, +-5695, +-5653, +-5611, +-5568, +-5524, +-5480, +-5436, +-5391, +-5345, +-5300, +-5253, +-5207, +-5159, +-5112, +-5064, +-5015, +-4966, +-4917, +-4868, +-4818, +-4767, +-4716, +-4665, +-4614, +-4562, +-4510, +-4457, +-4404, +-4351, +-4298, +-4244, +-4190, +-4136, +-4081, +-4026, +-3971, +-3916, +-3860, +-3804, +-3748, +-3692, +-3635, +-3578, +-3521, +-3464, +-3406, +-3349, +-3291, +-3233, +-3175, +-3117, +-3058, +-3000, +-2941, +-2882, +-2823, +-2764, +-2705, +-2646, +-2587, +-2527, +-2468, +-2408, +-2349, +-2289, +-2229, +-2169, +-2110, +-2050, +-1990, +-1930, +-1870, +-1811, +-1751, +-1691, +-1631, +-1571, +-1512, +-1452, +-1392, +-1333, +-1273, +-1214, +-1154, +-1095, +-1036, +-977, +-918, +-859, +-800, +-741, +-683, +-624, +-566, +-508, +-450, +-392, +-335, +-277, +-220, +-163, +-106, +-49, +6, +63, +119, +175, +230, +286, +341, +396, +450, +505, +559, +613, +667, +720, +773, +826, +878, +931, +983, +1034, +1086, +1137, +1187, +1238, +1288, +1337, +1387, +1436, +1484, +1533, +1581, +1628, +1675, +1722, +1769, +1815, +1861, +1906, +1951, +1996, +2040, +2084, +2127, +2170, +2212, +2255, +2296, +2338, +2378, +2419, +2459, +2498, +2538, +2576, +2615, +2652, +2690, +2727, +2763, +2799, +2834, +2870, +2904, +2938, +2972, +3005, +3038, +3070, +3102, +3133, +3164, +3194, +3224, +3253, +3282, +3310, +3338, +3365, +3392, +3418, +3444, +3469, +3494, +3518, +3542, +3566, +3588, +3611, +3632, +3653, +3674, +3694, +3714, +3733, +3752, +3770, +3788, +3805, +3821, +3837, +3853, +3868, +3882, +3896, +3910, +3923, +3935, +3947, +3958, +3969, +3980, +3989, +3999, +4007, +4016, +4023, +4031, +4037, +4044, +4049, +4054, +4059, +4063, +4067, +4070, +4073, +4075, +4076, +4077, +4078, +4078, +4078, +4077, +4076, +4074, +4071, +4068, +4065, +4061, +4057, +4052, +4047, +4041, +4035, +4028, +4021, +4013, +4005, +3997, +3988, +3978, +3968, +3958, +3947, +3936, +3924, +3912, +3899, +3886, +3872, +3858, +3844, +3829, +3814, +3798, +3782, +3766, +3749, +3731, +3714, +3696, +3677, +3658, +3639, +3619, +3599, +3578, +3558, +3536, +3515, +3493, +3470, +3448, +3425, +3401, +3378, +3353, +3329, +3304, +3279, +3254, +3228, +3202, +3175, +3149, +3122, +3094, +3067, +3039, +3011, +2982, +2953, +2924, +2895, +2865, +2835, +2805, +2775, +2744, +2713, +2682, +2651, +2619, +2587, +2555, +2523, +2490, +2457, +2424, +2391, +2358, +2324, +2290, +2256, +2222, +2188, +2153, +2119, +2084, +2049, +2014, +1978, +1943, +1907, +1872, +1836, +1800, +1764, +1727, +1691, +1655, +1618, +1581, +1545, +1508, +1471, +1434, +1397, +1360, +1322, +1285, +1248, +1210, +1173, +1135, +1098, +1060, +1023, +985, +947, +910, +872, +834, +797, +759, +721, +684, +646, +608, +571, +533, +496, +458, +421, +383, +346, +308, +271, +234, +197, +160, +123, +86, +49, +12, +-23, +-60, +-96, +-133, +-169, +-205, +-241, +-277, +-313, +-348, +-384, +-419, +-455, +-490, +-525, +-559, +-594, +-628, +-663, +-697, +-731, +-765, +-798, +-832, +-865, +-898, +-931, +-963, +-996, +-1028, +-1060, +-1092, +-1124, +-1155, +-1186, +-1217, +-1248, +-1279, +-1309, +-1339, +-1369, +-1398, +-1428, +-1457, +-1486, +-1514, +-1542, +-1571, +-1598, +-1626, +-1653, +-1680, +-1707, +-1733, +-1760, +-1785, +-1811, +-1836, +-1862, +-1886, +-1911, +-1935, +-1959, +-1982, +-2006, +-2029, +-2051, +-2074, +-2096, +-2118, +-2139, +-2160, +-2181, +-2202, +-2222, +-2242, +-2261, +-2280, +-2299, +-2318, +-2336, +-2354, +-2372, +-2389, +-2406, +-2423, +-2439, +-2455, +-2470, +-2486, +-2500, +-2515, +-2529, +-2543, +-2557, +-2570, +-2583, +-2595, +-2607, +-2619, +-2631, +-2642, +-2652, +-2663, +-2673, +-2683, +-2692, +-2701, +-2710, +-2718, +-2726, +-2734, +-2741, +-2748, +-2754, +-2760, +-2766, +-2772, +-2777, +-2782, +-2786, +-2790, +-2794, +-2797, +-2800, +-2803, +-2805, +-2807, +-2809, +-2810, +-2811, +-2812, +-2812, +-2812, +-2812, +-2811, +-2810, +-2808, +-2807, +-2804, +-2802, +-2799, +-2796, +-2792, +-2789, +-2785, +-2780, +-2775, +-2770, +-2765, +-2759, +-2753, +-2746, +-2740, +-2732, +-2725, +-2717, +-2709, +-2701, +-2692, +-2683, +-2674, +-2664, +-2655, +-2644, +-2634, +-2623, +-2612, +-2601, +-2589, +-2577, +-2565, +-2552, +-2539, +-2526, +-2513, +-2499, +-2485, +-2471, +-2457, +-2442, +-2427, +-2412, +-2396, +-2380, +-2364, +-2348, +-2331, +-2315, +-2297, +-2280, +-2263, +-2245, +-2227, +-2209, +-2190, +-2171, +-2152, +-2133, +-2114, +-2094, +-2075, +-2055, +-2034, +-2014, +-1993, +-1972, +-1951, +-1930, +-1909, +-1887, +-1865, +-1843, +-1821, +-1799, +-1776, +-1754, +-1731, +-1708, +-1685, +-1662, +-1638, +-1614, +-1591, +-1567, +-1543, +-1519, +-1494, +-1470, +-1445, +-1421, +-1396, +-1371, +-1346, +-1321, +-1295, +-1270, +-1244, +-1219, +-1193, +-1167, +-1142, +-1116, +-1090, +-1064, +-1037, +-1011, +-985, +-958, +-932, +-905, +-879, +-852, +-826, +-799, +-772, +-745, +-719, +-692, +-665, +-638, +-611, +-584, +-557, +-530, +-503, +-476, +-449, +-422, +-395, +-368, +-341, +-314, +-287, +-260, +-234, +-207, +-180, +-153, +-126, +-100, +-73, +-46, +-20, +6, +32, +59, +85, +111, +138, +164, +190, +216, +242, +268, +294, +319, +345, +370, +396, +421, +446, +471, +496, +521, +546, +571, +595, +619, +644, +668, +692, +716, +739, +763, +787, +810, +833, +856, +879, +902, +924, +947, +969, +991, +1013, +1035, +1056, +1078, +1099, +1120, +1141, +1162, +1182, +1202, +1223, +1243, +1262, +1282, +1301, +1320, +1339, +1358, +1377, +1395, +1413, +1431, +1449, +1467, +1484, +1501, +1518, +1535, +1551, +1567, +1583, +1599, +1615, +1630, +1645, +1660, +1674, +1689, +1703, +1717, +1731, +1744, +1757, +1770, +1783, +1795, +1808, +1820, +1831, +1843, +1854, +1865, +1876, +1886, +1897, +1907, +1916, +1926, +1935, +1944, +1953, +1961, +1970, +1978, +1985, +1993, +2000, +2007, +2014, +2020, +2026, +2032, +2038, +2043, +2048, +2053, +2058, +2062, +2066, +2070, +2073, +2077, +2080, +2083, +2085, +2087, +2089, +2091, +2093, +2094, +2095, +2095, +2096, +2096, +2096, +2096, +2095, +2094, +2093, +2092, +2090, +2088, +2086, +2084, +2081, +2079, +2075, +2072, +2069, +2065, +2061, +2056, +2052, +2047, +2042, +2037, +2031, +2025, +2019, +2013, +2006, +2000, +1993, +1986, +1978, +1971, +1963, +1955, +1946, +1938, +1929, +1920, +1911, +1901, +1892, +1882, +1872, +1862, +1851, +1841, +1830, +1819, +1807, +1796, +1784, +1772, +1760, +1748, +1735, +1723, +1710, +1697, +1684, +1670, +1657, +1643, +1629, +1615, +1601, +1586, +1572, +1557, +1542, +1527, +1512, +1496, +1481, +1465, +1449, +1433, +1417, +1401, +1384, +1368, +1351, +1334, +1317, +1300, +1283, +1265, +1248, +1230, +1212, +1195, +1177, +1159, +1140, +1122, +1104, +1085, +1067, +1048, +1029, +1010, +991, +972, +953, +934, +915, +895, +876, +856, +837, +817, +797, +777, +758, +738, +718, +698, +678, +658, +637, +617, +597, +577, +556, +536, +516, +495, +475, +454, +434, +414, +393, +373, +352, +332, +311, +291, +270, +250, +229, +208, +188, +168, +147, +127, +106, +86, +65, +45, +25, +5, +-15, +-35, +-55, +-75, +-95, +-115, +-135, +-155, +-175, +-195, +-215, +-234, +-254, +-274, +-293, +-313, +-332, +-351, +-370, +-390, +-409, +-428, +-446, +-465, +-484, +-503, +-521, +-539, +-558, +-576, +-594, +-612, +-630, +-648, +-666, +-683, +-701, +-718, +-735, +-752, +-769, +-786, +-803, +-819, +-836, +-852, +-868, +-885, +-900, +-916, +-932, +-947, +-963, +-978, +-993, +-1008, +-1023, +-1038, +-1052, +-1066, +-1081, +-1095, +-1108, +-1122, +-1136, +-1149, +-1162, +-1175, +-1188, +-1201, +-1214, +-1226, +-1238, +-1250, +-1262, +-1274, +-1285, +-1297, +-1308, +-1319, +-1330, +-1340, +-1351, +-1361, +-1371, +-1381, +-1390, +-1400, +-1409, +-1418, +-1427, +-1436, +-1445, +-1453, +-1461, +-1469, +-1477, +-1485, +-1492, +-1499, +-1506, +-1513, +-1520, +-1526, +-1532, +-1538, +-1544, +-1550, +-1555, +-1560, +-1566, +-1570, +-1575, +-1579, +-1584, +-1588, +-1592, +-1595, +-1599, +-1602, +-1605, +-1608, +-1610, +-1613, +-1615, +-1617, +-1619, +-1620, +-1622, +-1623, +-1624, +-1625, +-1625, +-1626, +-1626, +-1626, +-1626, +-1625, +-1625, +-1624, +-1623, +-1622, +-1621, +-1619, +-1617, +-1615, +-1613, +-1611, +-1608, +-1605, +-1603, +-1599, +-1596, +-1593, +-1589, +-1585, +-1581, +-1577, +-1572, +-1568, +-1563, +-1558, +-1553, +-1547, +-1542, +-1536, +-1530, +-1524, +-1518, +-1511, +-1505, +-1498, +-1491, +-1484, +-1477, +-1469, +-1462, +-1454, +-1446, +-1438, +-1430, +-1421, +-1413, +-1404, +-1395, +-1386, +-1377, +-1367, +-1358, +-1348, +-1338, +-1328, +-1318, +-1308, +-1297, +-1287, +-1276, +-1265, +-1254, +-1243, +-1232, +-1221, +-1209, +-1198, +-1186, +-1174, +-1162, +-1150, +-1138, +-1125, +-1113, +-1100, +-1087, +-1075, +-1062, +-1049, +-1035, +-1022, +-1009, +-995, +-982, +-968, +-954, +-941, +-927, +-913, +-898, +-884, +-870, +-856, +-841, +-827, +-812, +-797, +-783, +-768, +-753, +-738, +-723, +-708, +-692, +-677, +-662, +-647, +-631, +-616, +-600, +-585, +-569, +-554, +-538, +-522, +-506, +-491, +-475, +-459, +-443, +-427, +-411, +-395, +-379, +-363, +-347, +-331, +-315, +-299, +-283, +-267, +-251, +-235, +-218, +-202, +-186, +-170, +-154, +-138, +-122, +-106, +-90, +-74, +-58, +-42, +-26, +-10, +5, +21, +37, +53, +69, +85, +100, +116, +132, +147, +163, +179, +194, +209, +225, +240, +256, +271, +286, +301, +316, +331, +346, +361, +376, +391, +405, +420, +434, +449, +463, +477, +492, +506, +520, +534, +548, +561, +575, +589, +602, +615, +629, +642, +655, +668, +681, +694, +706, +719, +731, +744, +756, +768, +780, +792, +804, +816, +827, +839, +850, +861, +872, +883, +894, +905, +915, +926, +936, +946, +956, +966, +976, +986, +995, +1005, +1014, +1023, +1032, +1041, +1049, +1058, +1066, +1075, +1083, +1091, +1099, +1106, +1114, +1121, +1128, +1135, +1142, +1149, +1156, +1162, +1169, +1175, +1181, +1187, +1192, +1198, +1203, +1208, +1214, +1218, +1223, +1228, +1232, +1237, +1241, +1245, +1249, +1252, +1256, +1259, +1262, +1265, +1268, +1271, +1273, +1276, +1278, +1280, +1282, +1284, +1285, +1287, +1288, +1289, +1290, +1291, +1292, +1292, +1292, +1293, +1293, +1292, +1292, +1292, +1291, +1290, +1289, +1288, +1287, +1285, +1284, +1282, +1280, +1278, +1276, +1274, +1271, +1269, +1266, +1263, +1260, +1257, +1253, +1250, +1246, +1242, +1238, +1234, +1230, +1225, +1221, +1216, +1211, +1206, +1201, +1196, +1190, +1185, +1179, +1173, +1167, +1161, +1155, +1149, +1142, +1136, +1129, +1122, +1115, +1108, +1101, +1094, +1086, +1078, +1071, +1063, +1055, +1047, +1039, +1030, +1022, +1013, +1005, +996, +987, +978, +969, +960, +951, +941, +932, +922, +913, +903, +893, +883, +873, +863, +853, +842, +832, +821, +811, +800, +789, +778, +768, +757, +746, +734, +723, +712, +701, +689, +678, +666, +654, +643, +631, +619, +607, +596, +584, +572, +559, +547, +535, +523, +511, +498, +486, +474, +461, +449, +436, +424, +411, +399, +386, +373, +361, +348, +335, +322, +310, +297, +284, +271, +258, +246, +233, +220, +207, +194, +181, +168, +156, +143, +130, +117, +104, +91, +78, +65, +53, +40, +27, +14, +1, +-10, +-23, +-36, +-48, +-61, +-74, +-86, +-99, +-111, +-124, +-136, +-149, +-161, +-174, +-186, +-198, +-211, +-223, +-235, +-247, +-259, +-271, +-283, +-295, +-307, +-319, +-330, +-342, +-354, +-365, +-377, +-388, +-399, +-411, +-422, +-433, +-444, +-455, +-466, +-477, +-488, +-499, +-509, +-520, +-530, +-541, +-551, +-561, +-571, +-581, +-591, +-601, +-611, +-621, +-631, +-640, +-650, +-659, +-668, +-677, +-686, +-695, +-704, +-713, +-722, +-730, +-739, +-747, +-755, +-763, +-771, +-779, +-787, +-795, +-803, +-810, +-817, +-825, +-832, +-839, +-846, +-853, +-859, +-866, +-873, +-879, +-885, +-891, +-897, +-903, +-909, +-915, +-920, +-926, +-931, +-936, +-941, +-946, +-951, +-955, +-960, +-964, +-969, +-973, +-977, +-981, +-985, +-988, +-992, +-995, +-999, +-1002, +-1005, +-1008, +-1011, +-1013, +-1016, +-1018, +-1020, +-1023, +-1025, +-1026, +-1028, +-1030, +-1031, +-1033, +-1034, +-1035, +-1036, +-1037, +-1038, +-1038, +-1039, +-1039, +-1039, +-1039, +-1039, +-1039, +-1039, +-1038, +-1038, +-1037, +-1036, +-1036, +-1034, +-1033, +-1032, +-1031, +-1029, +-1027, +-1026, +-1024, +-1022, +-1019, +-1017, +-1015, +-1012, +-1010, +-1007, +-1004, +-1001, +-998, +-995, +-991, +-988, +-984, +-980, +-977, +-973, +-969, +-965, +-960, +-956, +-951, +-947, +-942, +-937, +-932, +-927, +-922, +-917, +-912, +-906, +-901, +-895, +-889, +-883, +-877, +-871, +-865, +-859, +-853, +-846, +-840, +-833, +-826, +-819, +-812, +-805, +-798, +-791, +-784, +-777, +-769, +-762, +-754, +-746, +-739, +-731, +-723, +-715, +-707, +-699, +-691, +-682, +-674, +-665, +-657, +-648, +-640, +-631, +-622, +-614, +-605, +-596, +-587, +-578, +-569, +-559, +-550, +-541, +-532, +-522, +-513, +-503, +-494, +-484, +-474, +-465, +-455, +-445, +-436, +-426, +-416, +-406, +-396, +-386, +-376, +-366, +-356, +-346, +-336, +-325, +-315, +-305, +-295, +-285, +-274, +-264, +-254, +-243, +-233, +-223, +-212, +-202, +-192, +-181, +-171, +-161, +-150, +-140, +-129, +-119, +-108, +-98, +-88, +-77, +-67, +-57, +-46, +-36, +-25, +-15, +-5, +5, +15, +25, +35, +46, +56, +66, +76, +86, +97, +107, +117, +127, +137, +147, +157, +167, +177, +186, +196, +206, +216, +225, +235, +245, +254, +264, +273, +283, +292, +301, +311, +320, +329, +338, +347, +356, +365, +374, +383, +392, +400, +409, +418, +426, +435, +443, +451, +460, +468, +476, +484, +492, +500, +508, +515, +523, +531, +538, +546, +553, +560, +568, +575, +582, +589, +596, +602, +609, +616, +622, +629, +635, +642, +648, +654, +660, +666, +672, +678, +683, +689, +694, +700, +705, +710, +715, +720, +725, +730, +735, +739, +744, +748, +753, +757, +761, +765, +769, +773, +777, +780, +784, +787, +791, +794, +797, +800, +803, +806, +809, +811, +814, +816, +818, +821, +823, +825, +827, +828, +830, +832, +833, +835, +836, +837, +838, +839, +840, +841, +841, +842, +842, +843, +843, +843, +843, +843, +843, +843, +842, +842, +841, +840, +840, +839, +838, +837, +835, +834, +833, +831, +830, +828, +826, +824, +822, +820, +818, +816, +813, +811, +808, +806, +803, +800, +797, +794, +791, +788, +784, +781, +777, +774, +770, +766, +763, +759, +755, +750, +746, +742, +738, +733, +729, +724, +719, +714, +710, +705, +700, +694, +689, +684, +679, +673, +668, +662, +657, +651, +645, +639, +633, +627, +621, +615, +609, +603, +596, +590, +584, +577, +571, +564, +557, +551, +544, +537, +530, +523, +516, +509, +502, +495, +487, +480, +473, +465, +458, +450, +443, +435, +428, +420, +413, +405, +397, +389, +381, +374, +366, +358, +350, +342, +334, +326, +318, +310, +301, +293, +285, +277, +269, +260, +252, +244, +236, +227, +219, +211, +202, +194, +185, +177, +169, +160, +152, +143, +135, +126, +118, +110, +101, +93, +84, +76, +67, +59, +50, +42, +34, +25, +17, +8, +0, +-7, +-16, +-24, +-32, +-41, +-49, +-57, +-66, +-74, +-82, +-90, +-98, +-106, +-115, +-123, +-131, +-139, +-147, +-155, +-163, +-171, +-179, +-186, +-194, +-202, +-210, +-217, +-225, +-233, +-240, +-248, +-255, +-263, +-270, +-278, +-285, +-292, +-299, +-307, +-314, +-321, +-328, +-335, +-342, +-349, +-356, +-362, +-369, +-376, +-382, +-389, +-396, +-402, +-408, +-415, +-421, +-427, +-433, +-439, +-445, +-451, +-457, +-463, +-469, +-475, +-480, +-486, +-491, +-497, +-502, +-507, +-513, +-518, +-523, +-528, +-533, +-538, +-542, +-547, +-552, +-556, +-561, +-565, +-570, +-574, +-578, +-582, +-586, +-590, +-594, +-598, +-602, +-605, +-609, +-612, +-616, +-619, +-622, +-625, +-629, +-632, +-634, +-637, +-640, +-643, +-645, +-648, +-650, +-653, +-655, +-657, +-659, +-661, +-663, +-665, +-667, +-668, +-670, +-671, +-673, +-674, +-675, +-676, +-678, +-679, +-679, +-680, +-681, +-682, +-682, +-683, +-683, +-683, +-684, +-684, +-684, +-684, +-684, +-684, +-683, +-683, +-682, +-682, +-681, +-681, +-680, +-679, +-678, +-677, +-676, +-675, +-674, +-672, +-671, +-669, +-668, +-666, +-664, +-662, +-661, +-659, +-657, +-654, +-652, +-650, +-648, +-645, +-643, +-640, +-637, +-635, +-632, +-629, +-626, +-623, +-620, +-617, +-613, +-610, +-607, +-603, +-600, +-596, +-593, +-589, +-585, +-581, +-577, +-573, +-569, +-565, +-561, +-557, +-552, +-548, +-544, +-539, +-534, +-530, +-525, +-520, +-516, +-511, +-506, +-501, +-496, +-491, +-486, +-481, +-475, +-470, +-465, +-460, +-454, +-449, +-443, +-438, +-432, +-426, +-421, +-415, +-409, +-403, +-398, +-392, +-386, +-380, +-374, +-368, +-362, +-355, +-349, +-343, +-337, +-331, +-324, +-318, +-312, +-305, +-299, +-292, +-286, +-280, +-273, +-266, +-260, +-253, +-247, +-240, +-234, +-227, +-220, +-213, +-207, +-200, +-193, +-187, +-180, +-173, +-166, +-159, +-153, +-146, +-139, +-132, +-125, +-118, +-112, +-105, +-98, +-91, +-84, +-77, +-70, +-64, +-57, +-50, +-43, +-36, +-29, +-22, +-16, +-9, +-2, +4, +11, +17, +24, +31, +38, +44, +51, +58, +64, +71, +78, +84, +91, +98, +104, +111, +117, +124, +130, +137, +143, +149, +156, +162, +168, +175, +181, +187, +193, +199, +205, +212, +218, +224, +230, +236, +241, +247, +253, +259, +265, +270, +276, +282, +287, +293, +298, +304, +309, +314, +320, +325, +330, +335, +340, +345, +350, +355, +360, +365, +370, +375, +380, +384, +389, +393, +398, +402, +407, +411, +415, +419, +424, +428, +432, +436, +440, +443, +447, +451, +455, +458, +462, +465, +469, +472, +475, +479, +482, +485, +488, +491, +494, +497, +499, +502, +505, +507, +510, +512, +515, +517, +519, +522, +524, +526, +528, +530, +532, +533, +535, +537, +538, +540, +541, +543, +544, +545, +546, +548, +549, +550, +550, +551, +552, +553, +553, +554, +554, +555, +555, +555, +556, +556, +556, +556, +556, +556, +555, +555, +555, +554, +554, +553, +553, +552, +551, +551, +550, +549, +548, +547, +546, +545, +543, +542, +541, +539, +538, +536, +534, +533, +531, +529, +527, +525, +523, +521, +519, +517, +514, +512, +510, +507, +505, +502, +500, +497, +494, +492, +489, +486, +483, +480, +477, +474, +471, +467, +464, +461, +457, +454, +450, +447, +443, +440, +436, +432, +429, +425, +421, +417, +413, +409, +405, +401, +397, +393, +388, +384, +380, +375, +371, +367, +362, +358, +353, +349, +344, +339, +335, +330, +325, +321, +316, +311, +306, +301, +296, +291, +286, +281, +276, +271, +266, +261, +256, +251, +245, +240, +235, +230, +225, +219, +214, +209, +203, +198, +193, +187, +182, +176, +171, +165, +160, +154, +149, +144, +138, +132, +127, +121, +116, +110, +105, +99, +94, +88, +83, +77, +71, +66, +60, +55, +49, +44, +38, +33, +27, +21, +16, +10, +5, +0, +-5, +-11, +-16, +-22, +-27, +-33, +-38, +-43, +-49, +-54, +-60, +-65, +-70, +-76, +-81, +-86, +-92, +-97, +-102, +-107, +-113, +-118, +-123, +-128, +-133, +-138, +-143, +-148, +-153, +-158, +-163, +-168, +-173, +-178, +-183, +-188, +-192, +-197, +-202, +-207, +-211, +-216, +-221, +-225, +-230, +-234, +-239, +-243, +-247, +-252, +-256, +-260, +-265, +-269, +-273, +-277, +-281, +-285, +-289, +-293, +-297, +-301, +-305, +-308, +-312, +-316, +-319, +-323, +-327, +-330, +-334, +-337, +-340, +-344, +-347, +-350, +-353, +-357, +-360, +-363, +-366, +-369, +-372, +-374, +-377, +-380, +-383, +-385, +-388, +-390, +-393, +-395, +-398, +-400, +-402, +-405, +-407, +-409, +-411, +-413, +-415, +-417, +-419, +-420, +-422, +-424, +-425, +-427, +-429, +-430, +-431, +-433, +-434, +-435, +-436, +-438, +-439, +-440, +-441, +-442, +-442, +-443, +-444, +-445, +-445, +-446, +-446, +-447, +-447, +-448, +-448, +-448, +-448, +-449, +-449, +-449, +-449, +-449, +-448, +-448, +-448, +-448, +-447, +-447, +-446, +-446, +-445, +-445, +-444, +-443, +-442, +-442, +-441, +-440, +-439, +-438, +-437, +-435, +-434, +-433, +-432, +-430, +-429, +-427, +-426, +-424, +-423, +-421, +-419, +-418, +-416, +-414, +-412, +-410, +-408, +-406, +-404, +-402, +-400, +-397, +-395, +-393, +-390, +-388, +-385, +-383, +-380, +-378, +-375, +-373, +-370, +-367, +-364, +-361, +-359, +-356, +-353, +-350, +-347, +-344, +-340, +-337, +-334, +-331, +-328, +-324, +-321, +-318, +-314, +-311, +-307, +-304, +-300, +-297, +-293, +-290, +-286, +-282, +-279, +-275, +-271, +-267, +-263, +-260, +-256, +-252, +-248, +-244, +-240, +-236, +-232, +-228, +-224, +-220, +-216, +-212, +-207, +-203, +-199, +-195, +-191, +-186, +-182, +-178, +-174, +-169, +-165, +-161, +-156, +-152, +-148, +-143, +-139, +-134, +-130, +-126, +-121, +-117, +-112, +-108, +-103, +-99, +-95, +-90, +-86, +-81, +-77, +-72, +-68, +-63, +-59, +-54, +-50, +-45, +-41, +-36, +-32, +-27, +-23, +-18, +-14, +-9, +-5, +0, +3, +7, +12, +16, +21, +25, +29, +34, +38, +43, +47, +51, +56, +60, +64, +69, +73, +77, +81, +85, +90, +94, +98, +102, +106, +110, +115, +119, +123, +127, +131, +135, +139, +143, +146, +150, +154, +158, +162, +166, +169, +173, +177, +181, +184, +188, +192, +195, +199, +202, +206, +209, +212, +216, +219, +223, +226, +229, +232, +236, +239, +242, +245, +248, +251, +254, +257, +260, +263, +266, +268, +271, +274, +277, +279, +282, +284, +287, +289, +292, +294, +297, +299, +301, +304, +306, +308, +310, +312, +314, +316, +318, +320, +322, +324, +326, +328, +329, +331, +333, +334, +336, +337, +339, +340, +341, +343, +344, +345, +346, +348, +349, +350, +351, +352, +353, +354, +354, +355, +356, +357, +357, +358, +358, +359, +359, +360, +360, +361, +361, +361, +361, +362, +362, +362, +362, +362, +362, +362, +361, +361, +361, +361, +360, +360, +360, +359, +359, +358, +358, +357, +356, +356, +355, +354, +353, +352, +351, +350, +349, +348, +347, +346, +345, +344, +343, +341, +340, +339, +337, +336, +334, +333, +331, +330, +328, +326, +324, +323, +321, +319, +317, +315, +313, +311, +309, +307, +305, +303, +301, +299, +297, +294, +292, +290, +288, +285, +283, +280, +278, +275, +273, +270, +268, +265, +263, +260, +257, +254, +252, +249, +246, +243, +240, +238, +235, +232, +229, +226, +223, +220, +217, +214, +211, +208, +204, +201, +198, +195, +192, +188, +185, +182, +179, +175, +172, +169, +165, +162, +159, +155, +152, +149, +145, +142, +138, +135, +131, +128, +124, +121, +117, +114, +110, +107, +103, +100, +96, +93, +89, +85, +82, +78, +75, +71, +67, +64, +60, +57, +53, +49, +46, +42, +39, +35, +31, +28, +24, +21, +17, +14, +10, +6, +3, +0, +-3, +-7, +-10, +-14, +-18, +-21, +-25, +-28, +-32, +-35, +-39, +-42, +-45, +-49, +-52, +-56, +-59, +-63, +-66, +-69, +-73, +-76, +-79, +-83, +-86, +-89, +-93, +-96, +-99, +-102, +-105, +-109, +-112, +-115, +-118, +-121, +-124, +-127, +-130, +-133, +-136, +-139, +-142, +-145, +-148, +-151, +-154, +-157, +-160, +-162, +-165, +-168, +-171, +-173, +-176, +-179, +-181, +-184, +-186, +-189, +-191, +-194, +-196, +-199, +-201, +-204, +-206, +-208, +-211, +-213, +-215, +-217, +-219, +-221, +-224, +-226, +-228, +-230, +-232, +-234, +-236, +-237, +-239, +-241, +-243, +-245, +-246, +-248, +-250, +-251, +-253, +-254, +-256, +-257, +-259, +-260, +-262, +-263, +-264, +-266, +-267, +-268, +-269, +-270, +-271, +-273, +-274, +-275, +-275, +-276, +-277, +-278, +-279, +-280, +-281, +-281, +-282, +-283, +-283, +-284, +-284, +-285, +-285, +-286, +-286, +-286, +-287, +-287, +-287, +-287, +-288, +-288, +-288, +-288, +-288, +-288, +-288, +-288, +-288, +-288, +-287, +-287, +-287, +-287, +-286, +-286, +-286, +-285, +-285, +-284, +-284, +-283, +-283, +-282, +-281, +-281, +-280, +-279, +-278, +-277, +-277, +-276, +-275, +-274, +-273, +-272, +-271, +-270, +-269, +-267, +-266, +-265, +-264, +-262, +-261, +-260, +-258, +-257, +-256, +-254, +-253, +-251, +-250, +-248, +-247, +-245, +-243, +-242, +-240, +-238, +-236, +-235, +-233, +-231, +-229, +-227, +-225, +-223, +-221, +-219, +-217, +-215, +-213, +-211, +-209, +-207, +-205, +-203, +-201, +-198, +-196, +-194, +-192, +-189, +-187, +-185, +-182, +-180, +-178, +-175, +-173, +-170, +-168, +-165, +-163, +-160, +-158, +-155, +-153, +-150, +-148, +-145, +-142, +-140, +-137, +-135, +-132, +-129, +-127, +-124, +-121, +-118, +-116, +-113, +-110, +-108, +-105, +-102, +-99, +-96, +-94, +-91, +-88, +-85, +-82, +-80, +-77, +-74, +-71, +-68, +-65, +-63, +-60, +-57, +-54, +-51, +-48, +-45, +-42, +-40, +-37, +-34, +-31, +-28, +-25, +-22, +-20, +-17, +-14, +-11, +-8, +-5, +-2, +0, +2, +5, +8, +11, +13, +16, +19, +22, +25, +27, +30, +33, +36, +38, +41, +44, +47, +49, +52, +55, +57, +60, +63, +65, +68, +71, +73, +76, +78, +81, +83, +86, +88, +91, +93, +96, +98, +101, +103, +106, +108, +110, +113, +115, +117, +120, +122, +124, +127, +129, +131, +133, +135, +137, +140, +142, +144, +146, +148, +150, +152, +154, +156, +158, +160, +161, +163, +165, +167, +169, +171, +172, +174, +176, +177, +179, +181, +182, +184, +185, +187, +188, +190, +191, +193, +194, +195, +197, +198, +199, +201, +202, +203, +204, +205, +207, +208, +209, +210, +211, +212, +213, +214, +215, +216, +216, +217, +218, +219, +219, +220, +221, +222, +222, +223, +223, +224, +224, +225, +225, +226, +226, +227, +227, +227, +227, +228, +228, +228, +228, +228, +229, +229, +229, +229, +229, +229, +229, +229, +228, +228, +228, +228, +228, +228, +227, +227, +227, +226, +226, +225, +225, +225, +224, +224, +223, +222, +222, +221, +221, +220, +219, +218, +218, +217, +216, +215, +214, +214, +213, +212, +211, +210, +209, +208, +207, +206, +205, +203, +202, +201, +200, +199, +197, +196, +195, +194, +192, +191, +190, +188, +187, +185, +184, +182, +181, +179, +178, +176, +175, +173, +172, +170, +168, +167, +165, +163, +162, +160, +158, +156, +155, +153, +151, +149, +147, +146, +144, +142, +140, +138, +136, +134, +132, +130, +128, +126, +124, +122, +120, +118, +116, +114, +112, +110, +108, +106, +104, +102, +99, +97, +95, +93, +91, +89, +87, +84, +82, +80, +78, +76, +73, +71, +69, +67, +64, +62, +60, +58, +56, +53, +51, +49, +47, +44, +42, +40, +38, +35, +33, +31, +28, +26, +24, +22, +19, +17, +15, +13, +10, +8, +6, +4, +1, +0, +-2, +-4, +-6, +-9, +-11, +-13, +-15, +-17, +-20, +-22, +-24, +-26, +-28, +-30, +-33, +-35, +-37, +-39, +-41, +-43, +-45, +-47, +-49, +-52, +-54, +-56, +-58, +-60, +-62, +-64, +-66, +-68, +-70, +-72, +-74, +-76, +-77, +-79, +-81, +-83, +-85, +-87, +-89, +-90, +-92, +-94, +-96, +-98, +-99, +-101, +-103, +-105, +-106, +-108, +-110, +-111, +-113, +-114, +-116, +-118, +-119, +-121, +-122, +-124, +-125, +-127, +-128, +-130, +-131, +-132, +-134, +-135, +-136, +-138, +-139, +-140, +-142, +-143, +-144, +-145, +-146, +-148, +-149, +-150, +-151, +-152, +-153, +-154, +-155, +-156, +-157, +-158, +-159, +-160, +-161, +-162, +-162, +-163, +-164, +-165, +-166, +-166, +-167, +-168, +-168, +-169, +-170, +-170, +-171, +-171, +-172, +-172, +-173, +-173, +-174, +-174, +-175, +-175, +-175, +-176, +-176, +-176, +-177, +-177, +-177, +-177, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-178, +-177, +-177, +-177, +-177, +-177, +-176, +-176, +-176, +-175, +-175, +-175, +-174, +-174, +-173, +-173, +-172, +-172, +-171, +-171, +-170, +-170, +-169, +-168, +-168, +-167, +-166, +-166, +-165, +-164, +-163, +-163, +-162, +-161, +-160, +-159, +-158, +-158, +-157, +-156, +-155, +-154, +-153, +-152, +-151, +-150, +-149, +-148, +-147, +-145, +-144, +-143, +-142, +-141, +-140, +-139, +-137, +-136, +-135, +-134, +-132, +-131, +-130, +-128, +-127, +-126, +-124, +-123, +-122, +-120, +-119, +-118, +-116, +-115, +-113, +-112, +-110, +-109, +-107, +-106, +-104, +-103, +-101, +-100, +-98, +-97, +-95, +-94, +-92, +-90, +-89, +-87, +-86, +-84, +-82, +-81, +-79, +-77, +-76, +-74, +-72, +-71, +-69, +-67, +-66, +-64, +-62, +-60, +-59, +-57, +-55, +-54, +-52, +-50, +-48, +-47, +-45, +-43, +-41, +-40, +-38, +-36, +-34, +-33, +-31, +-29, +-27, +-25, +-24, +-22, +-20, +-18, +-17, +-15, +-13, +-11, +-10, +-8, +-6, +-4, +-3, +-1, +0, +2, +3, +5, +7, +8, +10, +12, +14, +15, +17, +19, +20, +22, +24, +25, +27, +29, +30, +32, +34, +35, +37, +39, +40, +42, +43, +45, +47, +48, +50, +51, +53, +54, +56, +57, +59, +60, +62, +63, +65, +66, +68, +69, +70, +72, +73, +75, +76, +77, +79, +80, +81, +83, +84, +85, +87, +88, +89, +90, +92, +93, +94, +95, +96, +97, +99, +100, +101, +102, +103, +104, +105, +106, +107, +108, +109, +110, +111, +112, +113, +114, +115, +116, +117, +117, +118, +119, +120, +121, +121, +122, +123, +124, +124, +125, +126, +126, +127, +128, +128, +129, +129, +130, +130, +131, +131, +132, +132, +133, +133, +134, +134, +135, +135, +135, +136, +136, +136, +136, +137, +137, +137, +137, +138, +138, +138, +138, +138, +138, +138, +138, +139, +139, +139, +139, +139, +139, +139, +138, +138, +138, +138, +138, +138, +138, +138, +137, +137, +137, +137, +136, +136, +136, +136, +135, +135, +134, +134, +134, +133, +133, +132, +132, +132, +131, +131, +130, +129, +129, +128, +128, +127, +127, +126, +125, +125, +124, +123, +123, +122, +121, +121, +120, +119, +118, +117, +117, +116, +115, +114, +113, +113, +112, +111, +110, +109, +108, +107, +106, +105, +104, +103, +102, +101, +100, +99, +98, +97, +96, +95, +94, +93, +92, +91, +90, +89, +87, +86, +85, +84, +83, +82, +81, +79, +78, +77, +76, +75, +73, +72, +71, +70, +68, +67, +66, +65, +63, +62, +61, +60, +58, +57, +56, +54, +53, +52, +50, +49, +48, +47, +45, +44, +43, +41, +40, +39, +37, +36, +34, +33, +32, +30, +29, +28, +26, +25, +24, +22, +21, +20, +18, +17, +16, +14, +13, +11, +10, +9, +7, +6, +5, +3, +2, +1, +0, +-1, +-2, +-4, +-5, +-6, +-8, +-9, +-10, +-11, +-13, +-14, +-15, +-17, +-18, +-19, +-20, +-22, +-23, +-24, +-26, +-27, +-28, +-29, +-30, +-32, +-33, +-34, +-35, +-37, +-38, +-39, +-40, +-41, +-42, +-44, +-45, +-46, +-47, +-48, +-49, +-50, +-51, +-53, +-54, +-55, +-56, +-57, +-58, +-59, +-60, +-61, +-62, +-63, +-64, +-65, +-66, +-67, +-68, +-69, +-70, +-71, +-71, +-72, +-73, +-74, +-75, +-76, +-77, +-77, +-78, +-79, +-80, +-81, +-81, +-82, +-83, +-84, +-84, +-85, +-86, +-87, +-87, +-88, +-89, +-89, +-90, +-90, +-91, +-92, +-92, +-93, +-93, +-94, +-94, +-95, +-95, +-96, +-96, +-97, +-97, +-98, +-98, +-99, +-99, +-99, +-100, +-100, +-100, +-101, +-101, +-101, +-102, +-102, +-102, +-102, +-103, +-103, +-103, +-103, +-103, +-104, +-104, +-104, +-104, +-104, +-104, +-104, +-105, +-105, +-105, +-105, +-105, +-105, +-105, +-105, +-105, +-105, +-105, +-105, +-104, +-104, +-104, +-104, +-104, +-104, +-104, +-104, +-103, +-103, +-103, +-103, +-103, +-102, +-102, +-102, +-102, +-101, +-101, +-101, +-100, +-100, +-100, +-99, +-99, +-99, +-98, +-98, +-97, +-97, +-97, +-96, +-96, +-95, +-95, +-94, +-94, +-93, +-93, +-92, +-92, +-91, +-90, +-90, +-89, +-89, +-88, +-87, +-87, +-86, +-86, +-85, +-84, +-84, +-83, +-82, +-81, +-81, +-80, +-79, +-79, +-78, +-77, +-76, +-76, +-75, +-74, +-73, +-72, +-72, +-71, +-70, +-69, +-68, +-67, +-67, +-66, +-65, +-64, +-63, +-62, +-61, +-61, +-60, +-59, +-58, +-57, +-56, +-55, +-54, +-53, +-52, +-51, +-50, +-49, +-48, +-48, +-47, +-46, +-45, +-44, +-43, +-42, +-41, +-40, +-39, +-38, +-37, +-36, +-35, +-34, +-33, +-32, +-31, +-30, +-29, +-28, +-27, +-26, +-25, +-24, +-23, +-21, +-20, +-19, +-18, +-17, +-16, +-15, +-14, +-13, +-12, +-11, +-10, +-9, +-8, +-7, +-6, +-5, +-4, +-3, +-2, +-1, +0, +0, +1, +2, +3, +4, +5, +6, +7, +8, +9, +10, +11, +12, +13, +14, +15, +16, +17, +18, +19, +20, +21, +22, +22, +23, +24, +25, +26, +27, +28, +29, +30, +31, +32, +32, +33, +34, +35, +36, +37, +38, +38, +39, +40, +41, +42, +42, +43, +44, +45, +46, +46, +47, +48, +49, +49, +50, +51, +52, +52, +53, +54, +54, +55, +56, +56, +57, +58, +58, +59, +59, +60, +61, +61, +62, +62, +63, +64, +64, +65, +65, +66, +66, +67, +67, +68, +68, +69, +69, +69, +70, +70, +71, +71, +72, +72, +72, +73, +73, +73, +74, +74, +74, +75, +75, +75, +76, +76, +76, +76, +77, +77, +77, +77, +77, +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, +79, +79, +79, +79, +78, +78, +78, +78, +78, +78, +77, +77, +77, +77, +77, +76, +76, +76, +76, +75, +75, +75, +74, +74, +74, +74, +73, +73, +72, +72, +72, +71, +71, +71, +70, +70, +69, +69, +69, +68, +68, +67, +67, +66, +66, +65, +65, +64, +64, +63, +63, +62, +62, +61, +61, +60, +60, +59, +59, +58, +57, +57, +56, +56, +55, +55, +54, +53, +53, +52, +51, +51, +50, +50, +49, +48, +48, +47, +46, +46, +45, +44, +44, +43, +42, +41, +41, +40, +39, +39, +38, +37, +37, +36, +35, +34, +34, +33, +32, +31, +31, +30, +29, +28, +28, +27, +26, +25, +25, +24, +23, +22, +22, +21, +20, +19, +19, +18, +17, +16, +16, +15, +14, +13, +12, +12, +11, +10, +9, +9, +8, +7, +6, +6, +5, +4, +3, +3, +2, +1, +0, +0, +0, +-1, +-2, +-2, +-3, +-4, +-5, +-5, +-6, +-7, +-8, +-8, +-9, +-10, +-10, +-11, +-12, +-13, +-13, +-14, +-15, +-15, +-16, +-17, +-17, +-18, +-19, +-19, +-20, +-21, +-21, +-22, +-23, +-23, +-24, +-25, +-25, +-26, +-27, +-27, +-28, +-28, +-29, +-30, +-30, +-31, +-31, +-32, +-33, +-33, +-34, +-34, +-35, +-35, +-36, +-36, +-37, +-37, +-38, +-38, +-39, +-39, +-40, +-40, +-41, +-41, +-42, +-42, +-43, +-43, +-44, +-44, +-45, +-45, +-45, +-46, +-46, +-47, +-47, +-47, +-48, +-48, +-49, +-49, +-49, +-50, +-50, +-50, +-51, +-51, +-51, +-51, +-52, +-52, +-52, +-53, +-53, +-53, +-53, +-54, +-54, +-54, +-54, +-54, +-55, +-55, +-55, +-55, +-55, +-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, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-57, +-56, +-56, +-56, +-56, +-56, +-56, +-56, +-55, +-55, +-55, +-55, +-55, +-54, +-54, +-54, +-54, +-54, +-53, +-53, +-53, +-53, +-52, +-52, +-52, +-52, +-51, +-51, +-51, +-50, +-50, +-50, +-50, +-49, +-49, +-49, +-48, +-48, +-48, +-47, +-47, +-46, +-46, +-46, +-45, +-45, +-45, +-44, +-44, +-43, +-43, +-43, +-42, +-42, +-41, +-41, +-40, +-40, +-40, +-39, +-39, +-38, +-38, +-37, +-37, +-36, +-36, +-35, +-35, +-35, +-34, +-34, +-33, +-33, +-32, +-32, +-31, +-31, +-30, +-30, +-29, +-29, +-28, +-28, +-27, +-26, +-26, +-25, +-25, +-24, +-24, +-23, +-23, +-22, +-22, +-21, +-21, +-20, +-19, +-19, +-18, +-18, +-17, +-17, +-16, +-16, +-15, +-15, +-14, +-13, +-13, +-12, +-12, +-11, +-11, +-10, +-9, +-9, +-8, +-8, +-7, +-7, +-6, +-6, +-5, +-4, +-4, +-3, +-3, +-2, +-2, +-1, +-1, +0, +0, +0, +1, +1, +2, +2, +3, +3, +4, +4, +5, +5, +6, +7, +7, +8, +8, +9, +9, +10, +10, +11, +11, +12, +12, +13, +13, +14, +14, +15, +15, +16, +16, +17, +17, +18, +18, +18, +19, +19, +20, +20, +21, +21, +22, +22, +22, +23, +23, +24, +24, +25, +25, +25, +26, +26, +27, +27, +27, +28, +28, +28, +29, +29, +30, +30, +30, +31, +31, +31, +32, +32, +32, +33, +33, +33, +33, +34, +34, +34, +35, +35, +35, +35, +36, +36, +36, +36, +37, +37, +37, +37, +38, +38, +38, +38, +38, +39, +39, +39, +39, +39, +40, +40, +40, +40, +40, +40, +40, +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, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +42, +41, +41, +41, +41, +41, +41, +41, +41, +41, +41, +40, +40, +40, +40, +40, +40, +40, +39, +39, +39, +39, +39, +38, +38, +38, +38, +38, +37, +37, +37, +37, +37, +36, +36, +36, +36, +35, +35, +35, +35, +34, +34, +34, +34, +33, +33, +33, +33, +32, +32, +32, +31, +31, +31, +30, +30, +30, +30, +29, +29, +29, +28, +28, +28, +27, +27, +27, +26, +26, +26, +25, +25, +25, +24, +24, +23, +23, +23, +22, +22, +22, +21, +21, +21, +20, +20, +19, +19, +19, +18, +18, +18, +17, +17, +16, +16, +16, +15, +15, +14, +14, +14, +13, +13, +12, +12, +12, +11, +11, +10, +10, +10, +9, +9, +8, +8, +8, +7, +7, +6, +6, +6, +5, +5, +4, +4, +4, +3, +3, +2, +2, +2, +1, +1, +1, +0, +0, +0, +0, +0, +-1, +-1, +-2, +-2, +-2, +-3, +-3, +-3, +-4, +-4, +-5, +-5, +-5, +-6, +-6, +-6, +-7, +-7, +-7, +-8, +-8, +-9, +-9, +-9, +-10, +-10, +-10, +-11, +-11, +-11, +-12, +-12, +-12, +-13, +-13, +-13, +-14, +-14, +-14, +-14, +-15, +-15, +-15, +-16, +-16, +-16, +-17, +-17, +-17, +-17, +-18, +-18, +-18, +-19, +-19, +-19, +-19, +-20, +-20, +-20, +-20, +-21, +-21, +-21, +-21, +-21, +-22, +-22, +-22, +-22, +-23, +-23, +-23, +-23, +-23, +-24, +-24, +-24, +-24, +-24, +-25, +-25, +-25, +-25, +-25, +-25, +-26, +-26, +-26, +-26, +-26, +-26, +-26, +-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, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-29, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-28, +-27, +-27, +-27, +-27, +-27, +-27, +-27, +-27, +-27, +-27, +-26, +-26, +-26, +-26, +-26, +-26, +-26, +-25, +-25, +-25, +-25, +-25, +-25, +-25, +-24, +-24, +-24, +-24, +-24, +-24, +-23, +-23, +-23, +-23, +-23, +-22, +-22, +-22, +-22, +-22, +-21, +-21, +-21, +-21, +-21, +-20, +-20, +-20, +-20, +-20, +-19, +-19, +-19, +-19, +-18, +-18, +-18, +-18, +-17, +-17, +-17, +-17, +-16, +-16, +-16, +-16, +-15, +-15, +-15, +-15, +-14, +-14, +-14, +-14, +-13, +-13, +-13, +-13, +-12, +-12, +-12, +-12, +-11, +-11, +-11, +-11, +-10, +-10, +-10, +-9, +-9, +-9, +-9, +-8, +-8, +-8, +-7, +-7, +-7, +-7, +-6, +-6, +-6, +-6, +-5, +-5, +-5, +-4, +-4, +-4, +-4, +-3, +-3, +-3, +-2, +-2, +-2, +-2, +-1, +-1, +-1, +-1, +0, +0, +0, +0, +0, +0, +0, +1, +1, +1, +1, +2, +2, +2, +2, +3, +3, +3, +3, +4, +4, +4, +5, +5, +5, +5, +6, +6, +6, +6, +6, +7, +7, +7, +7, +8, +8, +8, +8, +9, +9, +9, +9, +10, +10, +10, +10, +10, +11, +11, +11, +11, +11, +12, +12, +12, +12, +12, +13, +13, +13, +13, +13, +14, +14, +14, +14, +14, +14, +15, +15, +15, +15, +15, +15, +16, +16, +16, +16, +16, +16, +16, +17, +17, +17, +17, +17, +17, +17, +17, +18, +18, +18, +18, +18, +18, +18, +18, +18, +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, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +20, +19, +19, +19, +19, +19, +19, +19, +19, +19, +19, +19, +19, +19, +19, +18, +18, +18, +18, +18, +18, +18, +18, +18, +18, +17, +17, +17, +17, +17, +17, +17, +17, +16, +16, +16, +16, +16, +16, +16, +16, +15, +15, +15, +15, +15, +15, +15, +14, +14, +14, +14, +14, +14, +14, +13, +13, +13, +13, +13, +13, +12, +12, +12, +12, +12, +12, +11, +11, +11, +11, +11, +11, +10, +10, +10, +10, +10, +9, +9, +9, +9, +9, +9, +8, +8, +8, +8, +8, +7, +7, +7, +7, +7, +7, +6, +6, +6, +6, +6, +5, +5, +5, +5, +5, +4, +4, +4, +4, +4, +4, +3, +3, +3, +3, +3, +2, +2, +2, +2, +2, +2, +1, +1, +1, +1, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-2, +-2, +-2, +-2, +-2, +-3, +-3, +-3, +-3, +-3, +-3, +-4, +-4, +-4, +-4, +-4, +-4, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-7, +-7, +-7, +-7, +-7, +-7, +-7, +-7, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-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, +-11, +-11, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-7, +-7, +-7, +-7, +-7, +-7, +-7, +-7, +-7, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +3, +3, +3, +3, +3, +3, +3, +3, +3, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +8, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +7, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +6, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0}; + +static HWORD LARGE_FILTER_IMPD[] /* Impulse response differences */ = { +-1, +-2, +-3, +-5, +-6, +-7, +-9, +-10, +-11, +-13, +-14, +-15, +-17, +-18, +-19, +-21, +-22, +-23, +-25, +-26, +-27, +-28, +-30, +-32, +-32, +-34, +-35, +-36, +-38, +-39, +-40, +-42, +-43, +-44, +-45, +-47, +-48, +-49, +-51, +-52, +-53, +-54, +-56, +-56, +-58, +-60, +-60, +-62, +-63, +-64, +-66, +-66, +-68, +-69, +-70, +-72, +-72, +-74, +-75, +-76, +-77, +-79, +-79, +-81, +-82, +-83, +-84, +-85, +-87, +-87, +-89, +-90, +-90, +-92, +-93, +-94, +-95, +-96, +-98, +-98, +-99, +-100, +-102, +-102, +-103, +-105, +-105, +-106, +-108, +-108, +-109, +-110, +-111, +-112, +-113, +-114, +-115, +-116, +-116, +-118, +-118, +-119, +-121, +-120, +-122, +-123, +-123, +-125, +-125, +-126, +-126, +-128, +-128, +-129, +-130, +-130, +-132, +-132, +-132, +-134, +-134, +-135, +-135, +-136, +-137, +-137, +-138, +-139, +-139, +-140, +-141, +-141, +-142, +-142, +-143, +-143, +-144, +-145, +-145, +-145, +-146, +-147, +-147, +-147, +-148, +-149, +-148, +-150, +-149, +-150, +-151, +-151, +-151, +-152, +-152, +-152, +-153, +-153, +-153, +-153, +-154, +-154, +-155, +-155, +-155, +-155, +-155, +-156, +-156, +-156, +-156, +-156, +-157, +-157, +-157, +-157, +-157, +-157, +-157, +-158, +-157, +-158, +-158, +-157, +-158, +-158, +-158, +-158, +-157, +-158, +-158, +-158, +-157, +-158, +-158, +-157, +-158, +-157, +-157, +-157, +-157, +-157, +-157, +-157, +-156, +-156, +-156, +-156, +-156, +-155, +-155, +-155, +-155, +-155, +-154, +-154, +-153, +-154, +-153, +-153, +-152, +-152, +-152, +-151, +-151, +-151, +-150, +-150, +-150, +-149, +-149, +-148, +-148, +-147, +-147, +-147, +-146, +-145, +-145, +-145, +-144, +-144, +-143, +-142, +-142, +-142, +-141, +-140, +-140, +-139, +-139, +-138, +-137, +-137, +-136, +-136, +-135, +-134, +-134, +-133, +-132, +-132, +-131, +-130, +-130, +-129, +-128, +-128, +-126, +-126, +-126, +-125, +-123, +-124, +-122, +-122, +-121, +-120, +-119, +-119, +-117, +-117, +-117, +-115, +-114, +-113, +-113, +-112, +-112, +-110, +-110, +-108, +-108, +-107, +-106, +-106, +-104, +-104, +-102, +-102, +-101, +-100, +-99, +-98, +-98, +-96, +-95, +-95, +-94, +-92, +-92, +-91, +-90, +-89, +-88, +-87, +-86, +-85, +-85, +-83, +-82, +-82, +-80, +-80, +-78, +-78, +-76, +-76, +-75, +-73, +-73, +-72, +-70, +-70, +-69, +-68, +-66, +-66, +-65, +-64, +-63, +-61, +-61, +-60, +-59, +-58, +-57, +-56, +-55, +-54, +-53, +-51, +-51, +-50, +-49, +-48, +-47, +-46, +-45, +-44, +-43, +-42, +-41, +-41, +-39, +-38, +-37, +-36, +-35, +-34, +-34, +-32, +-31, +-31, +-29, +-28, +-28, +-26, +-26, +-24, +-24, +-23, +-21, +-21, +-20, +-19, +-18, +-17, +-16, +-15, +-14, +-13, +-13, +-11, +-11, +-9, +-9, +-8, +-7, +-6, +-5, +-5, +-3, +-2, +-2, +-1, +0, +1, +2, +2, +4, +4, +5, +6, +7, +8, +8, +10, +10, +11, +11, +13, +13, +14, +15, +15, +17, +17, +18, +18, +20, +20, +21, +21, +23, +23, +23, +25, +25, +26, +26, +27, +28, +28, +30, +29, +31, +31, +32, +32, +33, +34, +34, +35, +35, +36, +37, +37, +37, +39, +39, +39, +40, +40, +41, +42, +42, +42, +43, +44, +44, +44, +45, +46, +45, +47, +46, +48, +47, +48, +49, +49, +49, +49, +50, +51, +51, +51, +51, +52, +52, +53, +53, +53, +53, +54, +54, +54, +55, +55, +55, +55, +56, +56, +56, +56, +57, +57, +57, +57, +58, +57, +58, +58, +58, +58, +59, +58, +59, +59, +59, +59, +59, +59, +59, +60, +59, +60, +59, +60, +60, +60, +59, +60, +60, +60, +60, +59, +60, +60, +60, +60, +59, +60, +60, +59, +60, +59, +60, +59, +59, +59, +59, +59, +59, +59, +58, +59, +58, +58, +58, +58, +57, +58, +57, +57, +57, +57, +55, +57, +56, +56, +55, +56, +55, +55, +54, +55, +54, +54, +54, +53, +53, +53, +52, +53, +52, +51, +52, +51, +50, +51, +50, +49, +50, +49, +48, +49, +48, +47, +47, +47, +47, +46, +46, +45, +45, +45, +44, +44, +43, +43, +42, +43, +41, +42, +40, +41, +40, +39, +40, +38, +39, +37, +38, +37, +36, +36, +35, +36, +34, +34, +34, +33, +33, +32, +32, +31, +31, +30, +30, +29, +29, +28, +28, +27, +27, +26, +26, +25, +25, +24, +24, +24, +22, +23, +21, +21, +21, +20, +20, +19, +19, +18, +18, +17, +16, +16, +16, +15, +14, +14, +14, +13, +12, +12, +11, +11, +11, +9, +10, +8, +9, +7, +8, +6, +7, +5, +5, +5, +4, +4, +3, +3, +2, +1, +1, +1, +0, +0, +-1, +-1, +-2, +-3, +-3, +-3, +-4, +-4, +-5, +-5, +-6, +-6, +-7, +-7, +-8, +-8, +-8, +-9, +-10, +-10, +-10, +-11, +-11, +-12, +-12, +-13, +-13, +-14, +-14, +-14, +-15, +-15, +-16, +-16, +-16, +-17, +-18, +-17, +-18, +-19, +-19, +-19, +-20, +-20, +-21, +-20, +-22, +-21, +-22, +-23, +-22, +-23, +-24, +-23, +-25, +-24, +-25, +-25, +-25, +-26, +-26, +-27, +-26, +-27, +-28, +-27, +-28, +-28, +-29, +-29, +-29, +-29, +-30, +-30, +-30, +-30, +-31, +-31, +-31, +-31, +-32, +-32, +-32, +-32, +-33, +-33, +-33, +-33, +-33, +-34, +-34, +-34, +-34, +-34, +-35, +-34, +-35, +-35, +-35, +-36, +-35, +-36, +-35, +-36, +-36, +-36, +-37, +-36, +-36, +-37, +-37, +-36, +-37, +-37, +-37, +-37, +-37, +-38, +-37, +-37, +-38, +-37, +-38, +-37, +-38, +-37, +-38, +-38, +-37, +-38, +-38, +-37, +-38, +-38, +-37, +-38, +-38, +-37, +-38, +-37, +-38, +-37, +-38, +-37, +-38, +-37, +-37, +-37, +-37, +-37, +-37, +-37, +-37, +-35, +-37, +-36, +-37, +-36, +-36, +-36, +-36, +-36, +-35, +-36, +-35, +-36, +-35, +-35, +-34, +-35, +-34, +-35, +-34, +-34, +-34, +-33, +-34, +-33, +-33, +-33, +-32, +-33, +-32, +-32, +-32, +-32, +-31, +-31, +-31, +-31, +-31, +-30, +-30, +-30, +-29, +-30, +-29, +-29, +-28, +-28, +-29, +-27, +-28, +-27, +-27, +-27, +-26, +-27, +-25, +-26, +-25, +-26, +-24, +-25, +-24, +-24, +-23, +-24, +-23, +-22, +-23, +-22, +-22, +-21, +-21, +-21, +-21, +-20, +-20, +-19, +-19, +-19, +-19, +-18, +-18, +-18, +-17, +-17, +-17, +-16, +-16, +-15, +-16, +-14, +-15, +-14, +-14, +-14, +-13, +-13, +-12, +-12, +-12, +-12, +-11, +-10, +-11, +-10, +-10, +-9, +-9, +-9, +-8, +-8, +-8, +-7, +-7, +-6, +-6, +-6, +-6, +-5, +-5, +-4, +-4, +-4, +-3, +-3, +-3, +-2, +-2, +-2, +-1, +-1, +-1, +0, +0, +0, +1, +1, +2, +1, +3, +2, +3, +3, +4, +3, +4, +5, +5, +5, +5, +6, +6, +7, +6, +8, +7, +8, +8, +8, +9, +9, +9, +10, +9, +11, +10, +11, +11, +11, +12, +12, +12, +13, +13, +13, +13, +14, +14, +14, +14, +15, +15, +15, +16, +16, +16, +16, +17, +16, +18, +17, +17, +18, +18, +18, +19, +19, +19, +19, +19, +20, +19, +20, +21, +20, +21, +21, +21, +21, +21, +22, +22, +22, +22, +22, +23, +22, +23, +23, +23, +23, +24, +24, +23, +24, +24, +24, +25, +24, +25, +24, +25, +25, +25, +25, +26, +25, +26, +25, +26, +26, +25, +26, +26, +26, +27, +26, +26, +27, +26, +27, +26, +27, +26, +27, +27, +27, +26, +27, +27, +27, +27, +27, +27, +27, +27, +27, +27, +27, +27, +27, +27, +27, +27, +27, +26, +27, +27, +27, +27, +26, +27, +27, +26, +26, +26, +27, +26, +26, +27, +26, +26, +26, +26, +26, +26, +25, +26, +25, +26, +25, +25, +25, +25, +25, +25, +25, +24, +24, +25, +24, +24, +24, +23, +24, +24, +23, +23, +23, +23, +23, +22, +23, +22, +22, +22, +22, +21, +22, +21, +21, +21, +21, +20, +20, +21, +20, +19, +20, +19, +19, +19, +19, +19, +18, +18, +18, +18, +18, +17, +17, +17, +17, +16, +16, +16, +16, +16, +15, +15, +15, +14, +15, +14, +14, +14, +13, +13, +13, +13, +12, +13, +12, +11, +12, +11, +11, +11, +10, +11, +10, +9, +10, +9, +9, +9, +8, +9, +8, +7, +8, +7, +7, +7, +6, +6, +6, +6, +5, +5, +5, +5, +4, +4, +4, +3, +4, +3, +3, +2, +2, +2, +2, +2, +1, +1, +0, +1, +0, +0, +0, +-1, +-1, +-1, +-1, +-2, +-2, +-2, +-2, +-3, +-2, +-4, +-3, +-3, +-4, +-4, +-5, +-4, +-5, +-5, +-5, +-6, +-6, +-6, +-6, +-7, +-6, +-7, +-7, +-8, +-7, +-8, +-8, +-9, +-8, +-9, +-9, +-9, +-10, +-9, +-10, +-10, +-10, +-11, +-10, +-11, +-11, +-12, +-11, +-12, +-12, +-12, +-12, +-13, +-12, +-13, +-13, +-13, +-14, +-13, +-14, +-14, +-14, +-14, +-15, +-14, +-15, +-15, +-15, +-15, +-16, +-15, +-16, +-16, +-16, +-16, +-16, +-17, +-16, +-17, +-17, +-17, +-17, +-17, +-18, +-17, +-18, +-18, +-17, +-18, +-18, +-19, +-18, +-18, +-19, +-18, +-19, +-19, +-19, +-19, +-19, +-19, +-19, +-19, +-20, +-19, +-20, +-19, +-20, +-20, +-20, +-19, +-20, +-20, +-20, +-20, +-20, +-21, +-20, +-20, +-20, +-21, +-20, +-20, +-21, +-20, +-21, +-20, +-20, +-21, +-20, +-21, +-20, +-21, +-20, +-21, +-20, +-21, +-21, +-20, +-20, +-21, +-20, +-21, +-20, +-21, +-20, +-20, +-20, +-20, +-20, +-20, +-20, +-20, +-20, +-20, +-20, +-20, +-20, +-20, +-19, +-20, +-20, +-19, +-20, +-19, +-19, +-19, +-20, +-19, +-19, +-18, +-19, +-19, +-19, +-18, +-18, +-19, +-18, +-18, +-18, +-18, +-18, +-18, +-17, +-18, +-17, +-17, +-17, +-17, +-17, +-17, +-16, +-17, +-16, +-16, +-17, +-15, +-16, +-16, +-15, +-16, +-15, +-15, +-15, +-15, +-15, +-14, +-14, +-15, +-14, +-13, +-14, +-14, +-13, +-13, +-13, +-13, +-13, +-13, +-12, +-12, +-12, +-12, +-12, +-11, +-12, +-11, +-11, +-11, +-10, +-11, +-10, +-10, +-10, +-9, +-10, +-9, +-9, +-9, +-9, +-9, +-8, +-8, +-8, +-8, +-8, +-7, +-7, +-7, +-7, +-7, +-6, +-6, +-6, +-6, +-6, +-5, +-5, +-6, +-4, +-5, +-4, +-5, +-4, +-4, +-3, +-4, +-3, +-3, +-3, +-2, +-3, +-2, +-2, +-2, +-1, +-2, +-1, +-1, +-1, +0, +-1, +0, +0, +0, +1, +0, +1, +1, +1, +1, +2, +2, +2, +2, +2, +3, +3, +2, +4, +3, +3, +4, +4, +4, +4, +5, +4, +5, +5, +5, +6, +5, +6, +6, +6, +6, +7, +6, +7, +7, +7, +7, +8, +7, +8, +8, +8, +8, +9, +8, +9, +9, +9, +9, +10, +9, +10, +10, +10, +10, +10, +11, +10, +11, +11, +11, +11, +11, +11, +12, +11, +12, +12, +12, +12, +12, +13, +12, +13, +13, +12, +13, +13, +14, +13, +13, +14, +13, +14, +14, +13, +14, +14, +15, +14, +14, +14, +15, +14, +15, +15, +14, +15, +15, +15, +15, +15, +16, +15, +15, +15, +16, +15, +16, +15, +16, +15, +16, +16, +16, +15, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +17, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +16, +15, +16, +16, +16, +16, +16, +15, +16, +16, +15, +16, +16, +15, +15, +16, +15, +16, +15, +15, +15, +15, +15, +15, +15, +15, +15, +14, +15, +14, +15, +14, +14, +15, +14, +14, +14, +14, +13, +14, +14, +13, +13, +14, +13, +13, +13, +13, +13, +12, +13, +12, +13, +12, +12, +12, +12, +12, +12, +11, +12, +11, +11, +11, +11, +11, +11, +10, +11, +10, +10, +10, +10, +10, +10, +9, +10, +9, +9, +9, +9, +8, +9, +8, +9, +8, +8, +8, +7, +8, +7, +7, +7, +7, +7, +7, +6, +7, +6, +6, +6, +5, +6, +5, +5, +6, +4, +5, +5, +4, +5, +4, +4, +4, +3, +4, +3, +3, +3, +3, +3, +2, +3, +2, +2, +2, +2, +1, +2, +1, +1, +1, +1, +1, +0, +0, +1, +0, +-1, +0, +0, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-3, +-3, +-3, +-3, +-4, +-3, +-4, +-4, +-4, +-4, +-4, +-5, +-4, +-5, +-5, +-5, +-5, +-5, +-6, +-5, +-6, +-6, +-6, +-6, +-6, +-6, +-7, +-6, +-7, +-7, +-7, +-7, +-7, +-7, +-8, +-8, +-7, +-8, +-8, +-8, +-8, +-9, +-8, +-9, +-8, +-9, +-9, +-9, +-9, +-9, +-9, +-10, +-9, +-10, +-9, +-10, +-10, +-10, +-10, +-10, +-10, +-11, +-10, +-11, +-10, +-11, +-11, +-11, +-10, +-11, +-11, +-12, +-11, +-11, +-11, +-12, +-11, +-12, +-12, +-11, +-12, +-12, +-12, +-11, +-12, +-12, +-13, +-12, +-12, +-12, +-12, +-13, +-12, +-12, +-13, +-12, +-13, +-12, +-13, +-12, +-13, +-13, +-12, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-11, +-13, +-13, +-12, +-13, +-13, +-12, +-13, +-12, +-13, +-12, +-13, +-12, +-13, +-12, +-12, +-13, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-11, +-12, +-12, +-11, +-12, +-11, +-11, +-12, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-10, +-11, +-10, +-11, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-10, +-9, +-10, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-9, +-8, +-9, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-7, +-7, +-8, +-7, +-7, +-7, +-7, +-6, +-7, +-7, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-5, +-6, +-5, +-5, +-5, +-5, +-5, +-4, +-5, +-4, +-5, +-4, +-4, +-4, +-4, +-3, +-4, +-3, +-4, +-3, +-3, +-3, +-3, +-2, +-3, +-2, +-2, +-3, +-2, +-1, +-2, +-2, +-1, +-2, +-1, +-1, +-1, +-1, +-1, +0, +-1, +0, +0, +0, +0, +0, +0, +1, +0, +1, +1, +0, +2, +1, +1, +1, +2, +2, +1, +2, +2, +3, +2, +2, +3, +2, +3, +3, +3, +3, +3, +4, +3, +4, +4, +3, +4, +4, +4, +5, +4, +5, +4, +5, +5, +5, +5, +5, +5, +5, +6, +5, +6, +6, +6, +6, +6, +6, +6, +6, +7, +6, +7, +7, +7, +7, +7, +7, +7, +7, +7, +8, +7, +8, +8, +7, +8, +8, +8, +8, +8, +8, +9, +8, +9, +8, +9, +8, +9, +9, +8, +9, +9, +9, +9, +9, +10, +9, +9, +9, +10, +9, +10, +9, +10, +10, +9, +10, +10, +9, +10, +10, +10, +10, +10, +10, +10, +10, +10, +10, +11, +10, +10, +10, +10, +11, +10, +10, +11, +10, +10, +11, +10, +10, +11, +10, +10, +11, +10, +11, +10, +11, +10, +10, +11, +10, +10, +11, +10, +11, +10, +10, +10, +10, +10, +10, +11, +10, +10, +10, +10, +11, +10, +10, +10, +10, +10, +10, +10, +10, +9, +10, +10, +10, +9, +10, +10, +9, +10, +9, +10, +9, +9, +10, +9, +9, +9, +9, +9, +9, +9, +9, +9, +8, +9, +9, +8, +9, +8, +8, +9, +8, +8, +8, +8, +8, +8, +7, +8, +8, +7, +8, +7, +7, +8, +7, +7, +7, +7, +6, +7, +7, +6, +7, +6, +7, +6, +6, +6, +6, +6, +6, +5, +6, +5, +6, +5, +5, +5, +5, +5, +5, +5, +4, +5, +4, +5, +4, +4, +4, +4, +4, +4, +3, +4, +3, +4, +3, +3, +3, +3, +3, +3, +2, +3, +2, +2, +3, +2, +2, +2, +1, +2, +2, +1, +2, +1, +1, +1, +1, +1, +1, +0, +1, +0, +1, +0, +0, +0, +0, +0, +0, +-1, +0, +-1, +-1, +0, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-3, +-2, +-3, +-3, +-3, +-3, +-3, +-3, +-4, +-3, +-4, +-3, +-4, +-4, +-3, +-4, +-4, +-5, +-4, +-4, +-4, +-5, +-4, +-5, +-5, +-5, +-4, +-5, +-5, +-6, +-5, +-5, +-5, +-6, +-5, +-6, +-5, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-7, +-6, +-6, +-7, +-6, +-7, +-7, +-6, +-7, +-7, +-7, +-7, +-7, +-7, +-7, +-7, +-8, +-7, +-7, +-8, +-7, +-8, +-7, +-8, +-7, +-8, +-7, +-8, +-8, +-8, +-8, +-7, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-9, +-8, +-8, +-8, +-8, +-9, +-8, +-8, +-8, +-9, +-8, +-8, +-9, +-8, +-9, +-8, +-8, +-9, +-8, +-9, +-8, +-9, +-8, +-8, +-9, +-8, +-9, +-8, +-9, +-8, +-9, +-8, +-8, +-9, +-8, +-9, +-8, +-7, +-9, +-8, +-8, +-9, +-8, +-8, +-9, +-8, +-8, +-8, +-8, +-8, +-9, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-8, +-7, +-8, +-8, +-8, +-7, +-8, +-8, +-7, +-8, +-7, +-8, +-7, +-8, +-7, +-7, +-7, +-8, +-7, +-7, +-7, +-7, +-7, +-7, +-7, +-6, +-7, +-7, +-6, +-7, +-7, +-6, +-6, +-7, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-6, +-5, +-6, +-5, +-6, +-5, +-5, +-6, +-5, +-5, +-5, +-5, +-5, +-4, +-5, +-5, +-4, +-5, +-4, +-5, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-3, +-4, +-3, +-4, +-3, +-3, +-3, +-4, +-3, +-2, +-3, +-3, +-3, +-2, +-3, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-2, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +0, +-1, +-1, +-1, +0, +-1, +0, +0, +-1, +0, +0, +0, +0, +0, +1, +0, +1, +0, +1, +0, +1, +1, +1, +1, +1, +1, +1, +2, +1, +2, +1, +2, +2, +2, +1, +2, +2, +3, +2, +2, +2, +3, +2, +3, +3, +2, +3, +3, +3, +3, +3, +3, +4, +3, +3, +4, +3, +4, +3, +4, +4, +4, +4, +4, +4, +4, +4, +4, +5, +4, +4, +5, +5, +4, +5, +5, +4, +5, +5, +5, +5, +5, +5, +5, +6, +5, +5, +5, +6, +5, +6, +5, +6, +6, +5, +6, +6, +6, +5, +6, +6, +6, +6, +6, +6, +7, +6, +6, +6, +6, +7, +6, +6, +7, +6, +7, +6, +6, +7, +7, +6, +7, +6, +7, +6, +7, +7, +7, +6, +7, +7, +6, +7, +7, +7, +7, +6, +7, +7, +7, +7, +7, +6, +7, +7, +7, +7, +7, +7, +6, +7, +7, +7, +7, +7, +7, +6, +7, +7, +6, +7, +6, +7, +7, +7, +6, +7, +7, +6, +7, +7, +6, +7, +7, +6, +7, +6, +7, +6, +7, +6, +6, +7, +6, +6, +7, +6, +6, +6, +6, +6, +7, +6, +6, +6, +6, +5, +6, +6, +6, +6, +5, +6, +6, +5, +6, +5, +6, +5, +5, +6, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +5, +4, +5, +4, +5, +4, +5, +4, +4, +4, +5, +4, +4, +4, +4, +3, +4, +4, +4, +3, +4, +3, +4, +3, +3, +4, +3, +3, +3, +3, +3, +3, +2, +3, +3, +2, +3, +2, +3, +2, +2, +3, +2, +2, +2, +2, +2, +1, +2, +2, +1, +2, +1, +2, +1, +1, +1, +2, +1, +1, +0, +1, +1, +1, +0, +1, +0, +1, +0, +0, +1, +0, +0, +0, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-2, +-2, +-1, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-3, +-2, +-3, +-2, +-3, +-3, +-2, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-4, +-3, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-4, +-3, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-5, +-4, +-4, +-5, +-4, +-4, +-5, +-4, +-5, +-4, +-5, +-5, +-4, +-5, +-5, +-4, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-6, +-5, +-5, +-5, +-5, +-6, +-5, +-5, +-6, +-5, +-5, +-6, +-5, +-6, +-5, +-6, +-5, +-6, +-5, +-5, +-6, +-6, +-5, +-6, +-5, +-6, +-5, +-6, +-5, +-6, +-5, +-6, +-6, +-5, +-6, +-5, +-6, +-5, +-6, +-5, +-6, +-6, +-5, +-6, +-5, +-5, +-5, +-6, +-5, +-6, +-5, +-6, +-5, +-5, +-6, +-5, +-6, +-5, +-5, +-6, +-5, +-5, +-6, +-5, +-5, +-5, +-6, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-4, +-5, +-5, +-5, +-4, +-5, +-5, +-4, +-5, +-4, +-5, +-4, +-4, +-5, +-4, +-4, +-5, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-4, +-3, +-4, +-4, +-3, +-4, +-4, +-3, +-4, +-3, +-3, +-4, +-3, +-3, +-3, +-4, +-3, +-3, +-3, +-3, +-3, +-2, +-3, +-3, +-3, +-2, +-3, +-2, +-3, +-2, +-3, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-2, +-2, +-1, +-2, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +1, +0, +0, +0, +1, +0, +1, +0, +1, +0, +1, +1, +1, +0, +1, +1, +1, +1, +1, +2, +1, +1, +1, +2, +1, +2, +1, +2, +1, +2, +2, +1, +2, +2, +2, +2, +2, +2, +2, +2, +2, +3, +2, +2, +3, +2, +3, +2, +3, +2, +3, +2, +3, +3, +3, +3, +2, +3, +3, +3, +3, +3, +4, +3, +3, +3, +3, +4, +3, +3, +4, +3, +4, +3, +4, +3, +4, +3, +4, +4, +3, +4, +4, +4, +4, +3, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +4, +5, +4, +4, +4, +4, +5, +4, +4, +4, +5, +4, +4, +5, +4, +4, +5, +4, +5, +4, +4, +5, +4, +5, +4, +5, +4, +4, +5, +4, +5, +4, +5, +4, +5, +4, +5, +4, +5, +4, +5, +4, +5, +4, +5, +4, +5, +4, +5, +3, +4, +5, +4, +5, +4, +4, +5, +4, +5, +4, +4, +5, +4, +4, +5, +4, +4, +4, +4, +5, +4, +4, +4, +4, +4, +5, +4, +4, +4, +4, +4, +4, +4, +3, +4, +4, +4, +4, +4, +3, +4, +4, +4, +3, +4, +4, +3, +4, +3, +4, +3, +3, +4, +3, +4, +3, +3, +3, +4, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +2, +3, +3, +3, +2, +3, +2, +3, +2, +3, +2, +3, +2, +2, +3, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +1, +2, +2, +1, +2, +1, +2, +1, +1, +2, +1, +1, +1, +2, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-2, +-2, +-1, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-3, +-2, +-3, +-2, +-3, +-2, +-3, +-2, +-3, +-2, +-3, +-3, +-3, +-2, +-3, +-3, +-3, +-3, +-2, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-4, +-3, +-3, +-3, +-3, +-4, +-3, +-3, +-3, +-4, +-3, +-3, +-4, +-3, +-3, +-4, +-3, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-4, +-3, +-4, +-3, +-4, +-4, +-3, +-4, +-3, +-4, +-4, +-3, +-4, +-3, +-4, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-4, +-3, +-3, +-3, +-4, +-3, +-4, +-4, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-3, +-4, +-3, +-4, +-3, +-4, +-3, +-3, +-4, +-3, +-3, +-4, +-3, +-3, +-4, +-3, +-3, +-3, +-3, +-4, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-3, +-2, +-3, +-3, +-3, +-2, +-3, +-3, +-2, +-3, +-2, +-3, +-2, +-3, +-2, +-3, +-2, +-3, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-2, +-2, +-2, +-2, +-1, +-2, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +0, +-1, +-1, +-1, +-1, +-1, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +1, +1, +1, +2, +1, +1, +1, +2, +1, +1, +2, +1, +1, +2, +1, +2, +1, +2, +1, +2, +2, +1, +2, +2, +2, +1, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +3, +2, +2, +2, +3, +2, +2, +3, +2, +2, +3, +2, +3, +2, +3, +2, +3, +2, +3, +2, +3, +2, +3, +3, +2, +3, +2, +3, +3, +2, +3, +3, +3, +2, +3, +3, +2, +3, +3, +3, +3, +2, +3, +3, +3, +3, +2, +3, +3, +3, +3, +3, +2, +3, +3, +3, +3, +3, +3, +3, +2, +3, +3, +3, +3, +3, +3, +2, +3, +3, +3, +3, +3, +3, +2, +2, +3, +3, +3, +2, +3, +3, +3, +3, +2, +3, +3, +3, +2, +3, +3, +3, +2, +3, +3, +2, +3, +3, +2, +3, +3, +2, +3, +2, +3, +2, +3, +2, +3, +2, +3, +2, +3, +2, +3, +2, +2, +3, +2, +2, +3, +2, +2, +3, +2, +2, +2, +2, +2, +3, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +1, +2, +2, +2, +2, +2, +1, +2, +2, +1, +2, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +1, +2, +1, +1, +2, +1, +1, +1, +1, +2, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +0, +1, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-2, +-1, +-2, +-2, +-1, +-2, +-2, +-2, +-1, +-2, +-2, +-2, +-2, +-1, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-3, +-2, +-2, +-3, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-3, +-1, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-2, +-2, +-2, +-2, +-1, +-2, +-2, +-2, +-1, +-2, +-2, +-1, +-2, +-1, +-2, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +1, +0, +1, +1, +1, +0, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +2, +1, +1, +1, +1, +1, +1, +2, +1, +1, +1, +2, +1, +1, +2, +1, +1, +2, +1, +1, +2, +1, +1, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +2, +2, +1, +2, +1, +2, +2, +1, +2, +2, +1, +2, +2, +1, +2, +2, +1, +2, +2, +2, +1, +2, +2, +1, +2, +2, +2, +1, +2, +2, +2, +1, +2, +2, +2, +1, +2, +2, +2, +2, +1, +2, +2, +2, +1, +2, +2, +2, +1, +2, +2, +2, +1, +2, +1, +2, +1, +2, +2, +1, +2, +2, +2, +1, +2, +2, +1, +2, +2, +1, +2, +2, +1, +2, +2, +1, +2, +2, +1, +2, +1, +2, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +2, +1, +1, +2, +1, +2, +1, +1, +2, +1, +1, +2, +1, +1, +2, +1, +1, +1, +2, +1, +1, +1, +1, +1, +2, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +0, +1, +1, +1, +0, +1, +1, +0, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +1, +0, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +1, +0, +1, +1, +1, +0, +1, +1, +0, +1, +1, +1, +0, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +2, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +1, +0, +1, +1, +1, +1, +0, +1, +1, +1, +0, +1, +1, +1, +0, +1, +1, +0, +1, +1, +0, +1, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +0, +1, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +0, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +1, +0, +1, +0, +0, +1, +0, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +1, +0, +0, +1, +0, +0, +1, +0, +1, +0, +0, +1, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0}; diff --git a/pjmedia/src/pjmedia/resample.c b/pjmedia/src/pjmedia/resample.c new file mode 100644 index 00000000..0fd08468 --- /dev/null +++ b/pjmedia/src/pjmedia/resample.c @@ -0,0 +1,562 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Based on: + * resample-1.2.tar.Z (from ftp://ccrma-ftp.stanford.edu/pub/NeXT) + * SOFTWARE FOR SAMPLING-RATE CONVERSION AND FIR DIGITAL FILTER DESIGN + * + * COPYING + * + * This software package is Copyright 1994 by Julius O. Smith + * (jos@ccrma.stanford.edu), all rights reserved. Permission to use and copy + * is granted subject to the terms of the "GNU Software General Public + * License" (see ftp://prep.ai.mit.edu/pub/gnu/COPYING). In addition, we + * request that a copy of any modified files be sent by email to + * jos@ccrma.stanford.edu so that we may incorporate them in the CCRMA + * version. + */ + +/* PJMEDIA modification: + * - remove resample(), just use SrcUp, SrcUD, and SrcLinear directly. + * - move FilterUp() and FilterUD() from filterkit.c + * - move stddefs.h and resample.h to this file. + * - const correctness. + */ +#include <pjmedia/resample.h> +#include <pjmedia/errno.h> +#include <pj/assert.h> +#include <pj/pool.h> + + + +/* + * Taken from stddefs.h + */ +#ifndef PI +#define PI (3.14159265358979232846) +#endif + +#ifndef PI2 +#define PI2 (6.28318530717958465692) +#endif + +#define D2R (0.01745329348) /* (2*pi)/360 */ +#define R2D (57.29577951) /* 360/(2*pi) */ + +#ifndef MAX +#define MAX(x,y) ((x)>(y) ?(x):(y)) +#endif +#ifndef MIN +#define MIN(x,y) ((x)<(y) ?(x):(y)) +#endif + +#ifndef ABS +#define ABS(x) ((x)<0 ?(-(x)):(x)) +#endif + +#ifndef SGN +#define SGN(x) ((x)<0 ?(-1):((x)==0?(0):(1))) +#endif + +typedef char BOOL; +typedef short HWORD; +typedef unsigned short UHWORD; +typedef int WORD; +typedef unsigned int UWORD; + +#define MAX_HWORD (32767) +#define MIN_HWORD (-32768) + +#ifdef DEBUG +#define INLINE +#else DEBUG +#define INLINE inline +#endif DEBUG + +/* + * Taken from resample.h + * + * The configuration constants below govern + * the number of bits in the input sample and filter coefficients, the + * number of bits to the right of the binary-point for fixed-point math, etc. + * + */ + +/* Conversion constants */ +#define Nhc 8 +#define Na 7 +#define Np (Nhc+Na) +#define Npc (1<<Nhc) +#define Amask ((1<<Na)-1) +#define Pmask ((1<<Np)-1) +#define Nh 16 +#define Nb 16 +#define Nhxn 14 +#define Nhg (Nh-Nhxn) +#define NLpScl 13 + +/* Description of constants: + * + * Npc - is the number of look-up values available for the lowpass filter + * between the beginning of its impulse response and the "cutoff time" + * of the filter. The cutoff time is defined as the reciprocal of the + * lowpass-filter cut off frequence in Hz. For example, if the + * lowpass filter were a sinc function, Npc would be the index of the + * impulse-response lookup-table corresponding to the first zero- + * crossing of the sinc function. (The inverse first zero-crossing + * time of a sinc function equals its nominal cutoff frequency in Hz.) + * Npc must be a power of 2 due to the details of the current + * implementation. The default value of 512 is sufficiently high that + * using linear interpolation to fill in between the table entries + * gives approximately 16-bit accuracy in filter coefficients. + * + * Nhc - is log base 2 of Npc. + * + * Na - is the number of bits devoted to linear interpolation of the + * filter coefficients. + * + * Np - is Na + Nhc, the number of bits to the right of the binary point + * in the integer "time" variable. To the left of the point, it indexes + * the input array (X), and to the right, it is interpreted as a number + * between 0 and 1 sample of the input X. Np must be less than 16 in + * this implementation. + * + * Nh - is the number of bits in the filter coefficients. The sum of Nh and + * the number of bits in the input data (typically 16) cannot exceed 32. + * Thus Nh should be 16. The largest filter coefficient should nearly + * fill 16 bits (32767). + * + * Nb - is the number of bits in the input data. The sum of Nb and Nh cannot + * exceed 32. + * + * Nhxn - is the number of bits to right shift after multiplying each input + * sample times a filter coefficient. It can be as great as Nh and as + * small as 0. Nhxn = Nh-2 gives 2 guard bits in the multiply-add + * accumulation. If Nhxn=0, the accumulation will soon overflow 32 bits. + * + * Nhg - is the number of guard bits in mpy-add accumulation (equal to Nh-Nhxn) + * + * NLpScl - is the number of bits allocated to the unity-gain normalization + * factor. The output of the lowpass filter is multiplied by LpScl and + * then right-shifted NLpScl bits. To avoid overflow, we must have + * Nb+Nhg+NLpScl < 32. + */ + + +#ifdef _MSC_VER +# pragma warning(push, 3) +//# pragma warning(disable: 4245) // Conversion from uint to ushort +# pragma warning(disable: 4244) // Conversion from double to uint +# pragma warning(disable: 4146) // unary minus operator applied to unsigned type, result still unsigned +# pragma warning(disable: 4761) // integral size mismatch in argument; conversion supplied +#endif + +#include "smallfilter.h" +#include "largefilter.h" + +#undef INLINE +#define INLINE +#define HAVE_FILTER 0 + +#ifndef NULL +# define NULL 0 +#endif + + +static INLINE HWORD WordToHword(WORD v, int scl) +{ + HWORD out; + WORD llsb = (1<<(scl-1)); + v += llsb; /* round */ + v >>= scl; + if (v>MAX_HWORD) { + v = MAX_HWORD; + } else if (v < MIN_HWORD) { + v = MIN_HWORD; + } + out = (HWORD) v; + return out; +} + +/* Sampling rate conversion using linear interpolation for maximum speed. + */ +static int + SrcLinear(const HWORD X[], HWORD Y[], double pFactor, UHWORD nx) +{ + HWORD iconst; + UWORD time = 0; + const HWORD *xp; + HWORD *Ystart; + WORD v,x1,x2; + + double dt; /* Step through input signal */ + UWORD dtb; /* Fixed-point version of Dt */ + UWORD endTime; /* When time reaches EndTime, return to user */ + + dt = 1.0/pFactor; /* Output sampling period */ + dtb = dt*(1<<Np) + 0.5; /* Fixed-point representation */ + + Ystart = Y; + endTime = time + (1<<Np)*(WORD)nx; + while (time < endTime) + { + iconst = (time) & Pmask; + xp = &X[(time)>>Np]; /* Ptr to current input sample */ + x1 = *xp++; + x2 = *xp; + x1 *= ((1<<Np)-iconst); + x2 *= iconst; + v = x1 + x2; + *Y++ = WordToHword(v,Np); /* Deposit output */ + time += dtb; /* Move to next sample by time increment */ + } + return (Y - Ystart); /* Return number of output samples */ +} + +static WORD FilterUp(const HWORD Imp[], const HWORD ImpD[], + UHWORD Nwing, BOOL Interp, + const HWORD *Xp, HWORD Ph, HWORD Inc) +{ + const HWORD *Hp; + const HWORD *Hdp = NULL; + const HWORD *End; + HWORD a = 0; + WORD v, t; + + v=0; + Hp = &Imp[Ph>>Na]; + End = &Imp[Nwing]; + if (Interp) { + Hdp = &ImpD[Ph>>Na]; + a = Ph & Amask; + } + if (Inc == 1) /* If doing right wing... */ + { /* ...drop extra coeff, so when Ph is */ + End--; /* 0.5, we don't do too many mult's */ + if (Ph == 0) /* If the phase is zero... */ + { /* ...then we've already skipped the */ + Hp += Npc; /* first sample, so we must also */ + Hdp += Npc; /* skip ahead in Imp[] and ImpD[] */ + } + } + if (Interp) + while (Hp < End) { + t = *Hp; /* Get filter coeff */ + t += (((WORD)*Hdp)*a)>>Na; /* t is now interp'd filter coeff */ + Hdp += Npc; /* Filter coeff differences step */ + t *= *Xp; /* Mult coeff by input sample */ + if (t & (1<<(Nhxn-1))) /* Round, if needed */ + t += (1<<(Nhxn-1)); + t >>= Nhxn; /* Leave some guard bits, but come back some */ + v += t; /* The filter output */ + Hp += Npc; /* Filter coeff step */ + + Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ + } + else + while (Hp < End) { + t = *Hp; /* Get filter coeff */ + t *= *Xp; /* Mult coeff by input sample */ + if (t & (1<<(Nhxn-1))) /* Round, if needed */ + t += (1<<(Nhxn-1)); + t >>= Nhxn; /* Leave some guard bits, but come back some */ + v += t; /* The filter output */ + Hp += Npc; /* Filter coeff step */ + Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ + } + return(v); +} + + +static WORD FilterUD(const HWORD Imp[], const HWORD ImpD[], + UHWORD Nwing, BOOL Interp, + const HWORD *Xp, HWORD Ph, HWORD Inc, UHWORD dhb) +{ + HWORD a; + const HWORD *Hp, *Hdp, *End; + WORD v, t; + UWORD Ho; + + v=0; + Ho = (Ph*(UWORD)dhb)>>Np; + End = &Imp[Nwing]; + if (Inc == 1) /* If doing right wing... */ + { /* ...drop extra coeff, so when Ph is */ + End--; /* 0.5, we don't do too many mult's */ + if (Ph == 0) /* If the phase is zero... */ + Ho += dhb; /* ...then we've already skipped the */ + } /* first sample, so we must also */ + /* skip ahead in Imp[] and ImpD[] */ + if (Interp) + while ((Hp = &Imp[Ho>>Na]) < End) { + t = *Hp; /* Get IR sample */ + Hdp = &ImpD[Ho>>Na]; /* get interp (lower Na) bits from diff table*/ + a = Ho & Amask; /* a is logically between 0 and 1 */ + t += (((WORD)*Hdp)*a)>>Na; /* t is now interp'd filter coeff */ + t *= *Xp; /* Mult coeff by input sample */ + if (t & 1<<(Nhxn-1)) /* Round, if needed */ + t += 1<<(Nhxn-1); + t >>= Nhxn; /* Leave some guard bits, but come back some */ + v += t; /* The filter output */ + Ho += dhb; /* IR step */ + Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ + } + else + while ((Hp = &Imp[Ho>>Na]) < End) { + t = *Hp; /* Get IR sample */ + t *= *Xp; /* Mult coeff by input sample */ + if (t & 1<<(Nhxn-1)) /* Round, if needed */ + t += 1<<(Nhxn-1); + t >>= Nhxn; /* Leave some guard bits, but come back some */ + v += t; /* The filter output */ + Ho += dhb; /* IR step */ + Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ + } + return(v); +} + +/* Sampling rate up-conversion only subroutine; + * Slightly faster than down-conversion; + */ +static int SrcUp(const HWORD X[], HWORD Y[], double pFactor, + UHWORD nx, UHWORD pNwing, UHWORD pLpScl, + const HWORD pImp[], const HWORD pImpD[], BOOL Interp) +{ + const HWORD *xp; + HWORD *Ystart; + WORD v; + + double dt; /* Step through input signal */ + UWORD dtb; /* Fixed-point version of Dt */ + UWORD time = 0; + UWORD endTime; /* When time reaches EndTime, return to user */ + + dt = 1.0/pFactor; /* Output sampling period */ + dtb = dt*(1<<Np) + 0.5; /* Fixed-point representation */ + + Ystart = Y; + endTime = time + (1<<Np)*(WORD)nx; + while (time < endTime) + { + xp = &X[time>>Np]; /* Ptr to current input sample */ + /* Perform left-wing inner product */ + v = 0; + v = FilterUp(pImp, pImpD, pNwing, Interp, xp, (HWORD)(time&Pmask),-1); + + /* Perform right-wing inner product */ + v += FilterUp(pImp, pImpD, pNwing, Interp, xp+1, (HWORD)((-time)&Pmask),1); + + v >>= Nhg; /* Make guard bits */ + v *= pLpScl; /* Normalize for unity filter gain */ + *Y++ = WordToHword(v,NLpScl); /* strip guard bits, deposit output */ + time += dtb; /* Move to next sample by time increment */ + } + return (Y - Ystart); /* Return the number of output samples */ +} + + +/* Sampling rate conversion subroutine */ + +static int SrcUD(const HWORD X[], HWORD Y[], double pFactor, + UHWORD nx, UHWORD pNwing, UHWORD pLpScl, + const HWORD pImp[], const HWORD pImpD[], BOOL Interp) +{ + const HWORD *xp; + HWORD *Ystart; + WORD v; + + double dh; /* Step through filter impulse response */ + double dt; /* Step through input signal */ + UWORD time = 0; + UWORD endTime; /* When time reaches EndTime, return to user */ + UWORD dhb, dtb; /* Fixed-point versions of Dh,Dt */ + + dt = 1.0/pFactor; /* Output sampling period */ + dtb = dt*(1<<Np) + 0.5; /* Fixed-point representation */ + + dh = MIN(Npc, pFactor*Npc); /* Filter sampling period */ + dhb = dh*(1<<Na) + 0.5; /* Fixed-point representation */ + + Ystart = Y; + endTime = time + (1<<Np)*(WORD)nx; + while (time < endTime) + { + xp = &X[time>>Np]; /* Ptr to current input sample */ + v = FilterUD(pImp, pImpD, pNwing, Interp, xp, (HWORD)(time&Pmask), + -1, dhb); /* Perform left-wing inner product */ + v += FilterUD(pImp, pImpD, pNwing, Interp, xp+1, (HWORD)((-time)&Pmask), + 1, dhb); /* Perform right-wing inner product */ + v >>= Nhg; /* Make guard bits */ + v *= pLpScl; /* Normalize for unity filter gain */ + *Y++ = WordToHword(v,NLpScl); /* strip guard bits, deposit output */ + time += dtb; /* Move to next sample by time increment */ + } + return (Y - Ystart); /* Return the number of output samples */ +} + + +/* *************************************************************************** + * + * PJMEDIA RESAMPLE + * + * *************************************************************************** + */ + +struct pjmedia_resample +{ + double factor; /* Conversion factor = rate_out / rate_in. */ + pj_bool_t large_filter; /* Large filter? */ + pj_bool_t high_quality; /* Not fast? */ + unsigned xoff; /* History and lookahead size, in samples */ + unsigned frame_size; /* Samples per frame. */ + pj_int16_t *buffer; /* Input buffer. */ +}; + + +PJ_DEF(pj_status_t) pjmedia_resample_create( pj_pool_t *pool, + pj_bool_t high_quality, + pj_bool_t large_filter, + unsigned rate_in, + unsigned rate_out, + unsigned samples_per_frame, + pjmedia_resample **p_resample) +{ + pjmedia_resample *resample; + + PJ_ASSERT_RETURN(pool && p_resample && rate_in && + rate_out && samples_per_frame, PJ_EINVAL); + + resample = pj_pool_alloc(pool, sizeof(pjmedia_resample)); + PJ_ASSERT_RETURN(resample, PJ_ENOMEM); + + /* + * If we're downsampling, always use the fast algorithm since it seems + * to yield the same performance. + */ + if (rate_out < rate_in) { + high_quality = 0; + } + + resample->factor = rate_out * 1.0 / rate_in; + resample->large_filter = large_filter; + resample->high_quality = high_quality; + resample->xoff = large_filter ? 32 : 6; + resample->frame_size = samples_per_frame; + + if (high_quality) { + unsigned size; + unsigned i; + + size = (samples_per_frame + 2*resample->xoff) * sizeof(pj_int16_t); + resample->buffer = pj_pool_alloc(pool, size); + PJ_ASSERT_RETURN(resample->buffer, PJ_ENOMEM); + + for (i=0; i<resample->xoff*2; ++i) { + resample->buffer[i] = 0; + } + } + + *p_resample = resample; + return PJ_SUCCESS; +} + + + +PJ_DEF(void) pjmedia_resample_run( pjmedia_resample *resample, + const pj_int16_t *input, + pj_int16_t *output ) +{ + PJ_ASSERT_ON_FAIL(resample, return); + + if (resample->high_quality) { + unsigned i; + pj_int16_t *dst_buf; + const pj_int16_t *src_buf; + + /* Buffer layout: + * + * run 0 + * +------+------+--------------+ + * | 0000 | 0000 | frame0... | + * +------+------+--------------+ + * ^ ^ ^ ^ + * 0 xoff 2*xoff size+2*xoff + * + * run 01 + * +------+------+--------------+ + * | frm0 | frm0 | frame1... | + * +------+------+--------------+ + * ^ ^ ^ ^ + * 0 xoff 2*xoff size+2*xoff + */ + dst_buf = resample->buffer + resample->xoff*2; + for (i=0; i<resample->frame_size; ++i) + dst_buf[i] = input[i]; + + if (resample->factor >= 1) { + + if (resample->large_filter) { + SrcUp(resample->buffer + resample->xoff, output, + resample->factor, resample->frame_size, + LARGE_FILTER_NWING, LARGE_FILTER_SCALE, + LARGE_FILTER_IMP, LARGE_FILTER_IMPD, + PJ_TRUE); + } else { + SrcUp(resample->buffer + resample->xoff, output, + resample->factor, resample->frame_size, + SMALL_FILTER_NWING, SMALL_FILTER_SCALE, + SMALL_FILTER_IMP, SMALL_FILTER_IMPD, + PJ_TRUE); + } + + } else { + + if (resample->large_filter) { + + SrcUD( resample->buffer + resample->xoff, output, + resample->factor, resample->frame_size, + LARGE_FILTER_NWING, + LARGE_FILTER_SCALE * resample->factor + 0.5, + LARGE_FILTER_IMP, LARGE_FILTER_IMPD, + PJ_TRUE); + + } else { + + SrcUD( resample->buffer + resample->xoff, output, + resample->factor, resample->frame_size, + SMALL_FILTER_NWING, + SMALL_FILTER_SCALE * resample->factor + 0.5, + SMALL_FILTER_IMP, SMALL_FILTER_IMPD, + PJ_TRUE); + + } + + } + + dst_buf = resample->buffer; + src_buf = input + resample->frame_size - resample->xoff*2; + for (i=0; i<resample->xoff * 2; ++i) { + dst_buf[i] = src_buf[i]; + } + + } else { + SrcLinear( input, output, resample->factor, resample->frame_size); + } +} diff --git a/pjmedia/src/pjmedia/smallfilter.h b/pjmedia/src/pjmedia/smallfilter.h new file mode 100644 index 00000000..6f6f0f84 --- /dev/null +++ b/pjmedia/src/pjmedia/smallfilter.h @@ -0,0 +1,4617 @@ +/* Included by resamplesubs.c */ +#define SMALL_FILTER_NMULT ((HWORD)13) +#define SMALL_FILTER_SCALE 13128 /* Unity-gain scale factor */ +#define SMALL_FILTER_NWING 1536 /* Filter table length */ +static HWORD SMALL_FILTER_IMP[] /* Impulse response */ = { +32767, +32766, +32764, +32760, +32755, +32749, +32741, +32731, +32721, +32708, +32695, +32679, +32663, +32645, +32625, +32604, +32582, +32558, +32533, +32506, +32478, +32448, +32417, +32385, +32351, +32316, +32279, +32241, +32202, +32161, +32119, +32075, +32030, +31984, +31936, +31887, +31836, +31784, +31731, +31676, +31620, +31563, +31504, +31444, +31383, +31320, +31256, +31191, +31124, +31056, +30987, +30916, +30845, +30771, +30697, +30621, +30544, +30466, +30387, +30306, +30224, +30141, +30057, +29971, +29884, +29796, +29707, +29617, +29525, +29433, +29339, +29244, +29148, +29050, +28952, +28852, +28752, +28650, +28547, +28443, +28338, +28232, +28125, +28017, +27908, +27797, +27686, +27574, +27461, +27346, +27231, +27115, +26998, +26879, +26760, +26640, +26519, +26398, +26275, +26151, +26027, +25901, +25775, +25648, +25520, +25391, +25262, +25131, +25000, +24868, +24735, +24602, +24467, +24332, +24197, +24060, +23923, +23785, +23647, +23507, +23368, +23227, +23086, +22944, +22802, +22659, +22515, +22371, +22226, +22081, +21935, +21789, +21642, +21494, +21346, +21198, +21049, +20900, +20750, +20600, +20449, +20298, +20146, +19995, +19842, +19690, +19537, +19383, +19230, +19076, +18922, +18767, +18612, +18457, +18302, +18146, +17990, +17834, +17678, +17521, +17365, +17208, +17051, +16894, +16737, +16579, +16422, +16264, +16106, +15949, +15791, +15633, +15475, +15317, +15159, +15001, +14843, +14685, +14527, +14369, +14212, +14054, +13896, +13739, +13581, +13424, +13266, +13109, +12952, +12795, +12639, +12482, +12326, +12170, +12014, +11858, +11703, +11548, +11393, +11238, +11084, +10929, +10776, +10622, +10469, +10316, +10164, +10011, +9860, +9708, +9557, +9407, +9256, +9106, +8957, +8808, +8659, +8511, +8364, +8216, +8070, +7924, +7778, +7633, +7488, +7344, +7200, +7057, +6914, +6773, +6631, +6490, +6350, +6210, +6071, +5933, +5795, +5658, +5521, +5385, +5250, +5115, +4981, +4848, +4716, +4584, +4452, +4322, +4192, +4063, +3935, +3807, +3680, +3554, +3429, +3304, +3180, +3057, +2935, +2813, +2692, +2572, +2453, +2335, +2217, +2101, +1985, +1870, +1755, +1642, +1529, +1418, +1307, +1197, +1088, +979, +872, +765, +660, +555, +451, +348, +246, +145, +44, +-54, +-153, +-250, +-347, +-443, +-537, +-631, +-724, +-816, +-908, +-998, +-1087, +-1175, +-1263, +-1349, +-1435, +-1519, +-1603, +-1685, +-1767, +-1848, +-1928, +-2006, +-2084, +-2161, +-2237, +-2312, +-2386, +-2459, +-2531, +-2603, +-2673, +-2742, +-2810, +-2878, +-2944, +-3009, +-3074, +-3137, +-3200, +-3261, +-3322, +-3381, +-3440, +-3498, +-3554, +-3610, +-3665, +-3719, +-3772, +-3824, +-3875, +-3925, +-3974, +-4022, +-4069, +-4116, +-4161, +-4205, +-4249, +-4291, +-4333, +-4374, +-4413, +-4452, +-4490, +-4527, +-4563, +-4599, +-4633, +-4666, +-4699, +-4730, +-4761, +-4791, +-4820, +-4848, +-4875, +-4901, +-4926, +-4951, +-4974, +-4997, +-5019, +-5040, +-5060, +-5080, +-5098, +-5116, +-5133, +-5149, +-5164, +-5178, +-5192, +-5205, +-5217, +-5228, +-5238, +-5248, +-5257, +-5265, +-5272, +-5278, +-5284, +-5289, +-5293, +-5297, +-5299, +-5301, +-5303, +-5303, +-5303, +-5302, +-5300, +-5298, +-5295, +-5291, +-5287, +-5282, +-5276, +-5270, +-5263, +-5255, +-5246, +-5237, +-5228, +-5217, +-5206, +-5195, +-5183, +-5170, +-5157, +-5143, +-5128, +-5113, +-5097, +-5081, +-5064, +-5047, +-5029, +-5010, +-4991, +-4972, +-4952, +-4931, +-4910, +-4889, +-4867, +-4844, +-4821, +-4797, +-4774, +-4749, +-4724, +-4699, +-4673, +-4647, +-4620, +-4593, +-4566, +-4538, +-4510, +-4481, +-4452, +-4422, +-4393, +-4363, +-4332, +-4301, +-4270, +-4238, +-4206, +-4174, +-4142, +-4109, +-4076, +-4042, +-4009, +-3975, +-3940, +-3906, +-3871, +-3836, +-3801, +-3765, +-3729, +-3693, +-3657, +-3620, +-3584, +-3547, +-3510, +-3472, +-3435, +-3397, +-3360, +-3322, +-3283, +-3245, +-3207, +-3168, +-3129, +-3091, +-3052, +-3013, +-2973, +-2934, +-2895, +-2855, +-2816, +-2776, +-2736, +-2697, +-2657, +-2617, +-2577, +-2537, +-2497, +-2457, +-2417, +-2377, +-2337, +-2297, +-2256, +-2216, +-2176, +-2136, +-2096, +-2056, +-2016, +-1976, +-1936, +-1896, +-1856, +-1817, +-1777, +-1737, +-1698, +-1658, +-1619, +-1579, +-1540, +-1501, +-1462, +-1423, +-1384, +-1345, +-1306, +-1268, +-1230, +-1191, +-1153, +-1115, +-1077, +-1040, +-1002, +-965, +-927, +-890, +-854, +-817, +-780, +-744, +-708, +-672, +-636, +-600, +-565, +-530, +-494, +-460, +-425, +-391, +-356, +-322, +-289, +-255, +-222, +-189, +-156, +-123, +-91, +-59, +-27, +4, +35, +66, +97, +127, +158, +188, +218, +247, +277, +306, +334, +363, +391, +419, +447, +474, +501, +528, +554, +581, +606, +632, +657, +683, +707, +732, +756, +780, +803, +827, +850, +872, +895, +917, +939, +960, +981, +1002, +1023, +1043, +1063, +1082, +1102, +1121, +1139, +1158, +1176, +1194, +1211, +1228, +1245, +1262, +1278, +1294, +1309, +1325, +1340, +1354, +1369, +1383, +1397, +1410, +1423, +1436, +1448, +1461, +1473, +1484, +1496, +1507, +1517, +1528, +1538, +1548, +1557, +1566, +1575, +1584, +1592, +1600, +1608, +1616, +1623, +1630, +1636, +1643, +1649, +1654, +1660, +1665, +1670, +1675, +1679, +1683, +1687, +1690, +1694, +1697, +1700, +1702, +1704, +1706, +1708, +1709, +1711, +1712, +1712, +1713, +1713, +1713, +1713, +1712, +1711, +1710, +1709, +1708, +1706, +1704, +1702, +1700, +1697, +1694, +1691, +1688, +1685, +1681, +1677, +1673, +1669, +1664, +1660, +1655, +1650, +1644, +1639, +1633, +1627, +1621, +1615, +1609, +1602, +1596, +1589, +1582, +1575, +1567, +1560, +1552, +1544, +1536, +1528, +1520, +1511, +1503, +1494, +1485, +1476, +1467, +1458, +1448, +1439, +1429, +1419, +1409, +1399, +1389, +1379, +1368, +1358, +1347, +1337, +1326, +1315, +1304, +1293, +1282, +1271, +1260, +1248, +1237, +1225, +1213, +1202, +1190, +1178, +1166, +1154, +1142, +1130, +1118, +1106, +1094, +1081, +1069, +1057, +1044, +1032, +1019, +1007, +994, +981, +969, +956, +943, +931, +918, +905, +892, +879, +867, +854, +841, +828, +815, +802, +790, +777, +764, +751, +738, +725, +713, +700, +687, +674, +662, +649, +636, +623, +611, +598, +585, +573, +560, +548, +535, +523, +510, +498, +486, +473, +461, +449, +437, +425, +413, +401, +389, +377, +365, +353, +341, +330, +318, +307, +295, +284, +272, +261, +250, +239, +228, +217, +206, +195, +184, +173, +163, +152, +141, +131, +121, +110, +100, +90, +80, +70, +60, +51, +41, +31, +22, +12, +3, +-5, +-14, +-23, +-32, +-41, +-50, +-59, +-67, +-76, +-84, +-93, +-101, +-109, +-117, +-125, +-133, +-140, +-148, +-156, +-163, +-170, +-178, +-185, +-192, +-199, +-206, +-212, +-219, +-226, +-232, +-239, +-245, +-251, +-257, +-263, +-269, +-275, +-280, +-286, +-291, +-297, +-302, +-307, +-312, +-317, +-322, +-327, +-332, +-336, +-341, +-345, +-349, +-354, +-358, +-362, +-366, +-369, +-373, +-377, +-380, +-384, +-387, +-390, +-394, +-397, +-400, +-402, +-405, +-408, +-411, +-413, +-416, +-418, +-420, +-422, +-424, +-426, +-428, +-430, +-432, +-433, +-435, +-436, +-438, +-439, +-440, +-442, +-443, +-444, +-445, +-445, +-446, +-447, +-447, +-448, +-448, +-449, +-449, +-449, +-449, +-449, +-449, +-449, +-449, +-449, +-449, +-449, +-448, +-448, +-447, +-447, +-446, +-445, +-444, +-443, +-443, +-442, +-441, +-440, +-438, +-437, +-436, +-435, +-433, +-432, +-430, +-429, +-427, +-426, +-424, +-422, +-420, +-419, +-417, +-415, +-413, +-411, +-409, +-407, +-405, +-403, +-400, +-398, +-396, +-393, +-391, +-389, +-386, +-384, +-381, +-379, +-376, +-374, +-371, +-368, +-366, +-363, +-360, +-357, +-355, +-352, +-349, +-346, +-343, +-340, +-337, +-334, +-331, +-328, +-325, +-322, +-319, +-316, +-313, +-310, +-307, +-304, +-301, +-298, +-294, +-291, +-288, +-285, +-282, +-278, +-275, +-272, +-269, +-265, +-262, +-259, +-256, +-252, +-249, +-246, +-243, +-239, +-236, +-233, +-230, +-226, +-223, +-220, +-217, +-213, +-210, +-207, +-204, +-200, +-197, +-194, +-191, +-187, +-184, +-181, +-178, +-175, +-172, +-168, +-165, +-162, +-159, +-156, +-153, +-150, +-147, +-143, +-140, +-137, +-134, +-131, +-128, +-125, +-122, +-120, +-117, +-114, +-111, +-108, +-105, +-102, +-99, +-97, +-94, +-91, +-88, +-86, +-83, +-80, +-78, +-75, +-72, +-70, +-67, +-65, +-62, +-59, +-57, +-55, +-52, +-50, +-47, +-45, +-43, +-40, +-38, +-36, +-33, +-31, +-29, +-27, +-25, +-22, +-20, +-18, +-16, +-14, +-12, +-10, +-8, +-6, +-4, +-2, +0, +0, +2, +4, +6, +8, +9, +11, +13, +14, +16, +17, +19, +21, +22, +24, +25, +27, +28, +29, +31, +32, +33, +35, +36, +37, +38, +40, +41, +42, +43, +44, +45, +46, +47, +48, +49, +50, +51, +52, +53, +54, +55, +56, +56, +57, +58, +59, +59, +60, +61, +62, +62, +63, +63, +64, +64, +65, +66, +66, +66, +67, +67, +68, +68, +69, +69, +69, +70, +70, +70, +70, +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, +72, +71, +71, +71, +71, +71, +70, +70, +70, +70, +69, +69, +69, +69, +68, +68, +68, +67, +67, +67, +66, +66, +66, +65, +65, +64, +64, +64, +63, +63, +62, +62, +62, +61, +61, +60, +60, +59, +59, +58, +58, +58, +57, +57, +56, +56, +55, +55, +54, +54, +53, +53, +52, +52, +51, +51, +50, +50, +49, +48, +48, +47, +47, +46, +46, +45, +45, +44, +44, +43, +43, +42, +42, +41, +41, +40, +39, +39, +38, +38, +37, +37, +36, +36, +35, +35, +34, +34, +33, +33, +32, +32, +31, +31, +30, +30, +29, +29, +28, +28, +27, +27, +26, +26, +25, +25, +24, +24, +23, +23, +23, +22, +22, +21, +21, +20, +20, +20, +19, +19, +18, +18, +17, +17, +17, +16, +16, +15, +15, +15, +14, +14, +14, +13, +13, +12, +12, +12, +11, +11, +11, +10, +10, +10, +9, +9, +9, +9, +8, +8, +8, +7, +7, +7, +7, +6, +6, +6, +6, +5, +5, +5, +5, +4, +4, +4, +4, +3, +3, +3, +3, +3, +2, +2, +2, +2, +2, +1, +1, +1, +1, +1, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1, +-1 +}; + +static HWORD SMALL_FILTER_IMPD[] = { +-1, +-2, +-4, +-5, +-6, +-8, +-10, +-10, +-13, +-13, +-16, +-16, +-18, +-20, +-21, +-22, +-24, +-25, +-27, +-28, +-30, +-31, +-32, +-34, +-35, +-37, +-38, +-39, +-41, +-42, +-44, +-45, +-46, +-48, +-49, +-51, +-52, +-53, +-55, +-56, +-57, +-59, +-60, +-61, +-63, +-64, +-65, +-67, +-68, +-69, +-71, +-71, +-74, +-74, +-76, +-77, +-78, +-79, +-81, +-82, +-83, +-84, +-86, +-87, +-88, +-89, +-90, +-92, +-92, +-94, +-95, +-96, +-98, +-98, +-100, +-100, +-102, +-103, +-104, +-105, +-106, +-107, +-108, +-109, +-111, +-111, +-112, +-113, +-115, +-115, +-116, +-117, +-119, +-119, +-120, +-121, +-121, +-123, +-124, +-124, +-126, +-126, +-127, +-128, +-129, +-129, +-131, +-131, +-132, +-133, +-133, +-135, +-135, +-135, +-137, +-137, +-138, +-138, +-140, +-139, +-141, +-141, +-142, +-142, +-143, +-144, +-144, +-145, +-145, +-146, +-146, +-147, +-148, +-148, +-148, +-149, +-149, +-150, +-150, +-151, +-151, +-152, +-151, +-153, +-152, +-153, +-154, +-153, +-154, +-154, +-155, +-155, +-155, +-155, +-156, +-156, +-156, +-156, +-157, +-156, +-157, +-157, +-157, +-157, +-158, +-157, +-158, +-158, +-157, +-158, +-158, +-158, +-158, +-158, +-158, +-158, +-158, +-158, +-158, +-157, +-158, +-158, +-157, +-158, +-157, +-158, +-157, +-157, +-157, +-156, +-157, +-156, +-156, +-156, +-156, +-155, +-155, +-155, +-155, +-154, +-155, +-153, +-154, +-153, +-153, +-152, +-153, +-151, +-152, +-151, +-150, +-151, +-150, +-149, +-149, +-149, +-148, +-147, +-148, +-146, +-146, +-146, +-145, +-145, +-144, +-144, +-143, +-143, +-141, +-142, +-141, +-140, +-140, +-139, +-138, +-138, +-137, +-137, +-136, +-135, +-135, +-134, +-133, +-132, +-132, +-132, +-130, +-130, +-129, +-128, +-128, +-127, +-126, +-125, +-125, +-124, +-123, +-122, +-122, +-121, +-120, +-119, +-118, +-118, +-116, +-116, +-115, +-115, +-113, +-113, +-111, +-111, +-110, +-109, +-109, +-107, +-107, +-105, +-105, +-104, +-103, +-102, +-101, +-101, +-98, +-99, +-97, +-97, +-96, +-94, +-94, +-93, +-92, +-92, +-90, +-89, +-88, +-88, +-86, +-86, +-84, +-84, +-82, +-82, +-81, +-80, +-78, +-78, +-77, +-76, +-75, +-74, +-73, +-72, +-72, +-70, +-69, +-68, +-68, +-66, +-65, +-65, +-63, +-63, +-61, +-61, +-59, +-59, +-58, +-56, +-56, +-55, +-54, +-53, +-52, +-51, +-50, +-49, +-48, +-47, +-47, +-45, +-44, +-44, +-42, +-42, +-41, +-39, +-39, +-38, +-37, +-36, +-36, +-34, +-33, +-33, +-31, +-31, +-30, +-29, +-28, +-27, +-26, +-25, +-25, +-23, +-23, +-22, +-21, +-20, +-20, +-18, +-18, +-17, +-16, +-15, +-14, +-14, +-13, +-12, +-11, +-10, +-10, +-9, +-8, +-7, +-6, +-6, +-5, +-4, +-4, +-2, +-2, +-2, +0, +0, +1, +2, +2, +3, +4, +4, +5, +6, +6, +7, +8, +9, +9, +9, +11, +11, +11, +12, +13, +13, +14, +15, +15, +16, +16, +17, +17, +18, +19, +19, +19, +20, +21, +21, +21, +22, +23, +23, +24, +23, +25, +25, +25, +26, +26, +27, +27, +27, +28, +28, +29, +29, +30, +29, +30, +31, +31, +31, +32, +32, +32, +32, +33, +33, +34, +33, +34, +35, +34, +35, +35, +35, +36, +36, +36, +36, +37, +36, +37, +37, +38, +37, +38, +37, +38, +39, +38, +38, +39, +39, +38, +39, +39, +40, +39, +39, +40, +39, +40, +40, +39, +40, +40, +40, +40, +40, +40, +40, +40, +40, +40, +41, +40, +40, +40, +40, +40, +40, +40, +40, +40, +40, +39, +40, +40, +39, +40, +39, +40, +39, +39, +39, +39, +39, +39, +39, +38, +38, +39, +38, +38, +38, +37, +38, +37, +38, +37, +36, +37, +37, +36, +36, +36, +36, +36, +35, +35, +36, +34, +35, +34, +35, +34, +33, +34, +33, +33, +33, +33, +32, +32, +32, +31, +31, +31, +31, +30, +31, +30, +30, +29, +30, +29, +28, +29, +28, +28, +28, +27, +27, +27, +26, +27, +25, +26, +25, +26, +24, +25, +24, +24, +23, +24, +23, +22, +23, +22, +22, +21, +21, +21, +21, +20, +20, +19, +20, +19, +18, +19, +18, +18, +17, +17, +17, +17, +16, +16, +15, +16, +15, +14, +15, +14, +14, +13, +13, +13, +12, +13, +12, +11, +12, +11, +10, +11, +10, +10, +9, +9, +9, +9, +8, +8, +8, +8, +7, +7, +6, +7, +6, +5, +6, +5, +5, +5, +4, +4, +4, +3, +4, +3, +3, +2, +2, +2, +2, +1, +2, +1, +0, +1, +0, +0, +0, +-1, +-1, +-1, +-1, +-1, +-2, +-2, +-2, +-2, +-3, +-3, +-3, +-3, +-3, +-4, +-4, +-4, +-4, +-5, +-4, +-5, +-5, +-6, +-5, +-6, +-6, +-6, +-6, +-6, +-7, +-6, +-7, +-7, +-7, +-8, +-7, +-8, +-8, +-8, +-8, +-8, +-9, +-8, +-9, +-9, +-9, +-9, +-9, +-10, +-9, +-10, +-10, +-10, +-10, +-10, +-10, +-11, +-10, +-11, +-10, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-12, +-11, +-12, +-12, +-11, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-13, +-12, +-12, +-13, +-12, +-13, +-12, +-13, +-13, +-12, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-12, +-13, +-13, +-12, +-13, +-12, +-13, +-12, +-13, +-12, +-12, +-13, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-11, +-12, +-11, +-12, +-11, +-12, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-10, +-11, +-11, +-10, +-10, +-11, +-10, +-10, +-10, +-10, +-10, +-9, +-10, +-10, +-9, +-10, +-9, +-8, +-9, +-9, +-9, +-9, +-9, +-9, +-8, +-9, +-8, +-9, +-8, +-8, +-8, +-8, +-8, +-7, +-8, +-8, +-7, +-7, +-8, +-7, +-7, +-7, +-7, +-6, +-7, +-7, +-6, +-7, +-6, +-6, +-6, +-6, +-6, +-6, +-5, +-6, +-5, +-6, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-4, +-5, +-4, +-4, +-5, +-4, +-4, +-4, +-3, +-4, +-4, +-3, +-4, +-3, +-3, +-4, +-3, +-3, +-2, +-3, +-3, +-3, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-2, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +1, +0, +1, +1, +1, +1, +0, +1, +1, +1, +2, +1, +1, +1, +2, +1, +2, +1, +2, +1, +2, +2, +2, +1, +2, +2, +2, +2, +2, +2, +2, +2, +3, +2, +2, +3, +2, +2, +3, +2, +3, +2, +3, +2, +3, +3, +2, +3, +3, +3, +2, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +4, +3, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +3, +3, +4, +3, +3, +3, +3, +3, +3, +3, +4, +3, +3, +3, +3, +3, +3, +3, +2, +3, +3, +3, +3, +3, +3, +3, +2, +3, +3, +3, +2, +3, +3, +2, +3, +3, +2, +3, +2, +3, +3, +2, +2, +3, +2, +3, +2, +2, +3, +2, +2, +3, +2, +2, +2, +2, +3, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +0, +2, +2, +2, +2, +1, +2, +2, +1, +2, +1, +2, +2, +1, +2, +1, +2, +1, +1, +2, +1, +1, +2, +1, +1, +1, +2, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +0, +1, +1, +1, +0, +1, +0, +1, +0, +1, +1, +0, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +-1, +-2, +-4, +-5, +-6, +-8, +-10, +-10, +-13, +-13, +-16, +-16, +-18, +-20, +-21, +-22, +-24, +-25, +-27, +-28, +-30, +-31, +-32, +-34, +-35, +-37, +-38, +-39, +-41, +-42, +-44, +-45, +-46, +-48, +-49, +-51, +-52, +-53, +-55, +-56, +-57, +-59, +-60, +-61, +-63, +-64, +-65, +-67, +-68, +-69, +-71, +-71, +-74, +-74, +-76, +-77, +-78, +-79, +-81, +-82, +-83, +-84, +-86, +-87, +-88, +-89, +-90, +-92, +-92, +-94, +-95, +-96, +-98, +-98, +-100, +-100, +-102, +-103, +-104, +-105, +-106, +-107, +-108, +-109, +-111, +-111, +-112, +-113, +-115, +-115, +-116, +-117, +-119, +-119, +-120, +-121, +-121, +-123, +-124, +-124, +-126, +-126, +-127, +-128, +-129, +-129, +-131, +-131, +-132, +-133, +-133, +-135, +-135, +-135, +-137, +-137, +-138, +-138, +-140, +-139, +-141, +-141, +-142, +-142, +-143, +-144, +-144, +-145, +-145, +-146, +-146, +-147, +-148, +-148, +-148, +-149, +-149, +-150, +-150, +-151, +-151, +-152, +-151, +-153, +-152, +-153, +-154, +-153, +-154, +-154, +-155, +-155, +-155, +-155, +-156, +-156, +-156, +-156, +-157, +-156, +-157, +-157, +-157, +-157, +-158, +-157, +-158, +-158, +-157, +-158, +-158, +-158, +-158, +-158, +-158, +-158, +-158, +-158, +-158, +-157, +-158, +-158, +-157, +-158, +-157, +-158, +-157, +-157, +-157, +-156, +-157, +-156, +-156, +-156, +-156, +-155, +-155, +-155, +-155, +-154, +-155, +-153, +-154, +-153, +-153, +-152, +-153, +-151, +-152, +-151, +-150, +-151, +-150, +-149, +-149, +-149, +-148, +-147, +-148, +-146, +-146, +-146, +-145, +-145, +-144, +-144, +-143, +-143, +-141, +-142, +-141, +-140, +-140, +-139, +-138, +-138, +-137, +-137, +-136, +-135, +-135, +-134, +-133, +-132, +-132, +-132, +-130, +-130, +-129, +-128, +-128, +-127, +-126, +-125, +-125, +-124, +-123, +-122, +-122, +-121, +-120, +-119, +-118, +-118, +-116, +-116, +-115, +-115, +-113, +-113, +-111, +-111, +-110, +-109, +-109, +-107, +-107, +-105, +-105, +-104, +-103, +-102, +-101, +-101, +-98, +-99, +-97, +-97, +-96, +-94, +-94, +-93, +-92, +-92, +-90, +-89, +-88, +-88, +-86, +-86, +-84, +-84, +-82, +-82, +-81, +-80, +-78, +-78, +-77, +-76, +-75, +-74, +-73, +-72, +-72, +-70, +-69, +-68, +-68, +-66, +-65, +-65, +-63, +-63, +-61, +-61, +-59, +-59, +-58, +-56, +-56, +-55, +-54, +-53, +-52, +-51, +-50, +-49, +-48, +-47, +-47, +-45, +-44, +-44, +-42, +-42, +-41, +-39, +-39, +-38, +-37, +-36, +-36, +-34, +-33, +-33, +-31, +-31, +-30, +-29, +-28, +-27, +-26, +-25, +-25, +-23, +-23, +-22, +-21, +-20, +-20, +-18, +-18, +-17, +-16, +-15, +-14, +-14, +-13, +-12, +-11, +-10, +-10, +-9, +-8, +-7, +-6, +-6, +-5, +-4, +-4, +-2, +-2, +-2, +0, +0, +1, +2, +2, +3, +4, +4, +5, +6, +6, +7, +8, +9, +9, +9, +11, +11, +11, +12, +13, +13, +14, +15, +15, +16, +16, +17, +17, +18, +19, +19, +19, +20, +21, +21, +21, +22, +23, +23, +24, +23, +25, +25, +25, +26, +26, +27, +27, +27, +28, +28, +29, +29, +30, +29, +30, +31, +31, +31, +32, +32, +32, +32, +33, +33, +34, +33, +34, +35, +34, +35, +35, +35, +36, +36, +36, +36, +37, +36, +37, +37, +38, +37, +38, +37, +38, +39, +38, +38, +39, +39, +38, +39, +39, +40, +39, +39, +40, +39, +40, +40, +39, +40, +40, +40, +40, +40, +40, +40, +40, +40, +40, +41, +40, +40, +40, +40, +40, +40, +40, +40, +40, +40, +39, +40, +40, +39, +40, +39, +40, +39, +39, +39, +39, +39, +39, +39, +38, +38, +39, +38, +38, +38, +37, +38, +37, +38, +37, +36, +37, +37, +36, +36, +36, +36, +36, +35, +35, +36, +34, +35, +34, +35, +34, +33, +34, +33, +33, +33, +33, +32, +32, +32, +31, +31, +31, +31, +30, +31, +30, +30, +29, +30, +29, +28, +29, +28, +28, +28, +27, +27, +27, +26, +27, +25, +26, +25, +26, +24, +25, +24, +24, +23, +24, +23, +22, +23, +22, +22, +21, +21, +21, +21, +20, +20, +19, +20, +19, +18, +19, +18, +18, +17, +17, +17, +17, +16, +16, +15, +16, +15, +14, +15, +14, +14, +13, +13, +13, +12, +13, +12, +11, +12, +11, +10, +11, +10, +10, +9, +9, +9, +9, +8, +8, +8, +8, +7, +7, +6, +7, +6, +5, +6, +5, +5, +5, +4, +4, +4, +3, +4, +3, +3, +2, +2, +2, +2, +1, +2, +1, +0, +1, +0, +0, +0, +-1, +-1, +-1, +-1, +-1, +-2, +-2, +-2, +-2, +-3, +-3, +-3, +-3, +-3, +-4, +-4, +-4, +-4, +-5, +-4, +-5, +-5, +-6, +-5, +-6, +-6, +-6, +-6, +-6, +-7, +-6, +-7, +-7, +-7, +-8, +-7, +-8, +-8, +-8, +-8, +-8, +-9, +-8, +-9, +-9, +-9, +-9, +-9, +-10, +-9, +-10, +-10, +-10, +-10, +-10, +-10, +-11, +-10, +-11, +-10, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-12, +-11, +-12, +-12, +-11, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-13, +-12, +-12, +-13, +-12, +-13, +-12, +-13, +-13, +-12, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-12, +-13, +-13, +-13, +-12, +-13, +-13, +-12, +-13, +-12, +-13, +-12, +-13, +-12, +-12, +-13, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-12, +-11, +-12, +-11, +-12, +-11, +-12, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-11, +-10, +-11, +-11, +-10, +-10, +-11, +-10, +-10, +-10, +-10, +-10, +-9, +-10, +-10, +-9, +-10, +-9, +-8, +-9, +-9, +-9, +-9, +-9, +-9, +-8, +-9, +-8, +-9, +-8, +-8, +-8, +-8, +-8, +-7, +-8, +-8, +-7, +-7, +-8, +-7, +-7, +-7, +-7, +-6, +-7, +-7, +-6, +-7, +-6, +-6, +-6, +-6, +-6, +-6, +-5, +-6, +-5, +-6, +-5, +-5, +-5, +-5, +-5, +-5, +-5, +-4, +-5, +-4, +-4, +-5, +-4, +-4, +-4, +-3, +-4, +-4, +-3, +-4, +-3, +-3, +-4, +-3, +-3, +-2, +-3, +-3, +-3, +-2, +-3, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-2, +-1, +-2, +-1, +-2, +-1, +-1, +-2, +-1, +-1, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +1, +0, +1, +1, +1, +1, +0, +1, +1, +1, +2, +1, +1, +1, +2, +1, +2, +1, +2, +1, +2, +2, +2, +1, +2, +2, +2, +2, +2, +2, +2, +2, +3, +2, +2, +3, +2, +2, +3, +2, +3, +2, +3, +2, +3, +3, +2, +3, +3, +3, +2, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +3, +4, +3, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +4, +3, +3, +3, +3, +3, +4, +3, +3, +3, +3, +3, +3, +3, +4, +3, +3, +3, +3, +3, +3, +3, +2, +3, +3, +3, +3, +3, +3, +3, +2, +3, +3, +3, +2, +3, +3, +2, +3, +3, +2, +3, +2, +3, +3, +2, +2, +3, +2, +3, +2, +2, +3, +2, +2, +3, +2, +2, +2, +2, +3, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +2, +0, +2, +2, +2, +2, +1, +2, +2, +1, +2, +1, +2, +2, +1, +2, +1, +2, +1, +1, +2, +1, +1, +2, +1, +1, +1, +2, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +1, +0, +1, +1, +1, +0, +1, +1, +1, +0, +1, +0, +1, +0, +1, +1, +0, +0, +1, +0, +1, +0, +1, +0, +0, +1, +0, +0, +0, +1, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +-1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +1 +}; diff --git a/pjsip-apps/src/pjsua/main.c b/pjsip-apps/src/pjsua/main.c index 08f0a380..1b0074b4 100644 --- a/pjsip-apps/src/pjsua/main.c +++ b/pjsip-apps/src/pjsua/main.c @@ -384,8 +384,10 @@ static void conf_list(void) pj_ansi_strcat(txlist, s); } } - printf("Port #%02d %20.*s transmitting to: %s\n", + printf("Port #%02d[%2dKHz/%dms] %20.*s transmitting to: %s\n", port_info->slot, + port_info->clock_rate/1000, + port_info->samples_per_frame * 1000 / port_info->clock_rate, (int)port_info->name.slen, port_info->name.ptr, txlist); diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h index d120a062..1ed8f3af 100644 --- a/pjsip/include/pjsua-lib/pjsua.h +++ b/pjsip/include/pjsua-lib/pjsua.h @@ -177,6 +177,7 @@ struct pjsua /* Media: */ int start_rtp_port;/**< Start of RTP port to try. */ pjmedia_endpt *med_endpt; /**< Media endpoint. */ + unsigned clock_rate; /**< Internal clock rate. */ pjmedia_conf *mconf; /**< Media conference. */ pj_bool_t null_audio; /**< Null audio flag. */ char *wav_file; /**< WAV file name to play. */ diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c index 081a3a87..e944ea42 100644 --- a/pjsip/src/pjsua-lib/pjsua_core.c +++ b/pjsip/src/pjsua-lib/pjsua_core.c @@ -72,6 +72,9 @@ void pjsua_default(void) /* Default: do not use STUN: */ pjsua.stun_port1 = pjsua.stun_port2 = 0; + /* Default: sampling rate is 8000 */ + pjsua.clock_rate = 8000; + /* Init accounts: */ pjsua.acc_cnt = 1; for (i=0; i<PJ_ARRAY_SIZE(pjsua.acc); ++i) { @@ -618,7 +621,9 @@ pj_status_t pjsua_start(void) status = pjmedia_conf_create(pjsua.pool, pjsua.max_calls+PJSUA_CONF_MORE_PORTS, - 8000, 160, 16, &pjsua.mconf); + pjsua.clock_rate, + pjsua.clock_rate * 20 / 1000, 16, + &pjsua.mconf); if (status != PJ_SUCCESS) { pj_caching_pool_destroy(&pjsua.cp); pjsua_perror(THIS_FILE, diff --git a/pjsip/src/pjsua-lib/pjsua_settings.c b/pjsip/src/pjsua-lib/pjsua_settings.c index e861f5c6..9e1d3ff8 100644 --- a/pjsip/src/pjsua-lib/pjsua_settings.c +++ b/pjsip/src/pjsua-lib/pjsua_settings.c @@ -83,6 +83,8 @@ static void usage(void) puts(" --use-stun2=host[:port] Resolve local IP with the specified STUN servers"); puts(""); puts("Media Options:"); + puts(" --wb Enable wideband codecs (16KHz)"); + puts(" --uwb Enable ultra-wideband codecs (32KHz)"); puts(" --null-audio Use NULL audio device"); puts(" --play-file=file Play WAV file in conference bridge"); puts(" --auto-play Automatically play the file (to incoming calls only)"); @@ -218,7 +220,7 @@ pj_status_t pjsua_parse_args(int argc, char *argv[]) OPT_ADD_BUDDY, OPT_OFFER_X_MS_MSG, OPT_NO_PRESENCE, OPT_AUTO_ANSWER, OPT_AUTO_HANGUP, OPT_AUTO_PLAY, OPT_AUTO_LOOP, OPT_AUTO_CONF, - OPT_PLAY_FILE, OPT_RTP_PORT, + OPT_PLAY_FILE, OPT_WB, OPT_UWB, OPT_RTP_PORT, OPT_NEXT_ACCOUNT, OPT_NEXT_CRED, OPT_MAX_CALLS, }; struct option long_options[] = { @@ -228,6 +230,8 @@ pj_status_t pjsua_parse_args(int argc, char *argv[]) { "app-log-level",1,0,OPT_APP_LOG_LEVEL}, { "help", 0, 0, OPT_HELP}, { "version", 0, 0, OPT_VERSION}, + { "wb", 0, 0, OPT_WB}, + { "uwb", 0, 0, OPT_UWB}, { "null-audio", 0, 0, OPT_NULL_AUDIO}, { "local-port", 1, 0, OPT_LOCAL_PORT}, { "proxy", 1, 0, OPT_PROXY}, @@ -327,6 +331,14 @@ pj_status_t pjsua_parse_args(int argc, char *argv[]) pjsua.null_audio = 1; break; + case OPT_WB: + pjsua.clock_rate = 16000; + break; + + case OPT_UWB: + pjsua.clock_rate = 32000; + break; + case OPT_LOCAL_PORT: /* local-port */ lval = pj_strtoul(pj_cstr(&tmp, optarg)); if (lval < 1 || lval > 65535) { |