SHRT_MAX) {
output[n*getChannel()+c] = SHRT_MAX;
} else if (tmp < SHRT_MIN) {
output[n*getChannel()+c] = SHRT_MIN;
} else {
output[n*getChannel()+c] = (short) tmp;
}
}
}
// Didn't get as many samples as we wanted ?
if (getChannel() == 2 && samples_read[0] != samples_read[1]) {
Reporter::reportEvent( 2,
"Warning: Read a different number of samples "
"for left and right channels");
}
// Return the number of bytes put in the output buffer
return samples_read[0] * 2 * getChannel();
}
/*------------------------------------------------------------------------------
* Close the audio source
*----------------------------------------------------------------------------*/
void
JackDspSource :: close ( void ) throw ( Exception )
{
unsigned int i;
if ( !isOpen() ) {
return;
}
for(i = 0; i < getChannel(); i++) {
// Close the port for channel
if ( ports[i] ) {
jack_port_unregister( client, ports[i] );
ports[i] = NULL;
}
// Free up the ring buffer for channel
if ( rb[i] ) {
jack_ringbuffer_free( rb[i] );
rb[i] = NULL;
}
}
/* Leave the jack graph */
if (client) {
jack_client_close(client);
client = NULL;
}
}
/*------------------------------------------------------------------------------
* Callback called by JACK when audio is available
*
* Don't do anything too expensive here
* - just shove audio samples in ring buffer
*----------------------------------------------------------------------------*/
int
JackDspSource :: process_callback( jack_nframes_t nframes, void *arg )
{
JackDspSource* self = (JackDspSource*)arg;
size_t to_write = sizeof (jack_default_audio_sample_t) * nframes;
unsigned int c;
// Wait until it is ready
if (self->client == NULL) {
return 0;
}
/* copy data to ringbuffer; one per channel */
for (c=0; c < self->getChannel(); c++) {
/* check space */
size_t len;
if (jack_ringbuffer_write_space(self->rb[c]) < to_write) {
/* buffer is overflowing, skip the incoming data */
jack_ringbuffer_write_advance(self->rb[c], to_write);
/* prevent blocking the ring buffer by updating internal pointers
* jack will now not terminate on xruns
*/
Reporter::reportEvent( 1, "ring buffer full, skipping data");
/* We do not return error to jack callback handler and keep going */
} else {
/* buffer has space, put data into ringbuffer */
len = jack_ringbuffer_write(self->rb[c], (char *) jack_port_get_buffer(
self->ports[c], nframes), to_write);
if (len != to_write)
Reporter::reportEvent( 1, "failed to write to ring buffer (can not happen)");
}
}
// Success
return 0;
}
/*------------------------------------------------------------------------------
* Callback called when
*----------------------------------------------------------------------------*/
void
JackDspSource :: shutdown_callback( void *arg )
{
//JackDspSource* self = (JackDspSource*)arg;
Reporter::reportEvent( 1, "JackDspSource :: shutdown_callback");
}
#endif // SUPPORT_JACK_DSP
darkice-1.3/src/FileSink.h 0000644 0001750 0001750 00000017632 12526421577 012370 0000000 0000000 /*------------------------------------------------------------------------------
Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved.
Tyrell DarkIce
File : FileSink.h
Version : $Revision$
Author : $Author$
Location : $HeadURL$
Copyright notice:
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 3
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 FILE_SINK_H
#define FILE_SINK_H
#ifndef __cplusplus
#error This is a C++ include file
#endif
/* ============================================================ include files */
#include "Reporter.h"
#include "Sink.h"
/* ================================================================ constants */
/* =================================================================== macros */
/* =============================================================== data types */
/**
* File data output
*
* @author $Author$
* @version $Revision$
*/
class FileSink : public Sink, public virtual Reporter
{
private:
/**
* The name of the configuration related to
* this file sink. something like "file-0" or "file-2".
*/
char * configName;
/**
* Name of the file represented by the FileSink.
*/
char * fileName;
/**
* Initialize the object.
*
* @param configName the name of the configuration related to
* this file sink. something like "file-0" or "file-2".
* @param name name of the file to be represented by the object.
* @exception Exception
*/
void
init ( const char * configName,
const char * name ) throw ( Exception );
/**
* De-initialize the object.
*
* @exception Exception
*/
void
strip ( void ) throw ( Exception );
/**
* Get the file name to where to move the data saved so far.
* Used in cut().
*
* @return the file name where to move the data saved so far.
* @throws Exception on file operation errors
*/
std::string
getArchiveFileName( void ) throw ( Exception );
protected:
/**
* Low-level file descriptor for the file represented by this object.
*/
int fileDescriptor;
/**
* Default constructor. Always throws an Exception.
*
* @exception Exception
*/
inline
FileSink ( void ) throw ( Exception )
{
throw Exception( __FILE__, __LINE__);
}
public:
/**
* Constructor by a file name.
*
* @param configName the name of the configuration related to
* this file sink. something like "file-0" or "file-2".
* @param name name of the file to be represented by the object.
* @exception Exception
*/
inline
FileSink( const char * configName,
const char * name ) throw ( Exception )
{
init( configName, name);
}
/**
* Copy constructor.
*
* @param fsink the FileSink to copy.
* @exception Exception
*/
FileSink( const FileSink & fsink ) throw ( Exception );
/**
* Destructor.
*
* @exception Exception
*/
inline virtual
~FileSink( void ) throw ( Exception )
{
strip();
}
/**
* Assignment operator.
*
* @param fs the FileSink to assign to this object.
* @return a reference to this object.
* @exception Exception
*/
virtual FileSink &
operator= ( const FileSink & fs ) throw ( Exception );
/**
* Get the file name this FileSink represents.
*
* @return the file name this FileSink represents.
*/
inline const char *
getFileName ( void ) const throw ()
{
return fileName;
}
/**
* Check for the existence of the file this FileSink represents.
*
* @return true if the file exists and is a regular file,
* false otherwise.
*/
virtual bool
exists ( void ) const throw ();
/**
* Create the file.
*
* @return true if creation was successful, false otherwise.
* @exception Exception
*/
virtual bool
create ( void ) throw ( Exception );
/**
* Open the file. Truncates the file.
*
* @return true if opening was successful, false otherwise.
* @exception Exception
*/
virtual bool
open ( void ) throw ( Exception );
/**
* Check if the FileSink is open.
*
* @return true if the FileSink is open, false otherwise.
*/
inline virtual bool
isOpen ( void ) const throw ()
{
return fileDescriptor != 0;
}
/**
* Check if the FileSink is ready to accept data.
* Blocks until the specified time for data to be available.
*
* @param sec the maximum seconds to block.
* @param usec micro seconds to block after the full seconds.
* @return true if the Sink is ready to accept data, false otherwise.
* @exception Exception
*/
virtual bool
canWrite ( unsigned int sec,
unsigned int usec ) throw ( Exception );
/**
* Write data to the FileSink.
*
* @param buf the data to write.
* @param len number of bytes to write from buf.
* @return the number of bytes written (may be less than len).
* @exception Exception
*/
virtual unsigned int
write ( const void * buf,
unsigned int len ) throw ( Exception );
/**
* This is a no-op in this FileSink.
*
* @exception Exception
*/
inline virtual void
flush ( void ) throw ( Exception )
{
}
/**
* Cut what the sink has been doing so far, and start anew.
* This usually means separating the data sent to the sink up
* until now, and start saving a new chunk of data.
*/
virtual void
cut ( void ) throw ();
/**
* Close the FileSink.
*
* @exception Exception
*/
virtual void
close ( void ) throw ( Exception );
};
/* ================================================= external data structures */
/* ====================================================== function prototypes */
#endif /* FILE_SINK_H */
darkice-1.3/src/Sink.h 0000644 0001750 0001750 00000012017 12526421577 011560 0000000 0000000 /*------------------------------------------------------------------------------
Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved.
Tyrell DarkIce
File : Sink.h
Version : $Revision$
Author : $Author$
Location : $HeadURL$
Copyright notice:
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 3
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 SINK_H
#define SINK_H
#ifndef __cplusplus
#error This is a C++ include file
#endif
/* ============================================================ include files */
#include "Referable.h"
#include "Exception.h"
/* ================================================================ constants */
/* =================================================================== macros */
/* =============================================================== data types */
/**
* A general data sink
*
* @author $Author$
* @version $Revision$
*/
class Sink : public virtual Referable
{
private:
protected:
/**
* Default constructor.
*/
inline
Sink ( void ) throw ()
{
}
/**
* Copy constructor.
*
* @param sink the Sink to copy.
*/
inline
Sink ( const Sink & sink ) throw ()
{
}
/**
* Assignment operator.
*
* @param sink the Sink to assign this to.
* @return a reference to this Sink.
* @exception Exception
*/
inline virtual Sink &
operator= ( const Sink & sink ) throw ( Exception )
{
return *this;
}
public:
/**
* Destructor.
*
* @exception Exception
*/
inline virtual
~Sink ( void ) throw ( Exception )
{
}
/**
* Open the sink.
*
* @return true if opening was successfull, false otherwise.
* @exception Exception
*/
virtual bool
open ( void ) throw ( Exception ) = 0;
/**
* Check if the Sink is open.
*
* @return true if the Sink is open, false otherwise.
*/
virtual bool
isOpen ( void ) const throw () = 0;
/**
* Check if the Sink is ready to accept data.
* Blocks until the specified time for data to be available.
*
* @param sec the maximum seconds to block.
* @param usec micro seconds to block after the full seconds.
* @return true if the Sink is ready to accept data, false otherwise.
* @exception Exception
*/
virtual bool
canWrite ( unsigned int sec,
unsigned int usec ) throw ( Exception ) = 0;
/**
* Write data to the Sink.
*
* @param buf the data to write.
* @param len number of bytes to write from buf.
* @return the number of bytes written (may be less than len).
* @exception Exception
*/
virtual unsigned int
write ( const void * buf,
unsigned int len ) throw ( Exception ) = 0;
/**
* Flush all data that was written to the Sink to the underlying
* construct.
*
* @exception Exception
*/
virtual void
flush ( void ) throw ( Exception ) = 0;
/**
* Cut what the sink has been doing so far, and start anew.
* This usually means separating the data sent to the sink up
* until now, and start saving a new chunk of data.
*/
virtual void
cut ( void ) throw () = 0;
/**
* Close the Sink.
*
* @exception Exception
*/
virtual void
close ( void ) throw ( Exception ) = 0;
};
/* ================================================= external data structures */
/* ====================================================== function prototypes */
#endif /* SINK_H */
darkice-1.3/src/Util.h 0000644 0001750 0001750 00000025650 12750450634 011573 0000000 0000000 /*------------------------------------------------------------------------------
Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved.
Tyrell DarkIce
File : Util.h
Version : $Revision$
Author : $Author$
Location : $HeadURL$
Copyright notice:
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 3
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 UTIL_H
#define UTIL_H
#ifndef __cplusplus
#error This is a C++ include file
#endif
/* ============================================================ include files */
#include "Exception.h"
/* ================================================================ constants */
/* =================================================================== macros */
/* =============================================================== data types */
/**
* Widely used utilities.
* This class can not be instantiated, but contains useful (?) static
* functions.
*
* Typical usage:
*
*
* #include "Util.h"
*
* char * str = Util::strDup( otherStr);
*
*
* @author $Author$
* @version $Revision$
*/
class Util
{
private:
/**
* Helper table for base64 encoding.
*/
static char base64Table[];
protected:
/**
* Default constructor. Always throws an Exception.
*
* @exception Exception
*/
inline
Util ( void ) throw ( Exception )
{
throw Exception( __FILE__, __LINE__);
}
/**
* Copy constructor. Always throws an Exception.
*
* @exception Exception
*/
inline
Util ( const Util & e ) throw ( Exception )
{
throw Exception( __FILE__, __LINE__);
}
/**
* Destructor. Always throws an Exception.
*
* @exception Exception
*/
inline
~Util ( void ) throw ( Exception )
{
throw Exception( __FILE__, __LINE__);
}
/**
* Assignment operator. Always throws an Exception.
*
* @param u the object to assign to this one.
* @exception Exception
*/
inline Util &
operator= ( const Util & u ) throw ( Exception )
{
throw Exception( __FILE__, __LINE__);
}
public:
/**
* Determine a C string's length.
*
* @param str a zero-terminated C string.
* @return length of str
* @exception Exception
*/
static unsigned int
strLen ( const char * str ) throw ( Exception );
/**
* Copy a C string into another.
*
* @param dest place for the copy. Storage size must be at least
* Util::strLen(src) + 1 long.
* @param src the string to copy.
* @exception Exception
*/
static void
strCpy ( char * dest,
const char * src ) throw ( Exception );
/**
* Concatenate a string to another's end.
*
* @param dest the string to concatenate to.
* Storage size of dest must be at least
* Util::strLen(dest) + Util::strLen(src) + 1 long.
* @param src the string to concatenate.
* @exception Exception
*/
static void
strCat ( char * dest,
const char * src ) throw ( Exception );
/**
* Duplicate a string by allocating space with new[].
* The returned string must be freed with delete[].
*
* @param str the string to duplicate.
* @exception Exception
*/
static char *
strDup ( const char * str ) throw ( Exception );
/**
* Determine whether two string are equal.
*
* @param str1 one of the strings.
* @param str2 the other string.
* @param len check the first most len characters. if 0, check
* the whole string
* @return true if the two strings are equal, false othersize.
* @exception Exception
*/
static bool
strEq ( const char * str1,
const char * str2,
unsigned int len = 0 ) throw ( Exception );
/**
* Convert a string to long.
*
* @param str the string to convert.
* @return the value of str as a long int
* @exception Exception
*/
static long int
strToL ( const char * str) throw ( Exception );
/**
* Convert a string to double.
*
* @param str the string to convert.
* @return the value of str as a double
* @exception Exception
*/
static double
strToD ( const char * str ) throw ( Exception );
/**
* Add current date to a file name, before the file extension (if any)
*
* @param str the string to convert (file name).
* @return the new string with the date appended before
* extension of the file name. the string has to be
* deleted with delete[] after it is not needed
* @exception Exception
*/
static char *
fileAddDate ( const char * str,
const char * format = "[%m-%d-%Y-%H-%M-%S]" )
throw ( Exception );
/**
* Convert a string into base64 encoding.
* base64 is described in RFC 2045, section 6.8
* The returned string must be freed with delete[].
*
* @param str the string to convert.
* @return the supplied string in base64 encoding.
* @exception Exception
*/
static char *
base64Encode ( const char * str ) throw ( Exception );
/**
* Convert an unsigned char buffer holding 8 or 16 bit PCM values
* with channels interleaved to a short int buffer, still
* with channels interleaved.
*
* @param bitsPerSample the number of bits per sample in the input
* @param pcmBuffer the input buffer
* @param lenPcmBuffer the number of samples total in pcmBuffer
* (e.g. if 2 channel input, this is twice the
* number of sound samples)
* @param outBuffer the output buffer, must be big enough
* @param isBigEndian true if the input is big endian, false otherwise
*/
static void
conv ( unsigned int bitsPerSample,
unsigned char * pcmBuffer,
unsigned int lenPcmBuffer,
short int * outBuffer,
bool isBigEndian = true ) throw ( Exception );
/**
* Convert a short buffer holding PCM values with channels interleaved
* to one or more float buffers, one for each channel
*
* @param shortBuffer the input buffer
* @param lenShortBuffer total length of the input buffer
* @param floatBuffers an array of float buffers, each
* (lenShortBuffer / channels) long
* @param channels number of channels to separate the input to
*/
static void
conv ( short int * shortBuffer,
unsigned int lenShortBuffer,
float ** floatBuffers,
unsigned int channels ) throw ( Exception );
/**
* Convert a char buffer holding 8 bit PCM values to a short buffer
*
* @param pcmBuffer buffer holding 8 bit PCM audio values,
* channels are interleaved
* @param lenPcmBuffer length of pcmBuffer
* @param leftBuffer put the left channel here (must be big enough)
* @param rightBuffer put the right channel here (not touched if mono,
* must be big enough)
* @param channels number of channels (1 = mono, 2 = stereo)
*/
static void
conv8 ( unsigned char * pcmBuffer,
unsigned int lenPcmBuffer,
short int * leftBuffer,
short int * rightBuffer,
unsigned int channels ) throw ( Exception );
/**
* Convert a char buffer holding 16 bit PCM values to a short buffer
*
* @param pcmBuffer buffer holding 16 bit PCM audio values,
* channels are interleaved
* @param lenPcmBuffer length of pcmBuffer
* @param leftBuffer put the left channel here (must be big enough)
* @param rightBuffer put the right channel here (not touched if mono,
* must be big enough)
* @param channels number of channels (1 = mono, 2 = stereo)
* @param isBigEndian true if input is big endian, false otherwise
*/
static void
conv16 ( unsigned char * pcmBuffer,
unsigned int lenPcmBuffer,
short int * leftBuffer,
short int * rightBuffer,
unsigned int channels,
bool isBigEndian ) throw ( Exception );
/**
* Make a thread sleep for specified amount of time.
* Only the thread which this is called in will sleep.
* The SIGUSR1 signal will be blocked during the sleep.
*
* @param sec the number of seconds to sleep.
* @param nsec the number of nano-seconds to sleep.
*/
static void
sleep( long sec,
long nsec);
};
/* ================================================= external data structures */
/* ====================================================== function prototypes */
#endif /* UTIL_H */
darkice-1.3/src/SolarisDspSource.h 0000644 0001750 0001750 00000016703 12526421577 014126 0000000 0000000 /*------------------------------------------------------------------------------
Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved.
Tyrell DarkIce
File : SolarisDspSource.h
Version : $Revision$
Author : $Author$
Location : $HeadURL$
Copyright notice:
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 3
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 SOLARIS_DSP_SOURCE_H
#define SOLARIS_DSP_SOURCE_H
#ifndef __cplusplus
#error This is a C++ include file
#endif
/* ============================================================ include files */
#include "Reporter.h"
#include "AudioSource.h"
/* ================================================================ constants */
/* =================================================================== macros */
/* =============================================================== data types */
/**
* An audio input based on Solaris /dev/audio devices
*
* @author $Author$
* @version $Revision$
*/
class SolarisDspSource : public AudioSource, public virtual Reporter
{
private:
/**
* The file name of the OSS DSP device (e.g. /dev/audio)
*/
char * fileName;
/**
* The low-level file descriptor of the Solaris DSP device.
*/
int fileDescriptor;
protected:
/**
* Default constructor. Always throws an Exception.
*
* @exception Exception
*/
inline
SolarisDspSource ( void ) throw ( Exception )
{
throw Exception( __FILE__, __LINE__);
}
/**
* Initialize the object
*
* @param name the file name of the Solaris DSP device.
* @exception Exception
*/
void
init ( const char * name ) throw ( Exception );
/**
* De-iitialize the object
*
* @exception Exception
*/
void
strip ( void ) throw ( Exception );
public:
/**
* Constructor.
*
* @param name the file name of the Solaris DSP device
* (e.g. /dev/audio or /dev/sound/0)
* @param sampleRate samples per second (e.g. 44100 for 44.1kHz).
* @param bitsPerSample bits per sample (e.g. 16 bits).
* @param channel number of channels of the audio source
* (e.g. 1 for mono, 2 for stereo, etc.).
* @exception Exception
*/
inline
SolarisDspSource ( const char * name,
int sampleRate = 44100,
int bitsPerSample = 16,
int channel = 2 )
throw ( Exception )
: AudioSource( sampleRate, bitsPerSample, channel)
{
init( name);
}
/**
* Copy Constructor.
*
* @param sds the object to copy.
* @exception Exception
*/
inline
SolarisDspSource ( const SolarisDspSource & sds )
throw ( Exception )
: AudioSource( sds )
{
init( sds.fileName);
}
/**
* Destructor.
*
* @exception Exception
*/
inline virtual
~SolarisDspSource ( void ) throw ( Exception )
{
strip();
}
/**
* Assignment operator.
*
* @param ds the object to assign to this one.
* @return a reference to this object.
* @exception Exception
*/
inline virtual SolarisDspSource &
operator= ( const SolarisDspSource & ds ) throw ( Exception )
{
if ( this != &ds ) {
strip();
AudioSource::operator=( ds);
init( ds.fileName);
}
return *this;
}
/**
* Tell if the data from this source comes in big or little endian.
*
* @return true
*/
virtual inline bool
isBigEndian ( void ) const throw ()
{
#ifdef WORDS_BIGENDIAN
return true;
#else
return false;
#endif
}
/**
* Open the SolarisDspSource.
* This does not put the Solaris DSP device into recording mode.
* To start getting samples, call either canRead() or read().
*
* @return true if opening was successful, false otherwise
* @exception Exception
*
* @see #canRead
* @see #read
*/
virtual bool
open ( void ) throw ( Exception );
/**
* Check if the SolarisDspSource is open.
*
* @return true if the SolarisDspSource is open, false otherwise.
*/
inline virtual bool
isOpen ( void ) const throw ()
{
return fileDescriptor != 0;
}
/**
* Check if the SolarisDspSource can be read from.
* Blocks until the specified time for data to be available.
* Puts the Solaris DSP device into recording mode.
*
* @param sec the maximum seconds to block.
* @param usec micro seconds to block after the full seconds.
* @return true if the SolarisDspSource is ready to be read from,
* false otherwise.
* @exception Exception
*/
virtual bool
canRead ( unsigned int sec,
unsigned int usec ) throw ( Exception );
/**
* Read from the SolarisDspSource.
* Puts the Solaris DSP device into recording mode.
*
* @param buf the buffer to read into.
* @param len the number of bytes to read into buf
* @return the number of bytes read (may be less than len).
* @exception Exception
*/
virtual unsigned int
read ( void * buf,
unsigned int len ) throw ( Exception );
/**
* Close the SolarisDspSource.
*
* @exception Exception
*/
virtual void
close ( void ) throw ( Exception );
};
/* ================================================= external data structures */
/* ====================================================== function prototypes */
#endif /* SOLARIS_DSP_SOURCE_H */
darkice-1.3/src/Reporter.h 0000644 0001750 0001750 00000022203 12526421577 012454 0000000 0000000 /*------------------------------------------------------------------------------
Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved.
Tyrell Reporter
File : Reporter.h
Version : $Revision$
Author : $Author$
Location : $HeadURL$
Copyright notice:
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 3
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 REPORTER_H
#define REPORTER_H
#ifndef __cplusplus
#error This is a C++ include file
#endif
/* ============================================================ include files */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_UNISTD_H
#include
#else
#error need unistd.h
#endif
#ifdef HAVE_TIME_H
#include
#else
#error need time.h
#endif
#include
#include "Exception.h"
/* ================================================================ constants */
/* =================================================================== macros */
/* =============================================================== data types */
/**
* Class for reporting events. All objects of this class share
* the same verbosity level. Typical usage is to inherit this class
* and use the report() function to report events. Only reports
* which are of suffucient importance are really reported.
*
* The default verbosity is 1, and the default ostream is cout.
*
* Known problems: this class is not thread-safe.
*
* @author $Author$
* @version $Revision$
*/
class Reporter
{
private:
/**
* Verbosity level shared among all Reporter objects
*/
static unsigned int verbosity;
/**
* The output stream to report to.
*/
static std::ostream * os;
/**
* Print timestamp for every report only if verbosity level
* is above this value.
*/
static const unsigned int prefixVerbosity = 3;
/**
* Print a prefix to each report.
*/
static void
printPrefix( void ) throw ()
{
if ( verbosity > prefixVerbosity ) {
char str[32];
time_t now;
now = time(NULL);
strftime( str, 32, "%d-%b-%Y %H:%M:%S ", localtime(&now) );
(*(Reporter::os)) << str;
}
}
protected:
public:
/**
* Destructor.
*
* @exception Exception
*/
inline virtual
~Reporter ( void ) throw ( Exception )
{
(Reporter::os)->flush();
}
/**
* Set the verbosity level. This sets the verbosity for all
* Reporter objects.
*
* @param verbosity the new verbosity level.
*/
static inline void
setReportVerbosity ( unsigned int verbosity ) throw ()
{
Reporter::verbosity = verbosity;
}
/**
* Get the verbosity level.
*
* @return the current verbosity level.
*/
static inline unsigned int
getReportVerbosity ( void ) throw ()
{
return Reporter::verbosity;
}
/**
* Set the output stream to report to. This setting effects all
* Reporter objects.
*
* @param os the output stream
*/
static inline void
setReportOutputStream ( std::ostream & os ) throw ()
{
Reporter::os = &os;
}
/**
* Get the output stream to report to.
*
* @return the output stream
*/
static inline std::ostream &
getReportOutputStream ( void ) throw ()
{
return *(Reporter::os);
}
/**
* Report an event with a given verbosity.
*
* @param verbosity the importance of the event, with 0 being
* the most important.
* @param t the object to report. Must have an
* ostream & operator<<( ostream&, const T)
* operator overload.
*/
template
static inline void
reportEvent ( unsigned int verbosity,
const T t ) throw ()
{
if ( Reporter::verbosity >= verbosity ) {
printPrefix();
(*(Reporter::os)) << t << std::endl;
}
}
/**
* Report an event with a given verbosity.
*
* @param verbosity the importance of the event, with 0 being
* the most important.
* @param t the object 1 to report. Must have an
* ostream & operator<<( ostream&, const T)
* operator overload.
* @param u the object 2 to report. Must have an
* ostream & operator<<( ostream&, const U)
* operator overload.
*/
template
inline void
static reportEvent ( unsigned int verbosity,
const T t,
const U u ) throw ()
{
if ( Reporter::verbosity >= verbosity ) {
printPrefix();
(*(Reporter::os)) << t << " "
<< u << std::endl;
}
}
/**
* Report an event with a given verbosity.
*
* @param verbosity the importance of the event, with 0 being
* the most important.
* @param t the object 1 to report. Must have an
* ostream & operator<<( ostream&, const T)
* operator overload.
* @param u the object 2 to report. Must have an
* ostream & operator<<( ostream&, const U)
* operator overload.
* @param v the object 3 to report. Must have an
* ostream & operator<<( ostream&, const V)
* operator overload.
*/
template
static inline void
reportEvent ( unsigned int verbosity,
const T t,
const U u,
const V v ) throw ()
{
if ( Reporter::verbosity >= verbosity ) {
printPrefix();
(*(Reporter::os)) << t << " "
<< u << " "
<< v << std::endl;
}
}
/**
* Report an event with a given verbosity.
*
* @param verbosity the importance of the event, with 0 being
* the most important.
* @param t the object 1 to report. Must have an
* ostream & operator<<( ostream&, const T)
* operator overload.
* @param u the object 2 to report. Must have an
* ostream & operator<<( ostream&, const U)
* operator overload.
* @param v the object 3 to report. Must have an
* ostream & operator<<( ostream&, const V)
* operator overload.
* @param w the object 4 to report. Must have an
* ostream & operator<<( ostream&, const W)
* operator overload.
*/
template
static inline void
reportEvent ( unsigned int verbosity,
const T t,
const U u,
const V v,
const W w ) throw ()
{
if ( Reporter::verbosity >= verbosity ) {
printPrefix();
(*(Reporter::os)) << t << " "
<< u << " "
<< v << " "
<< w << std::endl;
}
}
};
/* ================================================= external data structures */
/* ====================================================== function prototypes */
#endif /* REPORTER_H */
darkice-1.3/src/MultiThreadedConnector.cpp 0000644 0001750 0001750 00000032573 12750450634 015621 0000000 0000000 /*------------------------------------------------------------------------------
Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved.
Tyrell DarkIce
File : MultiThreadedConnector.cpp
Version : $Revision$
Author : $Author$
Location : $HeadURL$
Copyright notice:
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 3
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.
------------------------------------------------------------------------------*/
/* ============================================================ include files */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_SYS_TYPES_H
#include
#else
#error need sys/types.h
#endif
#include "Exception.h"
#include "MultiThreadedConnector.h"
#include "Util.h"
/* =================================================== local data structures */
/* ================================================ local constants & macros */
/*------------------------------------------------------------------------------
* File identity
*----------------------------------------------------------------------------*/
static const char fileid[] = "$Id$";
/* =============================================== local function prototypes */
/* ============================================================= module code */
/*------------------------------------------------------------------------------
* Initialize the object
*----------------------------------------------------------------------------*/
void
MultiThreadedConnector :: init ( bool reconnect ) throw ( Exception )
{
this->reconnect = reconnect;
pthread_mutex_init( &mutexProduce, 0);
pthread_cond_init( &condProduce, 0);
threads = 0;
}
/*------------------------------------------------------------------------------
* De-initialize the object
*----------------------------------------------------------------------------*/
void
MultiThreadedConnector :: strip ( void ) throw ( Exception )
{
if ( threads ) {
delete[] threads;
threads = 0;
}
pthread_cond_destroy( &condProduce);
pthread_mutex_destroy( &mutexProduce);
}
/*------------------------------------------------------------------------------
* Constructor
*----------------------------------------------------------------------------*/
MultiThreadedConnector :: MultiThreadedConnector (
const MultiThreadedConnector & connector )
throw ( Exception )
: Connector( connector)
{
reconnect = connector.reconnect;
mutexProduce = connector.mutexProduce;
condProduce = connector.condProduce;
if ( threads ) {
delete[] threads;
}
threads = new ThreadData[numSinks];
for ( unsigned int i = 0; i < numSinks; ++i ) {
threads[i] = connector.threads[i];
}
}
/*------------------------------------------------------------------------------
* Assignment operator
*----------------------------------------------------------------------------*/
MultiThreadedConnector &
MultiThreadedConnector :: operator= ( const MultiThreadedConnector & connector )
throw ( Exception )
{
if ( this != &connector ) {
Connector::operator=( connector);
reconnect = connector.reconnect;
mutexProduce = connector.mutexProduce;
condProduce = connector.condProduce;
if ( threads ) {
delete[] threads;
}
threads = new ThreadData[numSinks];
for ( unsigned int i = 0; i < numSinks; ++i ) {
threads[i] = connector.threads[i];
}
}
return *this;
}
/*------------------------------------------------------------------------------
* Open the source and all the sinks if needed
* Create the sink threads
*----------------------------------------------------------------------------*/
bool
MultiThreadedConnector :: open ( void ) throw ( Exception )
{
unsigned int i;
size_t st;
if ( !Connector::open() ) {
return false;
}
running = true;
pthread_attr_init( &threadAttr);
pthread_attr_getstacksize(&threadAttr, &st);
if (st < 128 * 1024) {
reportEvent( 5, "MultiThreadedConnector :: open, stack size ",
(long)st);
st = 128 * 1024;
pthread_attr_setstacksize(&threadAttr, st);
}
pthread_attr_setdetachstate( &threadAttr, PTHREAD_CREATE_JOINABLE);
threads = new ThreadData[numSinks];
for ( i = 0; i < numSinks; ++i ) {
ThreadData * threadData = threads + i;
threadData->connector = this;
threadData->ixSink = i;
threadData->accepting = true;
threadData->isDone = true;
if ( pthread_create( &(threadData->thread),
&threadAttr,
ThreadData::threadFunction,
threadData ) ) {
break;
}
}
// if could not create all, delete the ones created
if ( i < numSinks ) {
unsigned int j;
// signal to stop for all running threads
pthread_mutex_lock( &mutexProduce);
running = false;
pthread_cond_broadcast( &condProduce);
pthread_mutex_unlock( &mutexProduce);
for ( j = 0; j < i; ++j ) {
pthread_join( threads[j].thread, 0);
}
delete[] threads;
threads = 0;
return false;
}
return true;
}
/*------------------------------------------------------------------------------
* Transfer some data from the source to the sink
*----------------------------------------------------------------------------*/
unsigned int
MultiThreadedConnector :: transfer ( unsigned long bytes,
unsigned int bufSize,
unsigned int sec,
unsigned int usec )
throw ( Exception )
{
unsigned int b;
if ( numSinks == 0 ) {
return 0;
}
if ( bufSize == 0 ) {
return 0;
}
dataBuffer = new unsigned char[bufSize];
dataSize = 0;
reportEvent( 6, "MultiThreadedConnector :: transfer, bytes", bytes);
for ( b = 0; !bytes || b < bytes; ) {
if ( source->canRead( sec, usec) ) {
unsigned int i;
pthread_mutex_lock( &mutexProduce);
dataSize = source->read( dataBuffer, bufSize);
b += dataSize;
// check for EOF
if ( dataSize == 0 ) {
reportEvent( 3, "MultiThreadedConnector :: transfer, EOF");
pthread_mutex_unlock( &mutexProduce);
break;
}
for ( i = 0; i < numSinks; ++i ) {
threads[i].isDone = false;
}
// tell sink threads that there is some data available
pthread_cond_broadcast( &condProduce);
// wait for all sink threads to get done with this data
while ( true ) {
for ( i = 0; i < numSinks && threads[i].isDone; ++i );
if ( i == numSinks ) {
break;
}
pthread_cond_wait( &condProduce, &mutexProduce);
}
pthread_mutex_unlock( &mutexProduce);
} else {
reportEvent( 3, "MultiThreadedConnector :: transfer, can't read");
break;
}
}
delete[] dataBuffer;
return b;
}
/*------------------------------------------------------------------------------
* The function for each thread.
* Read the presented data
*----------------------------------------------------------------------------*/
void
MultiThreadedConnector :: sinkThread( int ixSink )
{
ThreadData * threadData = &threads[ixSink];
Sink * sink = sinks[ixSink].get();
while ( running ) {
// wait for some data to become available
pthread_mutex_lock( &mutexProduce);
while ( running && threadData->isDone ) {
pthread_cond_wait( &condProduce, &mutexProduce);
}
if ( !running ) {
pthread_mutex_unlock( &mutexProduce);
break;
}
if ( threadData->cut) {
sink->cut();
threadData->cut = false;
}
if ( threadData->accepting ) {
if ( sink->canWrite( 0, 0) ) {
try {
sink->write( dataBuffer, dataSize);
} catch ( Exception & e ) {
// something wrong. don't accept more data, try to
// reopen the sink next time around
threadData->accepting = false;
}
} else {
reportEvent( 4,
"MultiThreadedConnector :: sinkThread can't write ",
ixSink);
// don't care if we can't write
}
}
threadData->isDone = true;
pthread_cond_broadcast( &condProduce);
pthread_mutex_unlock( &mutexProduce);
if ( !threadData->accepting ) {
if ( reconnect ) {
reportEvent( 4,
"MultiThreadedConnector :: sinkThread reconnecting ",
ixSink);
// if we're not accepting, try to reopen the sink
try {
sink->close();
Util::sleep(1L, 0L);
sink->open();
sched_yield();
threadData->accepting = sink->isOpen();
} catch ( Exception & e ) {
// don't care, just try and try again
}
} else {
// if !reconnect, just stop the connector
running = false;
}
}
}
}
/*------------------------------------------------------------------------------
* Signal to each sink to cut what they've done so far, and start anew.
*----------------------------------------------------------------------------*/
void
MultiThreadedConnector :: cut ( void ) throw ()
{
for ( unsigned int i = 0; i < numSinks; ++i ) {
threads[i].cut = true;
}
// TODO: it might be more appropriate to signal all the threads here
// but, they'll get signaled on new data anyway, and it might be
// enough for them to cut at that time
}
/*------------------------------------------------------------------------------
* Stop the treads
* Close the source and all the sinks if needed
*----------------------------------------------------------------------------*/
void
MultiThreadedConnector :: close ( void ) throw ( Exception )
{
unsigned int i;
// signal to stop for all threads
pthread_mutex_lock( &mutexProduce);
running = false;
pthread_cond_broadcast( &condProduce);
pthread_mutex_unlock( &mutexProduce);
// wait for all the threads to finish
for ( i = 0; i < numSinks; ++i ) {
pthread_join( threads[i].thread, 0);
}
pthread_attr_destroy( &threadAttr);
Connector::close();
}
/*------------------------------------------------------------------------------
* The thread function
*----------------------------------------------------------------------------*/
void *
MultiThreadedConnector :: ThreadData :: threadFunction( void * param )
{
struct sched_param sched;
int sched_type;
ThreadData * threadData = (ThreadData*) param;
pthread_getschedparam( threadData->thread, &sched_type, &sched );
reportEvent( 5,
"MultiThreadedConnector :: ThreadData :: threadFunction, "
"was (thread, priority, type): ",
param,
sched.sched_priority,
sched_type == SCHED_FIFO ? "SCHED_FIFO" :
sched_type == SCHED_RR ? "SCHED_RR" :
sched_type == SCHED_OTHER ? "SCHED_OTHER" :
"INVALID"
);
sched.sched_priority = 1;
pthread_setschedparam( threadData->thread, SCHED_FIFO, &sched);
pthread_getschedparam( threadData->thread, &sched_type, &sched );
reportEvent( 5,
"MultiThreadedConnector :: ThreadData :: threadFunction, "
"now is (thread, priority, type): ",
param,
sched.sched_priority,
sched_type == SCHED_FIFO ? "SCHED_FIFO" :
sched_type == SCHED_RR ? "SCHED_RR" :
sched_type == SCHED_OTHER ? "SCHED_OTHER" :
"INVALID"
);
threadData->connector->sinkThread( threadData->ixSink);
return 0;
}
darkice-1.3/src/aflibConverterLargeFilter.h 0000644 0001750 0001750 00000213726 12526421600 015737 0000000 0000000 /*
* Copyright: (C) 2000 Julius O. Smith
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Julius O. Smith jos@ccrma.stanford.edu
*
*/
/*
The default filter requires an
oversampling factor of around 20% to avoid aliasing. The expensive
filter is five times more computationally expensive and requires only
about a 5-10% oversampling factor. Both filters have comparable
stop-band attenuations (approximately 80 dB). The
expensive filter is not yet documented because its cut-off frequency
should be retuned slightly for optimal performance. Also, we plan to
compute truly optimized resampling filters sometime in the future. In
the meantime, the default filter is fast, well tuned, and works very
well for its level of computational expense.
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#define LARGE_FILTER_NMULT ((short)65)
#define LARGE_FILTER_SCALE 14746 /* Unity-gain scale factor */
#define LARGE_FILTER_NWING 8192 /* Filter table length */
short aflibConverter::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 short 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};
darkice-1.3/src/DarkIce.cpp 0000644 0001750 0001750 00000146141 12750450634 012512 0000000 0000000 /*------------------------------------------------------------------------------
Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved.
Tyrell DarkIce
File : DarkIce.cpp
Version : $Revision$
Author : $Author$
Location : $HeadURL$
Copyright notice:
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 3
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.
------------------------------------------------------------------------------*/
/* ============================================================ include files */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_STDLIB_H
#include
#else
#error need stdlib.h
#endif
#ifdef HAVE_UNISTD_H
#include
#else
#error need unistd.h
#endif
#ifdef HAVE_SYS_TYPES_H
#include
#else
#error need sys/types.h
#endif
#ifdef HAVE_SYS_WAIT_H
#include
#else
#error need sys/wait.h
#endif
#ifdef HAVE_ERRNO_H
#include
#else
#error need errno.h
#endif
#ifdef HAVE_SCHED_H
#include
#else
#error need sched.h
#endif
#include "Util.h"
#include "IceCast.h"
#include "IceCast2.h"
#include "ShoutCast.h"
#include "FileCast.h"
#include "MultiThreadedConnector.h"
#include "DarkIce.h"
#ifdef HAVE_LAME_LIB
#include "LameLibEncoder.h"
#endif
#ifdef HAVE_TWOLAME_LIB
#include "TwoLameLibEncoder.h"
#endif
#ifdef HAVE_VORBIS_LIB
#include "VorbisLibEncoder.h"
#endif
#ifdef HAVE_OPUS_LIB
#include "OpusLibEncoder.h"
#endif
#ifdef HAVE_FAAC_LIB
#include "FaacEncoder.h"
#endif
#ifdef HAVE_AACPLUS_LIB
#include "aacPlusEncoder.h"
#endif
/* =================================================== local data structures */
/* ================================================ local constants & macros */
/*------------------------------------------------------------------------------
* File identity
*----------------------------------------------------------------------------*/
static const char fileid[] = "$Id$";
/*------------------------------------------------------------------------------
* Make sure wait-related stuff is what we expect
*----------------------------------------------------------------------------*/
#ifndef WEXITSTATUS
# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
#endif
#ifndef WIFEXITED
# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
#endif
/* =============================================== local function prototypes */
/* ============================================================= module code */
/*------------------------------------------------------------------------------
* Initialize the object
*----------------------------------------------------------------------------*/
void
DarkIce :: init ( const Config & config ) throw ( Exception )
{
unsigned int bufferSecs;
const ConfigSection * cs;
const char * str;
unsigned int sampleRate;
unsigned int bitsPerSample;
unsigned int channel;
bool reconnect;
const char * device;
const char * jackClientName;
const char * paSourceName;
// the [general] section
if ( !(cs = config.get( "general")) ) {
throw Exception( __FILE__, __LINE__, "no section [general] in config");
}
str = cs->getForSure( "duration", " missing in section [general]");
duration = Util::strToL( str);
str = cs->getForSure( "bufferSecs", " missing in section [general]");
bufferSecs = Util::strToL( str);
if (bufferSecs == 0) {
throw Exception(__FILE__, __LINE__,
"setting bufferSecs to 0 not supported");
}
str = cs->get( "reconnect");
reconnect = str ? (Util::strEq( str, "yes") ? true : false) : true;
// real-time scheduling is enabled by default
str = cs->get( "realtime" );
enableRealTime = str ? (Util::strEq( str, "yes") ? true : false) : true;
// get realtime scheduling priority. If unspecified, set it to 4.
// Why 4? jackd's default priority is 10, jackd client threads run
// at 5, so make the encoder thread use 4. jackd automatically sets
// the process callback priority to the right value, so all we have
// to care about is the encoder priority.
str = cs->get( "rtprio" );
realTimeSchedPriority = (str != NULL) ? Util::strToL( str ) : 4;
// the [input] section
if ( !(cs = config.get( "input")) ) {
throw Exception( __FILE__, __LINE__, "no section [input] in config");
}
str = cs->getForSure( "sampleRate", " missing in section [input]");
sampleRate = Util::strToL( str);
str = cs->getForSure( "bitsPerSample", " missing in section [input]");
bitsPerSample = Util::strToL( str);
str = cs->getForSure( "channel", " missing in section [input]");
channel = Util::strToL( str);
device = cs->getForSure( "device", " missing in section [input]");
jackClientName = cs->get ( "jackClientName");
paSourceName = cs->get ( "paSourceName");
dsp = AudioSource::createDspSource( device,
jackClientName,
paSourceName,
sampleRate,
bitsPerSample,
channel );
encConnector = new MultiThreadedConnector( dsp.get(), reconnect );
noAudioOuts = 0;
configIceCast( config, bufferSecs);
configIceCast2( config, bufferSecs);
configShoutCast( config, bufferSecs);
configFileCast( config);
}
/*------------------------------------------------------------------------------
* Look for the IceCast stream outputs in the config file
*----------------------------------------------------------------------------*/
void
DarkIce :: configIceCast ( const Config & config,
unsigned int bufferSecs )
throw ( Exception )
{
// look for IceCast encoder output streams,
// sections [icecast-0], [icecast-1], ...
char stream[] = "icecast- ";
size_t streamLen = Util::strLen( stream);
unsigned int u;
for ( u = noAudioOuts; u < maxOutput; ++u ) {
const ConfigSection * cs;
// ugly hack to change the section name to "stream0", "stream1", etc.
stream[streamLen-1] = '0' + (u - noAudioOuts);
if ( !(cs = config.get( stream)) ) {
break;
}
#if !defined HAVE_LAME_LIB && !defined HAVE_TWOLAME_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with lame or twolame support, "
"thus can't connect to IceCast 1.x, stream: ",
stream);
#else
const char * str;
unsigned int sampleRate = 0;
unsigned int channel = 0;
AudioEncoder::BitrateMode bitrateMode;
unsigned int bitrate = 0;
double quality = 0.0;
const char * server = 0;
unsigned int port = 0;
const char * password = 0;
const char * mountPoint = 0;
const char * remoteDumpFile = 0;
const char * name = 0;
const char * description = 0;
const char * url = 0;
const char * genre = 0;
bool isPublic = false;
int lowpass = 0;
int highpass = 0;
const char * localDumpName = 0;
FileSink * localDumpFile = 0;
bool fileAddDate = false;
const char * fileDateFormat = 0;
BufferedSink * audioOut = 0;
int bufferSize = 0;
str = cs->get( "sampleRate");
sampleRate = str ? Util::strToL( str) : dsp->getSampleRate();
str = cs->get( "channel");
channel = str ? Util::strToL( str) : dsp->getChannel();
str = cs->get( "bitrate");
bitrate = str ? Util::strToL( str) : 0;
str = cs->get( "quality");
quality = str ? Util::strToD( str) : 0.0;
str = cs->getForSure( "bitrateMode",
" not specified in section ",
stream);
if ( Util::strEq( str, "cbr") ) {
bitrateMode = AudioEncoder::cbr;
if ( bitrate == 0 ) {
throw Exception( __FILE__, __LINE__,
"bitrate not specified for CBR encoding");
}
if ( cs->get( "quality" ) == 0 ) {
throw Exception( __FILE__, __LINE__,
"quality not specified for CBR encoding");
}
} else if ( Util::strEq( str, "abr") ) {
bitrateMode = AudioEncoder::abr;
if ( bitrate == 0 ) {
throw Exception( __FILE__, __LINE__,
"bitrate not specified for ABR encoding");
}
} else if ( Util::strEq( str, "vbr") ) {
bitrateMode = AudioEncoder::vbr;
if ( cs->get( "quality" ) == 0 ) {
throw Exception( __FILE__, __LINE__,
"quality not specified for VBR encoding");
}
} else {
throw Exception( __FILE__, __LINE__,
"invalid bitrate mode: ", str);
}
server = cs->getForSure( "server", " missing in section ", stream);
str = cs->getForSure( "port", " missing in section ", stream);
port = Util::strToL( str);
password = cs->getForSure("password"," missing in section ",stream);
mountPoint = cs->getForSure( "mountPoint",
" missing in section ",
stream);
remoteDumpFile = cs->get( "remoteDumpFile");
name = cs->get( "name");
description = cs->get("description");
url = cs->get( "url");
genre = cs->get( "genre");
str = cs->get( "public");
isPublic = str ? (Util::strEq( str, "yes") ? true : false) : false;
str = cs->get( "lowpass");
lowpass = str ? Util::strToL( str) : 0;
str = cs->get( "highpass");
highpass = str ? Util::strToL( str) : 0;
str = cs->get("fileAddDate");
fileAddDate = str ? (Util::strEq( str, "yes") ? true : false) : false;
fileDateFormat = cs->get("fileDateFormat");
bufferSize = dsp->getSampleSize() * dsp->getSampleRate() * bufferSecs;
reportEvent( 3, "buffer size: ", bufferSize);
localDumpName = cs->get( "localDumpFile");
// go on and create the things
// check for and create the local dump file if needed
if ( localDumpName != 0 ) {
if ( fileAddDate ) {
if (fileDateFormat == 0) {
localDumpName = Util::fileAddDate(localDumpName);
}
else {
localDumpName = Util::fileAddDate( localDumpName,
fileDateFormat );
}
}
localDumpFile = new FileSink( stream, localDumpName);
if ( !localDumpFile->exists() ) {
if ( !localDumpFile->create() ) {
reportEvent( 1, "can't create local dump file",
localDumpName);
localDumpFile = 0;
}
}
if ( fileAddDate ) {
delete[] localDumpName;
}
}
// streaming related stuff
audioOuts[u].socket = new TcpSocket( server, port);
audioOuts[u].server = new IceCast( audioOuts[u].socket.get(),
password,
mountPoint,
bitrate,
name,
description,
url,
genre,
isPublic,
remoteDumpFile,
localDumpFile);
str = cs->getForSure( "format", " missing in section ", stream);
if (!Util::strEq(str, "mp3") && !Util::strEq(str, "mp2")) {
throw Exception( __FILE__, __LINE__,
"unsupported stream format: ", str);
}
// augment audio outs with a buffer when used from encoder
audioOut = new BufferedSink( audioOuts[u].server.get(),
bufferSize, 1);
#ifdef HAVE_LAME_LIB
if ( Util::strEq( str, "mp3") ) {
audioOuts[u].encoder = new LameLibEncoder( audioOut,
dsp.get(),
bitrateMode,
bitrate,
quality,
sampleRate,
channel,
lowpass,
highpass );
}
#endif
#ifdef HAVE_TWOLAME_LIB
if ( Util::strEq( str, "mp2") ) {
audioOuts[u].encoder = new TwoLameLibEncoder(
audioOut,
dsp.get(),
bitrateMode,
bitrate,
sampleRate,
channel );
}
#endif
encConnector->attach( audioOuts[u].encoder.get());
#endif // HAVE_LAME_LIB || HAVE_TWOLAME_LIB
}
noAudioOuts += u;
}
/*------------------------------------------------------------------------------
* Look for the IceCast2 stream outputs in the config file
*----------------------------------------------------------------------------*/
void
DarkIce :: configIceCast2 ( const Config & config,
unsigned int bufferSecs )
throw ( Exception )
{
// look for IceCast2 encoder output streams,
// sections [icecast2-0], [icecast2-1], ...
char stream[] = "icecast2- ";
size_t streamLen = Util::strLen( stream);
unsigned int u;
for ( u = noAudioOuts; u < maxOutput; ++u ) {
const ConfigSection * cs;
// ugly hack to change the section name to "stream0", "stream1", etc.
stream[streamLen-1] = '0' + (u - noAudioOuts);
if ( !(cs = config.get( stream)) ) {
break;
}
const char * str;
IceCast2::StreamFormat format;
unsigned int sampleRate = 0;
unsigned int channel = 0;
AudioEncoder::BitrateMode bitrateMode;
unsigned int bitrate = 0;
unsigned int maxBitrate = 0;
double quality = 0.0;
const char * server = 0;
unsigned int port = 0;
const char * password = 0;
const char * mountPoint = 0;
const char * name = 0;
const char * description = 0;
const char * url = 0;
const char * genre = 0;
bool isPublic = false;
int lowpass = 0;
int highpass = 0;
const char * localDumpName = 0;
FileSink * localDumpFile = 0;
bool fileAddDate = false;
const char * fileDateFormat = 0;
BufferedSink * audioOut = 0;
int bufferSize = 0;
str = cs->getForSure( "format", " missing in section ", stream);
if ( Util::strEq( str, "vorbis") ) {
format = IceCast2::oggVorbis;
} else if ( Util::strEq( str, "opus") ) {
format = IceCast2::oggOpus;
} else if ( Util::strEq( str, "mp3") ) {
format = IceCast2::mp3;
} else if ( Util::strEq( str, "mp2") ) {
format = IceCast2::mp2;
} else if ( Util::strEq( str, "aac") ) {
format = IceCast2::aac;
} else if ( Util::strEq( str, "aacp") ) {
format = IceCast2::aacp;
} else {
throw Exception( __FILE__, __LINE__,
"unsupported stream format: ", str);
}
str = cs->get( "sampleRate");
sampleRate = str ? Util::strToL( str) : dsp->getSampleRate();
str = cs->get( "channel");
channel = str ? Util::strToL( str) : dsp->getChannel();
// determine fixed bitrate or variable bitrate quality
str = cs->get( "bitrate");
bitrate = str ? Util::strToL( str) : 0;
str = cs->get( "maxBitrate");
maxBitrate = str ? Util::strToL( str) : 0;
str = cs->get( "quality");
quality = str ? Util::strToD( str) : 0.0;
str = cs->getForSure( "bitrateMode",
" not specified in section ",
stream);
if ( Util::strEq( str, "cbr") ) {
bitrateMode = AudioEncoder::cbr;
if ( bitrate == 0 ) {
throw Exception( __FILE__, __LINE__,
"bitrate not specified for CBR encoding");
}
} else if ( Util::strEq( str, "abr") ) {
bitrateMode = AudioEncoder::abr;
if ( bitrate == 0 ) {
throw Exception( __FILE__, __LINE__,
"bitrate not specified for ABR encoding");
}
} else if ( Util::strEq( str, "vbr") ) {
bitrateMode = AudioEncoder::vbr;
if ( cs->get( "quality" ) == 0 ) {
throw Exception( __FILE__, __LINE__,
"quality not specified for VBR encoding");
}
} else {
throw Exception( __FILE__, __LINE__,
"invalid bitrate mode: ", str);
}
server = cs->getForSure( "server", " missing in section ", stream);
str = cs->getForSure( "port", " missing in section ", stream);
port = Util::strToL( str);
password = cs->getForSure("password"," missing in section ",stream);
mountPoint = cs->getForSure( "mountPoint",
" missing in section ",
stream);
name = cs->get( "name");
description = cs->get( "description");
url = cs->get( "url");
genre = cs->get( "genre");
str = cs->get( "public");
isPublic = str ? (Util::strEq( str, "yes") ? true : false) : false;
str = cs->get( "lowpass");
lowpass = str ? Util::strToL( str) : 0;
str = cs->get( "highpass");
highpass = str ? Util::strToL( str) : 0;
str = cs->get( "fileAddDate");
fileAddDate = str ? (Util::strEq( str, "yes") ? true : false) : false;
fileDateFormat = cs->get( "fileDateFormat");
bufferSize = dsp->getSampleSize() * dsp->getSampleRate() * bufferSecs;
reportEvent( 3, "buffer size: ", bufferSize);
localDumpName = cs->get( "localDumpFile");
// go on and create the things
// check for and create the local dump file if needed
if ( localDumpName != 0 ) {
if ( fileAddDate ) {
if (fileDateFormat == 0) {
localDumpName = Util::fileAddDate(localDumpName);
}
else {
localDumpName = Util::fileAddDate( localDumpName,
fileDateFormat );
}
}
localDumpFile = new FileSink( stream, localDumpName);
if ( !localDumpFile->exists() ) {
if ( !localDumpFile->create() ) {
reportEvent( 1, "can't create local dump file",
localDumpName);
localDumpFile = 0;
}
}
if ( fileAddDate ) {
delete[] localDumpName;
}
}
// streaming related stuff
audioOuts[u].socket = new TcpSocket( server, port);
audioOuts[u].server = new IceCast2( audioOuts[u].socket.get(),
password,
mountPoint,
format,
bitrate,
name,
description,
url,
genre,
isPublic,
localDumpFile);
audioOut = new BufferedSink( audioOuts[u].server.get(),
bufferSize, 1);
switch ( format ) {
case IceCast2::mp3:
#ifndef HAVE_LAME_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with lame support, "
"thus can't create mp3 stream: ",
stream);
#else
audioOuts[u].encoder = new LameLibEncoder(
audioOut,
dsp.get(),
bitrateMode,
bitrate,
quality,
sampleRate,
channel,
lowpass,
highpass );
#endif // HAVE_LAME_LIB
break;
case IceCast2::oggVorbis:
#ifndef HAVE_VORBIS_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with Ogg Vorbis support, "
"thus can't Ogg Vorbis stream: ",
stream);
#else
audioOuts[u].encoder = new VorbisLibEncoder(
audioOut,
dsp.get(),
bitrateMode,
bitrate,
quality,
sampleRate,
dsp->getChannel(),
maxBitrate);
#endif // HAVE_VORBIS_LIB
break;
case IceCast2::oggOpus:
#ifndef HAVE_OPUS_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with Ogg Opus support, "
"thus can't Ogg Opus stream: ",
stream);
#else
audioOuts[u].encoder = new OpusLibEncoder(
audioOut,
dsp.get(),
bitrateMode,
bitrate,
quality,
sampleRate,
dsp->getChannel(),
maxBitrate);
#endif // HAVE_OPUS_LIB
break;
case IceCast2::mp2:
#ifndef HAVE_TWOLAME_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with TwoLame support, "
"thus can't create mp2 stream: ",
stream);
#else
audioOuts[u].encoder = new TwoLameLibEncoder(
audioOut,
dsp.get(),
bitrateMode,
bitrate,
sampleRate,
channel );
#endif // HAVE_TWOLAME_LIB
break;
case IceCast2::aac:
#ifndef HAVE_FAAC_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with AAC support, "
"thus can't aac stream: ",
stream);
#else
audioOuts[u].encoder = new FaacEncoder(
audioOut,
dsp.get(),
bitrateMode,
bitrate,
quality,
sampleRate,
dsp->getChannel());
#endif // HAVE_FAAC_LIB
break;
case IceCast2::aacp:
#ifndef HAVE_AACPLUS_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with AAC+ support, "
"thus can't aacp stream: ",
stream);
#else
audioOuts[u].encoder = new aacPlusEncoder(
audioOut,
dsp.get(),
bitrateMode,
bitrate,
quality,
sampleRate,
channel );
#endif // HAVE_AACPLUS_LIB
break;
default:
throw Exception( __FILE__, __LINE__,
"Illegal stream format: ", format);
}
encConnector->attach( audioOuts[u].encoder.get());
}
noAudioOuts += u;
}
/*------------------------------------------------------------------------------
* Look for the ShoutCast stream outputs in the config file
*----------------------------------------------------------------------------*/
void
DarkIce :: configShoutCast ( const Config & config,
unsigned int bufferSecs )
throw ( Exception )
{
// look for Shoutcast encoder output streams,
// sections [shoutcast-0], [shoutcast-1], ...
char stream[] = "shoutcast- ";
size_t streamLen = Util::strLen( stream);
unsigned int u;
for ( u = noAudioOuts; u < maxOutput; ++u ) {
const ConfigSection * cs;
// ugly hack to change the section name to "stream0", "stream1", etc.
stream[streamLen-1] = '0' + (u - noAudioOuts);
if ( !(cs = config.get( stream)) ) {
break;
}
#ifndef HAVE_LAME_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with lame support, "
"thus can't connect to ShoutCast, stream: ",
stream);
#else
const char * str;
unsigned int sampleRate = 0;
unsigned int channel = 0;
AudioEncoder::BitrateMode bitrateMode;
unsigned int bitrate = 0;
double quality = 0.0;
const char * server = 0;
unsigned int port = 0;
const char * password = 0;
const char * name = 0;
const char * url = 0;
const char * genre = 0;
bool isPublic = false;
const char * mountPoint = 0;
int lowpass = 0;
int highpass = 0;
const char * irc = 0;
const char * aim = 0;
const char * icq = 0;
const char * localDumpName = 0;
FileSink * localDumpFile = 0;
bool fileAddDate = false;
const char * fileDateFormat = 0;
BufferedSink * audioOut = 0;
int bufferSize = 0;
str = cs->get( "sampleRate");
sampleRate = str ? Util::strToL( str) : dsp->getSampleRate();
str = cs->get( "channel");
channel = str ? Util::strToL( str) : dsp->getChannel();
str = cs->get( "bitrate");
bitrate = str ? Util::strToL( str) : 0;
str = cs->get( "quality");
quality = str ? Util::strToD( str) : 0.0;
str = cs->getForSure( "bitrateMode",
" not specified in section ",
stream);
if ( Util::strEq( str, "cbr") ) {
bitrateMode = AudioEncoder::cbr;
if ( bitrate == 0 ) {
throw Exception( __FILE__, __LINE__,
"bitrate not specified for CBR encoding");
}
if ( cs->get( "quality" ) == 0 ) {
throw Exception( __FILE__, __LINE__,
"quality not specified for CBR encoding");
}
} else if ( Util::strEq( str, "abr") ) {
bitrateMode = AudioEncoder::abr;
if ( bitrate == 0 ) {
throw Exception( __FILE__, __LINE__,
"bitrate not specified for ABR encoding");
}
} else if ( Util::strEq( str, "vbr") ) {
bitrateMode = AudioEncoder::vbr;
if ( cs->get( "quality" ) == 0 ) {
throw Exception( __FILE__, __LINE__,
"quality not specified for VBR encoding");
}
} else {
throw Exception( __FILE__, __LINE__,
"invalid bitrate mode: ", str);
}
server = cs->getForSure( "server", " missing in section ", stream);
str = cs->getForSure( "port", " missing in section ", stream);
port = Util::strToL( str);
password = cs->getForSure("password"," missing in section ",stream);
name = cs->get( "name");
mountPoint = cs->get( "mountPoint" );
url = cs->get( "url");
genre = cs->get( "genre");
str = cs->get( "public");
isPublic = str ? (Util::strEq( str, "yes") ? true : false) : false;
str = cs->get( "lowpass");
lowpass = str ? Util::strToL( str) : 0;
str = cs->get( "highpass");
highpass = str ? Util::strToL( str) : 0;
irc = cs->get( "irc");
aim = cs->get( "aim");
icq = cs->get( "icq");
str = cs->get("fileAddDate");
fileAddDate = str ? (Util::strEq( str, "yes") ? true : false) : false;
fileDateFormat = cs->get( "fileDateFormat");
bufferSize = dsp->getBitsPerSample() / 8 * dsp->getSampleRate() * dsp->getChannel() * bufferSecs;
reportEvent( 3, "buffer size: ", bufferSize);
localDumpName = cs->get( "localDumpFile");
// go on and create the things
// check for and create the local dump file if needed
if ( localDumpName != 0 ) {
if ( fileAddDate ) {
if (fileDateFormat == 0) {
localDumpName = Util::fileAddDate(localDumpName);
}
else {
localDumpName = Util::fileAddDate( localDumpName,
fileDateFormat );
}
}
localDumpFile = new FileSink( stream, localDumpName);
if ( !localDumpFile->exists() ) {
if ( !localDumpFile->create() ) {
reportEvent( 1, "can't create local dump file",
localDumpName);
localDumpFile = 0;
}
}
if ( fileAddDate ) {
delete[] localDumpName;
}
}
// streaming related stuff
audioOuts[u].socket = new TcpSocket( server, port);
audioOuts[u].server = new ShoutCast( audioOuts[u].socket.get(),
password,
mountPoint,
bitrate,
name,
url,
genre,
isPublic,
irc,
aim,
icq,
localDumpFile);
audioOut = new BufferedSink(audioOuts[u].socket.get(), bufferSize, 1);
audioOuts[u].encoder = new LameLibEncoder(
audioOut,
dsp.get(),
bitrateMode,
bitrate,
quality,
sampleRate,
channel,
lowpass,
highpass );
encConnector->attach( audioOuts[u].encoder.get());
#endif // HAVE_LAME_LIB
}
noAudioOuts += u;
}
/*------------------------------------------------------------------------------
* Look for the FileCast stream outputs in the config file
*----------------------------------------------------------------------------*/
void
DarkIce :: configFileCast ( const Config & config )
throw ( Exception )
{
// look for FileCast encoder output streams,
// sections [file-0], [file-1], ...
char stream[] = "file- ";
size_t streamLen = Util::strLen( stream);
unsigned int u;
for ( u = noAudioOuts; u < maxOutput; ++u ) {
const ConfigSection * cs;
// ugly hack to change the section name to "stream0", "stream1", etc.
stream[streamLen-1] = '0' + (u - noAudioOuts);
if ( !(cs = config.get( stream)) ) {
break;
}
const char * str;
const char * format = 0;
AudioEncoder::BitrateMode bitrateMode;
unsigned int bitrate = 0;
double quality = 0.0;
const char * targetFileName = 0;
unsigned int sampleRate = 0;
int lowpass = 0;
int highpass = 0;
bool fileAddDate = false;
const char * fileDateFormat = 0;
format = cs->getForSure( "format", " missing in section ", stream);
if ( !Util::strEq( format, "vorbis")
&& !Util::strEq( format, "opus")
&& !Util::strEq( format, "mp3")
&& !Util::strEq( format, "mp2")
&& !Util::strEq( format, "aac")
&& !Util::strEq( format, "aacp") ) {
throw Exception( __FILE__, __LINE__,
"unsupported stream format: ", format);
}
str = cs->getForSure("bitrate", " missing in section ", stream);
bitrate = Util::strToL( str);
targetFileName = cs->getForSure( "fileName",
" missing in section ",
stream);
str = cs->get( "fileAddDate");
fileAddDate = str ? (Util::strEq( str, "yes") ? true : false) : false;
fileDateFormat = cs->get( "fileDateFormat");
str = cs->get( "sampleRate");
sampleRate = str ? Util::strToL( str) : dsp->getSampleRate();
str = cs->get( "bitrate");
bitrate = str ? Util::strToL( str) : 0;
str = cs->get( "quality");
quality = str ? Util::strToD( str) : 0.0;
str = cs->getForSure( "bitrateMode",
" not specified in section ",
stream);
if ( Util::strEq( str, "cbr") ) {
bitrateMode = AudioEncoder::cbr;
if ( bitrate == 0 ) {
throw Exception( __FILE__, __LINE__,
"bitrate not specified for CBR encoding");
}
} else if ( Util::strEq( str, "abr") ) {
bitrateMode = AudioEncoder::abr;
if ( bitrate == 0 ) {
throw Exception( __FILE__, __LINE__,
"bitrate not specified for ABR encoding");
}
} else if ( Util::strEq( str, "vbr") ) {
bitrateMode = AudioEncoder::vbr;
if ( cs->get( "quality" ) == 0 ) {
throw Exception( __FILE__, __LINE__,
"quality not specified for VBR encoding");
}
} else {
throw Exception( __FILE__, __LINE__,
"invalid bitrate mode: ", str);
}
if (Util::strEq(format, "aac") && bitrateMode != AudioEncoder::abr) {
throw Exception(__FILE__, __LINE__,
"currently the AAC format only supports "
"average bitrate mode");
}
if (Util::strEq(format, "aacp") && bitrateMode != AudioEncoder::cbr) {
throw Exception(__FILE__, __LINE__,
"currently the AAC+ format only supports "
"constant bitrate mode");
}
str = cs->get( "lowpass");
lowpass = str ? Util::strToL( str) : 0;
str = cs->get( "highpass");
highpass = str ? Util::strToL( str) : 0;
// go on and create the things
// the underlying file
if ( fileAddDate ) {
if (fileDateFormat == 0) {
targetFileName = Util::fileAddDate( targetFileName);
}
else {
targetFileName = Util::fileAddDate( targetFileName,
fileDateFormat );
}
}
FileSink * targetFile = new FileSink( stream, targetFileName);
if ( !targetFile->exists() ) {
if ( !targetFile->create() ) {
throw Exception( __FILE__, __LINE__,
"can't create output file", targetFileName);
}
}
// streaming related stuff
audioOuts[u].socket = 0;
audioOuts[u].server = new FileCast( targetFile );
if ( Util::strEq( format, "mp3") ) {
#ifndef HAVE_LAME_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with lame support, "
"thus can't create mp3 stream: ",
stream);
#else
audioOuts[u].encoder = new LameLibEncoder(
audioOuts[u].server.get(),
dsp.get(),
bitrateMode,
bitrate,
quality,
sampleRate,
dsp->getChannel(),
lowpass,
highpass );
#endif // HAVE_TWOLAME_LIB
} else if ( Util::strEq( format, "mp2") ) {
#ifndef HAVE_TWOLAME_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with TwoLAME support, "
"thus can't create MPEG Audio Layer 2 stream: ",
stream);
#else
audioOuts[u].encoder = new TwoLameLibEncoder(
audioOuts[u].server.get(),
dsp.get(),
bitrateMode,
bitrate,
sampleRate,
dsp->getChannel() );
#endif // HAVE_TWOLAME_LIB
} else if ( Util::strEq( format, "vorbis") ) {
#ifndef HAVE_VORBIS_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with Ogg Vorbis support, "
"thus can't Ogg Vorbis stream: ",
stream);
#else
audioOuts[u].encoder = new VorbisLibEncoder(
audioOuts[u].server.get(),
dsp.get(),
bitrateMode,
bitrate,
quality,
dsp->getSampleRate(),
dsp->getChannel() );
#endif // HAVE_VORBIS_LIB
} else if ( Util::strEq( format, "opus") ) {
#ifndef HAVE_OPUS_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with Ogg Opus support, "
"thus can't Ogg Opus stream: ",
stream);
#else
audioOuts[u].encoder = new OpusLibEncoder(
audioOuts[u].server.get(),
dsp.get(),
bitrateMode,
bitrate,
quality,
dsp->getSampleRate(),
dsp->getChannel() );
#endif // HAVE_OPUS_LIB
} else if ( Util::strEq( format, "aac") ) {
#ifndef HAVE_FAAC_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with AAC support, "
"thus can't aac stream: ",
stream);
#else
audioOuts[u].encoder = new FaacEncoder(
audioOuts[u].server.get(),
dsp.get(),
bitrateMode,
bitrate,
quality,
sampleRate,
dsp->getChannel());
#endif // HAVE_FAAC_LIB
} else if ( Util::strEq( format, "aacp") ) {
#ifndef HAVE_AACPLUS_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with AAC+ support, "
"thus can't aacplus stream: ",
stream);
#else
audioOuts[u].encoder = new aacPlusEncoder(
audioOuts[u].server.get(),
dsp.get(),
bitrateMode,
bitrate,
quality,
sampleRate,
dsp->getChannel());
#endif // HAVE_AACPLUS_LIB
} else {
throw Exception( __FILE__, __LINE__,
"Illegal stream format: ", format);
}
encConnector->attach( audioOuts[u].encoder.get());
}
noAudioOuts += u;
}
/*------------------------------------------------------------------------------
* Set POSIX real-time scheduling
*----------------------------------------------------------------------------*/
void
DarkIce :: setRealTimeScheduling ( void ) throw ( Exception )
{
// Only if the OS has the POSIX real-time scheduling functions implemented.
#if defined( HAVE_SCHED_GETSCHEDULER ) && defined( HAVE_SCHED_GETPARAM )
int high_priority;
struct sched_param param;
/* store the old scheduling parameters */
if ( (origSchedPolicy = sched_getscheduler(0)) == -1 ) {
throw Exception( __FILE__, __LINE__, "sched_getscheduler", errno);
}
if ( sched_getparam( 0, ¶m) == -1 ) {
throw Exception( __FILE__, __LINE__, "sched_getparam", errno);
}
origSchedPriority = param.sched_priority;
/* set SCHED_FIFO with max - 1 priority or user configured value */
if ( (high_priority = sched_get_priority_max(SCHED_FIFO)) == -1 ) {
throw Exception(__FILE__,__LINE__,"sched_get_priority_max",errno);
}
reportEvent( 8, "scheduler high priority", high_priority);
if (realTimeSchedPriority > high_priority) {
param.sched_priority = high_priority - 1;
} else {
param.sched_priority = realTimeSchedPriority;
}
if ( sched_setscheduler( 0, SCHED_FIFO, ¶m) == -1 ) {
reportEvent( 1,
"Could not set POSIX real-time scheduling, "
"this may cause recording skips.\n"
"Try to run darkice as the super-user.");
} else {
/* ask the new priortiy and report it */
if ( sched_getparam( 0, ¶m) == -1 ) {
throw Exception( __FILE__, __LINE__, "sched_getparam", errno);
}
reportEvent( 1,
"Using POSIX real-time scheduling, priority",
param.sched_priority );
}
#else
reportEvent( 1, "POSIX scheduling not supported on this system, "
"this may cause recording skips");
#endif // HAVE_SCHED_GETSCHEDULER && HAVE_SCHED_GETPARAM
}
/*------------------------------------------------------------------------------
* Set the original scheduling of the process, the one prior to the
* setRealTimeScheduling call.
* WARNING: make sure you don't call this before setRealTimeScheduling!!
*----------------------------------------------------------------------------*/
void
DarkIce :: setOriginalScheduling ( void ) throw ( Exception )
{
// Only if the OS has the POSIX real-time scheduling functions implemented.
#if defined( HAVE_SCHED_GETSCHEDULER ) && defined( HAVE_SCHED_GETPARAM )
uid_t euid;
euid = geteuid();
if ( euid == 0 ) {
struct sched_param param;
if ( sched_getparam( 0, ¶m) == -1 ) {
throw Exception( __FILE__, __LINE__, "sched_getparam", errno);
}
param.sched_priority = origSchedPriority;
if ( sched_setscheduler( 0, origSchedPolicy, ¶m) == -1 ) {
throw Exception( __FILE__, __LINE__, "sched_setscheduler", errno);
}
reportEvent( 5, "reverted to original scheduling");
}
#endif // HAVE_SCHED_GETSCHEDULER && HAVE_SCHED_GETPARAM
}
/*------------------------------------------------------------------------------
* Run the encoder
*----------------------------------------------------------------------------*/
bool
DarkIce :: encode ( void ) throw ( Exception )
{
unsigned int len;
unsigned long bytes;
if ( !encConnector->open() ) {
throw Exception( __FILE__, __LINE__, "can't open connector");
}
bytes = dsp->getSampleRate() * dsp->getSampleSize() * duration;
len = encConnector->transfer( bytes, 4096, 1, 0 );
reportEvent( 1, len, "bytes transferred to the encoders");
encConnector->close();
return true;
}
/*------------------------------------------------------------------------------
* Run
*----------------------------------------------------------------------------*/
int
DarkIce :: run ( void ) throw ( Exception )
{
reportEvent( 3, "encoding");
if (enableRealTime) {
setRealTimeScheduling();
}
encode();
if (enableRealTime) {
setOriginalScheduling();
}
reportEvent( 3, "encoding ends");
return 0;
}
/*------------------------------------------------------------------------------
* Tell each sink to cut what they are doing, and start again.
*----------------------------------------------------------------------------*/
void
DarkIce :: cut ( void ) throw ()
{
reportEvent( 5, "cutting");
encConnector->cut();
reportEvent( 5, "cutting ends");
}
darkice-1.3/src/Connector.cpp 0000644 0001750 0001750 00000022624 12526421577 013146 0000000 0000000 /*------------------------------------------------------------------------------
Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved.
Tyrell DarkIce
File : Connector.cpp
Version : $Revision$
Author : $Author$
Location : $HeadURL$
Copyright notice:
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 3
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.
------------------------------------------------------------------------------*/
/* ============================================================ include files */
#include "Exception.h"
#include "Connector.h"
/* =================================================== local data structures */
/* ================================================ local constants & macros */
/*------------------------------------------------------------------------------
* File identity
*----------------------------------------------------------------------------*/
static const char fileid[] = "$Id$";
/* =============================================== local function prototypes */
/* ============================================================= module code */
/*------------------------------------------------------------------------------
* Initialize the object
*----------------------------------------------------------------------------*/
void
Connector :: init ( Source * source ) throw ( Exception )
{
this->source = source;
this->sinks = 0;
this->numSinks = 0;
}
/*------------------------------------------------------------------------------
* De-initialize the object
*----------------------------------------------------------------------------*/
void
Connector :: strip ( void ) throw ( Exception )
{
source = 0;
if ( sinks ) {
unsigned int u;
for ( u = 0; u < numSinks; ++u ) {
sinks[u] = 0;
}
delete[] sinks;
}
}
/*------------------------------------------------------------------------------
* Constructor
*----------------------------------------------------------------------------*/
Connector :: Connector ( const Connector & connector ) throw ( Exception )
{
unsigned int u;
init( connector.source.get());
for ( u = 0; u < connector.numSinks; ++u ) {
attach( connector.sinks[u].get() );
}
}
/*------------------------------------------------------------------------------
* Assignment operator
*----------------------------------------------------------------------------*/
Connector &
Connector :: operator= ( const Connector & connector ) throw ( Exception )
{
if ( this != &connector ) {
unsigned int u;
// first free everything
strip();
// then fill in
init( connector.source.get() );
for ( u = 0; u < connector.numSinks; ++u ) {
attach( connector.sinks[u].get() );
}
}
return *this;
}
/*------------------------------------------------------------------------------
* Attach a sink to the connector
*----------------------------------------------------------------------------*/
void
Connector :: attach ( Sink * sink ) throw ( Exception )
{
if ( !sinks ) {
numSinks = 1;
sinks = new Ref[1];
sinks[0] = sink;
} else {
unsigned int u;
Ref * s = new Ref[numSinks + 1];
for ( u = 0; u < numSinks; ++u ) {
s[u] = sinks[u].get();
}
s[numSinks] = sink;
delete[] sinks;
sinks = s;
++numSinks;
}
}
/*------------------------------------------------------------------------------
* Detach a sink to the connector
*----------------------------------------------------------------------------*/
bool
Connector :: detach ( Sink * sink ) throw ( Exception )
{
if ( numSinks == 0 ) {
return false;
} else if ( numSinks == 1 ) {
if ( sinks[0].get() != sink ) {
return false;
}
sinks[0] = 0;
delete[] sinks;
sinks = 0;
--numSinks;
return true;
} else {
unsigned int u;
unsigned int v;
unsigned int ix;
Ref * s;
ix = numSinks;
for ( u = 0; u < numSinks; ++u ) {
if ( sinks[u].get() == sink ) {
ix = u;
break;
}
}
if ( ix == numSinks ) {
return false;
}
s = new Ref[numSinks - 1];
for ( u = 0, v = 0; u < numSinks; ++u ) {
if ( u != ix ) {
s[v++] = sinks[u];
}
}
sinks[ix] = 0;
delete[] sinks;
sinks = s;
--numSinks;
return true;
}
}
/*------------------------------------------------------------------------------
* Open the source and all the sinks if needed
*----------------------------------------------------------------------------*/
bool
Connector :: open ( void ) throw ( Exception )
{
unsigned int u;
if ( !source->isOpen() ) {
if ( !source->open() ) {
return false;
}
}
for ( u = 0; u < numSinks; ++u ) {
if ( !sinks[u]->isOpen() ) {
if ( !sinks[u]->open() ) {
break;
}
}
}
// if not all could be opened, close those that were
if ( u < numSinks ) {
unsigned int v;
for ( v = 0; v < u; ++v ) {
sinks[v]->close();
}
source->close();
return false;
}
return true;
}
/*------------------------------------------------------------------------------
* Transfer some data from the source to the sink
*----------------------------------------------------------------------------*/
unsigned int
Connector :: transfer ( unsigned long bytes,
unsigned int bufSize,
unsigned int sec,
unsigned int usec ) throw ( Exception )
{
unsigned int u;
unsigned long b;
if ( numSinks == 0 ) {
return 0;
}
if ( bufSize == 0 ) {
return 0;
}
unsigned char * buf = new unsigned char[bufSize];
reportEvent( 6, "Connector :: transfer, bytes", bytes);
for ( b = 0; !bytes || b < bytes; ) {
unsigned int d = 0;
unsigned int e = 0;
if ( source->canRead( sec, usec) ) {
d = source->read( buf, bufSize);
// check for EOF
if ( d == 0 ) {
reportEvent( 3, "Connector :: transfer, EOF");
break;
}
for ( u = 0; u < numSinks; ++u ) {
if ( sinks[u]->canWrite( sec, usec) ) {
try {
// we expect the sink to accept all data written
e = sinks[u]->write( buf, d);
} catch ( Exception & e ) {
sinks[u]->close();
detach( sinks[u].get() );
reportEvent( 4,
"Connector :: transfer, sink removed, remaining",
numSinks);
if ( numSinks == 0 ) {
reportEvent( 4,
"Connector :: transfer, no more sinks");
delete[] buf;
return b;
}
// with the call to detach, numSinks gets 1 lower,
// and the next sink comes to sinks[u]
--u;
}
}
}
b += d;
} else {
reportEvent( 3, "Connector :: transfer, can't read");
break;
}
}
delete[] buf;
return b;
}
/*------------------------------------------------------------------------------
* Signal to each sink to cut what they've done so far, and start anew.
*----------------------------------------------------------------------------*/
void
Connector :: cut ( void ) throw ()
{
unsigned int u;
for ( u = 0; u < numSinks; ++u ) {
if ( sinks[u]->isOpen() ) {
sinks[u]->cut();
}
}
}
/*------------------------------------------------------------------------------
* Close the source and all the sinks if needed
*----------------------------------------------------------------------------*/
void
Connector :: close ( void ) throw ( Exception )
{
unsigned int u;
source->close();
for ( u = 0; u < numSinks; ++u ) {
sinks[u]->close();
}
}
darkice-1.3/src/BufferedSink.cpp 0000644 0001750 0001750 00000033313 12526421577 013560 0000000 0000000 /*------------------------------------------------------------------------------
Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved.
Tyrell DarkIce
File : BufferedSink.cpp
Version : $Revision$
Author : $Author$
Location : $HeadURL$
the buffer is filled like this:
buffer bufferEnd
| |
+----------+--------------------------+--------------+
|<---- valid data -------->|
outp inp
buffer bufferEnd
| |
+----------------+--------------+--------------------+
-- valid data -->| |--- valid data ----->
inp outp
Copyright notice:
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 3
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.
------------------------------------------------------------------------------*/
/* ============================================================ include files */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_STRING_H
#include
#else
#error need string.h
#endif
#include "Exception.h"
#include "BufferedSink.h"
/* =================================================== local data structures */
/* ================================================ local constants & macros */
/*------------------------------------------------------------------------------
* File identity
*----------------------------------------------------------------------------*/
static const char fileid[] = "$Id$";
/* =============================================== local function prototypes */
/* ============================================================= module code */
/*------------------------------------------------------------------------------
* Initialize the object
*----------------------------------------------------------------------------*/
void
BufferedSink :: init ( Sink * sink,
unsigned int size,
unsigned int chunkSize ) throw ( Exception )
{
if ( !sink ) {
throw Exception( __FILE__, __LINE__, "no sink");
}
this->sink = sink; // create a reference
this->chunkSize = chunkSize ? chunkSize : 1;
this->bufferSize = size;
// make bufferSize a multiple of chunkSize
this->bufferSize -= this->bufferSize % this->chunkSize;
this->peak = 0;
this->misalignment = 0;
this->buffer = new unsigned char[bufferSize];
this->bufferEnd = buffer + bufferSize;
this->inp = buffer;
this->outp = buffer;
this->bOpen = true;
this->openAttempts = 0;
}
/*------------------------------------------------------------------------------
* Copy Constructor
*----------------------------------------------------------------------------*/
BufferedSink :: BufferedSink ( const BufferedSink & buffer )
throw ( Exception )
{
init( buffer.sink.get(), buffer.bufferSize, buffer.chunkSize);
this->peak = buffer.peak;
this->misalignment = buffer.misalignment;
this->bOpen = buffer.bOpen;
this->openAttempts = buffer.openAttempts;
memcpy( this->buffer, buffer.buffer, this->bufferSize);
}
/*------------------------------------------------------------------------------
* De-initalize the object
*----------------------------------------------------------------------------*/
void
BufferedSink :: strip ( void ) throw ( Exception )
{
if ( isOpen() ) {
close();
}
sink = 0; // delete the reference
delete buffer;
}
/*------------------------------------------------------------------------------
* Assignment operator
*----------------------------------------------------------------------------*/
BufferedSink &
BufferedSink :: operator= ( const BufferedSink & buffer )
throw ( Exception )
{
if ( this != &buffer ) {
strip();
Sink::operator=( buffer );
init( buffer.sink.get(), buffer.bufferSize, buffer.chunkSize);
this->peak = buffer.peak;
this->misalignment = buffer.misalignment;
this->bOpen = buffer.bOpen;
this->openAttempts = buffer.openAttempts;
memcpy( this->buffer, buffer.buffer, this->bufferSize);
}
return *this;
}
/*------------------------------------------------------------------------------
* Store bufferSize bytes into the buffer
* All data is consumed. The return value is less then bufferSize only
* if the BufferedSink's internal buffer is smaller than bufferSize,
* thus can't hold that much
* The data to be stored is treated as parts with chunkSize size
* Only full chunkSize sized parts are stored
*----------------------------------------------------------------------------*/
unsigned int
BufferedSink :: store ( const void * buffer,
unsigned int bufferSize ) throw ( Exception )
{
const unsigned char * buf;
unsigned int size;
unsigned int i;
unsigned char * oldInp;
if ( !buffer ) {
throw Exception( __FILE__, __LINE__, "buffer is null");
}
if ( !bufferSize ) {
return 0;
}
unsigned int remaining = this->bufferSize - ( outp <= inp ? inp - outp :
(bufferEnd - outp) + (inp - this->buffer) );
// react only to the first overrun whenever there is a series of overruns
if ( remaining + chunkSize <= bufferSize && remaining > chunkSize ) {
reportEvent(3,"BufferedSink :: store, buffer overrun");
throw Exception( __FILE__, __LINE__,
"buffer overrun");
}
oldInp = inp;
buf = (const unsigned char *) buffer;
// adjust so it is a multiple of chunkSize
bufferSize -= bufferSize % chunkSize;
// cut the front of the supplied buffer if it wouldn't fit
if ( bufferSize > this->bufferSize ) {
size = this->bufferSize - 1;
size -= size % chunkSize; // keep it a multiple of chunkSize
buf += bufferSize - size;
} else {
size = bufferSize;
}
// copy the data into the buffer
i = bufferEnd - inp;
if ( (i % chunkSize) != 0 ) {
throw Exception( __FILE__, __LINE__, "copy quantity not aligned", i);
}
if ( size <= i ) {
// the place between inp and bufferEnd is
// big enough to hold the data
memcpy( inp, buf, size);
inp = slidePointer( inp, size);
// adjust outp, lose the data that was overwritten, if any
if ( outp > oldInp && outp <= inp ) {
outp = slidePointer( inp, chunkSize);
}
} else {
// the place between inp and bufferEnd is not
// big enough to hold the data
// writing will take place in two turns, once from
// inp -> bufferEnd, then from buffer ->
memcpy( inp, buf, i);
i = size - i;
if ( (i % chunkSize) != 0 ) {
throw Exception(__FILE__, __LINE__, "copy quantity not aligned", i);
}
memcpy( this->buffer, buf, i);
inp = slidePointer( this->buffer, i);
// adjust outp, lose the data that was overwritten, if any
if ( outp <= oldInp ) {
if ( outp < inp ) {
outp = slidePointer( inp, chunkSize);
}
} else {
outp = slidePointer( inp, chunkSize);
}
}
updatePeak();
if ( ((inp - this->buffer) % chunkSize) != 0 ) {
throw Exception( __FILE__, __LINE__,
"inp not aligned", inp - this->buffer);
}
if ( ((outp - this->buffer) % chunkSize) != 0 ) {
throw Exception( __FILE__, __LINE__,
"outp not aligned", outp - this->buffer);
}
return size;
}
/*------------------------------------------------------------------------------
* Write some data to the sink
* if len == 0, try to flush the buffer
*----------------------------------------------------------------------------*/
unsigned int
BufferedSink :: write ( const void * buf,
unsigned int len ) throw ( Exception )
{
unsigned int length = 0;
unsigned int soFar = 0;
unsigned char * b = (unsigned char *) buf;
if ( !buf ) {
throw Exception( __FILE__, __LINE__, "buf is null");
}
if ( !isOpen() ) {
return 0;
}
if ( !align() ) {
return 0;
}
if ( !sink->isOpen() && openAttempts < 10 ) {
// try to reopen underlying sink, because it has closed on its own
openAttempts++;
try {
if( sink->open() ) {
// if reopening succeeds, reset open attempts
openAttempts = 0;
}
} catch ( Exception &e ) {
reportEvent( 4,"BufferedSink :: write,",
"couldn't reopen underlying sink, attempt",
openAttempts, "/ 10" );
}
if( openAttempts == 10 ) {
// all the attempts have been used, give up
close();
throw Exception( __FILE__, __LINE__,
"reopen failed");
}
}
// make it a multiple of chunkSize
len -= len % chunkSize;
// try to write data from the buffer first, if any
if ( inp != outp ) {
unsigned int size = 0;
unsigned int total = 0;
if ( outp > inp ) {
// valuable data is between outp -> bufferEnd and buffer -> inp
// try to write the outp -> bufferEnd
// the rest will be written in the next if
size = bufferEnd - outp;
size -= size % chunkSize;
if( size > len * 2 ) {
// do not try to send the content of the entire buffer at once,
// but limit sending to a multiple of len
// this prevents a surge of data to underlying buffer
// which is important especially during a lot of packet loss
size = len * 2;
}
soFar = 0;
while ( outp > inp && soFar < size && sink->canWrite( 0, 0) ) {
try {
length = sink->write( outp + soFar, size - soFar);
} catch (Exception &e) {
length = 0;
reportEvent(3,"Exception caught in BufferedSink :: write1");
}
outp = slidePointer( outp, length);
soFar += length;
}
total += soFar;
}
if ( outp < inp ) {
// valuable data is between outp and inp
// in the previous if wrote all data from the end
// this part will write the rest
size = inp - outp;
if( size > len * 2 ) {
// prevent a surge of data to underlying buffer
size = len * 2;
}
soFar = 0;
while ( soFar < size && sink->canWrite( 0, 0) ) {
try {
length = sink->write( outp + soFar, size - soFar);
} catch (Exception &e) {
length = 0;
reportEvent(3,"Exception caught in BufferedSink :: write2" );
}
outp = slidePointer( outp, length);
soFar += length;
}
total += soFar;
}
while ( (outp - buffer) % chunkSize ) {
slidePointer( outp, 1);
}
// calulate the misalignment to chunkSize boundaries
misalignment = (chunkSize - (total % chunkSize)) % chunkSize;
}
if ( !align() ) {
return 0;
}
// the internal buffer is empty, try to write the fresh data
soFar = 0;
if ( inp == outp ) {
while ( soFar < len && sink->canWrite( 0, 0) ) {
try {
soFar += sink->write( b + soFar, len - soFar);
} catch (Exception &e) {
reportEvent(3,"Exception caught in BufferedSink :: write3");
}
}
}
length = soFar;
// calulate the misalignment to chunkSize boundaries
misalignment = (chunkSize - (length % chunkSize)) % chunkSize;
if ( length < len ) {
// if not all fresh could be written, store the remains
store( b + length, len - length);
}
updatePeak();
// tell them we ate everything up to chunkSize alignment
return len;
}
/*------------------------------------------------------------------------------
* Close the sink, lose all pending data
*----------------------------------------------------------------------------*/
void
BufferedSink :: close ( void ) throw ( Exception )
{
if ( !isOpen() ) {
return;
}
flush();
sink->close();
inp = outp = buffer;
bOpen = false;
}
darkice-1.3/src/IceCast2.h 0000644 0001750 0001750 00000017113 12526421577 012253 0000000 0000000 /*------------------------------------------------------------------------------
Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved.
Tyrell DarkIce
File : IceCast2.h
Version : $Revision$
Author : $Author$
Location : $HeadURL$
Copyright notice:
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 3
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 ICE_CAST2_H
#define ICE_CAST2_H
#ifndef __cplusplus
#error This is a C++ include file
#endif
/* ============================================================ include files */
#include "Sink.h"
#include "TcpSocket.h"
#include "CastSink.h"
/* ================================================================ constants */
/* =================================================================== macros */
/* =============================================================== data types */
/**
* Class representing output to an IceCast2 server with
* ice login
*
* @author $Author$
* @version $Revision$
*/
class IceCast2 : public CastSink
{
public:
/**
* Type for specifying the format of the stream.
*/
enum StreamFormat { mp3, mp2, oggVorbis, oggOpus, aac, aacp };
private:
/**
* The format of the stream.
*/
StreamFormat format;
/**
* Mount point of the stream on the server.
*/
char * mountPoint;
/**
* Description of the stream.
*/
char * description;
/**
* Initalize the object.
*
* @param mountPoint mount point of the stream on the server.
* @param remoteDumpFile remote dump file (may be NULL).
* @param description description of the stream.
* @exception Exception
*/
void
init ( StreamFormat format,
const char * mountPoint,
const char * description )
throw ( Exception );
/**
* De-initalize the object.
*
* @exception Exception
*/
void
strip ( void ) throw ( Exception );
protected:
/**
* Default constructor. Always throws an Exception.
*
* @exception Exception
*/
inline
IceCast2 ( void ) throw ( Exception )
{
throw Exception( __FILE__, __LINE__);
}
/**
* Log in to the server using the socket avialable.
*
* @return true if login was successful, false otherwise.
* @exception Exception
*/
virtual bool
sendLogin ( void ) throw ( Exception );
public:
/**
* Constructor.
*
* @param socket socket connection to the server.
* @param password password to the server.
* @param mountPoint mount point of the stream on the server.
* @param format the format of the stream.
* @param name name of the stream.
* @param description description of the stream.
* @param url URL associated with the stream.
* @param genre genre of the stream.
* @param bitRate bitrate of the stream (e.g. mp3 bitrate).
* @param isPublic is the stream public?
* @param streamDump an optional sink to dump the binary stream
* data to.
* @param bufferDuration duration of the BufferedSink buffer
* in seconds.
* @exception Exception
*/
inline
IceCast2 ( TcpSocket * socket,
const char * password,
const char * mountPoint,
StreamFormat format,
unsigned int bitRate,
const char * name = 0,
const char * description = 0,
const char * url = 0,
const char * genre = 0,
bool isPublic = false,
Sink * streamDump = 0 )
throw ( Exception )
: CastSink( socket,
password,
bitRate,
name,
url,
genre,
isPublic,
streamDump )
{
init( format, mountPoint, description);
}
/**
* Copy constructor.
*
* @param cs the IceCast2 to copy.
*/
inline
IceCast2( const IceCast2 & cs ) throw ( Exception )
: CastSink( cs )
{
init( cs.getFormat(),
cs.getMountPoint(),
cs.getDescription() );
}
/**
* Destructor.
*
* @exception Exception
*/
inline virtual
~IceCast2( void ) throw ( Exception )
{
strip();
}
/**
* Assignment operator.
*
* @param cs the IceCast2 to assign this to.
* @return a reference to this IceCast2.
* @exception Exception
*/
inline virtual IceCast2 &
operator= ( const IceCast2 & cs ) throw ( Exception )
{
if ( this != &cs ) {
strip();
CastSink::operator=( cs );
init( cs.getFormat(),
cs.getMountPoint(),
cs.getDescription() );
}
return *this;
}
/**
* Get the format of the stream.
*
* @return the format of the stream.
*/
inline StreamFormat
getFormat ( void ) const throw ()
{
return format;
}
/**
* Get the mount point of the stream on the server.
*
* @return the mount point of the stream on the server.
*/
inline const char *
getMountPoint ( void ) const throw ()
{
return mountPoint;
}
/**
* Get the description of the stream.
*
* @return the description of the stream.
*/
inline const char *
getDescription ( void ) const throw ()
{
return description;
}
};
/* ================================================= external data structures */
/* ====================================================== function prototypes */
#endif /* ICE_CAST2_H */
darkice-1.3/src/aacPlusEncoder.h 0000644 0001750 0001750 00000041666 12750450634 013553 0000000 0000000 /*------------------------------------------------------------------------------
Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved.
Tyrell DarkIce
File : aacPlusEncoder.h
Version : $Revision$
Author : $Author$
Location : $HeadURL$
Copyright notice:
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 3
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 AACP_ENCODER_H
#define AACP_ENCODER_H
#ifndef __cplusplus
#error This is a C++ include file
#endif
/* ============================================================ include files */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_AACPLUS_LIB
#include
#else
#error configure with aacplus
#endif
#include
#include
#include "Ref.h"
#include "Exception.h"
#include "Reporter.h"
#include "AudioEncoder.h"
#include "Sink.h"
#ifdef HAVE_SRC_LIB
#include
#else
#include "aflibConverter.h"
#endif
/* ================================================================ constants */
/* =================================================================== macros */
/* =============================================================== data types */
/**
* A class representing aacplus AAC+ encoder.
*
* @author $Author$
* @version $Revision$
*/
class aacPlusEncoder : public AudioEncoder, public virtual Reporter
{
private:
/**
* A flag to indicate if the encoding session is open.
*/
bool aacplusOpen;
/**
* Resample ratio
*/
double resampleRatio;
/**
* sample rate converter object for possible resampling
*/
#ifdef HAVE_SRC_LIB
SRC_STATE *converter;
SRC_DATA converterData;
float *resampledOffset;
#else
aflibConverter *converter;
short *resampledOffset;
#endif
unsigned int resampledOffsetSize;
/**
* The Sink to dump aac+ data to
*/
Ref sink;
/**
* The handle to the AAC+ encoder instance.
*/
aacplusEncHandle encoderHandle;
/**
* The maximum number of input samples to supply to the encoder.
*/
unsigned long inputSamples;
/**
* The maximum number of output bytes the encoder returns in one call.
*/
unsigned long maxOutputBytes;
/**
* Lowpass filter. Sound frequency in Hz, from where up the
* input is cut.
*/
int lowpass;
/**
* Initialize the object.
*
* @param sink the sink to send mp3 output to
* @exception Exception
*/
inline void
init ( Sink * sink, int lowpass) throw (Exception)
{
this->aacplusOpen = false;
this->sink = sink;
this->lowpass = lowpass;
/* TODO: if we have float as input, we don't need conversion */
if ( getInBitsPerSample() != 16 && getInBitsPerSample() != 32 ) {
throw Exception( __FILE__, __LINE__,
"specified bits per sample not supported",
getInBitsPerSample() );
}
if ( getInChannel() > 2 ) {
throw Exception( __FILE__, __LINE__,
"unsupported number of input channels for the encoder",
getInChannel() );
}
if ( getOutChannel() > 2 ) {
throw Exception( __FILE__, __LINE__,
"unsupported number of output channels for the encoder",
getOutChannel() );
}
if ( getOutSampleRate() == getInSampleRate() ) {
resampleRatio = 1;
converter = 0;
} else if (getInBitsPerSample() == 16) {
resampleRatio = ( (double) getOutSampleRate() /
(double) getInSampleRate() );
// Determine if we can use linear interpolation.
// The inverse of the ratio must be a power of two for linear mode to
// be of sufficient quality.
bool useLinear = true;
double inverse = 1 / resampleRatio;
int integer = (int) inverse;
// Check that the inverse of the ratio is an integer
if( integer == inverse ) {
while( useLinear && integer ) { // Loop through the bits
// If the lowest order bit is not the only one set
if( integer & 1 && integer != 1 ) {
// Not a power of two; cannot use linear
useLinear = false;
} else {
// Shift all the bits over and try again
integer >>= 1;
}
}
} else {
useLinear = false;
}
// If we get here and useLinear is still true, then we have
// a power of two.
// open the aflibConverter in
// - high quality
// - linear or quadratic (non-linear) based on algorithm
// - not filter interpolation
#ifdef HAVE_SRC_LIB
int srcError = 0;
converter = src_new(useLinear == true ? SRC_LINEAR : SRC_SINC_FASTEST,
getInChannel(), &srcError);
if(srcError)
throw Exception (__FILE__, __LINE__, "libsamplerate error: ", src_strerror (srcError));
#else
converter = new aflibConverter( true, useLinear, false);
#endif
} else {
throw Exception( __FILE__, __LINE__,
"specified bits per sample with samplerate conversion not supported",
getInBitsPerSample() );
}
}
/**
* De-initialize the object.
*
* @exception Exception
*/
inline void
strip ( void ) throw ( Exception )
{
if ( converter ) {
#ifdef HAVE_SRC_LIB
delete [] converterData.data_in;
src_delete (converter);
#else
delete converter;
#endif
delete [] resampledOffset;
}
}
protected:
/**
* Default constructor. Always throws an Exception.
*
* @exception Exception
*/
inline
aacPlusEncoder ( void ) throw ( Exception )
{
throw Exception( __FILE__, __LINE__);
}
public:
/**
* Constructor.
*
* @param sink the sink to send mp3 output to
* @param inSampleRate sample rate of the input.
* @param inBitsPerSample number of bits per sample of the input.
* @param inChannel number of channels of the input.
* @param inBigEndian shows if the input is big or little endian
* @param outBitrateMode the bit rate mode of the output.
* @param outBitrate bit rate of the output (kbits/sec).
* @param outQuality the quality of the stream.
* @param outSampleRate sample rate of the output.
* If 0, inSampleRate is used.
* @param outChannel number of channels of the output.
* If 0, inChannel is used.
* @param lowpass frequency threshold for the lowpass filter.
* Input above this frequency is cut.
* If 0, aacplus's default values are used,
* which depends on the out sample rate.
* @exception Exception
*/
inline
aacPlusEncoder ( Sink * sink,
unsigned int inSampleRate,
unsigned int inBitsPerSample,
unsigned int inChannel,
bool inBigEndian,
BitrateMode outBitrateMode,
unsigned int outBitrate,
double outQuality,
unsigned int outSampleRate = 0,
unsigned int outChannel = 0,
int lowpass = 0)
throw ( Exception )
: AudioEncoder ( sink,
inSampleRate,
inBitsPerSample,
inChannel,
inBigEndian,
outBitrateMode,
outBitrate,
outQuality,
outSampleRate,
outChannel )
{
init( sink, lowpass);
}
/**
* Constructor.
*
* @param sink the sink to send mp3 output to
* @param as get input sample rate, bits per sample and channels
* from this AudioSource.
* @param outBitrateMode the bit rate mode of the output.
* @param outBitrate bit rate of the output (kbits/sec).
* @param outQuality the quality of the stream.
* @param outSampleRate sample rate of the output.
* If 0, input sample rate is used.
* @param outChannel number of channels of the output.
* If 0, input channel is used.
* @param lowpass frequency threshold for the lowpass filter.
* Input above this frequency is cut.
* If 0, aacplus's default values are used,
* which depends on the out sample rate.
* @exception Exception
*/
inline
aacPlusEncoder ( Sink * sink,
const AudioSource * as,
BitrateMode outBitrateMode,
unsigned int outBitrate,
double outQuality,
unsigned int outSampleRate = 0,
unsigned int outChannel = 0,
int lowpass = 0)
throw ( Exception )
: AudioEncoder ( sink,
as,
outBitrateMode,
outBitrate,
outQuality,
outSampleRate,
outChannel )
{
init( sink, lowpass );
}
/**
* Copy constructor.
*
* @param encoder the aacPlusEncoder to copy.
*/
inline
aacPlusEncoder ( const aacPlusEncoder & encoder )
throw ( Exception )
: AudioEncoder( encoder )
{
init( encoder.sink.get(), encoder.lowpass);
}
/**
* Destructor.
*
* @exception Exception
*/
inline virtual
~aacPlusEncoder ( void ) throw ( Exception )
{
if ( isOpen() ) {
close();
}
strip();
}
/**
* Assignment operator.
*
* @param encoder the aacPlusEncoder to assign this to.
* @return a reference to this aacPlusEncoder.
* @exception Exception
*/
inline virtual aacPlusEncoder &
operator= ( const aacPlusEncoder & encoder ) throw ( Exception )
{
if ( this != &encoder ) {
strip();
AudioEncoder::operator=( encoder);
init( encoder.sink.get(), encoder.lowpass);
}
return *this;
}
/**
* Get the version string of the underlying aacplus library.
*
* @return the version string of the underlying aacplus library.
*/
inline const char *
getAacPlusVersion( void )
{
char * id;
//char * copyright;
/* aacplusEncGetVersion(&id, ©right); */
return id;
}
/**
* Check whether encoding is in progress.
*
* @return true if encoding is in progress, false otherwise.
*/
inline virtual bool
isRunning ( void ) const throw ()
{
return isOpen();
}
/**
* Start encoding. This function returns as soon as possible,
* with encoding started in the background.
*
* @return true if encoding has started, false otherwise.
* @exception Exception
*/
inline virtual bool
start ( void ) throw ( Exception )
{
return open();
}
/**
* Stop encoding. Stops the encoding running in the background.
*
* @exception Exception
*/
inline virtual void
stop ( void ) throw ( Exception )
{
return close();
}
/**
* Open an encoding session.
*
* @return true if opening was successfull, false otherwise.
* @exception Exception
*/
virtual bool
open ( void ) throw ( Exception );
/**
* Check if the encoding session is open.
*
* @return true if the encoding session is open, false otherwise.
*/
inline virtual bool
isOpen ( void ) const throw ()
{
return aacplusOpen;
}
/**
* Check if the encoder is ready to accept data.
*
* @param sec the maximum seconds to block.
* @param usec micro seconds to block after the full seconds.
* @return true if the encoder is ready to accept data,
* false otherwise.
* @exception Exception
*/
inline virtual bool
canWrite ( unsigned int sec,
unsigned int usec ) throw ( Exception )
{
if ( !isOpen() ) {
return false;
}
return true;
}
/**
* Write data to the encoder.
* Buf is expected to be a sequence of big-endian 16 bit values,
* with left and right channels interleaved. Len is the number of
* bytes, must be a multiple of 4.
*
* @param buf the data to write.
* @param len number of bytes to write from buf.
* @return the number of bytes written (may be less than len).
* @exception Exception
*/
virtual unsigned int
write ( const void * buf,
unsigned int len ) throw ( Exception );
/**
* Flush all data that was written to the encoder to the underlying
* connection.
*
* @exception Exception
*/
virtual void
flush ( void ) throw ( Exception );
/**
* Close the encoding session.
*
* @exception Exception
*/
virtual void
close ( void ) throw ( Exception );
};
/* ================================================= external data structures */
/* ====================================================== function prototypes */
#endif /* AACP_ENCODER_H */
darkice-1.3/src/OssDspSource.cpp 0000644 0001750 0001750 00000017725 12750450634 013611 0000000 0000000 /*------------------------------------------------------------------------------
Copyright (c) 2000-2007 Tyrell Corporation. All rights reserved.
Tyrell DarkIce
File : OssDspSource.cpp
Version : $Revision$
Author : $Author$
Location : $HeadURL$
Copyright notice:
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 3
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.
------------------------------------------------------------------------------*/
/* ============================================================ include files */
#include "OssDspSource.h"
#ifdef SUPPORT_OSS_DSP
// only compile this code if there is support for it
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_UNISTD_H
#include
#else
#error need unistd.h
#endif
#ifdef HAVE_STRING_H
#include
#else
#error need string.h
#endif
#ifdef HAVE_SYS_TYPES_H
#include
#else
#error need sys/types.h
#endif
#ifdef HAVE_SYS_STAT_H
#include
#else
#error need sys/stat.h
#endif
#ifdef HAVE_FCNTL_H
#include
#else
#error need fcntl.h
#endif
#ifdef HAVE_SYS_TIME_H
#include
#else
#error need sys/time.h
#endif
#ifdef HAVE_SYS_IOCTL_H
#include
#else
#error need sys/ioctl.h
#endif
#ifdef HAVE_SIGNAL_H
#include
#else
#error need signal.h
#endif
#ifdef HAVE_SYS_SOUNDCARD_H
#include