./PaxHeaders.32572/drumstick-1.1.30000644000000000000000000000013213532747316013353 xustar0030 mtime=1567346382.729999891 30 atime=1567346382.729999891 30 ctime=1567346382.729999891 drumstick-1.1.3/0000755000175000001440000000000013532747316014064 5ustar00pedrousers00000000000000drumstick-1.1.3/PaxHeaders.32572/configure_dbg0000644000000000000000000000013213532747316016013 xustar0030 mtime=1567346382.729999891 30 atime=1567346382.729999891 30 ctime=1567346382.729999891 drumstick-1.1.3/configure_dbg0000755000175000001440000000040013532747316016601 0ustar00pedrousers00000000000000#!/bin/bash # a typical configuration for development usage... mkdir -p build cd build cmake .. -DCMAKE_CXX_FLAGS="-W -Wall" \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_INSTALL_PREFIX=/usr/local \ -DSTATIC_DRUMSTICK=YES \ -DUSE_DBUS=YES \ -DENABLE_PCH=NO $* drumstick-1.1.3/PaxHeaders.32572/library0000644000000000000000000000013013532747316014660 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.729999891 29 ctime=1567346382.71399987 drumstick-1.1.3/library/0000755000175000001440000000000013532747316015530 5ustar00pedrousers00000000000000drumstick-1.1.3/library/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316017477 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.729999891 30 ctime=1567346382.693999845 drumstick-1.1.3/library/CMakeLists.txt0000644000175000001440000000154313532747316020273 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . if(ALSA_FOUND) add_subdirectory(alsa) endif() add_subdirectory(file) add_subdirectory(rt) add_subdirectory(rt-backends) drumstick-1.1.3/library/PaxHeaders.32572/include0000644000000000000000000000013013532747316016303 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.729999891 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/0000755000175000001440000000000013532747316017153 5ustar00pedrousers00000000000000drumstick-1.1.3/library/include/PaxHeaders.32572/drumstick.h0000644000000000000000000000013013532747316020536 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.729999891 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick.h0000644000175000001440000000275513532747316021342 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DRUMSTICK_H #define DRUMSTICK_H #include /** * @file drumstick.h * The main header that a program can include to use all drumstick features. */ #if defined(Q_OS_LINUX) // ALSA library interface #include #include #include #include #include #include #include #include #endif // File formats #include #include #include // RealTime interfaces #include #include #include #endif /*DRUMSTICK_H*/ drumstick-1.1.3/library/include/PaxHeaders.32572/drumstick0000644000000000000000000000013013532747316020310 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.729999891 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick/0000755000175000001440000000000013532747316021160 5ustar00pedrousers00000000000000drumstick-1.1.3/library/include/drumstick/PaxHeaders.32572/alsaport.h0000644000000000000000000000013013532747316022363 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.729999891 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick/alsaport.h0000644000175000001440000001423613532747316023164 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DRUMSTICK_ALSAPORT_H #define DRUMSTICK_ALSAPORT_H #include "subscription.h" #include /** * @file alsaport.h * Classes managing ALSA Sequencer ports. * @defgroup ALSAPort ALSA Sequencer Ports * @{ */ namespace drumstick { class MidiClient; /** * Port information container */ class DRUMSTICK_EXPORT PortInfo { friend class MidiPort; friend class ClientInfo; friend class MidiClient; public: PortInfo(); PortInfo(const PortInfo& other); PortInfo(snd_seq_port_info_t* other); PortInfo(MidiClient* seq, const int client, const int port); PortInfo(MidiClient* seq, const int port); virtual ~PortInfo(); PortInfo* clone(); PortInfo& operator=(const PortInfo& other); int getSizeOfInfo() const; int getClient(); int getPort(); /** Gets the client name. @see setClientName() */ QString getClientName() const { return m_ClientName; } const snd_seq_addr_t* getAddr(); QString getName(); unsigned int getCapability(); unsigned int getType(); int getMidiChannels(); int getMidiVoices(); int getSynthVoices(); int getReadUse(); int getWriteUse(); int getPortSpecified(); void setClient(int client); void setPort(int port); void setAddr(const snd_seq_addr_t* addr); void setName( QString const& name ); void setCapability(unsigned int capability); void setType(unsigned int type); void setMidiChannels(int channels); void setMidiVoices(int voices); void setSynthVoices(int voices); void setPortSpecified(int val); SubscribersList getReadSubscribers() const; SubscribersList getWriteSubscribers() const; bool getTimestamping(); bool getTimestampReal(); int getTimestampQueue(); void setTimestamping(bool value); void setTimestampReal(bool value); void setTimestampQueue(int queueId); protected: void readSubscribers(MidiClient* seq); void freeSubscribers(); /** * Sets the client name. @see getClientName() * @param name Client name */ void setClientName(QString name) { m_ClientName = name; } private: snd_seq_port_info_t* m_Info; QString m_ClientName; SubscribersList m_ReadSubscribers; SubscribersList m_WriteSubscribers; }; /** * List of port information objects */ typedef QList PortInfoList; /** * Port management. * * This class represents an ALSA sequencer port. */ class DRUMSTICK_EXPORT MidiPort : public QObject { Q_OBJECT friend class MidiClient; public: MidiPort( QObject* parent = 0 ); virtual ~MidiPort(); void attach( MidiClient* seq ); void detach(); void subscribe( Subscription* subs ); void unsubscribe( Subscription* subs ); void unsubscribeAll(); void unsubscribeTo( QString const& name ); void unsubscribeTo( PortInfo* port ); void unsubscribeTo( const snd_seq_addr_t* addr ); void unsubscribeFrom( QString const& name ); void unsubscribeFrom( PortInfo* port ); void unsubscribeFrom( const snd_seq_addr_t* addr ); void subscribeTo( PortInfo* port); void subscribeTo( int client, int port ); void subscribeTo( QString const& name ); void subscribeFrom( PortInfo* port ); void subscribeFrom( int client, int port ); void subscribeFrom( QString const& name ); void subscribeFromAnnounce(); void updateSubscribers(); SubscriptionsList getSubscriptions() const; PortInfoList getReadSubscribers(); PortInfoList getWriteSubscribers(); void updateConnectionsTo(const PortInfoList& desired); void updateConnectionsFrom(const PortInfoList& desired); static bool containsAddress(const snd_seq_addr_t* addr, const PortInfoList& lst); void applyPortInfo(); QString getPortName(); void setPortName( QString const& newName); int getPortId(); unsigned int getCapability(); void setCapability( unsigned int newValue); unsigned int getPortType(); void setPortType( unsigned int newValue); int getMidiChannels(); void setMidiChannels(int newValue); int getMidiVoices(); void setMidiVoices(int newValue); int getSynthVoices(); void setSynthVoices(int newValue); bool getTimestamping(); bool getTimestampReal(); int getTimestampQueue(); void setTimestamping(bool value); void setTimestampReal(bool value); void setTimestampQueue(int queueId); signals: /** * Signal emitted when an internal subscription is done. * @param port MIDI port object pointer * @param subs Subscription object pointer */ void subscribed(MidiPort* port, Subscription* subs); /** * Signal emitted when the MidiClient has changed * @param port MIDI port object pinter * @param seq MidiClient object pointer */ void midiClientChanged(MidiPort* port, MidiClient* seq); /** * Signal emitted when the port is attached to a MidiClient * @param port MIDI port object pointer */ void attached(MidiPort* port); /** * Signal emitted when the port is detached from a MidiClient * @param port MIDI port object pointer */ void detached(MidiPort* port); protected: PortInfo* getPortInfo(); void freeSubscriptions(); void setMidiClient( MidiClient* seq ); private: MidiClient* m_MidiClient; PortInfo m_Info; bool m_Attached; SubscriptionsList m_Subscriptions; }; /** * List of Ports instances. */ typedef QList MidiPortList; } /** @} */ #endif //DRUMSTICK_ALSAPORT_H drumstick-1.1.3/library/include/drumstick/PaxHeaders.32572/macros.h0000644000000000000000000000013013532747316022022 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.729999891 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick/macros.h0000644000175000001440000000262213532747316022617 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DRUMSTICK_MACROS_H #define DRUMSTICK_MACROS_H #include /** * @file macros.h * Drumstick visibility macros * @defgroup Common Common Functionality * @{ */ #if !defined(DRUMSTICK_EXPORT) # if defined(DRUMSTICK_STATIC) # define DRUMSTICK_EXPORT # else # if defined(drumstick_alsa_EXPORTS) || defined(drumstick_file_EXPORTS) || defined(drumstick_rt_EXPORTS) # define DRUMSTICK_EXPORT Q_DECL_EXPORT # else # if defined(Q_OS_WIN) # define DRUMSTICK_EXPORT Q_DECL_IMPORT # else # define DRUMSTICK_EXPORT Q_DECL_EXPORT # endif # endif # endif #endif /** @} */ #endif /* DRUMSTICK_MACROS_H */ drumstick-1.1.3/library/include/drumstick/PaxHeaders.32572/qsmf.h0000644000000000000000000000013013532747316021504 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.729999891 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick/qsmf.h0000644000175000001440000002527413532747316022311 0ustar00pedrousers00000000000000/* Standard MIDI File component Copyright (C) 2006-2019, Pedro Lopez-Cabanillas Based on midifile.c by Tim Thompson, M.Czeiszperger and Greg Lee This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DRUMSTICK_QSMF_H #define DRUMSTICK_QSMF_H #include "macros.h" #include class QDataStream; /** * @file qsmf.h * Standard MIDI Files Input/Output * @defgroup SMF Standard MIDI Files management (I/O) * @{ */ namespace drumstick { #define MThd 0x4d546864 /**< SMF Header prefix */ #define MTrk 0x4d54726b /**< SMF Track prefix */ /* Standard MIDI Files meta event definitions */ #define meta_event 0xff /**< SMF Meta Event prefix */ #define sequence_number 0x00 /**< SMF Sequence number */ #define text_event 0x01 /**< SMF Text event */ #define copyright_notice 0x02 /**< SMF Copyright notice */ #define sequence_name 0x03 /**< SMF Sequence name */ #define instrument_name 0x04 /**< SMF Instrument name */ #define lyric 0x05 /**< SMF Lyric */ #define marker 0x06 /**< SMF Marker */ #define cue_point 0x07 /**< SMF Cue point */ #define forced_channel 0x20 /**< SMF Forced MIDI channel */ #define forced_port 0x21 /**< SMF Forced MIDI port */ #define end_of_track 0x2f /**< SMF End of track */ #define set_tempo 0x51 /**< SMF Tempo change */ #define smpte_offset 0x54 /**< SMF SMPTE offset */ #define time_signature 0x58 /**< SMF Time signature */ #define key_signature 0x59 /**< SMF Key signature */ #define sequencer_specific 0x7f /**< SMF Sequencer specific */ /* MIDI status commands most significant bit is 1 */ #define note_off 0x80 /**< MIDI event Note Off */ #define note_on 0x90 /**< MIDI event Note On */ #define poly_aftertouch 0xa0 /**< MIDI event Polyphonic pressure */ #define control_change 0xb0 /**< MIDI event Control change */ #define program_chng 0xc0 /**< MIDI event Program change */ #define channel_aftertouch 0xd0 /**< MIDI event Channel after-touch */ #define pitch_wheel 0xe0 /**< MIDI event Bender */ #define system_exclusive 0xf0 /**< MIDI event System Exclusive begin */ #define end_of_sysex 0xf7 /**< MIDI event System Exclusive end */ #define midi_command_mask 0xf0 /**< Mask to extract the command from the status byte */ #define midi_channel_mask 0x0f /**< Mask to extract the channel from the status byte */ #define major_mode 0 /**< Major mode scale */ #define minor_mode 1 /**< Minor mode scale */ /** * Standard MIDI Files input/output * * This class is used to parse and encode Standard MIDI Files (SMF) */ class DRUMSTICK_EXPORT QSmf : public QObject { Q_OBJECT public: QSmf(QObject * parent = nullptr); virtual ~QSmf(); void readFromStream(QDataStream *stream); void readFromFile(const QString& fileName); void writeToStream(QDataStream *stream); void writeToFile(const QString& fileName); void writeMetaEvent(long deltaTime, int type, const QByteArray& data); void writeMetaEvent(long deltaTime, int type, const QString& data); void writeMetaEvent(long deltaTime, int type, int data); void writeMetaEvent(long deltaTime, int type); void writeMidiEvent(long deltaTime, int type, int chan, int b1); void writeMidiEvent(long deltaTime, int type, int chan, int b1, int b2); void writeMidiEvent(long deltaTime, int type, int chan, const QByteArray& data); void writeMidiEvent(long deltaTime, int type, long len, char* data); void writeTempo(long deltaTime, long tempo); void writeBpmTempo(long deltaTime, int tempo); void writeTimeSignature(long deltaTime, int num, int den, int cc, int bb); void writeKeySignature(long deltaTime, int tone, int mode); void writeSequenceNumber(long deltaTime, int seqnum); long getCurrentTime(); long getCurrentTempo(); long getRealTime(); long getFilePos(); int getDivision(); void setDivision(int division); int getTracks(); void setTracks(int tracks); int getFileFormat(); void setFileFormat(int fileFormat); QTextCodec* getTextCodec(); void setTextCodec(QTextCodec *codec); signals: /** * Emitted for a SMF read or write error * @param errorStr Error string */ void signalSMFError(const QString& errorStr); /** * Emitted after reading a SMF header * @param format SMF format (0/1) * @param ntrks Number pof tracks * @param division Division (resolution in ticks per quarter note) */ void signalSMFHeader(int format, int ntrks, int division); /** * Emitted after reading a Note On message * @param chan MIDI Channel * @param pitch MIDI Note * @param vol Velocity */ void signalSMFNoteOn(int chan, int pitch, int vol); /** * Emitted after reading a Note Off message * @param chan MIDI Channel * @param pitch MIDI Note * @param vol Velocity */ void signalSMFNoteOff(int chan, int pitch, int vol); /** * Emitted after reading a Polyphonic Aftertouch message * @param chan MIDI Channel * @param pitch MIDI Note * @param press Pressure amount */ void signalSMFKeyPress(int chan, int pitch, int press); /** * Emitted after reading a Control Change message * @param chan MIDI Channel * @param ctl MIDI Controller * @param value Control value */ void signalSMFCtlChange(int chan, int ctl, int value); /** * Emitted after reading a Bender message * @param chan MIDI Channel * @param value Bender value */ void signalSMFPitchBend(int chan, int value); /** * Emitted after reading a Program change message * @param chan MIDI Channel * @param patch Program number */ void signalSMFProgram(int chan, int patch); /** * Emitted after reading a Channel Aftertouch message * @param chan MIDI Channel * @param press Pressure amount */ void signalSMFChanPress(int chan, int press); /** * Emitted after reading a System Exclusive message * @param data Sysex bytes */ void signalSMFSysex(const QByteArray& data); /** * Emitted after reading a Sequencer specific message * @param data Message data */ void signalSMFSeqSpecific(const QByteArray& data); /** * Emitted after reading an unregistered SMF Meta message * @param typ Message type * @param data Message data * @since 0.2.0 */ void signalSMFMetaUnregistered(int typ, const QByteArray& data); /** * Emitted after reading any SMF Meta message * @param typ Message type * @param data Message data */ void signalSMFMetaMisc(int typ, const QByteArray& data); /** * Emitted after reading a Sequence number message * @param seq Sequence number */ void signalSMFSequenceNum(int seq); /** * Emitted after reading a Forced channel message * @param channel MIDI Channel */ void signalSMFforcedChannel(int channel); /** * Emitted after reading a Forced port message * @param port Port number */ void signalSMFforcedPort(int port); /** * Emitted after reading a SMF text message * @param typ Text type * @param data Text data */ void signalSMFText(int typ, const QString& data); /** * Emitted after reading a SMPT offset message * @param b0 Hours * @param b1 Minutes * @param b2 Seconds * @param b3 Frames * @param b4 Fractional frames */ void signalSMFSmpte(int b0, int b1, int b2, int b3, int b4); /** * Emitted after reading a SMF Time signature message * @param b0 Numerator * @param b1 Denominator (exponent in a power of two) * @param b2 Number of MIDI clocks per metronome click * @param b3 Number of notated 32nd notes per 24 MIDI clocks */ void signalSMFTimeSig(int b0, int b1, int b2, int b3); /** * Emitted after reading a SMF Key Signature smessage * @param b0 Number of alterations (negative=flats, positive=sharps) * @param b1 Scale Mode (0=major, 1=minor) */ void signalSMFKeySig(int b0, int b1); /** * Emitted after reading a Tempo Change message * @param tempo Microseconds per quarter note */ void signalSMFTempo(int tempo); /** * Emitted after reading a End-Of-Track message */ void signalSMFendOfTrack(); /** * Emitted after reading a track prefix */ void signalSMFTrackStart(); /** * Emitted after a track has finished */ void signalSMFTrackEnd(); /** * Emitted to request the user to write the tempo track. * This is the first track in a format 1 SMF. */ void signalSMFWriteTempoTrack(); /** * Emitted to request the user to write a track. * @param track Track number */ void signalSMFWriteTrack(int track); private: /** * Tempo change within a SMF or sequence */ struct QSmfRecTempo { quint64 tempo; quint64 time; }; class QSmfPrivate; QSmfPrivate *d; void SMFRead(); void SMFWrite(); quint8 getByte(); void putByte(quint8 value); void readHeader(); void readTrack(); quint16 to16bit(quint8 c1, quint8 c2); quint32 to32bit(quint8 c1, quint8 c2, quint8 c3, quint8 c4); quint16 read16bit(); quint32 read32bit(); void write16bit(quint16 data); void write32bit(quint32 data); void writeVarLen(quint64 value); double ticksToSecs(quint64 ticks, quint16 division, quint64 tempo); long readVarLen(); void readExpected(const QString& s); void addTempo(quint64 tempo, quint64 time); quint64 findTempo(); void SMFError(const QString& s); void channelMessage(quint8 status, quint8 c1, quint8 c2); void msgInit(); void msgAdd(quint8 b); void metaEvent(quint8 b); void sysEx(); void badByte(quint8 b, int p); quint8 lowerByte(quint16 x); quint8 upperByte(quint16 x); bool endOfSmf(); void writeHeaderChunk(int format, int ntracks, int division); void writeTrackChunk(int track); }; } /* namespace drumstick */ /** @} */ #endif /* DRUMSTICK_QSMF_H */ drumstick-1.1.3/library/include/drumstick/PaxHeaders.32572/backendmanager.h0000644000000000000000000000013013532747316023460 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.729999891 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick/backendmanager.h0000644000175000001440000000623713532747316024263 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef BACKENDMANAGER_H #define BACKENDMANAGER_H #include #include "macros.h" #include "rtmidiinput.h" #include "rtmidioutput.h" /** * @file backendmanager.h * Realtime MIDI input/output multiplatform classes * @defgroup RT Realtime MIDI (I/O) * @{ */ namespace drumstick { namespace rt { const QString QSTR_DRUMSTICK(QLatin1Literal("drumstick")); const QString QSTR_DRUMSTICKRT(QLatin1Literal("DRUMSTICKRT")); const QString QSTR_DRUMSTICKRT_GROUP(QLatin1Literal("DrumstickRT")); const QString QSTR_DRUMSTICKRT_PUBLICNAMEIN(QLatin1Literal("PublicNameIN")); const QString QSTR_DRUMSTICKRT_PUBLICNAMEOUT(QLatin1Literal("PublicNameOUT")); const QString QSTR_DRUMSTICKRT_EXCLUDED(QLatin1Literal("ExcludedNames")); const QString QSTR_DRUMSTICKRT_PATH(QLatin1Literal("BackendsPath")); /** * @brief The BackendManager class manages lists of dynamic and static * backends for applications based on drumstick-rt */ class DRUMSTICK_EXPORT BackendManager { public: /** * @brief BackendManager constructor */ explicit BackendManager(); /** * @brief ~BackendManager destructor */ virtual ~BackendManager(); /** * @brief refresh the list of backends * @param settings Program settings */ void refresh(QSettings* settings = 0); /** * @brief availableInputs * @return list of available MIDI inputs */ QList availableInputs(); /** * @brief availableOutputs * @return list of available MIDI outputs */ QList availableOutputs(); /** * @brief defaultPaths * @return list of paths for backends search */ QStringList defaultPaths(); /** * @brief inputBackendByName * @param name The name of some input backend * @return Input backend instance if available */ MIDIInput* inputBackendByName(const QString name); /** * @brief outputBackendByName * @param name The name of some output backend * @return Output backend instance if available */ MIDIOutput* outputBackendByName(const QString name); private: class BackendManagerPrivate; BackendManagerPrivate *d; }; }} /** @} */ #endif // BACKENDMANAGER_H drumstick-1.1.3/library/include/drumstick/PaxHeaders.32572/alsaqueue.h0000644000000000000000000000013013532747316022523 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.729999891 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick/alsaqueue.h0000644000175000001440000001374013532747316023323 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DRUMSTICK_ALSAQUEUE_H #define DRUMSTICK_ALSAQUEUE_H #include "drumstickcommon.h" /** * @file alsaqueue.h * Classes managing ALSA Sequencer queues * @defgroup ALSAQueue ALSA Sequencer Queues * @{ */ namespace drumstick { /** * This is the value for the base skew used in ALSA. It is not possible * to assign an arbitrary value (ALSA version <= 1.0.20). */ #define SKEW_BASE 0x10000 class MidiClient; class TimerId; /** * Queue information container. * * This class is used to hold some properties about an ALSA queue object. */ class DRUMSTICK_EXPORT QueueInfo { friend class MidiQueue; public: QueueInfo(); QueueInfo(const QueueInfo& other); QueueInfo(snd_seq_queue_info_t* other); virtual ~QueueInfo(); QueueInfo* clone(); QueueInfo& operator=(const QueueInfo& other); int getInfoSize() const; int getId(); QString getName(); int getOwner(); bool isLocked(); unsigned int getFlags(); void setName(QString value); void setOwner(int value); void setLocked(bool locked); void setFlags(unsigned int value); private: snd_seq_queue_info_t* m_Info; }; /** * Queue status container. * * This class is used to retrieve some status information from an ALSA queue. */ class DRUMSTICK_EXPORT QueueStatus { friend class MidiQueue; public: QueueStatus(); QueueStatus(const QueueStatus& other); QueueStatus(snd_seq_queue_status_t* other); virtual ~QueueStatus(); QueueStatus* clone(); QueueStatus& operator=(const QueueStatus& other); int getInfoSize() const; int getId(); int getEvents(); const snd_seq_real_time_t* getRealtime(); unsigned int getStatusBits(); bool isRunning(); double getClockTime(); snd_seq_tick_time_t getTickTime(); private: snd_seq_queue_status_t* m_Info; }; /** * Queue tempo container. * * This class is used to hold some tempo properties of an ALSA queue object. * The queue's resolution defines the meaning of the musical time, in ticks. It * is expressed in PPQ (parts per quarter), or ticks in a quarter note (crotchet). * The nominal tempo is usually expressed in BPM (beats per minute), or Maelzel * metronome units. It can be also given in microseconds per beat. The tempo skew * factor is given as two integer numbers: skew value and skew base, being the * factor the quotient of both quantities = value / base. Currently (ALSA <= 1.0.20) * you can only use the base constant 0x10000 (decimal 65536). */ class DRUMSTICK_EXPORT QueueTempo { friend class MidiQueue; public: QueueTempo(); QueueTempo(const QueueTempo& other); QueueTempo(snd_seq_queue_tempo_t* other); virtual ~QueueTempo(); QueueTempo* clone(); QueueTempo& operator=(const QueueTempo& other); int getInfoSize() const; int getId(); int getPPQ(); unsigned int getSkewValue(); unsigned int getSkewBase(); unsigned int getTempo(); void setPPQ(int value); void setSkewValue(unsigned int value); void setTempo(unsigned int value); float getNominalBPM(); float getRealBPM(); void setTempoFactor(float value); void setNominalBPM(float value); protected: void setSkewBase(unsigned int value); private: snd_seq_queue_tempo_t* m_Info; }; /** * Queue timer container. * * This class is used to hold some properties about the Timer used with an ALSA * queue object. */ class DRUMSTICK_EXPORT QueueTimer { friend class MidiQueue; public: QueueTimer(); QueueTimer(const QueueTimer& other); QueueTimer(snd_seq_queue_timer_t* other); virtual ~QueueTimer(); QueueTimer* clone(); QueueTimer& operator=(const QueueTimer& other); int getInfoSize() const; int getQueueId(); snd_seq_queue_timer_type_t getType(); const snd_timer_id_t* getId(); unsigned int getResolution(); void setType(snd_seq_queue_timer_type_t value); void setId(snd_timer_id_t* value); void setId(const TimerId& id); void setResolution(unsigned int value); private: snd_seq_queue_timer_t* m_Info; }; /** * Queue management. * * This class represents an ALSA sequencer queue object. */ class DRUMSTICK_EXPORT MidiQueue : public QObject { Q_OBJECT public: explicit MidiQueue(MidiClient* seq, QObject* parent = 0); MidiQueue(MidiClient* seq, const QueueInfo& info, QObject* parent = 0); MidiQueue(MidiClient* seq, const QString name, QObject* parent = 0); MidiQueue(MidiClient* seq, const int queue_id, QObject* parent = 0); virtual ~MidiQueue(); int getId() const { return m_Id; } void start(); void stop(); void continueRunning(); void clear(); void setTickPosition(snd_seq_tick_time_t pos); void setRealTimePosition(snd_seq_real_time_t* pos); QueueInfo& getInfo(); QueueStatus& getStatus(); QueueTempo& getTempo(); QueueTimer& getTimer(); int getUsage(); void setInfo(const QueueInfo& value); void setTempo(const QueueTempo& value); void setTimer(const QueueTimer& value); void setUsage(int used); private: bool m_allocated; int m_Id; MidiClient* m_MidiClient; QueueInfo m_Info; QueueTempo m_Tempo; QueueTimer m_Timer; QueueStatus m_Status; }; } /* namespace drumstick */ /** @} */ #endif //DRUMSTICK_ALSAQUEUE_H drumstick-1.1.3/library/include/drumstick/PaxHeaders.32572/alsaevent.h0000644000000000000000000000013013532747316022520 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick/alsaevent.h0000644000175000001440000005342113532747316023320 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DRUMSTICK_ALSAEVENT_H #define DRUMSTICK_ALSAEVENT_H #include "drumstickcommon.h" #include /** * @file alsaevent.h * Classes managing ALSA Sequencer events. * * @defgroup ALSAEvent ALSA Sequencer Events * @{ */ namespace drumstick { /** * Constant SequencerEventType is the QEvent::type() of any SequencerEvent * object to be used to check the argument in QObject::customEvent(). */ const QEvent::Type SequencerEventType = QEvent::Type(QEvent::User + 4154); // :-) /** * Macro to declare a virtual clone() method for SequencerEvent and derived classes. */ #define CLONE_EVENT_DECLARATION(T) virtual T* clone() { return new T(&m_event); } /** * Base class for the event's hierarchy * * All event classes share this base class. It provides several common * properties and methods. */ class DRUMSTICK_EXPORT SequencerEvent : public QEvent { public: SequencerEvent(); SequencerEvent(const SequencerEvent& other); SequencerEvent(snd_seq_event_t* event); /** Destructor */ virtual ~SequencerEvent() {} SequencerEvent& operator=(const SequencerEvent& other); void setSequencerType(const snd_seq_event_type_t eventType); /** * Gets the sequencer event type. * @return The sequencer event type. * @see setSequencerType() */ snd_seq_event_type_t getSequencerType() const { return m_event.type; } void setDestination(const unsigned char client, const unsigned char port); void setSource(const unsigned char port); /** * Gets the source client id. * @return The source client id. * @see setSource() */ unsigned char getSourceClient() const { return m_event.source.client; } /** * Gets the source port id. * @return The source port id. * @see setSource() */ unsigned char getSourcePort() const { return m_event.source.port; } /** * Gets the tick time of the event. * @return The tick time. * @see scheduleTick() */ snd_seq_tick_time_t getTick() const { return m_event.time.tick; } /** * Gets the seconds of the event's real time. * @return The seconds of the time. * @see scheduleReal(), getRealTimeNanos() */ unsigned int getRealTimeSecs() const { return m_event.time.time.tv_sec; } /** * Gets the nanoseconds of the event's real time. * @return The nanoseconds of the time. * @see scheduleReal(), getRealTimeSecs() */ unsigned int getRealTimeNanos() const { return m_event.time.time.tv_nsec; } void setSubscribers(); void setBroadcast(); void setDirect(); void scheduleTick(const int queue, const int tick, const bool relative); void scheduleReal(const int queue, const ulong secs, const ulong nanos, const bool relative); void setPriority(const bool high); /** * Gets the tag of the event * @return The event's tag * @see setTag() */ unsigned char getTag() const { return m_event.tag; } void setTag(const unsigned char aTag); unsigned int getRaw32(const unsigned int n) const; void setRaw32(const unsigned int n, const unsigned int value); unsigned char getRaw8(const unsigned int n) const; void setRaw8(const unsigned int n, const unsigned char value); /** * Gets the handle of the event * @return The event's handle */ snd_seq_event_t* getHandle() { return &m_event; } int getEncodedLength(); static bool isSubscription(const SequencerEvent* event); static bool isPort(const SequencerEvent* event); static bool isClient(const SequencerEvent* event); static bool isConnectionChange(const SequencerEvent* event); static bool isChannel(const SequencerEvent* event); /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(SequencerEvent); protected: void free() __attribute__((deprecated)); /** * ALSA sequencer event record. * @see http://www.alsa-project.org/alsa-doc/alsa-lib/structsnd__seq__event.html */ snd_seq_event_t m_event; }; /** * Base class for the events having a Channel property */ class DRUMSTICK_EXPORT ChannelEvent : public SequencerEvent { public: /** Default constructor */ ChannelEvent() : SequencerEvent() {} /** Constructor from an ALSA event record */ ChannelEvent(snd_seq_event_t* event) : SequencerEvent(event) {} /** * Sets the channel of the event * @param c A channel, between 0 and 15. * @see getChannel() */ void setChannel(const MidiByte c) { m_event.data.note.channel = (c & 0xf); } /** * Gets the event's channel * @return The event's channel * @see setChannel() */ int getChannel() const { return m_event.data.note.channel; } }; /** * Base class for the events having Key and Velocity properties. */ class DRUMSTICK_EXPORT KeyEvent : public ChannelEvent { public: /** Default constructor */ KeyEvent() : ChannelEvent() {} /** Constructor from an ALSA event record */ KeyEvent(snd_seq_event_t* event) : ChannelEvent(event) {} /** * Gets the MIDI note of this event. * @return The event's MIDI note. * @see setKey() */ int getKey() const { return m_event.data.note.note; } /** * Sets the MIDI note of this event. * @param b A MIDI note, between 0 and 127. * @see getKey() */ void setKey(const MidiByte b) { m_event.data.note.note = b; } /** * Gets the note velocity of this event. * @return The event's note velocity. * @see setVelocity() */ int getVelocity() const { return m_event.data.note.velocity; } /** * Sets the note velocity of this event. * @param b A velocity value, between 0 and 127. * @see getVelocity() */ void setVelocity(const MidiByte b) { m_event.data.note.velocity = b; } }; /** * Class representing a note event with duration * * Note events are converted into two MIDI events, a note-on and a note-off * over the wire. */ class DRUMSTICK_EXPORT NoteEvent : public KeyEvent { public: /** Default constructor */ NoteEvent() : KeyEvent() { m_event.type = SND_SEQ_EVENT_NOTE; } /** Constructor from an ALSA event record */ NoteEvent(snd_seq_event_t* event) : KeyEvent(event) {} NoteEvent(const int ch, const int key, const int vel, const int dur); /** * Gets the note's duration * @return The duration of the event * @see setDuration() */ ulong getDuration() const { return m_event.data.note.duration; } /** * Sets the note's duration * @param d The duration of the event * @see getDuration() */ void setDuration(const ulong d) { m_event.data.note.duration = d; } /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(NoteEvent) }; /** * Event representing a note-on MIDI event */ class DRUMSTICK_EXPORT NoteOnEvent : public KeyEvent { public: /** Default constructor */ NoteOnEvent() : KeyEvent() { m_event.type = SND_SEQ_EVENT_NOTEON; } /** Constructor from an ALSA event record */ NoteOnEvent(snd_seq_event_t* event) : KeyEvent(event) {} NoteOnEvent(const int ch, const int key, const int vel); /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(NoteOnEvent) }; /** * Event representing a note-off MIDI event */ class DRUMSTICK_EXPORT NoteOffEvent : public KeyEvent { public: /** Default constructor */ NoteOffEvent() : KeyEvent() { m_event.type = SND_SEQ_EVENT_NOTEOFF; } /** Constructor from an ALSA event record */ NoteOffEvent(snd_seq_event_t* event) : KeyEvent(event) {} NoteOffEvent(const int ch, const int key, const int vel); /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(NoteOffEvent) }; /** * Event representing a MIDI key pressure, or polyphonic after-touch event */ class DRUMSTICK_EXPORT KeyPressEvent : public KeyEvent { public: /** Default constructor */ KeyPressEvent() : KeyEvent() { m_event.type = SND_SEQ_EVENT_KEYPRESS; } /** Constructor from an ALSA event record */ KeyPressEvent(snd_seq_event_t* event) : KeyEvent(event) {} KeyPressEvent(const int ch, const int key, const int vel); /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(KeyPressEvent) }; /** * Event representing a MIDI control change event */ class DRUMSTICK_EXPORT ControllerEvent : public ChannelEvent { public: /** Default constructor */ ControllerEvent() : ChannelEvent() {} /** Constructor from an ALSA event record */ ControllerEvent(snd_seq_event_t* event) : ChannelEvent(event) {} ControllerEvent(const int ch, const int cc, const int val); /** * Gets the controller event's parameter. * @return The controller event's parameter. * @see setParam() */ uint getParam() const { return m_event.data.control.param; } /** * Sets the controller event's parameter. * @param p The controller event's parameter. * @see getParam() */ void setParam( const uint p ) { m_event.data.control.param = p; } /** * Gets the controller event's value. * @return The controller event's value. * @see setValue() */ int getValue() const { return m_event.data.control.value; } /** * Sets the controller event's value. * @param v The controller event's value. * @see getValue() */ void setValue( const int v ) { m_event.data.control.value = v; } /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(ControllerEvent) }; /** * Event representing a MIDI program change event */ class DRUMSTICK_EXPORT ProgramChangeEvent : public ChannelEvent { public: /** Default constructor */ ProgramChangeEvent() : ChannelEvent() { m_event.type = SND_SEQ_EVENT_PGMCHANGE; } /** Constructor from an ALSA event record */ ProgramChangeEvent(snd_seq_event_t* event) : ChannelEvent(event) {} ProgramChangeEvent(const int ch, const int val); /** Gets the MIDI program number */ int getValue() const { return m_event.data.control.value; } /** Sets the MIDI program number */ void setValue( const int v ) { m_event.data.control.value = v; } /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(ProgramChangeEvent) }; /** * Event representing a MIDI bender, or pitch wheel event */ class DRUMSTICK_EXPORT PitchBendEvent : public ChannelEvent { public: /** Default constructor */ PitchBendEvent() : ChannelEvent() { m_event.type = SND_SEQ_EVENT_PITCHBEND; } /** Constructor from an ALSA event record */ PitchBendEvent(snd_seq_event_t* event) : ChannelEvent(event) {} PitchBendEvent(const int ch, const int val); /** Gets the MIDI pitch bend value, zero centered from -8192 to 8191 */ int getValue() const { return m_event.data.control.value; } /** Sets the MIDI pitch bend value, zero centered from -8192 to 8191 */ void setValue( const int v ) { m_event.data.control.value = v; } /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(PitchBendEvent) }; /** * Event representing a MIDI channel pressure or after-touch event */ class DRUMSTICK_EXPORT ChanPressEvent : public ChannelEvent { public: /** Default constructor */ ChanPressEvent() : ChannelEvent() { m_event.type = SND_SEQ_EVENT_CHANPRESS; } /** Constructor from an ALSA event record */ ChanPressEvent(snd_seq_event_t* event) : ChannelEvent(event) {} ChanPressEvent( const int ch, const int val); /** Gets the channel aftertouch value */ int getValue() const { return m_event.data.control.value; } /** Sets the channel aftertouch value */ void setValue( const int v ) { m_event.data.control.value = v; } /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(ChanPressEvent) }; /** * Base class for variable length events */ class DRUMSTICK_EXPORT VariableEvent : public SequencerEvent { public: VariableEvent(); VariableEvent(snd_seq_event_t* event); VariableEvent(const QByteArray& data); VariableEvent(const VariableEvent& other); VariableEvent(const unsigned int datalen, char* dataptr); VariableEvent& operator=(const VariableEvent& other); /** Gets the data length */ unsigned int getLength() const { return m_event.data.ext.len; } /** Gets the data pointer */ const char* getData() const { return static_cast(m_event.data.ext.ptr); } /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(VariableEvent) protected: QByteArray m_data; }; /** * Event representing a MIDI system exclusive event */ class DRUMSTICK_EXPORT SysExEvent : public VariableEvent { public: SysExEvent(); SysExEvent(snd_seq_event_t* event); SysExEvent(const QByteArray& data); SysExEvent(const SysExEvent& other); SysExEvent(const unsigned int datalen, char* dataptr); /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(SysExEvent) }; /** * Event representing a SMF text event * * This event type is not intended to be transmitted over the wire to an * external device, but it is useful for sequencer programs or MIDI applications */ class DRUMSTICK_EXPORT TextEvent : public VariableEvent { public: TextEvent(); TextEvent(snd_seq_event_t* event); explicit TextEvent(const QString& text, const int textType = 1); TextEvent(const TextEvent& other); TextEvent(const unsigned int datalen, char* dataptr); QString getText() const; int getTextType() const; /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(TextEvent) protected: int m_textType; }; /** * Generic event */ class DRUMSTICK_EXPORT SystemEvent : public SequencerEvent { public: /** Default constructor */ SystemEvent() : SequencerEvent() {} /** Constructor from an ALSA event record */ SystemEvent(snd_seq_event_t* event) : SequencerEvent(event) {} SystemEvent(const snd_seq_event_type_t type); /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(SystemEvent) }; /** * ALSA Event representing a queue control command * * This event is used to schedule changes to the ALSA queues */ class DRUMSTICK_EXPORT QueueControlEvent : public SequencerEvent { public: /** Default constructor */ QueueControlEvent() : SequencerEvent() {} /** Constructor from an ALSA event record */ QueueControlEvent(snd_seq_event_t* event) : SequencerEvent(event) {} QueueControlEvent(const snd_seq_event_type_t type, const int queue, const int value); /** Gets the queue number */ int getQueue() const { return m_event.data.queue.queue; } /** Sets the queue number */ void setQueue(const uchar q) { m_event.data.queue.queue = q; } /** Gets the event's value */ int getValue() const { return m_event.data.queue.param.value; } /** Sets the event's value */ void setValue(const int val) { m_event.data.queue.param.value = val; } /** Gets the queue position */ uint getPosition() const { return m_event.data.queue.param.position; } /** Sets the queue position */ void setPosition(const uint pos) { m_event.data.queue.param.position = pos; } /** Gets the musical time in ticks */ snd_seq_tick_time_t getTickTime() const { return m_event.data.queue.param.time.tick; } /** Sets the musical time in ticks */ void setTickTime(const snd_seq_tick_time_t t) { m_event.data.queue.param.time.tick = t; } /** Gets the skew base */ uint getSkewBase() const { return m_event.data.queue.param.skew.base; } /** Sets the skew base, should be 65536 */ void setSkewBase(const uint base) { m_event.data.queue.param.skew.base = base; } /** Gets the skew value */ uint getSkewValue() const { return m_event.data.queue.param.skew.value; } /** Sets the skew value */ void setSkewValue(const uint val) {m_event.data.queue.param.skew.value = val; } /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(QueueControlEvent) }; /** * Generic event having a value property */ class DRUMSTICK_EXPORT ValueEvent : public SequencerEvent { public: /** Default constructor */ ValueEvent() : SequencerEvent() {} /** Constructor from an ALSA event record */ ValueEvent(snd_seq_event_t* event) : SequencerEvent(event) {} ValueEvent(const snd_seq_event_type_t type, const int val); /** Gets the event's value */ int getValue() const { return m_event.data.control.value; } /** Sets the event's value */ void setValue( const int v ) { m_event.data.control.value = v; } /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(ValueEvent) }; /** * ALSA Event representing a tempo change for an ALSA queue */ class DRUMSTICK_EXPORT TempoEvent : public QueueControlEvent { public: /** Default constructor */ TempoEvent() : QueueControlEvent() {} /** Constructor from an ALSA event record */ TempoEvent(snd_seq_event_t* event) : QueueControlEvent(event) {} TempoEvent(const int queue, const int tempo); /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(TempoEvent) }; /** * ALSA Event representing a subscription between two ALSA clients and ports */ class DRUMSTICK_EXPORT SubscriptionEvent : public SequencerEvent { public: /** Default constructor */ SubscriptionEvent() : SequencerEvent() {} /** Constructor from an ALSA event record */ SubscriptionEvent(snd_seq_event_t* event) : SequencerEvent(event) {} /** Returns true if the event was a subscribed port */ bool subscribed() const { return (m_event.type == SND_SEQ_EVENT_PORT_SUBSCRIBED); } /** Returns true if the event was an unsubscribed port */ bool unsubscribed() const { return (m_event.type == SND_SEQ_EVENT_PORT_UNSUBSCRIBED); } /** Gets the sender client number */ int getSenderClient() const { return m_event.data.connect.sender.client; } /** Gets the sender port number */ int getSenderPort() const { return m_event.data.connect.sender.port; } /** Gets the destination client number */ int getDestClient() const { return m_event.data.connect.dest.client; } /** Gets the destination port number */ int getDestPort() const { return m_event.data.connect.dest.port; } /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(SubscriptionEvent) }; /** * ALSA Event representing a change on some ALSA sequencer client on the system */ class DRUMSTICK_EXPORT ClientEvent : public SequencerEvent { public: /** Default constructor */ ClientEvent() : SequencerEvent() {} /** Constructor from an ALSA event record */ ClientEvent(snd_seq_event_t* event) : SequencerEvent(event) {} int getClient() const { return m_event.data.addr.client; } /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(ClientEvent) }; /** * ALSA Event representing a change on some ALSA sequencer port on the system */ class DRUMSTICK_EXPORT PortEvent : public ClientEvent { public: /** Default constructor */ PortEvent() : ClientEvent() {} /** Constructor from an ALSA event record */ PortEvent(snd_seq_event_t* event) : ClientEvent(event) {} /** Gets the port number */ int getPort() const { return m_event.data.addr.port; } /** Clone this object returning a pointer to the new object */ CLONE_EVENT_DECLARATION(PortEvent) }; /** * Auxiliary class to remove events from an ALSA queue * @see MidiClient::removeEvents() */ class DRUMSTICK_EXPORT RemoveEvents { public: friend class MidiClient; public: /** Default constructor */ RemoveEvents(); RemoveEvents(const RemoveEvents& other); RemoveEvents(snd_seq_remove_events_t* other); virtual ~RemoveEvents(); RemoveEvents* clone(); RemoveEvents& operator=(const RemoveEvents& other); int getSizeOfInfo() const; int getChannel(); unsigned int getCondition(); const snd_seq_addr_t* getDest(); int getEventType(); int getQueue(); int getTag(); const snd_seq_timestamp_t* getTime(); void setChannel(int chan); void setCondition(unsigned int cond); void setDest(const snd_seq_addr_t* dest); void setEventType(int type); void setQueue(int queue); void setTag(int tag); void setTime(const snd_seq_timestamp_t* time); private: snd_seq_remove_events_t* m_Info; }; /** * Auxiliary class to translate between raw MIDI streams and ALSA events */ class DRUMSTICK_EXPORT MidiCodec : public QObject { Q_OBJECT public: explicit MidiCodec(int bufsize, QObject* parent = 0); ~MidiCodec(); void init(); long decode(unsigned char *buf, long count, const snd_seq_event_t *ev); long encode(const unsigned char *buf, long count, snd_seq_event_t *ev); long encode(int c, snd_seq_event_t *ev); void enableRunningStatus(bool enable); void resetEncoder(); void resetDecoder(); void resizeBuffer(int bufsize); private: snd_midi_event_t* m_Info; }; } /* namespace drumstick */ /** @} */ #endif //DRUMSTICK_ALSAEVENT_H drumstick-1.1.3/library/include/drumstick/PaxHeaders.32572/qove.h0000644000000000000000000000013013532747316021510 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick/qove.h0000644000175000001440000001643113532747316022310 0ustar00pedrousers00000000000000/* Overture OVE File component Copyright (C) 2006-2019, Rui Fan This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DRUMSTICK_OVE_H #define DRUMSTICK_OVE_H #include "macros.h" #include namespace OVE { class Track; class Voice; class Measure; class MeasureData; class NoteContainer; } /** * @file qove.h * Overture OVE Files Input * @defgroup OVE Overture File Parser (Input) * @{ */ namespace drumstick { class MeasureToTick; /** * Overture OVE Files (input only) * * This class is used to parse Overture Files * @since 0.5.0 */ class DRUMSTICK_EXPORT QOve : public QObject { Q_OBJECT public: QOve(QObject * parent = 0); virtual ~QOve(); void setTextCodecName(const QString& codec); void readFromFile(const QString& fileName); Q_SIGNALS: /** * Emitted for a OVE file read error * * @param errorStr Error string */ void signalOVEError(const QString& errorStr); /** * Emitted after reading a WRK header * * @param quarter of OVE file * @param trackCount of OVE file */ void signalOVEHeader(int quarter, int trackCount); /** * Emitted after reading the last chunk of a OVE file */ void signalOVEEnd(); /** * Emitted after reading a Note message * * @param track track number * @param tick musical time * @param channel MIDI Channel * @param pitch MIDI Note * @param vol Velocity */ void signalOVENoteOn(int track, long tick, int channel, int pitch, int vol); void signalOVENoteOff(int track, long tick, int channel, int pitch, int vol); /** * Emitted after reading a Control Change message * * @param track track number * @param tick musical time * @param channel MIDI Channel * @param ctl MIDI Controller * @param value Control value */ void signalOVECtlChange(int track, long tick, int channel, int ctl, int value); /** * Emitted after reading a Polyphonic Aftertouch message (Key Aftertouch) * * @param track track number * @param tick musical time * @param channel MIDI Channel * @param pitch MIDI Note * @param press Pressure amount */ void signalOVEKeyPress(int track, long tick, int channel, int pitch, int press); /** * Emitted after reading a Bender message * * @param track track number * @param tick musical time * @param channel MIDI Channel * @param value Bender value */ void signalOVEPitchBend(int track, long tick, int channel, int value); /** * Emitted after reading a Program change message * * @param track track number * @param tick musical time * @param channel MIDI Channel * @param patch Program number */ void signalOVEProgram(int track, long tick, int channel, int patch); /** * Emitted after reading a Channel Aftertouch message * * @param track track number * @param tick musical time * @param channel MIDI Channel * @param press Pressure amount */ void signalOVEChanPress(int track, long tick, int channel, int press); /** * Emitted after reading a System Exclusive event * * @param track track number * @param tick musical time * @param bank Sysex Bank number */ void signalOVESysexEvent(int track, long tick, int bank); /** * Emitted after reading a System Exclusive Bank * * @param bank Sysex Bank number * @param name Sysex Bank name * @param autosend Send automatically after loading the song * @param port MIDI output port * @param data Sysex bytes */ void signalOVESysex(int bank, const QString& name, bool autosend, int port, const QByteArray& data); /** * Emitted after reading a text message * * @param track track number * @param tick musical time * @param data Text data */ void signalOVEText(int track, long tick, const QString& data); /** * Emitted after reading a Time signature * * @param bar Measure number * @param tick musical time * @param num Numerator * @param den Denominator (exponent in a power of two) */ void signalOVETimeSig(int bar, long tick, int num, int den); /** * Emitted after reading a Key Signature * * @param bar Measure number * @param tick musical time * @param alt Number of alterations (negative=flats, positive=sharps) */ void signalOVEKeySig(int bar, long tick, int alt); /** * Emitted after reading a Tempo Change message. * * Tempo units are given in beats * 100 per minute, so to obtain BPM * it is necessary to divide by 100 the tempo. * * @param tick musical time * @param tempo beats per minute multiplied by 100 */ void signalOVETempo(long tick, int tempo); /** * Emitted after reading a new track prefix * * @param name track name * @param track track number * @param channel forced MIDI channel * @param pitch Note transposition * @param velocity Velocity increment * @param port MIDI port number * @param selected track is selected * @param muted track is muted * @param loop track loop enabled */ void signalOVENewTrack(const QString& name, int track, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop); /** * Emitted after reading a track patch chunk * * @param track track number * @param channel MIDI Channel * @param patch */ void signalOVETrackPatch(int track, int channel, int patch); /** * Emitted after reading a track bank chunk * * @param track track number * @param channel MIDI Channel * @param bank */ void signalOVETrackBank(int track, int channel, int bank); /** * Emitted after reading a track volume chunk. * * @param track track number * @param channel MIDI Channel * @param vol initial volume */ void signalOVETrackVol(int track, int channel, int vol); /** * Emitted after reading a chord diagram chunk. * * @param track track number * @param tick event time in ticks * @param name chord name * @param data chord data definition (not decoded) */ void signalOVEChord(int track, long tick, const QString& name, const QByteArray& data); /** * Emitted after reading an expression indication (notation) chunk. * * @param track track number * @param time event time in ticks * @param code expression event code * @param text expression text */ void signalOVEExpression(int track, long time, int code, const QString& text); private: void convertSong(); void convertSignatures(); void convertTrackHeader(OVE::Track* track, int trackNo); void convertMeasure( OVE::Track* track, int trackNo, const QList& voices, OVE::Measure* measure, OVE::MeasureData* measureData, int transpose, int offsetTick); void convertNotes(int trackNo, int measureTick, OVE::NoteContainer* container, int channel, int pitchShift); private: class QOvePrivate; QOvePrivate* d; }; } // namespace drumstick /** @} */ #endif // DRUMSTICK_OVE_H drumstick-1.1.3/library/include/drumstick/PaxHeaders.32572/rtmidioutput.h0000644000000000000000000000013013532747316023307 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick/rtmidioutput.h0000644000175000001440000001327613532747316024113 0ustar00pedrousers00000000000000/* Drumstick MIDI realtime input-output Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef MIDIOUTPUT_H #define MIDIOUTPUT_H #include #include #include #include #include #define MIDI_CHANNELS 16 #define MIDI_GM_DRUM_CHANNEL (10-1) #define MIDI_CTL_MSB_BANK_SELECT 0x00 #define MIDI_CTL_MSB_MAIN_VOLUME 0x07 #define MIDI_CTL_LSB_BANK_SELECT 0x20 #define MIDI_CTL_REVERB_SEND 0x5b #define MIDI_CTL_ALL_SOUNDS_OFF 0x78 #define MIDI_CTL_ALL_NOTES_OFF 0x7b #define MIDI_CTL_RESET_CONTROLLERS 0x79 #define MIDI_STATUS_NOTEOFF 0x80 #define MIDI_STATUS_NOTEON 0x90 #define MIDI_STATUS_KEYPRESURE 0xa0 #define MIDI_STATUS_CONTROLCHANGE 0xb0 #define MIDI_STATUS_PROGRAMCHANGE 0xc0 #define MIDI_STATUS_CHANNELPRESSURE 0xd0 #define MIDI_STATUS_PITCHBEND 0xe0 #define MIDI_STATUS_SYSEX 0xf0 #define MIDI_STATUS_ENDSYSEX 0xf7 #define MIDI_STATUS_REALTIME 0xf8 #define MIDI_STATUS_MASK 0xf0 #define MIDI_CHANNEL_MASK 0x0f #define MIDI_COMMON_QTRFRAME 0xF1 #define MIDI_COMMON_SONGPP 0xF2 #define MIDI_COMMON_SONSELECT 0xF3 #define MIDI_COMMON_TUNEREQ 0xF6 #define MIDI_REALTIME_CLOCK 0xF8 #define MIDI_REALTIME_START 0xFA #define MIDI_REALTIME_CONTINUE 0xFB #define MIDI_REALTIME_STOP 0xFC #define MIDI_REALTIME_SENSING 0xFE #define MIDI_REALTIME_RESET 0xFF #define MIDI_LSB(x) (x % 0x80) #define MIDI_MSB(x) (x / 0x80) /** * @file rtmidioutput.h * Realtime MIDI output interface * @addtogroup RT * @{ */ namespace drumstick { namespace rt { /** * @brief MIDI OUT interface */ class MIDIOutput : public QObject { Q_OBJECT public: /** * @brief MIDIOutput constructor * @param parent */ explicit MIDIOutput(QObject *parent = 0) : QObject(parent) {} /** * @brief ~MIDIOutput destructor */ virtual ~MIDIOutput() {} /** * @brief initialize * @param settings */ virtual void initialize(QSettings* settings) = 0; /** * @brief backendName * @return plugin name */ virtual QString backendName() = 0; /** * @brief publicName * @return MIDI port name */ virtual QString publicName() = 0; /** * @brief setPublicName * @param name MIDI port name */ virtual void setPublicName(QString name) = 0; /** * @brief connections * @return list of available MIDI ports */ virtual QStringList connections(bool advanced = false) = 0; /** * @brief setExcludedConnections * @param conns */ virtual void setExcludedConnections(QStringList conns) = 0; /** * @brief open the MIDI port by name * @param name */ virtual void open(QString name) = 0; /** * @brief close the MIDI port */ virtual void close() = 0; /** * @brief currentConnection * @return name of the current connection if it is opened */ virtual QString currentConnection() = 0; public Q_SLOTS: /** * @brief sendNoteOff 0x8 * @param chan * @param note * @param vel */ virtual void sendNoteOff(int chan, int note, int vel) = 0; /** * @brief sendNoteOn 0x9 * @param chan * @param note * @param vel */ virtual void sendNoteOn(int chan, int note, int vel) = 0; /** * @brief sendKeyPressure 0xA * @param chan * @param note * @param value */ virtual void sendKeyPressure(int chan, int note, int value) = 0; /** * @brief sendController 0xB * @param chan * @param control * @param value */ virtual void sendController(int chan, int control, int value) = 0; /** * @brief sendProgram 0xC * @param chan * @param program */ virtual void sendProgram(int chan, int program) = 0; /** * @brief sendChannelPressure 0xD * @param chan * @param value */ virtual void sendChannelPressure(int chan, int value) = 0; /** * @brief sendPitchBend 0xE * @param chan * @param value */ virtual void sendPitchBend(int chan, int value) = 0; /** * @brief sendSysex * @param data 0xF0 ... 0xF7 */ virtual void sendSysex(const QByteArray& data) = 0; /** * @brief sendSystemMsg * @param status 0xF */ virtual void sendSystemMsg(const int status) = 0; }; }} Q_DECLARE_INTERFACE(drumstick::rt::MIDIOutput, "net.sourceforge.drumstick.rt.MIDIOutput/1.0") /** @} */ #endif /* MIDIOUTPUT_H */ drumstick-1.1.3/library/include/drumstick/PaxHeaders.32572/qwrk.h0000644000000000000000000000013013532747316021522 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick/qwrk.h0000644000175000001440000003663613532747316022333 0ustar00pedrousers00000000000000/* WRK File component Copyright (C) 2010-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DRUMSTICK_QWRK_H #define DRUMSTICK_QWRK_H #include "macros.h" #include class QDataStream; /** * @file qwrk.h * Cakewalk WRK Files Input * @defgroup WRK Cakewalk WRK File Parser (Input) * @{ */ namespace drumstick { /** * Record types within a WRK file */ enum WrkChunkType { TRACK_CHUNK = 1, ///< Track prefix STREAM_CHUNK = 2, ///< Events stream VARS_CHUNK = 3, ///< Global variables TEMPO_CHUNK = 4, ///< Tempo map METER_CHUNK = 5, ///< Meter map SYSEX_CHUNK = 6, ///< System exclusive bank MEMRGN_CHUNK = 7, ///< Memory region COMMENTS_CHUNK = 8, ///< Comments TRKOFFS_CHUNK = 9, ///< Track offset TIMEBASE_CHUNK = 10, ///< Timebase. If present is the first chunk in the file. TIMEFMT_CHUNK = 11, ///< SMPTE time format TRKREPS_CHUNK = 12, ///< Track repetitions TRKPATCH_CHUNK = 14, ///< Track patch NTEMPO_CHUNK = 15, ///< New Tempo map THRU_CHUNK = 16, ///< Extended thru parameters LYRICS_CHUNK = 18, ///< Events stream with lyrics TRKVOL_CHUNK = 19, ///< Track volume SYSEX2_CHUNK = 20, ///< System exclusive bank STRTAB_CHUNK = 22, ///< Table of text event types METERKEY_CHUNK = 23, ///< Meter/Key map TRKNAME_CHUNK = 24, ///< Track name VARIABLE_CHUNK = 26, ///< Variable record chunk NTRKOFS_CHUNK = 27, ///< Track offset TRKBANK_CHUNK = 30, ///< Track bank NTRACK_CHUNK = 36, ///< Track prefix NSYSEX_CHUNK = 44, ///< System exclusive bank NSTREAM_CHUNK = 45, ///< Events stream SGMNT_CHUNK = 49, ///< Segment prefix SOFTVER_CHUNK = 74, ///< Software version which saved the file END_CHUNK = 255 ///< Last chunk, end of file }; const QByteArray HEADER("CAKEWALK"); ///< Cakewalk WRK File header id /** * Cakewalk WRK file format (input only) * * This class is used to parse Cakewalk WRK Files * @since 0.3.0 */ class DRUMSTICK_EXPORT QWrk : public QObject { Q_OBJECT public: QWrk(QObject * parent = 0); virtual ~QWrk(); void readFromStream(QDataStream *stream); void readFromFile(const QString& fileName); QTextCodec* getTextCodec(); void setTextCodec(QTextCodec *codec); long getFilePos(); int getNow() const; int getFrom() const; int getThru() const; int getKeySig() const; int getClock() const; int getAutoSave() const; int getPlayDelay() const; bool getZeroCtrls() const; bool getSendSPP() const; bool getSendCont() const; bool getPatchSearch() const; bool getAutoStop() const; unsigned int getStopTime() const; bool getAutoRewind() const; int getRewindTime() const; bool getMetroPlay() const; bool getMetroRecord() const; bool getMetroAccent() const; int getCountIn() const; bool getThruOn() const; bool getAutoRestart() const; int getCurTempoOfs() const; int getTempoOfs1() const; int getTempoOfs2() const; int getTempoOfs3() const; bool getPunchEnabled() const; int getPunchInTime() const; int getPunchOutTime() const; int getEndAllTime() const; QByteArray getLastChunkRawData() const; double getRealTime(long ticks) const; Q_SIGNALS: /** * Emitted for a WRK file read error * * @param errorStr Error string */ void signalWRKError(const QString& errorStr); /** * Emitted after reading an unknown chunk * * @param type chunk type * @param data chunk data (not decoded) */ void signalWRKUnknownChunk(int type, const QByteArray& data); /** * Emitted after reading a WRK header * * @param verh WRK file format version major * @param verl WRK file format version minor */ void signalWRKHeader(int verh, int verl); /** * Emitted after reading the last chunk of a WRK file */ void signalWRKEnd(); /** * Emitted after reading the last event of a event stream */ void signalWRKStreamEnd(long time); /** * Emitted after reading a Note message * * @param track track number * @param time musical time * @param chan MIDI Channel * @param pitch MIDI Note * @param vol Velocity * @param dur Duration */ void signalWRKNote(int track, long time, int chan, int pitch, int vol, int dur); /** * Emitted after reading a Polyphonic Aftertouch message * * @param track track number * @param time musical time * @param chan MIDI Channel * @param pitch MIDI Note * @param press Pressure amount */ void signalWRKKeyPress(int track, long time, int chan, int pitch, int press); /** * Emitted after reading a Control Change message * * @param track track number * @param time musical time * @param chan MIDI Channel * @param ctl MIDI Controller * @param value Control value */ void signalWRKCtlChange(int track, long time, int chan, int ctl, int value); /** * Emitted after reading a Bender message * * @param track track number * @param time musical time * @param chan MIDI Channel * @param value Bender value */ void signalWRKPitchBend(int track, long time, int chan, int value); /** * Emitted after reading a Program change message * * @param track track number * @param time musical time * @param chan MIDI Channel * @param patch Program number */ void signalWRKProgram(int track, long time, int chan, int patch); /** * Emitted after reading a Channel Aftertouch message * * @param track track number * @param time musical time * @param chan MIDI Channel * @param press Pressure amount */ void signalWRKChanPress(int track, long time, int chan, int press); /** * Emitted after reading a System Exclusive event * * @param track track number * @param time musical time * @param bank Sysex Bank number */ void signalWRKSysexEvent(int track, long time, int bank); /** * Emitted after reading a System Exclusive Bank * * @param bank Sysex Bank number * @param name Sysex Bank name * @param autosend Send automatically after loading the song * @param port MIDI output port * @param data Sysex bytes */ void signalWRKSysex(int bank, const QString& name, bool autosend, int port, const QByteArray& data); /** * Emitted after reading a text message * * @param track track number * @param time musical time * @param type Text type * @param data Text data */ void signalWRKText(int track, long time, int type, const QString& data); /** * Emitted after reading a WRK Time signature * * @param bar Measure number * @param num Numerator * @param den Denominator (exponent in a power of two) */ void signalWRKTimeSig(int bar, int num, int den); /** * Emitted after reading a WRK Key Signature * * @param bar Measure number * @param alt Number of alterations (negative=flats, positive=sharps) */ void signalWRKKeySig(int bar, int alt); /** * Emitted after reading a Tempo Change message. * * Tempo units are given in beats * 100 per minute, so to obtain BPM * it is necessary to divide by 100 the tempo. * * @param time musical time * @param tempo beats per minute multiplied by 100 */ void signalWRKTempo(long time, int tempo); /** * Emitted after reading a track prefix chunk * * @param name1 track 1st name * @param name2 track 2nd name * @param trackno track number * @param channel track forced channel (-1=no forced) * @param pitch track pitch transpose in semitones (-127..127) * @param velocity track velocity increment (-127..127) * @param port track forced port * @param selected true if track is selected * @param muted true if track is muted * @param loop true if loop is enabled */ void signalWRKTrack(const QString& name1, const QString& name2, int trackno, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop ); /** * Emitted after reading the timebase chunk * * @param timebase ticks per quarter note */ void signalWRKTimeBase(int timebase); /** * Emitted after reading the global variables chunk. * * This record contains miscellaneous Cakewalk global variables that can * be retrieved using individual getters. * * @see getNow(), getFrom(), getThru() */ void signalWRKGlobalVars(); /** * Emitted after reading an Extended Thru parameters chunk. * * It was introduced in Cakewalk version 4.0. These parameters are * intended to override the global vars Thruon value, so this record should * come after the VARS_CHUNK record. It is optional. * * @param mode (auto, off, on) * @param port MIDI port * @param channel MIDI channel * @param keyPlus Note transpose * @param velPlus Velocity transpose * @param localPort MIDI local port */ void signalWRKThru(int mode, int port, int channel, int keyPlus, int velPlus, int localPort); /** * Emitted after reading a track offset chunk * * @param track track number * @param offset time offset */ void signalWRKTrackOffset(int track, int offset); /** * Emitted after reading a track offset chunk * * @param track track number * @param reps number of repetitions */ void signalWRKTrackReps(int track, int reps); /** * Emitted after reading a track patch chunk * * @param track track number * @param patch */ void signalWRKTrackPatch(int track, int patch); /** * Emitted after reading a track bank chunk * * @param track track number * @param bank */ void signalWRKTrackBank(int track, int bank); /** * Emitted after reading a SMPTE time format chunk * * @param frames frames/sec (24, 25, 29=30-drop, 30) * @param offset frames of offset */ void signalWRKTimeFormat(int frames, int offset); /** * Emitted after reading a comments chunk * * @param data file text comments */ void signalWRKComments(const QString& data); /** * Emitted after reading a variable chunk. * This record may contain data in text or binary format. * * @param name record identifier * @param data record variable data */ void signalWRKVariableRecord(const QString& name, const QByteArray& data); /** * Emitted after reading a track volume chunk. * * @param track track number * @param vol initial volume */ void signalWRKTrackVol(int track, int vol); /** * Emitted after reading a new track prefix * * @param name track name * @param trackno track number * @param channel forced MIDI channel * @param pitch Note transposition * @param velocity Velocity increment * @param port MIDI port number * @param selected track is selected * @param muted track is muted * @param loop track loop enabled */ void signalWRKNewTrack( const QString& name, int trackno, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop ); /** * Emitted after reading a software version chunk. * * @param version software version string */ void signalWRKSoftVer(const QString& version); /** * Emitted after reading a track name chunk. * * @param track track number * @param name track name */ void signalWRKTrackName(int track, const QString& name); /** * Emitted after reading a string event types chunk. * * @param strs list of declared string event types */ void signalWRKStringTable(const QStringList& strs); /** * Emitted after reading a segment prefix chunk. * * @param track track number * @param time segment time offset * @param name segment name */ void signalWRKSegment(int track, long time, const QString& name); /** * Emitted after reading a chord diagram chunk. * * @param track track number * @param time event time in ticks * @param name chord name * @param data chord data definition (not decoded) */ void signalWRKChord(int track, long time, const QString& name, const QByteArray& data); /** * Emitted after reading an expression indication (notation) chunk. * * @param track track number * @param time event time in ticks * @param code expression event code * @param text expression text */ void signalWRKExpression(int track, long time, int code, const QString& text); /** * Emitted after reading a hairpin symbol (notation) chunk. * * @param track track number * @param time event time in ticks * @param code hairpin code * @param dur duration */ void signalWRKHairpin(int track, long time, int code, int dur); private: quint8 readByte(); quint16 to16bit(quint8 c1, quint8 c2); quint32 to32bit(quint8 c1, quint8 c2, quint8 c3, quint8 c4); quint16 read16bit(); quint32 read24bit(); quint32 read32bit(); QString readString(int len); QString readVarString(); void readRawData(int size); void readGap(int size); bool atEnd(); void seek(qint64 pos); int readChunk(); void processTrackChunk(); void processVarsChunk(); void processTimebaseChunk(); void processNoteArray(int track, int events); void processStreamChunk(); void processMeterChunk(); void processTempoChunk(int factor = 1); void processSysexChunk(); void processSysex2Chunk(); void processNewSysexChunk(); void processThruChunk(); void processTrackOffset(); void processTrackReps(); void processTrackPatch(); void processTrackBank(); void processTimeFormat(); void processComments(); void processVariableRecord(int max); void processNewTrack(); void processSoftVer(); void processTrackName(); void processStringTable(); void processLyricsStream(); void processTrackVol(); void processNewTrackOffset(); void processMeterKeyChunk(); void processSegmentChunk(); void processNewStream(); void processUnknown(int id); void processEndChunk(); void wrkRead(); struct RecTempo { long time; double tempo; double seconds; }; class QWrkPrivate; QWrkPrivate *d; }; } // namespace drumstick; /** @} */ #endif // DRUMSTICK_QWRK_H drumstick-1.1.3/library/include/drumstick/PaxHeaders.32572/subscription.h0000644000000000000000000000013013532747316023262 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick/subscription.h0000644000175000001440000000637113532747316024064 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DRUMSTICK_SUBSCRIPTION_H #define DRUMSTICK_SUBSCRIPTION_H #include "drumstickcommon.h" #include /** * @file subscription.h * Classes managing ALSA sequencer subscriptions * @defgroup ALSASubscription ALSA Sequencer Subscriptions * @{ */ namespace drumstick { class MidiClient; /** * Subscriber container class. * * This class is used to enumerate the subscribers of a given (root) port. */ class DRUMSTICK_EXPORT Subscriber { friend class PortInfo; public: Subscriber(); Subscriber(const Subscriber& other); Subscriber(snd_seq_query_subscribe_t* other); virtual ~Subscriber(); Subscriber* clone(); int getSizeOfInfo() const; int getClient(); int getPort(); const snd_seq_addr_t* getRoot(); snd_seq_query_subs_type_t getType(); int getIndex(); int getNumSubs(); const snd_seq_addr_t* getAddr(); int getQueue(); bool getExclusive(); bool getTimeUpdate(); bool getTimeReal(); void setClient(int client); void setPort(int port); void setRoot(snd_seq_addr_t* addr); void setType(snd_seq_query_subs_type_t type); void setIndex(int index); Subscriber& operator=(const Subscriber& other); private: snd_seq_query_subscribe_t* m_Info; }; /** * Subscription management. * * This class represents a connection between two ports. */ class DRUMSTICK_EXPORT Subscription { public: Subscription(); Subscription(const Subscription& other); Subscription(snd_seq_port_subscribe_t* other); Subscription(MidiClient* seq); virtual ~Subscription(); Subscription* clone(); int getSizeOfInfo() const; void setSender(unsigned char client, unsigned char port); void setDest(unsigned char client, unsigned char port); void subscribe(MidiClient* seq); void unsubscribe(MidiClient* seq); const snd_seq_addr_t* getSender(); const snd_seq_addr_t* getDest(); int getQueue(); bool getExclusive(); bool getTimeUpdate(); bool getTimeReal(); void setSender(const snd_seq_addr_t* addr); void setDest(const snd_seq_addr_t* addr); void setQueue(int queue); void setExclusive(bool val); void setTimeUpdate(bool val); void setTimeReal(bool val); Subscription& operator=(const Subscription& other); private: snd_seq_port_subscribe_t* m_Info; }; /** * List of subscriptions */ typedef QList SubscriptionsList; /** * List of subscribers */ typedef QList SubscribersList; } /** @} */ #endif //DRUMSTICK_SUBSCRIPTION_H drumstick-1.1.3/library/include/drumstick/PaxHeaders.32572/playthread.h0000644000000000000000000000013013532747316022673 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick/playthread.h0000644000175000001440000000703713532747316023475 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DRUMSTICK_PLAYTHREAD_H #define DRUMSTICK_PLAYTHREAD_H #include "alsaevent.h" #include #include /** * @file playthread.h * Sequencer output thread * @defgroup PlayThread Sequencer Output * @{ */ namespace drumstick { class MidiClient; class MidiQueue; /** * Sequence player auxiliary class * * This class is used to implement an asynchronous sequence player using * ALSA sequencer scheduling * * Examples: guiplayer.cpp and playsmf.cpp */ class DRUMSTICK_EXPORT SequencerOutputThread : public QThread { Q_OBJECT public: SequencerOutputThread(MidiClient *seq, int portId); virtual void run(); /** * Gets the initial position in ticks of the sequence * @return Initial position (ticks) */ virtual unsigned int getInitialPosition() { return 0; } /** * Gets the echo event resolution in ticks. This is the time * between echo events interleaved with the MIDI sequence. The default * value zero means that not echo events are sent at all. * @return Echo resolution (ticks) */ virtual unsigned int getEchoResolution() { return 0; } /** * Check if there is one more event in the sequence. * This is a pure virtual method that must be overridden in the derived * class. * @return True if the sequence has another event. */ virtual bool hasNext() = 0; /** * Gets the next event in the sequence. * This is a pure virtual function that must be overridden in the derived * class. * @return Pointer to the next SequencerEvent to be played. */ virtual SequencerEvent* nextEvent() = 0; /** * Stops playing the current sequence. */ virtual void stop(); signals: /** * Signal emitted when the sequence play-back has finished. */ void finished(); /** * Signal emitted when the play-back has stopped. * @since 0.2.0 */ void stopped(); public slots: void start( Priority priority = InheritPriority ); protected: virtual void sendEchoEvent(int tick); virtual void sendSongEvent(SequencerEvent* ev); virtual void drainOutput(); virtual void syncOutput(); virtual bool stopRequested(); MidiClient *m_MidiClient; /**< MidiClient instance pointer */ MidiQueue *m_Queue; /**< MidiQueue instance pointer */ int m_PortId; /**< MidiPort numeric identifier */ bool m_Stopped; /**< Stopped status */ int m_QueueId; /**< MidiQueue numeric identifier */ int m_npfds; /**< Number of pollfd pointers */ pollfd* m_pfds; /**< Array of pollfd pointers */ QReadWriteLock m_mutex; /**< Mutex object used for synchronization */ }; } /* namespace drumstick */ /** @} */ #endif /*DRUMSTICK_PLAYTHREAD_H*/ drumstick-1.1.3/library/include/drumstick/PaxHeaders.32572/drumstickcommon.h0000644000000000000000000000013013532747316023754 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick/drumstickcommon.h0000644000175000001440000000760613532747316024560 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DRUMSTICK_DRUMSTICKCOMMON_H #define DRUMSTICK_DRUMSTICKCOMMON_H #include "macros.h" #include #include #include #include extern "C" { #include } /** * @file drumstickcommon.h * Common functionality * @defgroup Common Common Functionality * @{ * drumstick::SequencerError is a common exception object, encapsulating ALSA error codes. */ namespace drumstick { /** * 8-bit unsigned number to be used as a MIDI message parameter */ typedef quint8 MidiByte; /** * Class used to report errors from the ALSA sequencer. * * The class SequencerError represents an exception object reported when the * ALSA library returns an error code. It is only used for severe errors. */ class DRUMSTICK_EXPORT SequencerError { public: /** * Constructor * @param s Error location * @param rc Numeric error code */ SequencerError(QString const& s, int rc) : m_location(s), m_errCode(rc) {} /** * Destructor */ virtual ~SequencerError() {} /** * Gets the human readable error message from the error code * @return Error message */ const QString qstrError() const { return QString(snd_strerror(m_errCode)); } /** * Gets the numeric error code * @return Error code */ int code() const { return m_errCode; } /** * Gets the location of the error code as provided in the constructor * @return Error location */ const QString& location() const { return m_location; } private: QString m_location; int m_errCode; }; /** * Checks the error code for severe errors. * If the provided error code is less than zero an exception is thrown, * containing both the error code and the location. * @param rc Error code * @param where Location * @return Error code */ inline int checkErrorAndThrow(int rc, const char *where) { if (rc < 0) { qDebug() << "Error code:" << rc << "(" << snd_strerror(rc) << ")"; qDebug() << "Location:" << where; throw SequencerError(QString(where), rc); } return rc; } /** * Check the error code for warning errors. * This method doesn't throw an exception. * @param rc Error code * @param where Location * @return Error code */ inline int checkWarning(int rc, const char *where) { if (rc < 0) { qWarning() << "Exception code:" << rc << "(" << snd_strerror(rc) << ")"; qWarning() << "Location:" << where; } return rc; } /** * This macro calls the check error function. * @param x Error code */ #define CHECK_ERROR(x) (checkErrorAndThrow((x),__PRETTY_FUNCTION__)) /** * This macro calls the check warning function. * @param x Error code */ #define CHECK_WARNING(x) (checkWarning((x),__PRETTY_FUNCTION__)) /** * ALSA library version as a constant string. * * This string corresponds to the compilation library, which may be * different to the runtime library. * @see getRuntimeALSALibraryVersion */ const QString LIBRARY_VERSION(SND_LIB_VERSION_STR); } /* namespace drumstick */ /** @} */ #endif /*DRUMSTICK_DRUMSTICKCOMMON_H*/ drumstick-1.1.3/library/include/drumstick/PaxHeaders.32572/alsaclient.h0000644000000000000000000000013013532747316022655 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick/alsaclient.h0000644000175000001440000002253313532747316023455 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DRUMSTICK_ALSACLIENT_H #define DRUMSTICK_ALSACLIENT_H #include "alsaport.h" #include #include #include /** * @file alsaclient.h * Classes managing ALSA Sequencer clients * * @defgroup ALSAClient ALSA Sequencer Clients * @{ */ namespace drumstick { class MidiQueue; class MidiClient; class SequencerEvent; class SequencerInputThread; class RemoveEvents; /** * Client information * * This class is used to retrieve, hold and set some data from * sequencer clients, like the name or id. */ class DRUMSTICK_EXPORT ClientInfo { friend class MidiClient; public: ClientInfo(); ClientInfo(const ClientInfo& other); ClientInfo(snd_seq_client_info_t* other); ClientInfo(MidiClient* seq, int id); virtual ~ClientInfo(); ClientInfo* clone(); ClientInfo& operator=(const ClientInfo& other); int getSizeOfInfo() const; int getClientId(); snd_seq_client_type_t getClientType(); QString getName(); bool getBroadcastFilter(); bool getErrorBounce(); int getNumPorts(); int getEventLost(); void setClient(int client); void setName(QString name); void setBroadcastFilter(bool val); void setErrorBounce(bool val); PortInfoList getPorts() const; #if SND_LIB_VERSION > 0x010010 void addFilter(int eventType); bool isFiltered(int eventType); void clearFilter(); void removeFilter(int eventType); #endif protected: void readPorts(MidiClient* seq); void freePorts(); const unsigned char* getEventFilter() __attribute__((deprecated)); void setEventFilter(unsigned char* filter) __attribute__((deprecated)); private: snd_seq_client_info_t* m_Info; PortInfoList m_Ports; }; /** * List of sequencer client information */ typedef QList ClientInfoList; /** * System information * * This class is used to retrieve and hold some data about the * whole sequencer subsystem. */ class DRUMSTICK_EXPORT SystemInfo { friend class MidiClient; public: SystemInfo(); SystemInfo(const SystemInfo& other); SystemInfo(snd_seq_system_info_t* other); SystemInfo(MidiClient* seq); virtual ~SystemInfo(); SystemInfo* clone(); SystemInfo& operator=(const SystemInfo& other); int getSizeOfInfo() const; int getMaxClients(); int getMaxPorts(); int getMaxQueues(); int getMaxChannels(); int getCurrentQueues(); int getCurrentClients(); private: snd_seq_system_info_t* m_Info; }; /** * Sequencer Pool information * * This class is used to get and set the size of the input and output pool * buffers for a sequencer client. */ class DRUMSTICK_EXPORT PoolInfo { friend class MidiClient; public: PoolInfo(); PoolInfo(const PoolInfo& other); PoolInfo(snd_seq_client_pool_t* other); PoolInfo(MidiClient* seq); virtual ~PoolInfo(); PoolInfo* clone(); PoolInfo& operator=(const PoolInfo& other); int getSizeOfInfo() const; int getClientId(); int getInputFree(); int getInputPool(); int getOutputFree(); int getOutputPool(); int getOutputRoom(); void setInputPool(int size); void setOutputPool(int size); void setOutputRoom(int size); private: snd_seq_client_pool_t* m_Info; }; /** * Sequencer events handler * * This abstract class is used to define an interface that other class can * implement to receive sequencer events. It is one of the three methods of * delivering events offered by this library. * * @see ALSAClient */ class DRUMSTICK_EXPORT SequencerEventHandler { public: /** Destructor */ virtual ~SequencerEventHandler() {} /** * Callback function to be implemented by the derived class. * It will be invoked by the client to deliver received events to the * registered listener. * * @param ev A pointer to the received SequencerEvent * @see MidiClient::setHandler(), MidiClient::startSequencerInput(), * MidiClient::stopSequencerInput(), MidiClient::doEvents() */ virtual void handleSequencerEvent(SequencerEvent* ev) = 0; }; /** * Client management. * * This class represents an ALSA sequencer client */ class DRUMSTICK_EXPORT MidiClient : public QObject { Q_OBJECT public: MidiClient( QObject* parent = 0 ); virtual ~MidiClient(); void open( const QString deviceName = "default", const int openMode = SND_SEQ_OPEN_DUPLEX, const bool blockMode = false ); void open( snd_config_t* conf, const QString deviceName = "default", const int openMode = SND_SEQ_OPEN_DUPLEX, const bool blockMode = false ); void close(); void startSequencerInput(); void stopSequencerInput(); MidiPort* createPort(); MidiQueue* createQueue(); MidiQueue* createQueue(QString const& name); MidiQueue* getQueue(); MidiQueue* useQueue(int queue_id); MidiQueue* useQueue(const QString& name); MidiQueue* useQueue(MidiQueue* queue); void portAttach(MidiPort* port); void portDetach(MidiPort* port); void detachAllPorts(); void addEventFilter(int evtype); void output(SequencerEvent* ev, bool async = false, int timeout = -1); void outputDirect(SequencerEvent* ev, bool async = false, int timeout = -1); void outputBuffer(SequencerEvent* ev); void drainOutput(bool async = false, int timeout = -1); void synchronizeOutput(); int getClientId(); snd_seq_type_t getSequencerType(); snd_seq_t* getHandle(); bool isOpened(); size_t getOutputBufferSize(); void setOutputBufferSize(size_t newSize); size_t getInputBufferSize(); void setInputBufferSize(size_t newSize); QString getDeviceName(); int getOpenMode(); bool getBlockMode(); void setBlockMode(bool newValue); QString getClientName(); QString getClientName(const int clientId); void setClientName(QString const& newName); bool getBroadcastFilter(); void setBroadcastFilter(bool newValue); bool getErrorBounce(); void setErrorBounce(bool newValue); ClientInfo& getThisClientInfo(); void setThisClientInfo(const ClientInfo& val); MidiPortList getMidiPorts() const; ClientInfoList getAvailableClients(); PortInfoList getAvailableInputs(); PortInfoList getAvailableOutputs(); SystemInfo& getSystemInfo(); QList getAvailableQueues(); PoolInfo& getPoolInfo(); void setPoolInfo(const PoolInfo& info); void setPoolInput(int size); void setPoolOutput(int size); void setPoolOutputRoom(int size); void resetPoolInput(); void resetPoolOutput(); void dropInput(); void dropInputBuffer(); void dropOutput(); void dropOutputBuffer(); void removeEvents(const RemoveEvents* spec); SequencerEvent* extractOutput(); int outputPending(); int inputPending(bool fetch); int getQueueId(const QString& name); void addListener(QObject* listener); void removeListener(QObject* listener); void setEventsEnabled(const bool bEnabled); bool getEventsEnabled() const; void setHandler(SequencerEventHandler* handler); bool parseAddress( const QString& straddr, snd_seq_addr& result ); void setRealTimeInput(bool enabled); bool realTimeInputEnabled(); signals: /** Signal emitted when an event is received */ void eventReceived(SequencerEvent* ev); protected: void doEvents(); void applyClientInfo(); void readClients(); void freeClients(); void updateAvailablePorts(); PortInfoList filterPorts(unsigned int filter); /* low level public functions */ const char * _getDeviceName(); int getPollDescriptorsCount(short events); int pollDescriptors(struct pollfd *pfds, unsigned int space, short events); unsigned short pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds); /* mid level functions */ void _setClientName( const char *name ); int createSimplePort( const char *name, unsigned int caps, unsigned int type ); void deleteSimplePort( int port ); void connectFrom(int myport, int client, int port); void connectTo(int myport, int client, int port); void disconnectFrom(int myport, int client, int port); void disconnectTo(int myport, int client, int port); private: class SequencerInputThread; class MidiClientPrivate; MidiClientPrivate *d; }; #if SND_LIB_VERSION > 0x010004 DRUMSTICK_EXPORT QString getRuntimeALSALibraryVersion(); DRUMSTICK_EXPORT int getRuntimeALSALibraryNumber(); #endif DRUMSTICK_EXPORT QString getRuntimeALSADriverVersion(); DRUMSTICK_EXPORT int getRuntimeALSADriverNumber(); } /* namespace drumstick */ /** @} */ #endif // DRUMSTICK_ALSACLIENT_H drumstick-1.1.3/library/include/drumstick/PaxHeaders.32572/rtmidiinput.h0000644000000000000000000000013013532747316023106 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick/rtmidiinput.h0000644000175000001440000001170513532747316023705 0ustar00pedrousers00000000000000/* Drumstick MIDI realtime input-output Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef MIDIINPUT_H #define MIDIINPUT_H #include #include #include #include #include #include "rtmidioutput.h" /** * @file rtmidiinput.h * Realtime MIDI input interface * @addtogroup RT * @{ */ namespace drumstick { namespace rt { /** * @brief MIDI IN interface */ class MIDIInput : public QObject { Q_OBJECT public: /** * @brief MIDIInput constructor * @param parent */ explicit MIDIInput(QObject *parent = 0) : QObject(parent) {} /** * @brief ~MIDIInput destructor */ virtual ~MIDIInput() {} /** * @brief initialize * @param settings */ virtual void initialize(QSettings* settings) = 0; /** * @brief backendName * @return plugin name */ virtual QString backendName() = 0; /** * @brief publicName * @return MIDI port name */ virtual QString publicName() = 0; /** * @brief setPublicName * @param name MIDI port name */ virtual void setPublicName(QString name) = 0; /** * @brief connections * @return list of available MIDI ports */ virtual QStringList connections(bool advanced = false) = 0; /** * @brief setExcludedConnections * @param conns */ virtual void setExcludedConnections(QStringList conns) = 0; /** * @brief open the MIDI port by name * @param name */ virtual void open(QString name) = 0; /** * @brief close the MIDI port */ virtual void close() = 0; /** * @brief currentConnection * @return name of the current connection if it is opened */ virtual QString currentConnection() = 0; /** * @brief setMIDIThruDevice * @param device */ virtual void setMIDIThruDevice(MIDIOutput* device) = 0; /** * @brief enableMIDIThru * @param enable */ virtual void enableMIDIThru(bool enable) = 0; /** * @brief isEnabledMIDIThru * @return */ virtual bool isEnabledMIDIThru() = 0; Q_SIGNALS: /** * @brief midiNoteOff 0x8 * @param chan * @param note * @param vel */ void midiNoteOff(const int chan, const int note, const int vel); /** * @brief midiNoteOn 0x9 * @param chan * @param note * @param vel */ void midiNoteOn(const int chan, const int note, const int vel); /** * @brief midiKeyPressure 0xA * @param chan * @param note * @param value */ void midiKeyPressure(const int chan, const int note, const int value); /** * @brief midiController 0xB * @param chan * @param control * @param value */ void midiController(const int chan, const int control, const int value); /** * @brief midiProgram 0xC * @param chan * @param program */ void midiProgram(const int chan, const int program); /** * @brief midiChannelPressure 0xD * @param chan * @param value */ void midiChannelPressure(const int chan, const int value); /** * @brief midiPitchBend 0xE * @param chan * @param value */ void midiPitchBend(const int chan, const int value); /** * @brief midiSysex * @param data 0xF0 ... 0xF7 */ void midiSysex(const QByteArray &data); /** * @brief midiSystemCommon * @param status 0xF (1..6) */ void midiSystemCommon(const int status); /** * @brief midiSystemRealtime * @param status 0xF (8..F) */ void midiSystemRealtime(const int status); }; }} Q_DECLARE_INTERFACE(drumstick::rt::MIDIInput, "net.sourceforge.drumstick.rt.MIDIInput/1.0") /** @} */ #endif // MIDIINPUT_H drumstick-1.1.3/library/include/drumstick/PaxHeaders.32572/alsatimer.h0000644000000000000000000000013013532747316022517 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/include/drumstick/alsatimer.h0000644000175000001440000002164413532747316023321 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DRUMSTICK_ALSATIMER_H #define DRUMSTICK_ALSATIMER_H #include "drumstickcommon.h" #include #include #include #include /** * @file alsatimer.h * Classes managing ALSA Timers * @defgroup ALSATimer ALSA Timers * @{ */ namespace drumstick { class TimerQuery; class TimerId; class TimerGlobalInfo; /** * ALSA Timer information container. * * This class is used to hold properties about ALSA Timers. */ class DRUMSTICK_EXPORT TimerInfo { friend class Timer; public: TimerInfo(); TimerInfo(const TimerInfo& other); TimerInfo(const snd_timer_info_t* other); virtual ~TimerInfo(); TimerInfo* clone(); TimerInfo& operator=(const TimerInfo& other); int getSizeOfInfo() const; bool isSlave(); int getCard(); QString getId(); QString getName(); long getResolution(); long getFrequency(); protected: long getTicks() __attribute__((deprecated)); private: snd_timer_info_t *m_Info; }; /** * ALSA Timer identifier container. * * This class provides an unique identifier for a Timer. */ class DRUMSTICK_EXPORT TimerId { friend class TimerQuery; friend class TimerGlobalInfo; friend class QueueTimer; public: TimerId(); TimerId(const TimerId& other); TimerId(const snd_timer_id_t *other); TimerId(int cls, int scls, int card, int dev, int sdev); virtual ~TimerId(); TimerId* clone(); TimerId& operator=(const TimerId& other); int getSizeOfInfo() const; void setClass(int devclass); int getClass(); void setSlaveClass(int devsclass); int getSlaveClass(); void setCard(int card); int getCard(); void setDevice(int device); int getDevice(); void setSubdevice(int subdevice); int getSubdevice(); private: snd_timer_id_t *m_Info; }; /** * List of timer identifiers */ typedef QList TimerIdList; /** * Global timer information container. * * This class provides global timer parameters. */ class DRUMSTICK_EXPORT TimerGlobalInfo { friend class TimerQuery; public: TimerGlobalInfo(); TimerGlobalInfo(const TimerGlobalInfo& other); TimerGlobalInfo(const snd_timer_ginfo_t* other); virtual ~TimerGlobalInfo(); TimerGlobalInfo* clone(); TimerGlobalInfo& operator=(const TimerGlobalInfo& other); int getSizeOfInfo() const; void setTimerId(const TimerId& tid); TimerId& getTimerId(); unsigned int getFlags(); int getCard(); QString getId(); QString getName(); unsigned long getResolution(); unsigned long getMinResolution(); unsigned long getMaxResolution(); unsigned int getClients(); private: snd_timer_ginfo_t* m_Info; TimerId m_Id; }; /** * ALSA Timer inquiry helper. * * This class provides a mechanism to enumerate the available system timers. */ class DRUMSTICK_EXPORT TimerQuery { public: TimerQuery(const QString& deviceName, int openMode); TimerQuery(const QString& deviceName, int openMode, snd_config_t* conf); virtual ~TimerQuery(); /** * Gets the list of available timers * @return List of TimerId objects */ TimerIdList getTimers() const { return m_timers; } TimerGlobalInfo& getGlobalInfo(); void setGlobalParams(snd_timer_gparams_t* params); void getGlobalParams(snd_timer_gparams_t* params); void getGlobalStatus(snd_timer_gstatus_t* status); protected: void readTimers(); void freeTimers(); private: snd_timer_query_t *m_Info; TimerIdList m_timers; TimerGlobalInfo m_GlobalInfo; }; /** * ALSA Timer parameters container. * * This class provides several parameters about a Timer. */ class DRUMSTICK_EXPORT TimerParams { friend class Timer; public: TimerParams(); TimerParams(const TimerParams& other); TimerParams(const snd_timer_params_t* other); virtual ~TimerParams(); TimerParams* clone(); TimerParams& operator=(const TimerParams& other); int getSizeOfInfo() const; void setAutoStart(bool auto_start); bool getAutoStart(); void setExclusive(bool exclusive); bool getExclusive(); void setEarlyEvent(bool early_event); bool getEarlyEvent(); void setTicks(long ticks); long getTicks(); void setQueueSize(long queue_size); long getQueueSize(); void setFilter(unsigned int filter); unsigned int getFilter(); private: snd_timer_params_t* m_Info; }; /** * ALSA Timer status container. * * This class provides some status information about a Timer. */ class DRUMSTICK_EXPORT TimerStatus { friend class Timer; public: TimerStatus(); TimerStatus(const TimerStatus& other); TimerStatus(const snd_timer_status_t* other); virtual ~TimerStatus(); TimerStatus* clone(); TimerStatus& operator=(const TimerStatus& other); int getSizeOfInfo() const; snd_htimestamp_t getTimestamp(); long getResolution(); long getLost(); long getOverrun(); long getQueue(); private: snd_timer_status_t* m_Info; }; /** * ALSA Timer events handler. * * This abstract class is used to define an interface that other class can * implement to receive timer events. */ class DRUMSTICK_EXPORT TimerEventHandler { public: /** Destructor */ virtual ~TimerEventHandler() {} /** * Timer event handler. This method is called when the timer expires. * @param ticks The time in ticks. * @param msecs The time in milliseconds. */ virtual void handleTimerEvent(int ticks, int msecs) = 0; }; /** * ALSA Timer management. * * This class represents an ALSA timer object. */ class DRUMSTICK_EXPORT Timer : public QObject { Q_OBJECT private: /** * This class manages timer events input from ALSA */ class TimerInputThread : public QThread { public: /** Constructor */ TimerInputThread(Timer* t, int timeout) : QThread(), m_timer(t), m_Wait(timeout), m_Stopped(false) {} /** Destructor */ virtual ~TimerInputThread() {} virtual void run(); bool stopped(); void stop(); private: Timer* m_timer; int m_Wait; bool m_Stopped; QReadWriteLock m_mutex; }; public: Timer(int cls, int scls, int card, int dev, int sdev, int openMode, QObject* parent = 0); Timer(const QString& deviceName, int openMode, QObject* parent = 0); Timer(const QString& deviceName, int openMode, snd_config_t* config, QObject* parent = 0); Timer(TimerId& id, int openMode, QObject* parent = 0); virtual ~Timer(); static TimerId bestGlobalTimerId(); static Timer* bestGlobalTimer(int openMode, QObject* parent = 0); /** * Gets the ALSA timer object. * @return ALSA timer object pointer. */ snd_timer_t* getHandle() { return m_Info; } TimerInfo& getTimerInfo(); TimerStatus& getTimerStatus(); void setTimerParams(const TimerParams& params); void start(); void stop(); void continueRunning(); void addAsyncTimerHandler(snd_async_callback_t callback, void *private_data); int getPollDescriptorsCount(); void pollDescriptors(struct pollfd *pfds, unsigned int space); void pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds, unsigned short *revents); ssize_t read(void *buffer, size_t size); snd_timer_t* getTimerHandle(); /** * Sets an event handler providing a method to be called when a timer expires. * @param h A TimerEventHandler instance. */ void setHandler(TimerEventHandler* h) { m_handler = h; } void startEvents(); void stopEvents(); protected: void doEvents(); signals: /** * This signal is emitted when the timer has expired, if there is not an * event hander installed. * * @param ticks The time in ticks. * @param msecs The time in milliseconds. */ void timerExpired(int ticks, int msecs); private: snd_timer_t *m_Info; snd_async_handler_t *m_asyncHandler; TimerEventHandler* m_handler; QPointer m_thread; TimerInfo m_TimerInfo; TimerStatus m_TimerStatus; QString m_deviceName; snd_htimestamp_t m_last_time; }; } /* namespace drumstick */ /** @} */ #endif /* DRUMSTICK_ALSATIMER_H */ drumstick-1.1.3/library/PaxHeaders.32572/library.pro0000644000000000000000000000013213532747316017125 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.733999895 30 ctime=1567346382.693999845 drumstick-1.1.3/library/library.pro0000644000175000001440000000024513532747316017717 0ustar00pedrousers00000000000000TEMPLATE = subdirs CONFIG += ordered linux* { SUBDIRS += alsa } SUBDIRS += file SUBDIRS += rt-backends SUBDIRS += rt macx { OTHER_FILES += Info.plist.lib } drumstick-1.1.3/library/PaxHeaders.32572/rt-backends0000644000000000000000000000013013532747316017055 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/0000755000175000001440000000000013532747316017725 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/mac-in0000644000000000000000000000013213532747316020223 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.733999895 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/mac-in/0000755000175000001440000000000013532747316021071 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/mac-in/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316023040 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.733999895 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/mac-in/CMakeLists.txt0000644000175000001440000000437713532747316023644 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(CMAKE_INCLUDE_CURRENT_DIR ON) #include_directories(../common) set(drumstick-rt-mac-in_QTOBJ_SRCS ../../include/drumstick/rtmidiinput.h ../../include/drumstick/rtmidioutput.h macmidiinput.h ) set(drumstick-rt-mac-in_SRCS ../common/maccommon.h ../common/maccommon.cpp macmidiinput.cpp ) qt5_wrap_cpp(drumstick-rt-mac-in_MOC_SRCS ${drumstick-rt-mac-in_QTOBJ_SRCS} OPTIONS -I ${DRUMSTICK_SOURCE_DIR}/library/include ) if(STATIC_DRUMSTICK) add_library(drumstick-rt-mac-in STATIC ${drumstick-rt-mac-in_MOC_SRCS} ${drumstick-rt-mac-in_SRCS}) target_compile_definitions(drumstick-rt-mac-in PRIVATE QT_STATICPLUGIN) set_target_properties(drumstick-rt-mac-in PROPERTIES STATIC_LIB "libdrumstick-rt-mac-in") else() add_library(drumstick-rt-mac-in MODULE ${drumstick-rt-mac-in_MOC_SRCS} ${drumstick-rt-mac-in_SRCS}) target_compile_definitions(drumstick-rt-mac-in PRIVATE QT_PLUGIN) endif() target_include_directories(drumstick-rt-mac-in PRIVATE ${DRUMSTICK_SOURCE_DIR}/library/include ../common ) target_link_libraries(drumstick-rt-mac-in Qt5::Core Qt5::Concurrent "-framework CoreMIDI -framework CoreFoundation" ) set_target_properties(drumstick-rt-mac-in PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/drumstick) install(TARGETS drumstick-rt-mac-in RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick) drumstick-1.1.3/library/rt-backends/mac-in/PaxHeaders.32572/macmidiinput.h0000644000000000000000000000013213532747316023134 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.733999895 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/mac-in/macmidiinput.h0000644000175000001440000000364613532747316023736 0ustar00pedrousers00000000000000/* Drumstick RT Backend Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef MACMIDIOBJECT_H #define MACMIDIOBJECT_H #include namespace drumstick { namespace rt { class MIDIOutput; class MacMIDIInputPrivate; class MacMIDIInput : public MIDIInput { Q_OBJECT #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) Q_PLUGIN_METADATA(IID "net.sourceforge.drumstick.rt.MIDIInput") #endif Q_INTERFACES(drumstick::rt::MIDIInput) public: explicit MacMIDIInput(QObject *parent = 0); ~MacMIDIInput(); // MIDIInput interface public: virtual void initialize(QSettings* settings); virtual QString backendName(); virtual QString publicName(); virtual void setPublicName(QString name); virtual QStringList connections(bool advanced); virtual void setExcludedConnections(QStringList conns); virtual void open(QString name); virtual void close(); virtual QString currentConnection(); virtual void setMIDIThruDevice(MIDIOutput *device); virtual void enableMIDIThru(bool enable); virtual bool isEnabledMIDIThru(); private: MacMIDIInputPrivate* const d; }; }} #endif // MACMIDIOBJECT_H drumstick-1.1.3/library/rt-backends/mac-in/PaxHeaders.32572/mac-in.pro0000644000000000000000000000013213532747316022166 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.733999895 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/mac-in/mac-in.pro0000644000175000001440000000117613532747316022764 0ustar00pedrousers00000000000000TEMPLATE = lib CONFIG += plugin static { CONFIG += staticlib create_prl } TARGET = drumstick-rt-mac-in DESTDIR = ../../../build/lib/drumstick DEPENDPATH += . ../../include ../common INCLUDEPATH += . ../../include ../common include (../../../global.pri) QT -= gui QT += concurrent HEADERS += ../../include/drumstick/rtmidiinput.h \ ../../include/drumstick/rtmidioutput.h \ macmidiinput.h \ ../common/maccommon.h SOURCES += macmidiinput.cpp \ ../common/maccommon.cpp LIBS += -framework CoreMIDI -framework CoreFoundation #-framework CoreAudio -framework AudioToolbox -framework AudioUnit drumstick-1.1.3/library/rt-backends/mac-in/PaxHeaders.32572/macmidiinput.cpp0000644000000000000000000000013213532747316023467 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.733999895 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/mac-in/macmidiinput.cpp0000644000175000001440000002652313532747316024270 0ustar00pedrousers00000000000000/* Drumstick RT Backend Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include "macmidiinput.h" #include "maccommon.h" #include #include #include #include #include #include #include #include namespace drumstick { namespace rt { static CFStringRef DEFAULT_PUBLIC_NAME CFSTR("MIDI In"); void MacMIDIReadProc( const MIDIPacketList *pktlist, void *refCon, void *connRefCon ); class MacMIDIInputPrivate { public: MacMIDIInput *m_inp; MIDIOutput *m_out; MIDIClientRef m_client; MIDIPortRef m_port; MIDIEndpointRef m_endpoint; MIDIEndpointRef m_source; bool m_thruEnabled; bool m_clientFilter; QString m_publicName; QString m_currentInput; QStringList m_excludedNames; QStringList m_inputDevices; MacMIDIInputPrivate(MacMIDIInput *inp) : m_inp(inp), m_out(nullptr), m_client(0), m_port(0), m_endpoint(0), m_source(0), m_thruEnabled(false), m_clientFilter(true), m_publicName(QString::fromCFString(DEFAULT_PUBLIC_NAME)) { internalCreate( DEFAULT_PUBLIC_NAME ); } void internalCreate(CFStringRef name) { OSStatus result = noErr; result = MIDIClientCreate( name , nullptr, nullptr, &m_client ); if (result != noErr) { qDebug() << "MIDIClientCreate() err:" << result; return; } result = MIDIDestinationCreate ( m_client, name, MacMIDIReadProc, (void*) this, &m_endpoint ); if (result != noErr) { qDebug() << "MIDIDestinationCreate() err:" << result; return; } result = MIDIInputPortCreate( m_client, name, MacMIDIReadProc, (void *) this, &m_port ); if (result != noErr) { qDebug() << "MIDIInputPortCreate() error:" << result; return; } reloadDeviceList(true); } virtual ~MacMIDIInputPrivate() { internalDispose(); } void internalDispose() { OSStatus result = noErr; if (m_port != 0) { result = MIDIPortDispose(m_port); if (result != noErr) { qDebug() << "MIDIPortDispose() error:" << result; m_port = 0; } } if (m_endpoint != 0) { result = MIDIEndpointDispose(m_endpoint); if (result != noErr) { qDebug() << "MIDIEndpointDispose() err:" << result; m_endpoint = 0; } } if (m_client != 0) { result = MIDIClientDispose(m_client); if (result != noErr) { qDebug() << "MIDIClientDispose() err:" << result; m_client = 0; } } } void reloadDeviceList(bool advanced) { int num = MIDIGetNumberOfSources(); m_clientFilter = !advanced; m_inputDevices.clear(); for (int i = 0; i < num; ++i) { bool excluded = false; MIDIEndpointRef dest = MIDIGetSource( i ); if (dest != 0) { QString name = getEndpointName(dest); if ( m_clientFilter && name.contains(QLatin1String("IAC"), Qt::CaseSensitive) ) continue; if ( name.contains(m_publicName)) continue; foreach( const QString& n, m_excludedNames) { if (name.contains(n)) { excluded = true; break; } } if (!excluded) m_inputDevices << name; } } if (!m_currentInput.isEmpty() && m_source != 0 && !m_inputDevices.contains(m_currentInput)) { m_currentInput.clear(); m_source = 0; } } void setPublicName(QString name) { if (m_publicName != name) { internalDispose(); internalCreate(name.toCFString()); m_publicName = name; } } void open(QString name) { int index = -1; OSStatus result = noErr; QStringList allInputDevices; int num = MIDIGetNumberOfSources(); for (int i = 0; i < num; ++i) { MIDIEndpointRef dest = MIDIGetSource( i ); if (dest != 0) allInputDevices << getEndpointName( dest ); } index = allInputDevices.indexOf(name); if (index < 0) return; m_source = MIDIGetSource( index ); result = MIDIPortConnectSource( m_port, m_source, nullptr ); if (result != noErr) { qDebug() << "MIDIPortConnectSource() error:" << result; return; } m_currentInput = name; return; } void close() { OSStatus result = noErr; if (m_source != 0) { result = MIDIPortDisconnectSource(m_port, m_source); if (result != noErr) qDebug() << "MIDIPortDisconnectSource() error:" << result; m_source = 0; m_currentInput.clear(); } } void emitSignals(QByteArray& packet) { int value = 0, j = 0; while(j < packet.length()) { int status = packet[j] & 0xf0; int channel = packet[j] & 0x0f; QByteArray data; switch (status) { case MIDI_STATUS_NOTEOFF: if(m_out != nullptr && m_thruEnabled) m_out->sendNoteOff(channel, packet[j+1], packet[j+2]); emit m_inp->midiNoteOff(channel, packet[j+1], packet[j+2]); j+=3; break; case MIDI_STATUS_NOTEON: if(m_out != nullptr && m_thruEnabled) m_out->sendNoteOn(channel, packet[j+1], packet[j+2]); emit m_inp->midiNoteOn(channel, packet[j+1], packet[j+2]); j+=3; break; case MIDI_STATUS_KEYPRESURE: if(m_out != nullptr && m_thruEnabled) m_out->sendKeyPressure(channel, packet[j+1], packet[j+2]); emit m_inp->midiKeyPressure(channel, packet[j+1], packet[j+2]); j+=3; break; case MIDI_STATUS_CONTROLCHANGE: if(m_out != nullptr && m_thruEnabled) m_out->sendController(channel, packet[j+1], packet[j+2]); emit m_inp->midiController(channel, packet[j+1], packet[j+2]); j+=3; break; case MIDI_STATUS_PROGRAMCHANGE: if(m_out != nullptr && m_thruEnabled) m_out->sendProgram(channel, packet[j+1]); emit m_inp->midiProgram(channel, packet[j+1]); j+=2; break; case MIDI_STATUS_CHANNELPRESSURE: if(m_out != nullptr && m_thruEnabled) m_out->sendChannelPressure(channel, packet[j+1]); emit m_inp->midiChannelPressure(channel, packet[j+1]); j+=2; break; case MIDI_STATUS_PITCHBEND: value = (packet[j+1] + packet[j+2] * 0x80) - 8192; if(m_out != nullptr && m_thruEnabled) m_out->sendPitchBend(channel, value); emit m_inp->midiPitchBend(channel, value); j+=3; break; case MIDI_STATUS_SYSEX: if(m_out != nullptr && m_thruEnabled) m_out->sendSysex(packet); emit m_inp->midiSysex(packet); j+=packet.length(); break; default: qDebug() << "status?" << status; } } } }; void MacMIDIReadProc( const MIDIPacketList *pktlist, void *refCon, void *connRefCon ) { Q_UNUSED(connRefCon) MacMIDIInputPrivate *obj = nullptr; if (refCon != nullptr) obj = static_cast(refCon); const MIDIPacket *packet = static_cast(pktlist->packet); for (unsigned int i = 0; i < pktlist->numPackets; ++i) { if (obj != nullptr && packet != nullptr) { QByteArray data((const char *)packet->data, packet->length); QtConcurrent::run(obj, &MacMIDIInputPrivate::emitSignals, data); } packet = MIDIPacketNext(packet); } } MacMIDIInput::MacMIDIInput(QObject *parent) : MIDIInput(parent), d(new MacMIDIInputPrivate(this)) { } MacMIDIInput::~MacMIDIInput() { delete d; } void MacMIDIInput::initialize(QSettings *settings) { Q_UNUSED(settings) } QString MacMIDIInput::backendName() { return QLatin1Literal("CoreMIDI"); } QString MacMIDIInput::publicName() { return d->m_publicName; } void MacMIDIInput::setPublicName(QString name) { d->setPublicName(name); } QStringList MacMIDIInput::connections(bool advanced) { d->reloadDeviceList(advanced); return d->m_inputDevices; } void MacMIDIInput::setExcludedConnections(QStringList conns) { d->m_excludedNames = conns; } void MacMIDIInput::open(QString name) { d->open(name); } void MacMIDIInput::close() { d->close(); } QString MacMIDIInput::currentConnection() { return d->m_currentInput; } void MacMIDIInput::setMIDIThruDevice(MIDIOutput *device) { d->m_out = device; } void MacMIDIInput::enableMIDIThru(bool enable) { d->m_thruEnabled = enable; } bool MacMIDIInput::isEnabledMIDIThru() { return d->m_thruEnabled && d->m_out != 0; } }} // namespace drumstick::rt drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316021674 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.733999895 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/CMakeLists.txt0000644000175000001440000000307713532747316022474 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . if(FALSE) add_subdirectory(dummy-in) add_subdirectory(dummy-out) endif() if(ALSA_FOUND) add_subdirectory(alsa-in) add_subdirectory(alsa-out) endif() if (PULSE_FOUND) add_subdirectory(eassynth) endif() find_package(Qt5Network) if(Qt5Network_FOUND) add_subdirectory(net-in) add_subdirectory(net-out) endif() if(UNIX AND NOT APPLE) add_subdirectory(oss-in) add_subdirectory(oss-out) endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") add_subdirectory(mac-in) add_subdirectory(mac-out) add_subdirectory(macsynth) endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") add_subdirectory(win-in) add_subdirectory(win-out) endif() if (PKG_CONFIG_FOUND) pkg_check_modules(FLUIDSYNTH fluidsynth>=1.1.1 fluidsynth<=1.1.11) if(FLUIDSYNTH_FOUND) add_subdirectory(fluidsynth) endif() endif() drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/net-out0000644000000000000000000000013013532747316020450 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/net-out/0000755000175000001440000000000013532747316021320 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/net-out/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013013532747316023265 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/net-out/CMakeLists.txt0000644000175000001440000000414113532747316024060 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . find_package(Qt5Network REQUIRED) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(drumstick-rt-net-out_QTOBJ_SRCS ../../include/drumstick/rtmidioutput.h netmidioutput.h ) set(drumstick-rt-net-out_SRCS netmidioutput.cpp ) qt5_wrap_cpp(drumstick-rt-net-out_MOC_SRCS ${drumstick-rt-net-out_QTOBJ_SRCS} OPTIONS -I ${DRUMSTICK_SOURCE_DIR}/library/include ) if(STATIC_DRUMSTICK) add_library(drumstick-rt-net-out STATIC ${drumstick-rt-net-out_MOC_SRCS} ${drumstick-rt-net-out_SRCS}) target_compile_definitions(drumstick-rt-net-out PRIVATE QT_STATICPLUGIN) set_target_properties(drumstick-rt-net-out PROPERTIES STATIC_LIB "libdrumstick-rt-net-out") else() add_library(drumstick-rt-net-out MODULE ${drumstick-rt-net-out_MOC_SRCS} ${drumstick-rt-net-out_SRCS}) target_compile_definitions(drumstick-rt-net-out PRIVATE QT_PLUGIN) endif() target_include_directories(drumstick-rt-net-out PRIVATE ${DRUMSTICK_SOURCE_DIR}/library/include ) target_link_libraries(drumstick-rt-net-out Qt5::Network) set_target_properties(drumstick-rt-net-out PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/drumstick) install(TARGETS drumstick-rt-net-out RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick) drumstick-1.1.3/library/rt-backends/net-out/PaxHeaders.32572/netmidioutput.cpp0000644000000000000000000000013013532747316024143 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/net-out/netmidioutput.cpp0000644000175000001440000001544013532747316024742 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include "netmidioutput.h" namespace drumstick { namespace rt { static QString DEFAULT_PUBLIC_NAME(QLatin1String("MIDI Out")); class NetMIDIOutput::NetMIDIOutputPrivate { public: QUdpSocket *m_socket; QString m_publicName; QHostAddress m_groupAddress; QString m_currentOutput; QStringList m_outputDevices; QStringList m_excludedNames; QNetworkInterface m_iface; quint16 m_port; bool m_ipv6; NetMIDIOutputPrivate() : m_socket(nullptr), m_publicName(DEFAULT_PUBLIC_NAME), m_groupAddress(QHostAddress(STR_ADDRESS_IPV4)), m_port(0), m_ipv6(false) { for(int i=MULTICAST_PORT; ibeginGroup("Network"); QString ifaceName = settings->value("interface", QString()).toString(); m_ipv6 = settings->value("ipv6", false).toBool(); QString address = settings->value("address", m_ipv6 ? STR_ADDRESS_IPV6 : STR_ADDRESS_IPV4).toString(); settings->endGroup(); if (!ifaceName.isEmpty()) { m_iface = QNetworkInterface::interfaceFromName(ifaceName); } if (address.isEmpty()) { m_groupAddress.setAddress(m_ipv6 ? STR_ADDRESS_IPV6 : STR_ADDRESS_IPV4); } else { m_groupAddress.setAddress(address); } } } void open(QString portName) { qDebug() << Q_FUNC_INFO << portName; int p = m_outputDevices.indexOf(portName); if (p > -1) { m_socket = new QUdpSocket(); bool res = m_socket->bind(m_ipv6 ? QHostAddress::AnyIPv6 : QHostAddress::AnyIPv4, m_socket->localPort()); if (res) { m_socket->setSocketOption(QAbstractSocket::MulticastTtlOption, 1); #ifdef Q_OS_UNIX m_socket->setSocketOption(QAbstractSocket::MulticastLoopbackOption, 0); #endif m_port = static_cast(MULTICAST_PORT + p); if (m_iface.isValid()) { m_socket->setMulticastInterface(m_iface); } m_currentOutput = portName; } if (!res) { qWarning() << Q_FUNC_INFO << "Socket error:" << m_socket->error() << m_socket->errorString(); } } } void close() { delete m_socket; m_socket = nullptr; m_currentOutput.clear(); } void sendMessage(int m0) { QByteArray m; m.resize(1); m[0] = static_cast(m0); sendMessage(m); } void sendMessage(int m0, int m1) { QByteArray m; m.resize(2); m[0] = static_cast(m0); m[1] = static_cast(m1); sendMessage(m); } void sendMessage(int m0, int m1, int m2) { QByteArray m; m.resize(3); m[0] = static_cast(m0); m[1] = static_cast(m1); m[2] = static_cast(m2); sendMessage(m); } void sendMessage(const QByteArray& message ) { //qDebug() << Q_FUNC_INFO << message.toHex() << m_groupAddress << m_port; if (m_socket == nullptr) { qWarning() << Q_FUNC_INFO << "udp socket is null"; return; } else if (!m_socket->isValid() || m_socket->state() != QAbstractSocket::BoundState) { qWarning() << Q_FUNC_INFO << "udp socket has invalid state:" << m_socket->state() << "Error:" << m_socket->error() << m_socket->errorString(); return; } auto res = m_socket->writeDatagram(message, m_groupAddress, m_port); //qDebug() << Q_FUNC_INFO << "writeDatagram:" << res; if (res < 0) { qWarning() << Q_FUNC_INFO << "Error:" << m_socket->error() << m_socket->errorString(); } } }; NetMIDIOutput::NetMIDIOutput(QObject *parent) : MIDIOutput(parent), d(new NetMIDIOutputPrivate) { } NetMIDIOutput::~NetMIDIOutput() { delete d; } void NetMIDIOutput::initialize(QSettings *settings) { d->initialize(settings); } QString NetMIDIOutput::backendName() { return QLatin1String("Network"); } QString NetMIDIOutput::publicName() { return d->m_publicName; } void NetMIDIOutput::setPublicName(QString name) { d->m_publicName = name; } QStringList NetMIDIOutput::connections(bool advanced) { Q_UNUSED(advanced) return d->m_outputDevices; } void NetMIDIOutput::setExcludedConnections(QStringList conns) { Q_UNUSED(conns) } void NetMIDIOutput::open(QString name) { d->open(name); } void NetMIDIOutput::close() { d->close(); } QString NetMIDIOutput::currentConnection() { return d->m_currentOutput; } void NetMIDIOutput::sendNoteOff(int chan, int note, int vel) { d->sendMessage(MIDI_STATUS_NOTEOFF + chan, note, vel); } void NetMIDIOutput::sendNoteOn(int chan, int note, int vel) { d->sendMessage(MIDI_STATUS_NOTEON + chan, note, vel); } void NetMIDIOutput::sendKeyPressure(int chan, int note, int value) { d->sendMessage(MIDI_STATUS_KEYPRESURE + chan, note, value); } void NetMIDIOutput::sendController(int chan, int control, int value) { d->sendMessage(MIDI_STATUS_CONTROLCHANGE + chan, control, value); } void NetMIDIOutput::sendProgram(int chan, int program) { d->sendMessage(MIDI_STATUS_PROGRAMCHANGE + chan, program); } void NetMIDIOutput::sendChannelPressure(int chan, int value) { d->sendMessage(MIDI_STATUS_CHANNELPRESSURE + chan, value); } void NetMIDIOutput::sendPitchBend(int chan, int v) { // -8192 <= v <= 8191; 0 <= value <= 16384 int value = 8192 + v; d->sendMessage(MIDI_STATUS_PITCHBEND + chan, MIDI_LSB(value), MIDI_MSB(value)); } void NetMIDIOutput::sendSysex(const QByteArray &data) { d->sendMessage(data); } void NetMIDIOutput::sendSystemMsg(const int status) { d->sendMessage(status); } }} drumstick-1.1.3/library/rt-backends/net-out/PaxHeaders.32572/netmidioutput.h0000644000000000000000000000013013532747316023610 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/net-out/netmidioutput.h0000644000175000001440000000502613532747316024406 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef NETMIDIOUTPUT_H #define NETMIDIOUTPUT_H #include #include #include namespace drumstick { namespace rt { const QString STR_ADDRESS_IPV4(QLatin1Literal("225.0.0.37")); const QString STR_ADDRESS_IPV6(QLatin1Literal("ff12::37")); const int MULTICAST_PORT(21928); const int LAST_PORT(21948); class NetMIDIOutput : public MIDIOutput { Q_OBJECT Q_PLUGIN_METADATA(IID "net.sourceforge.drumstick.rt.MIDIOutput") Q_INTERFACES(drumstick::rt::MIDIOutput) public: NetMIDIOutput(QObject *parent = nullptr); virtual ~NetMIDIOutput(); // MIDIOutput interface public: virtual void initialize(QSettings* settings); virtual QString backendName(); virtual QString publicName(); virtual void setPublicName(QString name); virtual QStringList connections(bool advanced); virtual void setExcludedConnections(QStringList conns); virtual void open(QString name); virtual void close(); virtual QString currentConnection(); public slots: virtual void sendNoteOff(int chan, int note, int vel); virtual void sendNoteOn(int chan, int note, int vel); virtual void sendKeyPressure(int chan, int note, int value); virtual void sendController(int chan, int control, int value); virtual void sendProgram(int chan, int program); virtual void sendChannelPressure(int chan, int value); virtual void sendPitchBend(int chan, int value); virtual void sendSysex(const QByteArray &data); virtual void sendSystemMsg(const int status); private: class NetMIDIOutputPrivate; NetMIDIOutputPrivate * const d; }; }} #endif // NETMIDIOUTPUT_H drumstick-1.1.3/library/rt-backends/net-out/PaxHeaders.32572/net-out.pro0000644000000000000000000000013013532747316022642 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/net-out/net-out.pro0000644000175000001440000000075513532747316023444 0ustar00pedrousers00000000000000TEMPLATE = lib CONFIG += plugin static { CONFIG += staticlib create_prl } TARGET = drumstick-rt-net-out DESTDIR = ../../../build/lib/drumstick DEPENDPATH += . ../../include INCLUDEPATH += . ../../include include (../../../global.pri) DEPENDPATH += ../../include INCLUDEPATH += ../../include QT -= gui HEADERS += ../../include/drumstick/rtmidiinput.h \ ../../include/drumstick/rtmidioutput.h \ netmidioutput.h SOURCES += \ netmidioutput.cpp QT += network drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/oss-out0000644000000000000000000000013013532747316020466 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/oss-out/0000755000175000001440000000000013532747316021336 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/oss-out/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013013532747316023303 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/oss-out/CMakeLists.txt0000644000175000001440000000406413532747316024102 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(CMAKE_INCLUDE_CURRENT_DIR ON) set(drumstick-rt-oss-out_QTOBJ_SRCS ../../include/drumstick/rtmidioutput.h ossoutput.h ) set(drumstick-rt-oss-out_SRCS ossoutput.cpp ) qt5_wrap_cpp(drumstick-rt-oss-out_MOC_SRCS ${drumstick-rt-oss-out_QTOBJ_SRCS} OPTIONS -I ${DRUMSTICK_SOURCE_DIR}/library/include ) if(STATIC_DRUMSTICK) add_library(drumstick-rt-oss-out STATIC ${drumstick-rt-oss-out_MOC_SRCS} ${drumstick-rt-oss-out_SRCS}) target_compile_definitions(drumstick-rt-oss-out PRIVATE QT_STATICPLUGIN) set_target_properties(drumstick-rt-oss-out PROPERTIES STATIC_LIB "libdrumstick-rt-oss-out") else() add_library(drumstick-rt-oss-out MODULE ${drumstick-rt-oss-out_MOC_SRCS} ${drumstick-rt-oss-out_SRCS}) target_compile_definitions(drumstick-rt-oss-out PRIVATE QT_PLUGIN) endif() target_include_directories(drumstick-rt-oss-out PRIVATE ${DRUMSTICK_SOURCE_DIR}/library/include ) target_link_libraries(drumstick-rt-oss-out Qt5::Core) set_target_properties(drumstick-rt-oss-out PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/drumstick) install(TARGETS drumstick-rt-oss-out RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick) drumstick-1.1.3/library/rt-backends/oss-out/PaxHeaders.32572/ossoutput.h0000644000000000000000000000013013532747316023001 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/oss-out/ossoutput.h0000644000175000001440000000447213532747316023603 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef ossOUTPUT_H #define ossOUTPUT_H #include #include namespace drumstick { namespace rt { class OSSOutput : public MIDIOutput { Q_OBJECT #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) Q_PLUGIN_METADATA(IID "net.sourceforge.drumstick.rt.MIDIOutput") #endif Q_INTERFACES(drumstick::rt::MIDIOutput) public: OSSOutput(QObject *parent = 0); virtual ~OSSOutput(); // MIDIOutput interface public: virtual void initialize(QSettings* settings); virtual QString backendName(); virtual QString publicName(); virtual void setPublicName(QString name); virtual QStringList connections(bool advanced); virtual void setExcludedConnections(QStringList conns); virtual void open(QString name); virtual void close(); virtual QString currentConnection(); public slots: virtual void sendNoteOff(int chan, int note, int vel); virtual void sendNoteOn(int chan, int note, int vel); virtual void sendKeyPressure(int chan, int note, int value); virtual void sendController(int chan, int control, int value); virtual void sendProgram(int chan, int program); virtual void sendChannelPressure(int chan, int value); virtual void sendPitchBend(int chan, int value); virtual void sendSysex(const QByteArray &data); virtual void sendSystemMsg(const int status); private: class OSSOutputPrivate; OSSOutputPrivate *d; }; }} #endif // ossOUTPUT_H drumstick-1.1.3/library/rt-backends/oss-out/PaxHeaders.32572/oss-out.pro0000644000000000000000000000013013532747316022676 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/oss-out/oss-out.pro0000644000175000001440000000063313532747316023473 0ustar00pedrousers00000000000000TEMPLATE = lib TARGET = drumstick-rt-oss-out DESTDIR = ../../../build/lib/drumstick include (../../../global.pri) CONFIG += plugin static { CONFIG += staticlib create_prl } DEPENDPATH += ../../include INCLUDEPATH += ../../include QT -= gui HEADERS += ../../include/drumstick/rtmidiinput.h \ ../../include/drumstick/rtmidioutput.h \ ossoutput.h SOURCES += \ ossoutput.cpp drumstick-1.1.3/library/rt-backends/oss-out/PaxHeaders.32572/ossoutput.cpp0000644000000000000000000000013013532747316023334 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.733999895 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/oss-out/ossoutput.cpp0000644000175000001440000001162113532747316024130 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include "ossoutput.h" namespace drumstick { namespace rt { static QString DEFAULT_PUBLIC_NAME(QLatin1String("MIDI Out")); class OSSOutput::OSSOutputPrivate { public: bool m_advanced; QIODevice *m_device; QString m_publicName; QString m_currentOutput; QStringList m_outputDevices; QStringList m_excludedNames; OSSOutputPrivate() : m_advanced(false), m_device(0), m_publicName(DEFAULT_PUBLIC_NAME) { reloadDeviceList(); } ~OSSOutputPrivate() { close(); } void reloadDeviceList(bool advanced = false) { QDir dir("/dev"); QStringList filters; m_advanced = advanced; filters << "dmmidi*" << "admmidi*"; if (advanced) { filters << "midi*" << "amidi*"; } dir.setNameFilters(filters); dir.setFilter(QDir::System); dir.setSorting(QDir::Name); m_outputDevices.clear(); QFileInfoList listInfo = dir.entryInfoList(); foreach(const QFileInfo &info, listInfo) { m_outputDevices << info.absoluteFilePath(); } } void open(QString portName) { //qDebug() << Q_FUNC_INFO << portName; m_device = new QFile(portName); m_device->open(QIODevice::WriteOnly | QIODevice::Unbuffered); m_currentOutput = portName; } void close() { if (m_device != 0) { m_device->close(); delete m_device; m_device = 0; } m_currentOutput.clear(); } void sendMessage(int m0) { QByteArray m; m.resize(1); m[0] = m0; sendMessage(m); } void sendMessage(int m0, int m1) { QByteArray m; m.resize(2); m[0] = m0; m[1] = m1; sendMessage(m); } void sendMessage(int m0, int m1, int m2) { QByteArray m; m.resize(3); m[0] = m0; m[1] = m1; m[2] = m2; sendMessage(m); } void sendMessage(const QByteArray& message ) { if (m_device == 0) { qDebug() << "qfile is null"; return; } m_device->write(message); //m_device->flush(); } }; OSSOutput::OSSOutput(QObject *parent) : MIDIOutput(parent), d(new OSSOutputPrivate) {} OSSOutput::~OSSOutput() { delete d; } void OSSOutput::initialize(QSettings *settings) { Q_UNUSED(settings) } QString OSSOutput::backendName() { return QLatin1String("OSS"); } QString OSSOutput::publicName() { return d->m_publicName; } void OSSOutput::setPublicName(QString name) { d->m_publicName = name; } QStringList OSSOutput::connections(bool advanced) { d->reloadDeviceList(advanced); return d->m_outputDevices; } void OSSOutput::setExcludedConnections(QStringList conns) { Q_UNUSED(conns) } void OSSOutput::open(QString name) { d->open(name); } void OSSOutput::close() { d->close(); } QString OSSOutput::currentConnection() { return d->m_currentOutput; } void OSSOutput::sendNoteOff(int chan, int note, int vel) { d->sendMessage(MIDI_STATUS_NOTEOFF + chan, note, vel);} void OSSOutput::sendNoteOn(int chan, int note, int vel) { d->sendMessage(MIDI_STATUS_NOTEON + chan, note, vel); } void OSSOutput::sendKeyPressure(int chan, int note, int value) { d->sendMessage(MIDI_STATUS_KEYPRESURE + chan, note, value); } void OSSOutput::sendController(int chan, int control, int value) { d->sendMessage(MIDI_STATUS_CONTROLCHANGE + chan, control, value); } void OSSOutput::sendProgram(int chan, int program) { d->sendMessage(MIDI_STATUS_PROGRAMCHANGE + chan, program); } void OSSOutput::sendChannelPressure(int chan, int value) { d->sendMessage(MIDI_STATUS_CHANNELPRESSURE + chan, value); } void OSSOutput::sendPitchBend(int chan, int v) { // -8192 <= v <= 8191; 0 <= value <= 16384 int value = 8192 + v; d->sendMessage(MIDI_STATUS_PITCHBEND + chan, MIDI_LSB(value), MIDI_MSB(value)); } void OSSOutput::sendSysex(const QByteArray &data) { d->sendMessage(data); } void OSSOutput::sendSystemMsg(const int status) { d->sendMessage(status); } }} drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/alsa-out0000644000000000000000000000013213532747316020604 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.733999895 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/alsa-out/0000755000175000001440000000000013532747316021452 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/alsa-out/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316023421 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.733999895 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/alsa-out/CMakeLists.txt0000644000175000001440000000400013532747316024204 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(CMAKE_INCLUDE_CURRENT_DIR ON) set(drumstick-rt-alsa-out_QTOBJ_SRCS ../../include/drumstick/rtmidioutput.h alsamidioutput.h ) set(drumstick-rt-alsa-out_SRCS alsamidioutput.cpp ) qt5_wrap_cpp(drumstick-rt-alsa-out_MOC_SRCS ${drumstick-rt-alsa-out_QTOBJ_SRCS} OPTIONS -I ${DRUMSTICK_SOURCE_DIR}/library/include ) if(STATIC_DRUMSTICK) add_library(drumstick-rt-alsa-out STATIC ${drumstick-rt-alsa-out_MOC_SRCS} ${drumstick-rt-alsa-out_SRCS}) target_compile_definitions(drumstick-rt-alsa-out PRIVATE QT_STATICPLUGIN) set_target_properties(drumstick-rt-alsa-out PROPERTIES STATIC_LIB "libdrumstick-rt-alsa-out") else() add_library(drumstick-rt-alsa-out MODULE ${drumstick-rt-alsa-out_MOC_SRCS} ${drumstick-rt-alsa-out_SRCS} ) target_compile_definitions(drumstick-rt-alsa-out PRIVATE QT_PLUGIN) endif() target_link_libraries(drumstick-rt-alsa-out drumstick-alsa Qt5::Core) set_target_properties(drumstick-rt-alsa-out PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/drumstick) install(TARGETS drumstick-rt-alsa-out RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick) drumstick-1.1.3/library/rt-backends/alsa-out/PaxHeaders.32572/alsa-out.pro0000644000000000000000000000013213532747316023130 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.733999895 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/alsa-out/alsa-out.pro0000644000175000001440000000066413532747316023727 0ustar00pedrousers00000000000000TEMPLATE = lib CONFIG += plugin static { CONFIG += staticlib create_prl } TARGET = drumstick-rt-alsa-out DESTDIR = ../../../build/lib/drumstick DEPENDPATH += . ../../include INCLUDEPATH += . ../../include include (../../../global.pri) QT -= gui HEADERS += ../../include/drumstick/rtmidioutput.h \ alsamidioutput.h SOURCES += alsamidioutput.cpp LIBS += -L../../../build/lib \ -ldrumstick-alsa \ -lasound drumstick-1.1.3/library/rt-backends/alsa-out/PaxHeaders.32572/alsamidioutput.cpp0000644000000000000000000000013213532747316024431 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.733999895 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/alsa-out/alsamidioutput.cpp0000644000175000001440000001667513532747316025241 0ustar00pedrousers00000000000000/* Drumstick RT Backend using the ALSA Sequencer Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include "alsamidioutput.h" namespace drumstick { namespace rt { static QString DEFAULT_PUBLIC_NAME(QLatin1String("MIDI Out")); class ALSAMIDIOutput::ALSAMIDIOutputPrivate { public: ALSAMIDIOutput *m_out; MidiClient *m_client; MidiPort *m_port; int m_portId; bool m_clientFilter; int m_runtimeAlsaNum; QString m_publicName; QString m_currentOutput; QStringList m_outputDevices; QStringList m_excludedNames; QMutex m_outMutex; ALSAMIDIOutputPrivate(ALSAMIDIOutput *q): m_out(q), m_client(0), m_port(0), m_portId(0), m_clientFilter(true), m_runtimeAlsaNum(0), m_publicName(DEFAULT_PUBLIC_NAME) { m_runtimeAlsaNum = getRuntimeALSALibraryNumber(); m_client = new MidiClient(m_out); m_client->open(); m_client->setClientName(m_publicName); m_port = m_client->createPort(); m_port->setPortName("out"); m_port->setCapability( SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ ); m_port->setPortType( SND_SEQ_PORT_TYPE_APPLICATION | SND_SEQ_PORT_TYPE_MIDI_GENERIC ); m_portId = m_port->getPortId(); } ~ALSAMIDIOutputPrivate() { if (m_client != NULL) { clearSubscription(); if (m_port != NULL) m_port->detach(); m_client->close(); delete m_client; } } bool clientIsAdvanced(int clientId) { // asking for runtime version instead of SND_LIB_VERSION if (m_runtimeAlsaNum < 0x01000B) // ALSA <= 1.0.10 return (clientId < 64); else // ALSA >= 1.0.11 return (clientId < 16); } void reloadDeviceList(bool advanced) { m_clientFilter = !advanced; m_outputDevices.clear(); QListIterator it(m_client->getAvailableOutputs()); while(it.hasNext()) { bool excluded = false; PortInfo p = it.next(); QString name = QString("%1:%2").arg(p.getClientName()).arg(p.getPort()); if (m_clientFilter && clientIsAdvanced(p.getClient())) continue; if ( m_clientFilter && name.startsWith(QLatin1String("Virtual Raw MIDI")) ) continue; if ( name.startsWith(m_publicName) ) continue; foreach(const QString& n, m_excludedNames) { if ( name.startsWith(n) ) { excluded = true; break; } } if (!excluded) m_outputDevices << name; } if (!m_currentOutput.isEmpty() && !m_outputDevices.contains(m_currentOutput)) { m_currentOutput.clear(); } } bool setSubscription(const QString &newOutputDevice) { //qDebug() << Q_FUNC_INFO << newOutputDevice; if (m_outputDevices.contains(newOutputDevice)) { m_currentOutput = newOutputDevice; m_port->unsubscribeAll(); m_port->subscribeTo(newOutputDevice); return true; } return false; } void clearSubscription() { if (!m_currentOutput.isEmpty()) { m_port->unsubscribeAll(); m_currentOutput.clear(); } } void sendEvent(SequencerEvent *ev) { QMutexLocker locker(&m_outMutex); ev->setSource(m_portId); ev->setSubscribers(); ev->setDirect(); m_client->outputDirect(ev); } void setPublicName(QString newName) { if (newName != m_publicName) { m_client->setClientName(newName); m_publicName = newName; } } }; ALSAMIDIOutput::ALSAMIDIOutput(QObject *parent) : MIDIOutput(parent), d(new ALSAMIDIOutputPrivate(this)) { } ALSAMIDIOutput::~ALSAMIDIOutput() { delete d; } void ALSAMIDIOutput::initialize(QSettings* settings) { Q_UNUSED(settings) } /* SLOTS */ void ALSAMIDIOutput::sendNoteOn(int chan, int note, int vel) { NoteOnEvent ev(chan, note, vel); d->sendEvent(&ev); } void ALSAMIDIOutput::sendNoteOff(int chan, int note, int vel) { NoteOffEvent ev(chan, note, vel); d->sendEvent(&ev); } void ALSAMIDIOutput::sendController(int chan, int control, int value) { ControllerEvent ev(chan, control, value); d->sendEvent(&ev); } void ALSAMIDIOutput::sendKeyPressure(int chan, int note, int value) { KeyPressEvent ev(chan, note, value); d->sendEvent(&ev); } void ALSAMIDIOutput::sendProgram(int chan, int program) { ProgramChangeEvent ev(chan, program); d->sendEvent(&ev); } void ALSAMIDIOutput::sendChannelPressure(int chan, int value) { ChanPressEvent ev(chan, value); d->sendEvent(&ev); } void ALSAMIDIOutput::sendPitchBend(int chan, int value) { PitchBendEvent ev(chan, value); d->sendEvent(&ev); } void ALSAMIDIOutput::sendSysex(const QByteArray& data) { SysExEvent ev(data); d->sendEvent(&ev); } void ALSAMIDIOutput::sendSystemMsg(const int status) { SystemEvent ev(status); d->sendEvent(&ev); } QString ALSAMIDIOutput::backendName() { return "ALSA"; } QString ALSAMIDIOutput::publicName() { return d->m_publicName; } void ALSAMIDIOutput::setPublicName(QString name) { d->setPublicName(name); } QStringList ALSAMIDIOutput::connections(bool advanced) { d->reloadDeviceList(advanced); return d->m_outputDevices; } void ALSAMIDIOutput::setExcludedConnections(QStringList conns) { d->m_excludedNames = conns; } QString ALSAMIDIOutput::currentConnection() { return d->m_currentOutput; } void ALSAMIDIOutput::open(QString name) { d->setSubscription(name); } void ALSAMIDIOutput::close() { d->clearSubscription(); } }} drumstick-1.1.3/library/rt-backends/alsa-out/PaxHeaders.32572/alsamidioutput.h0000644000000000000000000000013213532747316024076 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.733999895 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/alsa-out/alsamidioutput.h0000644000175000001440000000450413532747316024672 0ustar00pedrousers00000000000000/* Drumstick RT Backend using the ALSA Sequencer Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef ALSAMIDIOUTPUT_H #define ALSAMIDIOUTPUT_H #include #include namespace drumstick { namespace rt { class ALSAMIDIOutput : public MIDIOutput { Q_OBJECT #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) Q_PLUGIN_METADATA(IID "net.sourceforge.drumstick.rt.MIDIOutput") #endif Q_INTERFACES(drumstick::rt::MIDIOutput) public: ALSAMIDIOutput(QObject *parent = 0); virtual ~ALSAMIDIOutput(); virtual void initialize(QSettings* settings); virtual QString backendName(); virtual QString publicName(); virtual void setPublicName(QString name); virtual QStringList connections(bool advanced); virtual void setExcludedConnections(QStringList conns); virtual void open(QString name); virtual void close(); virtual QString currentConnection(); public slots: virtual void sendNoteOn(int chan, int note, int vel); virtual void sendNoteOff(int chan, int note, int vel); virtual void sendController(int chan, int control, int value); virtual void sendKeyPressure(int chan, int note, int value); virtual void sendProgram(int chan, int program); virtual void sendChannelPressure(int chan, int value); virtual void sendPitchBend(int chan, int value); virtual void sendSysex(const QByteArray& data); virtual void sendSystemMsg(const int status); private: class ALSAMIDIOutputPrivate; ALSAMIDIOutputPrivate *d; }; }} #endif /* ALSAMIDIOUTPUT_H */ drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/eassynth0000644000000000000000000000013213532747316020715 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.733999895 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/eassynth/0000755000175000001440000000000013532747316021563 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/eassynth/PaxHeaders.32572/eassynth.pro0000644000000000000000000000013213532747316023352 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.733999895 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/eassynth/eassynth.pro0000644000175000001440000000011213532747316024135 0ustar00pedrousers00000000000000TEMPLATE = subdirs CONFIG += ordered SUBDIRS += sonivox \ src drumstick-1.1.3/library/rt-backends/eassynth/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316023532 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.733999895 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/eassynth/CMakeLists.txt0000644000175000001440000000020013532747316024313 0ustar00pedrousers00000000000000set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DQT_NO_DEBUG_OUTPUT") add_subdirectory(sonivox) add_subdirectory(src) drumstick-1.1.3/library/rt-backends/eassynth/PaxHeaders.32572/sonivox0000644000000000000000000000013213532747316022422 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.733999895 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/0000755000175000001440000000000013532747316023270 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/eassynth/sonivox/PaxHeaders.32572/lib_src0000644000000000000000000000013213532747316024037 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.733999895 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/0000755000175000001440000000000013532747316024705 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_xmfdata.h0000644000000000000000000000013213532747316026541 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.733999895 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_xmfdata.h0000644000175000001440000000313613532747316027335 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_xmfdata.h * * Contents and purpose: * Contains declarations for the XMF file parser. * * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_XMFDATA_H #define _EAS_XMFDATA_H #include "eas_data.h" /*---------------------------------------------------------------------------- * * S_XMF_DATA * * This structure contains the instance data required to parse an XMF file. * *---------------------------------------------------------------------------- */ typedef struct { EAS_FILE_HANDLE fileHandle; EAS_I32 fileOffset; EAS_VOID_PTR pSMFData; EAS_I32 midiOffset; EAS_I32 dlsOffset; S_DLS *pDLS; } S_XMF_DATA; #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_xmf.c0000644000000000000000000000013213532747316025702 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.733999895 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_xmf.c0000644000175000001440000006644713532747316026514 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_xmf.c * 5 * Contents and purpose: * XMF File Parser * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 501 $ * $Date: 2006-12-11 17:53:36 -0800 (Mon, 11 Dec 2006) $ *---------------------------------------------------------------------------- */ #include "eas_data.h" #include "eas_miditypes.h" #include "eas_parser.h" #include "eas_report.h" #include "eas_host.h" #include "eas_midi.h" #include "eas_xmf.h" #include "eas_xmfdata.h" #include "eas_config.h" #include "eas_vm_protos.h" #include "eas_mdls.h" #include "eas_smf.h" /* XMF header file type */ #define XMF_IDENTIFIER 0x584d465f #define XMF_VERSION_1_00 0x312e3030 #define XMF_VERSION_1_01 0x312e3031 #define XMF_VERSION_2_00 0x322e3030 #define XMF_FILE_TYPE 0x00000002 #define XMF_SPEC_LEVEL 0x00000001 #define XMF_RIFF_CHUNK 0x52494646 #define XMF_RIFF_DLS 0x444c5320 #define XMF_SMF_CHUNK 0x4d546864 /* local prototypes */ static EAS_RESULT XMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); static EAS_RESULT XMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT XMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); static EAS_RESULT XMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); static EAS_RESULT XMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); static EAS_RESULT XMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT XMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT XMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT XMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT XMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); static EAS_RESULT XMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); static EAS_RESULT XMF_FindFileContents (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData); static EAS_RESULT XMF_ReadNode (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData, EAS_I32 nodeOffset, EAS_I32 *pLength); static EAS_RESULT XMF_ReadVLQ (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 *value); /*---------------------------------------------------------------------------- * * XMF_Parser * * This structure contains the functional interface for the XMF parser *---------------------------------------------------------------------------- */ const S_FILE_PARSER_INTERFACE EAS_XMF_Parser = { XMF_CheckFileType, XMF_Prepare, XMF_Time, XMF_Event, XMF_State, XMF_Close, XMF_Reset, XMF_Pause, XMF_Resume, NULL, XMF_SetData, XMF_GetData, NULL }; /*---------------------------------------------------------------------------- * XMF_CheckFileType() *---------------------------------------------------------------------------- * Purpose: * Check the file type to see if we can parse it * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT XMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) { S_XMF_DATA *pXMFData; EAS_RESULT result; EAS_U32 temp; /* assume we don't recognize it initially */ *ppHandle = NULL; /* read the file identifier */ if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS) return result; if (temp != XMF_IDENTIFIER) return EAS_SUCCESS; /* read the version */ if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS) return result; if (temp == XMF_VERSION_2_00) { /* read the file type */ result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE); if (result != EAS_SUCCESS) return result; if (temp != XMF_FILE_TYPE) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "XMF file type was 0x%08x, expected 0x%08x\n", temp, XMF_FILE_TYPE); */ } return EAS_SUCCESS; } /* read the spec level */ result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &temp, EAS_TRUE); if (result != EAS_SUCCESS) return result; if (temp != XMF_SPEC_LEVEL) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "XMF file spec was 0x%08x, expected 0x%08x\n", temp, XMF_SPEC_LEVEL); */ } return EAS_SUCCESS; } } else if (temp != XMF_VERSION_1_00 && temp != XMF_VERSION_1_01) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "XMF file version was 0x%08x\n", temp); */ } return EAS_SUCCESS; } /* check for static memory allocation */ if (pEASData->staticMemoryModel) pXMFData = EAS_CMEnumData(EAS_CM_XMF_DATA); else pXMFData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_XMF_DATA)); if (!pXMFData) return EAS_ERROR_MALLOC_FAILED; /* zero the memory to insure complete initialization */ EAS_HWMemSet((void *)pXMFData,0, sizeof(S_XMF_DATA)); pXMFData->fileHandle = fileHandle; pXMFData->fileOffset = offset; *ppHandle = pXMFData; /* locate the SMF and DLS contents */ if ((result = XMF_FindFileContents(pEASData->hwInstData, pXMFData)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No SMF data found in XMF file\n"); */ } return result; } /* let the SMF parser take over */ if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, pXMFData->midiOffset)) != EAS_SUCCESS) return result; return SMF_CheckFileType(pEASData, fileHandle, &pXMFData->pSMFData, pXMFData->midiOffset); } /*---------------------------------------------------------------------------- * XMF_Prepare() *---------------------------------------------------------------------------- * Purpose: * Prepare to parse the file. Allocates instance data (or uses static allocation for * static memory model). * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT XMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_XMF_DATA* pXMFData; EAS_RESULT result; /* parse DLS collection */ pXMFData = (S_XMF_DATA*) pInstData; if (pXMFData->dlsOffset != 0) { if ((result = DLSParser(pEASData->hwInstData, pXMFData->fileHandle, pXMFData->dlsOffset, &pXMFData->pDLS)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error converting XMF DLS data\n"); */ } return result; } } /* Prepare the SMF parser */ if ((result = SMF_Prepare(pEASData, pXMFData->pSMFData)) != EAS_SUCCESS) return result; /* if no DLS file, skip this step */ if (pXMFData->pDLS == NULL) return EAS_SUCCESS; /* tell the synth to use the DLS collection */ result = VMSetDLSLib(((S_SMF_DATA*) pXMFData->pSMFData)->pSynth, pXMFData->pDLS); if (result == EAS_SUCCESS) { DLSAddRef(pXMFData->pDLS); VMInitializeAllChannels(pEASData->pVoiceMgr, ((S_SMF_DATA*) pXMFData->pSMFData)->pSynth); } return result; } /*---------------------------------------------------------------------------- * XMF_Time() *---------------------------------------------------------------------------- * Purpose: * Returns the time of the next event in msecs * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * pTime - pointer to variable to hold time of next event (in msecs) * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT XMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) { return SMF_Time(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, pTime); } /*---------------------------------------------------------------------------- * XMF_Event() *---------------------------------------------------------------------------- * Purpose: * Parse the next event in the file * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT XMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) { return SMF_Event(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, parserMode); } /*---------------------------------------------------------------------------- * XMF_State() *---------------------------------------------------------------------------- * Purpose: * Returns the current state of the stream * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * pState - pointer to variable to store state * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT XMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) { return SMF_State(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, pState); } /*---------------------------------------------------------------------------- * XMF_Close() *---------------------------------------------------------------------------- * Purpose: * Close the file and clean up * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT XMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_XMF_DATA* pXMFData; EAS_RESULT result; pXMFData = (S_XMF_DATA *)pInstData; /* close the SMF stream, it will close the file handle */ if ((result = SMF_Close(pEASData, pXMFData->pSMFData)) != EAS_SUCCESS) return result; if (pXMFData->pDLS) DLSCleanup(pEASData->hwInstData, pXMFData->pDLS); /* if using dynamic memory, free it */ if (!pEASData->staticMemoryModel) { /* free the instance data */ EAS_HWFree(pEASData->hwInstData, pXMFData); } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * XMF_Reset() *---------------------------------------------------------------------------- * Purpose: * Reset the sequencer. Used for locating backwards in the file. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT XMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { return SMF_Reset(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData); } /*---------------------------------------------------------------------------- * XMF_Pause() *---------------------------------------------------------------------------- * Purpose: * Pauses the sequencer. Mutes all voices and sets state to pause. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT XMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { return SMF_Pause(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData); } /*---------------------------------------------------------------------------- * XMF_Resume() *---------------------------------------------------------------------------- * Purpose: * Resume playing after a pause, sets state back to playing. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT XMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { return SMF_Resume(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData); } /*---------------------------------------------------------------------------- * XMF_SetData() *---------------------------------------------------------------------------- * Purpose: * Sets the playback rate of the underlying SMF file * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * rate - rate (28-bit fraction) * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT XMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) { return SMF_SetData(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, param, value); } /*---------------------------------------------------------------------------- * XMF_GetData() *---------------------------------------------------------------------------- * Purpose: * Gets the file type * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * rate - rate (28-bit fraction) * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT XMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) { EAS_RESULT result; /* call SMF parser to get value */ if ((result = SMF_GetData(pEASData, ((S_XMF_DATA*) pInstData)->pSMFData, param, pValue)) != EAS_SUCCESS) return result; /* special case for file type */ if (param == PARSER_DATA_FILE_TYPE) { if (*pValue == EAS_FILE_SMF0) *pValue = EAS_FILE_XMF0; else if (*pValue == EAS_FILE_SMF1) *pValue = EAS_FILE_XMF1; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * XMF_FindFileContents() *---------------------------------------------------------------------------- * Purpose: * Finds SMF data and DLS data in XMF file, and remembers offset for each. * If more than one is found, uses the first one found of each. * Makes assumptions about the format of a mobile XMF file * * Inputs: * pEASData - pointer to overall EAS data structure * pXMFData - pointer to XMF parser instance data * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT XMF_FindFileContents (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData) { EAS_RESULT result; EAS_I32 value; EAS_I32 length; /* initialize offsets */ pXMFData->dlsOffset = pXMFData->midiOffset = 0; /* read file length, ignore it for now */ if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS) return result; /* read MetaDataTypesTable length and skip over it */ if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS) return result; if ((result = EAS_HWFileSeekOfs(hwInstData, pXMFData->fileHandle, value)) != EAS_SUCCESS) return result; /* get TreeStart offset and jump to it */ if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &value)) != EAS_SUCCESS) return result; if ((result = XMF_ReadNode(hwInstData, pXMFData, value, &length)) != EAS_SUCCESS) return result; /* check for SMF data */ if (pXMFData->midiOffset == 0) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No SMF data found in XMF file\n"); */ } return EAS_ERROR_FILE_FORMAT; } /* check for SFM in wrong order */ if ((pXMFData->dlsOffset > 0) && (pXMFData->midiOffset < pXMFData->dlsOffset)) { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS data must precede SMF data in Mobile XMF file\n"); */ } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * XMF_ReadNode() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT XMF_ReadNode (EAS_HW_DATA_HANDLE hwInstData, S_XMF_DATA *pXMFData, EAS_I32 nodeOffset, EAS_I32 *pLength) { EAS_RESULT result; EAS_I32 refType; EAS_I32 numItems; EAS_I32 offset; EAS_I32 length; EAS_I32 headerLength; EAS_U32 chunkType; /* seek to start of node */ if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, nodeOffset)) != EAS_SUCCESS) return result; /* get node length */ if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, pLength)) != EAS_SUCCESS) return result; /* get number of contained items */ if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &numItems)) != EAS_SUCCESS) return result; /* get node header length */ if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &headerLength)) != EAS_SUCCESS) return result; /* get metadata length */ if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &length)) != EAS_SUCCESS) return result; /* get the current location */ if ((result = EAS_HWFilePos(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS) return result; /* skip to node contents */ if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, nodeOffset + headerLength)) != EAS_SUCCESS) return result; /* get reference type */ if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &refType)) != EAS_SUCCESS) return result; /* get the current location */ if ((result = EAS_HWFilePos(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS) return result; /* process file node */ if (numItems == 0) { /* if in-file resource, find out where it is and jump to it */ if (refType == 2) { if ((result = XMF_ReadVLQ(hwInstData, pXMFData->fileHandle, &offset)) != EAS_SUCCESS) return result; offset += pXMFData->fileOffset; if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, offset)) != EAS_SUCCESS) return result; } /* or else it must be an inline resource */ else if (refType != 1) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected reference type %d\n", refType); */ } return EAS_ERROR_FILE_FORMAT; } /* get the chunk type */ if ((result = EAS_HWGetDWord(hwInstData, pXMFData->fileHandle, &chunkType, EAS_TRUE)) != EAS_SUCCESS) return result; /* found a RIFF chunk, check for DLS type */ if (chunkType == XMF_RIFF_CHUNK) { /* skip length */ if ((result = EAS_HWFileSeekOfs(hwInstData, pXMFData->fileHandle, sizeof(EAS_I32))) != EAS_SUCCESS) return result; /* get RIFF file type */ if ((result = EAS_HWGetDWord(hwInstData, pXMFData->fileHandle, &chunkType, EAS_TRUE)) != EAS_SUCCESS) return result; if (chunkType == XMF_RIFF_DLS) pXMFData->dlsOffset = offset; } /* found an SMF chunk */ else if (chunkType == XMF_SMF_CHUNK) pXMFData->midiOffset = offset; } /* folder node, process the items in the list */ else { for ( ; numItems > 0; numItems--) { /* process this item */ if ((result = XMF_ReadNode(hwInstData, pXMFData, offset, &length)) != EAS_SUCCESS) return result; /* seek to start of next item */ offset += length; if ((result = EAS_HWFileSeek(hwInstData, pXMFData->fileHandle, offset)) != EAS_SUCCESS) return result; } } return EAS_SUCCESS; } #if 0 /*---------------------------------------------------------------------------- * XMF_FindFileContents() *---------------------------------------------------------------------------- * Purpose: * Finds SMF data and DLS data in XMF file, and remembers offset for each. * If more than one is found, uses the first one found of each. * Makes assumptions about the format of a mobile XMF file * * Inputs: * pEASData - pointer to overall EAS data structure * pXMFData - pointer to XMF parser instance data * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT XMF_FindFileContents(S_EAS_DATA *pEASData, S_XMF_DATA *pXMFData, EAS_FILE_HANDLE fileHandle) { EAS_RESULT result; EAS_I32 offset; EAS_I32 value; EAS_I32 numItems; EAS_I32 length; EAS_CHAR id[4]; EAS_I32 location; /* init dls offset, so that we know we haven't found a dls chunk yet */ pXMFData->dlsOffset = 0; /* read file length, ignore it for now */ if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) return result; /* read MetaDataTypesTable length and skip over it */ if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) return result; if ((result = EAS_HWFileSeekOfs(pEASData, fileHandle, value)) != EAS_SUCCESS) return result; /* get TreeStart offset and jump to it */ if ((result = XMF_ReadVLQ(pEASData, fileHandle, &offset)) != EAS_SUCCESS) return result; if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset)) != EAS_SUCCESS) return result; /* read node length, ignore it for now */ if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) return result; /* read number of contained items */ if ((result = XMF_ReadVLQ(pEASData, fileHandle, &numItems)) != EAS_SUCCESS) return result; /*read node header length */ if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) return result; /*go to the node offset */ if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + value)) != EAS_SUCCESS) return result; /* read Reference Type */ if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) return result; /* make sure it is an in-line resource, for now */ if (value != 1) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file tree\n"); */ } return EAS_FAILURE; } /* parse through the list of items */ while (numItems > 0) { /*get current offset */ if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &offset)) != EAS_SUCCESS) return result; /*read node length */ if ((result = XMF_ReadVLQ(pEASData, fileHandle, &length)) != EAS_SUCCESS) return result; /* read number of items */ if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) return result; /* make sure not a folder */ if (value != 0) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file node\n"); */ } return EAS_FAILURE; } /* read offset to resource and jump to it */ if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) return result; if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + value)) != EAS_SUCCESS) return result; /* read Reference Type */ if ((result = XMF_ReadVLQ(pEASData, fileHandle, &value)) != EAS_SUCCESS) return result; /* make sure it is an in-line resource */ if (value != 1) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Problem parsing XMF file node\n"); */ } return EAS_FAILURE; } /* get current offset as a possible location for SMF file or DLS file */ if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &location)) != EAS_SUCCESS) return result; /* read four bytes */ if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, id, sizeof(id), &value)) != EAS_SUCCESS) return result; /* check if DLS */ if (pXMFData->dlsOffset == 0 && id[0] == 'R' && id[1] == 'I' && id[2] == 'F' && id[3] == 'F') { //remember offset pXMFData->dlsOffset = location; } /* else check if SMF */ else if (id[0] == 'M' && id[1] == 'T' && id[2] == 'h' && id[3] == 'd') { //remember offset pXMFData->midiOffset = location; //we are done return EAS_SUCCESS; } //one less item numItems--; //if more data, go to the next item if (numItems >0) { if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset + length)) != EAS_SUCCESS) return result; } } return EAS_FAILURE; } #endif /*---------------------------------------------------------------------------- * XMF_ReadVLQ() *---------------------------------------------------------------------------- * Purpose: * Reads a VLQ encoded value from the file referenced by fileHandle * * Inputs: * pEASData - pointer to overall EAS data structure * fileHandle - pointer to file handle * * Outputs: * value - pointer to the value decoded from the VLQ data * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT XMF_ReadVLQ (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 *value) { EAS_RESULT result; EAS_U8 c; *value = 0; if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS) return result; while (c > 0x7F) { /*lint -e{703} shift for performance */ *value = (*value << 7) | (c & 0x7F); if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS) return result; } /*lint -e{703} shift for performance */ *value = (*value << 7) | c; return EAS_SUCCESS; } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_wt_IPC_frame.h0000644000000000000000000000013213532747316027414 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.733999895 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_wt_IPC_frame.h0000644000175000001440000000556113532747316030214 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_wt_IPC_frame.h * * Contents and purpose: * This module contains data definitions for the interprocessor * communications framework for a split-architecture synthesizer. * * This sample version writes IPC data to a file that can be used * as a test vector for the DSP simulator. For a real-time system * the file I/O is replaced with an IPC protocol in the hardware. * * Synchronization with the DSP is accomplished at the API level, * i.e. the host code should call EAS_Render when it is ready to * buffer another block of data for transmission to the DSP. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 818 $ * $Date: 2007-08-02 15:19:41 -0700 (Thu, 02 Aug 2007) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_WT_IPC_FRAME_H #define _EAS_WT_IPC_FRAME_H /*---------------------------------------------------------------------------- * S_WT_FRAME * * This structure contains the common parameters that are updated *for each frame of audio. *---------------------------------------------------------------------------- */ typedef struct s_wt_frame_tag { EAS_I32 gainTarget; EAS_I32 phaseIncrement; #if defined(_FILTER_ENABLED) EAS_I32 k; EAS_I32 b1; EAS_I32 b2; #endif } S_WT_FRAME; /*---------------------------------------------------------------------------- * S_WT_CONFIG * * This structure contains state data for the wavetable engine *---------------------------------------------------------------------------- */ typedef struct s_wt_config_tag { EAS_U32 loopEnd; /* points to last PCM sample (not 1 beyond last) */ EAS_U32 loopStart; /* points to first sample at start of loop */ EAS_U32 phaseAccum; /* current sample, integer portion of phase */ #if (NUM_OUTPUT_CHANNELS == 2) EAS_I16 gainLeft; /* left channel gain */ EAS_I16 gainRight; /* right channel gain */ #endif EAS_I16 gain; /* current voice gain */ } S_WT_CONFIG; #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_public.c0000644000000000000000000000013213532747316026366 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.733999895 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_public.c0000644000175000001440000025365513532747316027177 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_public.c * * Contents and purpose: * Contains EAS library public interface * * Copyright Sonic Network Inc. 2004 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 842 $ * $Date: 2007-08-23 14:32:31 -0700 (Thu, 23 Aug 2007) $ *---------------------------------------------------------------------------- */ #include "eas_synthcfg.h" #include "eas.h" #include "eas_config.h" #include "eas_host.h" #include "eas_report.h" #include "eas_data.h" #include "eas_parser.h" #include "eas_pcm.h" #include "eas_midi.h" #include "eas_mixer.h" #include "eas_build.h" #include "eas_vm_protos.h" #include "eas_math.h" #ifdef JET_INTERFACE #include "jet_data.h" #endif #ifdef DLS_SYNTHESIZER #include "eas_mdls.h" #endif /* number of events to parse before calling EAS_HWYield function */ #define YIELD_EVENT_COUNT 10 /*---------------------------------------------------------------------------- * easLibConfig * * This structure is available through the EAS public interface to allow * the user to check the configuration of the library. *---------------------------------------------------------------------------- */ static const S_EAS_LIB_CONFIG easLibConfig = { LIB_VERSION, #ifdef _CHECKED_BUILD EAS_TRUE, #else EAS_FALSE, #endif MAX_SYNTH_VOICES, NUM_OUTPUT_CHANNELS, _OUTPUT_SAMPLE_RATE, BUFFER_SIZE_IN_MONO_SAMPLES, #ifdef _FILTER_ENABLED EAS_TRUE, #else EAS_FALSE, #endif _BUILD_TIME_, _BUILD_VERSION_ }; /* local prototypes */ static EAS_RESULT EAS_ParseEvents (S_EAS_DATA *pEASData, S_EAS_STREAM *pStream, EAS_U32 endTime, EAS_INT parseMode); /*---------------------------------------------------------------------------- * EAS_SetStreamParameter *---------------------------------------------------------------------------- * Sets the specified parameter in the stream. Allows access to * customizable settings within the individual file parsers. *---------------------------------------------------------------------------- * pEASData - pointer to EAS persistent data object * pStream - stream handle * param - enumerated parameter (see eas_parser.h) * value - new value *---------------------------------------------------------------------------- */ EAS_RESULT EAS_SetStreamParameter (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 param, EAS_I32 value) { S_FILE_PARSER_INTERFACE *pParserModule; pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; if (pParserModule->pfSetData) return (*pParserModule->pfSetData)(pEASData, pStream->handle, param, value); return EAS_ERROR_FEATURE_NOT_AVAILABLE; } /*---------------------------------------------------------------------------- * EAS_GetStreamParameter *---------------------------------------------------------------------------- * Sets the specified parameter in the stream. Allows access to * customizable settings within the individual file parsers. *---------------------------------------------------------------------------- * pEASData - pointer to EAS persistent data object * pStream - stream handle * param - enumerated parameter (see eas_parser.h) * pValue - pointer to variable to receive current setting *---------------------------------------------------------------------------- */ EAS_RESULT EAS_GetStreamParameter (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 param, EAS_I32 *pValue) { S_FILE_PARSER_INTERFACE *pParserModule; pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; if (pParserModule->pfGetData) return (*pParserModule->pfGetData)(pEASData, pStream->handle, param, pValue); return EAS_ERROR_FEATURE_NOT_AVAILABLE; } /*---------------------------------------------------------------------------- * EAS_StreamReady() *---------------------------------------------------------------------------- * This routine sets common parameters like transpose, volume, etc. * First, it attempts to use the parser EAS_SetStreamParameter interface. If that * fails, it attempts to get the synth handle from the parser and * set the parameter directly on the synth. This eliminates duplicate * code in the parser. *---------------------------------------------------------------------------- */ EAS_BOOL EAS_StreamReady (S_EAS_DATA *pEASData, EAS_HANDLE pStream) { S_FILE_PARSER_INTERFACE *pParserModule; EAS_STATE state; pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; if (pParserModule->pfState(pEASData, pStream->handle, &state) != EAS_SUCCESS) return EAS_FALSE; return (state < EAS_STATE_OPEN); } /*---------------------------------------------------------------------------- * EAS_IntSetStrmParam() *---------------------------------------------------------------------------- * This routine sets common parameters like transpose, volume, etc. * First, it attempts to use the parser EAS_SetStreamParameter interface. If that * fails, it attempts to get the synth handle from the parser and * set the parameter directly on the synth. This eliminates duplicate * code in the parser. *---------------------------------------------------------------------------- */ EAS_RESULT EAS_IntSetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 value) { S_SYNTH *pSynth; /* try to set the parameter using stream interface */ if (EAS_SetStreamParameter(pEASData, pStream, param, value) == EAS_SUCCESS) return EAS_SUCCESS; /* get a pointer to the synth object and set it directly */ /*lint -e{740} we are cheating by passing a pointer through this interface */ if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) return EAS_ERROR_INVALID_PARAMETER; if (pSynth == NULL) return EAS_ERROR_INVALID_PARAMETER; switch (param) { #ifdef DLS_SYNTHESIZER case PARSER_DATA_DLS_COLLECTION: { EAS_RESULT result = VMSetDLSLib(pSynth, (EAS_DLSLIB_HANDLE) value); if (result == EAS_SUCCESS) { DLSAddRef((S_DLS*) value); VMInitializeAllChannels(pEASData->pVoiceMgr, pSynth); } return result; } #endif case PARSER_DATA_EAS_LIBRARY: return VMSetEASLib(pSynth, (EAS_SNDLIB_HANDLE) value); case PARSER_DATA_POLYPHONY: return VMSetPolyphony(pEASData->pVoiceMgr, pSynth, value); case PARSER_DATA_PRIORITY: return VMSetPriority(pEASData->pVoiceMgr, pSynth, value); case PARSER_DATA_TRANSPOSITION: VMSetTranposition(pSynth, value); break; case PARSER_DATA_VOLUME: VMSetVolume(pSynth, (EAS_U16) value); break; default: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Invalid paramter %d in call to EAS_IntSetStrmParam", param); */ } return EAS_ERROR_INVALID_PARAMETER; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_IntGetStrmParam() *---------------------------------------------------------------------------- * This routine gets common parameters like transpose, volume, etc. * First, it attempts to use the parser EAS_GetStreamParameter interface. If that * fails, it attempts to get the synth handle from the parser and * get the parameter directly on the synth. *---------------------------------------------------------------------------- */ EAS_RESULT EAS_IntGetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 *pValue) { S_SYNTH *pSynth; /* try to set the parameter */ if (EAS_GetStreamParameter(pEASData, pStream, param, pValue) == EAS_SUCCESS) return EAS_SUCCESS; /* get a pointer to the synth object and retrieve data directly */ /*lint -e{740} we are cheating by passing a pointer through this interface */ if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) return EAS_ERROR_INVALID_PARAMETER; if (pSynth == NULL) return EAS_ERROR_INVALID_PARAMETER; switch (param) { case PARSER_DATA_POLYPHONY: return VMGetPolyphony(pEASData->pVoiceMgr, pSynth, pValue); case PARSER_DATA_PRIORITY: return VMGetPriority(pEASData->pVoiceMgr, pSynth, pValue); case PARSER_DATA_TRANSPOSITION: VMGetTranposition(pSynth, pValue); break; case PARSER_DATA_NOTE_COUNT: *pValue = VMGetNoteCount(pSynth); break; default: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Invalid paramter %d in call to EAS_IntSetStrmParam", param); */ } return EAS_ERROR_INVALID_PARAMETER; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_AllocateStream() *---------------------------------------------------------------------------- * Purpose: * Allocates a stream handle * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ static EAS_INT EAS_AllocateStream (EAS_DATA_HANDLE pEASData) { EAS_INT streamNum; /* check for static allocation, only one stream allowed */ if (pEASData->staticMemoryModel) { if (pEASData->streams[0].handle != NULL) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Attempt to open multiple streams in static model\n"); */ } return -1; } return 0; } /* dynamic model */ for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++) if (pEASData->streams[streamNum].handle == NULL) break; if (streamNum == MAX_NUMBER_STREAMS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Exceeded maximum number of open streams\n"); */ } return -1; } return streamNum; } /*---------------------------------------------------------------------------- * EAS_InitStream() *---------------------------------------------------------------------------- * Purpose: * Initialize a stream * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ static void EAS_InitStream (S_EAS_STREAM *pStream, EAS_VOID_PTR pParserModule, EAS_VOID_PTR streamHandle) { pStream->pParserModule = pParserModule; pStream->handle = streamHandle; pStream->time = 0; pStream->frameLength = AUDIO_FRAME_LENGTH; pStream->repeatCount = 0; pStream->volume = DEFAULT_STREAM_VOLUME; pStream->streamFlags = 0; } /*---------------------------------------------------------------------------- * EAS_Config() *---------------------------------------------------------------------------- * Purpose: * Returns a pointer to a structure containing the configuration options * in this library build. * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ EAS_PUBLIC const S_EAS_LIB_CONFIG *EAS_Config (void) { return &easLibConfig; } /*---------------------------------------------------------------------------- * EAS_Init() *---------------------------------------------------------------------------- * Purpose: * Initialize the synthesizer library * * Inputs: * ppEASData - pointer to data handle variable for this instance * * Outputs: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_Init (EAS_DATA_HANDLE *ppEASData) { EAS_HW_DATA_HANDLE pHWInstData; EAS_RESULT result; S_EAS_DATA *pEASData; EAS_INT module; EAS_BOOL staticMemoryModel; /* get the memory model */ staticMemoryModel = EAS_CMStaticMemoryModel(); /* initialize the host wrapper interface */ *ppEASData = NULL; if ((result = EAS_HWInit(&pHWInstData)) != EAS_SUCCESS) return result; /* check Configuration Module for S_EAS_DATA allocation */ if (staticMemoryModel) pEASData = EAS_CMEnumData(EAS_CM_EAS_DATA); else pEASData = EAS_HWMalloc(pHWInstData, sizeof(S_EAS_DATA)); if (!pEASData) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate EAS library memory\n"); */ } return EAS_ERROR_MALLOC_FAILED; } /* initialize some data */ EAS_HWMemSet(pEASData, 0, sizeof(S_EAS_DATA)); pEASData->staticMemoryModel = (EAS_BOOL8) staticMemoryModel; pEASData->hwInstData = pHWInstData; pEASData->renderTime = 0; /* set header search flag */ #ifdef FILE_HEADER_SEARCH pEASData->searchHeaderFlag = EAS_TRUE; #endif /* initalize parameters */ EAS_SetVolume(pEASData, NULL, DEFAULT_VOLUME); #ifdef _METRICS_ENABLED /* initalize the metrics module */ pEASData->pMetricsModule = EAS_CMEnumOptModules(EAS_MODULE_METRICS); if (pEASData->pMetricsModule != NULL) { if ((result = (*pEASData->pMetricsModule->pfInit)(pEASData, &pEASData->pMetricsData)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld initializing metrics module\n", result); */ } return result; } } #endif /* initailize the voice manager & synthesizer */ if ((result = VMInitialize(pEASData)) != EAS_SUCCESS) return result; /* initialize mix engine */ if ((result = EAS_MixEngineInit(pEASData)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld starting up mix engine\n", result); */ } return result; } /* initialize effects modules */ for (module = 0; module < NUM_EFFECTS_MODULES; module++) { pEASData->effectsModules[module].effect = EAS_CMEnumFXModules(module); if (pEASData->effectsModules[module].effect != NULL) { if ((result = (*pEASData->effectsModules[module].effect->pfInit)(pEASData, &pEASData->effectsModules[module].effectData)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Initialization of effects module %d returned %d\n", module, result); */ } return result; } } } /* initialize PCM engine */ if ((result = EAS_PEInit(pEASData)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_PEInit failed with error code %ld\n", result); */ } return result; } /* return instance data pointer to host */ *ppEASData = pEASData; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_Shutdown() *---------------------------------------------------------------------------- * Purpose: * Shuts down the library. Deallocates any memory associated with the * synthesizer (dynamic memory model only) * * Inputs: * pEASData - handle to data for this instance * * Outputs: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_Shutdown (EAS_DATA_HANDLE pEASData) { EAS_HW_DATA_HANDLE hwInstData; EAS_RESULT result, reportResult; EAS_INT i; /* establish pointers */ hwInstData = pEASData->hwInstData; /* check for NULL handle */ if (!pEASData) return EAS_ERROR_HANDLE_INTEGRITY; /* if there are streams open, close them */ reportResult = EAS_SUCCESS; for (i = 0; i < MAX_NUMBER_STREAMS; i++) { if (pEASData->streams[i].pParserModule && pEASData->streams[i].handle) { if ((result = (*((S_FILE_PARSER_INTERFACE*)(pEASData->streams[i].pParserModule))->pfClose)(pEASData, pEASData->streams[i].handle)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down parser module\n", result); */ } reportResult = result; } } } /* shutdown PCM engine */ if ((result = EAS_PEShutdown(pEASData)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down PCM engine\n", result); */ } if (reportResult == EAS_SUCCESS) reportResult = result; } /* shutdown mix engine */ if ((result = EAS_MixEngineShutdown(pEASData)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down mix engine\n", result); */ } if (reportResult == EAS_SUCCESS) reportResult = result; } /* shutdown effects modules */ for (i = 0; i < NUM_EFFECTS_MODULES; i++) { if (pEASData->effectsModules[i].effect) { if ((result = (*pEASData->effectsModules[i].effect->pfShutdown)(pEASData, pEASData->effectsModules[i].effectData)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Shutdown of effects module %d returned %d\n", i, result); */ } if (reportResult == EAS_SUCCESS) reportResult = result; } } } /* shutdown the voice manager & synthesizer */ VMShutdown(pEASData); #ifdef _METRICS_ENABLED /* shutdown the metrics module */ if (pEASData->pMetricsModule != NULL) { if ((result = (*pEASData->pMetricsModule->pfShutdown)(pEASData, pEASData->pMetricsData)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down metrics module\n", result); */ } if (reportResult == EAS_SUCCESS) reportResult = result; } } #endif /* release allocated memory */ if (!pEASData->staticMemoryModel) EAS_HWFree(hwInstData, pEASData); /* shutdown host wrappers */ if (hwInstData) { if ((result = EAS_HWShutdown(hwInstData)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %ld shutting down host wrappers\n", result); */ } if (reportResult == EAS_SUCCESS) reportResult = result; } } return reportResult; } #ifdef JET_INTERFACE /*---------------------------------------------------------------------------- * EAS_OpenJETStream() *---------------------------------------------------------------------------- * Private interface for JET to open an SMF stream with an offset *---------------------------------------------------------------------------- */ EAS_RESULT EAS_OpenJETStream (EAS_DATA_HANDLE pEASData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_HANDLE *ppStream) { EAS_RESULT result; EAS_VOID_PTR streamHandle; S_FILE_PARSER_INTERFACE *pParserModule; EAS_INT streamNum; /* allocate a stream */ if ((streamNum = EAS_AllocateStream(pEASData)) < 0) return EAS_ERROR_MAX_STREAMS_OPEN; /* check Configuration Module for SMF parser */ *ppStream = NULL; streamHandle = NULL; pParserModule = (S_FILE_PARSER_INTERFACE *) EAS_CMEnumModules(0); if (pParserModule == NULL) return EAS_ERROR_UNRECOGNIZED_FORMAT; /* see if SMF parser recognizes the file */ if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, offset)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ } return result; } /* parser recognized the file, return the handle */ if (streamHandle) { EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle); *ppStream = &pEASData->streams[streamNum]; return EAS_SUCCESS; } return EAS_ERROR_UNRECOGNIZED_FORMAT; } #endif /*---------------------------------------------------------------------------- * EAS_OpenFile() *---------------------------------------------------------------------------- * Purpose: * Opens a file for audio playback. * * Inputs: * pEASData - pointer to overall EAS data structure * pHandle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_OpenFile (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *ppStream) { EAS_RESULT result; EAS_FILE_HANDLE fileHandle; EAS_VOID_PTR streamHandle; S_FILE_PARSER_INTERFACE *pParserModule; EAS_INT streamNum; EAS_INT moduleNum; /* open the file */ if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS) return result; /* allocate a stream */ if ((streamNum = EAS_AllocateStream(pEASData)) < 0) { /* Closing the opened file as stream allocation failed */ EAS_HWCloseFile(pEASData->hwInstData, fileHandle); return EAS_ERROR_MAX_STREAMS_OPEN; } /* check Configuration Module for file parsers */ pParserModule = NULL; *ppStream = NULL; streamHandle = NULL; for (moduleNum = 0; ; moduleNum++) { pParserModule = (S_FILE_PARSER_INTERFACE *) EAS_CMEnumModules(moduleNum); if (pParserModule == NULL) break; /* see if this parser recognizes it */ if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, 0L)) != EAS_SUCCESS) { /* Closing the opened file as file type check failed */ EAS_HWCloseFile(pEASData->hwInstData, fileHandle); { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ } return result; } /* parser recognized the file, return the handle */ if (streamHandle) { /* save the parser pointer and file handle */ EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle); *ppStream = &pEASData->streams[streamNum]; return EAS_SUCCESS; } /* rewind the file for the next parser */ if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, 0L)) != EAS_SUCCESS) { /* Closing the opened file as file seek failed */ EAS_HWCloseFile(pEASData->hwInstData, fileHandle); return result; } } /* no parser was able to recognize the file, close it and return an error */ EAS_HWCloseFile(pEASData->hwInstData, fileHandle); { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "No parser recognized the requested file\n"); */ } return EAS_ERROR_UNRECOGNIZED_FORMAT; } #ifdef MMAPI_SUPPORT /*---------------------------------------------------------------------------- * EAS_MMAPIToneControl() *---------------------------------------------------------------------------- * Purpose: * Opens a ToneControl file for audio playback. * * Inputs: * pEASData - pointer to overall EAS data structure * pHandle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_MMAPIToneControl (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *ppStream) { EAS_RESULT result; EAS_FILE_HANDLE fileHandle; EAS_VOID_PTR streamHandle; S_FILE_PARSER_INTERFACE *pParserModule; EAS_INT streamNum; /* check if the tone control parser is available */ *ppStream = NULL; streamHandle = NULL; pParserModule = EAS_CMEnumOptModules(EAS_MODULE_MMAPI_TONE_CONTROL); if (pParserModule == NULL) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_MMAPIToneControl: ToneControl parser not available\n"); */ } return EAS_ERROR_FEATURE_NOT_AVAILABLE; } /* open the file */ if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS) return result; /* allocate a stream */ if ((streamNum = EAS_AllocateStream(pEASData)) < 0) return EAS_ERROR_MAX_STREAMS_OPEN; /* see if ToneControl parser recognizes it */ if ((result = (*pParserModule->pfCheckFileType)(pEASData, fileHandle, &streamHandle, 0L)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "CheckFileType returned error %ld\n", result); */ } return result; } /* parser accepted the file, return the handle */ if (streamHandle) { /* save the parser pointer and file handle */ EAS_InitStream(&pEASData->streams[streamNum], pParserModule, streamHandle); *ppStream = &pEASData->streams[streamNum]; return EAS_SUCCESS; } /* parser did not recognize the file, close it and return an error */ EAS_HWCloseFile(pEASData->hwInstData, fileHandle); { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "No parser recognized the requested file\n"); */ } return EAS_ERROR_UNRECOGNIZED_FORMAT; } /*---------------------------------------------------------------------------- * EAS_GetWaveFmtChunk *---------------------------------------------------------------------------- * Helper function to retrieve WAVE file fmt chunk for MMAPI *---------------------------------------------------------------------------- * pEASData - pointer to EAS persistent data object * pStream - stream handle * pFmtChunk - pointer to variable to receive current setting *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetWaveFmtChunk (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_VOID_PTR *ppFmtChunk) { EAS_RESULT result; EAS_I32 value; if ((result = EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_FORMAT, &value)) != EAS_SUCCESS) return result; *ppFmtChunk = (EAS_VOID_PTR) value; return EAS_SUCCESS; } #endif /*---------------------------------------------------------------------------- * EAS_GetFileType *---------------------------------------------------------------------------- * Returns the file type (see eas_types.h for enumerations) *---------------------------------------------------------------------------- * pEASData - pointer to EAS persistent data object * pStream - stream handle * pFileType - pointer to variable to receive file type *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetFileType (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_I32 *pFileType) { if (!EAS_StreamReady (pEASData, pStream)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; return EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_FILE_TYPE, pFileType); } /*---------------------------------------------------------------------------- * EAS_Prepare() *---------------------------------------------------------------------------- * Purpose: * Prepares the synthesizer to play the file or stream. Parses the first * frame of data from the file and arms the synthesizer. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - file or stream handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_Prepare (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) { S_FILE_PARSER_INTERFACE *pParserModule; EAS_STATE state; EAS_RESULT result; pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; if (pParserModule == NULL) return EAS_ERROR_FEATURE_NOT_AVAILABLE; /* check for valid state */ result = pParserModule->pfState(pEASData, pStream->handle, &state); if (result == EAS_SUCCESS) { /* prepare the stream */ if (state == EAS_STATE_OPEN) { pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; result = (*pParserModule->pfPrepare)(pEASData, pStream->handle); /* set volume */ if (result == EAS_SUCCESS) result = EAS_SetVolume(pEASData, pStream, pStream->volume); } else result = EAS_ERROR_NOT_VALID_IN_THIS_STATE; } return result; } /*---------------------------------------------------------------------------- * EAS_Render() *---------------------------------------------------------------------------- * Purpose: * Parse the Midi data and render PCM audio data. * * Inputs: * pEASData - buffer for internal EAS data * pOut - output buffer pointer * nNumRequested - requested num samples to generate * pnNumGenerated - actual number of samples generated * * Outputs: * EAS_SUCCESS if PCM data was successfully rendered * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_Render (EAS_DATA_HANDLE pEASData, EAS_PCM *pOut, EAS_I32 numRequested, EAS_I32 *pNumGenerated) { S_FILE_PARSER_INTERFACE *pParserModule; EAS_RESULT result; EAS_I32 voicesRendered; EAS_STATE parserState; EAS_INT streamNum; /* assume no samples generated and reset workload */ *pNumGenerated = 0; VMInitWorkload(pEASData->pVoiceMgr); /* no support for other buffer sizes yet */ if (numRequested != BUFFER_SIZE_IN_MONO_SAMPLES) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "This library supports only %ld samples in buffer, host requested %ld samples\n", (EAS_I32) BUFFER_SIZE_IN_MONO_SAMPLES, numRequested); */ } return EAS_BUFFER_SIZE_MISMATCH; } #ifdef _METRICS_ENABLED /* start performance counter */ if (pEASData->pMetricsData) (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME); #endif /* prep the frame buffer, do mix engine prep only if TRUE */ #ifdef _SPLIT_ARCHITECTURE if (VMStartFrame(pEASData)) EAS_MixEnginePrep(pEASData, numRequested); #else /* prep the mix engine */ EAS_MixEnginePrep(pEASData, numRequested); #endif /* save the output buffer pointer */ pEASData->pOutputAudioBuffer = pOut; #ifdef _METRICS_ENABLED /* start performance counter */ if (pEASData->pMetricsData) (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_PARSE_TIME); #endif /* if we haven't finished parsing from last time, do it now */ /* need to parse another frame of events before we render again */ for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++) { /* clear the locate flag */ pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_LOCATE; if (pEASData->streams[streamNum].pParserModule) { /* establish pointer to parser module */ pParserModule = pEASData->streams[streamNum].pParserModule; /* handle pause */ if (pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_PAUSE) { if (pParserModule->pfPause) result = pParserModule->pfPause(pEASData, pEASData->streams[streamNum].handle); pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_PAUSE; } /* get current state */ if ((result = (*pParserModule->pfState)(pEASData, pEASData->streams[streamNum].handle, &parserState)) != EAS_SUCCESS) return result; /* handle resume */ if (parserState == EAS_STATE_PAUSED) { if (pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_RESUME) { if (pParserModule->pfResume) result = pParserModule->pfResume(pEASData, pEASData->streams[streamNum].handle); pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_RESUME; } } /* if necessary, parse stream */ if ((pEASData->streams[streamNum].streamFlags & STREAM_FLAGS_PARSED) == 0) if ((result = EAS_ParseEvents(pEASData, &pEASData->streams[streamNum], pEASData->streams[streamNum].time + pEASData->streams[streamNum].frameLength, eParserModePlay)) != EAS_SUCCESS) return result; /* check for an early abort */ if ((pEASData->streams[streamNum].streamFlags) == 0) { #ifdef _METRICS_ENABLED /* stop performance counter */ if (pEASData->pMetricsData) (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME); #endif return EAS_SUCCESS; } /* check for repeat */ if (pEASData->streams[streamNum].repeatCount) { /* check for stopped state */ if ((result = (*pParserModule->pfState)(pEASData, pEASData->streams[streamNum].handle, &parserState)) != EAS_SUCCESS) return result; if (parserState == EAS_STATE_STOPPED) { /* decrement repeat count, unless it is negative */ if (pEASData->streams[streamNum].repeatCount > 0) pEASData->streams[streamNum].repeatCount--; /* reset the parser */ if ((result = (*pParserModule->pfReset)(pEASData, pEASData->streams[streamNum].handle)) != EAS_SUCCESS) return result; pEASData->streams[streamNum].time = 0; } } } } #ifdef _METRICS_ENABLED /* stop performance counter */ if (pEASData->pMetricsData) (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_PARSE_TIME); #endif #ifdef _METRICS_ENABLED /* start the render timer */ if (pEASData->pMetricsData) (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_RENDER_TIME); #endif /* render audio */ if ((result = VMRender(pEASData->pVoiceMgr, BUFFER_SIZE_IN_MONO_SAMPLES, pEASData->pMixBuffer, &voicesRendered)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "pfRender function returned error %ld\n", result); */ } return result; } #ifdef _METRICS_ENABLED /* stop the render timer */ if (pEASData->pMetricsData) { (*pEASData->pMetricsModule->pfIncrementCounter)(pEASData->pMetricsData, EAS_PM_FRAME_COUNT, 1); (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_RENDER_TIME); (*pEASData->pMetricsModule->pfIncrementCounter)(pEASData->pMetricsData, EAS_PM_TOTAL_VOICE_COUNT, (EAS_U32) voicesRendered); (void)(*pEASData->pMetricsModule->pfRecordMaxValue)(pEASData->pMetricsData, EAS_PM_MAX_VOICES, (EAS_U32) voicesRendered); } #endif //2 Do we really need frameParsed? /* need to parse another frame of events before we render again */ for (streamNum = 0; streamNum < MAX_NUMBER_STREAMS; streamNum++) if (pEASData->streams[streamNum].pParserModule != NULL) pEASData->streams[streamNum].streamFlags &= ~STREAM_FLAGS_PARSED; #ifdef _METRICS_ENABLED /* start performance counter */ if (pEASData->pMetricsData) (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_STREAM_TIME); #endif /* render PCM audio */ if ((result = EAS_PERender(pEASData, numRequested)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_PERender returned error %ld\n", result); */ } return result; } #ifdef _METRICS_ENABLED /* stop the stream timer */ if (pEASData->pMetricsData) (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_STREAM_TIME); #endif #ifdef _METRICS_ENABLED /* start the post timer */ if (pEASData->pMetricsData) (*pEASData->pMetricsModule->pfStartTimer)(pEASData->pMetricsData, EAS_PM_POST_TIME); #endif /* for split architecture, send DSP vectors. Do post only if return is TRUE */ #ifdef _SPLIT_ARCHITECTURE if (VMEndFrame(pEASData)) { /* now do post-processing */ EAS_MixEnginePost(pEASData, numRequested); *pNumGenerated = numRequested; } #else /* now do post-processing */ EAS_MixEnginePost(pEASData, numRequested); *pNumGenerated = numRequested; #endif #ifdef _METRICS_ENABLED /* stop the post timer */ if (pEASData->pMetricsData) (void)(*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_POST_TIME); #endif /* advance render time */ pEASData->renderTime += AUDIO_FRAME_LENGTH; #if 0 /* dump workload for debug */ if (pEASData->pVoiceMgr->workload) { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Workload = %d\n", pEASData->pVoiceMgr->workload); */ } #endif #ifdef _METRICS_ENABLED /* stop performance counter */ if (pEASData->pMetricsData) { PERF_TIMER temp; temp = (*pEASData->pMetricsModule->pfStopTimer)(pEASData->pMetricsData, EAS_PM_TOTAL_TIME); /* if max render time, record the number of voices and time */ if ((*pEASData->pMetricsModule->pfRecordMaxValue) (pEASData->pMetricsData, EAS_PM_MAX_CYCLES, (EAS_U32) temp)) { (*pEASData->pMetricsModule->pfRecordValue)(pEASData->pMetricsData, EAS_PM_MAX_CYCLES_VOICES, (EAS_U32) voicesRendered); (*pEASData->pMetricsModule->pfRecordValue)(pEASData->pMetricsData, EAS_PM_MAX_CYCLES_TIME, (EAS_I32) (pEASData->renderTime >> 8)); } } #endif #ifdef JET_INTERFACE /* let JET to do its thing */ if (pEASData->jetHandle != NULL) { result = JET_Process(pEASData); if (result != EAS_SUCCESS) return result; } #endif return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_SetRepeat() *---------------------------------------------------------------------------- * Purpose: * Set the selected stream to repeat. * * Inputs: * pEASData - handle to data for this instance * handle - handle to stream * repeatCount - repeat count * * Outputs: * * Side Effects: * * Notes: * 0 = no repeat * 1 = repeat once, i.e. play through twice * -1 = repeat forever *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_PUBLIC EAS_RESULT EAS_SetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 repeatCount) { pStream->repeatCount = repeatCount; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_GetRepeat() *---------------------------------------------------------------------------- * Purpose: * Gets the current repeat count for the selected stream. * * Inputs: * pEASData - handle to data for this instance * handle - handle to stream * pRrepeatCount - pointer to variable to hold repeat count * * Outputs: * * Side Effects: * * Notes: * 0 = no repeat * 1 = repeat once, i.e. play through twice * -1 = repeat forever *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_PUBLIC EAS_RESULT EAS_GetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pRepeatCount) { *pRepeatCount = pStream->repeatCount; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_SetPlaybackRate() *---------------------------------------------------------------------------- * Purpose: * Sets the playback rate. * * Inputs: * pEASData - handle to data for this instance * handle - handle to stream * rate - rate (28-bit fractional amount) * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_PUBLIC EAS_RESULT EAS_SetPlaybackRate (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U32 rate) { /* check range */ if ((rate < (1 << 27)) || (rate > (1 << 29))) return EAS_ERROR_INVALID_PARAMETER; /* calculate new frame length * * NOTE: The maximum frame length we can accomodate based on a * maximum rate of 2.0 (2^28) is 2047 (2^13-1). To accomodate a * longer frame length or a higher maximum rate, the fixed point * divide below will need to be adjusted */ pStream->frameLength = (AUDIO_FRAME_LENGTH * (rate >> 8)) >> 20; /* notify stream of new playback rate */ EAS_SetStreamParameter(pEASData, pStream, PARSER_DATA_PLAYBACK_RATE, (EAS_I32) rate); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_SetTransposition) *---------------------------------------------------------------------------- * Purpose: * Sets the key tranposition for the synthesizer. Transposes all * melodic instruments by the specified amount. Range is limited * to +/-12 semitones. * * Inputs: * pEASData - handle to data for this instance * handle - handle to stream * transposition - +/-12 semitones * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetTransposition (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 transposition) { /* check range */ if ((transposition < -12) || (transposition > 12)) return EAS_ERROR_INVALID_PARAMETER; if (!EAS_StreamReady(pEASData, pStream)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_TRANSPOSITION, transposition); } /*---------------------------------------------------------------------------- * EAS_ParseEvents() *---------------------------------------------------------------------------- * Purpose: * Parse events in the current streams until the desired time is reached. * * Inputs: * pEASData - buffer for internal EAS data * endTime - stop parsing if this time is reached * parseMode - play, locate, or metadata * * Outputs: * EAS_SUCCESS if PCM data was successfully rendered * *---------------------------------------------------------------------------- */ static EAS_RESULT EAS_ParseEvents (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_U32 endTime, EAS_INT parseMode) { S_FILE_PARSER_INTERFACE *pParserModule; EAS_RESULT result; EAS_I32 parserState; EAS_BOOL done; EAS_INT yieldCount = YIELD_EVENT_COUNT; EAS_U32 time = 0; /* does this parser have a time function? */ pParserModule = pStream->pParserModule; if (pParserModule->pfTime == NULL) { /* check state */ if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &parserState)) != EAS_SUCCESS) return result; /* if play state, advance time */ if ((parserState >= EAS_STATE_READY) && (parserState <= EAS_STATE_PAUSING)) pStream->time += pStream->frameLength; done = EAS_TRUE; } /* assume we're not done, in case we abort out */ else { pStream->streamFlags &= ~STREAM_FLAGS_PARSED; done = EAS_FALSE; } while (!done) { /* check for stopped state */ if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &parserState)) != EAS_SUCCESS) return result; if (parserState > EAS_STATE_PLAY) { /* save current time if we're not in play mode */ if (parseMode != eParserModePlay) pStream->time = time << 8; done = EAS_TRUE; break; } /* get the next event time */ if (pParserModule->pfTime) { if ((result = (*pParserModule->pfTime)(pEASData, pStream->handle, &time)) != EAS_SUCCESS) return result; /* if next event is within this frame, parse it */ if (time < (endTime >> 8)) { /* parse the next event */ if (pParserModule->pfEvent) if ((result = (*pParserModule->pfEvent)(pEASData, pStream->handle, parseMode)) != EAS_SUCCESS) return result; } /* no more events in this frame, advance time */ else { pStream->time = endTime; done = EAS_TRUE; } } /* check for max workload exceeded */ if (VMCheckWorkload(pEASData->pVoiceMgr)) { /* stop even though we may not have parsed * all the events in this frame. The parser will try to * catch up on the next frame. */ break; } /* give host a chance for an early abort */ if (--yieldCount == 0) { if (EAS_HWYield(pEASData->hwInstData)) break; yieldCount = YIELD_EVENT_COUNT; } } /* if no early abort, parsing is complete for this frame */ if (done) pStream->streamFlags |= STREAM_FLAGS_PARSED; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_ParseMetaData() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * pEASData - pointer to overall EAS data structure * handle - file or stream handle * playLength - pointer to variable to store the play length (in msecs) * * Outputs: * * * Side Effects: * - resets the parser to the start of the file *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_ParseMetaData (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *playLength) { S_FILE_PARSER_INTERFACE *pParserModule; EAS_RESULT result; EAS_STATE state; pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; if (pParserModule == NULL) return EAS_ERROR_FEATURE_NOT_AVAILABLE; /* check parser state */ if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &state)) != EAS_SUCCESS) return result; if (state >= EAS_STATE_OPEN) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; /* if parser has metadata function, use that */ if (pParserModule->pfGetMetaData != NULL) return pParserModule->pfGetMetaData(pEASData, pStream->handle, playLength); /* reset the parser to the beginning */ if ((result = (*pParserModule->pfReset)(pEASData, pStream->handle)) != EAS_SUCCESS) return result; /* parse the file to end */ pStream->time = 0; VMInitWorkload(pEASData->pVoiceMgr); if ((result = EAS_ParseEvents(pEASData, pStream, 0x7fffffff, eParserModeMetaData)) != EAS_SUCCESS) return result; /* get the parser time */ if ((result = EAS_GetLocation(pEASData, pStream, playLength)) != EAS_SUCCESS) return result; /* reset the parser to the beginning */ pStream->time = 0; return (*pParserModule->pfReset)(pEASData, pStream->handle); } /*---------------------------------------------------------------------------- * EAS_RegisterMetaDataCallback() *---------------------------------------------------------------------------- * Purpose: * Registers a metadata callback function for parsed metadata. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - file or stream handle * cbFunc - pointer to host callback function * metaDataBuffer - pointer to metadata buffer * metaDataBufSize - maximum size of the metadata buffer * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_RegisterMetaDataCallback ( EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_METADATA_CBFUNC cbFunc, char *metaDataBuffer, EAS_I32 metaDataBufSize, EAS_VOID_PTR pUserData) { S_METADATA_CB metadata; if (!EAS_StreamReady(pEASData, pStream)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; /* register callback function */ metadata.callback = cbFunc; metadata.buffer = metaDataBuffer; metadata.bufferSize = metaDataBufSize; metadata.pUserData = pUserData; return EAS_SetStreamParameter(pEASData, pStream, PARSER_DATA_METADATA_CB, (EAS_I32) &metadata); } /*---------------------------------------------------------------------------- * EAS_GetNoteCount () *---------------------------------------------------------------------------- * Returns the total number of notes played in this stream *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetNoteCount (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pNoteCount) { if (!EAS_StreamReady(pEASData, pStream)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_NOTE_COUNT, pNoteCount); } /*---------------------------------------------------------------------------- * EAS_CloseFile() *---------------------------------------------------------------------------- * Purpose: * Closes an audio file or stream. Playback should have either paused or * completed (EAS_State returns EAS_PAUSED or EAS_STOPPED). * * Inputs: * pEASData - pointer to overall EAS data structure * handle - file or stream handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_CloseFile (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) { S_FILE_PARSER_INTERFACE *pParserModule; EAS_RESULT result; /* call the close function */ pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; if (pParserModule == NULL) return EAS_ERROR_FEATURE_NOT_AVAILABLE; result = (*pParserModule->pfClose)(pEASData, pStream->handle); /* clear the handle and parser interface pointer */ pStream->handle = NULL; pStream->pParserModule = NULL; return result; } /*---------------------------------------------------------------------------- * EAS_OpenMIDIStream() *---------------------------------------------------------------------------- * Purpose: * Opens a raw MIDI stream allowing the host to route MIDI cable data directly to the synthesizer * * Inputs: * pEASData - pointer to overall EAS data structure * pHandle - pointer to variable to hold file or stream handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_OpenMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE *ppStream, EAS_HANDLE streamHandle) { EAS_RESULT result; S_INTERACTIVE_MIDI *pMIDIStream; EAS_INT streamNum; /* initialize some pointers */ *ppStream = NULL; /* allocate a stream */ if ((streamNum = EAS_AllocateStream(pEASData)) < 0) return EAS_ERROR_MAX_STREAMS_OPEN; /* check Configuration Module for S_EAS_DATA allocation */ if (pEASData->staticMemoryModel) pMIDIStream = EAS_CMEnumData(EAS_CM_MIDI_STREAM_DATA); else pMIDIStream = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_INTERACTIVE_MIDI)); /* allocate dynamic memory */ if (!pMIDIStream) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate MIDI stream data\n"); */ } return EAS_ERROR_MALLOC_FAILED; } /* zero the memory to insure complete initialization */ EAS_HWMemSet(pMIDIStream, 0, sizeof(S_INTERACTIVE_MIDI)); EAS_InitStream(&pEASData->streams[streamNum], NULL, pMIDIStream); /* instantiate a new synthesizer */ if (streamHandle == NULL) { result = VMInitMIDI(pEASData, &pMIDIStream->pSynth); } /* use an existing synthesizer */ else { EAS_I32 value; result = EAS_GetStreamParameter(pEASData, streamHandle, PARSER_DATA_SYNTH_HANDLE, &value); pMIDIStream->pSynth = (S_SYNTH*) value; VMIncRefCount(pMIDIStream->pSynth); } if (result != EAS_SUCCESS) { EAS_CloseMIDIStream(pEASData, &pEASData->streams[streamNum]); return result; } /* initialize the MIDI stream data */ EAS_InitMIDIStream(&pMIDIStream->stream); *ppStream = (EAS_HANDLE) &pEASData->streams[streamNum]; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_WriteMIDIStream() *---------------------------------------------------------------------------- * Purpose: * Send data to the MIDI stream device * * Inputs: * pEASData - pointer to overall EAS data structure * handle - stream handle * pBuffer - pointer to buffer * count - number of bytes to write * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_WriteMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U8 *pBuffer, EAS_I32 count) { S_INTERACTIVE_MIDI *pMIDIStream; EAS_RESULT result; pMIDIStream = (S_INTERACTIVE_MIDI*) pStream->handle; if (count <= 0) return EAS_ERROR_PARAMETER_RANGE; /* send the entire buffer */ while (count--) { if ((result = EAS_ParseMIDIStream(pEASData, pMIDIStream->pSynth, &pMIDIStream->stream, *pBuffer++, eParserModePlay)) != EAS_SUCCESS) return result; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_CloseMIDIStream() *---------------------------------------------------------------------------- * Purpose: * Closes a raw MIDI stream * * Inputs: * pEASData - pointer to overall EAS data structure * handle - stream handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_CloseMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) { S_INTERACTIVE_MIDI *pMIDIStream; pMIDIStream = (S_INTERACTIVE_MIDI*) pStream->handle; /* close synth */ if (pMIDIStream->pSynth != NULL) { VMMIDIShutdown(pEASData, pMIDIStream->pSynth); pMIDIStream->pSynth = NULL; } /* release allocated memory */ if (!pEASData->staticMemoryModel) EAS_HWFree(((S_EAS_DATA*) pEASData)->hwInstData, pMIDIStream); pStream->handle = NULL; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_State() *---------------------------------------------------------------------------- * Purpose: * Returns the state of an audio file or stream. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - file or stream handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_State (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_STATE *pState) { S_FILE_PARSER_INTERFACE *pParserModule; EAS_RESULT result; /* call the parser to return state */ pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; if (pParserModule == NULL) return EAS_ERROR_FEATURE_NOT_AVAILABLE; if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, pState)) != EAS_SUCCESS) return result; /* if repeat count is set for this parser, mask the stopped state from the application */ if (pStream->repeatCount && (*pState == EAS_STATE_STOPPED)) *pState = EAS_STATE_PLAY; /* if we're not paused or pausing, we don't need to hide state from host */ if (*pState != EAS_STATE_PAUSED && *pState != EAS_STATE_PAUSING) return EAS_SUCCESS; /* if stream is about to be paused, report it as paused */ if (pStream->streamFlags & STREAM_FLAGS_PAUSE) { if (pStream->streamFlags & STREAM_FLAGS_LOCATE) *pState = EAS_STATE_PAUSED; else *pState = EAS_STATE_PAUSING; } /* if stream is about to resume, report it as playing */ if (pStream->streamFlags & STREAM_FLAGS_RESUME) *pState = EAS_STATE_PLAY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_SetPolyphony() *---------------------------------------------------------------------------- * Purpose: * Set the polyphony of the stream. A value of 0 allows the stream * to use all voices (set by EAS_SetSynthPolyphony). * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - handle returned by EAS_OpenFile * polyphonyCount - the desired polyphony count * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 polyphonyCount) { if (!EAS_StreamReady(pEASData, pStream)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_POLYPHONY, polyphonyCount); } /*---------------------------------------------------------------------------- * EAS_GetPolyphony() *---------------------------------------------------------------------------- * Purpose: * Returns the current polyphony setting of the stream * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - handle returned by EAS_OpenFile * pPolyphonyCount - pointer to variable to receive polyphony count * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pPolyphonyCount) { if (!EAS_StreamReady(pEASData, pStream)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_POLYPHONY, pPolyphonyCount); } /*---------------------------------------------------------------------------- * EAS_SetSynthPolyphony() *---------------------------------------------------------------------------- * Purpose: * Set the polyphony of the synth . Value must be >= 1 and <= the * maximum number of voices. This function will pin the polyphony * at those limits * * Inputs: * pEASData - pointer to overall EAS data structure * synthNum - synthesizer number (0 = onboard, 1 = DSP) * polyphonyCount - the desired polyphony count * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 polyphonyCount) { return VMSetSynthPolyphony(pEASData->pVoiceMgr, synthNum, polyphonyCount); } /*---------------------------------------------------------------------------- * EAS_GetSynthPolyphony() *---------------------------------------------------------------------------- * Purpose: * Returns the current polyphony setting of the synth * * Inputs: * pEASData - pointer to overall EAS data structure * synthNum - synthesizer number (0 = onboard, 1 = DSP) * pPolyphonyCount - pointer to variable to receive polyphony count * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 *pPolyphonyCount) { return VMGetSynthPolyphony(pEASData->pVoiceMgr, synthNum, pPolyphonyCount); } /*---------------------------------------------------------------------------- * EAS_SetPriority() *---------------------------------------------------------------------------- * Purpose: * Set the priority of the stream. Determines which stream's voices * are stolen when there are insufficient voices for all notes. * Value must be in the range of 1-15, lower values are higher * priority. * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - handle returned by EAS_OpenFile * polyphonyCount - the desired polyphony count * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 priority) { if (!EAS_StreamReady(pEASData, pStream)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_PRIORITY, priority); } /*---------------------------------------------------------------------------- * EAS_GetPriority() *---------------------------------------------------------------------------- * Purpose: * Returns the current priority setting of the stream * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - handle returned by EAS_OpenFile * pPriority - pointer to variable to receive priority * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pPriority) { if (!EAS_StreamReady(pEASData, pStream)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; return EAS_IntGetStrmParam(pEASData, pStream, PARSER_DATA_PRIORITY, pPriority); } /*---------------------------------------------------------------------------- * EAS_SetVolume() *---------------------------------------------------------------------------- * Purpose: * Set the master gain for the mix engine in 1dB increments * * Inputs: * pEASData - pointer to overall EAS data structure * volume - the desired master gain (100 is max) * handle - file or stream handle * * Outputs: * * * Side Effects: * overrides any previously set master volume from sysex * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 volume) { EAS_I16 gain; /* check range */ if ((volume < 0) || (volume > EAS_MAX_VOLUME)) return EAS_ERROR_PARAMETER_RANGE; /* stream volume */ if (pStream != NULL) { EAS_I32 gainOffset; EAS_RESULT result; if (!EAS_StreamReady(pEASData, pStream)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; /* get gain offset */ pStream->volume = (EAS_U8) volume; result = EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_GAIN_OFFSET, &gainOffset); if (result == EAS_SUCCESS) volume += gainOffset; /* set stream volume */ gain = EAS_VolumeToGain(volume - STREAM_VOLUME_HEADROOM); /* convert to linear scalar */ return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_VOLUME, gain); } /* master volume */ pEASData->masterVolume = (EAS_U8) volume; #if (NUM_OUTPUT_CHANNELS == 1) /* leave 3dB headroom for mono output */ volume -= 3; #endif gain = EAS_VolumeToGain(volume - STREAM_VOLUME_HEADROOM); pEASData->masterGain = gain; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_GetVolume() *---------------------------------------------------------------------------- * Purpose: * Returns the master volume for the synthesizer. The default volume setting is * 50. The volume range is 0 to 100; * * Inputs: * pEASData - pointer to overall EAS data structure * volume - the desired master volume * handle - file or stream handle * * Outputs: * * * Side Effects: * overrides any previously set master volume from sysex * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_I32 EAS_GetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) { if (pStream == NULL) return pEASData->masterVolume; if (!EAS_StreamReady(pEASData, pStream)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; return pStream->volume; } /*---------------------------------------------------------------------------- * EAS_SetMaxLoad() *---------------------------------------------------------------------------- * Purpose: * Sets the maximum workload the parsers will do in a single call to * EAS_Render. The units are currently arbitrary, but should correlate * well to the actual CPU cycles consumed. The primary effect is to * reduce the occasional peaks in CPU cycles consumed when parsing * dense parts of a MIDI score. * * Inputs: * pEASData - handle to data for this instance * maxLoad - the desired maximum workload * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetMaxLoad (EAS_DATA_HANDLE pEASData, EAS_I32 maxLoad) { VMSetWorkload(pEASData->pVoiceMgr, maxLoad); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_SetMaxPCMStreams() *---------------------------------------------------------------------------- * Sets the maximum number of PCM streams allowed in parsers that * use PCM streaming. * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - handle returned by EAS_OpenFile * maxNumStreams - maximum number of PCM streams *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetMaxPCMStreams (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 maxNumStreams) { if (!EAS_StreamReady(pEASData, pStream)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_MAX_PCM_STREAMS, maxNumStreams); } /*---------------------------------------------------------------------------- * EAS_Locate() *---------------------------------------------------------------------------- * Purpose: * Locate into the file associated with the handle. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - file handle * milliseconds - playback offset from start of file in milliseconds * * Outputs: * * * Side Effects: * the actual offset will be quantized to the closest update period, typically * a resolution of 5.9ms. Notes that are started prior to this time will not * sound. Any notes currently playing will be shut off. * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_Locate (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 milliseconds, EAS_BOOL offset) { S_FILE_PARSER_INTERFACE *pParserModule; EAS_RESULT result; EAS_U32 requestedTime; EAS_STATE state; /* get pointer to parser function table */ pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; if (pParserModule == NULL) return EAS_ERROR_FEATURE_NOT_AVAILABLE; if ((result = (*pParserModule->pfState)(pEASData, pStream->handle, &state)) != EAS_SUCCESS) return result; if (state >= EAS_STATE_OPEN) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; /* handle offset and limit to start of file */ /*lint -e{704} use shift for performance*/ if (offset) milliseconds += (EAS_I32) pStream->time >> 8; if (milliseconds < 0) milliseconds = 0; /* check to see if the request is different from the current time */ requestedTime = (EAS_U32) milliseconds; if (requestedTime == (pStream->time >> 8)) return EAS_SUCCESS; /* set the locate flag */ pStream->streamFlags |= STREAM_FLAGS_LOCATE; /* use the parser locate function, if available */ if (pParserModule->pfLocate != NULL) { EAS_BOOL parserLocate = EAS_FALSE; result = pParserModule->pfLocate(pEASData, pStream->handle, (EAS_I32) requestedTime, &parserLocate); if (!parserLocate) { if (result == EAS_SUCCESS) pStream->time = requestedTime << 8; return result; } } /* if we were paused and not going to resume, set pause request flag */ if (((state == EAS_STATE_PAUSING) || (state == EAS_STATE_PAUSED)) && ((pStream->streamFlags & STREAM_FLAGS_RESUME) == 0)) pStream->streamFlags |= STREAM_FLAGS_PAUSE; /* reset the synth and parser */ if ((result = (*pParserModule->pfReset)(pEASData, pStream->handle)) != EAS_SUCCESS) return result; pStream->time = 0; /* locating forward, clear parsed flag and parse data until we get to the requested location */ if ((result = EAS_ParseEvents(pEASData, pStream, requestedTime << 8, eParserModeLocate)) != EAS_SUCCESS) return result; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_GetLocation() *---------------------------------------------------------------------------- * Purpose: * Returns the current playback offset * * Inputs: * pEASData - pointer to overall EAS data structure * handle - file handle * * Outputs: * The offset in milliseconds from the start of the current sequence, quantized * to the nearest update period. Actual resolution is typically 5.9 ms. * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_PUBLIC EAS_RESULT EAS_GetLocation (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pTime) { if (!EAS_StreamReady(pEASData, pStream)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; *pTime = pStream->time >> 8; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_GetRenderTime() *---------------------------------------------------------------------------- * Purpose: * Returns the current playback offset * * Inputs: * pEASData - pointer to overall EAS data structure * * Outputs: * Gets the render time clock in msecs. * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetRenderTime (EAS_DATA_HANDLE pEASData, EAS_I32 *pTime) { *pTime = pEASData->renderTime >> 8; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_Pause() *---------------------------------------------------------------------------- * Purpose: * Pauses the playback of the data associated with this handle. The audio * is gracefully ramped down to prevent clicks and pops. It may take several * buffers of audio before the audio is muted. * * Inputs: * psEASData - pointer to overall EAS data structure * handle - file or stream handle * * Outputs: * * * Side Effects: * * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_Pause (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) { S_FILE_PARSER_INTERFACE *pParserModule; EAS_STATE state; EAS_RESULT result; pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; if (pParserModule == NULL) return EAS_ERROR_FEATURE_NOT_AVAILABLE; /* check for valid state */ result = pParserModule->pfState(pEASData, pStream->handle, &state); if (result == EAS_SUCCESS) { if ((state != EAS_STATE_PLAY) && (state != EAS_STATE_READY) && ((pStream->streamFlags & STREAM_FLAGS_RESUME) == 0)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; /* make sure parser implements pause */ if (pParserModule->pfPause == NULL) result = EAS_ERROR_NOT_IMPLEMENTED; /* clear resume flag */ pStream->streamFlags &= ~STREAM_FLAGS_RESUME; /* set pause flag */ pStream->streamFlags |= STREAM_FLAGS_PAUSE; #if 0 /* pause the stream */ if (pParserModule->pfPause) result = pParserModule->pfPause(pEASData, pStream->handle); else result = EAS_ERROR_NOT_IMPLEMENTED; #endif } return result; } /*---------------------------------------------------------------------------- * EAS_Resume() *---------------------------------------------------------------------------- * Purpose: * Resumes the playback of the data associated with this handle. The audio * is gracefully ramped up to prevent clicks and pops. * * Inputs: * psEASData - pointer to overall EAS data structure * handle - file or stream handle * * Outputs: * * * Side Effects: * * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_Resume (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream) { S_FILE_PARSER_INTERFACE *pParserModule; EAS_STATE state; EAS_RESULT result; pParserModule = (S_FILE_PARSER_INTERFACE*) pStream->pParserModule; if (pParserModule == NULL) return EAS_ERROR_FEATURE_NOT_AVAILABLE; /* check for valid state */ result = pParserModule->pfState(pEASData, pStream->handle, &state); if (result == EAS_SUCCESS) { if ((state != EAS_STATE_PAUSED) && (state != EAS_STATE_PAUSING) && ((pStream->streamFlags & STREAM_FLAGS_PAUSE) == 0)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; /* make sure parser implements this function */ if (pParserModule->pfResume == NULL) result = EAS_ERROR_NOT_IMPLEMENTED; /* clear pause flag */ pStream->streamFlags &= ~STREAM_FLAGS_PAUSE; /* set resume flag */ pStream->streamFlags |= STREAM_FLAGS_RESUME; #if 0 /* resume the stream */ if (pParserModule->pfResume) result = pParserModule->pfResume(pEASData, pStream->handle); else result = EAS_ERROR_NOT_IMPLEMENTED; #endif } return result; } /*---------------------------------------------------------------------------- * EAS_GetParameter() *---------------------------------------------------------------------------- * Purpose: * Set the parameter of a module. See E_MODULES for a list of modules * and the header files of the modules for a list of parameters. * * Inputs: * psEASData - pointer to overall EAS data structure * handle - file or stream handle * module - enumerated module number * param - enumerated parameter number * pValue - pointer to variable to receive parameter value * * Outputs: * * * Side Effects: * * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 *pValue) { if (module >= NUM_EFFECTS_MODULES) return EAS_ERROR_INVALID_MODULE; if (pEASData->effectsModules[module].effectData == NULL) return EAS_ERROR_INVALID_MODULE; return (*pEASData->effectsModules[module].effect->pFGetParam) (pEASData->effectsModules[module].effectData, param, pValue); } /*---------------------------------------------------------------------------- * EAS_SetParameter() *---------------------------------------------------------------------------- * Purpose: * Set the parameter of a module. See E_MODULES for a list of modules * and the header files of the modules for a list of parameters. * * Inputs: * psEASData - pointer to overall EAS data structure * handle - file or stream handle * module - enumerated module number * param - enumerated parameter number * value - new parameter value * * Outputs: * * * Side Effects: * * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 value) { if (module >= NUM_EFFECTS_MODULES) return EAS_ERROR_INVALID_MODULE; if (pEASData->effectsModules[module].effectData == NULL) return EAS_ERROR_INVALID_MODULE; return (*pEASData->effectsModules[module].effect->pFSetParam) (pEASData->effectsModules[module].effectData, param, value); } #ifdef _METRICS_ENABLED /*---------------------------------------------------------------------------- * EAS_MetricsReport() *---------------------------------------------------------------------------- * Purpose: * Displays the current metrics through the metrics interface. * * Inputs: * p - instance data handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_MetricsReport (EAS_DATA_HANDLE pEASData) { if (!pEASData->pMetricsModule) return EAS_ERROR_INVALID_MODULE; return (*pEASData->pMetricsModule->pfReport)(pEASData->pMetricsData); } /*---------------------------------------------------------------------------- * EAS_MetricsReset() *---------------------------------------------------------------------------- * Purpose: * Resets the metrics. * * Inputs: * p - instance data handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_MetricsReset (EAS_DATA_HANDLE pEASData) { if (!pEASData->pMetricsModule) return EAS_ERROR_INVALID_MODULE; return (*pEASData->pMetricsModule->pfReset)(pEASData->pMetricsData); } #endif /*---------------------------------------------------------------------------- * EAS_SetSoundLibrary() *---------------------------------------------------------------------------- * Purpose: * Sets the location of the sound library. * * Inputs: * pEASData - instance data handle * pSoundLib - pointer to sound library * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetSoundLibrary (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_SNDLIB_HANDLE pSndLib) { if (pStream) { if (!EAS_StreamReady(pEASData, pStream)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_EAS_LIBRARY, (EAS_I32) pSndLib); } return VMSetGlobalEASLib(pEASData->pVoiceMgr, pSndLib); } /*---------------------------------------------------------------------------- * EAS_SetHeaderSearchFlag() *---------------------------------------------------------------------------- * By default, when EAS_OpenFile is called, the parsers check the * first few bytes of the file looking for a specific header. Some * mobile devices may add a header to the start of a file, which * will prevent the parser from recognizing the file. If the * searchFlag is set to EAS_TRUE, the parser will search the entire * file looking for the header. This may enable EAS to recognize * some files that it would ordinarily reject. The negative is that * it make take slightly longer to process the EAS_OpenFile request. * * Inputs: * pEASData - instance data handle * searchFlag - search flag (EAS_TRUE or EAS_FALSE) *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetHeaderSearchFlag (EAS_DATA_HANDLE pEASData, EAS_BOOL searchFlag) { pEASData->searchHeaderFlag = (EAS_BOOL8) searchFlag; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_SetPlayMode() *---------------------------------------------------------------------------- * Some file formats support special play modes, such as iMode partial * play mode. This call can be used to change the play mode. The * default play mode (usually straight playback) is always zero. * * Inputs: * pEASData - instance data handle * handle - file or stream handle * playMode - play mode (see file parser for specifics) *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetPlayMode (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 playMode) { return EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_PLAY_MODE, playMode); } #ifdef DLS_SYNTHESIZER /*---------------------------------------------------------------------------- * EAS_LoadDLSCollection() *---------------------------------------------------------------------------- * Purpose: * Sets the location of the sound library. * * Inputs: * pEASData - instance data handle * pSoundLib - pointer to sound library * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_LoadDLSCollection (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_FILE_LOCATOR locator) { EAS_FILE_HANDLE fileHandle; EAS_RESULT result; EAS_DLSLIB_HANDLE pDLS; if (pStream != NULL) { if (!EAS_StreamReady(pEASData, pStream)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; } /* open the file */ if ((result = EAS_HWOpenFile(pEASData->hwInstData, locator, &fileHandle, EAS_FILE_READ)) != EAS_SUCCESS) return result; /* parse the file */ result = DLSParser(pEASData->hwInstData, fileHandle, 0, &pDLS); EAS_HWCloseFile(pEASData->hwInstData, fileHandle); if (result == EAS_SUCCESS) { /* if a stream pStream is specified, point it to the DLS collection */ if (pStream) result = EAS_IntSetStrmParam(pEASData, pStream, PARSER_DATA_DLS_COLLECTION, (EAS_I32) pDLS); /* global DLS load */ else result = VMSetGlobalDLSLib(pEASData, pDLS); } return result; } #endif #ifdef EXTERNAL_AUDIO /*---------------------------------------------------------------------------- * EAS_RegExtAudioCallback() *---------------------------------------------------------------------------- * Purpose: * Registers callback functions for audio events. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - file or stream handle * cbProgChgFunc - pointer to host callback function for program change * cbEventFunc - pointer to host callback functio for note events * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_RegExtAudioCallback (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_VOID_PTR pInstData, EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, EAS_EXT_EVENT_FUNC cbEventFunc) { S_SYNTH *pSynth; if (!EAS_StreamReady(pEASData, pStream)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) return EAS_ERROR_INVALID_PARAMETER; if (pSynth == NULL) return EAS_ERROR_INVALID_PARAMETER; VMRegExtAudioCallback(pSynth, pInstData, cbProgChgFunc, cbEventFunc); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_GetMIDIControllers() *---------------------------------------------------------------------------- * Purpose: * Returns the current state of MIDI controllers on the requested channel. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - file or stream handle * pControl - pointer to structure to receive data * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetMIDIControllers (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl) { S_SYNTH *pSynth; if (!EAS_StreamReady(pEASData, pStream)) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; if (EAS_GetStreamParameter(pEASData, pStream, PARSER_DATA_SYNTH_HANDLE, (EAS_I32*) &pSynth) != EAS_SUCCESS) return EAS_ERROR_INVALID_PARAMETER; if (pSynth == NULL) return EAS_ERROR_INVALID_PARAMETER; VMGetMIDIControllers(pSynth, channel, pControl); return EAS_SUCCESS; } #endif #ifdef _SPLIT_ARCHITECTURE /*---------------------------------------------------------------------------- * EAS_SetFrameBuffer() *---------------------------------------------------------------------------- * Purpose: * Sets the frame buffer pointer passed to the IPC communications functions * * Inputs: * pEASData - instance data handle * locator - file locator * * Outputs: * * * Side Effects: * May overlay instruments in the GM sound set * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetFrameBuffer (EAS_DATA_HANDLE pEASData, EAS_FRAME_BUFFER_HANDLE pFrameBuffer) { if (pEASData->pVoiceMgr) pEASData->pVoiceMgr->pFrameBuffer = pFrameBuffer; return EAS_SUCCESS; } #endif /*---------------------------------------------------------------------------- * EAS_SearchFile *---------------------------------------------------------------------------- * Search file for specific sequence starting at current file * position. Returns offset to start of sequence. * * Inputs: * pEASData - pointer to EAS persistent data object * fileHandle - file handle * searchString - pointer to search sequence * len - length of search sequence * pOffset - pointer to variable to store offset to sequence * * Returns EAS_EOF if end-of-file is reached *---------------------------------------------------------------------------- */ EAS_RESULT EAS_SearchFile (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, const EAS_U8 *searchString, EAS_I32 len, EAS_I32 *pOffset) { EAS_RESULT result; EAS_INT index; EAS_U8 c; *pOffset = -1; index = 0; for (;;) { result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &c); if (result != EAS_SUCCESS) return result; if (c == searchString[index]) { index++; if (index == 4) { result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, pOffset); if (result != EAS_SUCCESS) return result; *pOffset -= len; break; } } else index = 0; } return EAS_SUCCESS; } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_chorusdata.c0000644000000000000000000000013213532747316027245 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.733999895 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_chorusdata.c0000644000175000001440000000215113532747316030035 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_chorusdata.c * * Contents and purpose: * Contains the static data allocation for the Chorus effect * * * Copyright Sonic Network Inc. 2006 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 550 $ * $Date: 2007-02-02 09:37:03 -0800 (Fri, 02 Feb 2007) $ *---------------------------------------------------------------------------- */ #include "eas_chorusdata.h" S_CHORUS_OBJECT eas_ChorusData; drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_otadata.h0000644000000000000000000000013213532747316026532 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.733999895 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_otadata.h0000644000175000001440000000620113532747316027322 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_otadata.h * * Contents and purpose: * OTA File Parser * * This file contains data declarations for the OTA parser. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ #ifndef EAS_OTADATA_H #define EAS_OTADATA_H #include "eas_data.h" /* definition for state flags */ #define OTA_FLAGS_UNICODE 0x01 /* unicode text */ /*---------------------------------------------------------------------------- * * S_OTA_DATA * * This structure contains the state data for the OTA parser *---------------------------------------------------------------------------- */ typedef struct { EAS_I32 fileOffset; /* offset to location in file */ EAS_U8 patternLen; /* length of current pattern */ EAS_U8 dataByte; /* previous char from file */ EAS_U8 bitCount; /* bit count in char */ } S_OTA_LOC; typedef struct { EAS_FILE_HANDLE fileHandle; /* file handle */ S_SYNTH *pSynth; /* synth handle */ EAS_I32 fileOffset; /* offset to start of data */ EAS_I32 time; /* current time in 256ths of a msec */ EAS_U32 tick; /* length of 32nd note in 256th of a msec */ EAS_U32 restTicks; /* ticks to rest after current note */ S_OTA_LOC patterns[4]; /* pattern locations */ S_OTA_LOC current; /* current location */ S_OTA_LOC restore; /* previous location */ S_METADATA_CB metadata; /* metadata callback */ EAS_U8 flags; /* bit flags */ EAS_U8 numPatterns; /* number of patterns left in song */ EAS_U8 currentPattern; /* current pattern for loop */ EAS_U8 note; /* MIDI note number */ EAS_U8 octave; /* octave modifier */ EAS_U8 style; /* from STYLE */ EAS_U8 velocity; /* current volume */ EAS_U8 state; /* current state EAS_STATE_XXXX */ EAS_U8 loopCount; /* loop count for pattern */ } S_OTA_DATA; #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_wavefiledata.c0000644000000000000000000000013213532747316027544 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.733999895 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_wavefiledata.c0000644000175000001440000000211713532747316030336 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_wavefiledata.c * * Contents and purpose: * Static data block for wave file parser. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 547 $ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ *---------------------------------------------------------------------------- */ #include "eas_wavefile.h" S_WAVE_STATE eas_WaveData; drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_math.h0000644000000000000000000000013213532747316026046 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.733999895 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_math.h0000644000175000001440000004033213532747316026641 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_math.h * * Contents and purpose: * Contains common math routines for the various audio engines. * * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 584 $ * $Date: 2007-03-08 09:49:24 -0800 (Thu, 08 Mar 2007) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_MATH_H #define _EAS_MATH_H #include /** coefs for pan, generates sin, cos */ #define COEFF_PAN_G2 -27146 /* -0.82842712474619 = 2 - 4/sqrt(2) */ #define COEFF_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */ /* coefficients for approximating 2^x = gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3 where x is a int.frac number representing number of octaves. Actually, we approximate only the 2^(frac) using the power series and implement the 2^(int) as a shift, so that 2^x == 2^(int.frac) == 2^(int) * 2^(fract) == (gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3) << (int) The gn2toX.. were generated using a best fit for a 3rd order polynomial, instead of taking the coefficients from a truncated Taylor (or Maclaurin?) series. */ #define GN2_TO_X0 32768 /* 1 */ #define GN2_TO_X1 22833 /* 0.696807861328125 */ #define GN2_TO_X2 7344 /* 0.22412109375 */ #define GN2_TO_X3 2588 /* 0.0789794921875 */ /*---------------------------------------------------------------------------- * Fixed Point Math *---------------------------------------------------------------------------- * These macros are used for fixed point multiplies. If the processor * supports fixed point multiplies, replace these macros with inline * assembly code to improve performance. *---------------------------------------------------------------------------- */ /* Fixed point multiply 0.15 x 0.15 = 0.15 returned as 32-bits */ #define FMUL_15x15(a,b) \ /*lint -e(704) */ \ (((int32_t)(a) * (int32_t)(b)) >> 15) /* Fixed point multiply 0.7 x 0.7 = 0.15 returned as 32-bits */ #define FMUL_7x7(a,b) \ /*lint -e(704) */ \ (((int32_t)(a) * (int32_t)(b) ) << 1) /* Fixed point multiply 0.8 x 0.8 = 0.15 returned as 32-bits */ #define FMUL_8x8(a,b) \ /*lint -e(704) */ \ (((int32_t)(a) * (int32_t)(b) ) >> 1) /* Fixed point multiply 0.8 x 1.15 = 0.15 returned as 32-bits */ #define FMUL_8x15(a,b) \ /*lint -e(704) */ \ (((int32_t)((a) << 7) * (int32_t)(b)) >> 15) /* macros for fractional phase accumulator */ /* Note: changed the _U32 to _I32 on 03/14/02. This should not affect the phase calculations, and should allow us to reuse these macros for other audio sample related math. */ #define HARDWARE_BIT_WIDTH 32 #define NUM_PHASE_INT_BITS 1 #define NUM_PHASE_FRAC_BITS 15 #define PHASE_FRAC_MASK (uint32_t) ((0x1L << NUM_PHASE_FRAC_BITS) -1) #define GET_PHASE_INT_PART(x) (uint32_t)((uint32_t)(x) >> NUM_PHASE_FRAC_BITS) #define GET_PHASE_FRAC_PART(x) (uint32_t)((uint32_t)(x) & PHASE_FRAC_MASK) #define DEFAULT_PHASE_FRAC 0 #define DEFAULT_PHASE_INT 0 /* Linear interpolation calculates: output = (1-frac) * sample[n] + (frac) * sample[n+1] where conceptually 0 <= frac < 1 For a fixed point implementation, frac is actually an integer value with an implied binary point one position to the left. The value of one (unity) is given by PHASE_ONE one half and one quarter are useful for 4-point linear interp. */ #define PHASE_ONE (int32_t) (0x1L << NUM_PHASE_FRAC_BITS) /* Multiply the signed audio sample by the unsigned fraction. - a is the signed audio sample - b is the unsigned fraction (cast to signed int as long as coef uses (n-1) or less bits, where n == hardware bit width) */ #define MULT_AUDIO_COEF(audio,coef) /*lint -e704 */ \ (int32_t)( \ ( \ ((int32_t)(audio)) * ((int32_t)(coef)) \ ) \ >> NUM_PHASE_FRAC_BITS \ ) \ /* lint +704 */ /* wet / dry calculation macros */ #define NUM_WET_DRY_FRAC_BITS 7 // 15 #define NUM_WET_DRY_INT_BITS 9 // 1 /* define a 1.0 */ #define WET_DRY_ONE (int32_t) ((0x1L << NUM_WET_DRY_FRAC_BITS)) #define WET_DRY_MINUS_ONE (int32_t) (~WET_DRY_ONE) #define WET_DRY_FULL_SCALE (int32_t) (WET_DRY_ONE - 1) #define MULT_AUDIO_WET_DRY_COEF(audio,coef) /*lint -e(702) */ \ (int32_t)( \ ( \ ((int32_t)(audio)) * ((int32_t)(coef)) \ ) \ >> NUM_WET_DRY_FRAC_BITS \ ) /* Envelope 1 (EG1) calculation macros */ #define NUM_EG1_INT_BITS 1 #define NUM_EG1_FRAC_BITS 15 /* the max positive gain used in the synth for EG1 */ /* SYNTH_FULL_SCALE_EG1_GAIN must match the value in the dls2eas converter, otherwise, the values we read from the .eas file are bogus. */ #define SYNTH_FULL_SCALE_EG1_GAIN (int32_t) ((0x1L << NUM_EG1_FRAC_BITS) -1) /* define a 1.0 */ #define EG1_ONE (int32_t) ((0x1L << NUM_EG1_FRAC_BITS)) #define EG1_MINUS_ONE (int32_t) (~SYNTH_FULL_SCALE_EG1_GAIN) #define EG1_HALF (int32_t) (EG1_ONE/2) #define EG1_MINUS_HALF (int32_t) (EG1_MINUS_ONE/2) /* We implement the EG1 using a linear gain value, which means that the attack segment is handled by incrementing (adding) the linear gain. However, EG1 treats the Decay, Sustain, and Release differently than the Attack portion. For Decay, Sustain, and Release, the gain is linear on dB scale, which is equivalent to exponential damping on a linear scale. Because we use a linear gain for EG1, we implement the Decay and Release as multiplication (instead of incrementing as we did for the attack segment). Therefore, we need the following macro to implement the multiplication (i.e., exponential damping) during the Decay and Release segments of the EG1 */ #define MULT_EG1_EG1(gain,damping) /*lint -e(704) */ \ (int32_t)( \ ( \ ((int32_t)(gain)) * ((int32_t)(damping)) \ ) \ >> NUM_EG1_FRAC_BITS \ ) // Use the following macro specifically for the filter, when multiplying // the b1 coefficient. The 0 <= |b1| < 2, which therefore might overflow // in certain conditions because we store b1 as a 1.15 value. // Instead, we could store b1 as b1p (b1' == b1 "prime") where // b1p == b1/2, thus ensuring no potential overflow for b1p because // 0 <= |b1p| < 1 // However, during the filter calculation, we must account for the fact // that we are using b1p instead of b1, and thereby multiply by // an extra factor of 2. Rather than multiply by an extra factor of 2, // we can instead shift the result right by one less, hence the // modified shift right value of (NUM_EG1_FRAC_BITS -1) #define MULT_EG1_EG1_X2(gain,damping) /*lint -e(702) */ \ (int32_t)( \ ( \ ((int32_t)(gain)) * ((int32_t)(damping)) \ ) \ >> (NUM_EG1_FRAC_BITS -1) \ ) #define SATURATE_EG1(x) /*lint -e{734} saturation operation */ \ ((int32_t)(x) > SYNTH_FULL_SCALE_EG1_GAIN) ? (SYNTH_FULL_SCALE_EG1_GAIN) : \ ((int32_t)(x) < EG1_MINUS_ONE) ? (EG1_MINUS_ONE) : (x); /* use "digital cents" == "dents" instead of cents */ /* we coudl re-use the phase frac macros, but if we do, we must change the phase macros to cast to _I32 instead of _U32, because using a _U32 cast causes problems when shifting the exponent for the 2^x calculation, because right shift a negative values MUST be sign extended, or else the 2^x calculation is wrong */ /* use "digital cents" == "dents" instead of cents */ #define NUM_DENTS_FRAC_BITS 12 #define NUM_DENTS_INT_BITS (HARDWARE_BIT_WIDTH - NUM_DENTS_FRAC_BITS) #define DENTS_FRAC_MASK (int32_t) ((0x1L << NUM_DENTS_FRAC_BITS) -1) #define GET_DENTS_INT_PART(x) /*lint -e(704) */ \ (int32_t)((int32_t)(x) >> NUM_DENTS_FRAC_BITS) #define GET_DENTS_FRAC_PART(x) (int32_t)((int32_t)(x) & DENTS_FRAC_MASK) #define DENTS_ONE (int32_t) (0x1L << NUM_DENTS_FRAC_BITS) /* use CENTS_TO_DENTS to convert a value in cents to dents */ #define CENTS_TO_DENTS (int32_t) (DENTS_ONE * (0x1L << NUM_EG1_FRAC_BITS) / 1200L) \ /* For gain, the LFO generates a value that modulates in terms of dB. However, we use a linear gain value, so we must convert the LFO value in dB to a linear gain. Normally, we would use linear gain = 10^x, where x = LFO value in dB / 20. Instead, we implement 10^x using our 2^x approximation. because 10^x = 2^(log2(10^x)) = 2^(x * log2(10)) so we need to multiply by log2(10) which is just a constant. Ah, but just wait -- our 2^x actually doesn't exactly implement 2^x, but it actually assumes that the input is in cents, and within the 2^x approximation converts its input from cents to octaves by dividing its input by 1200. So, in order to convert the LFO gain value in dB to something that our existing 2^x approximation can use, multiply the LFO gain by log2(10) * 1200 / 20 The divide by 20 helps convert dB to linear gain, and we might as well incorporate that operation into this conversion. Of course, we need to keep some fractional bits, so multiply the constant by NUM_EG1_FRAC_BITS */ /* use LFO_GAIN_TO_CENTS to convert the LFO gain value to cents */ #if 0 #define DOUBLE_LOG2_10 (double) (3.32192809488736) /* log2(10) */ #define DOUBLE_LFO_GAIN_TO_CENTS (double) \ ( \ (DOUBLE_LOG2_10) * \ 1200.0 / \ 20.0 \ ) #define LFO_GAIN_TO_CENTS (int32_t) \ ( \ DOUBLE_LFO_GAIN_TO_CENTS * \ (0x1L << NUM_EG1_FRAC_BITS) \ ) #endif #define LFO_GAIN_TO_CENTS (int32_t) (1671981156L >> (23 - NUM_EG1_FRAC_BITS)) #define MULT_DENTS_COEF(dents,coef) /*lint -e704 */ \ (int32_t)( \ ( \ ((int32_t)(dents)) * ((int32_t)(coef)) \ ) \ >> NUM_DENTS_FRAC_BITS \ ) \ /* lint +e704 */ /* we use 16-bits in the PC per audio sample */ #define BITS_PER_AUDIO_SAMPLE 16 /* we define 1 as 1.0 - 1 LSbit */ #define DISTORTION_ONE (int32_t)((0x1L << (BITS_PER_AUDIO_SAMPLE-1)) -1) #define DISTORTION_MINUS_ONE (int32_t)(~DISTORTION_ONE) /* drive coef is given as int.frac */ #define NUM_DRIVE_COEF_INT_BITS 1 #define NUM_DRIVE_COEF_FRAC_BITS 4 #define MULT_AUDIO_DRIVE(audio,drive) /*lint -e(702) */ \ (int32_t) ( \ ( \ ((int32_t)(audio)) * ((int32_t)(drive)) \ ) \ >> NUM_DRIVE_COEF_FRAC_BITS \ ) #define MULT_AUDIO_AUDIO(audio1,audio2) /*lint -e(702) */ \ (int32_t) ( \ ( \ ((int32_t)(audio1)) * ((int32_t)(audio2)) \ ) \ >> (BITS_PER_AUDIO_SAMPLE-1) \ ) #define SATURATE(x) \ ((((int32_t)(x)) > DISTORTION_ONE) ? (DISTORTION_ONE) : \ (((int32_t)(x)) < DISTORTION_MINUS_ONE) ? (DISTORTION_MINUS_ONE) : ((int32_t)(x))); /*---------------------------------------------------------------------------- * EAS_Calculate2toX() *---------------------------------------------------------------------------- * Purpose: * Calculate 2^x * * Inputs: * nCents - measured in cents * * Outputs: * nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS) * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_I32 EAS_Calculate2toX (EAS_I32 nCents); /*---------------------------------------------------------------------------- * EAS_LogToLinear16() *---------------------------------------------------------------------------- * Purpose: * Transform log value to linear gain multiplier using piece-wise linear * approximation * * Inputs: * nGain - log scale value in 20.10 format. Even though gain is normally * stored in 6.10 (16-bit) format we use 32-bit numbers here to eliminate * the need for saturation checking when combining gain values. * * Outputs: * Returns a 16-bit linear value approximately equal to 2^(nGain/1024) * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_U16 EAS_LogToLinear16 (EAS_I32 nGain); /*---------------------------------------------------------------------------- * EAS_VolumeToGain() *---------------------------------------------------------------------------- * Purpose: * Transform volume control in 1dB increments to gain multiplier * * Inputs: * volume - 100 = 0dB, 99 = -1dB, 0 = -inf * * Outputs: * Returns a 16-bit linear value *---------------------------------------------------------------------------- */ EAS_I16 EAS_VolumeToGain (EAS_INT volume); /*---------------------------------------------------------------------------- * EAS_fsqrt() *---------------------------------------------------------------------------- * Purpose: * Calculates the square root of a 32-bit fixed point value * * Inputs: * n = value of interest * * Outputs: * returns the square root of n * *---------------------------------------------------------------------------- */ EAS_U16 EAS_fsqrt (EAS_U32 n); /*---------------------------------------------------------------------------- * EAS_flog2() *---------------------------------------------------------------------------- * Purpose: * Calculates the log2 of a 32-bit fixed point value * * Inputs: * n = value of interest * * Outputs: * returns the log2 of n * *---------------------------------------------------------------------------- */ EAS_I32 EAS_flog2 (EAS_U32 n); #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_chorusdata.h0000644000000000000000000000013213532747316027252 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.733999895 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_chorusdata.h0000644000175000001440000001137213532747316030047 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_chorusdata.h * * Contents and purpose: * Contains the prototypes for the Chorus effect. * * * Copyright Sonic Network Inc. 2006 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 309 $ * $Date: 2006-09-12 18:52:45 -0700 (Tue, 12 Sep 2006) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_CHORUS_H #define _EAS_CHORUS_H #include "eas_types.h" #include "eas_audioconst.h" //defines for chorus #define EAS_CHORUS_BYPASS_DEFAULT 1 #define EAS_CHORUS_PRESET_DEFAULT 0 #define EAS_CHORUS_RATE_DEFAULT 30 #define EAS_CHORUS_DEPTH_DEFAULT 39 #define EAS_CHORUS_LEVEL_DEFAULT 32767 #define EAS_CHORUS_LEVEL_MIN 0 #define EAS_CHORUS_LEVEL_MAX 32767 #define EAS_CHORUS_RATE_MIN 10 #define EAS_CHORUS_RATE_MAX 50 #define EAS_CHORUS_DEPTH_MIN 15 #define EAS_CHORUS_DEPTH_MAX 60 #define CHORUS_SIZE_MS 20 #define CHORUS_L_SIZE ((CHORUS_SIZE_MS*_OUTPUT_SAMPLE_RATE)/1000) #define CHORUS_R_SIZE CHORUS_L_SIZE #define CHORUS_SHAPE_SIZE 128 #define CHORUS_DELAY_MS 10 #define CHORUS_MAX_TYPE 4 // any Chorus numbers larger than this are invalid typedef struct { EAS_I16 m_nRate; EAS_I16 m_nDepth; EAS_I16 m_nLevel; } S_CHORUS_PRESET; typedef struct { S_CHORUS_PRESET m_sPreset[CHORUS_MAX_TYPE]; //array of presets } S_CHORUS_PRESET_BANK; /* parameters for each Chorus */ typedef struct { EAS_I32 lfoLPhase; EAS_I32 lfoRPhase; EAS_I16 chorusIndexL; EAS_I16 chorusIndexR; EAS_U16 chorusTapPosition; EAS_I16 m_nRate; EAS_I16 m_nDepth; EAS_I16 m_nLevel; //delay lines used by the chorus, longer would sound better EAS_PCM chorusDelayL[CHORUS_L_SIZE]; EAS_PCM chorusDelayR[CHORUS_R_SIZE]; EAS_BOOL bypass; EAS_I8 preset; EAS_I16 m_nCurrentChorus; // preset number for current Chorus EAS_I16 m_nNextChorus; // preset number for next Chorus S_CHORUS_PRESET pPreset; S_CHORUS_PRESET_BANK m_sPreset; } S_CHORUS_OBJECT; /*---------------------------------------------------------------------------- * WeightedTap() *---------------------------------------------------------------------------- * Purpose: Does fractional array look-up using linear interpolation * * first convert indexDesired to actual desired index by taking into account indexReference * then do linear interpolation between two actual samples using fractional part * * Inputs: * array: pointer to array of signed 16 bit values, typically either PCM data or control data * indexReference: the circular buffer relative offset * indexDesired: the fractional index we are looking up (16 bits index + 16 bits fraction) * indexLimit: the total size of the array, used to compute buffer wrap * * Outputs: * Value from the input array, linearly interpolated between two actual data values * *---------------------------------------------------------------------------- */ static EAS_I16 WeightedTap(const EAS_I16 *array, EAS_I16 indexReference, EAS_I32 indexDesired, EAS_I16 indexLimit); /*---------------------------------------------------------------------------- * ChorusReadInPresets() *---------------------------------------------------------------------------- * Purpose: sets global Chorus preset bank to defaults * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ static EAS_RESULT ChorusReadInPresets(S_CHORUS_OBJECT *pChorusData); /*---------------------------------------------------------------------------- * ChorusUpdate *---------------------------------------------------------------------------- * Purpose: * Update the Chorus preset parameters as required * * Inputs: * * Outputs: * * * Side Effects: * - chorus paramters will be changed * - m_nCurrentChorus := m_nNextChorus *---------------------------------------------------------------------------- */ static EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT* pChorusData); #endif /* #ifndef _EAS_CHORUSDATA_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_tonecontrol.c0000644000000000000000000000013213532747316027456 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.733999895 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_tonecontrol.c0000644000175000001440000007026613532747316030262 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_tonecontrol.c * * Contents and purpose: * MMAPI ToneControl parser * * Copyright Sonic Network Inc. 2006 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 795 $ * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ *---------------------------------------------------------------------------- */ #include "eas_data.h" #include "eas_miditypes.h" #include "eas_parser.h" #include "eas_report.h" #include "eas_host.h" #include "eas_midi.h" #include "eas_config.h" #include "eas_vm_protos.h" #include "eas_tcdata.h" /* default channel and program for TC playback */ #define TC_CHANNEL 0 #define TC_PROGRAM 80 #define TC_VELOCITY 127 #define TC_FIELD_SILENCE -1 #define TC_FIELD_VERSION -2 #define TC_FIELD_TEMPO -3 #define TC_FIELD_RESOLUTION -4 #define TC_FIELD_BLOCK_START -5 #define TC_FIELD_BLOCK_END -6 #define TC_FIELD_PLAY_BLOCK -7 #define TC_FIELD_SET_VOLUME -8 #define TC_FIELD_REPEAT -9 #define TC_FIELD_INVALID -10 /* convert 0-100 volume to 0-127 velocity using fixed point */ #define TC_VOLUME_CONV 21307064 #define TC_VOLUME_SHIFT 24 /* local prototypes */ static EAS_RESULT TC_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); static EAS_RESULT TC_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT TC_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); static EAS_RESULT TC_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); static EAS_RESULT TC_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); static EAS_RESULT TC_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT TC_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT TC_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT TC_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT TC_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); static EAS_RESULT TC_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); static EAS_RESULT TC_ParseHeader (S_EAS_DATA *pEASData, S_TC_DATA* pData); static EAS_RESULT TC_StartNote (S_EAS_DATA *pEASData, S_TC_DATA* pData, EAS_INT parserMode, EAS_I8 note); static EAS_RESULT TC_GetRepeat (S_EAS_DATA *pEASData, S_TC_DATA* pData, EAS_INT parserMode); static EAS_RESULT TC_PlayBlock (S_EAS_DATA *pEASData, S_TC_DATA* pData); static EAS_RESULT TC_BlockEnd (S_EAS_DATA *pEASData, S_TC_DATA* pData); static EAS_RESULT TC_GetVolume (S_EAS_DATA *pEASData, S_TC_DATA* pData); static EAS_RESULT TC_GetTempo (S_EAS_DATA *pEASData, S_TC_DATA* pData); static EAS_RESULT TC_GetResolution (S_EAS_DATA *pEASData, S_TC_DATA* pData); static EAS_RESULT TC_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_TC_DATA *pData, EAS_I8 *pValue); static void TC_PutBackChar (S_TC_DATA *pData, EAS_I8 value); /* calculate a new tick time based on resolution & tempo */ EAS_INLINE void TC_CalcTimeBase (S_TC_DATA *pData) { /* ticks in 256ths of a millisecond */ pData->tick = ((60 * 1000) << 8) / (pData->tempo * pData->resolution); } /*---------------------------------------------------------------------------- * * EAS_TC_Parser * * This structure contains the functional interface for the iMelody parser *---------------------------------------------------------------------------- */ const S_FILE_PARSER_INTERFACE EAS_TC_Parser = { TC_CheckFileType, TC_Prepare, TC_Time, TC_Event, TC_State, TC_Close, TC_Reset, TC_Pause, TC_Resume, NULL, TC_SetData, TC_GetData, NULL }; /*---------------------------------------------------------------------------- * TC_CheckFileType() *---------------------------------------------------------------------------- * Purpose: * Check the file type to see if we can parse it * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT TC_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) { S_TC_DATA data; S_TC_DATA *pData; /* init data */ EAS_HWMemSet(&data, 0, sizeof(S_TC_DATA)); data.fileHandle = fileHandle; data.fileOffset = offset; *ppHandle= NULL; /* see if we can parse the header */ if (TC_ParseHeader(pEASData, &data) == EAS_SUCCESS) { /* check for static memory allocation */ if (pEASData->staticMemoryModel) pData = EAS_CMEnumOptData(EAS_MODULE_MMAPI_TONE_CONTROL); else pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_TC_DATA)); if (!pData) return EAS_ERROR_MALLOC_FAILED; /* copy data to persistent storage */ EAS_HWMemCpy(pData, &data, sizeof(S_TC_DATA)); /* return a pointer to the instance data */ pData->state = EAS_STATE_OPEN; *ppHandle = pData; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * TC_Prepare() *---------------------------------------------------------------------------- * Purpose: * Prepare to parse the file. Allocates instance data (or uses static allocation for * static memory model). * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT TC_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_TC_DATA* pData; EAS_RESULT result; /* check for valid state */ pData = (S_TC_DATA*) pInstData; if (pData->state != EAS_STATE_OPEN) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; /* instantiate a synthesizer */ if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } return result; } /* set to ready state */ pData->state = EAS_STATE_READY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * TC_Time() *---------------------------------------------------------------------------- * Purpose: * Returns the time of the next event in msecs * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * pTime - pointer to variable to hold time of next event (in msecs) * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ static EAS_RESULT TC_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) { S_TC_DATA *pData; pData = (S_TC_DATA*) pInstData; /* return time in milliseconds */ /*lint -e{704} use shift instead of division */ *pTime = pData->time >> 8; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * TC_Event() *---------------------------------------------------------------------------- * Purpose: * Parse the next event in the file * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT TC_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) { S_TC_DATA* pData; EAS_RESULT result; EAS_I8 temp; pData = (S_TC_DATA*) pInstData; if (pData->state >= EAS_STATE_OPEN) return EAS_SUCCESS; /* initialize MIDI channel when the track starts playing */ if (pData->time == 0) { /* set program to square lead */ VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, TC_PROGRAM); /* set channel volume to max */ VMControlChange(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, 7, 127); } /* check for end of note */ if (pData->note >= 0) { /* stop the note */ VMStopNote(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, (EAS_U8) pData->note, 0); /* check for repeat note */ if (pData->repeatCount) { pData->repeatCount--; pData->time += pData->length; if ((pData->note >= 0) && (parserMode == eParserModePlay)) VMStartNote(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, (EAS_U8) pData->note, pData->volume); return EAS_SUCCESS; } pData->note = TC_FIELD_SILENCE; } /* parse stream until we get a note or rest */ for (;;) { /* get next byte from stream */ if ((result = TC_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) { if (result == EAS_EOF) { pData->state = EAS_STATE_STOPPING; return EAS_SUCCESS; } break; } /* check for musical events */ if (temp >= TC_FIELD_SILENCE) { result = TC_StartNote(pEASData, pData, parserMode, temp); break; } /* must be a control field */ switch (temp) { case TC_FIELD_TEMPO: result = TC_GetTempo(pEASData, pData); break; case TC_FIELD_RESOLUTION: result = TC_GetResolution(pEASData, pData); break; case TC_FIELD_SET_VOLUME: result = TC_GetVolume(pEASData, pData); break; case TC_FIELD_REPEAT: result = TC_GetRepeat(pEASData, pData, parserMode); break; case TC_FIELD_PLAY_BLOCK: result = TC_PlayBlock(pEASData, pData); break; case TC_FIELD_BLOCK_START: result = TC_GetNextChar(pEASData->hwInstData, pData, &temp); break; case TC_FIELD_BLOCK_END: result = TC_BlockEnd(pEASData, pData); break; default: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected byte 0x%02x in ToneControl stream\n", temp); */ } result = EAS_ERROR_FILE_FORMAT; } /* check for error */ if (result != EAS_SUCCESS) break; } /* check for error */ if (result != EAS_SUCCESS) { if (result == EAS_EOF) result = EAS_ERROR_FILE_FORMAT; pData->state = EAS_STATE_ERROR; } else pData->state = EAS_STATE_PLAY; return result; } /*---------------------------------------------------------------------------- * TC_State() *---------------------------------------------------------------------------- * Purpose: * Returns the current state of the stream * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * pState - pointer to variable to store state * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ static EAS_RESULT TC_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) { S_TC_DATA* pData; /* establish pointer to instance data */ pData = (S_TC_DATA*) pInstData; /* if stopping, check to see if synth voices are active */ if (pData->state == EAS_STATE_STOPPING) { if (VMActiveVoices(pData->pSynth) == 0) pData->state = EAS_STATE_STOPPED; } if (pData->state == EAS_STATE_PAUSING) { if (VMActiveVoices(pData->pSynth) == 0) pData->state = EAS_STATE_PAUSED; } /* return current state */ *pState = pData->state; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * TC_Close() *---------------------------------------------------------------------------- * Purpose: * Close the file and clean up * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT TC_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_TC_DATA* pData; EAS_RESULT result; pData = (S_TC_DATA*) pInstData; /* close the file */ if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS) return result; /* free the synth */ if (pData->pSynth != NULL) VMMIDIShutdown(pEASData, pData->pSynth); /* if using dynamic memory, free it */ if (!pEASData->staticMemoryModel) EAS_HWFree(pEASData->hwInstData, pData); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * TC_Reset() *---------------------------------------------------------------------------- * Purpose: * Reset the sequencer. Used for locating backwards in the file. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT TC_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_TC_DATA* pData; EAS_RESULT result; pData = (S_TC_DATA*) pInstData; /* reset the synth */ VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE); /* reset time to zero */ pData->time = 0; /* reset file position and re-parse header */ pData->state = EAS_STATE_ERROR; if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) return result; if ((result = TC_ParseHeader (pEASData, pData)) != EAS_SUCCESS) return result; pData->state = EAS_STATE_READY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * TC_Pause() *---------------------------------------------------------------------------- * Purpose: * Pauses the sequencer. Mutes all voices and sets state to pause. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT TC_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_TC_DATA *pData; /* can't pause a stopped stream */ pData = (S_TC_DATA*) pInstData; if (pData->state == EAS_STATE_STOPPED) return EAS_ERROR_ALREADY_STOPPED; /* mute the synthesizer */ VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth); pData->state = EAS_STATE_PAUSING; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * TC_Resume() *---------------------------------------------------------------------------- * Purpose: * Resume playing after a pause, sets state back to playing. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ static EAS_RESULT TC_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_TC_DATA *pData; /* can't resume a stopped stream */ pData = (S_TC_DATA*) pInstData; if (pData->state == EAS_STATE_STOPPED) return EAS_ERROR_ALREADY_STOPPED; /* nothing to do but resume playback */ pData->state = EAS_STATE_PLAY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * TC_SetData() *---------------------------------------------------------------------------- * Purpose: * Return file type * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData, pInstData, value) reserved for future use */ static EAS_RESULT TC_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) { /* we don't parse any metadata, but we need to return success here */ if (param == PARSER_DATA_METADATA_CB) return EAS_SUCCESS; return EAS_ERROR_INVALID_PARAMETER; } /*---------------------------------------------------------------------------- * TC_GetData() *---------------------------------------------------------------------------- * Purpose: * Return file type * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -e{715} common with other parsers */ static EAS_RESULT TC_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) { S_TC_DATA *pData; pData = (S_TC_DATA *) pInstData; switch (param) { /* return file type as TC */ case PARSER_DATA_FILE_TYPE: *pValue = EAS_FILE_MMAPI_TONE_CONTROL; break; case PARSER_DATA_SYNTH_HANDLE: *pValue = (EAS_I32) pData->pSynth; break; default: return EAS_ERROR_INVALID_PARAMETER; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * TC_ParseHeader() *---------------------------------------------------------------------------- * Purpose: * Prepare to parse the file. Allocates instance data (or uses static allocation for * static memory model). * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT TC_ParseHeader (S_EAS_DATA *pEASData, S_TC_DATA* pData) { EAS_RESULT result; EAS_I8 temp; /* initialize some defaults */ pData->time = 0; pData->tempo = 120; pData->resolution = 64; pData->volume = 127; pData->repeatCount = 0; pData->note = TC_FIELD_SILENCE; pData->byteAvail = EAS_FALSE; /* set default timebase */ TC_CalcTimeBase(pData); /* seek to start of data */ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) return result; /* get version */ if ((result = TC_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) return result; /* check for version number */ if (temp == TC_FIELD_VERSION) { TC_GetNextChar(pEASData->hwInstData, pData, &temp); // { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "ToneControl sequence version %d\n", temp); */ } } else return EAS_ERROR_FILE_FORMAT; /* parse the header data until we find the first note or block */ for (;;) { /* get next byte from stream */ if ((result = TC_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) return result; /* check for tempo */ if (temp == TC_FIELD_TEMPO) { if ((result = TC_GetTempo(pEASData, pData)) != EAS_SUCCESS) return result; } /* or resolution */ else if (temp == TC_FIELD_TEMPO) { if ((result = TC_GetResolution(pEASData, pData)) != EAS_SUCCESS) return result; } /* must be music data */ else if (temp > TC_FIELD_INVALID) { TC_PutBackChar(pData, temp); return EAS_SUCCESS; } /* unknown codes */ else { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected byte 0x%02x in ToneControl stream\n", temp); */ } return EAS_ERROR_FILE_FORMAT; } } } /*---------------------------------------------------------------------------- * TC_StartNote() *---------------------------------------------------------------------------- * Process a note or silence event *---------------------------------------------------------------------------- */ static EAS_RESULT TC_StartNote (S_EAS_DATA *pEASData, S_TC_DATA* pData, EAS_INT parserMode, EAS_I8 note) { EAS_I8 duration; /* get the duration */ if (TC_GetNextChar(pEASData->hwInstData, pData, &duration) != EAS_SUCCESS) return EAS_ERROR_FILE_FORMAT; /* calculate time of next event */ pData->length = (EAS_I32) duration * pData->tick; pData->time += pData->length; /* start the note */ if ((note >= 0) && (parserMode == eParserModePlay)) { VMStartNote(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, (EAS_U8) note, pData->volume); pData->note = note; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * TC_GetRepeat() *---------------------------------------------------------------------------- * Process a repeat code *---------------------------------------------------------------------------- */ static EAS_RESULT TC_GetRepeat (S_EAS_DATA *pEASData, S_TC_DATA* pData, EAS_INT parserMode) { EAS_I8 count; /* get the repeat count */ if (TC_GetNextChar(pEASData->hwInstData, pData, &count) != EAS_SUCCESS) return EAS_ERROR_FILE_FORMAT; /* validiate it */ if (count < 2) return EAS_ERROR_FILE_FORMAT; /* calculate time of next event */ pData->time += pData->length; pData->repeatCount = count - 2; /* start the note */ if ((pData->note >= 0) && (parserMode == eParserModePlay)) VMStartNote(pEASData->pVoiceMgr, pData->pSynth, TC_CHANNEL, (EAS_U8) pData->note, pData->volume); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * TC_PlayBlock() *---------------------------------------------------------------------------- * Play a block of notes *---------------------------------------------------------------------------- */ static EAS_RESULT TC_PlayBlock (S_EAS_DATA *pEASData, S_TC_DATA* pData) { EAS_RESULT result; EAS_I8 blockNum; EAS_I8 temp; EAS_I8 temp2; /* get the block number */ if (TC_GetNextChar(pEASData->hwInstData, pData, &blockNum) != EAS_SUCCESS) return EAS_ERROR_FILE_FORMAT; /* validiate it */ if (blockNum < 0) return EAS_ERROR_FILE_FORMAT; /* save the current position */ if ((result = EAS_HWFilePos(pEASData->hwInstData, pData->fileHandle, &pData->restorePos)) != EAS_SUCCESS) return result; /* return to start of file */ pData->byteAvail = EAS_FALSE; if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) return result; /* find the block */ for (;;) { if (TC_GetNextChar(pEASData->hwInstData, pData, &temp) != EAS_SUCCESS) return EAS_ERROR_FILE_FORMAT; if (TC_GetNextChar(pEASData->hwInstData, pData, &temp2) != EAS_SUCCESS) return EAS_ERROR_FILE_FORMAT; if ((temp == TC_FIELD_BLOCK_START) && (temp2 == blockNum)) return EAS_SUCCESS; } } /*---------------------------------------------------------------------------- * TC_BlockEnd() *---------------------------------------------------------------------------- * Handle end of block *---------------------------------------------------------------------------- */ static EAS_RESULT TC_BlockEnd (S_EAS_DATA *pEASData, S_TC_DATA* pData) { EAS_I8 blockNum; /* get the block number */ if (TC_GetNextChar(pEASData->hwInstData, pData, &blockNum) != EAS_SUCCESS) return EAS_ERROR_FILE_FORMAT; /* validiate it */ if (blockNum < 0) return EAS_ERROR_FILE_FORMAT; /* if we were playing this block, restore to previous position */ pData->byteAvail = EAS_FALSE; return EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->restorePos); } /*---------------------------------------------------------------------------- * TC_GetVolume() *---------------------------------------------------------------------------- * Get the volume field and process it *---------------------------------------------------------------------------- */ static EAS_RESULT TC_GetVolume (S_EAS_DATA *pEASData, S_TC_DATA* pData) { EAS_I8 volume; /* get volume */ if (TC_GetNextChar(pEASData->hwInstData, pData, &volume) != EAS_SUCCESS) return EAS_ERROR_FILE_FORMAT; if ((volume < 0) || (volume > 100)) return EAS_ERROR_FILE_FORMAT; /* save volume */ pData->volume = (EAS_U8) ((EAS_I32) (volume * TC_VOLUME_CONV + 1) >> TC_VOLUME_SHIFT); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * TC_GetTempo() *---------------------------------------------------------------------------- * Get the tempo field and process it *---------------------------------------------------------------------------- */ static EAS_RESULT TC_GetTempo (S_EAS_DATA *pEASData, S_TC_DATA* pData) { EAS_I8 tempo; /* get tempo */ if (TC_GetNextChar(pEASData->hwInstData, pData, &tempo) != EAS_SUCCESS) return EAS_ERROR_FILE_FORMAT; if (tempo < 5) return EAS_ERROR_FILE_FORMAT; /* save tempo */ pData->tempo = tempo; /* calculate new timebase */ TC_CalcTimeBase(pData); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * TC_GetResolution() *---------------------------------------------------------------------------- * Get the resolution field and process it *---------------------------------------------------------------------------- */ static EAS_RESULT TC_GetResolution (S_EAS_DATA *pEASData, S_TC_DATA* pData) { EAS_I8 resolution; /* get resolution */ if (TC_GetNextChar(pEASData->hwInstData, pData, &resolution) != EAS_SUCCESS) return EAS_ERROR_FILE_FORMAT; if (resolution < 0) return EAS_ERROR_FILE_FORMAT; /* save tempo */ pData->resolution = resolution; /* calculate new timebase */ TC_CalcTimeBase(pData); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * TC_GetNextChar() *---------------------------------------------------------------------------- * Fetch the next character from the stream *---------------------------------------------------------------------------- */ static EAS_RESULT TC_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_TC_DATA *pData, EAS_I8 *pValue) { /* get character from "put back" buffer */ if (pData->byteAvail) { pData->byteAvail = EAS_FALSE; *pValue = pData->dataByte; return EAS_SUCCESS; } /* get character from file */ return EAS_HWGetByte(hwInstData, pData->fileHandle, pValue); } /*---------------------------------------------------------------------------- * TC_PutBackChar() *---------------------------------------------------------------------------- * Put back the character *---------------------------------------------------------------------------- */ static void TC_PutBackChar (S_TC_DATA *pData, EAS_I8 value) { pData->dataByte = value; pData->byteAvail = EAS_TRUE; } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_effects.h0000644000000000000000000000013213532747316026534 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.733999895 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_effects.h0000644000175000001440000000426013532747316027327 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_effects.h * * Contents and purpose: * Defines a generic effects interface. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_EFFECTS_H #define _EAS_EFFECTS_H #include "eas_types.h" typedef struct { EAS_RESULT (*pfInit)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); void (*pfProcess)(EAS_VOID_PTR pInstData, EAS_PCM *in, EAS_PCM *out, EAS_I32 numSamples); EAS_RESULT (*pfShutdown)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); EAS_RESULT (*pFGetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); EAS_RESULT (*pFSetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); } S_EFFECTS_INTERFACE; typedef struct { EAS_RESULT (*pfInit)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); void (*pfProcess)(EAS_VOID_PTR pInstData, EAS_I32 *in, EAS_I32 *out, EAS_I32 numSamples); EAS_RESULT (*pfShutdown)(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); EAS_RESULT (*pFGetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); EAS_RESULT (*pFSetParam)(EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); } S_EFFECTS32_INTERFACE; /* mixer instance data */ typedef struct { S_EFFECTS_INTERFACE *effect; EAS_VOID_PTR effectData; } S_EFFECTS_MODULE; #endif /* end _EAS_EFFECTS_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_smf.h0000644000000000000000000000013213532747316025702 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.733999895 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_smf.h0000644000175000001440000000416613532747316026502 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_smf.h * * Contents and purpose: * SMF Type 0 and 1 File Parser * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_SMF_H #define _EAS_SMF_H /* prototypes for private interface to SMF parser */ EAS_RESULT SMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); EAS_RESULT SMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); EAS_RESULT SMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); EAS_RESULT SMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); EAS_RESULT SMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); EAS_RESULT SMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); EAS_RESULT SMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); EAS_RESULT SMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); EAS_RESULT SMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); EAS_RESULT SMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); EAS_RESULT SMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); EAS_RESULT SMF_ParseHeader (EAS_HW_DATA_HANDLE hwInstData, S_SMF_DATA *pSMFData); #endif /* end _EAS_SMF_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_xmfdata.c0000644000000000000000000000013213532747316026534 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.733999895 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_xmfdata.c0000644000175000001440000000257513532747316027336 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_xmfdata.c * * Contents and purpose: * XMF File Parser * * This file contains data definitions for the XMF parser. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 547 $ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ *---------------------------------------------------------------------------- */ #include "eas_miditypes.h" #include "eas_xmf.h" #include "eas_xmfdata.h" /*---------------------------------------------------------------------------- * * eas_XMFData * * Static memory allocation for XMF parser *---------------------------------------------------------------------------- */ S_XMF_DATA eas_XMFData; drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_ima_tables.c0000644000000000000000000000013213532747316027210 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.733999895 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_ima_tables.c0000644000175000001440000000357213532747316030010 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_ima_tables.c * * Contents and purpose: * Contains the constant tables for IMA encode/decode * * Copyright (c) 2005 Sonic Network Inc. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 760 $ * $Date: 2007-07-17 23:09:36 -0700 (Tue, 17 Jul 2007) $ *---------------------------------------------------------------------------- */ #include "eas_types.h" /*---------------------------------------------------------------------------- * ADPCM decode tables *---------------------------------------------------------------------------- */ const EAS_I16 imaIndexTable[16] = { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8 }; const EAS_I16 imaStepSizeTable[89] = { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 }; drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_pcm.c0000644000000000000000000000013213532747316025667 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.733999895 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_pcm.c0000644000175000001440000013332013532747316026462 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_pcm.c * * Contents and purpose: * Implements the PCM engine including ADPCM decode for SMAF and CMX audio playback. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 849 $ * $Date: 2007-08-28 08:59:11 -0700 (Tue, 28 Aug 2007) $ *---------------------------------------------------------------------------- */ #include "eas_data.h" #include "eas_report.h" #include "eas_host.h" #include "eas_config.h" #include "eas_parser.h" #include "eas_pcm.h" #include "eas_math.h" #include "eas_mixer.h" #define PCM_MIXER_GUARD_BITS (NUM_MIXER_GUARD_BITS + 1) /*---------------------------------------------------------------------------- * Decoder interfaces *---------------------------------------------------------------------------- */ static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time); static const S_DECODER_INTERFACE PCMDecoder = { NULL, LinearPCMDecode, LinearPCMLocate, }; /* SMAF ADPCM decoder */ #ifdef _SMAF_PARSER extern S_DECODER_INTERFACE SmafDecoder; #define SMAF_DECODER &SmafDecoder extern S_DECODER_INTERFACE Smaf7BitDecoder; #define SMAF_7BIT_DECODER &Smaf7BitDecoder #else #define SMAF_DECODER NULL #define SMAF_7BIT_DECODER NULL #endif /* IMA ADPCM decoder */ #ifdef _IMA_DECODER extern S_DECODER_INTERFACE IMADecoder; #define IMA_DECODER &IMADecoder #else #define IMA_DECODER NULL #endif static const S_DECODER_INTERFACE * const decoders[] = { &PCMDecoder, SMAF_DECODER, IMA_DECODER, SMAF_7BIT_DECODER }; /*---------------------------------------------------------------------------- * Sample rate conversion *---------------------------------------------------------------------------- */ #define SRC_RATE_MULTIPLER (0x40000000 / _OUTPUT_SAMPLE_RATE) #ifdef _LOOKUP_SAMPLE_RATE static const EAS_U32 srcConvRate[][2] = { 4000L, (4000L << 15) / _OUTPUT_SAMPLE_RATE, 8000L, (8000L << 15) / _OUTPUT_SAMPLE_RATE, 11025L, (11025L << 15) / _OUTPUT_SAMPLE_RATE, 12000L, (12000L << 15) / _OUTPUT_SAMPLE_RATE, 16000L, (16000L << 15) / _OUTPUT_SAMPLE_RATE, 22050L, (22050L << 15) / _OUTPUT_SAMPLE_RATE, 24000L, (24000L << 15) / _OUTPUT_SAMPLE_RATE, 32000L, (32000L << 15) / _OUTPUT_SAMPLE_RATE }; static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate); #define SRC_CONV_RATE_ENTRIES (sizeof(srcConvRate)/sizeof(EAS_U32)/2) #endif /* interface prototypes */ static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples); /* local prototypes */ static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData); static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState); /*---------------------------------------------------------------------------- * EAS_PEInit() *---------------------------------------------------------------------------- * Purpose: * Initializes the PCM engine * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PEInit (S_EAS_DATA *pEASData) { S_PCM_STATE *pState; EAS_INT i; /* check for static memory allocation */ if (pEASData->staticMemoryModel) pEASData->pPCMStreams = EAS_CMEnumData(EAS_CM_PCM_DATA); /* allocate dynamic memory */ else pEASData->pPCMStreams = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS); if (!pEASData->pPCMStreams) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate memory for PCM streams\n"); */ } return EAS_ERROR_MALLOC_FAILED; } //zero the memory to insure complete initialization EAS_HWMemSet((void *)(pEASData->pPCMStreams),0, sizeof(S_PCM_STATE) * MAX_PCM_STREAMS); /* initialize the state data */ for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) pState->fileHandle = NULL; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_PEShutdown() *---------------------------------------------------------------------------- * Purpose: * Shuts down the PCM engine * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PEShutdown (S_EAS_DATA *pEASData) { /* free any dynamic memory */ if (!pEASData->staticMemoryModel) { if (pEASData->pPCMStreams) { EAS_HWFree(pEASData->hwInstData, pEASData->pPCMStreams); pEASData->pPCMStreams = NULL; } } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_PERender() *---------------------------------------------------------------------------- * Purpose: * Render a buffer of PCM audio * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PERender (S_EAS_DATA* pEASData, EAS_I32 numSamples) { S_PCM_STATE *pState; EAS_RESULT result; EAS_INT i; /* render all the active streams */ for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) { if ((pState->fileHandle) && (pState->state != EAS_STATE_STOPPED) && (pState->state != EAS_STATE_PAUSED)) if ((result = RenderPCMStream(pEASData, pState, numSamples)) != EAS_SUCCESS) return result; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_PEState() *---------------------------------------------------------------------------- * Purpose: * Returns the current state of the stream * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * pState - pointer to variable to store state * * Outputs: * * * Side Effects: * * Notes: * This interface is also exposed in the internal library for use by the other modules. *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_RESULT EAS_PEState (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pInstData, EAS_STATE *pState) { /* return current state */ *pState = pInstData->state; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_PEClose() *---------------------------------------------------------------------------- * Purpose: * Close the file and clean up * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PEClose (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) { EAS_RESULT result; if ((result = EAS_HWCloseFile(pEASData->hwInstData, pState->fileHandle)) != EAS_SUCCESS) return result; pState->fileHandle = NULL; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * PCM_Reset() *---------------------------------------------------------------------------- * Purpose: * Reset the sequencer. Used for locating backwards in the file. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PEReset (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) { EAS_RESULT result; /* reset file position to first byte of data in the stream */ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, pState->startPos)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d seeking to start of PCM file\n", result); */ } return result; } /* re-initialize stream */ return InitPCMStream(pEASData, pState); } /*---------------------------------------------------------------------------- * EAS_PEOpenStream() *---------------------------------------------------------------------------- * Purpose: * Starts up a PCM playback * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PEOpenStream (S_EAS_DATA *pEASData, S_PCM_OPEN_PARAMS *pParams, EAS_PCM_HANDLE *pHandle) { EAS_RESULT result; S_PCM_STATE *pState; EAS_I32 filePos; /* make sure we support this decoder */ if (pParams->decoder >= NUM_DECODER_MODULES) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder selector out of range\n"); */ } return EAS_ERROR_PARAMETER_RANGE; } if (decoders[pParams->decoder] == NULL) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Decoder module not available\n"); */ } return EAS_ERROR_FEATURE_NOT_AVAILABLE; } /* find a slot for the new stream */ if ((pState = FindSlot(pEASData, pParams->fileHandle, pParams->pCallbackFunc, pParams->cbInstData)) == NULL) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to open ADPCM stream, too many streams open\n"); */ } return EAS_ERROR_MAX_PCM_STREAMS; } /* get the current file position */ if ((result = EAS_HWFilePos(pEASData->hwInstData, pState->fileHandle, &filePos)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWFilePos returned %ld\n",result); */ } pState->fileHandle = NULL; return result; } pState->pDecoder = decoders[pParams->decoder]; pState->startPos = filePos; pState->bytesLeftLoop = pState->byteCount = pParams->size; pState->loopStart = pParams->loopStart; pState->samplesTilLoop = (EAS_I32) pState->loopStart; pState->loopSamples = pParams->loopSamples; pState->samplesInLoop = 0; pState->blockSize = (EAS_U16) pParams->blockSize; pState->flags = pParams->flags; pState->envData = pParams->envData; pState->volume = pParams->volume; pState->sampleRate = (EAS_U16) pParams->sampleRate; /* set the base frequency */ pState->basefreq = (SRC_RATE_MULTIPLER * (EAS_U32) pParams->sampleRate) >> 15; /* calculate shift for frequencies > 1.0 */ pState->rateShift = 0; while (pState->basefreq > 32767) { pState->basefreq = pState->basefreq >> 1; pState->rateShift++; } /* initialize */ if ((result = InitPCMStream(pEASData, pState)) != EAS_SUCCESS) return result; *pHandle = pState; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PEOpenStream: StartPos=%d, byteCount = %d, loopSamples=%d\n", pState->startPos, pState->byteCount, pState->loopSamples); */ } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_PEContinueStream() *---------------------------------------------------------------------------- * Purpose: * Continues a PCM stream * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -e{715} reserved for future use */ EAS_RESULT EAS_PEContinueStream (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 size) { /* add new samples to count */ pState->bytesLeft += size; if (pState->bytesLeft > 0) pState->flags &= ~PCM_FLAGS_EMPTY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_PEGetFileHandle() *---------------------------------------------------------------------------- * Purpose: * Returns the file handle of a stream * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_RESULT EAS_PEGetFileHandle (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_FILE_HANDLE *pFileHandle) { *pFileHandle = pState->fileHandle; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_PEUpdateParams() *---------------------------------------------------------------------------- * Purpose: * Update the pitch and volume parameters for a PCM stream * * Inputs: * pEASData - pointer to EAS library instance data * handle - pointer to S_PCM_STATE for this stream * gainLeft - linear gain multipler in 1.15 fraction format * gainRight - linear gain multipler in 1.15 fraction format * pitch - pitch shift in cents * initial - initial settings, set current gain * * Outputs: * * * Side Effects: * * Notes * In mono mode, leftGain controls the output gain and rightGain is ignored *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ /*lint -esym(715, gainRight) used only in 2-channel version */ EAS_RESULT EAS_PEUpdateParams (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch, EAS_I16 gainLeft, EAS_I16 gainRight) { pState->gainLeft = gainLeft; #if (NUM_OUTPUT_CHANNELS == 2) pState->gainRight = gainRight; #endif pState->pitch = pitch; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_PELocate() *---------------------------------------------------------------------------- * Purpose: * This function seeks to the requested place in the file. Accuracy * is dependent on the sample rate and block size. * * Inputs: * pEASData - pointer to overall EAS data structure * pState - stream handle * time - media time in milliseconds *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PELocate (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState, EAS_I32 time) { if (pState->pDecoder->pfLocate == NULL) return EAS_ERROR_FEATURE_NOT_AVAILABLE; return pState->pDecoder->pfLocate(pEASData, pState, time); } /*---------------------------------------------------------------------------- * EAS_PEUpdateVolume() *---------------------------------------------------------------------------- * Purpose: * Update the volume parameters for a PCM stream * * Inputs: * pEASData - pointer to EAS library instance data * handle - pointer to S_PCM_STATE for this stream * gainLeft - linear gain multipler in 1.15 fraction format * gainRight - linear gain multipler in 1.15 fraction format * initial - initial settings, set current gain * * Outputs: * * * Side Effects: * * Notes * In mono mode, leftGain controls the output gain and rightGain is ignored *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_RESULT EAS_PEUpdateVolume (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 volume) { pState->volume = volume; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_PEUpdatePitch() *---------------------------------------------------------------------------- * Purpose: * Update the pitch parameter for a PCM stream * * Inputs: * pEASData - pointer to EAS library instance data * pState - pointer to S_PCM_STATE for this stream * pitch - new pitch value in pitch cents *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_RESULT EAS_PEUpdatePitch (S_EAS_DATA* pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch) { pState->pitch = pitch; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_PEPause() *---------------------------------------------------------------------------- * Purpose: * Mute and stop rendering a PCM stream. Sets the gain target to zero and stops the playback * at the end of the next audio frame. * * Inputs: * pEASData - pointer to EAS library instance data * handle - pointer to S_PCM_STATE for this stream * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_RESULT EAS_PEPause (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) { /* set state to stopping */ pState->state = EAS_STATE_PAUSING; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_PEResume() *---------------------------------------------------------------------------- * Purpose: * Resume rendering a PCM stream. Sets the gain target back to its * previous setting and restarts playback at the end of the next audio * frame. * * Inputs: * pEASData - pointer to EAS library instance data * handle - pointer to S_PCM_STATE for this stream * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_RESULT EAS_PEResume (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) { /* set state to stopping */ pState->state = EAS_STATE_PLAY; return EAS_SUCCESS; } EAS_U32 getDecayScale(EAS_U32 index) { EAS_U32 utemp; //envelope decay segment switch (index) { case 0: //no decay utemp = 512;//32768; break; case 1: //.0156 dB per update utemp = 511;//32709; break; case 2: //.03125 utemp = 510;//32649; break; case 3: //.0625 utemp = 508;//32532; break; case 4: //.125 utemp = 505;//32298; break; case 5: //.25 utemp = 497;//31835; break; case 6: //.5 utemp = 483;//30929; break; case 7: //1.0 utemp = 456;//29193; break; case 8: //2.0 utemp = 406;//26008; break; case 9: //4.0 utemp = 323;//20642; break; case 10: //8.0 utemp = 203;//13004; break; case 11: //16.0 utemp = 81;//5160; break; case 12: //32.0 utemp = 13;//813; break; case 13: //64.0 utemp = 0;//20; break; case 14: //128.0 utemp = 0; break; case 15: //256.0 default: utemp = 0; break; } //printf("getdecayscale returned %d\n",utemp); return utemp; } EAS_U32 getAttackIncrement(EAS_U32 index) { EAS_U32 utemp; //envelope decay segment switch (index) { case 0: utemp = 32; break; case 1: utemp = 64; break; case 2: utemp = 128; break; case 3: utemp = 256; break; case 4: utemp = 512; break; case 5: utemp = 1024; break; case 6: utemp = 2048; break; case 7: utemp = 4096; break; case 8: utemp = 8192; break; case 9: utemp = 16384; break; case 10: utemp = 32768; break; case 11: utemp = 65536; break; case 12: utemp = 65536; break; case 13: utemp = 65536; break; case 14: utemp = 65535; break; case 15: default: utemp = 0; break; } //printf("getattackincrement returned %d\n",utemp); return utemp; } /*---------------------------------------------------------------------------- * EAS_PERelease() *---------------------------------------------------------------------------- * Purpose: * Put the PCM stream envelope into release. * * Inputs: * pEASData - pointer to EAS library instance data * handle - pointer to S_PCM_STATE for this stream * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_RESULT EAS_PERelease (S_EAS_DATA *pEASData, EAS_PCM_HANDLE pState) { EAS_U32 utemp; //printf("handling note-off part of envelope\n"); /*if the note is not ignore release or sustained*/ if (((pState->envData >> 24) & 0x0F)==0) { /* set envelope state to release */ pState->envState = PCM_ENV_RELEASE; utemp = ((pState->envData >> 20) & 0x0F); pState->envScale = getDecayScale(utemp); //getReleaseScale(utemp); } else { /*else change envelope state to sustain */ pState->envState = PCM_ENV_SUSTAIN; utemp = ((pState->envData >> 28) & 0x0F); pState->envScale = getDecayScale(utemp); //getSustainScale(utemp); } //since we are in release, don't let anything hang around too long //printf("checking env scale, val = %d\n",((S_PCM_STATE*) handle)->envScale); if (pState->envScale > 505) pState->envScale = 505; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * FindSlot() *---------------------------------------------------------------------------- * Purpose: * Locates an empty stream slot and assigns the file handle * * Inputs: * pEASData - pointer to EAS library instance data * fileHandle - file handle * pCallbackFunc - function to be called back upon EAS_STATE_STOPPED * * Outputs: * returns handle to slot or NULL if all slots are used * * Side Effects: * *---------------------------------------------------------------------------- */ static S_PCM_STATE *FindSlot (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_PCM_CALLBACK pCallbackFunc, EAS_VOID_PTR cbInstData) { EAS_INT i; S_PCM_STATE *pState; #ifndef NO_PCM_STEAL S_PCM_STATE *foundState = NULL; EAS_INT count = 0; EAS_U32 startOrder = 0xFFFFFFFF; S_PCM_STATE *stealState = NULL; EAS_U32 youngest = 0; /* find an empty slot, count total in use, and find oldest in use (lowest start order) */ for (i = 0, pState = pEASData->pPCMStreams; i < MAX_PCM_STREAMS; i++, pState++) { /* if this one is available */ if (pState->fileHandle == NULL) { foundState = pState; } /* else this one is in use, so see if it is the oldest, and count total in use */ /* also find youngest */ else { /*one more voice in use*/ count++; /* is this the oldest? (lowest start order) */ if ((pState->state != EAS_STATE_STOPPING) && (pState->startOrder < startOrder)) { /* remember this one */ stealState = pState; /* remember the oldest so far */ startOrder = pState->startOrder; } /* is this the youngest? (highest start order) */ if (pState->startOrder >= youngest) { youngest = pState->startOrder; } } } /* if there are too many voices active, stop the oldest one */ if (count > PCM_STREAM_THRESHOLD) { //printf("stealing!!!\n"); /* make sure we got one, although we should always have one at this point */ if (stealState != NULL) { //flag this as stopping, so it will get shut off stealState->state = EAS_STATE_STOPPING; } } /* if there are no available open streams (we won't likely see this, due to stealing) */ if (foundState == NULL) return NULL; /* save info */ foundState->startOrder = youngest + 1; foundState->fileHandle = fileHandle; foundState->pCallback = pCallbackFunc; foundState->cbInstData = cbInstData; return foundState; #else /* find an empty slot*/ for (i = 0; i < MAX_PCM_STREAMS; i++) { pState = &pEASData->pPCMStreams[i]; if (pState->fileHandle != NULL) continue; pState->fileHandle = fileHandle; pState->pCallback = pCallbackFunc; pState->cbInstData = cbInstData; return pState; } return NULL; #endif } #ifdef _LOOKUP_SAMPLE_RATE /*---------------------------------------------------------------------------- * CalcBaseFreq() *---------------------------------------------------------------------------- * Purpose: * Calculates the fractional phase increment for the sample rate converter * * Inputs: * sampleRate - sample rate in samples/sec * * Outputs: * Returns fractional sample rate with a 15-bit fraction * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_U32 CalcBaseFreq (EAS_U32 sampleRate) { EAS_INT i; /* look up the conversion rate */ for (i = 0; i < (EAS_INT)(SRC_CONV_RATE_ENTRIES); i ++) { if (srcConvRate[i][0] == sampleRate) return srcConvRate[i][1]; } /* if not found in table, do it the long way */ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Sample rate %u not in table, calculating by division\n", sampleRate); */ } return (SRC_RATE_MULTIPLER * (EAS_U32) sampleRate) >> 15; } #endif /*---------------------------------------------------------------------------- * InitPCMStream() *---------------------------------------------------------------------------- * Purpose: * Start an ADPCM stream playback. Decodes the header, preps the engine. * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT InitPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState) { /* initialize the data structure */ pState->bytesLeft = pState->byteCount; pState->phase = 0; pState->srcByte = 0; pState->decoderL.acc = 0; pState->decoderL.output = 0; pState->decoderL.x0 = pState->decoderL.x1 = 0; pState->decoderL.step = 0; pState->decoderR.acc = 0; pState->decoderR.output = 0; pState->decoderR.x0 = pState->decoderR.x1 = 0; pState->decoderR.step = 0; pState->hiNibble = EAS_FALSE; pState->pitch = 0; pState->blockCount = 0; pState->gainLeft = PCM_DEFAULT_GAIN_SETTING; // pState->currentGainLeft = PCM_DEFAULT_GAIN_SETTING; pState->envValue = 0; pState->envState = PCM_ENV_START; #if (NUM_OUTPUT_CHANNELS == 2) pState->gainRight = PCM_DEFAULT_GAIN_SETTING; // pState->currentGainRight = PCM_DEFAULT_GAIN_SETTING; #endif pState->state = EAS_STATE_READY; /* initialize the decoder */ if (pState->pDecoder->pfInit) return (*pState->pDecoder->pfInit)(pEASData, pState); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RenderPCMStream() *---------------------------------------------------------------------------- * Purpose: * Decodes a buffer of ADPCM data. * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT RenderPCMStream (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 numSamples) { EAS_RESULT result; EAS_U32 phaseInc; EAS_I32 gainLeft, gainIncLeft; EAS_I32 *pOut; EAS_I32 temp; EAS_U32 utemp; #if (NUM_OUTPUT_CHANNELS == 2) EAS_I32 gainRight, gainIncRight; #endif #if 0 printf("env data: AR = %d, DR = %d, SL = %d, SR = %d, RR = %d\n", ((pState->envData >> 12) & 0x0F), ((pState->envData >> 16) & 0x0F), ((pState->envData >> 8) & 0x0F), ((pState->envData >> 28) & 0x0F), ((pState->envData >> 20) & 0x0F)); #endif if (pState->envState == PCM_ENV_START) { //printf("env start\n"); utemp = ((pState->envData >> 12) & 0x0F); //if fastest rate, attack is already completed //do the same for slowest rate, since that allows zero to be passed for default envelope if (utemp == 0x0F || utemp == 0x00) { //start envelope at full pState->envValue = (32768<<7); //jump right into decay utemp = ((pState->envData >> 16) & 0x0F); pState->envScale = getDecayScale(utemp); pState->envState = PCM_ENV_DECAY; pState->currentGainLeft = (EAS_I16) FMUL_15x15(pState->gainLeft, pState->volume); pState->currentGainRight = (EAS_I16) FMUL_15x15(pState->gainRight, pState->volume); } //else attack has a ramp else { //start the envelope very low pState->envValue = (2<<7); pState->currentGainLeft = 0; pState->currentGainRight = 0; //get envelope attack scaling value pState->envScale = getAttackIncrement(utemp); //go to attack state pState->envState = PCM_ENV_ATTACK; } } if (pState->envState == PCM_ENV_ATTACK) { //printf("env attack, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); //update envelope value pState->envValue = pState->envValue + (pState->envScale << 7); //check envelope level and update state if needed if (pState->envValue >= (32768<<7)) { pState->envValue = (32768<<7); utemp = ((pState->envData >> 16) & 0x0F); pState->envScale = getDecayScale(utemp); pState->envState = PCM_ENV_DECAY; } } else if (pState->envState == PCM_ENV_DECAY) { //printf("env decay, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); //update envelope value pState->envValue = (pState->envValue * pState->envScale)>>9; //check envelope level against sustain level and update state if needed utemp = ((pState->envData >> 8) & 0x0F); if (utemp == (EAS_U32)0x0F) utemp = (2<<7); else { utemp = ((32769<<7) >> (utemp>>1)); } if (pState->envValue <= utemp) { utemp = ((pState->envData >> 28) & 0x0F); pState->envScale = getDecayScale(utemp); //getSustainScale(utemp); pState->envState = PCM_ENV_SUSTAIN; } } else if (pState->envState == PCM_ENV_SUSTAIN) { //printf("env sustain, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); //update envelope value pState->envValue = (pState->envValue * pState->envScale)>>9; //check envelope level against bottom level and update state if needed if (pState->envValue <= (2<<7)) { //no more decay pState->envScale = 512; pState->envState = PCM_ENV_END; } } else if (pState->envState == PCM_ENV_RELEASE) { //printf("env release, env value = %d, env scale = %d\n",pState->envValue>>7,pState->envScale); //update envelope value pState->envValue = (pState->envValue * pState->envScale)>>9; //check envelope level against bottom level and update state if needed if (pState->envValue <= (2<<7)) { //no more decay pState->envScale = 512; pState->envState = PCM_ENV_END; } } else if (pState->envState == PCM_ENV_END) { //printf("env end\n"); /* set state to stopping, already ramped down */ pState->state = EAS_STATE_STOPPING; } //pState->gainLeft = (EAS_U16)((pState->gainLeft * (pState->envValue>>7))>>15); //pState->gainRight = (EAS_U16)((pState->gainRight * (pState->envValue>>7))>>15); /* gain to 32-bits to increase resolution on anti-zipper filter */ /*lint -e{703} use shift for performance */ gainLeft = (EAS_I32) pState->currentGainLeft << SYNTH_UPDATE_PERIOD_IN_BITS; #if (NUM_OUTPUT_CHANNELS == 2) /*lint -e{703} use shift for performance */ gainRight = (EAS_I32) pState->currentGainRight << SYNTH_UPDATE_PERIOD_IN_BITS; #endif /* calculate a new gain increment, gain target is zero if pausing */ if ((pState->state == EAS_STATE_PAUSING) || (pState->state == EAS_STATE_PAUSED)) { gainIncLeft = -pState->currentGainLeft; #if (NUM_OUTPUT_CHANNELS == 2) gainIncRight= -pState->currentGainRight; #endif } else { EAS_I32 gain = FMUL_15x15(pState->envValue >> 7, pState->volume); gainIncLeft = FMUL_15x15(pState->gainLeft, gain) - pState->currentGainLeft; #if (NUM_OUTPUT_CHANNELS == 2) gainIncRight = FMUL_15x15(pState->gainRight, gain) - pState->currentGainRight; #endif } /* calculate phase increment */ phaseInc = pState->basefreq; /* convert pitch cents to linear multiplier */ if (pState->pitch) { temp = EAS_Calculate2toX(pState->pitch); phaseInc = FMUL_15x15(phaseInc, temp); } phaseInc = phaseInc << pState->rateShift; /* pointer to mix buffer */ pOut = pEASData->pMixBuffer; /* render a buffer of samples */ while (numSamples--) { /* interpolate an output sample */ pState->decoderL.output = pState->decoderL.x0 + FMUL_15x15((pState->decoderL.x1 - pState->decoderL.x0), pState->phase & PHASE_FRAC_MASK); /* stereo output */ #if (NUM_OUTPUT_CHANNELS == 2) /* stereo stream? */ if (pState->flags & PCM_FLAGS_STEREO) pState->decoderR.output = pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK); /* gain scale and mix */ /*lint -e{704} use shift instead of division */ *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; gainLeft += gainIncLeft; /*lint -e{704} use shift instead of division */ if (pState->flags & PCM_FLAGS_STEREO) *pOut++ += (pState->decoderR.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; else *pOut++ += (pState->decoderL.output * (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; gainRight += gainIncRight; /* mono output */ #else /* if stereo stream, decode right channel and mix to mono */ if (pState->flags & PCM_FLAGS_STEREO) { pState->decoderR.output= pState->decoderR.x0 + FMUL_15x15((pState->decoderR.x1 - pState->decoderR.x0), pState->phase & PHASE_FRAC_MASK); /* for mono, sum stereo ADPCM to mono */ /*lint -e{704} use shift instead of division */ *pOut++ += ((pState->decoderL.output + pState->decoderR.output) * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; } else /*lint -e{704} use shift instead of division */ *pOut++ += (pState->decoderL.output * (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS)) >> PCM_MIXER_GUARD_BITS; gainLeft += gainIncLeft; #endif /* advance phase accumulator */ pState->phase += phaseInc; /* if integer part of phase accumulator is non-zero, advance to next sample */ while (pState->phase & ~PHASE_FRAC_MASK) { pState->decoderL.x0 = pState->decoderL.x1; pState->decoderR.x0 = pState->decoderR.x1; /* give the source a chance to continue the stream */ if (!pState->bytesLeft && pState->pCallback && ((pState->flags & PCM_FLAGS_EMPTY) == 0)) { pState->flags |= PCM_FLAGS_EMPTY; (*pState->pCallback)(pEASData, pState->cbInstData, pState, EAS_STATE_EMPTY); { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "RenderPCMStream: After empty callback, bytesLeft = %d\n", pState->bytesLeft); */ } } /* decode the next sample */ if ((result = (*pState->pDecoder->pfDecodeSample)(pEASData, pState)) != EAS_SUCCESS) return result; /* adjust phase by one sample */ pState->phase -= (1L << NUM_PHASE_FRAC_BITS); } } /* save new gain */ /*lint -e{704} use shift instead of division */ pState->currentGainLeft = (EAS_I16) (gainLeft >> SYNTH_UPDATE_PERIOD_IN_BITS); #if (NUM_OUTPUT_CHANNELS == 2) /*lint -e{704} use shift instead of division */ pState->currentGainRight = (EAS_I16) (gainRight >> SYNTH_UPDATE_PERIOD_IN_BITS); #endif /* if pausing, set new state and notify */ if (pState->state == EAS_STATE_PAUSING) { pState->state = EAS_STATE_PAUSED; if (pState->pCallback) (*pState->pCallback)(pEASData, pState->cbInstData, pState, pState->state); } /* if out of data, set stopped state and notify */ if (pState->bytesLeft == 0 || pState->state == EAS_STATE_STOPPING) { pState->state = EAS_STATE_STOPPED; /* do callback unless the file has already been closed */ if (pState->pCallback && pState->fileHandle) (*pState->pCallback)(pEASData, pState->cbInstData, pState, pState->state); } if (pState->state == EAS_STATE_READY) pState->state = EAS_STATE_PLAY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * LinearPCMDecode() *---------------------------------------------------------------------------- * Purpose: * Decodes a PCM sample * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT LinearPCMDecode (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState) { EAS_RESULT result; EAS_HW_DATA_HANDLE hwInstData; hwInstData = ((S_EAS_DATA*) pEASData)->hwInstData; /* if out of data, check for loop */ if ((pState->bytesLeft == 0) && (pState->loopSamples != 0)) { if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, (EAS_I32) (pState->startPos + pState->loopLocation))) != EAS_SUCCESS) return result; pState->bytesLeft = pState->byteCount = (EAS_I32) pState->bytesLeftLoop; pState->flags &= ~PCM_FLAGS_EMPTY; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "LinearPCMDecode: Rewind file to %d, bytesLeft = %d\n", pState->startPos, pState->bytesLeft); */ } } if (pState->bytesLeft) { /* check format byte for 8-bit samples */ if (pState->flags & PCM_FLAGS_8_BIT) { /* fetch left or mono sample */ if ((result = EAS_HWGetByte(hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS) return result; /* if unsigned */ if (pState->flags & PCM_FLAGS_UNSIGNED) { /*lint -e{734} converting unsigned 8-bit to signed 16-bit */ pState->decoderL.x1 = (EAS_PCM)(((EAS_PCM) pState->srcByte << 8) ^ 0x8000); } else { /*lint -e{734} converting signed 8-bit to signed 16-bit */ pState->decoderL.x1 = (EAS_PCM)((EAS_PCM) pState->srcByte << 8); } pState->bytesLeft--; /* fetch right sample */ if(pState->flags & PCM_FLAGS_STEREO) { if ((result = EAS_HWGetByte(hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS) return result; /* if unsigned */ if (pState->flags & PCM_FLAGS_UNSIGNED) { /*lint -e{734} converting unsigned 8-bit to signed 16-bit */ pState->decoderR.x1 = (EAS_PCM)(((EAS_PCM) pState->srcByte << 8) ^ 0x8000); } else { /*lint -e{734} converting signed 8-bit to signed 16-bit */ pState->decoderR.x1 = (EAS_PCM)((EAS_PCM) pState->srcByte << 8); } pState->bytesLeft--; } } /* must be 16-bit samples */ else { //unsigned 16 bit currently not supported if (pState->flags & PCM_FLAGS_UNSIGNED) { return EAS_ERROR_INVALID_PCM_TYPE; } /* fetch left or mono sample */ if ((result = EAS_HWGetWord(hwInstData, pState->fileHandle, &pState->decoderL.x1, EAS_FALSE)) != EAS_SUCCESS) return result; pState->bytesLeft -= 2; /* fetch right sample */ if(pState->flags & PCM_FLAGS_STEREO) { if ((result = EAS_HWGetWord(hwInstData, pState->fileHandle, &pState->decoderR.x1, EAS_FALSE)) != EAS_SUCCESS) return result; pState->bytesLeft -= 2; } } } /* no more data, force zero samples */ else pState->decoderL.x1 = pState->decoderR.x1 = 0; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * LinearPCMLocate() *---------------------------------------------------------------------------- * Purpose: * Locate in a linear PCM stream *---------------------------------------------------------------------------- */ static EAS_RESULT LinearPCMLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time) { EAS_RESULT result; EAS_I32 temp; EAS_I32 secs, msecs; EAS_INT shift; /* calculate size of sample frame */ if (pState->flags & PCM_FLAGS_8_BIT) shift = 0; else shift = 1; if (pState->flags & PCM_FLAGS_STEREO) shift++; /* break down into secs and msecs */ secs = time / 1000; msecs = time - (secs * 1000); /* calculate sample number fraction from msecs */ temp = (msecs * pState->sampleRate); temp = (temp >> 10) + ((temp * 49) >> 21); /* add integer sample count */ temp += secs * pState->sampleRate; /* calculate the position based on sample frame size */ /*lint -e{703} use shift for performance */ temp <<= shift; /* past end of sample? */ if (temp > (EAS_I32) pState->loopStart) { /* if not looped, flag error */ if (pState->loopSamples == 0) { pState->bytesLeft = 0; pState->flags |= PCM_FLAGS_EMPTY; return EAS_ERROR_LOCATE_BEYOND_END; } /* looped sample - calculate position in loop */ while (temp > (EAS_I32) pState->loopStart) temp -= (EAS_I32) pState->loopStart; } /* seek to new position */ if ((result = EAS_PESeek(pEASData, pState, &temp)) != EAS_SUCCESS) return result; /* reset state */ if ((pState->state != EAS_STATE_PAUSING) && (pState->state != EAS_STATE_PAUSED)) pState->state = EAS_STATE_READY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_PESeek *---------------------------------------------------------------------------- * Purpose: * Locate to a particular byte in a PCM stream *---------------------------------------------------------------------------- * This bit is tricky because the chunks may not be contiguous, * so we have to rely on the parser to position in the file. We * do this by seeking to the end of each chunk and simulating an * empty buffer condition until we get to where we want to go. * * A better solution would be a parser API for re-positioning, * but there isn't time at the moment to re-factor all the * parsers to support a new API. *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PESeek (S_EAS_DATA *pEASData, S_PCM_STATE *pState, EAS_I32 *pLocation) { EAS_RESULT result; /* seek to start of audio */ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, pState->startPos)) != EAS_SUCCESS) { pState->state = EAS_STATE_ERROR; return result; } pState->bytesLeft = pState->bytesLeftLoop; /* skip through chunks until we find the right chunk */ while (*pLocation > (EAS_I32) pState->bytesLeft) { /* seek to end of audio chunk */ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: Seek to offset = %d\n", pState->bytesLeft); */ } if ((result = EAS_HWFileSeekOfs(pEASData->hwInstData, pState->fileHandle, pState->bytesLeft)) != EAS_SUCCESS) { pState->state = EAS_STATE_ERROR; return result; } *pLocation -= pState->bytesLeft; pState->bytesLeft = 0; pState->flags |= PCM_FLAGS_EMPTY; /* retrieve more data */ if (pState->pCallback) (*pState->pCallback)(pEASData, pState->cbInstData, pState, EAS_STATE_EMPTY); { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: bytesLeft=%d, byte location = %d\n", pState->bytesLeft, *pLocation); */ } /* no more samples */ if (pState->bytesLeft == 0) return EAS_ERROR_LOCATE_BEYOND_END; } /* seek to new offset in current chunk */ if (*pLocation > 0) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "EAS_PESeek: Seek to offset = %d\n", *pLocation); */ } if ((result = EAS_HWFileSeekOfs(pEASData->hwInstData, pState->fileHandle, *pLocation)) != EAS_SUCCESS) { pState->state = EAS_STATE_ERROR; return result; } /* if not streamed, calculate number of bytes left */ if (pState->flags & PCM_FLAGS_STREAMING) pState->bytesLeft = 0x7fffffff; else pState->bytesLeft -= *pLocation; } return EAS_SUCCESS; } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_mididata.c0000644000000000000000000000013213532747316026664 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.733999895 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_mididata.c0000644000175000001440000000212313532747316027453 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_mididata.c * * Contents and purpose: * Data module for MIDI stream interface * * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 547 $ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ *---------------------------------------------------------------------------- */ #include "eas_miditypes.h" S_INTERACTIVE_MIDI eas_MIDIData; drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_pan.c0000644000000000000000000000013213532747316025666 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.733999895 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_pan.c0000644000175000001440000000572313532747316026466 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_pan.c * * Contents and purpose: * Calculates left and right gain multipliers based on a pan value from -63 to +63 * * NOTES: * The _CMX_PARSER and _MFI_PARSER preprocessor symbols determine * whether the parser works for those particular file formats. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ #include "eas_pan.h" #include "eas_math.h" /*---------------------------------------------------------------------------- * EAS_CalcPanControl() *---------------------------------------------------------------------------- * Purpose: * Assign the left and right gain values corresponding to the given pan value. * * This routine uses sin/cos approximations for an equal power curve: * * sin(x) = (2-4*c)*x^2 + c + x * cos(x) = (2-4*c)*x^2 + c - x * * where c = 1/sqrt(2) * using the a0 + x*(a1 + x*a2) approach * * Inputs: * pan - pan value (-63 to + 63) * * Outputs: * pGainLeft linear gain multiplier for left channel (15-bit fraction) * pGainRight linear gain multiplier for left channel (15-bit fraction) * * Side Effects: *---------------------------------------------------------------------------- */ void EAS_CalcPanControl (EAS_INT pan, EAS_I16 *pGainLeft, EAS_I16 *pGainRight) { EAS_INT temp; EAS_INT netAngle; /* impose hard limit */ if (pan < -63) netAngle = -63; else if (pan > 63) netAngle = 63; else netAngle = pan; /*lint -e{701} */ netAngle = netAngle << 8; /* calculate sin */ temp = EG1_ONE + FMUL_15x15(COEFF_PAN_G2, netAngle); temp = COEFF_PAN_G0 + FMUL_15x15(temp, netAngle); if (temp > SYNTH_FULL_SCALE_EG1_GAIN) temp = SYNTH_FULL_SCALE_EG1_GAIN; else if (temp < 0) temp = 0; *pGainRight = (EAS_I16) temp; /* calculate cos */ temp = -EG1_ONE + FMUL_15x15(COEFF_PAN_G2, netAngle); temp = COEFF_PAN_G0 + FMUL_15x15(temp, netAngle); if (temp > SYNTH_FULL_SCALE_EG1_GAIN) temp = SYNTH_FULL_SCALE_EG1_GAIN; else if (temp < 0) temp = 0; *pGainLeft = (EAS_I16) temp; } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/wt_22khz.c0000644000000000000000000000013213532747316025732 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.733999895 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/wt_22khz.c0000644000175000001440000522416213532747316026537 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * Filename: wt_200k_G.c * Source: wt_200k_G.dls * CmdLine: -w wt_200k_G.c -l wt_200k_G.log -ce -cf wt_200k_G.dls -w -l -ce -cf wt_200k_G.dls * Purpose: Wavetable sound libary * * Copyright (c) 2009 Sonic Network Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 960 $ * $Date: 2009-03-18 15:08:29 -0500 (Wed, 18 Mar 2009) $ *---------------------------------------------------------------------------- */ #include "eas_sndlib.h" /*---------------------------------------------------------------------------- * Articulations *---------------------------------------------------------------------------- */ const S_ARTICULATION eas_articulations[] = { { /* articulation 0 */ { 32767, 30725, 0, 30725 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 1 */ { 32767, 26863, 0, 26863 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 2 */ { 32767, 30484, 0, 30668 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 3 */ { 32767, 26439, 0, 26439 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 4 */ { 32767, 0, 32767, 32715 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 5 */ { 32767, 21333, 0, 21333 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 6 */ { 32767, 31882, 0, 31938 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 7 */ { 32767, 32663, 32767, 32663 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 8 */ { 32767, 0, 32767, 0 }, { 32767, 1902, 0, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 9 */ { 32767, 32349, 0, 32349 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 10 */ { 32767, 0, 32767, 17213 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -1 }, { /* articulation 11 */ { 32767, 31730, 0, 31730 }, { 32767, 761, 0, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -44 }, { /* articulation 12 */ { 32767, 23749, 0, 23749 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 56 }, { /* articulation 13 */ { 32767, 31730, 0, 31730 }, { 32767, 761, 0, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -31 }, { /* articulation 14 */ { 9511, 21333, 0, 21333 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 56 }, { /* articulation 15 */ { 32767, 31617, 0, 31617 }, { 32767, 761, 0, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -6 }, { /* articulation 16 */ { 32767, 32123, 0, 32194 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 56 }, { /* articulation 17 */ { 32767, 31550, 0, 31550 }, { 32767, 761, 0, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 6 }, { /* articulation 18 */ { 32767, 31391, 0, 31391 }, { 32767, 951, 0, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 31 }, { /* articulation 19 */ { 32767, 31964, 0, 31964 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 25 }, { /* articulation 20 */ { 32767, 31056, 0, 31056 }, { 32767, 951, 0, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 63 }, { /* articulation 21 */ { 32767, 32289, 0, 32271 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -37 }, { /* articulation 22 */ { 19021, 31882, 0, 31911 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -37 }, { /* articulation 23 */ { 32767, 31988, 0, 32032 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -37 }, { /* articulation 24 */ { 32767, 0, 32767, 32663 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 12 }, { /* articulation 25 */ { 32767, 31352, 0, 31352 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -25 }, { /* articulation 26 */ { 32767, 0, 32767, 32663 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 25 }, { /* articulation 27 */ { 32767, 31817, 0, 31781 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -25 }, { /* articulation 28 */ { 32767, 30725, 0, 30725 }, { 32767, 95, 0, 0 }, 0, 0, 951, 240, 0, 0, 0, 0, -56 }, { /* articulation 29 */ { 32767, 32230, 0, 32218 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -37 }, { /* articulation 30 */ { 32767, 26439, 0, 26439 }, { 32767, 3804, 0, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 50 }, { /* articulation 31 */ { 32767, 23749, 0, 23749 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -50 }, { /* articulation 32 */ { 32767, 29434, 0, 29434 }, { 32767, 3804, 0, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -50 }, { /* articulation 33 */ { 32767, 30240, 0, 30234 }, { 32767, 3804, 0, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -44 }, { /* articulation 34 */ { 32767, 32558, 0, 32558 }, { 32767, 254, 0, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 25 }, { /* articulation 35 */ { 32767, 0, 32767, 32663 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -63 }, { /* articulation 36 */ { 3804, 23749, 0, 23749 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -63 }, { /* articulation 37 */ { 32767, 23749, 0, 23749 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -59 }, { /* articulation 38 */ { 32767, 30725, 0, 30725 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 50 }, { /* articulation 39 */ { 32767, 28809, 0, 28809 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 44 }, { /* articulation 40 */ { 1902, 30725, 0, 30725 }, { 32767, 380, 0, 0 }, 0, 0, 951, -100, 0, 0, 0, 0, 44 }, { /* articulation 41 */ { 32767, 9042, 0, 9042 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 25 }, { /* articulation 42 */ { 32767, 29889, 0, 29889 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 63 }, { /* articulation 43 */ { 32767, 30240, 0, 30234 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 63 }, { /* articulation 44 */ { 19021, 19970, 0, 19970 }, { 951, 32767, 32767, 0 }, 0, 0, 951, 100, 0, 0, 0, 0, -25 }, { /* articulation 45 */ { 3804, 17213, 0, 17213 }, { 951, 32767, 32767, 0 }, 0, 0, 951, 500, 0, 0, 0, 0, -25 }, { /* articulation 46 */ { 32767, 17213, 0, 17213 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -56 }, { /* articulation 47 */ { 32767, 30725, 0, 30725 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, -56 }, { /* articulation 48 */ { 32767, 0, 32767, 0 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 49 */ { 32767, 31180, 0, 31180 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 50 */ { 19021, 31964, 0, 32071 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 51 */ { 32767, 29669, 0, 29669 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 52 */ { 32767, 31742, 0, 31352 }, { 32767, 294, 0, 0 }, 0, 0, 951, 0, 10000, 7121, 0, 0, 0 }, { /* articulation 53 */ { 32767, 0, 32767, 31391 }, { 32767, 32767, 32767, 0 }, 0, 0, 1555, 0, -2300, 11920, 0, 0, 0 }, { /* articulation 54 */ { 1174, 0, 32767, 31988 }, { 32767, 127, 0, 0 }, 0, 0, 1555, 0, 2000, 10721, 0, 8, 15 }, { /* articulation 55 */ { 1174, 0, 32767, 31988 }, { 951, 127, 0, 0 }, 0, 0, 1555, 0, 2000, 9023, 0, 5, 15 }, { /* articulation 56 */ { 7608, 0, 32767, 30237 }, { 32767, 69, 5898, 0 }, 0, 0, 1555, 0, 6000, 9080, 0, 0, -2 }, { /* articulation 57 */ { 32767, 0, 32767, 29337 }, { 32767, 32767, 32767, 0 }, 0, 0, 1555, 0, 0, 0, 0, 0, 1 }, { /* articulation 58 */ { 5141, 0, 32767, 30194 }, { 32767, 32767, 32767, 0 }, 0, 0, 1555, 0, 0, 0, 0, 0, 0 }, { /* articulation 59 */ { 32767, 32558, 0, 26439 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 60 */ { 32767, 32349, 0, 26439 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 61 */ { 32767, 32072, 0, 32072 }, { 32767, 95, 0, 0 }, 0, 34, 989, 0, 2400, 9521, 0, 0, 0 }, { /* articulation 62 */ { 32767, 30234, 0, 30234 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 11738, 0, 16, 0 }, { /* articulation 63 */ { 32767, 32349, 0, 30073 }, { 32767, 634, 0, 0 }, 0, 34, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 64 */ { 32767, 31730, 0, 31476 }, { 32767, 634, 0, 0 }, 0, 34, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 65 */ { 32767, 32418, 0, 25329 }, { 32767, 95, 0, 0 }, 0, 34, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 66 */ { 32767, 32052, 0, 31964 }, { 32767, 634, 0, 0 }, 0, 34, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 67 */ { 32767, 31938, 0, 31938 }, { 32767, 634, 0, 0 }, 0, 34, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 68 */ { 9511, 32663, 18820, 23749 }, { 1902, 57, 13107, 0 }, 0, 0, 989, 0, 6000, 5535, 0, 4, 0 }, { /* articulation 69 */ { 32767, 31754, 0, 31730 }, { 32767, 1902, 0, 0 }, 0, 52, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 70 */ { 127, 32686, 3811, 32349 }, { 95, 38, 32767, 0 }, 0, 0, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 71 */ { 4755, 32663, 3566, 28809 }, { 3804, 32767, 32767, 0 }, 0, 0, 989, 100, 0, 11919, 0, 0, 0 }, { /* articulation 72 */ { 32767, 31935, 0, 31935 }, { 32767, 335, 0, 0 }, 0, 17, 989, 0, 7000, 9023, 0, 0, 0 }, { /* articulation 73 */ { 32767, 31391, 0, 31391 }, { 32767, 335, 0, 0 }, 0, 2, 951, 0, 7000, 9023, 0, 0, 0 }, { /* articulation 74 */ { 32767, 32628, 6208, 31935 }, { 380, 95, 0, 0 }, 0, 0, 989, 0, 3840, 8302, 0, 8, 0 }, { /* articulation 75 */ { 32767, 32072, 0, 32171 }, { 32767, 380, 0, 0 }, 0, 0, 989, 0, 5000, 8321, 0, 0, 0 }, { /* articulation 76 */ { 32767, 31935, 0, 31935 }, { 32767, 380, 0, 0 }, 0, 0, 951, 0, 5000, 7934, 0, 0, 0 }, { /* articulation 77 */ { 32767, 32117, 0, 30685 }, { 32767, 63, 0, 0 }, 0, 17, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 78 */ { 32767, 32245, 0, 23749 }, { 32767, 1902, 0, 0 }, 0, 172, 989, 0, 1000, 11107, 0, 0, 0 }, { /* articulation 79 */ { 32767, 32663, 6208, 31935 }, { 95, 95, 0, 0 }, 0, 34, 1622, 0, 3560, 8834, 1, 8, 0 }, { /* articulation 80 */ { 32767, 32362, 0, 26439 }, { 32767, 190, 0, 0 }, 0, 17, 989, 0, 6000, 9907, 0, 0, 0 }, { /* articulation 81 */ { 32767, 32245, 0, 23749 }, { 32767, 63, 0, 0 }, 0, 17, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 82 */ { 32767, 31730, 18820, 9042 }, { 32767, 32767, 32767, 0 }, 0, 17, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 83 */ { 32767, 32715, 128, 32168 }, { 32767, 127, 0, 0 }, 0, 0, 989, 0, 0, 11920, 0, 8, 0 }, { /* articulation 84 */ { 32767, 32072, 0, 32072 }, { 32767, 67, 0, 0 }, 3, 0, 572, 0, 5000, 5535, 0, 0, 0 }, { /* articulation 85 */ { 3804, 32663, 18820, 23749 }, { 32767, 2024, 0, 0 }, 10, 34, 1008, -30, 0, 0, 0, 0, 0 }, { /* articulation 86 */ { 19021, 32663, 18820, 23749 }, { 761, 95, 0, 0 }, 0, 34, 989, 0, 4473, 7131, 0, 8, 0 }, { /* articulation 87 */ { 1902, 32628, 6208, 32171 }, { 634, 38, 16384, 0 }, 0, 0, 989, 0, 2987, 7877, 0, 12, 0 }, { /* articulation 88 */ { 32767, 32593, 0, 31935 }, { 32767, 95, 0, 0 }, 0, 0, 1162, 0, 4053, 7930, 2, 12, 0 }, { /* articulation 89 */ { 380, 32684, 6208, 31935 }, { 32767, 112, 0, 0 }, 0, 0, 989, 0, 0, 8887, 0, 0, 0 }, { /* articulation 90 */ { 19021, 32663, 18820, 23749 }, { 1268, 95, 0, 0 }, 0, 34, 989, 0, 5113, 7981, 0, 4, 0 }, { /* articulation 91 */ { 1902, 32663, 6208, 30725 }, { 1902, 127, 0, 0 }, 0, 34, 989, 0, 3500, 7877, 0, 5, 0 }, { /* articulation 92 */ { 1902, 32663, 6208, 30725 }, { 1268, 95, 0, 0 }, 0, 34, 951, 0, 4773, 8355, 0, 5, 0 }, { /* articulation 93 */ { 476, 32663, 10809, 31935 }, { 32767, 32767, 32767, 0 }, 0, 34, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 94 */ { 3804, 32663, 18820, 30234 }, { 32767, 32767, 32767, 0 }, 0, 34, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 95 */ { 7608, 32663, 18820, 17213 }, { 2536, 261, 0, 0 }, 0, 34, 989, 0, 1200, 11690, 0, 4, 0 }, { /* articulation 96 */ { 32767, 32468, 15076, 30234 }, { 32767, 32767, 32767, 0 }, 0, 36, 2183, 0, 0, 11919, 1, 0, 0 }, { /* articulation 97 */ { 32767, 0, 32767, 32663 }, { 380, 32767, 32767, 0 }, 0, 0, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 98 */ { 32767, 31391, 0, 31391 }, { 32767, 634, 0, 0 }, 0, 0, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 99 */ { 32767, 32558, 0, 23749 }, { 1268, 190, 13107, 0 }, 0, 34, 989, 0, 3200, 8321, 0, 0, 0 }, { /* articulation 100 */ { 32767, 0, 32767, 0 }, { 32767, 32767, 32767, 0 }, 0, 0, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 101 */ { 32767, 32072, 0, 23749 }, { 32767, 1087, 0, 0 }, 0, 34, 989, 0, 8187, 5535, 0, 5, 0 }, { /* articulation 102 */ { 32767, 32558, 0, 29434 }, { 32767, 190, 7667, 0 }, 5, 0, 989, 0, 6053, 5535, 0, 5, 0 }, { /* articulation 103 */ { 32767, 32663, 18820, 23749 }, { 1902, 95, 0, 0 }, 0, 0, 989, 0, 2700, 9852, 0, 0, 0 }, { /* articulation 104 */ { 32767, 32663, 18820, 27897 }, { 1902, 95, 0, 0 }, 0, 0, 989, 0, 2700, 9852, 0, 0, 0 }, { /* articulation 105 */ { 32767, 32663, 18820, 23749 }, { 32767, 1268, 0, 0 }, 0, 52, 951, 0, 2500, 10490, 1, 8, 0 }, { /* articulation 106 */ { 32767, 32663, 23493, 23749 }, { 32767, 380, 0, 0 }, 0, 34, 988, 0, 4000, 10223, 1, 4, 0 }, { /* articulation 107 */ { 32767, 32663, 18820, 27897 }, { 32767, 126, 7667, 0 }, 0, 0, 989, 0, 1813, 9154, 0, 0, 0 }, { /* articulation 108 */ { 32767, 31730, 0, 31730 }, { 32767, 380, 0, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 109 */ { 32767, 31180, 0, 30484 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 11690, 0, 0, 0 }, { /* articulation 110 */ { 32767, 30725, 0, 30725 }, { 32767, 380, 0, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 111 */ { 32767, 32349, 18820, 27897 }, { 32767, 95, 0, 0 }, 12, 34, 951, 0, 3000, 10223, 0, 0, 0 }, { /* articulation 112 */ { 32767, 32349, 18820, 27897 }, { 32767, 63, 0, 0 }, 12, 34, 951, 0, 1900, 10031, 0, 0, 0 }, { /* articulation 113 */ { 32767, 32663, 18820, 26439 }, { 32767, 63, 0, 0 }, 12, 34, 988, 0, 1000, 11107, 0, 0, 0 }, { /* articulation 114 */ { 32767, 32663, 18820, 26439 }, { 32767, 63, 0, 0 }, 12, 34, 988, 0, 2000, 11107, 0, 0, 0 }, { /* articulation 115 */ { 32767, 32505, 0, 26439 }, { 32767, 190, 0, 0 }, 0, 17, 989, 0, 4000, 8321, 0, 0, 0 }, { /* articulation 116 */ { 32767, 31832, 19893, 9042 }, { 32767, 476, 0, 0 }, 0, 34, 1452, 0, 0, 11919, 0, 0, 0 }, { /* articulation 117 */ { 19021, 32072, 23493, 9042 }, { 32767, 32767, 32767, 0 }, 0, 34, 1355, 0, 0, 11877, 1, 0, 0 }, { /* articulation 118 */ { 32767, 32468, 0, 23749 }, { 32767, 190, 0, 0 }, 0, 34, 989, 0, 3500, 9023, 0, 0, 0 }, { /* articulation 119 */ { 32767, 17213, 23493, 0 }, { 32767, 32767, 32767, 0 }, 0, 17, 1521, 0, 0, 10925, 1, 0, 0 }, { /* articulation 120 */ { 32767, 32505, 0, 26439 }, { 32767, 190, 0, 0 }, 0, 52, 989, 0, 3200, 8721, 0, 4, 0 }, { /* articulation 121 */ { 3804, 32663, 18820, 23749 }, { 32767, 32767, 32767, 0 }, 0, 34, 989, 0, 0, 0, 1, 0, 0 }, { /* articulation 122 */ { 9511, 32663, 18820, 25329 }, { 32767, 32767, 32767, 0 }, 0, 34, 989, 0, 0, 11877, 0, 8, 0 }, { /* articulation 123 */ { 32767, 32663, 18820, 23749 }, { 32767, 32, 0, 0 }, 0, 17, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 124 */ { 32767, 32558, 0, 23749 }, { 32767, 380, 0, 0 }, 0, 34, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 125 */ { 32767, 32663, 18820, 23749 }, { 32767, 24, 0, 0 }, 0, 17, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 126 */ { 32767, 30725, 0, 30725 }, { 32767, 761, 0, 0 }, 0, 0, 989, 0, 3000, 10223, 0, 8, 0 }, { /* articulation 127 */ { 127, 0, 32767, 32349 }, { 32767, 32767, 32767, 0 }, 0, 0, 1522, 0, 0, 11423, 4, 0, 0 }, { /* articulation 128 */ { 951, 32422, 0, 32387 }, { 32767, 19, 0, 0 }, 0, 0, 989, 0, 0, 11423, 0, 0, 0 }, { /* articulation 129 */ { 391, 0, 0, 31180 }, { 190, 32767, 32767, 0 }, 0, 0, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 130 */ { 32767, 30725, 0, 30725 }, { 32767, 761, 0, 0 }, 0, 0, 989, 1200, 0, 0, 0, 0, 0 }, { /* articulation 131 */ { 32767, 31730, 0, 31935 }, { 32767, 380, 0, 0 }, 0, 0, 989, 50, 0, 0, 0, 0, 0 }, { /* articulation 132 */ { 32767, 32072, 0, 32072 }, { 32767, 19021, 0, 0 }, 0, 0, 989, 0, 4700, 7769, 0, 0, 0 }, { /* articulation 133 */ { 32767, 30073, 0, 30073 }, { 32767, 32767, 0, 0 }, 0, 0, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 134 */ { 32767, 32558, 32767, 32558 }, { 32767, 32767, 32767, 0 }, 0, 0, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 135 */ { 32767, 32663, 18820, 17213 }, { 32767, 190, 0, 0 }, 10, 34, 951, 0, 2000, 10696, 0, 0, 0 }, { /* articulation 136 */ { 32767, 32663, 10809, 17213 }, { 32767, 190, 0, 0 }, 12, 34, 982, 0, 0, 10910, 0, 0, 0 }, { /* articulation 137 */ { 32767, 32663, 18820, 17213 }, { 32767, 190, 0, 0 }, 10, 34, 951, 0, 1200, 10218, 0, 0, 0 }, { /* articulation 138 */ { 32767, 32663, 18820, 17213 }, { 32767, 190, 0, 0 }, 10, 34, 951, 0, 1100, 9525, 0, 0, 0 }, { /* articulation 139 */ { 19021, 32558, 18820, 23749 }, { 32767, 19, 0, 0 }, 10, 34, 988, 0, 2000, 10962, 0, 0, 0 }, { /* articulation 140 */ { 32767, 32349, 18820, 23749 }, { 19021, 634, 0, 0 }, 10, 32, 1008, 0, 1200, 10090, 0, 0, 0 }, { /* articulation 141 */ { 2536, 0, 32767, 27897 }, { 1902, 380, 0, 0 }, 7, 34, 988, 0, 1620, 8933, 0, 0, 0 }, { /* articulation 142 */ { 32767, 32349, 10809, 23749 }, { 32767, 380, 0, 0 }, 7, 34, 988, 0, 2200, 8994, 0, 0, 0 }, { /* articulation 143 */ { 32767, 32663, 15076, 23749 }, { 32767, 1902, 0, 0 }, 10, 34, 982, 0, 2500, 9525, 0, 0, 0 }, { /* articulation 144 */ { 32767, 32663, 15076, 23749 }, { 32767, 190, 0, 0 }, 10, 34, 951, 0, 1500, 11423, 0, 0, 0 }, { /* articulation 145 */ { 32767, 32663, 18820, 23749 }, { 32767, 1902, 0, 0 }, 9, 34, 982, 0, 1500, 9521, 0, 0, 0 }, { /* articulation 146 */ { 3804, 0, 32767, 28809 }, { 32767, 32767, 32767, 0 }, 0, 0, 1521, 0, 0, 9521, 0, 0, 0 }, { /* articulation 147 */ { 32767, 32558, 0, 23749 }, { 32767, 19021, 0, 0 }, 0, 17, 989, 0, 5000, 10223, 0, 0, 0 }, { /* articulation 148 */ { 32767, 32663, 18820, 23749 }, { 32767, 63, 0, 0 }, 10, 34, 951, 0, 1500, 9907, 0, 0, 0 }, { /* articulation 149 */ { 32767, 32698, 11682, 23749 }, { 32767, 1902, 0, 0 }, 0, 34, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 150 */ { 32767, 32072, 0, 32072 }, { 32767, 380, 0, 0 }, 0, 17, 989, 0, 3440, 9260, 0, 0, 0 }, { /* articulation 151 */ { 32767, 30234, 0, 30725 }, { 32767, 1902, 0, 0 }, 0, 17, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 152 */ { 32767, 31730, 0, 30725 }, { 32767, 380, 0, 0 }, 0, 17, 989, 0, 4000, 7823, 0, 0, 0 }, { /* articulation 153 */ { 32767, 32558, 3566, 23749 }, { 783, 32767, 32767, 0 }, 100, 0, 1522, 500, 0, 11877, 0, 0, 0 }, { /* articulation 154 */ { 32767, 32663, 18820, 17213 }, { 32767, 1902, 0, 0 }, 8, 34, 989, -22, 0, 0, 0, 0, 0 }, { /* articulation 155 */ { 19021, 29007, 6784, 23749 }, { 32767, 1902, 0, 0 }, 0, 34, 951, 0, 5000, 9521, 1, 0, 0 }, { /* articulation 156 */ { 32767, 32558, 0, 31935 }, { 1902, 254, 16384, 0 }, 0, 52, 989, 0, 3627, 10547, 0, 5, 0 }, { /* articulation 157 */ { 3804, 0, 32767, 23749 }, { 1902, 1902, 0, 0 }, 0, 34, 989, 27, 0, 11919, 0, 0, 0 }, { /* articulation 158 */ { 32767, 0, 32767, 31730 }, { 76, 66, 10092, 0 }, 5, 0, 989, 0, 8007, 5535, 0, 8, 0 }, { /* articulation 159 */ { 32767, 32468, 0, 29434 }, { 32767, 127, 0, 0 }, 0, 52, 989, 0, 2500, 9032, 0, 0, 0 }, { /* articulation 160 */ { 9511, 32663, 10809, 25329 }, { 32767, 32767, 32767, 0 }, 0, 34, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 161 */ { 19021, 32558, 18820, 23749 }, { 32767, 190, 0, 0 }, 10, 34, 988, 0, 2600, 9513, 0, 0, 0 }, { /* articulation 162 */ { 32767, 32106, 9568, 23749 }, { 2348, 391, 0, 0 }, 10, 52, 980, 0, 6500, 9023, 0, 0, 0 }, { /* articulation 163 */ { 32767, 32558, 0, 26439 }, { 32767, 63, 0, 0 }, 0, 34, 989, 0, 0, 0, 0, 0, 0 }, { /* articulation 164 */ { 32767, 32072, 15076, 17213 }, { 32767, 1268, 0, 0 }, 0, 0, 951, 0, 2000, 10223, 0, 0, 0 }, { /* articulation 165 */ { 32767, 32558, 0, 23749 }, { 32767, 380, 0, 0 }, 0, 34, 989, 0, 3000, 9366, 0, 0, 0 }, { /* articulation 166 */ { 32767, 32663, 18820, 23749 }, { 1902, 127, 10879, 0 }, 0, 0, 989, 0, 6000, 7121, 0, 4, 0 }, { /* articulation 167 */ { 32767, 32505, 0, 26439 }, { 32767, 21, 0, 0 }, 0, 52, 989, 0, 3500, 6236, 0, 5, 0 }, { /* articulation 168 */ { 32767, 32505, 0, 26439 }, { 32767, 190, 0, 0 }, 0, 52, 989, 0, 2800, 7121, 0, 0, 0 }, { /* articulation 169 */ { 32767, 32418, 0, 29434 }, { 32767, 127, 0, 0 }, 0, 52, 989, 0, 2100, 9626, 0, 0, 0 }, { /* articulation 170 */ { 32767, 32349, 0, 30234 }, { 32767, 127, 0, 0 }, 0, 52, 989, 0, 3000, 9626, 0, 0, 0 }, { /* articulation 171 */ { 32767, 32288, 0, 28400 }, { 32767, 127, 0, 0 }, 0, 52, 989, 0, 1000, 9032, 0, 0, 0 }, { /* articulation 172 */ { 32767, 32072, 0, 28809 }, { 32767, 127, 0, 0 }, 0, 52, 989, 0, 1000, 9032, 0, 0, 0 }, { /* articulation 173 */ { 3804, 32072, 15076, 17213 }, { 32767, 1268, 0, 0 }, 0, 52, 991, 0, 0, 11107, 0, 8, 0 }, { /* articulation 174 */ { 32767, 32349, 15076, 23749 }, { 7608, 147, 0, 0 }, 0, 0, 989, 0, 4500, 9521, 0, 8, 0 }, { /* articulation 175 */ { 32767, 32663, 18820, 23749 }, { 32767, 95, 0, 0 }, 0, 0, 989, 0, 2000, 8321, 0, 8, 0 }, { /* articulation 176 */ { 32767, 32715, 128, 29669 }, { 32767, 1729, 0, 0 }, 0, 0, 989, 0, 6000, 7823, 0, 8, 0 }, { /* articulation 177 */ { 19021, 32448, 0, 31882 }, { 32767, 95, 0, 0 }, 0, 0, 989, 0, 4500, 7121, 0, 8, 0 }, { /* articulation 178 */ { 32767, 32560, 3646, 32107 }, { 32767, 190, 0, 0 }, 0, 0, 989, 0, 4000, 8321, 0, 8, 0 }, { /* articulation 179 */ { 32767, 32602, 13644, 26439 }, { 32767, 63, 0, 0 }, 12, 34, 988, 0, 2000, 11107, 0, 0, 0 }, { /* articulation 180 */ { 19021, 30484, 0, 23749 }, { 32767, 1902, 0, 0 }, 0, 0, 989, 0, 5000, 8321, 1, 0, 0 }, { /* articulation 181 */ { 261, 32466, 0, 31938 }, { 32767, 634, 0, 0 }, 0, 34, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 182 */ { 32767, 32418, 0, 31742 }, { 2348, 39, 0, 0 }, 0, 34, 989, 0, 3600, 7121, 0, 4, 0 }, { /* articulation 183 */ { 32767, 32090, 0, 32090 }, { 32767, 634, 0, 0 }, 0, 34, 951, 0, 0, 0, 0, 0, 0 }, { /* articulation 184 */ { 1669, 32715, 19242, 30194 }, { 32767, 296, 0, 0 }, 0, 0, 1555, 0, 3000, 9907, 0, 4, 0 } }; /*end Articulations */ /*---------------------------------------------------------------------------- * Regions *---------------------------------------------------------------------------- */ const S_WT_REGION eas_regions[] = { { { 0, 27, 27 }, -2868, 16422, 0, 0, 81, 0 }, /* region 0 */ { { 0, 28, 28 }, -3568, 32767, 0, 0, 40, 0 }, /* region 1 */ { { 0, 29, 29 }, -4553, 32767, 0, 0, 32, 1 }, /* region 2 */ { { 0, 30, 30 }, -4853, 32767, 0, 0, 32, 2 }, /* region 3 */ { { 0, 31, 31 }, -3868, 23197, 0, 0, 48, 3 }, /* region 4 */ { { 1536, 32, 32 }, -3200, 20675, 0, 0, 137, 4 }, /* region 5 */ { { 1537, 33, 33 }, -3703, 20675, 792, 879, 50, 5 }, /* region 6 */ { { 1537, 34, 34 }, -3803, 16422, 792, 879, 50, 6 }, /* region 7 */ { { 0, 35, 35 }, -4968, 32767, 0, 0, 83, 7 }, /* region 8 */ { { 0, 36, 36 }, -4968, 32767, 0, 0, 83, 7 }, /* region 9 */ { { 0, 37, 37 }, -4051, 18426, 0, 0, 53, 8 }, /* region 10 */ { { 0, 38, 38 }, -4151, 23197, 0, 0, 16, 9 }, /* region 11 */ { { 0, 39, 39 }, -3568, 32767, 0, 0, 40, 10 }, /* region 12 */ { { 0, 40, 40 }, -4151, 23197, 0, 0, 16, 4 }, /* region 13 */ { { 1, 41, 41 }, -5855, 26028, 798, 993, 45, 11 }, /* region 14 */ { { 257, 42, 42 }, -4200, 26028, 4288, 7488, 7, 12 }, /* region 15 */ { { 1, 43, 43 }, -5755, 26028, 798, 993, 45, 13 }, /* region 16 */ { { 257, 44, 44 }, -4400, 26028, 4288, 7488, 7, 14 }, /* region 17 */ { { 1, 45, 45 }, -5755, 26028, 798, 993, 45, 15 }, /* region 18 */ { { 257, 46, 46 }, -4600, 26028, 4288, 7488, 7, 16 }, /* region 19 */ { { 1, 47, 47 }, -5455, 26028, 798, 993, 45, 17 }, /* region 20 */ { { 1, 48, 48 }, -5355, 26028, 798, 993, 45, 18 }, /* region 21 */ { { 1, 49, 49 }, -5200, 16422, 1294, 5778, 8, 19 }, /* region 22 */ { { 1, 50, 50 }, -5255, 26028, 798, 993, 45, 20 }, /* region 23 */ { { 1, 51, 51 }, -5268, 16422, 6592, 9921, 6, 21 }, /* region 24 */ { { 1, 52, 52 }, -5600, 32767, 1294, 5778, 8, 22 }, /* region 25 */ { { 1, 53, 53 }, -5418, 14636, 6592, 9921, 6, 23 }, /* region 26 */ { { 0, 54, 54 }, -5751, 26028, 0, 0, 39, 24 }, /* region 27 */ { { 1, 55, 55 }, -5300, 32767, 1294, 5778, 8, 25 }, /* region 28 */ { { 0, 56, 56 }, -7255, 32767, 0, 0, 90, 26 }, /* region 29 */ { { 1, 57, 57 }, -5700, 32767, 1294, 5778, 8, 27 }, /* region 30 */ { { 1, 58, 58 }, -7053, 23197, 0, 166, 113, 28 }, /* region 31 */ { { 1, 59, 59 }, -5968, 16422, 6592, 9921, 6, 29 }, /* region 32 */ { { 1, 60, 60 }, -6453, 23197, 432, 582, 63, 30 }, /* region 33 */ { { 1, 61, 61 }, -6853, 16422, 432, 582, 63, 30 }, /* region 34 */ { { 1, 62, 62 }, -7253, 20675, 432, 582, 63, 31 }, /* region 35 */ { { 1, 63, 63 }, -7353, 23197, 432, 582, 63, 32 }, /* region 36 */ { { 1, 64, 64 }, -7953, 23197, 432, 582, 63, 33 }, /* region 37 */ { { 0, 65, 65 }, -7555, 32767, 0, 0, 14, 34 }, /* region 38 */ { { 0, 66, 66 }, -7955, 20675, 0, 0, 14, 34 }, /* region 39 */ { { 512, 67, 67 }, -7155, 18426, 0, 0, 90, 35 }, /* region 40 */ { { 512, 68, 68 }, -7755, 18426, 0, 0, 90, 35 }, /* region 41 */ { { 0, 69, 69 }, -7755, 32767, 0, 0, 86, 36 }, /* region 42 */ { { 0, 70, 70 }, -6855, 21900, 0, 0, 86, 37 }, /* region 43 */ { { 769, 71, 71 }, -6355, 23197, 0, 1226, 35, 38 }, /* region 44 */ { { 769, 72, 72 }, -6955, 26028, 0, 1226, 35, 38 }, /* region 45 */ { { 1024, 73, 73 }, -7955, 32767, 0, 0, 22, 39 }, /* region 46 */ { { 1024, 74, 74 }, -8455, 32767, 0, 0, 22, 40 }, /* region 47 */ { { 1, 75, 75 }, -7900, 23197, 0, 31, 139, 41 }, /* region 48 */ { { 0, 76, 76 }, -10455, 23197, 0, 0, 134, 42 }, /* region 49 */ { { 0, 77, 77 }, -10055, 23197, 0, 0, 134, 43 }, /* region 50 */ { { 0, 78, 78 }, -8853, 16422, 0, 0, 89, 44 }, /* region 51 */ { { 0, 79, 79 }, -10253, 16422, 0, 0, 89, 45 }, /* region 52 */ { { 1281, 80, 80 }, -6300, 13045, 209, 230, 103, 46 }, /* region 53 */ { { 1281, 81, 81 }, -6400, 16422, 209, 230, 103, 47 }, /* region 54 */ { { 0, 82, 82 }, -8455, 20675, 0, 0, 87, 48 }, /* region 55 */ { { 0, 83, 83 }, -8900, 32767, 0, 0, 13, 49 }, /* region 56 */ { { 1, 84, 84 }, -8400, 23197, 0, 10294, 5, 50 }, /* region 57 */ { { 0, 85, 85 }, -9655, 32767, 0, 0, 135, 4 }, /* region 58 */ { { 0, 86, 86 }, -9068, 16422, 0, 0, 24, 51 }, /* region 59 */ { { 32769, 87, 87 }, -9168, 32767, 1335, 1603, 24, 52 }, /* region 60 */ { { 1, 12, 67 }, -6605, 23197, 437, 16584, 2, 48 }, /* region 61 */ { { 1, 68, 73 }, -7196, 23197, 452, 16803, 0, 48 }, /* region 62 */ { { 32769, 74, 108 }, -8467, 23197, 404, 16698, 1, 48 }, /* region 63 */ { { 1, 12, 78 }, -6605, 16422, 437, 16584, 2, 48 }, /* region 64 */ { { 1, 79, 91 }, -7196, 16422, 452, 16803, 0, 48 }, /* region 65 */ { { 32769, 92, 108 }, -8467, 16422, 404, 16698, 1, 48 }, /* region 66 */ { { 1, 12, 78 }, -6605, 16422, 437, 16584, 2, 48 }, /* region 67 */ { { 1, 79, 91 }, -7196, 16422, 452, 16803, 0, 48 }, /* region 68 */ { { 32769, 92, 108 }, -8467, 16422, 404, 16698, 1, 48 }, /* region 69 */ { { 1, 12, 70 }, -6600, 23197, 437, 16584, 2, 48 }, /* region 70 */ { { 1, 71, 88 }, -7191, 23197, 452, 16803, 0, 48 }, /* region 71 */ { { 32769, 89, 108 }, -8462, 23197, 404, 16698, 1, 48 }, /* region 72 */ { { 1, 12, 54 }, -5956, 13045, 639, 4368, 10, 48 }, /* region 73 */ { { 32769, 55, 108 }, -6351, 18426, 702, 3112, 12, 48 }, /* region 74 */ { { 1, 12, 66 }, -6611, 23197, 437, 16584, 2, 48 }, /* region 75 */ { { 1, 67, 87 }, -7202, 23197, 452, 16803, 0, 48 }, /* region 76 */ { { 32769, 88, 108 }, -8473, 16422, 404, 16698, 1, 48 }, /* region 77 */ { { 1, 12, 43 }, -3055, 23197, 920, 1383, 30, 59 }, /* region 78 */ { { 32769, 44, 96 }, -5060, 18426, 885, 1176, 37, 59 }, /* region 79 */ { { 1, 12, 48 }, -3461, 18426, 1148, 1514, 26, 60 }, /* region 80 */ { { 32769, 49, 96 }, -6253, 16422, 1347, 1420, 29, 60 }, /* region 81 */ { { 1, 33, 56 }, -5600, 26028, 1064, 1170, 38, 61 }, /* region 82 */ { { 1, 57, 72 }, -6000, 26028, 930, 1014, 44, 61 }, /* region 83 */ { { 32769, 73, 108 }, -7600, 26028, 726, 826, 52, 61 }, /* region 84 */ { { 1, 36, 96 }, -7600, 20675, 635, 735, 58, 62 }, /* region 85 */ { { 32769, 97, 108 }, -10108, 13045, 0, 31, 139, 62 }, /* region 86 */ { { 1, 36, 96 }, -7600, 14636, 635, 735, 58, 0 }, /* region 87 */ { { 32769, 97, 108 }, -10108, 13045, 0, 31, 139, 0 }, /* region 88 */ { { 1, 36, 83 }, -6006, 13045, 838, 922, 47, 63 }, /* region 89 */ { { 1, 84, 93 }, -8406, 14636, 209, 230, 103, 63 }, /* region 90 */ { { 32769, 94, 108 }, -10108, 13045, 0, 31, 139, 63 }, /* region 91 */ { { 1, 36, 83 }, -6006, 13045, 838, 922, 47, 64 }, /* region 92 */ { { 1, 84, 93 }, -8406, 13045, 209, 230, 103, 64 }, /* region 93 */ { { 32769, 94, 108 }, -10108, 13045, 0, 31, 139, 64 }, /* region 94 */ { { 1, 21, 56 }, -5595, 23197, 1064, 1170, 38, 65 }, /* region 95 */ { { 1, 57, 72 }, -5995, 23197, 930, 1014, 44, 65 }, /* region 96 */ { { 32769, 73, 108 }, -7598, 23197, 726, 826, 52, 65 }, /* region 97 */ { { 1, 12, 83 }, -6006, 16422, 838, 922, 47, 66 }, /* region 98 */ { { 1, 84, 93 }, -8406, 16422, 209, 230, 103, 66 }, /* region 99 */ { { 32769, 94, 108 }, -10108, 16422, 0, 31, 139, 66 }, /* region 100 */ { { 1, 24, 83 }, -6006, 16422, 838, 922, 47, 67 }, /* region 101 */ { { 1, 84, 93 }, -8406, 16422, 209, 230, 103, 67 }, /* region 102 */ { { 32769, 94, 108 }, -10108, 16422, 0, 31, 139, 67 }, /* region 103 */ { { 1, 12, 83 }, -6020, 16422, 0, 83, 126, 68 }, /* region 104 */ { { 1, 84, 90 }, -8482, 16422, 0, 20, 145, 68 }, /* region 105 */ { { 32769, 91, 108 }, -9101, 16422, 6, 20, 147, 68 }, /* region 106 */ { { 1, 21, 75 }, -7241, 16422, 419, 460, 76, 69 }, /* region 107 */ { { 32769, 76, 108 }, -9690, 14636, 254, 264, 101, 69 }, /* region 108 */ { { 32769, 36, 84 }, -7755, 16422, 0, 2775, 17, 70 }, /* region 109 */ { { 32769, 12, 108 }, -6655, 23197, 30, 276, 100, 71 }, /* region 110 */ { { 0, 12, 60 }, -7914, 26028, 0, 0, 15, 72 }, /* region 111 */ { { 32768, 61, 96 }, -7914, 26028, 0, 0, 15, 73 }, /* region 112 */ { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 74 }, /* region 113 */ { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 74 }, /* region 114 */ { { 1, 12, 35 }, -5355, 16422, 2869, 3778, 11, 75 }, /* region 115 */ { { 1, 36, 48 }, -6555, 20675, 2869, 3778, 11, 75 }, /* region 116 */ { { 32769, 49, 72 }, -6555, 20675, 2869, 3778, 11, 76 }, /* region 117 */ { { 1, 16, 55 }, -6224, 20675, 1045, 1119, 41, 77 }, /* region 118 */ { { 32769, 56, 96 }, -6718, 20675, 907, 963, 46, 77 }, /* region 119 */ { { 1, 16, 53 }, -5994, 29204, 1140, 1479, 27, 78 }, /* region 120 */ { { 1, 54, 70 }, -7171, 29204, 726, 812, 55, 78 }, /* region 121 */ { { 32769, 71, 108 }, -7788, 29204, 718, 748, 56, 78 }, /* region 122 */ { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 79 }, /* region 123 */ { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 79 }, /* region 124 */ { { 1, 16, 54 }, -5727, 20675, 5362, 5461, 9, 80 }, /* region 125 */ { { 1, 55, 63 }, -5851, 26028, 1362, 1454, 28, 80 }, /* region 126 */ { { 32769, 64, 108 }, -6744, 16422, 311, 366, 88, 80 }, /* region 127 */ { { 1, 16, 48 }, -4798, 20675, 1132, 1301, 31, 81 }, /* region 128 */ { { 32769, 49, 108 }, -5988, 20675, 1099, 1184, 36, 81 }, /* region 129 */ { { 1, 21, 68 }, -8458, 20675, 87, 2170, 18, 82 }, /* region 130 */ { { 1, 69, 82 }, -8960, 20675, 120, 2167, 19, 82 }, /* region 131 */ { { 32769, 83, 108 }, -10160, 20675, 376, 2041, 20, 82 }, /* region 132 */ { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 83 }, /* region 133 */ { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 83 }, /* region 134 */ { { 32769, 55, 108 }, -7368, 20675, 0, 477, 75, 84 }, /* region 135 */ { { 32769, 36, 96 }, -6900, 14636, 101, 151, 116, 85 }, /* region 136 */ { { 1, 24, 83 }, -6020, 13045, 0, 83, 126, 86 }, /* region 137 */ { { 1, 84, 90 }, -8482, 13045, 0, 20, 145, 86 }, /* region 138 */ { { 32769, 91, 108 }, -9101, 13045, 6, 20, 147, 86 }, /* region 139 */ { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 87 }, /* region 140 */ { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 87 }, /* region 141 */ { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 88 }, /* region 142 */ { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 88 }, /* region 143 */ { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 89 }, /* region 144 */ { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 89 }, /* region 145 */ { { 1, 24, 83 }, -6020, 13045, 0, 83, 126, 90 }, /* region 146 */ { { 1, 84, 90 }, -8482, 13045, 0, 20, 145, 90 }, /* region 147 */ { { 32769, 91, 108 }, -9101, 13045, 6, 20, 147, 90 }, /* region 148 */ { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 91 }, /* region 149 */ { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 91 }, /* region 150 */ { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 92 }, /* region 151 */ { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 92 }, /* region 152 */ { { 1, 12, 62 }, -7053, 16422, 23, 10953, 4, 93 }, /* region 153 */ { { 32769, 63, 108 }, -7755, 20675, 11, 11753, 3, 93 }, /* region 154 */ { { 1, 12, 62 }, -7053, 16422, 23, 10953, 4, 94 }, /* region 155 */ { { 32769, 63, 108 }, -7755, 16422, 11, 11753, 3, 94 }, /* region 156 */ { { 1, 24, 79 }, -6020, 13045, 0, 83, 126, 95 }, /* region 157 */ { { 1, 80, 90 }, -8482, 13045, 0, 20, 145, 95 }, /* region 158 */ { { 32769, 91, 108 }, -9101, 13045, 6, 20, 147, 95 }, /* region 159 */ { { 1, 12, 65 }, -7053, 13045, 23, 10953, 4, 96 }, /* region 160 */ { { 32769, 66, 108 }, -7755, 16422, 11, 11753, 3, 96 }, /* region 161 */ { { 32768, 36, 84 }, -7500, 20675, 0, 0, 25, 97 }, /* region 162 */ { { 32769, 36, 96 }, -8855, 20675, 1482, 1613, 23, 98 }, /* region 163 */ { { 32769, 12, 96 }, -4366, 32767, 818, 1033, 42, 99 }, /* region 164 */ { { 32769, 36, 84 }, -8568, 18426, 0, 293, 98, 100 }, /* region 165 */ { { 32769, 12, 96 }, -6020, 26028, 0, 83, 125, 101 }, /* region 166 */ { { 32769, 12, 96 }, -6020, 20675, 0, 83, 125, 102 }, /* region 167 */ { { 1, 12, 83 }, -6020, 13045, 0, 83, 125, 104 }, /* region 168 */ { { 1, 84, 90 }, -8482, 13045, 0, 20, 146, 104 }, /* region 169 */ { { 32769, 91, 108 }, -9101, 13045, 6, 20, 148, 104 }, /* region 170 */ { { 32769, 36, 108 }, -8570, 32767, 472, 491, 74, 105 }, /* region 171 */ { { 32769, 36, 108 }, -8570, 20675, 472, 491, 74, 106 }, /* region 172 */ { { 1, 12, 72 }, -6012, 7336, 2, 86, 124, 107 }, /* region 173 */ { { 1, 73, 101 }, -8500, 8231, 2, 22, 143, 107 }, /* region 174 */ { { 32769, 102, 108 }, -9683, 20675, 173, 183, 110, 107 }, /* region 175 */ { { 1, 21, 96 }, -7768, 13045, 477, 507, 73, 108 }, /* region 176 */ { { 32769, 97, 108 }, -9683, 13045, 173, 183, 110, 109 }, /* region 177 */ { { 32769, 12, 108 }, -7771, 16422, 477, 507, 73, 110 }, /* region 178 */ { { 1, 12, 53 }, -4971, 16422, 388, 541, 68, 111 }, /* region 179 */ { { 32769, 54, 60 }, -5949, 11626, 473, 560, 65, 111 }, /* region 180 */ { { 32769, 36, 72 }, -5949, 16422, 473, 560, 65, 112 }, /* region 181 */ { { 1, 48, 58 }, -7053, 16422, 356, 402, 82, 113 }, /* region 182 */ { { 1, 59, 65 }, -7574, 16422, 514, 548, 67, 113 }, /* region 183 */ { { 1, 66, 78 }, -8174, 16422, 505, 529, 71, 113 }, /* region 184 */ { { 32769, 79, 96 }, -9233, 16422, 178, 191, 109, 113 }, /* region 185 */ { { 1, 55, 60 }, -7053, 16422, 356, 402, 82, 114 }, /* region 186 */ { { 1, 61, 69 }, -7574, 16422, 514, 548, 67, 114 }, /* region 187 */ { { 1, 70, 79 }, -8174, 16422, 505, 529, 71, 114 }, /* region 188 */ { { 32769, 80, 108 }, -9233, 16422, 178, 191, 109, 114 }, /* region 189 */ { { 1, 16, 82 }, -8029, 23197, 180, 206, 106, 115 }, /* region 190 */ { { 32769, 83, 108 }, -7240, 18426, 3, 44, 131, 115 }, /* region 191 */ { { 32769, 21, 108 }, -8869, 20675, 483, 515, 72, 116 }, /* region 192 */ { { 1, 21, 89 }, -7205, 18426, 3, 45, 130, 117 }, /* region 193 */ { { 32769, 90, 108 }, -9101, 10362, 6, 20, 148, 117 }, /* region 194 */ { { 1, 21, 42 }, -4686, 20675, 0, 180, 111, 118 }, /* region 195 */ { { 1, 43, 51 }, -5286, 23197, 0, 127, 120, 118 }, /* region 196 */ { { 1, 52, 58 }, -6292, 26028, 0, 71, 127, 118 }, /* region 197 */ { { 1, 59, 68 }, -7468, 23197, 0, 36, 136, 118 }, /* region 198 */ { { 32769, 69, 108 }, -8574, 20675, 0, 19, 149, 118 }, /* region 199 */ { { 1, 21, 89 }, -7199, 20675, 3, 45, 130, 119 }, /* region 200 */ { { 32769, 90, 108 }, -9101, 14636, 6, 20, 148, 119 }, /* region 201 */ { { 1, 21, 46 }, -5651, 26028, 236, 340, 92, 120 }, /* region 202 */ { { 1, 47, 71 }, -6563, 20675, 824, 885, 49, 120 }, /* region 203 */ { { 1, 72, 88 }, -7907, 18426, 719, 747, 57, 120 }, /* region 204 */ { { 1, 89, 93 }, -8876, 16422, 83, 99, 122, 120 }, /* region 205 */ { { 32769, 94, 108 }, -9689, 16422, 173, 183, 110, 120 }, /* region 206 */ { { 1, 60, 71 }, -7205, 16422, 0, 42, 132, 121 }, /* region 207 */ { { 1, 72, 78 }, -7903, 16422, 0, 28, 141, 121 }, /* region 208 */ { { 32769, 79, 96 }, -8405, 16422, 0, 21, 144, 121 }, /* region 209 */ { { 1, 48, 65 }, -6316, 11626, 0, 70, 128, 122 }, /* region 210 */ { { 1, 66, 79 }, -7724, 14636, 0, 31, 138, 122 }, /* region 211 */ { { 32769, 80, 96 }, -8030, 11626, 0, 26, 142, 122 }, /* region 212 */ { { 1, 16, 44 }, -5868, 14636, 163, 254, 102, 123 }, /* region 213 */ { { 1, 45, 51 }, -6418, 16422, 261, 393, 85, 123 }, /* region 214 */ { { 1, 52, 58 }, -7333, 18426, 190, 229, 104, 123 }, /* region 215 */ { { 1, 59, 66 }, -8100, 18426, 168, 193, 108, 123 }, /* region 216 */ { { 1, 67, 70 }, -8576, 18426, 138, 157, 115, 123 }, /* region 217 */ { { 1, 71, 80 }, -9103, 18426, 166, 180, 112, 123 }, /* region 218 */ { { 32769, 81, 108 }, -10074, 18426, 135, 151, 117, 123 }, /* region 219 */ { { 32769, 12, 96 }, -5004, 23197, 570, 719, 59, 124 }, /* region 220 */ { { 1, 12, 48 }, -5868, 14636, 163, 254, 102, 125 }, /* region 221 */ { { 1, 49, 54 }, -6418, 16422, 261, 393, 85, 125 }, /* region 222 */ { { 1, 55, 63 }, -7333, 18426, 190, 229, 104, 125 }, /* region 223 */ { { 1, 64, 70 }, -8100, 18426, 168, 193, 108, 125 }, /* region 224 */ { { 1, 71, 75 }, -8576, 18426, 138, 157, 115, 125 }, /* region 225 */ { { 1, 76, 82 }, -9103, 18426, 166, 180, 112, 125 }, /* region 226 */ { { 32769, 83, 108 }, -10074, 18426, 135, 151, 117, 125 }, /* region 227 */ { { 32770, 36, 84 }, -7200, 29204, 0, 0, 0, 126 }, /* region 228 */ { { 32770, 36, 84 }, -7600, 8231, 0, 0, 0, 127 }, /* region 229 */ { { 32770, 36, 84 }, -7200, 20675, 0, 0, 0, 128 }, /* region 230 */ { { 32769, 36, 84 }, -6000, -24285, 1294, 5778, 8, 129 }, /* region 231 */ { { 32769, 36, 84 }, -6555, 29204, 798, 993, 45, 130 }, /* region 232 */ { { 32769, 36, 84 }, -6855, 20675, 798, 993, 45, 131 }, /* region 233 */ { { 32769, 36, 84 }, -7755, 29204, 798, 993, 45, 132 }, /* region 234 */ { { 32768, 36, 84 }, -8155, 32767, 0, 0, 133, 133 }, /* region 235 */ { { 32768, 36, 84 }, -6555, 20675, 0, 0, 91, 134 }, /* region 236 */ { { 1, 24, 62 }, -7000, 23197, 286, 333, 94, 135 }, /* region 237 */ { { 1, 63, 66 }, -7364, 26028, 297, 335, 93, 135 }, /* region 238 */ { { 1, 67, 72 }, -7722, 23197, 368, 399, 84, 135 }, /* region 239 */ { { 32769, 73, 96 }, -8310, 23197, 116, 138, 119, 135 }, /* region 240 */ { { 1, 24, 48 }, -5141, 23197, 309, 447, 77, 136 }, /* region 241 */ { { 1, 49, 56 }, -6266, 26028, 211, 283, 99, 136 }, /* region 242 */ { { 1, 57, 63 }, -7000, 26028, 286, 333, 94, 136 }, /* region 243 */ { { 32769, 64, 84 }, -7722, 23197, 368, 399, 84, 136 }, /* region 244 */ { { 1, 24, 56 }, -6266, 29204, 211, 283, 99, 137 }, /* region 245 */ { { 1, 57, 63 }, -7000, 29204, 286, 333, 94, 137 }, /* region 246 */ { { 1, 64, 69 }, -7722, 29204, 368, 399, 84, 137 }, /* region 247 */ { { 32769, 70, 96 }, -8310, 29204, 116, 138, 119, 137 }, /* region 248 */ { { 1, 24, 68 }, -7722, 18426, 368, 399, 84, 138 }, /* region 249 */ { { 1, 69, 76 }, -8310, 26028, 116, 138, 119, 138 }, /* region 250 */ { { 32769, 77, 108 }, -8758, 23197, 127, 144, 118, 138 }, /* region 251 */ { { 1, 24, 82 }, -7613, 23197, 389, 422, 80, 139 }, /* region 252 */ { { 32769, 83, 108 }, -8764, 26028, 146, 163, 114, 139 }, /* region 253 */ { { 1, 12, 58 }, -6898, 29204, 386, 436, 78, 140 }, /* region 254 */ { { 32769, 59, 96 }, -7371, 26028, 290, 328, 95, 140 }, /* region 255 */ { { 1, 12, 58 }, -6898, 16422, 386, 436, 78, 141 }, /* region 256 */ { { 32769, 59, 96 }, -7371, 18426, 290, 328, 95, 141 }, /* region 257 */ { { 1, 12, 48 }, -6898, -28771, 386, 436, 78, 142 }, /* region 258 */ { { 32769, 49, 84 }, -7371, 29204, 290, 328, 95, 142 }, /* region 259 */ { { 1, 12, 60 }, -5453, 20675, 314, 430, 79, 143 }, /* region 260 */ { { 32769, 61, 84 }, -6553, 18426, 263, 324, 96, 143 }, /* region 261 */ { { 1, 24, 60 }, -6553, 16422, 263, 324, 96, 144 }, /* region 262 */ { { 1, 61, 70 }, -7669, 20675, 279, 311, 97, 144 }, /* region 263 */ { { 32769, 71, 96 }, -8098, 23197, 179, 204, 107, 144 }, /* region 264 */ { { 1, 24, 84 }, -8483, 20675, 191, 211, 105, 145 }, /* region 265 */ { { 32769, 85, 108 }, -9683, 20675, 92, 102, 121, 145 }, /* region 266 */ { { 1, 21, 69 }, -6553, 13045, 263, 324, 96, 146 }, /* region 267 */ { { 1, 70, 94 }, -7669, 20675, 279, 311, 97, 146 }, /* region 268 */ { { 1, 95, 96 }, -8098, -24285, 179, 204, 107, 146 }, /* region 269 */ { { 32769, 97, 108 }, -9683, -24285, 173, 183, 110, 146 }, /* region 270 */ { { 1, 16, 55 }, -8100, 20675, 168, 193, 108, 147 }, /* region 271 */ { { 1, 56, 74 }, -8576, 26028, 138, 157, 115, 147 }, /* region 272 */ { { 32769, 75, 96 }, -10074, 26028, 135, 151, 117, 147 }, /* region 273 */ { { 1, 24, 72 }, -8098, 26028, 179, 204, 107, 148 }, /* region 274 */ { { 1, 73, 85 }, -8483, 20675, 191, 211, 105, 148 }, /* region 275 */ { { 32769, 86, 108 }, -9683, 18426, 92, 102, 121, 148 }, /* region 276 */ { { 32769, 36, 108 }, -7730, 18426, 1839, 1901, 21, 149 }, /* region 277 */ { { 32769, 24, 108 }, -7273, 20675, 494, 534, 69, 150 }, /* region 278 */ { { 32769, 12, 108 }, -7273, 20675, 494, 534, 69, 151 }, /* region 279 */ { { 32769, 24, 108 }, -7273, 20675, 494, 534, 69, 152 }, /* region 280 */ { { 1, 36, 60 }, -4900, 5193, 2, 22, 143, 153 }, /* region 281 */ { { 32769, 61, 84 }, -6083, 20675, 173, 183, 110, 153 }, /* region 282 */ { { 32769, 24, 96 }, -6553, 14636, 263, 324, 96, 154 }, /* region 283 */ { { 32769, 36, 96 }, -7730, 26028, 1839, 1901, 21, 155 }, /* region 284 */ { { 32769, 24, 108 }, -7273, 20675, 494, 534, 69, 156 }, /* region 285 */ { { 1, 24, 58 }, -7851, 14636, 0, 29, 140, 157 }, /* region 286 */ { { 32769, 59, 96 }, -7851, 14636, 0, 29, 140, 157 }, /* region 287 */ { { 1, 12, 83 }, -6020, 13045, 0, 83, 125, 158 }, /* region 288 */ { { 1, 84, 90 }, -8482, 13045, 0, 20, 146, 158 }, /* region 289 */ { { 32769, 91, 108 }, -9101, 13045, 6, 20, 148, 158 }, /* region 290 */ { { 1, 21, 42 }, -4663, 26028, 1047, 1229, 34, 159 }, /* region 291 */ { { 1, 43, 48 }, -5456, 29204, 1138, 1253, 33, 159 }, /* region 292 */ { { 1, 49, 53 }, -5845, 26028, 559, 651, 60, 159 }, /* region 293 */ { { 1, 54, 60 }, -6732, 26028, 508, 563, 64, 159 }, /* region 294 */ { { 1, 61, 65 }, -7080, 32767, 819, 864, 51, 159 }, /* region 295 */ { { 1, 66, 70 }, -6866, 26942, 981, 1032, 43, 159 }, /* region 296 */ { { 1, 71, 76 }, -8166, 26028, 790, 814, 54, 159 }, /* region 297 */ { { 1, 77, 82 }, -8766, 26028, 592, 609, 61, 159 }, /* region 298 */ { { 1, 83, 87 }, -9517, 23197, 543, 554, 66, 159 }, /* region 299 */ { { 1, 88, 96 }, -10071, 18426, 601, 609, 62, 159 }, /* region 300 */ { { 32769, 97, 108 }, -10566, 18426, 523, 529, 70, 159 }, /* region 301 */ { { 1, 48, 69 }, -6313, 14636, 0, 70, 128, 160 }, /* region 302 */ { { 1, 70, 79 }, -7724, 18426, 0, 31, 138, 160 }, /* region 303 */ { { 32769, 80, 96 }, -8030, 14636, 0, 26, 142, 160 }, /* region 304 */ { { 1, 36, 72 }, -7134, 29204, 0, 87, 123, 161 }, /* region 305 */ { { 32769, 73, 96 }, -7960, 29204, 0, 54, 129, 161 }, /* region 306 */ { { 32769, 36, 96 }, -7730, 26028, 1839, 1901, 21, 162 }, /* region 307 */ { { 32769, 12, 96 }, -4372, 32767, 818, 1033, 42, 163 }, /* region 308 */ { { 32769, 36, 108 }, -8570, 26028, 472, 491, 74, 164 }, /* region 309 */ { { 32769, 12, 96 }, -5004, 29204, 570, 719, 59, 165 }, /* region 310 */ { { 1, 12, 83 }, -6020, 13045, 0, 83, 125, 166 }, /* region 311 */ { { 1, 84, 90 }, -8482, 13045, 0, 20, 146, 166 }, /* region 312 */ { { 32769, 91, 108 }, -9101, 13045, 6, 20, 148, 166 }, /* region 313 */ { { 1, 21, 46 }, -5651, 32767, 236, 340, 92, 167 }, /* region 314 */ { { 1, 47, 75 }, -6563, 26028, 824, 885, 49, 167 }, /* region 315 */ { { 1, 76, 84 }, -7907, 23197, 719, 747, 57, 167 }, /* region 316 */ { { 1, 85, 93 }, -8876, 20675, 83, 99, 122, 167 }, /* region 317 */ { { 32769, 94, 108 }, -9689, 20675, 173, 183, 110, 167 }, /* region 318 */ { { 1, 21, 46 }, -5651, 26028, 236, 340, 92, 168 }, /* region 319 */ { { 1, 47, 71 }, -6563, 20675, 824, 885, 49, 168 }, /* region 320 */ { { 1, 72, 88 }, -7907, 18426, 719, 747, 57, 168 }, /* region 321 */ { { 1, 89, 93 }, -8876, 16422, 83, 99, 122, 168 }, /* region 322 */ { { 32769, 94, 108 }, -9689, 16422, 173, 183, 110, 168 }, /* region 323 */ { { 1, 21, 45 }, -4663, 26028, 1047, 1229, 34, 169 }, /* region 324 */ { { 1, 46, 51 }, -5456, 29204, 1138, 1253, 33, 169 }, /* region 325 */ { { 1, 52, 54 }, -5845, 26028, 559, 651, 60, 169 }, /* region 326 */ { { 1, 55, 63 }, -6732, 26028, 508, 563, 64, 169 }, /* region 327 */ { { 1, 64, 68 }, -7080, 32767, 819, 864, 51, 169 }, /* region 328 */ { { 1, 69, 73 }, -6866, 26942, 981, 1032, 43, 169 }, /* region 329 */ { { 1, 74, 79 }, -8166, 26028, 790, 814, 54, 169 }, /* region 330 */ { { 1, 80, 88 }, -8766, 23197, 592, 609, 61, 169 }, /* region 331 */ { { 1, 89, 99 }, -10071, 18426, 601, 609, 62, 169 }, /* region 332 */ { { 32769, 100, 108 }, -10566, 18426, 523, 529, 70, 169 }, /* region 333 */ { { 1, 21, 45 }, -4663, 26028, 1047, 1229, 34, 170 }, /* region 334 */ { { 1, 46, 51 }, -5456, 29204, 1138, 1253, 33, 170 }, /* region 335 */ { { 1, 52, 54 }, -5845, 26028, 559, 651, 60, 170 }, /* region 336 */ { { 1, 55, 63 }, -6732, 26028, 508, 563, 64, 170 }, /* region 337 */ { { 1, 64, 68 }, -7080, 32767, 819, 864, 51, 170 }, /* region 338 */ { { 1, 69, 73 }, -6866, 26942, 981, 1032, 43, 170 }, /* region 339 */ { { 1, 74, 79 }, -8166, 26028, 790, 814, 54, 170 }, /* region 340 */ { { 1, 80, 88 }, -8766, 23197, 592, 609, 61, 170 }, /* region 341 */ { { 1, 89, 99 }, -10071, 18426, 601, 609, 62, 171 }, /* region 342 */ { { 32769, 100, 108 }, -10566, 18426, 523, 529, 70, 172 }, /* region 343 */ { { 32769, 36, 108 }, -8570, 20675, 472, 491, 74, 173 }, /* region 344 */ { { 32769, 12, 108 }, -7730, 20675, 1839, 1901, 21, 174 }, /* region 345 */ { { 1, 12, 44 }, -5868, 18426, 163, 254, 102, 175 }, /* region 346 */ { { 1, 45, 51 }, -6418, 20675, 261, 393, 85, 175 }, /* region 347 */ { { 1, 52, 58 }, -7333, 23197, 190, 229, 104, 175 }, /* region 348 */ { { 1, 59, 66 }, -8100, 23197, 168, 193, 108, 175 }, /* region 349 */ { { 1, 67, 70 }, -8576, 23197, 138, 157, 115, 175 }, /* region 350 */ { { 1, 71, 80 }, -9103, 23197, 166, 180, 112, 175 }, /* region 351 */ { { 32769, 81, 108 }, -10074, 23197, 135, 151, 117, 175 }, /* region 352 */ { { 1, 12, 65 }, -7053, 16422, 23, 10953, 4, 176 }, /* region 353 */ { { 32769, 66, 108 }, -7755, 20675, 11, 11753, 3, 176 }, /* region 354 */ { { 1, 12, 48 }, -4798, 29204, 1132, 1301, 31, 177 }, /* region 355 */ { { 32769, 49, 108 }, -5988, 29204, 1099, 1184, 36, 177 }, /* region 356 */ { { 1, 12, 83 }, -7241, 20675, 419, 460, 76, 178 }, /* region 357 */ { { 32769, 84, 108 }, -10123, 20675, 0, 31, 139, 178 }, /* region 358 */ { { 1, 55, 60 }, -7053, 18426, 356, 402, 82, 179 }, /* region 359 */ { { 1, 61, 69 }, -7574, 18426, 514, 548, 67, 179 }, /* region 360 */ { { 1, 70, 79 }, -8174, 18426, 505, 529, 71, 179 }, /* region 361 */ { { 32769, 80, 108 }, -9233, 23197, 178, 191, 109, 179 }, /* region 362 */ { { 32769, 36, 96 }, -7730, -24285, 1839, 1901, 21, 180 }, /* region 363 */ { { 1, 12, 83 }, -6006, 16422, 838, 922, 47, 181 }, /* region 364 */ { { 1, 84, 93 }, -8406, 18426, 209, 230, 103, 181 }, /* region 365 */ { { 32769, 94, 108 }, -10108, 16422, 0, 31, 139, 181 }, /* region 366 */ { { 1, 12, 56 }, -5595, 23197, 1064, 1170, 38, 182 }, /* region 367 */ { { 1, 57, 72 }, -5995, 23197, 930, 1014, 44, 182 }, /* region 368 */ { { 32769, 73, 108 }, -7598, 23197, 726, 826, 52, 182 }, /* region 369 */ { { 32769, 24, 108 }, -7600, 23197, 635, 735, 58, 62 }, /* region 370 */ { { 1, 36, 83 }, -6006, 13045, 838, 922, 47, 183 }, /* region 371 */ { { 1, 84, 93 }, -8406, 13045, 209, 230, 103, 183 }, /* region 372 */ { { 32769, 94, 108 }, -10108, 13045, 0, 31, 139, 183 }, /* region 373 */ { { 1, 12, 66 }, -6611, 23197, 437, 16584, 2, 184 }, /* region 374 */ { { 1, 67, 87 }, -7202, 23197, 452, 16803, 0, 184 }, /* region 375 */ { { 32769, 88, 108 }, -8473, 16422, 404, 16698, 1, 184 } /* region 376 */ }; /* end Regions */ /*---------------------------------------------------------------------------- * Programs *---------------------------------------------------------------------------- */ const S_PROGRAM eas_programs[] = { { 7864320, 0 } /* program 0 */ }; /* end Programs */ /*---------------------------------------------------------------------------- * Banks *---------------------------------------------------------------------------- */ const S_BANK eas_banks[] = { { /* bank 0 */ 30976, { 291, 324, 314, 334, 202, 319, 95, 195, 107, 92, 371, 89, 87, 85, 135, 82, 200, 192, 130, 267, 193, 302, 207, 210, 128, 125, 190, 120, 118, 213, 221, 271, 80, 78, 308, 164, 220, 310, 166, 167, 186, 182, 181, 179, 160, 178, 176, 115, 155, 153, 151, 149, 75, 73, 374, 111, 252, 254, 258, 305, 256, 157, 146, 137, 249, 237, 245, 241, 274, 262, 260, 265, 172, 171, 309, 277, 284, 307, 136, 344, 173, 168, 345, 353, 346, 70, 110, 311, 357, 144, 104, 67, 364, 367, 64, 288, 142, 140, 98, 355, 133, 123, 61, 113, 285, 280, 279, 278, 370, 286, 359, 283, 101, 236, 163, 235, 234, 233, 232, 231, 162, 363, 230, 281, 165, 229, 109, 228 } } }; /* end Banks */ /*---------------------------------------------------------------------------- * Samples *---------------------------------------------------------------------------- */ const EAS_SAMPLE eas_samples[] = { 0, 0, -3, -4, -6, -8, -10, -12, -12, -11, -8, -3, 3, 7, 10, 14, 16, 16, 15, 12, 9, 4, -4, -12, -18, -21, -21, -19, -18, -15, -10, -3, 10, 20, 34, 44, 51, 52, 48, 43, 38, 26, 8, -15, -37, -52, -61, -64, -66, -64, -59, -47, -31, -13, 4, 18, 30, 37, 40, 36, 30, 24, 19, 11, -2, -17, -24, -28, -28, -21, -18, -16, -10, -3, 12, 27, 39, 49, 53, 53, 50, 43, 37, 25, 11, -11, -31, -46, -57, -63, -66, -63, -57, -46, -34, -19, -3, 13, 27, 35, 39, 37, 32, 26, 20, 11, 0, -13, -20, -24, -25, -21, -19, -14, -8, -2, 9, 23, 37, 47, 53, 52, 49, 42, 35, 25, 13, -6, -28, -48, -60, -67, -67, -64, -60, -51, -39, -23, -7, 10, 23, 35, 39, 38, 32, 26, 21, 15, 4, -9, -20, -22, -21, -19, -14, -11, -5, 1, 9, 19, 31, 45, 51, 52, 47, 39, 35, 25, 15, -3, -23, -42, -58, -70, -71, -66, -60, -51, -43, -30, -13, 6, 22, 32, 40, 40, 38, 33, 27, 19, 9, -5, -17, -25, -26, -22, -16, -11, -8, -4, 7, 21, 35, 48, 53, 56, 50, 43, 34, 22, 13, -2, -22, -44, -63, -75, -76, -69, -61, -51, -43, -29, -13, 6, 23, 32, 41, 43, 41, 37, 26, 18, 7, -8, -19, -25, -25, -22, -15, -9, -5, 0, 10, 24, 37, 44, 48, 52, 52, 46, 33, 20, 8, -5, -20, -38, -59, -74, -79, -73, -67, -55, -43, -26, -11, 4, 18, 29, 41, 45, 45, 38, 29, 21, 11, -3, -15, -25, -27, -22, -16, -11, -8, 0, 10, 25, 38, 44, 47, 50, 53, 49, 37, 20, 7, -5, -17, -34, -58, -74, -82, -76, -67, -59, -47, -29, -12, 3, 14, 25, 38, 50, 52, 46, 33, 23, 14, 3, -11, -25, -28, -27, -21, -16, -13, -7, 8, 27, 41, 44, 45, 47, 54, 55, 44, 25, 7, -7, -18, -32, -53, -71, -81, -81, -72, -67, -55, -37, -16, 3, 15, 23, 34, 48, 57, 56, 44, 30, 19, 5, -12, -26, -33, -31, -25, -19, -16, -11, 7, 25, 45, 49, 49, 52, 57, 59, 48, 32, 11, -5, -22, -39, -56, -73, -82, -88, -84, -75, -60, -38, -16, 5, 21, 30, 39, 52, 59, 61, 53, 37, 22, 7, -12, -28, -35, -36, -30, -22, -19, -16, -2, 21, 41, 52, 51, 52, 57, 62, 54, 40, 18, -2, -18, -36, -54, -70, -80, -86, -87, -81, -69, -48, -23, 0, 18, 28, 35, 45, 57, 64, 59, 46, 27, 9, -11, -24, -30, -32, -29, -25, -20, -16, -5, 15, 36, 47, 50, 49, 53, 57, 54, 43, 24, 5, -14, -32, -50, -65, -75, -82, -86, -86, -77, -58, -32, -8, 14, 25, 30, 41, 56, 69, 69, 57, 36, 17, -4, -20, -29, -32, -27, -28, -27, -23, -13, 10, 33, 46, 50, 48, 50, 54, 55, 48, 34, 16, -6, -29, -50, -68, -75, -78, -82, -86, -84, -72, -47, -16, 11, 28, 34, 41, 51, 64, 70, 64, 49, 27, 5, -17, -30, -33, -29, -29, -30, -30, -22, -2, 23, 41, 49, 51, 51, 54, 56, 50, 42, 25, 4, -20, -44, -62, -70, -76, -83, -87, -89, -78, -56, -29, 0, 19, 31, 38, 48, 63, 72, 71, 60, 40, 14, -12, -25, -29, -26, -27, -33, -37, -30, -12, 11, 31, 41, 48, 51, 53, 55, 55, 51, 39, 17, -12, -38, -58, -67, -74, -82, -92, -98, -89, -69, -41, -13, 10, 29, 41, 50, 64, 72, 78, 74, 57, 29, 0, -18, -26, -28, -32, -38, -42, -38, -23, -3, 18, 30, 42, 52, 58, 60, 61, 57, 48, 28, 2, -30, -51, -62, -70, -81, -94, -101, -93, -75, -49, -23, -2, 18, 36, 50, 61, 69, 77, 78, 66, 42, 11, -11, -22, -27, -32, -39, -46, -46, -36, -14, 8, 25, 41, 52, 59, 62, 63, 62, 57, 38, 11, -20, -47, -61, -69, -78, -89, -98, -94, -80, -60, -37, -12, 13, 33, 48, 62, 70, 78, 81, 72, 52, 23, 0, -14, -24, -33, -43, -49, -49, -39, -23, -2, 15, 33, 47, 57, 63, 62, 62, 57, 40, 20, -7, -34, -52, -65, -74, -83, -94, -92, -81, -63, -42, -22, 0, 21, 39, 54, 63, 73, 79, 76, 61, 37, 12, -5, -19, -28, -37, -46, -51, -47, -32, -13, 7, 25, 43, 54, 58, 60, 60, 61, 48, 27, 3, -25, -45, -60, -72, -81, -90, -92, -84, -71, -52, -32, -9, 14, 33, 50, 61, 74, 80, 78, 67, 47, 24, 6, -12, -26, -37, -50, -56, -52, -37, -19, -2, 16, 35, 52, 61, 63, 61, 59, 51, 35, 12, -15, -38, -55, -66, -77, -83, -83, -80, -68, -55, -39, -19, 4, 25, 41, 54, 66, 73, 75, 68, 52, 31, 11, -7, -22, -33, -46, -54, -51, -39, -24, -5, 12, 32, 48, 56, 60, 61, 58, 50, 36, 17, -8, -30, -46, -63, -74, -80, -80, -74, -69, -58, -43, -27, -5, 15, 31, 48, 60, 68, 72, 68, 57, 39, 20, 2, -16, -30, -44, -51, -50, -41, -27, -10, 9, 28, 43, 53, 57, 57, 54, 48, 37, 19, -3, -25, -41, -56, -69, -75, -73, -69, -63, -59, -49, -32, -13, 9, 25, 37, 48, 58, 66, 65, 58, 42, 25, 8, -9, -22, -36, -41, -43, -37, -26, -14, 4, 21, 37, 48, 52, 53, 47, 42, 34, 21, 3, -18, -39, -51, -64, -67, -62, -60, -60, -58, -50, -36, -16, 3, 17, 29, 41, 49, 58, 61, 60, 49, 29, 11, -7, -19, -28, -32, -33, -30, -25, -14, 2, 19, 33, 41, 45, 42, 38, 36, 29, 20, 6, -14, -28, -43, -54, -58, -55, -50, -51, -54, -51, -41, -22, -4, 11, 19, 30, 37, 47, 55, 56, 51, 34, 16, 0, -15, -19, -23, -22, -22, -21, -14, 0, 15, 29, 39, 43, 37, 31, 25, 21, 18, 6, -11, -28, -42, -50, -51, -48, -44, -41, -44, -43, -41, -25, -8, 9, 16, 22, 26, 35, 43, 50, 48, 33, 16, -3, -13, -16, -16, -15, -13, -11, -6, 5, 16, 28, 38, 41, 35, 24, 15, 12, 10, 4, -11, -27, -39, -46, -46, -45, -40, -36, -36, -37, -38, -29, -13, 6, 16, 19, 22, 27, 37, 43, 42, 32, 19, 2, -10, -13, -12, -7, -4, -2, 2, 10, 18, 27, 36, 38, 32, 20, 9, 4, -2, -4, -11, -23, -34, -42, -42, -38, -31, -28, -29, -32, -33, -30, -18, 0, 10, 12, 12, 17, 26, 35, 36, 31, 19, 5, -6, -11, -9, -2, 7, 14, 13, 13, 16, 23, 31, 34, 29, 15, -3, -8, -10, -10, -14, -20, -26, -30, -32, -30, -25, -18, -17, -24, -31, -32, -26, -11, 2, 7, 8, 9, 17, 25, 29, 28, 21, 9, -2, -7, -5, 4, 12, 21, 24, 23, 25, 26, 29, 31, 27, 15, -2, -15, -21, -23, -23, -23, -28, -30, -31, -27, -19, -10, -9, -13, -21, -22, -20, -11, -4, -3, -5, -2, 5, 13, 17, 17, 16, 10, 6, 0, 3, 11, 23, 32, 33, 30, 28, 27, 24, 24, 19, 9, -6, -19, -29, -29, -26, -20, -19, -22, -24, -23, -16, -10, -9, -14, -20, -24, -21, -16, -10, -6, -5, 1, 5, 11, 12, 13, 11, 8, 6, 1, 4, 9, 23, 33, 39, 36, 32, 32, 28, 22, 17, 7, -7, -22, -31, -33, -31, -24, -19, -18, -18, -16, -13, -7, -6, -8, -14, -21, -24, -20, -15, -12, -9, -6, 0, 4, 6, 8, 8, 5, 5, 2, 7, 15, 27, 37, 42, 45, 41, 39, 32, 22, 13, 3, -11, -26, -37, -41, -37, -29, -21, -18, -15, -11, -6, -2, -2, -4, -7, -13, -16, -20, -21, -16, -14, -10, -6, -3, -3, 0, 3, 2, 3, 3, 9, 18, 32, 41, 46, 49, 44, 43, 35, 24, 12, 1, -14, -27, -39, -40, -36, -31, -22, -16, -13, -6, -3, -3, -4, -9, -9, -13, -16, -20, -21, -16, -15, -11, -6, -4, -4, -5, -5, -3, -3, 0, 10, 19, 33, 44, 51, 56, 52, 50, 40, 23, 11, -6, -19, -30, -40, -43, -40, -35, -24, -16, -7, 2, 6, 5, 1, -6, -9, -9, -9, -12, -19, -21, -21, -17, -9, -7, -9, -11, -15, -14, -9, -7, 7, 19, 36, 51, 57, 61, 59, 56, 48, 33, 13, -8, -24, -35, -45, -51, -46, -38, -26, -14, -7, 3, 11, 15, 12, 3, -5, -7, -6, -9, -15, -22, -25, -23, -17, -13, -12, -16, -19, -21, -18, -12, 3, 21, 38, 50, 58, 67, 65, 64, 55, 41, 21, -4, -25, -38, -46, -50, -49, -43, -33, -23, -11, 3, 14, 19, 16, 8, 0, -2, -2, 0, -8, -19, -27, -30, -25, -22, -20, -20, -22, -25, -24, -16, 1, 22, 43, 56, 62, 67, 68, 65, 60, 46, 24, -3, -25, -40, -45, -49, -50, -46, -37, -23, -10, 1, 12, 20, 20, 14, 7, 2, 3, 3, -4, -15, -26, -31, -30, -27, -26, -26, -29, -33, -33, -25, -8, 17, 41, 57, 65, 71, 73, 73, 66, 53, 33, 5, -23, -41, -48, -50, -48, -48, -40, -30, -14, 1, 12, 21, 24, 18, 13, 6, 5, 5, 0, -11, -25, -37, -39, -35, -31, -31, -33, -38, -37, -29, -12, 15, 40, 59, 67, 71, 72, 73, 69, 59, 39, 14, -16, -38, -50, -51, -50, -48, -45, -36, -21, -4, 12, 25, 30, 25, 18, 11, 11, 10, 6, -8, -25, -39, -46, -42, -38, -37, -37, -40, -42, -34, -15, 13, 40, 57, 66, 71, 72, 72, 69, 61, 45, 19, -10, -34, -46, -48, -47, -45, -45, -41, -28, -12, 7, 23, 27, 25, 18, 15, 17, 17, 12, 1, -20, -37, -47, -50, -46, -45, -44, -45, -46, -41, -21, 7, 37, 60, 69, 73, 72, 72, 72, 67, 52, 25, -6, -33, -47, -50, -47, -47, -47, -45, -35, -16, 6, 23, 31, 30, 24, 23, 24, 25, 18, 4, -15, -33, -50, -56, -57, -53, -48, -49, -49, -45, -29, 2, 35, 58, 68, 71, 72, 74, 73, 68, 56, 34, 5, -26, -43, -48, -45, -42, -46, -46, -41, -24, 0, 21, 33, 34, 31, 25, 27, 27, 19, 6, -14, -36, -55, -64, -64, -60, -50, -47, -45, -44, -31, -4, 32, 58, 71, 72, 68, 70, 70, 66, 57, 36, 11, -20, -43, -50, -48, -41, -37, -42, -40, -28, -5, 21, 36, 38, 34, 26, 29, 28, 20, 8, -13, -33, -52, -68, -69, -65, -55, -49, -47, -44, -31, -3, 30, 55, 67, 70, 68, 70, 70, 65, 57, 39, 15, -13, -38, -49, -47, -40, -35, -39, -41, -30, -9, 17, 37, 44, 45, 38, 32, 29, 22, 9, -10, -34, -54, -70, -75, -73, -64, -52, -45, -43, -31, -7, 25, 53, 67, 72, 70, 72, 70, 62, 53, 38, 16, -10, -32, -49, -50, -43, -35, -33, -36, -29, -10, 16, 35, 46, 46, 41, 35, 30, 23, 10, -10, -34, -53, -69, -75, -74, -66, -53, -45, -42, -34, -13, 17, 46, 63, 68, 66, 63, 65, 63, 54, 43, 24, 0, -20, -40, -43, -42, -36, -32, -32, -28, -16, 7, 29, 47, 52, 47, 39, 31, 21, 10, -9, -30, -50, -66, -78, -77, -71, -59, -49, -42, -34, -17, 9, 37, 56, 66, 66, 62, 62, 61, 56, 45, 30, 7, -13, -31, -39, -40, -36, -33, -32, -28, -18, 1, 21, 41, 54, 52, 44, 36, 26, 13, -8, -29, -48, -66, -76, -80, -74, -64, -55, -45, -34, -18, 5, 29, 50, 65, 68, 66, 64, 60, 59, 47, 33, 15, -5, -23, -37, -43, -41, -37, -35, -31, -21, -4, 16, 36, 52, 59, 54, 45, 33, 17, -5, -25, -45, -60, -74, -83, -82, -71, -59, -49, -37, -23, -2, 22, 43, 59, 66, 65, 64, 60, 58, 50, 39, 23, 2, -17, -32, -39, -40, -38, -35, -32, -23, -6, 14, 33, 49, 59, 58, 49, 34, 16, -5, -25, -43, -60, -74, -83, -83, -76, -63, -53, -40, -24, -5, 16, 36, 54, 65, 67, 65, 61, 57, 52, 43, 27, 9, -12, -26, -37, -40, -39, -36, -32, -28, -13, 6, 27, 46, 58, 60, 52, 39, 23, 5, -16, -36, -53, -66, -77, -84, -81, -72, -60, -45, -32, -15, 5, 25, 48, 62, 69, 71, 69, 65, 58, 50, 34, 16, -6, -24, -36, -42, -45, -44, -39, -33, -21, -2, 22, 43, 59, 64, 60, 47, 34, 17, -6, -28, -50, -66, -76, -84, -86, -82, -72, -57, -40, -21, -2, 21, 42, 58, 66, 73, 76, 71, 64, 53, 40, 26, 4, -17, -34, -45, -49, -48, -43, -38, -28, -10, 15, 40, 58, 66, 64, 56, 42, 25, 4, -21, -44, -62, -73, -81, -87, -86, -78, -65, -47, -31, -9, 15, 34, 52, 62, 72, 79, 80, 72, 61, 49, 34, 12, -12, -32, -43, -49, -54, -55, -48, -36, -16, 10, 35, 56, 67, 71, 67, 54, 38, 15, -10, -34, -57, -72, -85, -93, -97, -89, -76, -59, -40, -20, 8, 32, 50, 67, 77, 87, 89, 81, 66, 52, 35, 16, -6, -30, -47, -58, -61, -57, -50, -37, -19, 6, 29, 51, 65, 73, 73, 62, 44, 18, -6, -28, -49, -67, -81, -93, -97, -94, -83, -65, -47, -28, -5, 19, 42, 61, 76, 87, 90, 88, 80, 66, 48, 27, 3, -17, -40, -56, -65, -66, -58, -49, -30, -6, 17, 41, 59, 71, 77, 70, 56, 36, 11, -13, -34, -53, -71, -89, -98, -100, -94, -79, -62, -44, -21, 3, 27, 52, 74, 90, 98, 95, 86, 75, 59, 37, 12, -14, -35, -54, -64, -67, -64, -51, -34, -10, 11, 32, 50, 65, 73, 71, 58, 37, 14, -10, -29, -48, -64, -81, -93, -98, -94, -82, -63, -45, -26, -5, 16, 40, 65, 83, 94, 94, 84, 75, 63, 46, 23, -3, -27, -47, -58, -64, -64, -56, -39, -17, 3, 20, 38, 57, 71, 72, 61, 45, 24, 1, -19, -37, -56, -73, -91, -99, -100, -92, -74, -53, -34, -16, 7, 31, 59, 82, 97, 101, 92, 78, 65, 48, 29, 6, -21, -43, -55, -64, -66, -58, -40, -18, 3, 17, 32, 51, 69, 71, 62, 45, 27, 6, -15, -34, -50, -64, -81, -93, -99, -96, -80, -59, -40, -23, -4, 21, 50, 77, 94, 100, 93, 81, 67, 53, 36, 14, -12, -36, -53, -58, -63, -56, -42, -22, -5, 10, 23, 42, 63, 70, 62, 47, 29, 13, -6, -27, -43, -57, -72, -84, -98, -99, -87, -66, -44, -27, -11, 10, 38, 67, 91, 99, 92, 82, 70, 57, 41, 21, -3, -27, -47, -58, -63, -58, -44, -23, -5, 7, 17, 35, 55, 66, 61, 46, 29, 13, -4, -22, -39, -51, -65, -78, -90, -95, -85, -69, -47, -30, -12, 9, 30, 57, 83, 96, 91, 81, 67, 57, 42, 26, 6, -18, -39, -55, -62, -58, -43, -24, -8, 2, 14, 30, 47, 60, 60, 49, 34, 17, 0, -16, -31, -43, -58, -71, -86, -93, -86, -72, -52, -32, -15, 3, 22, 48, 76, 90, 89, 78, 69, 59, 46, 32, 14, -6, -27, -47, -57, -56, -45, -29, -12, -5, 4, 18, 37, 54, 58, 51, 36, 21, 6, -8, -20, -33, -52, -68, -84, -90, -85, -74, -58, -42, -22, 0, 20, 42, 67, 83, 87, 80, 68, 58, 47, 34, 19, 0, -20, -40, -52, -53, -45, -27, -13, -4, 6, 17, 33, 47, 53, 52, 38, 21, 3, -11, -24, -35, -50, -65, -80, -89, -85, -71, -55, -39, -21, -2, 20, 39, 59, 74, 81, 75, 67, 57, 47, 38, 23, 4, -17, -32, -43, -45, -39, -26, -14, -4, 4, 12, 26, 38, 47, 48, 35, 19, 4, -10, -20, -29, -41, -56, -71, -78, -81, -71, -56, -43, -23, -6, 15, 35, 49, 62, 72, 69, 63, 54, 45, 41, 28, 11, -11, -27, -37, -40, -35, -24, -17, -7, 2, 9, 22, 35, 46, 49, 37, 21, 4, -9, -18, -27, -41, -55, -71, -79, -79, -70, -53, -38, -23, -8, 9, 31, 46, 58, 63, 63, 59, 52, 45, 40, 32, 14, -6, -24, -32, -31, -30, -23, -18, -12, 1, 9, 21, 31, 41, 44, 33, 21, 5, -6, -20, -29, -43, -57, -69, -77, -73, -65, -52, -41, -27, -8, 11, 32, 49, 57, 64, 61, 55, 47, 39, 36, 29, 13, -8, -25, -36, -35, -26, -16, -9, -5, 1, 9, 22, 36, 45, 43, 33, 17, 1, -11, -21, -32, -45, -57, -71, -78, -73, -61, -45, -33, -23, -8, 11, 31, 46, 53, 57, 54, 48, 40, 34, 31, 27, 14, -4, -20, -29, -28, -22, -12, -4, 1, 4, 8, 21, 34, 43, 43, 31, 17, 1, -11, -22, -31, -44, -59, -72, -78, -70, -54, -40, -28, -19, -8, 10, 28, 45, 53, 57, 53, 43, 34, 28, 27, 26, 18, 0, -18, -31, -29, -20, -11, -3, 2, 5, 10, 19, 31, 43, 44, 34, 19, 2, -13, -23, -32, -43, -55, -68, -77, -73, -57, -41, -26, -15, -6, 11, 28, 43, 52, 52, 49, 41, 33, 24, 22, 21, 14, 1, -14, -25, -24, -18, -7, -2, 2, 7, 10, 20, 31, 40, 43, 33, 18, 3, -13, -24, -35, -44, -55, -70, -78, -74, -59, -40, -26, -11, 1, 13, 29, 44, 53, 57, 54, 45, 32, 24, 18, 13, 9, -4, -16, -26, -29, -22, -10, 1, 8, 13, 18, 23, 35, 42, 45, 37, 21, 5, -14, -30, -41, -49, -57, -69, -77, -76, -61, -39, -20, -5, 9, 20, 34, 47, 53, 55, 48, 39, 27, 14, 8, 3, 2, -4, -15, -23, -24, -16, -3, 6, 11, 19, 24, 30, 34, 41, 43, 35, 18, 1, -17, -31, -44, -52, -59, -68, -75, -73, -61, -38, -19, 1, 13, 23, 30, 42, 52, 52, 47, 36, 23, 14, 7, 4, 0, -6, -11, -20, -24, -18, -5, 7, 15, 18, 22, 28, 36, 43, 43, 38, 24, 4, -13, -30, -44, -55, -64, -69, -77, -76, -65, -44, -19, 1, 15, 27, 35, 46, 53, 53, 46, 36, 23, 11, 3, -5, -7, -9, -14, -20, -23, -19, -7, 11, 18, 21, 25, 30, 40, 43, 43, 38, 24, 7, -14, -30, -41, -55, -65, -73, -77, -74, -66, -49, -24, -2, 17, 29, 35, 44, 51, 54, 49, 35, 23, 11, 1, -6, -12, -15, -16, -20, -24, -21, -10, 8, 21, 27, 33, 35, 42, 48, 47, 37, 23, 7, -12, -28, -44, -60, -69, -75, -78, -74, -65, -49, -25, -2, 17, 30, 40, 48, 54, 55, 48, 36, 20, 6, -4, -9, -14, -20, -22, -24, -21, -15, -6, 7, 21, 32, 39, 43, 44, 49, 50, 38, 21, 4, -13, -28, -47, -62, -74, -77, -78, -77, -65, -48, -26, -4, 15, 28, 40, 50, 56, 54, 46, 33, 20, 9, -2, -10, -16, -21, -21, -23, -21, -15, -5, 9, 19, 30, 38, 42, 44, 46, 47, 36, 22, 6, -10, -23, -39, -57, -74, -78, -79, -75, -65, -51, -33, -11, 9, 25, 37, 46, 55, 56, 48, 34, 21, 10, 4, -4, -14, -20, -25, -24, -21, -12, -3, 8, 17, 26, 36, 47, 50, 50, 47, 36, 25, 10, -5, -21, -40, -57, -75, -82, -79, -75, -64, -51, -37, -16, 5, 25, 40, 48, 55, 55, 49, 37, 25, 15, 6, -6, -18, -26, -29, -25, -20, -16, -7, 5, 17, 29, 39, 49, 56, 56, 51, 39, 28, 15, 0, -17, -38, -58, -75, -86, -86, -80, -70, -54, -37, -16, 7, 25, 42, 50, 55, 58, 52, 40, 25, 11, 2, -5, -14, -21, -26, -26, -18, -12, -5, 4, 13, 25, 34, 45, 53, 55, 48, 39, 25, 16, 3, -13, -31, -54, -70, -83, -85, -78, -68, -55, -38, -20, 1, 20, 36, 46, 51, 55, 48, 39, 27, 17, 7, -5, -13, -20, -23, -23, -18, -10, -4, 3, 10, 21, 29, 40, 48, 52, 50, 40, 28, 20, 10, -5, -24, -48, -67, -82, -87, -81, -73, -56, -44, -25, -5, 15, 34, 46, 52, 55, 51, 39, 27, 18, 7, -2, -13, -22, -25, -24, -16, -9, 1, 8, 13, 22, 30, 42, 48, 50, 47, 38, 26, 15, 6, -8, -22, -41, -61, -77, -86, -81, -70, -54, -40, -27, -8, 12, 31, 42, 49, 50, 48, 38, 26, 16, 7, -4, -11, -18, -22, -21, -16, -9, 0, 9, 15, 21, 26, 35, 47, 50, 46, 36, 28, 18, 7, -7, -22, -37, -53, -70, -81, -83, -72, -58, -43, -30, -14, 5, 22, 37, 44, 46, 44, 37, 26, 17, 8, 2, -7, -12, -17, -16, -12, -6, 3, 8, 13, 17, 22, 31, 42, 43, 43, 35, 29, 25, 14, 2, -17, -35, -51, -65, -77, -80, -75, -63, -47, -34, -18, 4, 21, 32, 38, 41, 41, 36, 28, 17, 8, 1, -9, -12, -16, -15, -9, -2, 8, 13, 15, 17, 23, 28, 39, 43, 38, 30, 21, 17, 11, 4, -12, -28, -45, -60, -68, -71, -66, -58, -49, -38, -23, -5, 15, 27, 34, 34, 32, 28, 23, 18, 13, 4, -2, -7, -9, -7, -4, 5, 14, 16, 16, 14, 15, 24, 35, 39, 35, 23, 17, 15, 11, 8, -4, -19, -37, -53, -62, -65, -62, -57, -53, -43, -31, -14, 5, 19, 27, 31, 28, 26, 23, 20, 18, 11, 5, -2, -5, 0, 3, 8, 14, 16, 15, 11, 7, 12, 23, 32, 32, 21, 12, 10, 13, 12, 6, -9, -27, -43, -50, -55, -53, -51, -52, -44, -38, -23, -6, 7, 18, 22, 19, 16, 15, 16, 19, 17, 12, 6, 3, 7, 10, 16, 20, 23, 20, 14, 8, 9, 17, 27, 26, 17, 6, 3, 7, 10, 7, -5, -18, -32, -41, -46, -45, -45, -45, -44, -40, -30, -16, -3, 8, 15, 12, 10, 11, 16, 19, 19, 16, 12, 10, 11, 15, 20, 25, 26, 24, 18, 11, 6, 11, 17, 21, 15, 3, -6, -2, 4, 7, 2, -14, -25, -32, -36, -38, -37, -37, -35, -33, -33, -25, -15, -4, 3, 4, 0, -3, 2, 13, 21, 21, 20, 17, 19, 23, 27, 31, 33, 31, 24, 16, 4, 2, 7, 13, 13, 3, -10, -9, 0, 8, 7, -3, -15, -22, -24, -30, -32, -37, -39, -38, -37, -34, -28, -17, -8, -2, -4, -4, 4, 16, 26, 30, 26, 22, 22, 25, 29, 31, 30, 29, 24, 17, 6, -2, 7, 10, 13, 4, -11, -15, -10, 3, 8, 2, -10, -17, -17, -17, -23, -29, -35, -37, -34, -36, -35, -28, -19, -10, -11, -14, -8, 8, 21, 26, 26, 21, 24, 31, 38, 40, 38, 37, 33, 26, 15, 4, 1, 2, 1, -6, -19, -24, -18, -7, 2, 5, -4, -10, -9, -6, -7, -16, -27, -33, -35, -38, -41, -38, -32, -22, -20, -18, -10, 4, 20, 29, 31, 30, 28, 32, 38, 43, 42, 39, 34, 28, 14, 4, 1, 3, 4, -5, -21, -30, -26, -14, 1, 3, -4, -8, -8, 0, 0, -8, -15, -26, -29, -35, -40, -40, -36, -30, -28, -29, -22, -10, 9, 22, 28, 28, 27, 30, 39, 46, 50, 50, 43, 33, 21, 9, 3, 3, 1, -10, -22, -35, -34, -22, -8, 2, 0, -6, -7, 0, 5, -2, -9, -18, -28, -34, -41, -43, -39, -35, -33, -33, -25, -12, 5, 19, 26, 29, 31, 31, 39, 46, 51, 52, 47, 38, 27, 18, 10, 5, -3, -13, -22, -33, -36, -28, -16, -4, -2, -4, -6, 0, 8, 7, 0, -12, -22, -33, -40, -42, -39, -37, -38, -39, -32, -17, 2, 15, 24, 25, 28, 33, 39, 47, 51, 53, 51, 44, 35, 23, 15, 8, 1, -12, -25, -37, -41, -33, -22, -11, -4, -5, -3, 3, 10, 13, 6, -5, -17, -28, -38, -43, -44, -44, -44, -43, -36, -23, -7, 7, 20, 26, 29, 35, 43, 51, 54, 58, 56, 52, 44, 29, 18, 9, -2, -12, -28, -39, -45, -38, -26, -16, -7, -3, 1, 6, 12, 15, 12, 3, -11, -25, -37, -41, -43, -46, -47, -46, -39, -28, -15, 0, 11, 21, 25, 31, 38, 46, 53, 60, 62, 59, 53, 42, 32, 19, 6, -10, -27, -41, -47, -47, -39, -31, -21, -9, -2, 5, 11, 16, 19, 13, 2, -15, -30, -35, -37, -43, -47, -49, -42, -32, -21, -11, 0, 8, 19, 27, 38, 47, 51, 58, 63, 63, 59, 50, 41, 28, 10, -9, -26, -37, -43, -44, -40, -33, -23, -11, 0, 6, 9, 14, 15, 13, 1, -15, -25, -32, -34, -43, -49, -50, -43, -30, -20, -13, -9, 0, 10, 23, 36, 46, 52, 55, 62, 65, 66, 61, 51, 36, 15, -7, -24, -34, -42, -45, -46, -42, -34, -20, -5, 5, 11, 14, 16, 13, 2, -10, -18, -24, -31, -39, -49, -48, -42, -34, -24, -18, -15, -8, 2, 13, 29, 42, 51, 57, 62, 65, 70, 69, 60, 45, 20, -3, -24, -37, -43, -46, -49, -48, -39, -24, -6, 5, 12, 17, 20, 16, 6, -9, -15, -21, -26, -38, -50, -56, -50, -37, -26, -23, -19, -14, -4, 11, 27, 42, 54, 58, 63, 65, 68, 70, 63, 50, 26, 1, -21, -37, -43, -44, -44, -44, -40, -28, -11, 5, 10, 16, 18, 14, 5, -12, -19, -22, -24, -33, -47, -52, -52, -38, -25, -17, -17, -16, -10, 4, 22, 39, 53, 59, 62, 63, 66, 68, 66, 55, 32, 9, -17, -34, -43, -42, -39, -38, -38, -31, -19, -3, 10, 17, 19, 12, 3, -12, -21, -24, -24, -31, -40, -49, -52, -41, -30, -18, -15, -17, -10, 0, 16, 33, 47, 59, 65, 64, 65, 67, 63, 56, 38, 13, -12, -32, -41, -39, -35, -33, -32, -27, -17, -4, 8, 15, 16, 13, 4, -11, -20, -25, -27, -32, -40, -48, -52, -46, -37, -25, -18, -16, -10, 1, 16, 33, 49, 59, 66, 67, 65, 66, 62, 51, 38, 15, -9, -30, -38, -41, -33, -29, -26, -23, -17, -5, 7, 16, 15, 14, 5, -9, -19, -27, -31, -34, -40, -47, -52, -49, -40, -30, -22, -16, -8, 4, 19, 32, 46, 59, 67, 71, 69, 64, 57, 49, 36, 17, -7, -27, -38, -40, -35, -28, -23, -19, -12, -5, 6, 12, 16, 15, 10, -5, -19, -28, -32, -36, -39, -46, -53, -52, -45, -34, -25, -18, -7, 6, 20, 33, 46, 60, 67, 74, 71, 65, 56, 46, 37, 18, -2, -20, -33, -38, -38, -30, -22, -16, -12, -6, 2, 6, 15, 15, 11, 1, -11, -19, -31, -37, -42, -46, -51, -54, -53, -46, -35, -26, -14, 3, 17, 33, 45, 57, 67, 75, 77, 71, 62, 50, 36, 18, 0, -19, -31, -36, -37, -31, -23, -17, -11, -6, 1, 6, 11, 15, 14, 8, -3, -16, -27, -37, -41, -47, -52, -58, -60, -55, -46, -32, -16, 0, 17, 32, 46, 59, 70, 79, 80, 75, 65, 51, 35, 20, 2, -15, -27, -38, -42, -36, -27, -17, -10, -4, 3, 7, 12, 18, 19, 14, 5, -7, -22, -37, -46, -53, -57, -62, -67, -65, -58, -43, -22, 1, 20, 35, 48, 60, 69, 79, 82, 79, 68, 53, 36, 21, 4, -11, -24, -36, -40, -38, -31, -21, -14, -5, 1, 5, 11, 17, 22, 19, 14, -2, -17, -35, -48, -55, -63, -67, -73, -72, -64, -49, -27, -4, 19, 36, 52, 64, 73, 81, 85, 82, 72, 56, 36, 20, 3, -14, -24, -33, -36, -35, -32, -22, -13, -6, 2, 7, 10, 15, 19, 19, 17, 6, -10, -29, -48, -58, -67, -71, -75, -78, -72, -58, -35, -10, 16, 35, 52, 65, 74, 80, 86, 87, 79, 62, 39, 21, 5, -11, -22, -33, -39, -39, -34, -25, -15, -7, 3, 8, 16, 17, 21, 22, 19, 9, -6, -27, -47, -60, -71, -77, -80, -81, -73, -61, -39, -12, 16, 36, 52, 63, 73, 80, 85, 87, 76, 59, 41, 23, 8, -7, -18, -29, -36, -38, -33, -23, -13, -8, 1, 6, 14, 18, 19, 23, 23, 17, 1, -20, -43, -57, -67, -78, -83, -89, -81, -67, -45, -19, 9, 35, 55, 67, 74, 80, 87, 91, 83, 68, 44, 24, 6, -9, -21, -29, -36, -39, -39, -31, -20, -10, 1, 13, 20, 26, 26, 27, 28, 22, 8, -16, -40, -60, -75, -86, -93, -95, -89, -75, -52, -24, 7, 37, 57, 69, 77, 83, 90, 93, 85, 70, 48, 27, 8, -8, -19, -26, -32, -35, -39, -37, -28, -17, -2, 9, 19, 21, 27, 31, 32, 29, 12, -9, -32, -54, -71, -86, -94, -96, -90, -82, -62, -33, 2, 34, 56, 69, 78, 87, 94, 94, 85, 69, 49, 29, 9, -10, -21, -27, -30, -33, -37, -36, -29, -17, -5, 9, 19, 25, 27, 31, 33, 33, 21, -2, -25, -51, -71, -86, -95, -95, -92, -85, -69, -42, -8, 27, 52, 67, 74, 83, 92, 95, 89, 75, 56, 35, 16, -6, -17, -26, -28, -34, -41, -39, -37, -25, -9, 6, 20, 28, 31, 37, 37, 34, 24, 3, -20, -46, -69, -85, -96, -99, -97, -89, -73, -47, -11, 21, 45, 61, 73, 84, 92, 95, 89, 77, 61, 41, 20, -2, -13, -20, -28, -36, -43, -46, -40, -30, -16, 0, 12, 24, 30, 38, 43, 41, 33, 13, -14, -39, -63, -80, -93, -98, -100, -94, -76, -52, -19, 14, 38, 56, 70, 80, 90, 94, 88, 75, 58, 40, 22, 6, -8, -19, -25, -33, -39, -41, -38, -31, -19, -5, 7, 21, 31, 39, 45, 42, 32, 15, -8, -32, -55, -77, -93, -102, -101, -94, -80, -57, -29, 5, 34, 54, 70, 78, 88, 96, 92, 80, 62, 41, 24, 8, -9, -21, -32, -35, -38, -41, -39, -35, -22, -6, 6, 21, 31, 39, 46, 44, 35, 18, -5, -27, -49, -70, -86, -97, -102, -96, -84, -58, -30, -2, 26, 45, 62, 74, 82, 89, 89, 80, 66, 46, 28, 12, -3, -14, -26, -36, -39, -42, -40, -36, -28, -15, 0, 17, 30, 37, 45, 48, 40, 23, 3, -20, -43, -64, -81, -93, -98, -96, -85, -65, -38, -8, 20, 40, 55, 68, 80, 88, 88, 82, 68, 54, 35, 18, 2, -12, -24, -35, -40, -45, -45, -41, -33, -20, -4, 15, 31, 41, 49, 52, 48, 32, 13, -14, -38, -59, -77, -92, -101, -102, -91, -70, -45, -15, 15, 38, 53, 65, 77, 89, 91, 85, 71, 52, 38, 21, 5, -12, -26, -36, -42, -45, -45, -43, -34, -22, -7, 9, 26, 39, 50, 56, 50, 34, 14, -7, -29, -50, -69, -84, -96, -98, -90, -72, -50, -24, 7, 32, 48, 57, 68, 84, 91, 88, 74, 58, 44, 30, 11, -9, -26, -38, -41, -46, -45, -44, -38, -23, -7, 9, 24, 36, 49, 55, 51, 35, 18, -3, -24, -45, -64, -78, -89, -93, -90, -75, -54, -29, 0, 23, 42, 54, 67, 80, 90, 91, 81, 65, 48, 31, 13, -5, -24, -41, -50, -53, -51, -46, -42, -28, -10, 8, 23, 36, 50, 59, 56, 44, 26, 8, -13, -35, -56, -77, -89, -94, -92, -80, -61, -39, -11, 14, 33, 50, 63, 77, 88, 89, 81, 67, 54, 38, 21, 1, -23, -39, -50, -54, -53, -46, -42, -31, -17, 1, 17, 33, 46, 56, 56, 46, 33, 16, -4, -24, -46, -67, -82, -92, -94, -87, -67, -45, -19, 4, 22, 43, 62, 76, 87, 90, 87, 76, 59, 40, 20, 1, -22, -40, -55, -62, -58, -50, -40, -29, -17, -3, 14, 33, 49, 59, 58, 49, 35, 21, 2, -17, -39, -59, -76, -90, -93, -86, -70, -49, -29, -8, 12, 33, 57, 75, 84, 87, 84, 78, 65, 47, 28, 6, -18, -39, -58, -65, -64, -57, -44, -33, -22, -10, 6, 26, 44, 56, 56, 48, 40, 27, 11, -8, -30, -49, -65, -80, -86, -87, -72, -51, -31, -13, 5, 24, 48, 70, 81, 86, 83, 79, 69, 51, 30, 8, -16, -37, -55, -65, -67, -61, -48, -36, -21, -10, 5, 22, 40, 55, 58, 53, 43, 31, 16, -2, -23, -45, -60, -74, -82, -86, -75, -56, -36, -16, 1, 21, 44, 65, 81, 88, 85, 81, 72, 54, 33, 8, -18, -41, -58, -71, -74, -70, -56, -41, -23, -6, 8, 23, 38, 53, 60, 59, 50, 37, 22, 1, -20, -41, -56, -69, -79, -83, -78, -62, -42, -20, 2, 22, 41, 59, 77, 86, 87, 79, 67, 50, 31, 10, -15, -36, -52, -63, -69, -69, -59, -41, -23, -9, 4, 15, 29, 44, 55, 56, 53, 43, 27, 12, -8, -27, -44, -57, -68, -78, -77, -67, -48, -29, -12, 12, 32, 52, 70, 79, 84, 82, 73, 59, 38, 15, -9, -33, -52, -63, -71, -72, -66, -50, -30, -13, 2, 12, 27, 42, 50, 54, 54, 46, 34, 19, -2, -19, -35, -47, -61, -71, -72, -66, -51, -36, -19, 5, 27, 46, 63, 74, 79, 79, 70, 58, 41, 21, 3, -24, -44, -58, -66, -66, -65, -52, -36, -22, -10, 4, 18, 34, 43, 49, 52, 48, 43, 31, 14, -4, -21, -35, -51, -61, -66, -64, -56, -43, -29, -8, 16, 37, 54, 67, 72, 74, 70, 61, 46, 27, 7, -19, -40, -56, -62, -62, -63, -55, -43, -26, -10, 3, 13, 26, 38, 44, 47, 43, 39, 30, 19, 5, -12, -24, -40, -47, -51, -53, -51, -44, -32, -14, 6, 24, 41, 54, 61, 63, 61, 56, 47, 32, 13, -9, -31, -46, -56, -53, -54, -54, -48, -37, -18, -3, 8, 17, 27, 33, 38, 39, 39, 37, 30, 18, 1, -16, -29, -35, -39, -42, -47, -47, -39, -22, -3, 14, 29, 42, 51, 57, 56, 54, 45, 36, 20, -2, -23, -41, -50, -51, -52, -53, -51, -42, -27, -8, 5, 12, 19, 28, 35, 40, 39, 40, 37, 28, 12, -7, -23, -28, -30, -37, -43, -49, -45, -32, -15, 3, 19, 34, 45, 49, 49, 51, 47, 41, 26, 6, -18, -34, -43, -45, -45, -48, -51, -49, -33, -15, -2, 8, 12, 19, 26, 33, 38, 38, 38, 34, 25, 8, -11, -19, -20, -23, -32, -43, -48, -41, -24, -8, 10, 21, 31, 38, 43, 47, 48, 45, 34, 16, -9, -31, -41, -42, -42, -46, -52, -52, -40, -23, -6, 6, 11, 17, 24, 30, 35, 38, 39, 40, 29, 14, -3, -14, -14, -15, -24, -36, -47, -45, -33, -15, 3, 14, 23, 29, 35, 39, 44, 45, 38, 22, -3, -26, -38, -37, -37, -41, -50, -56, -45, -26, -8, 5, 12, 16, 22, 27, 32, 39, 41, 41, 33, 17, 1, -9, -8, -8, -16, -30, -41, -45, -35, -21, -5, 10, 18, 24, 28, 31, 38, 42, 39, 25, 2, -23, -36, -36, -37, -39, -47, -53, -47, -31, -11, 3, 12, 16, 23, 27, 32, 37, 40, 41, 33, 18, 2, -7, -8, -6, -10, -23, -36, -41, -35, -20, -6, 7, 14, 17, 24, 29, 36, 42, 40, 28, 5, -20, -35, -38, -38, -39, -45, -51, -46, -33, -15, 2, 13, 22, 27, 28, 27, 30, 37, 41, 35, 20, 5, -4, -4, -2, -3, -13, -28, -35, -32, -23, -10, 3, 11, 14, 14, 20, 28, 37, 40, 27, 7, -16, -31, -36, -37, -36, -41, -44, -45, -35, -18, 1, 12, 19, 25, 26, 27, 31, 34, 39, 34, 20, 8, 0, 0, 1, 0, -9, -23, -33, -34, -24, -10, 2, 8, 8, 10, 16, 27, 34, 35, 27, 10, -10, -27, -35, -35, -34, -39, -46, -47, -38, -22, -3, 10, 19, 26, 31, 32, 32, 35, 41, 39, 25, 9, -2, -3, -2, -2, -7, -19, -30, -33, -26, -14, -3, 6, 6, 7, 12, 26, 37, 37, 26, 10, -8, -25, -35, -39, -39, -42, -47, -49, -42, -27, -4, 12, 20, 29, 33, 36, 35, 35, 38, 37, 27, 10, -3, -6, -3, -2, -7, -16, -24, -28, -24, -13, -4, 4, 5, 7, 9, 19, 30, 33, 28, 12, -6, -24, -35, -40, -39, -42, -47, -47, -41, -26, -8, 10, 22, 31, 36, 41, 39, 34, 33, 33, 29, 15, 2, -7, -8, -6, -6, -10, -18, -24, -24, -15, -5, 6, 7, 7, 10, 17, 23, 23, 18, 9, -7, -23, -36, -42, -41, -41, -45, -45, -39, -28, -11, 7, 21, 31, 36, 39, 39, 34, 31, 33, 29, 19, 7, -5, -6, -6, -4, -6, -13, -17, -20, -16, -8, 1, 6, 7, 7, 11, 16, 20, 18, 9, -7, -24, -37, -43, -42, -42, -42, -45, -41, -28, -11, 7, 19, 28, 35, 40, 42, 38, 33, 29, 27, 21, 10, -2, -8, -8, -6, -8, -11, -13, -16, -14, -8, 1, 5, 8, 9, 15, 19, 20, 18, 9, -4, -18, -34, -42, -46, -47, -45, -47, -45, -36, -20, 0, 13, 26, 36, 45, 48, 42, 35, 29, 28, 26, 20, 6, -6, -10, -10, -6, -7, -8, -10, -14, -10, -7, 0, 6, 8, 13, 14, 16, 13, 7, -3, -13, -27, -37, -44, -49, -44, -42, -40, -37, -25, -9, 9, 23, 31, 41, 44, 44, 37, 30, 27, 28, 27, 15, 2, -7, -9, -6, -7, -9, -8, -13, -12, -8, -3, 4, 9, 13, 14, 14, 11, 6, 0, -9, -23, -34, -43, -49, -46, -42, -40, -35, -29, -13, 3, 19, 31, 41, 45, 43, 37, 31, 29, 30, 28, 19, 4, -5, -7, -7, -5, -8, -7, -9, -11, -9, -4, 0, 6, 12, 14, 13, 9, 5, -3, -9, -19, -28, -37, -48, -48, -45, -39, -34, -30, -18, -5, 12, 23, 34, 42, 44, 39, 34, 32, 31, 33, 30, 18, 8, 1, -5, -6, -5, -5, -8, -13, -16, -14, -7, 2, 7, 11, 10, 7, 4, -2, -7, -12, -22, -32, -45, -50, -45, -38, -33, -30, -24, -13, 2, 20, 31, 39, 43, 42, 38, 36, 33, 33, 33, 24, 14, 1, -8, -9, -7, -4, -5, -11, -16, -16, -11, -4, 2, 9, 8, 7, 3, -3, -6, -9, -15, -24, -38, -47, -48, -42, -35, -32, -29, -21, -9, 11, 27, 35, 42, 42, 42, 40, 40, 38, 36, 30, 19, 8, -4, -9, -8, -5, -5, -12, -18, -20, -15, -5, -2, 3, 4, 5, 6, 1, -3, -8, -12, -19, -31, -43, -47, -43, -36, -35, -36, -32, -19, 2, 19, 30, 38, 42, 46, 49, 50, 47, 43, 39, 28, 16, 1, -10, -13, -11, -9, -14, -21, -25, -20, -10, -4, 1, 3, 4, 7, 4, -3, -7, -7, -10, -23, -38, -47, -46, -41, -37, -38, -37, -27, -11, 11, 24, 33, 38, 45, 50, 53, 52, 48, 43, 37, 25, 10, -3, -11, -11, -11, -13, -20, -27, -29, -22, -14, -7, -2, 2, 6, 3, -2, -3, 0, 0, -11, -28, -41, -45, -39, -35, -36, -39, -37, -24, -7, 11, 22, 32, 41, 51, 55, 56, 54, 53, 50, 40, 23, 6, -5, -10, -11, -14, -20, -28, -34, -33, -25, -16, -10, -5, 0, 0, 1, 2, 4, 5, -4, -16, -29, -35, -37, -37, -35, -39, -39, -32, -19, 0, 13, 23, 36, 46, 54, 58, 57, 59, 56, 47, 33, 16, 3, -5, -9, -11, -19, -29, -36, -39, -33, -26, -18, -12, -7, -5, -2, 4, 11, 15, 10, -3, -18, -29, -32, -35, -36, -41, -44, -40, -30, -18, 0, 13, 28, 41, 50, 59, 63, 66, 66, 60, 44, 26, 11, 2, -6, -12, -19, -29, -38, -44, -41, -33, -25, -16, -9, -8, -6, 1, 11, 18, 16, 8, -6, -17, -27, -32, -36, -39, -43, -44, -37, -30, -12, 8, 26, 39, 46, 56, 64, 70, 72, 66, 51, 36, 18, 7, -4, -11, -18, -29, -42, -50, -51, -45, -35, -23, -14, -10, -9, 0, 14, 27, 29, 20, 7, -5, -15, -23, -30, -38, -45, -50, -49, -43, -30, -9, 13, 31, 41, 52, 65, 75, 79, 77, 66, 50, 30, 13, 3, -6, -14, -26, -41, -53, -57, -54, -44, -32, -23, -17, -13, -5, 10, 24, 31, 28, 20, 9, -5, -17, -26, -35, -40, -48, -54, -53, -44, -23, 0, 21, 35, 46, 60, 73, 81, 83, 77, 60, 42, 25, 11, 1, -11, -25, -42, -57, -64, -62, -54, -43, -33, -24, -17, -6, 9, 23, 37, 37, 33, 19, 6, -9, -20, -30, -41, -49, -57, -59, -54, -38, -16, 10, 31, 46, 58, 70, 78, 85, 84, 73, 54, 32, 16, 5, -5, -22, -41, -60, -72, -71, -66, -54, -43, -30, -19, -6, 10, 25, 41, 47, 43, 32, 20, 7, -10, -25, -40, -52, -61, -68, -65, -54, -34, -11, 16, 39, 57, 72, 80, 88, 91, 83, 67, 46, 28, 13, 1, -18, -40, -62, -77, -77, -70, -63, -54, -43, -30, -12, 7, 25, 40, 51, 51, 42, 31, 19, 3, -13, -32, -48, -60, -68, -71, -63, -49, -28, -2, 23, 46, 66, 77, 86, 92, 89, 82, 62, 43, 22, 7, -12, -39, -59, -74, -80, -78, -72, -63, -50, -35, -17, 5, 22, 35, 45, 49, 49, 42, 31, 13, -7, -25, -38, -49, -59, -66, -65, -57, -42, -20, 8, 34, 55, 69, 79, 84, 84, 84, 77, 64, 42, 18, -6, -29, -49, -69, -82, -87, -87, -78, -66, -48, -27, -4, 17, 33, 47, 56, 60, 58, 49, 31, 8, -18, -36, -47, -57, -67, -75, -74, -60, -36, -3, 25, 48, 65, 76, 83, 87, 90, 88, 77, 52, 24, -4, -26, -42, -61, -77, -91, -94, -85, -70, -54, -34, -11, 12, 30, 44, 56, 63, 66, 61, 43, 19, -8, -27, -39, -49, -62, -74, -80, -71, -49, -20, 9, 34, 56, 70, 79, 86, 93, 96, 91, 70, 41, 11, -18, -39, -58, -77, -91, -99, -95, -83, -65, -42, -17, 7, 27, 43, 57, 66, 69, 67, 55, 32, 5, -21, -32, -42, -56, -73, -84, -79, -60, -33, -5, 21, 44, 61, 72, 80, 92, 100, 99, 82, 54, 23, -10, -31, -51, -71, -87, -101, -101, -92, -76, -49, -24, 1, 21, 37, 52, 66, 72, 72, 64, 44, 18, -7, -23, -31, -45, -64, -79, -83, -71, -46, -18, 7, 27, 46, 62, 72, 85, 97, 100, 92, 65, 35, 2, -22, -40, -60, -78, -92, -100, -96, -82, -59, -29, -6, 15, 28, 44, 57, 65, 67, 65, 49, 27, 2, -17, -23, -35, -53, -70, -79, -73, -52, -27, -4, 16, 35, 54, 65, 77, 88, 95, 93, 73, 44, 12, -17, -38, -54, -74, -86, -97, -98, -89, -69, -37, -11, 9, 27, 42, 56, 65, 68, 71, 59, 39, 13, -9, -20, -30, -45, -62, -74, -75, -60, -41, -18, 3, 23, 43, 60, 74, 83, 91, 91, 78, 52, 22, -8, -30, -46, -66, -82, -90, -92, -85, -70, -44, -17, 5, 22, 33, 45, 56, 60, 63, 56, 39, 21, 5, -9, -20, -33, -49, -62, -70, -62, -47, -28, -9, 11, 29, 47, 60, 73, 83, 87, 81, 62, 32, 4, -21, -39, -60, -78, -88, -90, -86, -73, -55, -28, -2, 18, 30, 42, 50, 57, 58, 53, 44, 27, 15, 4, -10, -24, -40, -53, -59, -57, -49, -38, -21, -3, 17, 34, 49, 62, 75, 81, 76, 63, 39, 15, -11, -31, -50, -69, -79, -84, -82, -73, -57, -34, -7, 12, 26, 35, 42, 50, 56, 53, 42, 31, 20, 13, 1, -16, -30, -43, -50, -51, -49, -42, -28, -11, 7, 23, 38, 52, 65, 75, 73, 62, 43, 20, -2, -24, -43, -60, -69, -74, -74, -69, -59, -42, -19, 2, 19, 27, 34, 41, 48, 50, 45, 39, 33, 25, 13, -3, -18, -32, -42, -47, -49, -47, -40, -27, -8, 11, 28, 43, 57, 69, 73, 65, 50, 31, 8, -16, -36, -53, -63, -70, -72, -70, -62, -46, -25, -6, 11, 23, 30, 38, 45, 49, 50, 46, 42, 33, 22, 6, -13, -25, -37, -43, -48, -50, -45, -35, -18, 2, 21, 39, 51, 61, 64, 63, 53, 38, 19, -6, -30, -49, -59, -63, -65, -66, -64, -52, -31, -14, 2, 13, 25, 35, 42, 46, 46, 47, 48, 44, 33, 15, -6, -21, -32, -37, -42, -48, -46, -39, -26, -8, 12, 31, 45, 55, 58, 57, 51, 39, 22, 2, -21, -39, -49, -56, -59, -62, -59, -52, -38, -22, -9, 5, 16, 25, 32, 40, 46, 51, 54, 52, 40, 24, 5, -11, -20, -28, -35, -44, -48, -43, -33, -17, 0, 18, 32, 44, 48, 49, 48, 40, 28, 11, -10, -26, -37, -45, -52, -58, -57, -51, -41, -29, -19, -10, 3, 15, 27, 36, 40, 50, 59, 60, 51, 33, 15, 2, -11, -21, -34, -45, -49, -45, -36, -25, -11, 8, 26, 38, 43, 42, 41, 39, 31, 16, -5, -24, -31, -37, -43, -51, -54, -49, -40, -31, -24, -13, -3, 12, 22, 29, 33, 43, 55, 60, 53, 37, 18, 5, -4, -12, -23, -35, -44, -42, -35, -26, -15, -2, 15, 26, 33, 31, 31, 29, 28, 21, 6, -13, -27, -30, -37, -44, -48, -45, -39, -34, -28, -18, -8, 4, 17, 23, 31, 40, 51, 58, 56, 42, 25, 12, 2, -7, -16, -27, -36, -39, -37, -31, -21, -12, 3, 14, 21, 25, 23, 23, 25, 23, 11, -4, -16, -21, -26, -34, -39, -40, -34, -31, -30, -23, -17, -3, 9, 16, 23, 31, 42, 54, 57, 49, 29, 14, 7, 4, -3, -15, -26, -32, -32, -31, -24, -16, -5, 5, 8, 10, 9, 10, 16, 19, 14, 4, -8, -14, -16, -21, -29, -34, -33, -30, -29, -26, -20, -10, 2, 11, 20, 28, 40, 51, 55, 51, 33, 17, 9, 6, 4, -9, -20, -28, -32, -29, -25, -20, -11, -2, 3, 4, 1, 6, 12, 18, 16, 8, -5, -10, -14, -17, -20, -23, -25, -26, -28, -26, -21, -12, -2, 6, 13, 20, 29, 40, 48, 48, 37, 23, 13, 8, 7, 3, -6, -15, -22, -24, -24, -21, -16, -10, -6, -11, -15, -10, 1, 12, 15, 9, 4, 3, 1, -5, -11, -18, -18, -22, -25, -29, -27, -19, -7, 4, 10, 14, 21, 35, 46, 48, 40, 27, 16, 13, 11, 11, 5, -5, -14, -19, -21, -24, -19, -14, -13, -17, -21, -21, -11, 1, 11, 12, 5, 3, 2, 5, 6, 0, -6, -16, -20, -25, -26, -20, -12, -4, 1, 5, 11, 25, 38, 46, 41, 33, 21, 17, 15, 15, 14, 8, -3, -14, -23, -27, -26, -21, -20, -22, -26, -25, -20, -7, 5, 10, 10, 8, 5, 6, 6, 5, 1, -7, -14, -20, -23, -21, -17, -11, -4, 2, 7, 17, 29, 38, 40, 37, 30, 23, 21, 20, 17, 14, 5, -6, -19, -26, -29, -25, -24, -27, -28, -28, -26, -18, -4, 6, 9, 8, 4, 5, 10, 12, 11, 3, -8, -15, -18, -18, -15, -11, -10, -5, 1, 8, 16, 26, 35, 35, 31, 24, 22, 21, 22, 21, 16, 5, -12, -24, -30, -31, -29, -31, -32, -31, -32, -22, -12, 0, 7, 11, 12, 10, 11, 15, 13, 10, 2, -10, -13, -16, -17, -14, -14, -12, -6, 0, 10, 20, 26, 32, 30, 29, 27, 26, 28, 26, 22, 13, -2, -16, -25, -30, -32, -33, -35, -35, -34, -28, -19, -12, -5, 1, 5, 9, 11, 16, 17, 18, 11, 3, -4, -10, -12, -13, -12, -13, -14, -10, -4, 8, 20, 27, 31, 31, 28, 29, 31, 30, 26, 17, 5, -9, -23, -32, -37, -36, -34, -35, -34, -32, -24, -16, -7, 2, 4, 6, 10, 16, 17, 15, 12, 8, 3, -5, -11, -11, -10, -11, -12, -11, -5, 3, 13, 22, 30, 32, 27, 25, 25, 28, 27, 19, 7, -8, -22, -31, -34, -32, -30, -28, -31, -31, -29, -21, -12, -4, 1, 1, 3, 10, 16, 18, 18, 14, 12, 3, -5, -8, -7, -8, -10, -12, -12, -5, 6, 16, 26, 30, 29, 24, 25, 26, 29, 23, 13, -2, -16, -26, -32, -33, -30, -30, -30, -30, -29, -25, -18, -12, -5, -2, 2, 8, 14, 18, 16, 18, 14, 10, 4, 0, -5, -4, -7, -9, -14, -10, -3, 9, 19, 26, 26, 23, 23, 26, 29, 28, 21, 7, -10, -19, -25, -26, -27, -27, -29, -30, -32, -31, -27, -19, -13, -9, -7, 0, 9, 18, 24, 26, 21, 13, 9, 8, 4, -2, -6, -9, -11, -11, -7, 4, 16, 24, 26, 21, 19, 22, 26, 29, 23, 7, -10, -17, -19, -19, -23, -25, -25, -25, -26, -26, -29, -26, -17, -14, -9, -7, 1, 12, 21, 26, 23, 18, 13, 11, 11, 6, -4, -6, -10, -10, -9, -2, 9, 20, 25, 23, 18, 18, 23, 26, 24, 10, -5, -13, -17, -14, -15, -17, -20, -24, -25, -29, -31, -32, -28, -22, -16, -13, -8, 2, 14, 25, 27, 27, 22, 17, 15, 13, 10, 5, -3, -6, -8, -6, 1, 11, 18, 20, 13, 11, 15, 19, 20, 14, 4, -4, -12, -12, -12, -12, -14, -17, -23, -30, -35, -37, -31, -26, -20, -16, -12, -4, 9, 22, 28, 26, 22, 17, 14, 15, 11, 8, 6, 2, 0, -2, 4, 11, 16, 16, 12, 7, 8, 13, 13, 10, 1, -5, -8, -8, -8, -7, -7, -10, -20, -26, -34, -36, -33, -31, -29, -25, -19, -12, 4, 18, 27, 28, 23, 22, 18, 19, 17, 14, 9, 7, 4, 0, 2, 8, 14, 16, 12, 2, 0, 2, 5, 6, 2, -4, -7, -6, -2, -2, -3, -5, -11, -19, -28, -37, -37, -37, -34, -29, -24, -18, -8, 7, 20, 25, 25, 25, 22, 21, 21, 21, 19, 15, 11, 6, 6, 6, 10, 11, 6, -2, -5, -5, -2, 0, 0, 0, -4, 0, 2, 4, 2, -2, -8, -16, -25, -34, -39, -42, -39, -33, -26, -21, -16, -4, 11, 22, 25, 27, 25, 23, 23, 24, 25, 22, 17, 13, 10, 9, 12, 10, 4, -5, -12, -12, -11, -9, -8, -6, -5, 1, 4, 8, 10, 7, 4, -7, -18, -26, -34, -39, -43, -42, -34, -28, -22, -13, 2, 14, 18, 21, 23, 27, 30, 32, 31, 28, 23, 20, 20, 15, 14, 10, 2, -5, -13, -15, -16, -16, -12, -12, -5, 1, 5, 8, 8, 10, 8, 0, -13, -23, -27, -33, -40, -44, -41, -32, -24, -17, -6, 3, 9, 17, 22, 25, 29, 34, 39, 36, 32, 26, 25, 23, 19, 11, 1, -9, -16, -18, -17, -19, -21, -17, -8, 0, 4, 7, 8, 10, 11, 6, -4, -13, -21, -25, -35, -40, -41, -37, -26, -21, -13, -8, -3, 6, 15, 23, 27, 35, 40, 41, 38, 33, 31, 29, 24, 16, 5, -5, -16, -23, -23, -23, -18, -14, -6, 2, 3, 4, 7, 11, 13, 7, -5, -13, -21, -25, -32, -40, -42, -37, -28, -21, -14, -13, -9, 1, 11, 22, 27, 33, 39, 43, 42, 41, 33, 29, 25, 18, 7, -6, -17, -25, -24, -23, -21, -16, -9, 2, 6, 5, 5, 10, 15, 12, 3, -8, -16, -22, -29, -39, -44, -42, -34, -27, -22, -21, -17, -8, 4, 19, 29, 40, 48, 53, 51, 49, 43, 38, 28, 19, 6, -9, -19, -27, -30, -30, -24, -16, -10, -3, 3, 6, 5, 6, 9, 11, 7, 2, -7, -16, -25, -34, -37, -37, -33, -31, -28, -27, -24, -20, -10, 8, 22, 35, 46, 52, 53, 54, 49, 46, 37, 23, 9, -7, -18, -24, -30, -32, -28, -22, -12, -5, 1, 6, 4, 8, 9, 11, 9, 3, -3, -13, -21, -32, -37, -38, -35, -34, -32, -32, -32, -27, -14, 5, 24, 38, 48, 55, 56, 56, 54, 50, 40, 23, 4, -10, -18, -24, -26, -29, -29, -24, -17, -5, 2, 9, 9, 6, 6, 7, 12, 11, 6, -7, -18, -30, -36, -36, -37, -35, -38, -40, -41, -36, -24, -2, 20, 35, 47, 55, 60, 62, 62, 61, 47, 26, 7, -12, -18, -22, -24, -28, -33, -31, -24, -12, -2, 7, 9, 5, 4, 5, 11, 14, 13, 7, -8, -24, -37, -41, -38, -34, -37, -44, -50, -46, -33, -10, 16, 36, 49, 57, 61, 64, 66, 65, 55, 34, 11, -14, -24, -26, -26, -24, -30, -34, -33, -24, -7, 5, 12, 10, 5, 6, 9, 16, 22, 21, 10, -10, -32, -45, -44, -38, -38, -47, -61, -60, -48, -21, 11, 34, 51, 60, 63, 66, 70, 69, 63, 45, 18, -10, -27, -27, -23, -20, -28, -36, -37, -32, -17, -2, 8, 9, 5, 6, 8, 15, 24, 30, 25, 5, -22, -41, -44, -40, -38, -50, -64, -72, -62, -37, -3, 29, 52, 62, 66, 69, 73, 78, 72, 54, 26, -5, -25, -32, -29, -24, -27, -34, -37, -36, -26, -11, 5, 15, 15, 11, 9, 15, 26, 35, 33, 14, -14, -37, -49, -47, -45, -51, -63, -72, -66, -42, -10, 22, 49, 64, 69, 69, 70, 75, 73, 59, 34, 4, -20, -30, -30, -25, -24, -29, -36, -40, -35, -22, -2, 16, 20, 17, 14, 15, 27, 39, 41, 27, -4, -32, -48, -54, -53, -59, -65, -73, -71, -55, -23, 16, 49, 67, 70, 68, 71, 77, 78, 65, 40, 10, -17, -31, -34, -28, -24, -26, -31, -40, -40, -30, -10, 10, 21, 18, 15, 16, 26, 40, 48, 40, 13, -20, -44, -55, -61, -63, -69, -76, -76, -63, -35, 6, 41, 66, 75, 71, 71, 75, 77, 67, 44, 17, -10, -25, -34, -35, -29, -27, -28, -35, -40, -35, -18, 1, 16, 21, 20, 19, 25, 38, 47, 43, 23, -9, -34, -50, -59, -65, -72, -76, -74, -66, -43, -9, 27, 58, 71, 69, 70, 71, 73, 67, 48, 25, 2, -18, -28, -33, -29, -25, -25, -31, -39, -41, -28, -10, 8, 19, 20, 23, 27, 36, 45, 45, 31, 4, -22, -45, -58, -67, -74, -75, -73, -66, -50, -21, 16, 49, 67, 73, 72, 72, 74, 69, 53, 33, 9, -11, -25, -34, -35, -31, -27, -30, -38, -43, -33, -16, 6, 18, 24, 27, 30, 38, 45, 46, 34, 10, -16, -40, -61, -70, -77, -76, -72, -66, -52, -31, 2, 36, 60, 71, 72, 69, 71, 68, 57, 44, 20, 2, -17, -32, -36, -33, -31, -31, -40, -46, -41, -29, -5, 16, 27, 34, 35, 41, 49, 51, 41, 17, -11, -34, -56, -71, -79, -80, -76, -68, -57, -36, -10, 21, 48, 64, 71, 71, 73, 69, 61, 48, 32, 11, -5, -21, -31, -34, -34, -37, -43, -48, -45, -34, -14, 8, 25, 34, 41, 43, 49, 51, 43, 26, -2, -27, -49, -65, -74, -77, -74, -70, -58, -42, -20, 9, 38, 56, 64, 67, 69, 71, 66, 53, 37, 16, 1, -15, -30, -33, -39, -38, -41, -45, -42, -35, -15, 7, 25, 36, 41, 45, 49, 49, 40, 23, 1, -20, -41, -59, -71, -75, -73, -65, -57, -45, -28, -6, 22, 42, 56, 63, 67, 71, 70, 59, 44, 28, 12, -3, -19, -32, -40, -41, -46, -47, -46, -37, -20, -2, 20, 34, 45, 48, 52, 53, 42, 26, 4, -15, -35, -51, -65, -70, -70, -68, -61, -50, -34, -15, 9, 28, 45, 54, 64, 71, 72, 67, 53, 40, 24, 8, -10, -27, -37, -41, -49, -53, -53, -42, -25, -8, 14, 31, 43, 52, 56, 56, 46, 30, 11, -8, -26, -43, -59, -70, -69, -68, -62, -55, -44, -25, -4, 17, 36, 48, 62, 69, 69, 67, 57, 47, 33, 17, -2, -21, -33, -41, -47, -52, -53, -43, -25, -10, 9, 23, 36, 46, 52, 54, 47, 31, 14, -4, -19, -32, -49, -57, -62, -60, -57, -58, -51, -39, -19, 6, 23, 38, 51, 60, 68, 71, 67, 58, 44, 27, 7, -17, -32, -41, -47, -52, -54, -46, -31, -12, 7, 22, 35, 45, 51, 53, 46, 33, 18, 2, -12, -26, -42, -55, -61, -60, -56, -57, -55, -46, -29, -8, 10, 27, 42, 55, 65, 70, 69, 61, 49, 34, 16, -5, -23, -36, -45, -51, -54, -50, -35, -17, 3, 17, 29, 37, 44, 51, 47, 39, 21, 6, -8, -20, -31, -44, -52, -58, -60, -58, -58, -51, -39, -22, -4, 14, 31, 48, 62, 70, 69, 65, 57, 45, 28, 7, -15, -31, -44, -50, -53, -50, -39, -24, -6, 11, 24, 33, 43, 46, 45, 35, 25, 14, 1, -13, -23, -35, -44, -53, -57, -59, -59, -57, -47, -33, -15, 3, 21, 39, 56, 69, 72, 69, 60, 49, 36, 17, -5, -25, -42, -52, -52, -48, -40, -26, -9, 9, 20, 29, 34, 39, 40, 34, 25, 16, 6, -6, -16, -27, -34, -44, -50, -55, -58, -57, -52, -41, -27, -11, 11, 31, 51, 67, 70, 68, 61, 53, 43, 30, 7, -14, -35, -49, -54, -50, -40, -26, -13, -2, 9, 22, 30, 38, 41, 36, 28, 20, 12, 4, -5, -15, -26, -41, -52, -58, -60, -60, -59, -55, -41, -25, -5, 19, 42, 62, 74, 75, 70, 63, 55, 43, 22, -3, -24, -42, -51, -50, -45, -32, -22, -14, -2, 14, 28, 35, 34, 33, 30, 25, 21, 11, 4, -6, -18, -32, -46, -56, -61, -61, -62, -60, -51, -39, -16, 11, 37, 58, 70, 75, 72, 67, 58, 46, 31, 10, -17, -35, -48, -49, -41, -28, -17, -14, -7, 4, 18, 28, 32, 29, 27, 21, 19, 16, 7, 2, -11, -22, -35, -48, -57, -61, -60, -60, -56, -47, -30, -5, 23, 48, 63, 72, 75, 71, 64, 53, 39, 20, -2, -22, -40, -48, -45, -34, -21, -17, -10, -4, 10, 22, 27, 28, 29, 26, 26, 22, 14, 7, -3, -14, -30, -46, -59, -65, -65, -65, -64, -56, -41, -17, 15, 42, 62, 73, 77, 75, 69, 57, 43, 25, 6, -12, -31, -44, -46, -37, -24, -16, -11, -3, 6, 20, 24, 23, 24, 23, 25, 23, 16, 9, 1, -10, -23, -41, -56, -63, -67, -67, -66, -59, -47, -25, 3, 32, 54, 70, 75, 76, 70, 62, 47, 32, 15, -3, -21, -38, -44, -41, -31, -21, -15, -11, -2, 8, 18, 24, 27, 28, 29, 29, 24, 17, 8, -2, -17, -35, -54, -66, -73, -74, -71, -66, -55, -35, -6, 24, 50, 69, 77, 79, 74, 63, 51, 38, 22, 2, -17, -35, -42, -39, -32, -24, -17, -11, -5, 6, 13, 20, 28, 31, 33, 29, 23, 15, 10, 3, -12, -30, -51, -65, -73, -75, -71, -67, -58, -41, -18, 11, 38, 60, 75, 77, 74, 64, 53, 42, 31, 15, -7, -25, -38, -40, -37, -29, -24, -15, -11, -2, 9, 17, 28, 33, 36, 33, 27, 18, 13, 4, -8, -26, -48, -65, -75, -76, -72, -68, -58, -43, -18, 11, 37, 58, 72, 76, 73, 63, 51, 40, 28, 13, -6, -23, -35, -41, -40, -33, -24, -16, -9, -2, 7, 18, 29, 38, 42, 38, 31, 21, 11, 3, -10, -26, -47, -65, -75, -79, -75, -69, -58, -39, -19, 7, 33, 54, 71, 77, 75, 66, 52, 39, 27, 15, -2, -22, -35, -41, -41, -36, -27, -17, -8, 1, 11, 22, 33, 41, 47, 45, 35, 21, 11, 4, -7, -24, -46, -66, -77, -81, -79, -73, -62, -44, -24, -2, 23, 47, 69, 79, 79, 70, 57, 45, 33, 20, 5, -18, -36, -43, -41, -37, -32, -23, -14, -3, 8, 20, 34, 45, 53, 52, 41, 27, 16, 7, -5, -24, -47, -69, -83, -86, -84, -74, -62, -44, -22, 1, 24, 47, 66, 78, 76, 69, 57, 43, 31, 17, 5, -13, -33, -43, -46, -41, -31, -22, -12, 0, 11, 24, 39, 49, 57, 58, 48, 30, 15, 4, -8, -26, -52, -74, -86, -89, -83, -74, -60, -43, -21, 1, 22, 45, 65, 78, 79, 68, 54, 40, 26, 17, 7, -9, -31, -45, -46, -40, -31, -21, -11, 0, 8, 21, 39, 51, 60, 60, 52, 36, 19, 4, -9, -25, -49, -71, -87, -92, -89, -79, -63, -45, -24, 0, 22, 43, 65, 75, 80, 70, 57, 44, 30, 16, 2, -14, -31, -46, -52, -47, -35, -21, -9, 1, 12, 26, 44, 59, 68, 68, 59, 42, 22, 6, -11, -29, -49, -72, -87, -96, -95, -86, -67, -46, -23, -4, 16, 38, 59, 76, 82, 74, 61, 45, 31, 20, 3, -14, -30, -44, -51, -51, -41, -26, -11, 3, 13, 25, 44, 61, 71, 72, 59, 45, 28, 9, -10, -33, -53, -70, -83, -93, -96, -91, -74, -53, -27, -6, 15, 35, 53, 71, 80, 77, 66, 51, 34, 20, 3, -15, -30, -45, -53, -55, -48, -32, -17, 1, 16, 29, 47, 62, 73, 77, 67, 50, 30, 9, -10, -32, -55, -73, -86, -93, -94, -90, -76, -54, -27, -4, 17, 32, 48, 64, 74, 78, 68, 55, 38, 17, 1, -15, -28, -39, -47, -52, -49, -37, -21, -3, 16, 31, 46, 61, 70, 75, 70, 55, 36, 13, -9, -32, -56, -72, -84, -89, -93, -91, -81, -61, -30, -5, 18, 32, 45, 58, 71, 76, 70, 57, 40, 18, 1, -17, -28, -35, -45, -52, -50, -39, -25, -7, 15, 33, 48, 60, 67, 73, 70, 60, 42, 19, -8, -34, -57, -69, -77, -83, -87, -92, -85, -66, -39, -10, 12, 27, 39, 52, 62, 73, 72, 61, 46, 25, 4, -14, -27, -34, -41, -46, -48, -43, -30, -11, 14, 38, 53, 63, 66, 69, 72, 65, 48, 23, -4, -31, -56, -72, -81, -83, -87, -91, -87, -72, -46, -15, 11, 28, 40, 50, 60, 71, 75, 69, 54, 32, 8, -13, -29, -39, -45, -48, -50, -48, -40, -21, 9, 37, 57, 66, 71, 74, 75, 71, 55, 32, 2, -29, -55, -73, -81, -84, -87, -89, -88, -75, -49, -19, 10, 29, 39, 48, 53, 62, 72, 68, 58, 35, 9, -11, -27, -34, -39, -42, -44, -46, -41, -26, 5, 35, 56, 65, 69, 72, 73, 72, 59, 37, 9, -22, -50, -71, -83, -83, -83, -86, -88, -81, -55, -24, 5, 24, 37, 48, 54, 59, 64, 66, 59, 41, 17, -9, -27, -36, -38, -39, -42, -45, -41, -28, -2, 28, 53, 65, 68, 71, 71, 70, 58, 40, 16, -14, -46, -67, -79, -81, -80, -83, -87, -83, -64, -36, -4, 19, 35, 46, 51, 58, 65, 69, 64, 49, 26, -2, -25, -38, -41, -39, -40, -43, -45, -33, -8, 24, 52, 65, 72, 74, 72, 66, 55, 40, 20, -7, -38, -65, -80, -85, -80, -82, -84, -82, -65, -38, -9, 13, 29, 41, 49, 57, 62, 64, 59, 48, 29, 6, -19, -36, -39, -37, -35, -38, -39, -31, -11, 19, 47, 63, 70, 71, 71, 65, 55, 38, 17, -4, -33, -58, -76, -83, -79, -79, -80, -82, -70, -46, -19, 8, 25, 36, 43, 51, 59, 63, 62, 50, 34, 14, -9, -27, -35, -38, -36, -38, -39, -30, -15, 10, 34, 52, 67, 73, 74, 68, 54, 37, 21, 2, -21, -45, -68, -78, -81, -81, -80, -79, -70, -51, -28, -4, 17, 32, 40, 48, 56, 59, 57, 46, 34, 18, 3, -20, -34, -39, -35, -31, -30, -26, -13, 8, 31, 48, 61, 67, 69, 66, 53, 38, 16, -4, -23, -41, -58, -72, -78, -80, -76, -74, -64, -50, -33, -8, 12, 28, 35, 41, 50, 57, 53, 44, 31, 20, 10, -8, -24, -34, -34, -30, -25, -21, -13, 5, 22, 38, 52, 61, 66, 65, 53, 36, 15, -4, -18, -33, -45, -61, -73, -79, -78, -72, -62, -49, -33, -13, 3, 19, 29, 38, 48, 52, 49, 41, 29, 22, 14, 2, -11, -25, -27, -25, -20, -15, -8, 4, 19, 30, 42, 53, 57, 61, 50, 32, 15, -7, -18, -27, -37, -50, -65, -73, -72, -66, -57, -49, -37, -19, -3, 13, 23, 32, 41, 44, 41, 35, 29, 26, 21, 10, -2, -13, -21, -18, -14, -8, -4, 3, 12, 21, 29, 42, 51, 54, 49, 32, 14, -5, -15, -22, -28, -39, -55, -69, -68, -62, -52, -44, -37, -25, -11, 4, 16, 24, 32, 37, 35, 28, 23, 23, 23, 18, 8, -4, -12, -12, -8, -2, 5, 9, 14, 18, 23, 31, 41, 45, 43, 29, 11, -8, -18, -23, -21, -29, -43, -60, -65, -58, -50, -39, -32, -26, -17, -6, 8, 18, 25, 31, 29, 24, 17, 20, 24, 25, 19, 8, 0, -5, -3, 4, 11, 13, 12, 14, 16, 22, 31, 38, 37, 27, 9, -11, -22, -24, -22, -25, -36, -50, -57, -53, -46, -37, -30, -24, -17, -9, 1, 10, 16, 20, 19, 17, 13, 14, 21, 24, 24, 19, 10, 8, 9, 13, 18, 20, 15, 12, 11, 14, 21, 27, 30, 21, 8, -12, -23, -24, -22, -20, -29, -40, -49, -47, -41, -33, -26, -23, -20, -16, -11, -2, 7, 12, 14, 14, 13, 14, 19, 26, 30, 26, 20, 11, 11, 16, 21, 26, 22, 18, 15, 14, 15, 19, 20, 16, 4, -15, -29, -32, -27, -21, -24, -34, -40, -41, -33, -28, -24, -21, -20, -15, -14, -10, -5, 1, 7, 10, 10, 12, 18, 26, 36, 34, 27, 21, 17, 20, 23, 25, 24, 19, 11, 10, 9, 12, 16, 14, 3, -16, -32, -34, -27, -19, -20, -27, -34, -35, -31, -27, -22, -18, -18, -19, -19, -20, -15, -7, 2, 6, 8, 9, 18, 26, 38, 41, 37, 28, 21, 23, 25, 27, 25, 20, 13, 7, 3, 5, 9, 11, 4, -14, -31, -35, -29, -20, -18, -23, -26, -32, -29, -25, -23, -15, -17, -18, -21, -25, -23, -15, -6, 0, 5, 6, 16, 25, 37, 45, 43, 36, 27, 25, 28, 30, 29, 26, 16, 7, -2, -2, 2, 3, -2, -15, -31, -38, -35, -23, -15, -15, -19, -23, -26, -23, -21, -15, -12, -18, -24, -27, -25, -19, -9, -3, 2, 5, 12, 19, 32, 42, 45, 41, 31, 28, 31, 33, 37, 33, 26, 14, 4, -2, -3, -3, -5, -18, -34, -43, -42, -31, -20, -18, -17, -19, -18, -16, -13, -9, -8, -13, -22, -32, -32, -28, -19, -11, -6, -2, 7, 18, 31, 42, 46, 46, 41, 36, 32, 35, 39, 39, 30, 17, 5, -3, -3, -3, -7, -19, -32, -39, -41, -36, -26, -17, -12, -13, -18, -20, -14, -7, -6, -11, -23, -32, -34, -28, -23, -15, -9, -2, 9, 17, 28, 37, 44, 48, 45, 38, 32, 35, 41, 45, 37, 23, 10, 1, -3, -5, -8, -20, -35, -44, -44, -42, -34, -24, -14, -10, -12, -14, -11, -6, -2, -5, -15, -25, -32, -29, -24, -19, -15, -10, 1, 10, 20, 31, 40, 45, 48, 43, 39, 39, 45, 51, 43, 28, 15, 2, -4, -8, -13, -20, -34, -42, -45, -45, -36, -26, -13, -8, -11, -13, -8, -2, 1, -4, -13, -22, -30, -33, -28, -25, -18, -12, -5, 3, 13, 25, 37, 46, 47, 45, 40, 41, 47, 53, 49, 35, 21, 10, 2, -6, -11, -22, -32, -43, -50, -50, -47, -34, -17, -9, -9, -12, -9, 3, 7, 4, -8, -18, -25, -31, -31, -27, -21, -16, -11, -8, 2, 17, 31, 45, 47, 44, 40, 43, 54, 60, 58, 42, 26, 14, 4, -5, -14, -26, -37, -47, -54, -53, -49, -38, -22, -13, -9, -7, -3, 6, 11, 6, -5, -14, -22, -28, -31, -30, -29, -24, -18, -15, -2, 14, 29, 42, 45, 47, 45, 48, 56, 63, 59, 46, 29, 17, 5, -4, -11, -23, -36, -49, -53, -52, -48, -40, -29, -21, -16, -11, -2, 5, 6, 3, -5, -10, -13, -17, -21, -25, -26, -23, -19, -15, -8, 5, 20, 31, 38, 42, 41, 46, 55, 62, 63, 50, 36, 24, 12, 5, -7, -20, -33, -46, -51, -51, -48, -40, -33, -27, -20, -15, 0, 9, 7, 1, -6, -10, -11, -16, -22, -25, -30, -28, -25, -21, -11, 2, 17, 28, 32, 41, 47, 55, 64, 66, 64, 54, 41, 32, 19, 4, -9, -24, -37, -48, -54, -55, -51, -41, -33, -29, -24, -15, 0, 13, 14, 8, 1, -5, -6, -10, -17, -24, -30, -32, -33, -32, -22, -9, 9, 21, 25, 35, 45, 56, 67, 71, 71, 63, 49, 37, 25, 11, -5, -19, -32, -45, -54, -59, -54, -43, -36, -31, -27, -18, -3, 11, 13, 9, 2, -3, -6, -9, -13, -20, -25, -29, -33, -30, -23, -9, 2, 11, 19, 28, 40, 51, 63, 68, 71, 66, 55, 44, 31, 16, 1, -15, -30, -41, -50, -57, -56, -46, -37, -32, -30, -21, -7, 8, 17, 12, 5, 3, -2, -6, -11, -19, -23, -27, -33, -34, -28, -19, -6, 3, 13, 24, 38, 51, 62, 70, 72, 68, 60, 48, 38, 22, 6, -13, -27, -39, -46, -53, -52, -48, -42, -37, -36, -25, -9, 4, 11, 9, 7, 8, 6, 2, -6, -13, -20, -24, -28, -31, -30, -27, -19, -10, 4, 19, 33, 45, 57, 67, 74, 74, 70, 60, 47, 31, 10, -8, -25, -36, -42, -51, -56, -56, -51, -40, -35, -28, -16, -4, 7, 7, 10, 12, 13, 11, 3, -8, -18, -21, -25, -29, -33, -33, -30, -20, -8, 11, 27, 42, 54, 64, 72, 77, 76, 69, 56, 34, 14, -5, -20, -32, -43, -50, -57, -59, -57, -47, -39, -31, -17, -5, 6, 8, 9, 17, 19, 16, 5, -9, -13, -18, -21, -26, -33, -37, -35, -28, -15, 1, 18, 34, 47, 58, 68, 76, 77, 76, 65, 47, 25, 6, -12, -24, -37, -49, -57, -62, -64, -58, -50, -40, -24, -12, 3, 9, 13, 22, 26, 26, 17, 4, -9, -21, -25, -30, -36, -41, -44, -41, -27, -8, 12, 31, 44, 57, 68, 77, 81, 80, 72, 56, 34, 12, -6, -19, -30, -41, -53, -65, -68, -65, -56, -44, -30, -17, -8, 2, 10, 23, 31, 32, 25, 10, -4, -14, -20, -25, -31, -39, -45, -45, -35, -17, 2, 22, 37, 51, 63, 72, 79, 78, 74, 62, 43, 20, 2, -12, -24, -34, -49, -61, -69, -70, -63, -48, -35, -23, -11, 0, 9, 20, 31, 36, 32, 20, 7, -9, -18, -24, -30, -38, -47, -50, -44, -29, -9, 10, 27, 45, 60, 71, 78, 80, 78, 68, 54, 33, 13, -5, -18, -29, -44, -57, -68, -74, -66, -54, -41, -30, -18, -5, 8, 19, 26, 33, 32, 24, 13, -4, -15, -22, -24, -29, -40, -44, -42, -29, -14, 0, 15, 31, 48, 63, 69, 74, 74, 72, 64, 47, 27, 11, -4, -17, -33, -50, -66, -78, -78, -68, -54, -38, -25, -11, 4, 18, 31, 38, 40, 34, 21, 5, -12, -23, -28, -34, -43, -50, -51, -39, -22, -6, 10, 26, 46, 61, 70, 75, 79, 76, 67, 52, 34, 18, 4, -11, -27, -45, -63, -76, -78, -70, -57, -44, -29, -15, 0, 14, 26, 35, 39, 34, 23, 9, -7, -18, -23, -30, -40, -49, -51, -41, -24, -9, 5, 19, 39, 55, 67, 74, 77, 79, 72, 56, 39, 24, 12, -5, -23, -42, -60, -73, -78, -74, -62, -48, -33, -18, -6, 10, 25, 34, 37, 34, 26, 16, -2, -15, -23, -28, -32, -42, -46, -44, -31, -16, -4, 11, 28, 44, 56, 64, 69, 75, 73, 63, 50, 37, 22, 6, -10, -27, -47, -68, -81, -80, -68, -52, -39, -25, -13, 2, 17, 29, 36, 37, 32, 23, 4, -14, -24, -26, -26, -36, -44, -45, -36, -20, -7, 9, 25, 38, 49, 58, 66, 75, 77, 67, 52, 39, 26, 14, -3, -21, -43, -65, -81, -84, -74, -56, -40, -27, -15, -2, 15, 27, 37, 38, 35, 26, 8, -11, -23, -26, -27, -34, -42, -45, -40, -27, -13, 4, 19, 33, 45, 54, 60, 67, 72, 67, 57, 44, 32, 20, 5, -11, -32, -55, -72, -82, -76, -62, -46, -31, -21, -5, 6, 19, 29, 34, 33, 26, 12, -6, -17, -22, -23, -28, -38, -42, -38, -27, -14, 1, 14, 27, 40, 48, 53, 62, 68, 67, 58, 44, 32, 21, 9, -5, -22, -43, -63, -76, -75, -62, -46, -30, -24, -13, 0, 10, 20, 28, 31, 27, 12, -5, -16, -20, -19, -21, -29, -35, -35, -27, -16, -6, 9, 21, 33, 41, 47, 53, 61, 63, 60, 51, 39, 27, 15, 3, -13, -33, -55, -72, -75, -67, -52, -37, -26, -18, -7, 4, 15, 26, 27, 25, 14, 0, -10, -15, -16, -19, -24, -31, -32, -27, -17, -5, 5, 15, 26, 35, 43, 49, 54, 57, 57, 52, 42, 29, 18, 10, -3, -23, -46, -64, -71, -66, -53, -39, -27, -19, -11, 0, 5, 16, 22, 23, 15, 1, -10, -15, -18, -17, -17, -20, -24, -22, -14, -4, 7, 16, 25, 31, 36, 41, 47, 49, 49, 46, 41, 32, 21, 13, 3, -14, -33, -51, -60, -60, -52, -39, -28, -20, -14, -7, 1, 9, 14, 16, 10, 1, -10, -15, -14, -15, -15, -15, -17, -14, -11, -4, 5, 13, 22, 29, 33, 35, 39, 43, 45, 45, 42, 35, 26, 17, 7, -10, -25, -38, -48, -53, -53, -46, -33, -23, -16, -13, -8, -3, 4, 9, 7, 1, -6, -10, -13, -12, -12, -8, -7, -6, -2, 3, 6, 10, 14, 23, 28, 29, 30, 29, 34, 39, 40, 36, 30, 21, 13, 1, -15, -27, -36, -44, -48, -45, -36, -26, -17, -13, -10, -6, -2, 2, 3, -3, -6, -10, -14, -13, -12, -7, -3, 1, 2, 5, 6, 10, 15, 19, 25, 25, 26, 26, 29, 34, 35, 32, 29, 20, 13, 4, -12, -20, -27, -33, -38, -41, -36, -27, -19, -13, -10, -8, -8, -7, -5, -5, -7, -9, -13, -18, -15, -12, -5, 3, 7, 10, 10, 11, 13, 20, 27, 27, 23, 20, 20, 24, 27, 25, 26, 23, 17, 7, -6, -13, -16, -20, -26, -32, -33, -28, -20, -13, -12, -12, -16, -15, -15, -12, -10, -13, -13, -16, -12, -7, 0, 9, 14, 18, 18, 14, 11, 14, 18, 21, 17, 10, 11, 15, 20, 21, 20, 20, 17, 9, 2, -5, -10, -14, -21, -25, -29, -27, -23, -17, -13, -13, -16, -18, -20, -20, -12, -8, -9, -15, -16, -10, -2, 9, 14, 18, 18, 18, 14, 14, 17, 20, 18, 12, 8, 11, 13, 16, 18, 19, 16, 9, 3, 1, 1, -6, -13, -20, -23, -21, -19, -15, -15, -14, -17, -21, -22, -22, -17, -11, -11, -13, -18, -14, -4, 12, 21, 22, 23, 21, 20, 17, 16, 16, 12, 7, 1, 5, 7, 8, 12, 15, 15, 10, 3, 0, 3, 1, -5, -12, -19, -19, -16, -11, -9, -11, -14, -23, -28, -29, -24, -17, -13, -15, -19, -18, -10, 7, 22, 29, 30, 24, 22, 18, 17, 17, 11, 4, -2, -3, 2, 4, 8, 13, 16, 13, 7, 4, 9, 8, 2, -7, -16, -15, -14, -12, -10, -12, -12, -19, -25, -29, -25, -18, -15, -18, -21, -19, -12, 1, 16, 28, 34, 32, 29, 23, 18, 15, 11, 4, -3, -10, -8, -5, 0, 7, 12, 14, 10, 6, 10, 15, 13, 3, -7, -11, -13, -13, -13, -12, -14, -20, -28, -31, -29, -20, -13, -14, -18, -18, -15, -3, 12, 24, 33, 32, 29, 25, 22, 16, 11, 3, -3, -6, -7, -8, -3, 2, 8, 11, 11, 9, 10, 13, 13, 8, 0, -6, -9, -9, -9, -10, -11, -18, -26, -30, -29, -22, -17, -18, -20, -21, -17, -7, 6, 21, 34, 38, 34, 29, 21, 17, 13, 8, 1, -8, -13, -15, -10, -3, 5, 10, 11, 10, 11, 15, 16, 11, 3, -4, -7, -9, -8, -10, -13, -19, -26, -26, -23, -17, -15, -16, -17, -17, -15, -9, -2, 10, 26, 31, 31, 24, 21, 18, 13, 6, 1, -6, -8, -9, -8, -4, 0, 6, 10, 12, 15, 14, 13, 9, 5, -2, -7, -8, -9, -8, -10, -18, -25, -25, -23, -18, -16, -19, -22, -18, -16, -10, 0, 10, 24, 33, 35, 29, 22, 17, 13, 7, -3, -8, -12, -14, -12, -7, -3, 4, 10, 14, 16, 17, 16, 16, 11, 3, -7, -11, -10, -7, -10, -19, -26, -27, -23, -17, -14, -14, -17, -18, -16, -12, -3, 7, 20, 26, 28, 24, 20, 16, 15, 10, 2, -8, -13, -11, -7, -2, -2, 4, 6, 9, 14, 17, 19, 15, 8, -4, -12, -15, -11, -5, -8, -18, -25, -24, -17, -9, -6, -7, -11, -15, -15, -13, -6, 4, 11, 15, 16, 15, 16, 13, 9, 5, 1, -3, -7, -5, -2, 3, 5, 6, 8, 10, 14, 17, 18, 14, 3, -8, -15, -13, -9, -6, -9, -19, -22, -19, -13, -6, -4, -5, -8, -13, -15, -10, -5, 5, 8, 8, 8, 11, 14, 14, 8, 2, 1, 1, 2, -2, 1, 5, 6, 7, 7, 6, 11, 13, 16, 13, 3, -6, -13, -14, -8, -5, -6, -15, -20, -15, -10, -5, -2, -6, -6, -8, -12, -10, -8, -3, 5, 3, 3, 5, 7, 10, 6, 2, -3, -2, 2, 8, 9, 12, 11, 8, 9, 8, 11, 13, 11, 10, 0, -12, -20, -21, -13, -10, -11, -14, -16, -10, -3, 4, 8, 5, 2, -2, -4, -4, -7, -4, -4, -5, -7, -8, -5, 0, 2, 2, 0, 1, 6, 11, 15, 19, 19, 18, 14, 10, 12, 12, 11, 6, -6, -16, -23, -23, -17, -13, -12, -12, -13, -8, -2, 8, 13, 13, 8, 4, 1, -3, -3, -3, -4, -11, -16, -16, -13, -9, -5, -4, -2, 1, 6, 13, 17, 21, 24, 23, 18, 14, 10, 11, 12, 8, -3, -16, -26, -27, -20, -17, -21, -21, -17, -7, 2, 10, 16, 19, 18, 13, 10, 5, 2, -2, -5, -14, -22, -26, -21, -15, -11, -11, -6, -2, 6, 16, 22, 27, 28, 28, 23, 17, 13, 10, 12, 7, -4, -18, -29, -32, -24, -20, -21, -22, -18, -5, 5, 14, 19, 21, 20, 17, 13, 8, 5, -2, -9, -18, -26, -26, -21, -14, -12, -11, -8, -2, 10, 16, 21, 24, 25, 27, 24, 16, 11, 6, 7, 6, -4, -16, -25, -29, -25, -19, -19, -22, -18, -7, 6, 15, 17, 18, 19, 18, 15, 10, 8, 3, -5, -15, -24, -30, -27, -19, -15, -15, -13, -8, 5, 14, 20, 25, 28, 31, 30, 26, 18, 11, 9, 7, -2, -14, -27, -33, -30, -25, -25, -27, -26, -15, 2, 17, 22, 23, 23, 22, 22, 18, 14, 7, -4, -14, -24, -31, -30, -25, -19, -16, -16, -11, -3, 8, 17, 24, 29, 31, 31, 29, 22, 17, 12, 8, 2, -12, -26, -36, -35, -30, -26, -26, -29, -20, -5, 13, 24, 26, 26, 26, 28, 23, 19, 11, 1, -9, -24, -34, -33, -30, -24, -21, -21, -17, -11, 1, 9, 19, 27, 33, 34, 30, 28, 24, 21, 16, 7, -6, -23, -35, -40, -36, -33, -31, -32, -27, -13, 3, 17, 25, 29, 34, 34, 30, 23, 17, 11, 0, -14, -27, -32, -33, -30, -26, -21, -18, -15, -9, 1, 11, 22, 29, 32, 33, 30, 28, 23, 21, 13, 3, -15, -30, -37, -38, -35, -35, -33, -28, -18, -5, 10, 22, 30, 37, 36, 32, 26, 21, 14, 7, -6, -19, -28, -34, -32, -27, -21, -20, -21, -20, -11, 5, 17, 25, 29, 30, 33, 35, 31, 27, 19, 8, -7, -25, -37, -42, -41, -39, -35, -30, -22, -11, 4, 21, 32, 38, 39, 36, 29, 22, 15, 9, -4, -15, -24, -32, -35, -31, -24, -18, -18, -19, -14, -3, 11, 21, 27, 31, 32, 34, 34, 31, 27, 18, 1, -19, -33, -39, -38, -40, -39, -35, -28, -17, -3, 14, 28, 37, 41, 40, 34, 30, 24, 18, 7, -6, -20, -30, -36, -34, -30, -26, -26, -27, -26, -16, 0, 16, 26, 30, 33, 36, 42, 43, 38, 27, 10, -10, -27, -39, -43, -43, -43, -40, -34, -26, -14, 2, 21, 36, 42, 40, 36, 33, 30, 24, 16, 5, -11, -25, -34, -35, -32, -29, -30, -31, -31, -27, -15, 5, 21, 27, 30, 34, 42, 51, 48, 40, 20, -3, -21, -32, -38, -40, -43, -42, -38, -30, -18, -3, 15, 29, 40, 41, 39, 34, 31, 28, 20, 10, -4, -18, -29, -33, -34, -34, -35, -37, -38, -34, -21, -6, 12, 22, 26, 33, 44, 55, 56, 46, 26, 5, -11, -25, -36, -42, -47, -47, -43, -37, -24, -11, 9, 25, 36, 38, 38, 40, 39, 39, 28, 17, 3, -10, -23, -30, -37, -38, -42, -44, -43, -40, -30, -16, 3, 17, 26, 34, 44, 57, 61, 52, 34, 9, -7, -21, -30, -38, -46, -49, -48, -39, -27, -13, 5, 22, 32, 35, 35, 37, 41, 43, 33, 19, 4, -8, -16, -25, -32, -39, -42, -44, -42, -41, -33, -20, -4, 11, 21, 28, 38, 49, 58, 54, 36, 16, -6, -16, -21, -28, -36, -46, -49, -42, -29, -17, 0, 13, 26, 30, 30, 35, 41, 47, 41, 25, 9, -4, -12, -17, -28, -38, -46, -52, -51, -49, -39, -23, -9, 4, 12, 23, 39, 54, 66, 62, 43, 23, 2, -10, -16, -26, -36, -45, -51, -50, -37, -20, 0, 16, 27, 28, 29, 38, 47, 50, 44, 28, 13, -2, -10, -16, -26, -35, -45, -55, -57, -56, -44, -27, -13, -4, 5, 17, 34, 53, 64, 64, 46, 29, 13, 1, -8, -17, -28, -39, -48, -51, -42, -26, -8, 9, 18, 20, 24, 34, 46, 53, 47, 33, 15, 4, -4, -13, -22, -35, -47, -56, -59, -56, -48, -32, -18, -8, 3, 14, 33, 52, 65, 64, 49, 31, 17, 5, -3, -13, -25, -36, -45, -49, -44, -31, -14, 7, 16, 21, 21, 31, 48, 57, 53, 38, 20, 8, -3, -9, -21, -35, -47, -57, -62, -62, -54, -38, -22, -12, -5, 7, 26, 49, 66, 69, 56, 37, 24, 15, 6, -4, -17, -30, -43, -53, -47, -34, -18, -2, 9, 14, 17, 29, 46, 58, 56, 43, 25, 13, 2, -5, -15, -30, -45, -59, -66, -65, -57, -43, -28, -16, -10, 2, 21, 44, 66, 71, 62, 43, 28, 19, 13, 3, -12, -25, -42, -51, -50, -38, -18, -3, 5, 12, 17, 30, 48, 59, 58, 45, 26, 11, 0, -6, -15, -29, -45, -63, -71, -68, -58, -41, -28, -19, -12, -4, 16, 42, 62, 70, 61, 43, 29, 21, 16, 8, -6, -20, -35, -45, -45, -37, -21, -6, 3, 8, 14, 24, 42, 54, 58, 47, 29, 16, 3, -3, -12, -27, -42, -62, -73, -74, -66, -52, -34, -23, -14, -5, 12, 38, 60, 72, 68, 49, 34, 23, 17, 10, -3, -18, -31, -42, -42, -36, -20, -4, 5, 9, 11, 22, 37, 51, 55, 46, 29, 13, 2, -9, -14, -25, -38, -53, -67, -72, -67, -53, -35, -23, -17, -10, 6, 32, 55, 69, 67, 53, 36, 26, 19, 12, 2, -13, -26, -37, -40, -36, -24, -7, 3, 9, 13, 20, 36, 49, 52, 47, 32, 17, 3, -12, -19, -29, -38, -52, -66, -75, -72, -56, -36, -20, -15, -10, 2, 25, 48, 63, 63, 52, 39, 28, 20, 14, 5, -6, -19, -30, -38, -35, -25, -8, 4, 8, 11, 17, 33, 47, 54, 47, 34, 18, 4, -9, -19, -28, -40, -53, -65, -75, -74, -60, -41, -22, -15, -12, -2, 18, 43, 59, 63, 55, 41, 31, 27, 20, 13, 3, -11, -24, -35, -34, -26, -11, 2, 8, 9, 11, 22, 37, 47, 49, 39, 22, 6, -7, -19, -26, -36, -48, -60, -74, -77, -66, -47, -26, -13, -8, 1, 15, 36, 53, 63, 56, 45, 30, 22, 16, 10, 5, -7, -19, -32, -34, -25, -7, 8, 16, 17, 17, 23, 37, 48, 51, 40, 22, 4, -14, -24, -33, -39, -49, -61, -72, -77, -66, -47, -27, -13, -5, 1, 13, 30, 47, 59, 57, 47, 31, 23, 17, 15, 6, -5, -18, -26, -30, -24, -10, 8, 19, 21, 20, 22, 30, 40, 48, 41, 25, 3, -17, -29, -32, -37, -46, -59, -70, -73, -65, -46, -27, -14, -4, 3, 15, 29, 41, 52, 54, 45, 31, 19, 15, 15, 9, 1, -14, -26, -27, -21, -8, 10, 17, 23, 23, 23, 32, 39, 45, 44, 29, 7, -16, -32, -40, -42, -49, -61, -72, -76, -69, -50, -28, -12, -2, 5, 17, 31, 43, 48, 49, 44, 34, 24, 15, 13, 9, 5, -8, -24, -27, -21, -7, 10, 20, 25, 29, 29, 32, 36, 41, 41, 34, 14, -12, -35, -46, -49, -52, -61, -74, -78, -73, -56, -31, -14, 2, 10, 19, 31, 44, 54, 53, 47, 34, 24, 16, 9, 4, -2, -12, -25, -28, -22, -7, 9, 23, 32, 36, 36, 36, 37, 42, 42, 33, 15, -14, -36, -50, -57, -56, -62, -74, -81, -77, -59, -36, -15, 2, 11, 20, 31, 44, 56, 56, 51, 39, 26, 15, 7, 1, -3, -13, -26, -33, -31, -14, 9, 25, 36, 41, 40, 41, 40, 44, 44, 35, 17, -13, -39, -54, -61, -64, -69, -76, -81, -78, -63, -39, -15, 4, 14, 24, 35, 45, 54, 56, 53, 41, 25, 14, 7, 3, -4, -14, -26, -34, -31, -15, 9, 25, 36, 41, 43, 44, 43, 46, 45, 35, 16, -9, -31, -49, -63, -69, -75, -78, -84, -79, -66, -45, -22, 0, 13, 23, 35, 48, 56, 58, 53, 43, 30, 19, 10, 4, -7, -18, -26, -33, -30, -17, 4, 24, 37, 44, 50, 50, 49, 46, 43, 35, 16, -7, -30, -52, -65, -75, -78, -83, -85, -82, -70, -50, -26, -4, 14, 26, 39, 53, 63, 64, 59, 49, 35, 18, 6, -2, -13, -25, -35, -40, -36, -22, 3, 26, 38, 47, 54, 60, 61, 57, 50, 39, 20, -5, -26, -49, -66, -80, -87, -91, -93, -88, -74, -54, -34, -12, 8, 24, 40, 55, 68, 70, 66, 55, 41, 26, 14, 6, -9, -25, -37, -43, -39, -28, -9, 15, 32, 41, 48, 59, 65, 65, 58, 45, 25, 5, -17, -38, -61, -77, -91, -97, -100, -94, -79, -64, -44, -23, -2, 24, 42, 57, 72, 77, 74, 63, 48, 33, 21, 10, -7, -27, -43, -45, -41, -29, -14, 4, 26, 40, 49, 58, 66, 69, 64, 48, 29, 7, -13, -31, -53, -73, -89, -100, -102, -95, -83, -67, -51, -29, -7, 17, 37, 55, 72, 81, 77, 67, 55, 40, 25, 12, -4, -22, -40, -45, -42, -31, -19, -4, 15, 34, 48, 55, 63, 67, 66, 57, 41, 20, -4, -25, -46, -69, -88, -104, -110, -106, -95, -79, -63, -39, -13, 15, 39, 60, 75, 88, 91, 81, 66, 44, 27, 13, -3, -22, -41, -50, -48, -38, -26, -13, 6, 29, 46, 55, 62, 66, 69, 63, 48, 26, 5, -14, -33, -57, -84, -105, -115, -113, -102, -88, -73, -53, -26, 1, 31, 57, 78, 91, 95, 88, 75, 60, 41, 22, 1, -19, -38, -51, -53, -48, -36, -22, -6, 19, 39, 53, 62, 65, 69, 67, 55, 36, 14, -6, -28, -54, -79, -100, -111, -116, -110, -98, -83, -61, -35, -6, 26, 53, 75, 89, 96, 96, 87, 71, 50, 29, 10, -9, -30, -44, -53, -50, -45, -32, -19, 2, 23, 43, 55, 62, 66, 66, 62, 49, 30, 11, -12, -39, -70, -95, -112, -118, -118, -109, -94, -74, -48, -18, 17, 47, 70, 88, 98, 99, 95, 80, 61, 37, 14, -9, -26, -43, -51, -52, -48, -40, -25, -6, 17, 37, 52, 57, 63, 64, 62, 55, 36, 17, -8, -34, -62, -86, -106, -117, -118, -110, -99, -83, -57, -27, 10, 42, 67, 85, 96, 101, 101, 91, 69, 46, 21, 1, -21, -38, -49, -54, -49, -44, -35, -18, 2, 24, 44, 55, 64, 67, 63, 59, 46, 29, 7, -21, -51, -79, -104, -117, -122, -117, -108, -94, -70, -40, 0, 34, 63, 85, 96, 104, 105, 99, 82, 59, 31, 4, -20, -37, -46, -51, -51, -50, -44, -28, -8, 17, 38, 53, 60, 65, 67, 64, 54, 40, 18, -10, -40, -71, -98, -115, -121, -118, -113, -103, -82, -52, -14, 22, 53, 77, 94, 106, 109, 104, 93, 76, 50, 21, -11, -33, -43, -48, -53, -56, -56, -46, -27, 2, 29, 48, 58, 62, 63, 62, 58, 49, 33, 5, -27, -57, -87, -108, -119, -118, -114, -106, -91, -68, -31, 8, 42, 69, 88, 102, 110, 110, 100, 83, 60, 33, 3, -23, -39, -46, -52, -57, -57, -51, -35, -14, 15, 38, 54, 63, 65, 66, 58, 51, 40, 17, -11, -44, -76, -101, -114, -116, -111, -106, -96, -77, -47, -11, 28, 58, 81, 97, 109, 112, 105, 95, 77, 53, 23, -9, -30, -45, -52, -58, -64, -61, -52, -35, -9, 20, 44, 62, 67, 67, 65, 62, 54, 35, 7, -24, -60, -91, -110, -119, -116, -112, -105, -90, -65, -31, 8, 43, 73, 94, 109, 117, 113, 105, 91, 68, 39, 4, -24, -43, -56, -64, -67, -67, -61, -47, -21, 9, 35, 55, 63, 66, 66, 61, 56, 46, 23, -10, -46, -81, -100, -111, -115, -112, -107, -94, -75, -48, -12, 28, 59, 84, 103, 116, 120, 114, 103, 81, 56, 22, -10, -35, -53, -64, -71, -73, -71, -59, -39, -10, 19, 43, 60, 66, 68, 67, 64, 53, 33, 7, -27, -64, -91, -108, -115, -113, -108, -97, -82, -59, -27, 11, 46, 75, 98, 112, 119, 117, 109, 89, 64, 34, 4, -24, -50, -62, -69, -69, -70, -65, -49, -23, 8, 32, 52, 61, 64, 65, 64, 55, 39, 15, -16, -46, -76, -97, -109, -110, -107, -102, -91, -71, -42, -4, 34, 66, 90, 106, 116, 121, 118, 101, 78, 47, 15, -15, -44, -60, -70, -73, -75, -74, -63, -39, -7, 23, 45, 60, 66, 69, 69, 62, 49, 29, 1, -32, -65, -94, -108, -112, -109, -102, -97, -83, -58, -22, 18, 54, 84, 103, 116, 121, 120, 112, 91, 63, 29, -6, -34, -54, -66, -75, -79, -81, -72, -50, -22, 9, 33, 50, 59, 67, 70, 70, 60, 43, 13, -20, -51, -78, -97, -107, -111, -109, -105, -94, -72, -37, 5, 42, 72, 96, 114, 124, 127, 118, 100, 75, 42, 10, -22, -47, -62, -72, -79, -84, -82, -64, -35, -2, 23, 39, 50, 61, 69, 71, 66, 51, 27, -6, -36, -62, -81, -96, -104, -105, -106, -101, -83, -52, -11, 27, 57, 82, 103, 120, 127, 122, 107, 82, 53, 19, -12, -39, -55, -65, -73, -81, -81, -67, -40, -8, 16, 30, 41, 52, 62, 68, 66, 56, 34, 3, -28, -53, -71, -86, -96, -102, -106, -103, -88, -62, -25, 15, 47, 72, 90, 109, 120, 123, 115, 93, 63, 31, 1, -24, -40, -52, -64, -76, -82, -73, -50, -22, 1, 18, 27, 39, 51, 63, 67, 61, 44, 18, -13, -38, -53, -69, -83, -96, -105, -103, -93, -69, -36, -3, 30, 56, 77, 95, 111, 116, 113, 97, 72, 42, 13, -12, -25, -38, -54, -70, -79, -74, -57, -32, -11, 4, 15, 26, 40, 55, 65, 62, 51, 28, 1, -24, -40, -56, -73, -89, -101, -102, -95, -79, -50, -17, 16, 47, 68, 88, 104, 114, 115, 102, 80, 53, 24, 0, -18, -31, -45, -60, -73, -74, -63, -42, -21, -6, 6, 16, 28, 45, 56, 59, 51, 35, 14, -9, -26, -41, -57, -73, -87, -97, -95, -85, -62, -32, -2, 26, 50, 71, 91, 105, 111, 105, 89, 64, 40, 16, -4, -20, -35, -49, -64, -70, -68, -53, -35, -18, -6, 5, 14, 29, 45, 55, 54, 39, 21, 4, -13, -25, -42, -63, -77, -89, -90, -80, -66, -44, -19, 10, 35, 57, 76, 93, 104, 104, 91, 68, 48, 29, 13, -6, -24, -42, -56, -63, -61, -54, -42, -27, -17, -6, 5, 18, 33, 44, 47, 39, 25, 10, 0, -14, -29, -50, -67, -79, -85, -81, -70, -53, -32, -5, 24, 47, 67, 84, 98, 103, 95, 77, 56, 37, 22, 6, -14, -34, -48, -56, -57, -52, -48, -37, -28, -17, -6, 8, 23, 34, 41, 38, 28, 15, 4, -4, -16, -38, -59, -73, -78, -75, -66, -54, -37, -19, 7, 32, 53, 72, 87, 95, 92, 78, 58, 44, 32, 20, 2, -21, -38, -47, -48, -47, -46, -42, -36, -26, -14, -5, 9, 20, 32, 35, 30, 19, 12, 8, -5, -25, -48, -63, -71, -70, -63, -58, -44, -26, -6, 20, 40, 59, 79, 92, 93, 83, 60, 47, 37, 29, 13, -10, -28, -40, -44, -44, -48, -47, -41, -33, -22, -13, 0, 14, 29, 36, 34, 24, 18, 15, 4, -13, -39, -60, -69, -72, -68, -62, -51, -34, -13, 9, 31, 52, 73, 88, 95, 87, 70, 55, 45, 35, 20, -2, -23, -36, -42, -47, -48, -51, -50, -40, -30, -17, -8, 7, 23, 36, 37, 30, 22, 19, 13, -3, -24, -49, -65, -71, -71, -64, -54, -40, -20, -3, 21, 44, 65, 85, 92, 87, 72, 57, 48, 39, 29, 11, -12, -27, -36, -41, -42, -47, -49, -45, -37, -28, -17, -4, 13, 28, 33, 29, 26, 23, 17, 6, -11, -33, -53, -64, -66, -62, -55, -44, -29, -12, 10, 31, 51, 71, 84, 85, 77, 61, 50, 41, 36, 22, 2, -17, -33, -38, -42, -45, -48, -46, -41, -34, -23, -9, 7, 24, 35, 32, 28, 23, 17, 10, -4, -26, -49, -64, -68, -64, -58, -46, -32, -13, 8, 28, 45, 65, 78, 82, 76, 62, 52, 45, 37, 23, 6, -10, -26, -35, -41, -45, -46, -48, -48, -39, -27, -11, 3, 14, 23, 27, 28, 25, 23, 15, 2, -17, -34, -52, -60, -61, -56, -44, -32, -17, -3, 16, 34, 54, 66, 73, 68, 58, 47, 42, 37, 29, 17, 3, -14, -25, -31, -36, -39, -44, -48, -44, -33, -20, -9, 2, 13, 22, 26, 24, 20, 14, 5, -7, -22, -39, -50, -55, -51, -43, -32, -20, -7, 10, 28, 44, 57, 65, 67, 64, 54, 44, 36, 28, 18, 4, -9, -23, -32, -39, -42, -46, -44, -38, -29, -19, -12, -4, 10, 22, 27, 22, 14, 8, 1, -6, -17, -30, -43, -49, -47, -38, -26, -18, -10, 3, 17, 34, 45, 54, 59, 57, 53, 45, 37, 30, 22, 11, -3, -14, -24, -34, -40, -45, -43, -39, -29, -21, -14, -6, 3, 16, 20, 17, 10, 3, 0, -6, -15, -25, -33, -38, -37, -31, -21, -12, -6, 5, 15, 27, 39, 46, 50, 51, 47, 44, 36, 29, 20, 10, 1, -10, -18, -27, -36, -40, -42, -37, -29, -21, -14, -7, 1, 10, 16, 10, 3, -2, -3, -6, -12, -22, -28, -30, -28, -23, -16, -11, -7, 0, 7, 19, 31, 42, 47, 47, 46, 46, 40, 33, 21, 10, 2, -6, -12, -24, -33, -37, -38, -36, -31, -21, -14, -7, -2, 2, 7, 8, 4, -2, -7, -12, -14, -19, -23, -24, -20, -16, -11, -6, -2, 3, 9, 16, 24, 33, 37, 40, 44, 44, 40, 33, 22, 13, 5, -3, -8, -21, -30, -35, -34, -32, -30, -23, -13, -6, -3, -3, -2, -2, -4, -7, -9, -12, -13, -13, -14, -14, -11, -12, -4, -2, 2, 0, 3, 10, 18, 27, 32, 35, 38, 40, 37, 32, 23, 13, 8, 2, -4, -11, -22, -27, -31, -30, -29, -24, -14, -7, -8, -7, -10, -10, -10, -10, -11, -12, -13, -12, -11, -11, -7, -2, 4, 5, 3, -2, 0, 8, 15, 21, 26, 30, 32, 37, 37, 32, 26, 16, 10, 4, -4, -9, -16, -21, -26, -29, -28, -23, -15, -11, -9, -11, -13, -14, -14, -13, -13, -12, -13, -12, -8, -3, 3, 6, 8, 10, 7, 1, -3, 2, 8, 17, 22, 22, 27, 32, 37, 35, 29, 18, 11, 2, -4, -8, -14, -17, -21, -23, -25, -22, -17, -11, -9, -11, -16, -16, -16, -16, -14, -15, -14, -11, -5, 0, 4, 5, 6, 7, 6, 4, 0, 3, 8, 16, 21, 20, 24, 28, 34, 35, 29, 17, 8, 3, 1, -3, -9, -15, -20, -21, -23, -22, -21, -17, -13, -14, -18, -23, -22, -17, -13, -10, -9, -8, 0, 6, 9, 10, 8, 6, 6, 4, 0, -2, 1, 10, 17, 20, 22, 25, 29, 31, 29, 20, 10, 2, -2, 0, -5, -11, -18, -20, -19, -19, -19, -18, -16, -14, -18, -26, -26, -22, -16, -13, -9, -6, 1, 7, 10, 10, 7, 7, 7, 5, 0, -4, -2, 7, 14, 19, 22, 26, 30, 32, 30, 22, 13, 6, 1, -2, -7, -13, -16, -18, -19, -19, -21, -21, -19, -17, -16, -23, -25, -23, -17, -10, -9, -4, 2, 8, 10, 12, 9, 7, 5, 4, 2, -3, -2, 3, 9, 18, 23, 28, 29, 28, 27, 26, 19, 12, 6, 0, -7, -11, -15, -17, -20, -21, -20, -22, -23, -25, -24, -26, -27, -25, -20, -13, -5, 3, 9, 11, 15, 17, 15, 10, 4, 0, -4, -5, -4, 2, 5, 13, 19, 25, 29, 28, 26, 25, 20, 16, 11, 2, -5, -10, -10, -10, -14, -17, -21, -24, -26, -29, -27, -28, -28, -26, -23, -17, -8, 1, 12, 15, 16, 14, 13, 10, 6, 0, -5, -6, -5, 1, 6, 12, 20, 27, 30, 28, 24, 23, 21, 17, 11, 4, -6, -9, -10, -10, -11, -16, -18, -21, -24, -26, -29, -28, -27, -25, -23, -18, -11, -2, 11, 15, 15, 12, 11, 9, 6, 1, -6, -6, -2, 3, 7, 11, 19, 26, 28, 26, 22, 21, 23, 24, 17, 10, 4, 0, -2, -5, -10, -15, -20, -25, -32, -36, -36, -35, -32, -30, -26, -19, -10, 2, 14, 21, 21, 17, 13, 10, 7, 1, -5, -5, -6, -4, 0, 6, 12, 19, 22, 24, 20, 21, 24, 29, 28, 20, 13, 8, 3, 2, -4, -9, -16, -27, -34, -41, -44, -41, -38, -35, -31, -27, -18, -3, 13, 26, 29, 23, 18, 14, 11, 8, 4, -2, -8, -11, -9, -6, 4, 9, 16, 17, 16, 16, 23, 33, 37, 33, 26, 19, 12, 8, 1, -7, -15, -30, -41, -50, -53, -50, -43, -38, -34, -28, -17, -3, 13, 26, 30, 26, 19, 14, 12, 9, 4, -2, -10, -14, -13, -7, 4, 9, 12, 13, 13, 17, 25, 32, 40, 39, 32, 24, 15, 11, 8, 1, -10, -27, -43, -51, -55, -52, -49, -45, -40, -32, -21, -8, 9, 23, 31, 30, 24, 19, 17, 16, 11, 4, -7, -15, -18, -14, -6, 2, 5, 7, 9, 14, 24, 35, 45, 48, 45, 34, 25, 16, 8, 2, -11, -27, -46, -59, -64, -61, -53, -46, -40, -35, -24, -9, 8, 23, 30, 31, 27, 24, 21, 17, 12, 4, -6, -15, -19, -17, -12, -3, 3, 4, 6, 12, 25, 37, 45, 47, 47, 43, 35, 23, 12, 2, -10, -24, -42, -60, -71, -71, -63, -55, -45, -36, -22, -7, 9, 22, 30, 35, 34, 31, 24, 19, 13, 6, -3, -13, -20, -21, -16, -9, -3, -2, 4, 11, 26, 38, 45, 50, 49, 48, 42, 31, 16, 4, -9, -21, -38, -59, -72, -77, -70, -61, -53, -41, -26, -9, 7, 17, 26, 34, 41, 41, 35, 25, 17, 9, 0, -10, -21, -24, -22, -15, -9, -7, -2, 10, 25, 39, 44, 47, 49, 52, 50, 39, 22, 6, -8, -20, -34, -54, -70, -78, -77, -68, -61, -49, -33, -15, 3, 16, 25, 32, 43, 49, 47, 37, 25, 16, 3, -10, -22, -29, -27, -22, -15, -12, -7, 7, 25, 42, 47, 50, 53, 57, 57, 46, 31, 11, -5, -22, -39, -56, -72, -81, -85, -81, -71, -56, -36, -16, 4, 19, 29, 37, 48, 55, 56, 48, 34, 20, 7, -10, -25, -32, -34, -28, -21, -17, -14, 0, 20, 40, 50, 51, 53, 58, 61, 53, 39, 18, -2, -18, -36, -53, -70, -80, -85, -86, -79, -67, -46, -23, -2, 17, 27, 35, 44, 55, 62, 57, 44, 26, 9, -10, -23, -29, -32, -28, -24, -20, -15, -4, 15, 35, 47, 50, 49, 53, 57, 53, 43, 24, 5, -14, -32, -50, -64, -5, 0, -2, -3, -3, -3, -3, -2, -2, 1, 2, 3, 5, 8, 11, 11, 10, 8, 5, 1, -6, -13, -19, -21, -18, -15, -13, -10, -7, -2, 4, 8, 12, 17, 28, 33, 29, 23, 14, 7, -5, -19, -33, -42, -36, -28, -24, -17, -13, -8, 1, 7, 15, 23, 33, 42, 42, 35, 26, 15, 0, -16, -30, -44, -45, -34, -27, -20, -16, -13, -4, 4, 12, 21, 29, 40, 45, 40, 30, 20, 6, -13, -25, -38, -45, -38, -31, -24, -18, -15, -10, -4, 5, 17, 27, 35, 44, 43, 37, 27, 15, -4, -19, -31, -44, -44, -35, -30, -22, -19, -16, -8, 2, 15, 25, 32, 42, 47, 42, 32, 18, 0, -16, -26, -39, -45, -38, -31, -25, -19, -18, -14, -5, 11, 23, 29, 39, 46, 45, 38, 25, 7, -8, -18, -31, -44, -43, -35, -30, -25, -25, -20, -9, 7, 21, 27, 36, 48, 51, 44, 32, 14, -3, -16, -28, -42, -46, -41, -33, -27, -24, -23, -15, 1, 16, 27, 33, 42, 47, 46, 38, 21, 5, -9, -21, -34, -44, -45, -39, -31, -28, -26, -20, -8, 9, 25, 34, 41, 49, 51, 47, 31, 11, -6, -18, -30, -42, -48, -45, -36, -28, -26, -23, -12, 6, 23, 33, 38, 43, 51, 50, 36, 15, 0, -12, -22, -35, -50, -50, -40, -31, -29, -27, -18, 1, 20, 32, 36, 43, 52, 56, 45, 23, 2, -10, -20, -33, -48, -56, -49, -36, -30, -26, -18, -5, 17, 33, 39, 40, 46, 52, 49, 32, 9, -8, -18, -26, -40, -54, -53, -39, -30, -28, -23, -12, 10, 31, 39, 38, 42, 54, 54, 41, 17, -5, -15, -22, -35, -53, -59, -47, -36, -30, -24, -14, 6, 27, 40, 42, 43, 51, 56, 46, 26, 3, -13, -22, -33, -49, -61, -55, -41, -32, -26, -18, 0, 22, 38, 45, 43, 48, 55, 50, 33, 11, -10, -21, -29, -43, -59, -60, -46, -35, -28, -18, -6, 15, 35, 45, 46, 45, 52, 53, 41, 20, -6, -19, -26, -38, -54, -62, -53, -39, -29, -19, -11, 6, 29, 44, 48, 45, 47, 52, 49, 32, 5, -18, -26, -32, -45, -61, -61, -48, -35, -23, -14, -2, 22, 42, 52, 50, 46, 50, 50, 38, 12, -15, -26, -31, -43, -59, -65, -53, -37, -25, -16, -6, 16, 40, 53, 53, 47, 49, 51, 42, 22, -10, -27, -31, -38, -54, -67, -63, -46, -27, -18, -7, 10, 31, 52, 59, 53, 48, 50, 46, 32, 3, -24, -34, -39, -50, -66, -68, -54, -35, -20, -8, 6, 23, 47, 62, 59, 52, 50, 48, 37, 13, -18, -35, -40, -46, -62, -72, -63, -43, -25, -10, 6, 20, 41, 59, 63, 55, 49, 46, 39, 21, -9, -31, -39, -42, -52, -68, -68, -52, -32, -17, -4, 9, 31, 54, 66, 63, 54, 51, 44, 32, 6, -26, -40, -44, -51, -65, -72, -61, -41, -23, -5, 9, 25, 48, 64, 66, 59, 54, 46, 33, 12, -17, -36, -45, -51, -62, -73, -67, -48, -31, -11, 8, 21, 44, 64, 70, 64, 57, 49, 36, 20, -8, -34, -47, -52, -58, -68, -73, -59, -40, -19, 4, 17, 36, 58, 72, 73, 65, 56, 41, 26, 4, -24, -44, -55, -63, -69, -73, -66, -51, -28, -2, 18, 32, 51, 67, 75, 72, 62, 46, 29, 11, -13, -37, -54, -64, -70, -71, -70, -58, -38, -13, 14, 30, 48, 64, 73, 76, 69, 52, 34, 15, -7, -31, -50, -62, -69, -71, -71, -66, -47, -19, 8, 26, 40, 58, 73, 81, 76, 57, 39, 23, 2, -22, -45, -62, -71, -73, -71, -69, -57, -32, 0, 26, 41, 55, 70, 81, 83, 64, 41, 24, 6, -15, -39, -60, -71, -73, -69, -69, -62, -40, -11, 20, 39, 51, 65, 78, 86, 75, 50, 29, 11, -8, -30, -53, -70, -77, -71, -66, -67, -53, -22, 13, 37, 49, 60, 75, 89, 84, 58, 33, 16, -2, -22, -47, -68, -77, -72, -67, -68, -60, -34, 0, 29, 47, 56, 69, 85, 88, 69, 40, 20, 4, -13, -35, -61, -76, -74, -65, -66, -65, -47, -15, 20, 43, 53, 64, 81, 89, 77, 50, 26, 9, -10, -29, -51, -71, -78, -71, -66, -64, -52, -27, 9, 38, 54, 62, 73, 85, 82, 60, 34, 13, -3, -19, -40, -65, -80, -74, -68, -69, -61, -40, -4, 29, 49, 61, 72, 86, 86, 70, 45, 21, 3, -16, -33, -56, -80, -78, -70, -70, -65, -50, -18, 20, 48, 62, 68, 80, 88, 78, 53, 26, 5, -12, -26, -45, -72, -81, -71, -67, -64, -56, -34, 4, 37, 57, 63, 73, 85, 83, 63, 37, 16, 0, -17, -36, -63, -79, -74, -70, -69, -63, -44, -10, 26, 52, 62, 69, 81, 84, 69, 45, 22, 3, -15, -28, -52, -75, -76, -69, -67, -64, -52, -24, 14, 45, 60, 65, 74, 82, 75, 54, 32, 12, -6, -21, -44, -68, -78, -74, -71, -69, -60, -34, 2, 34, 55, 66, 73, 79, 78, 61, 39, 20, 2, -16, -34, -56, -72, -74, -70, -71, -66, -47, -14, 21, 48, 61, 68, 76, 80, 69, 46, 27, 11, -7, -26, -50, -68, -72, -70, -70, -69, -54, -24, 10, 39, 57, 66, 72, 76, 70, 52, 33, 16, -4, -20, -39, -59, -70, -71, -69, -67, -60, -37, -6, 27, 50, 62, 67, 72, 74, 61, 41, 25, 10, -10, -31, -51, -67, -74, -73, -73, -68, -48, -16, 17, 45, 60, 66, 73, 75, 66, 48, 29, 15, -3, -24, -45, -62, -70, -72, -74, -70, -55, -26, 7, 32, 51, 63, 70, 73, 67, 51, 35, 24, 9, -16, -38, -54, -64, -68, -75, -75, -62, -36, -5, 22, 45, 60, 69, 74, 68, 57, 43, 29, 15, -9, -29, -45, -60, -67, -75, -76, -64, -44, -16, 10, 32, 52, 63, 68, 66, 59, 48, 36, 24, 6, -17, -35, -51, -60, -70, -78, -72, -55, -27, 1, 20, 39, 56, 65, 68, 60, 51, 41, 31, 15, -9, -27, -44, -58, -67, -75, -73, -58, -35, -8, 11, 32, 50, 60, 61, 57, 53, 47, 37, 25, 4, -19, -35, -48, -60, -73, -76, -67, -46, -18, 2, 20, 40, 56, 64, 62, 56, 49, 43, 34, 15, -10, -31, -45, -57, -70, -78, -69, -52, -27, -4, 13, 34, 52, 60, 57, 53, 52, 46, 36, 22, 1, -19, -35, -50, -65, -73, -70, -58, -41, -17, 4, 22, 42, 55, 58, 57, 55, 50, 43, 32, 12, -11, -30, -47, -61, -71, -72, -63, -46, -26, -6, 13, 30, 47, 53, 54, 56, 52, 46, 38, 24, 5, -20, -39, -52, -63, -67, -66, -57, -37, -15, 3, 18, 37, 50, 55, 59, 55, 49, 45, 32, 15, -10, -34, -50, -61, -66, -66, -58, -42, -24, -4, 11, 27, 44, 50, 54, 57, 53, 49, 39, 23, 2, -23, -43, -57, -64, -67, -62, -50, -33, -14, 4, 18, 37, 48, 53, 57, 55, 52, 44, 30, 13, -14, -38, -54, -62, -65, -62, -54, -42, -24, -2, 13, 28, 41, 48, 56, 57, 52, 45, 37, 23, 0, -28, -47, -57, -62, -63, -59, -50, -34, -14, 1, 16, 35, 48, 56, 59, 59, 54, 45, 31, 8, -20, -42, -56, -62, -64, -60, -52, -40, -23, -5, 10, 28, 43, 52, 56, 57, 56, 49, 38, 21, -8, -33, -46, -56, -60, -59, -56, -47, -32, -15, 0, 17, 34, 47, 55, 58, 57, 53, 43, 30, 8, -24, -42, -52, -59, -58, -57, -51, -42, -26, -8, 11, 29, 42, 50, 57, 59, 55, 48, 34, 15, -15, -36, -45, -52, -55, -58, -55, -43, -31, -17, -2, 16, 37, 50, 56, 58, 58, 54, 43, 23, -8, -33, -40, -47, -54, -57, -58, -48, -34, -23, -10, 9, 31, 48, 54, 55, 55, 57, 50, 32, 3, -28, -37, -41, -49, -55, -58, -49, -36, -27, -17, 1, 21, 41, 50, 52, 51, 54, 55, 41, 13, -18, -32, -35, -42, -50, -57, -55, -41, -32, -24, -10, 10, 33, 47, 50, 51, 54, 59, 49, 24, -8, -26, -30, -37, -46, -56, -59, -46, -35, -29, -18, 2, 25, 44, 48, 47, 51, 57, 56, 36, 5, -20, -28, -31, -40, -51, -58, -52, -39, -33, -25, -8, 15, 38, 49, 47, 50, 56, 60, 46, 15, -11, -25, -30, -36, -49, -60, -54, -39, -33, -30, -14, 8, 32, 47, 44, 44, 51, 59, 52, 26, -4, -20, -24, -29, -41, -54, -55, -43, -34, -33, -26, -8, 17, 37, 43, 42, 48, 59, 60, 42, 13, -11, -21, -25, -36, -51, -59, -51, -38, -34, -32, -17, 10, 33, 43, 43, 44, 55, 60, 46, 21, -6, -18, -22, -28, -42, -54, -52, -39, -30, -32, -25, -4, 20, 36, 39, 39, 48, 60, 57, 36, 10, -11, -19, -22, -34, -51, -58, -48, -35, -36, -34, -13, 13, 35, 41, 38, 46, 59, 61, 44, 20, -5, -20, -22, -30, -46, -56, -53, -39, -34, -36, -22, 1, 25, 39, 39, 42, 53, 60, 54, 34, 10, -10, -17, -21, -39, -57, -59, -48, -38, -43, -35, -11, 16, 37, 43, 42, 52, 61, 58, 41, 19, -3, -16, -21, -31, -50, -59, -53, -40, -39, -39, -22, 5, 30, 40, 38, 45, 58, 64, 52, 28, 5, -12, -17, -23, -44, -58, -56, -46, -40, -43, -33, -7, 22, 39, 41, 44, 55, 64, 60, 40, 13, -7, -16, -21, -35, -56, -60, -52, -44, -43, -40, -21, 11, 34, 40, 40, 50, 61, 64, 53, 29, 6, -10, -16, -25, -47, -62, -61, -53, -49, -47, -35, -5, 26, 42, 45, 49, 58, 65, 59, 39, 15, -5, -16, -22, -37, -56, -61, -56, -50, -47, -42, -21, 11, 33, 40, 44, 53, 63, 66, 54, 29, 8, -6, -15, -28, -52, -64, -60, -57, -53, -49, -31, 1, 28, 40, 42, 51, 63, 66, 56, 36, 14, -3, -13, -25, -45, -61, -61, -58, -54, -47, -38, -11, 20, 36, 41, 44, 55, 64, 60, 47, 28, 9, -4, -15, -32, -56, -67, -64, -62, -55, -48, -27, 8, 29, 41, 47, 57, 66, 65, 56, 39, 17, 0, -13, -27, -49, -66, -68, -67, -58, -48, -36, -8, 22, 38, 45, 53, 63, 65, 61, 51, 28, 11, -4, -20, -40, -62, -70, -71, -68, -55, -44, -24, 9, 30, 42, 52, 66, 69, 64, 58, 42, 20, 4, -14, -34, -57, -71, -73, -73, -63, -51, -35, -5, 23, 38, 48, 62, 71, 69, 65, 54, 32, 14, -6, -26, -48, -68, -79, -82, -72, -57, -42, -18, 11, 33, 48, 63, 73, 72, 68, 62, 46, 22, 0, -21, -42, -63, -76, -83, -80, -65, -49, -28, -2, 23, 42, 58, 71, 75, 72, 68, 56, 33, 10, -12, -32, -54, -73, -84, -87, -73, -54, -36, -15, 11, 34, 52, 67, 73, 73, 72, 66, 48, 21, -6, -26, -47, -67, -80, -88, -81, -62, -41, -23, 0, 27, 47, 65, 74, 74, 71, 67, 57, 33, 4, -20, -42, -64, -77, -88, -88, -72, -49, -27, -7, 16, 40, 63, 75, 75, 74, 69, 64, 46, 16, -13, -35, -57, -74, -87, -93, -81, -58, -35, -17, 6, 33, 59, 73, 76, 76, 71, 68, 58, 29, -4, -29, -48, -68, -83, -94, -92, -70, -42, -22, -4, 21, 51, 73, 78, 76, 73, 70, 63, 40, 7, -24, -42, -60, -79, -91, -92, -76, -52, -30, -12, 9, 39, 66, 76, 76, 75, 74, 70, 54, 24, -12, -36, -52, -72, -93, -100, -90, -64, -38, -21, -5, 25, 61, 81, 81, 77, 78, 76, 63, 33, -5, -33, -49, -67, -90, -100, -92, -71, -44, -21, -8, 14, 49, 75, 82, 77, 76, 75, 66, 45, 10, -27, -45, -59, -80, -98, -98, -81, -52, -26, -12, 2, 34, 71, 86, 80, 75, 77, 71, 54, 23, -17, -44, -57, -74, -93, -99, -87, -65, -36, -14, -4, 20, 55, 79, 82, 78, 78, 75, 65, 41, 1, -34, -52, -67, -88, -104, -98, -76, -47, -23, -12, 6, 45, 81, 90, 81, 79, 81, 72, 50, 11, -28, -50, -61, -81, -102, -103, -84, -57, -30, -13, 1, 30, 70, 92, 88, 81, 80, 75, 59, 27, -15, -48, -62, -76, -97, -106, -94, -69, -39, -16, -4, 17, 59, 92, 94, 87, 86, 83, 67, 36, -4, -38, -61, -77, -96, -111, -102, -80, -53, -26, -8, 14, 50, 89, 101, 93, 87, 83, 73, 46, 7, -31, -58, -72, -87, -106, -106, -88, -59, -31, -12, 5, 33, 74, 99, 99, 90, 84, 78, 57, 22, -18, -49, -70, -84, -100, -108, -96, -72, -43, -21, -3, 24, 61, 95, 106, 99, 90, 82, 65, 34, -6, -40, -66, -83, -96, -106, -102, -82, -52, -27, -8, 15, 48, 86, 107, 105, 94, 85, 73, 45, 6, -32, -61, -80, -91, -102, -106, -92, -63, -35, -15, 8, 37, 74, 102, 109, 98, 87, 76, 54, 21, -16, -50, -76, -89, -98, -104, -98, -76, -46, -23, -2, 25, 60, 93, 111, 106, 92, 82, 65, 35, -5, -39, -66, -83, -95, -105, -105, -86, -57, -33, -11, 15, 50, 86, 111, 115, 102, 88, 71, 43, 7, -32, -64, -86, -96, -100, -102, -92, -67, -40, -13, 13, 42, 75, 103, 116, 106, 90, 74, 49, 16, -21, -54, -80, -94, -98, -100, -94, -75, -50, -23, 4, 30, 62, 95, 117, 115, 100, 81, 57, 28, -10, -46, -75, -95, -102, -101, -97, -83, -61, -32, -2, 24, 55, 87, 111, 118, 106, 88, 65, 35, 0, -36, -67, -89, -101, -102, -98, -89, -68, -43, -13, 16, 46, 80, 107, 121, 116, 98, 75, 47, 11, -27, -62, -87, -101, -104, -100, -93, -77, -51, -18, 13, 36, 67, 99, 119, 119, 103, 81, 53, 21, -16, -52, -79, -96, -106, -102, -93, -82, -60, -30, 3, 30, 59, 88, 111, 121, 111, 89, 61, 30, -4, -41, -74, -94, -106, -104, -95, -87, -70, -41, -8, 22, 49, 81, 106, 120, 118, 98, 73, 41, 8, -30, -64, -87, -104, -111, -100, -91, -77, -51, -21, 13, 41, 73, 100, 117, 122, 107, 83, 52, 19, -18, -55, -82, -101, -111, -105, -93, -83, -60, -29, 5, 35, 64, 92, 112, 121, 112, 88, 61, 29, -7, -45, -75, -94, -108, -108, -96, -87, -67, -37, -5, 26, 52, 83, 105, 116, 116, 97, 70, 41, 7, -33, -67, -91, -105, -110, -99, -88, -73, -48, -18, 15, 45, 74, 98, 114, 118, 104, 79, 51, 17, -21, -58, -86, -102, -109, -103, -90, -77, -54, -23, 9, 36, 62, 88, 107, 114, 107, 88, 63, 30, -8, -46, -77, -96, -107, -108, -97, -81, -63, -36, -4, 30, 59, 84, 104, 115, 112, 95, 69, 38, 5, -33, -69, -94, -104, -105, -99, -87, -72, -44, -11, 21, 47, 71, 97, 113, 113, 99, 77, 49, 17, -19, -57, -87, -101, -105, -103, -90, -72, -54, -24, 10, 41, 64, 86, 104, 111, 104, 85, 57, 25, -7, -42, -75, -96, -101, -98, -92, -79, -61, -36, -4, 28, 51, 74, 98, 110, 107, 94, 70, 38, 5, -30, -64, -89, -101, -101, -95, -79, -63, -43, -14, 21, 48, 68, 90, 105, 108, 97, 74, 44, 12, -20, -52, -83, -96, -96, -92, -82, -67, -49, -24, 10, 39, 59, 79, 99, 107, 101, 83, 54, 21, -11, -41, -71, -92, -98, -95, -84, -68, -54, -35, -5, 28, 54, 73, 92, 103, 103, 90, 64, 31, -4, -34, -63, -85, -94, -92, -84, -70, -56, -38, -11, 19, 44, 64, 83, 95, 98, 90, 66, 39, 9, -22, -50, -73, -86, -89, -84, -72, -59, -45, -23, 6, 35, 58, 75, 89, 96, 92, 75, 49, 19, -14, -42, -63, -80, -88, -84, -74, -60, -48, -30, -5, 23, 52, 70, 82, 91, 91, 79, 57, 29, -3, -33, -54, -70, -84, -87, -79, -65, -50, -35, -16, 10, 41, 68, 80, 85, 88, 82, 64, 36, 3, -28, -49, -60, -72, -83, -81, -66, -49, -37, -22, -2, 28, 58, 74, 78, 83, 81, 69, 45, 14, -18, -42, -55, -66, -77, -79, -68, -53, -39, -25, -8, 17, 46, 67, 72, 75, 74, 70, 53, 24, -9, -34, -48, -55, -64, -74, -70, -55, -40, -28, -17, 3, 33, 61, 70, 71, 69, 68, 61, 37, 3, -28, -44, -50, -57, -70, -73, -58, -41, -30, -21, -8, 21, 52, 67, 69, 66, 66, 64, 44, 10, -22, -39, -48, -52, -61, -72, -62, -43, -29, -20, -12, 7, 38, 62, 68, 61, 56, 60, 51, 23, -12, -36, -43, -44, -49, -65, -65, -45, -29, -22, -19, -7, 24, 52, 65, 57, 52, 58, 57, 36, 0, -30, -38, -37, -39, -55, -66, -52, -33, -23, -21, -14, 10, 40, 60, 59, 49, 51, 54, 43, 11, -21, -35, -37, -33, -42, -55, -49, -29, -19, -20, -19, -5, 23, 49, 54, 43, 42, 50, 49, 23, -12, -30, -34, -29, -31, -49, -54, -35, -19, -16, -18, -11, 10, 39, 55, 45, 35, 41, 47, 31, -3, -26, -33, -28, -23, -36, -47, -36, -18, -11, -16, -16, -3, 21, 42, 42, 32, 32, 40, 35, 13, -13, -25, -24, -17, -22, -37, -38, -25, -16, -16, -19, -11, 7, 30, 42, 34, 27, 33, 35, 19, -6, -21, -23, -17, -14, -23, -29, -21, -11, -10, -17, -16, -4, 14, 30, 31, 20, 21, 29, 24, 6, -11, -16, -11, -5, -10, -20, -22, -15, -12, -17, -21, -15, 0, 20, 29, 22, 17, 23, 25, 16, -2, -14, -14, -7, -2, -9, -14, -12, -9, -11, -17, -17, -11, 3, 18, 17, 9, 13, 19, 17, 7, -5, -5, 3, 8, 3, -7, -10, -12, -14, -20, -22, -17, -7, 9, 17, 10, 8, 15, 18, 11, 2, -3, 1, 8, 9, 5, -3, -9, -12, -18, -21, -21, -19, -4, 10, 9, 2, 5, 14, 16, 11, 4, 5, 13, 16, 14, 6, -8, -14, -19, -23, -24, -21, -13, -2, 7, 3, -2, 8, 12, 11, 9, 10, 14, 19, 20, 16, 4, -9, -17, -23, -26, -27, -24, -14, -2, 1, -5, 3, 15, 17, 14, 14, 17, 22, 25, 20, 9, -8, -19, -25, -30, -29, -26, -22, -11, 0, -3, -3, 9, 16, 19, 20, 21, 24, 28, 28, 20, 2, -16, -25, -30, -34, -33, -32, -23, -9, -6, -8, 2, 15, 21, 24, 26, 29, 33, 34, 30, 14, -11, -26, -33, -38, -38, -37, -34, -23, -12, -7, 0, 11, 21, 29, 34, 35, 37, 39, 35, 21, -5, -26, -34, -39, -40, -42, -42, -31, -17, -9, -4, 7, 19, 31, 38, 38, 41, 42, 40, 28, 3, -22, -36, -42, -45, -46, -46, -37, -23, -14, -6, 6, 20, 32, 40, 40, 44, 46, 41, 31, 13, -12, -32, -44, -47, -48, -49, -44, -32, -20, -8, 3, 15, 27, 40, 45, 47, 50, 47, 39, 21, -6, -29, -42, -46, -51, -56, -52, -41, -24, -13, -4, 11, 27, 41, 51, 52, 53, 52, 45, 29, 2, -25, -45, -50, -52, -57, -56, -49, -32, -16, -4, 9, 22, 36, 49, 55, 56, 56, 50, 35, 11, -14, -37, -51, -57, -61, -61, -56, -41, -23, -8, 8, 21, 33, 48, 61, 64, 60, 54, 40, 17, -8, -34, -52, -59, -62, -63, -60, -49, -30, -14, 2, 19, 33, 47, 60, 66, 67, 65, 50, 25, -3, -26, -47, -59, -68, -72, -66, -57, -38, -20, -5, 14, 30, 44, 61, 71, 71, 68, 57, 34, 7, -20, -43, -58, -68, -72, -69, -62, -45, -25, -10, 7, 24, 42, 59, 70, 74, 73, 65, 46, 16, -15, -38, -53, -65, -77, -77, -70, -54, -34, -19, 0, 20, 41, 60, 74, 82, 80, 71, 54, 27, -8, -36, -55, -68, -78, -82, -76, -61, -40, -20, -2, 17, 36, 57, 74, 83, 82, 74, 62, 39, 3, -31, -49, -62, -75, -84, -84, -69, -47, -27, -13, 6, 31, 56, 73, 82, 86, 80, 68, 49, 14, -24, -46, -60, -74, -83, -86, -76, -54, -32, -15, 3, 23, 48, 71, 85, 87, 80, 71, 57, 27, -12, -41, -57, -68, -78, -88, -84, -64, -41, -23, -5, 16, 40, 65, 84, 90, 87, 77, 63, 36, -3, -34, -57, -69, -76, -85, -87, -73, -48, -27, -8, 13, 34, 60, 83, 91, 86, 77, 66, 44, 9, -26, -53, -68, -74, -83, -88, -80, -56, -33, -13, 9, 29, 55, 79, 93, 89, 76, 67, 52, 21, -15, -46, -69, -74, -77, -84, -86, -67, -42, -20, 4, 23, 43, 71, 94, 95, 80, 67, 56, 32, 0, -37, -66, -74, -73, -78, -87, -76, -50, -25, 1, 21, 37, 61, 88, 97, 84, 67, 57, 38, 8, -25, -59, -77, -77, -76, -81, -80, -61, -34, -6, 20, 36, 55, 80, 96, 91, 70, 54, 39, 17, -14, -51, -75, -79, -75, -77, -80, -68, -40, -11, 15, 33, 48, 71, 92, 91, 73, 57, 45, 24, -3, -38, -68, -79, -77, -76, -80, -74, -51, -19, 12, 32, 46, 65, 88, 96, 83, 59, 40, 24, 4, -31, -67, -83, -80, -73, -73, -72, -55, -24, 9, 31, 44, 58, 78, 90, 84, 63, 42, 28, 10, -18, -53, -77, -82, -76, -73, -74, -65, -37, -2, 27, 42, 55, 73, 88, 90, 72, 47, 28, 13, -12, -45, -74, -84, -78, -70, -68, -63, -43, -9, 23, 42, 52, 64, 78, 84, 75, 52, 32, 17, -3, -32, -62, -79, -78, -71, -67, -65, -52, -19, 15, 38, 50, 61, 73, 80, 79, 59, 34, 18, 3, -21, -51, -75, -81, -72, -64, -61, -54, -31, 4, 31, 48, 55, 63, 73, 78, 67, 40, 21, 8, -12, -39, -65, -80, -76, -65, -58, -52, -38, -8, 25, 45, 56, 61, 67, 74, 69, 47, 22, 7, -10, -31, -56, -75, -77, -66, -57, -49, -37, -14, 16, 40, 53, 57, 61, 67, 69, 55, 30, 11, -6, -25, -47, -69, -78, -70, -59, -51, -40, -20, 10, 34, 51, 58, 59, 63, 66, 59, 36, 14, -2, -19, -40, -61, -75, -71, -59, -51, -41, -27, -2, 26, 47, 58, 58, 59, 64, 63, 46, 19, -2, -17, -35, -56, -71, -75, -64, -50, -40, -26, -6, 21, 43, 55, 57, 56, 58, 59, 47, 23, 1, -13, -29, -48, -63, -69, -61, -48, -40, -29, -11, 13, 35, 48, 53, 51, 53, 57, 50, 33, 9, -10, -25, -42, -56, -65, -64, -51, -40, -29, -13, 9, 30, 44, 50, 48, 47, 50, 46, 35, 13, -8, -20, -33, -47, -57, -56, -48, -38, -30, -16, 1, 21, 35, 44, 46, 42, 44, 44, 39, 21, -3, -18, -30, -40, -51, -57, -51, -37, -26, -14, 0, 16, 33, 42, 43, 37, 34, 37, 35, 22, 1, -17, -27, -34, -41, -48, -45, -36, -25, -11, 0, 11, 24, 34, 38, 35, 30, 29, 30, 24, 8, -11, -24, -31, -36, -42, -42, -35, -25, -12, -2, 9, 21, 29, 33, 32, 27, 25, 26, 23, 9, -8, -21, -31, -34, -36, -37, -33, -26, -13, -2, 8, 18, 24, 28, 29, 27, 22, 20, 21, 14, -2, -17, -27, -30, -31, -33, -32, -26, -14, -3, 6, 15, 22, 27, 26, 25, 22, 17, 17, 13, 3, -12, -25, -30, -31, -30, -27, -24, -14, 0, 8, 16, 20, 22, 22, 21, 16, 11, 13, 13, 3, -8, -21, -27, -26, -25, -25, -23, -12, 0, 6, 12, 18, 20, 22, 20, 15, 9, 9, 10, 3, -9, -21, -29, -28, -23, -20, -19, -10, 3, 13, 17, 19, 19, 21, 17, 11, 4, 1, 4, 0, -8, -17, -25, -24, -21, -19, -16, -9, 4, 13, 17, 19, 20, 22, 19, 11, 3, -4, -3, -4, -12, -18, -26, -28, -23, -16, -10, -5, 5, 18, 25, 25, 22, 21, 19, 9, 0, -9, -11, -10, -13, -16, -24, -27, -22, -14, -8, -2, 7, 17, 25, 25, 22, 20, 17, 10, -2, -10, -12, -13, -15, -18, -20, -24, -22, -16, -8, 3, 11, 17, 25, 27, 23, 21, 17, 9, 0, -10, -12, -13, -18, -19, -20, -24, -23, -17, -10, 0, 11, 19, 26, 30, 26, 24, 20, 12, 3, -8, -15, -18, -22, -25, -25, -25, -24, -20, -12, 2, 15, 20, 25, 31, 33, 29, 23, 12, 3, -5, -15, -23, -28, -28, -25, -22, -22, -18, -10, 2, 15, 19, 23, 30, 32, 28, 24, 15, 7, 1, -13, -23, -27, -29, -28, -26, -24, -20, -14, -2, 13, 20, 24, 32, 34, 32, 29, 22, 9, -2, -10, -21, -30, -34, -34, -29, -22, -20, -18, -5, 14, 23, 25, 31, 36, 35, 30, 22, 10, 0, -8, -21, -34, -39, -36, -32, -27, -20, -15, -5, 14, 27, 28, 32, 36, 35, 33, 25, 14, 0, -11, -21, -34, -40, -41, -39, -30, -20, -13, -6, 10, 27, 30, 32, 35, 34, 36, 29, 17, 5, -7, -16, -33, -45, -45, -43, -33, -24, -18, -9, 8, 26, 32, 33, 39, 38, 36, 31, 20, 10, -6, -19, -32, -45, -47, -46, -39, -25, -12, -3, 8, 22, 32, 32, 35, 35, 32, 31, 23, 14, 0, -15, -26, -43, -51, -50, -43, -29, -17, -6, 5, 19, 34, 36, 33, 37, 37, 34, 25, 16, 5, -11, -26, -41, -51, -55, -51, -36, -21, -7, 7, 16, 28, 37, 35, 35, 36, 34, 30, 20, 9, -7, -22, -37, -49, -56, -54, -42, -25, -11, 2, 13, 24, 35, 38, 37, 38, 37, 32, 25, 16, 1, -21, -38, -47, -56, -58, -50, -34, -14, 4, 13, 20, 31, 40, 39, 35, 36, 34, 28, 20, 5, -15, -33, -44, -55, -63, -54, -38, -19, -2, 10, 17, 30, 40, 41, 36, 38, 41, 33, 22, 9, -13, -36, -50, -55, -63, -61, -44, -22, 2, 18, 22, 28, 38, 42, 39, 34, 35, 34, 27, 14, -7, -29, -43, -51, -60, -63, -50, -30, -10, 8, 16, 21, 32, 40, 40, 38, 39, 41, 35, 24, 6, -20, -41, -54, -62, -65, -58, -39, -16, 7, 18, 22, 29, 39, 43, 40, 35, 38, 37, 27, 12, -14, -37, -51, -58, -64, -64, -47, -22, -2, 14, 18, 24, 36, 44, 45, 41, 43, 43, 32, 17, -8, -35, -54, -63, -67, -68, -56, -29, -4, 16, 24, 26, 35, 44, 47, 43, 38, 38, 36, 24, 0, -30, -50, -57, -59, -63, -61, -40, -11, 11, 20, 20, 26, 39, 48, 46, 40, 39, 42, 33, 12, -20, -47, -58, -60, -62, -61, -49, -23, 2, 17, 21, 22, 33, 48, 51, 45, 43, 43, 38, 20, -10, -41, -58, -61, -64, -62, -55, -35, -9, 10, 21, 23, 32, 50, 57, 49, 45, 45, 43, 26, -6, -38, -58, -62, -65, -67, -61, -44, -15, 10, 23, 26, 28, 44, 59, 55, 46, 42, 41, 33, 6, -30, -57, -64, -62, -64, -62, -50, -26, 2, 18, 26, 28, 39, 59, 60, 48, 43, 43, 37, 14, -22, -53, -67, -63, -65, -66, -55, -33, -2, 19, 28, 31, 37, 55, 64, 53, 41, 39, 37, 20, -16, -48, -66, -65, -62, -66, -60, -43, -12, 15, 26, 31, 37, 53, 69, 63, 46, 39, 38, 27, -5, -44, -72, -73, -65, -65, -63, -52, -24, 11, 31, 36, 38, 48, 65, 70, 53, 38, 34, 28, 5, -35, -69, -78, -70, -65, -63, -53, -30, 2, 26, 38, 43, 49, 62, 69, 58, 40, 33, 28, 9, -25, -61, -78, -75, -69, -64, -55, -37, -7, 22, 36, 43, 49, 57, 66, 62, 44, 31, 29, 15, -16, -52, -76, -77, -69, -63, -57, -44, -16, 14, 33, 42, 48, 54, 65, 68, 52, 33, 27, 19, -6, -41, -72, -82, -74, -65, -59, -48, -24, 7, 29, 43, 50, 53, 60, 67, 58, 39, 28, 22, 2, -31, -64, -82, -79, -71, -61, -49, -31, -2, 22, 40, 51, 55, 58, 65, 63, 46, 29, 21, 9, -21, -56, -79, -83, -77, -65, -54, -37, -10, 16, 36, 50, 57, 60, 65, 64, 50, 33, 22, 11, -13, -47, -73, -82, -80, -70, -57, -42, -19, 8, 30, 49, 58, 61, 62, 64, 56, 41, 24, 11, -6, -35, -66, -80, -82, -75, -61, -45, -25, -2, 22, 43, 57, 63, 64, 63, 58, 49, 31, 15, -2, -26, -58, -79, -85, -81, -66, -49, -31, -9, 17, 39, 55, 64, 69, 67, 61, 53, 35, 16, 1, -20, -49, -75, -86, -85, -74, -54, -34, -11, 11, 33, 53, 64, 70, 68, 59, 51, 40, 22, 5, -15, -40, -66, -79, -81, -78, -63, -41, -19, 4, 25, 44, 58, 67, 72, 65, 57, 47, 29, 11, -8, -31, -61, -81, -85, -82, -68, -47, -25, -3, 21, 44, 59, 68, 73, 68, 56, 47, 33, 15, -7, -27, -52, -76, -82, -82, -72, -52, -30, -7, 13, 36, 57, 67, 74, 72, 61, 48, 36, 20, -4, -25, -47, -71, -81, -81, -75, -56, -33, -10, 11, 30, 49, 63, 73, 74, 63, 48, 37, 25, 6, -20, -41, -63, -79, -81, -77, -65, -43, -19, 4, 25, 45, 63, 73, 76, 70, 55, 41, 28, 10, -15, -38, -59, -77, -83, -79, -70, -49, -25, -4, 20, 40, 59, 74, 76, 73, 62, 46, 33, 16, -10, -34, -51, -68, -83, -85, -75, -58, -34, -11, 14, 35, 55, 73, 79, 76, 69, 51, 33, 20, -2, -30, -53, -67, -81, -84, -76, -61, -39, -14, 11, 32, 49, 67, 77, 74, 68, 55, 37, 23, 5, -22, -45, -59, -73, -84, -82, -68, -46, -24, 3, 26, 43, 62, 75, 74, 72, 61, 42, 25, 10, -15, -40, -57, -70, -83, -84, -71, -49, -28, -6, 20, 41, 59, 72, 72, 69, 63, 48, 29, 13, -8, -31, -51, -66, -79, -84, -75, -56, -37, -16, 12, 36, 55, 71, 74, 72, 69, 54, 34, 16, -5, -28, -47, -61, -75, -85, -80, -60, -38, -20, 4, 30, 53, 68, 71, 69, 67, 57, 39, 20, 0, -21, -41, -58, -71, -79, -79, -66, -45, -25, -3, 23, 45, 61, 68, 69, 70, 63, 47, 29, 8, -16, -37, -56, -71, -80, -81, -71, -52, -30, -7, 17, 41, 60, 67, 67, 68, 65, 50, 30, 10, -14, -31, -47, -65, -77, -79, -70, -53, -33, -14, 8, 34, 56, 62, 62, 66, 64, 54, 36, 15, -8, -27, -42, -61, -73, -75, -70, -56, -36, -14, 5, 26, 49, 60, 59, 61, 60, 54, 42, 23, -2, -22, -35, -53, -69, -75, -70, -58, -41, -20, -3, 18, 43, 59, 57, 57, 60, 56, 44, 28, 7, -17, -32, -47, -63, -73, -72, -62, -46, -23, -6, 12, 35, 55, 60, 57, 59, 56, 49, 35, 14, -13, -28, -40, -58, -72, -73, -62, -50, -31, -13, 5, 30, 51, 59, 56, 58, 61, 56, 38, 17, -9, -26, -37, -52, -68, -74, -63, -50, -32, -14, 1, 22, 45, 57, 56, 51, 54, 54, 41, 21, -4, -22, -31, -44, -59, -69, -63, -48, -36, -21, -7, 11, 35, 52, 56, 53, 54, 58, 48, 30, 8, -17, -32, -43, -57, -68, -69, -56, -39, -22, -8, 6, 28, 49, 57, 54, 51, 55, 52, 35, 13, -13, -29, -36, -49, -64, -70, -58, -39, -23, -11, 0, 19, 43, 57, 55, 47, 49, 55, 43, 18, -9, -28, -35, -42, -57, -69, -65, -45, -25, -11, 1, 14, 37, 55, 60, 50, 45, 48, 42, 21, -4, -25, -35, -40, -50, -60, -61, -46, -27, -15, -6, 6, 25, 46, 56, 50, 43, 45, 47, 33, 9, -15, -30, -37, -45, -58, -64, -56, -36, -18, -8, 4, 18, 40, 58, 59, 47, 39, 41, 35, 12, -15, -32, -38, -39, -46, -57, -55, -37, -17, -7, 1, 11, 27, 48, 56, 47, 37, 38, 38, 21, -6, -24, -32, -37, -43, -54, -57, -44, -25, -9, 2, 11, 24, 44, 57, 51, 38, 32, 31, 21, -5, -28, -35, -36, -36, -45, -51, -41, -25, -8, 3, 8, 17, 33, 48, 49, 37, 31, 30, 25, 7, -18, -30, -34, -37, -40, -48, -47, -33, -16, 1, 11, 16, 28, 42, 50, 43, 30, 25, 22, 10, -12, -28, -33, -34, -35, -41, -44, -33, -18, -2, 9, 12, 20, 32, 43, 41, 29, 24, 22, 14, -3, -21, -29, -30, -31, -35, -41, -35, -21, -6, 9, 13, 18, 27, 38, 42, 29, 18, 16, 13, 4, -15, -27, -28, -27, -28, -34, -34, -23, -10, 5, 11, 14, 22, 32, 37, 31, 20, 16, 12, 6, -9, -22, -25, -27, -26, -32, -34, -27, -15, 0, 10, 12, 18, 28, 36, 35, 23, 14, 11, 8, -3, -19, -28, -28, -25, -27, -32, -28, -16, -2, 11, 14, 14, 22, 30, 31, 24, 15, 11, 8, 2, -11, -22, -25, -25, -26, -30, -28, -18, -7, 5, 12, 14, 19, 27, 30, 26, 19, 13, 9, 4, -6, -20, -26, -23, -24, -27, -27, -19, -6, 4, 12, 12, 13, 22, 26, 22, 15, 11, 10, 6, -2, -12, -19, -19, -21, -25, -25, -20, -11, -3, 5, 9, 13, 19, 24, 24, 21, 15, 12, 7, 2, -9, -20, -22, -22, -23, -24, -22, -11, -2, 7, 11, 13, 17, 21, 21, 18, 13, 11, 7, 1, -7, -15, -19, -19, -21, -20, -18, -12, -4, 2, 8, 11, 15, 17, 16, 15, 13, 11, 8, 4, -3, -11, -16, -15, -19, -20, -16, -12, -5, 2, 5, 8, 14, 17, 15, 11, 10, 9, 8, 4, -2, -6, -11, -12, -14, -18, -13, -7, -6, -3, 2, 6, 10, 13, 13, 9, 8, 9, 6, 1, 0, -5, -9, -12, -12, -13, -12, -4, 1, 3, 4, 4, 7, 11, 10, 7, 3, 3, 4, 2, -2, -3, -6, -7, -6, -6, -8, -5, 2, 1, 1, 0, 1, 5, 5, 3, 0, 0, 5, 5, 2, 3, 0, -3, -5, -6, -8, -7, -2, -3, -4, -2, -2, 3, 6, 4, 1, -3, 1, 5, 3, 2, 0, -2, -3, -4, -5, -5, 1, 2, -3, -3, -4, -3, 4, 4, 0, -5, -3, 3, 3, 2, 1, 1, 0, 0, 0, -3, -2, 1, -2, -4, -3, -4, 1, 5, 2, -5, -7, -2, 2, -2, -2, 0, 2, 3, 2, 2, 3, 6, 4, -2, -5, -6, -2, 3, -2, -9, -11, -5, 0, -3, -4, -2, 3, 7, 8, 4, 2, 4, 3, 0, -6, -8, -6, 2, 4, -3, -10, -10, -5, -2, -4, -5, -3, 5, 11, 11, 8, 5, 5, 4, -2, -9, -9, -2, 0, -5, -13, -14, -10, -5, -4, -2, 2, 6, 14, 15, 11, 8, 6, 1, -5, -10, -12, -6, 1, -2, -10, -15, -11, -4, -3, -6, -5, 2, 14, 19, 14, 10, 10, 8, 3, -6, -15, -12, -4, -4, -12, -18, -17, -10, -2, 0, 1, 6, 16, 25, 21, 12, 8, 4, -2, -8, -18, -20, -11, -6, -9, -14, -14, -10, -3, 0, 1, 6, 13, 23, 25, 17, 13, 9, 1, -6, -13, -18, -14, -11, -13, -17, -19, -14, -8, -3, 1, 7, 14, 24, 30, 24, 16, 12, 4, -5, -11, -18, -19, -15, -12, -14, -19, -18, -14, -9, 0, 8, 13, 19, 27, 28, 22, 18, 9, -4, -11, -14, -16, -15, -16, -16, -17, -16, -14, -13, -6, 4, 12, 19, 26, 31, 27, 19, 13, 3, -8, -12, -16, -18, -19, -17, -16, -20, -18, -15, -10, 1, 10, 18, 24, 31, 30, 22, 18, 9, -4, -10, -14, -17, -20, -22, -19, -19, -22, -18, -13, -2, 9, 16, 21, 29, 36, 29, 19, 12, 1, -7, -10, -15, -22, -24, -20, -18, -21, -21, -17, -8, 7, 16, 23, 27, 33, 35, 26, 17, 7, -5, -11, -14, -22, -27, -24, -19, -22, -25, -19, -11, 5, 16, 21, 25, 33, 38, 31, 18, 9, -2, -10, -13, -22, -29, -28, -21, -18, -24, -22, -15, -3, 14, 21, 24, 30, 38, 36, 24, 13, 4, -5, -9, -16, -28, -32, -25, -21, -25, -27, -18, -7, 8, 18, 24, 31, 40, 40, 29, 16, 6, -3, -8, -16, -27, -31, -27, -22, -24, -27, -21, -10, 4, 16, 22, 28, 37, 40, 33, 19, 7, 1, -5, -12, -23, -32, -28, -23, -23, -27, -26, -15, -2, 13, 21, 25, 34, 41, 38, 28, 14, 4, -3, -11, -22, -34, -35, -30, -26, -28, -29, -20, -3, 14, 24, 27, 32, 41, 42, 34, 17, 4, -4, -11, -20, -32, -38, -33, -28, -27, -27, -22, -9, 7, 20, 29, 34, 39, 40, 37, 24, 10, 2, -7, -16, -28, -40, -40, -33, -29, -28, -27, -16, 5, 21, 28, 32, 36, 41, 40, 30, 12, 1, -6, -11, -22, -37, -42, -34, -30, -29, -27, -20, -3, 16, 27, 32, 34, 39, 41, 35, 20, 6, -4, -11, -16, -32, -45, -41, -33, -31, -27, -23, -10, 13, 28, 33, 35, 38, 39, 36, 25, 8, -6, -11, -14, -26, -42, -45, -34, -29, -25, -23, -15, 6, 26, 36, 36, 36, 37, 36, 29, 14, -2, -12, -14, -23, -42, -50, -42, -32, -23, -18, -15, 3, 25, 38, 39, 35, 35, 37, 33, 18, -3, -15, -18, -20, -34, -48, -47, -34, -22, -14, -12, -4, 17, 35, 41, 37, 34, 33, 33, 24, 6, -13, -22, -22, -30, -45, -51, -39, -23, -10, -6, -3, 13, 32, 41, 37, 30, 29, 31, 27, 10, -10, -22, -23, -26, -38, -48, -44, -28, -12, -5, -3, 9, 27, 38, 38, 32, 28, 29, 27, 17, -4, -21, -26, -27, -35, -47, -49, -33, -12, 2, 5, 9, 23, 35, 40, 34, 21, 23, 25, 22, 5, -20, -28, -28, -29, -39, -50, -43, -19, 3, 10, 7, 15, 29, 41, 43, 28, 22, 23, 22, 12, -16, -33, -32, -32, -38, -46, -43, -21, 3, 15, 13, 16, 29, 35, 35, 27, 19, 19, 19, 15, -8, -30, -31, -30, -32, -40, -44, -29, -2, 18, 17, 11, 22, 34, 37, 32, 21, 18, 20, 17, -2, -28, -37, -34, -34, -38, -42, -30, -7, 16, 22, 16, 20, 31, 31, 29, 23, 17, 18, 19, 6, -21, -37, -35, -34, -35, -38, -35, -15, 14, 27, 21, 13, 23, 31, 31, 26, 16, 12, 16, 12, -10, -35, -39, -35, -36, -36, -34, -21, 6, 24, 24, 16, 20, 29, 28, 27, 22, 16, 17, 15, -4, -29, -41, -39, -40, -39, -36, -29, -6, 20, 27, 21, 19, 28, 33, 31, 27, 18, 14, 13, 2, -22, -41, -43, -40, -39, -34, -28, -12, 16, 28, 24, 19, 25, 29, 27, 24, 19, 15, 12, 4, -15, -34, -41, -40, -37, -32, -26, -18, 5, 24, 24, 20, 21, 26, 27, 26, 24, 18, 12, 6, -9, -30, -44, -45, -41, -33, -26, -19, -2, 23, 29, 24, 22, 24, 28, 25, 22, 18, 13, 7, -7, -24, -40, -46, -42, -36, -28, -21, -6, 15, 28, 25, 22, 25, 29, 28, 23, 20, 14, 6, -6, -22, -40, -47, -42, -36, -28, -23, -10, 13, 30, 28, 21, 23, 27, 28, 21, 18, 16, 9, -2, -17, -33, -44, -44, -38, -31, -23, -14, 5, 25, 32, 25, 23, 26, 29, 24, 16, 13, 8, -2, -15, -31, -43, -44, -37, -30, -23, -14, 1, 21, 31, 27, 22, 24, 28, 25, 17, 13, 10, 3, -10, -27, -40, -44, -38, -32, -26, -17, -3, 16, 31, 31, 25, 25, 30, 29, 17, 8, 7, 3, -8, -25, -39, -43, -37, -31, -27, -18, -4, 13, 29, 32, 26, 24, 27, 27, 17, 9, 8, 6, -5, -20, -34, -39, -37, -34, -30, -21, -8, 6, 23, 34, 31, 29, 28, 27, 22, 13, 6, 5, -4, -18, -34, -40, -37, -34, -29, -23, -10, 5, 21, 32, 29, 27, 29, 26, 20, 12, 4, 3, 0, -12, -28, -37, -35, -31, -29, -23, -13, 1, 16, 30, 33, 29, 27, 25, 21, 15, 5, -2, -3, -9, -22, -35, -36, -31, -29, -24, -14, 0, 12, 27, 35, 31, 29, 26, 21, 16, 8, -2, -3, -7, -19, -34, -36, -32, -31, -28, -18, -3, 11, 22, 32, 32, 30, 29, 23, 16, 11, 2, -3, -6, -17, -32, -37, -32, -30, -31, -23, -6, 9, 18, 30, 36, 32, 31, 25, 17, 13, 4, -6, -8, -14, -26, -36, -34, -31, -31, -25, -11, 6, 16, 24, 34, 35, 33, 28, 17, 16, 10, -3, -9, -13, -23, -34, -36, -32, -31, -27, -16, 2, 16, 22, 30, 35, 33, 30, 21, 15, 11, 0, -7, -11, -20, -31, -35, -31, -31, -29, -21, -6, 13, 21, 25, 32, 34, 33, 26, 18, 13, 4, -6, -10, -19, -29, -34, -34, -29, -27, -24, -12, 7, 20, 25, 30, 33, 32, 29, 21, 13, 7, -5, -11, -18, -28, -35, -36, -29, -25, -24, -16, 3, 21, 26, 28, 34, 37, 34, 26, 12, 4, -5, -13, -20, -30, -35, -39, -35, -24, -19, -13, -2, 15, 27, 30, 32, 34, 31, 28, 18, 5, -6, -15, -20, -24, -31, -37, -35, -24, -19, -16, -9, 8, 24, 30, 30, 33, 35, 35, 24, 5, -5, -11, -20, -27, -34, -40, -39, -30, -21, -16, -9, 4, 20, 32, 36, 36, 36, 35, 31, 13, -3, -13, -23, -27, -29, -41, -44, -33, -19, -11, -10, -4, 14, 32, 38, 34, 33, 36, 33, 18, -4, -13, -20, -25, -28, -37, -43, -34, -22, -14, -8, -4, 9, 26, 39, 38, 35, 35, 34, 23, 3, -12, -21, -28, -28, -31, -41, -40, -27, -15, -7, -6, 2, 20, 37, 42, 36, 34, 35, 28, 9, -10, -18, -24, -26, -29, -38, -42, -32, -21, -11, -6, -3, 12, 33, 45, 41, 37, 37, 29, 13, -4, -17, -26, -28, -28, -33, -39, -37, -26, -15, -8, -7, 6, 29, 47, 46, 39, 34, 30, 20, 1, -18, -26, -26, -25, -29, -37, -40, -31, -17, -8, -7, 0, 20, 42, 51, 45, 38, 30, 18, 7, -10, -24, -27, -26, -24, -29, -38, -37, -27, -14, -9, -6, 11, 36, 51, 47, 42, 34, 24, 14, -3, -20, -25, -23, -22, -26, -37, -42, -33, -17, -8, -7, 4, 28, 50, 54, 45, 35, 24, 15, 3, -16, -24, -25, -22, -23, -32, -41, -37, -22, -11, -8, 0, 21, 44, 54, 46, 34, 26, 18, 7, -11, -22, -21, -20, -21, -28, -40, -43, -30, -15, -10, -3, 16, 40, 56, 52, 37, 24, 16, 9, -6, -21, -22, -18, -17, -22, -35, -43, -34, -21, -14, -9, 7, 34, 53, 54, 40, 29, 21, 14, 4, -14, -21, -17, -17, -22, -33, -46, -45, -31, -16, -8, 4, 25, 50, 60, 49, 31, 20, 15, 9, -5, -17, -18, -15, -17, -26, -42, -50, -40, -24, -11, -2, 18, 43, 56, 52, 35, 21, 17, 11, 0, -12, -18, -14, -15, -22, -36, -50, -46, -30, -15, -3, 12, 35, 53, 55, 41, 24, 18, 12, 5, -4, -15, -18, -15, -20, -33, -46, -49, -37, -21, -7, 7, 25, 46, 54, 45, 27, 18, 14, 10, 3, -8, -15, -16, -18, -28, -41, -49, -44, -29, -12, 4, 17, 35, 49, 49, 34, 19, 16, 15, 9, 1, -10, -14, -16, -24, -38, -50, -49, -36, -18, -3, 10, 26, 43, 49, 38, 22, 18, 20, 16, 9, -5, -13, -16, -23, -36, -50, -53, -43, -25, -8, 6, 21, 38, 48, 44, 27, 19, 21, 19, 13, -2, -13, -17, -21, -30, -45, -52, -46, -29, -10, 3, 14, 29, 42, 44, 30, 17, 19, 21, 17, 6, -8, -14, -19, -26, -39, -49, -48, -36, -18, -2, 11, 27, 37, 42, 37, 22, 18, 21, 19, 9, -5, -13, -18, -24, -33, -45, -46, -39, -24, -8, 6, 20, 33, 40, 38, 27, 19, 22, 23, 17, 4, -8, -14, -22, -29, -43, -48, -43, -32, -16, -2, 13, 25, 34, 39, 33, 23, 21, 23, 20, 9, -4, -11, -19, -25, -33, -43, -42, -34, -20, -7, 3, 14, 24, 32, 31, 22, 20, 26, 28, 20, 6, -5, -11, -18, -28, -42, -44, -38, -28, -15, -5, 8, 19, 28, 31, 24, 21, 25, 27, 22, 10, 0, -6, -12, -22, -34, -38, -34, -30, -20, -11, 0, 11, 20, 26, 23, 19, 22, 27, 25, 17, 7, -2, -7, -17, -29, -35, -35, -34, -26, -16, -5, 7, 15, 23, 28, 24, 21, 22, 24, 20, 11, -2, -8, -14, -24, -29, -31, -31, -27, -18, -9, 0, 8, 15, 22, 23, 20, 21, 24, 24, 19, 7, -4, -10, -19, -26, -32, -34, -33, -24, -12, -2, 6, 14, 22, 26, 23, 22, 22, 22, 21, 10, 0, -6, -15, -21, -24, -28, -31, -28, -17, -7, 2, 7, 13, 19, 23, 23, 21, 19, 21, 18, 8, -2, -11, -17, -21, -24, -30, -33, -25, -11, 0, 4, 9, 16, 20, 21, 20, 18, 18, 20, 14, 4, -6, -12, -15, -17, -25, -32, -32, -20, -6, -3, -3, 7, 18, 23, 19, 16, 19, 26, 24, 11, 0, -6, -9, -15, -25, -33, -35, -26, -15, -9, -6, 5, 17, 22, 21, 17, 18, 25, 26, 16, 4, -5, -7, -9, -18, -29, -38, -35, -21, -11, -9, -4, 9, 22, 25, 20, 16, 22, 30, 24, 8, -4, -5, -5, -13, -25, -36, -38, -26, -16, -11, -10, 2, 19, 25, 18, 12, 19, 30, 28, 14, 1, -2, 3, -3, -17, -31, -36, -29, -21, -18, -19, -11, 7, 20, 16, 10, 16, 30, 36, 24, 8, 4, 8, 6, -12, -32, -40, -35, -26, -21, -20, -14, 2, 19, 20, 10, 12, 24, 35, 29, 13, 5, 7, 9, -3, -23, -37, -37, -31, -23, -21, -19, -8, 12, 19, 10, 6, 19, 36, 37, 23, 11, 12, 16, 7, -15, -35, -43, -38, -30, -27, -23, -16, 2, 18, 16, 7, 13, 30, 38, 29, 17, 12, 16, 15, -4, -27, -40, -39, -32, -28, -28, -24, -8, 12, 14, 5, 7, 26, 40, 36, 24, 18, 21, 21, 4, -20, -38, -41, -37, -34, -30, -26, -15, 4, 14, 7, 3, 18, 37, 41, 33, 24, 22, 25, 14, -10, -33, -44, -42, -36, -32, -29, -22, -6, 10, 9, 2, 9, 29, 40, 37, 32, 28, 29, 21, 0, -24, -39, -44, -44, -38, -31, -24, -16, 0, 7, 3, 8, 24, 38, 43, 41, 32, 28, 25, 9, -15, -34, -44, -44, -39, -31, -26, -20, -10, 3, 2, 1, 14, 32, 44, 46, 39, 33, 31, 20, -7, -31, -45, -47, -44, -38, -30, -26, -16, 0, 5, 4, 12, 30, 45, 52, 47, 36, 30, 22, 0, -24, -40, -50, -49, -42, -31, -24, -19, -10, -3, 3, 11, 24, 39, 51, 55, 49, 37, 27, 8, -18, -36, -50, -54, -47, -36, -29, -25, -16, -6, 4, 10, 18, 34, 52, 59, 53, 39, 28, 15, -8, -29, -45, -53, -51, -43, -34, -29, -23, -14, -4, 7, 17, 33, 52, 62, 61, 50, 37, 23, -4, -28, -44, -55, -55, -48, -38, -30, -25, -18, -8, 5, 13, 25, 46, 61, 65, 57, 43, 30, 8, -17, -36, -50, -55, -53, -47, -39, -32, -24, -15, -3, 11, 25, 45, 62, 68, 63, 51, 37, 14, -14, -34, -46, -56, -57, -51, -44, -33, -25, -18, -6, 8, 19, 36, 55, 67, 65, 53, 42, 23, -4, -26, -40, -50, -56, -54, -49, -41, -31, -23, -12, 1, 15, 34, 53, 65, 68, 59, 49, 33, 6, -21, -37, -47, -57, -60, -56, -48, -38, -28, -16, -2, 14, 33, 51, 64, 70, 63, 53, 38, 13, -14, -34, -44, -53, -59, -59, -53, -42, -30, -19, -8, 5, 26, 47, 61, 68, 64, 57, 48, 26, -3, -26, -39, -49, -58, -63, -59, -49, -37, -24, -13, 1, 20, 42, 55, 65, 69, 64, 54, 34, 7, -18, -34, -44, -55, -65, -64, -54, -42, -31, -19, -8, 12, 37, 54, 61, 67, 67, 60, 46, 22, -8, -29, -40, -50, -64, -70, -63, -50, -34, -21, -13, 2, 28, 51, 62, 68, 68, 61, 51, 32, 3, -23, -36, -47, -60, -70, -67, -58, -44, -27, -14, -2, 22, 45, 58, 65, 70, 68, 56, 38, 16, -11, -32, -45, -58, -69, -70, -62, -52, -34, -17, -6, 13, 38, 54, 64, 70, 67, 59, 47, 29, -2, -28, -40, -51, -65, -74, -67, -54, -37, -20, -11, 5, 33, 53, 59, 63, 67, 62, 51, 34, 7, -20, -35, -46, -59, -72, -70, -60, -46, -27, -12, 1, 24, 47, 60, 64, 69, 66, 54, 39, 15, -13, -32, -44, -54, -68, -71, -60, -48, -32, -18, -7, 14, 38, 54, 61, 68, 70, 60, 46, 26, -2, -23, -38, -50, -63, -72, -68, -55, -39, -24, -13, 5, 31, 52, 61, 67, 71, 64, 53, 34, 7, -21, -36, -46, -57, -69, -72, -60, -42, -27, -17, -2, 21, 45, 58, 65, 69, 66, 57, 42, 15, -13, -30, -43, -54, -66, -72, -65, -47, -30, -18, -5, 15, 40, 57, 64, 67, 62, 56, 46, 23, -6, -27, -39, -50, -58, -67, -67, -51, -32, -20, -9, 9, 31, 51, 60, 64, 64, 58, 48, 27, 1, -20, -34, -46, -56, -65, -70, -57, -37, -22, -14, 2, 26, 48, 62, 66, 64, 59, 51, 34, 8, -18, -31, -42, -52, -61, -70, -63, -42, -24, -15, -3, 19, 43, 60, 63, 60, 57, 52, 39, 14, -14, -28, -36, -46, -54, -65, -66, -49, -29, -17, -9, 10, 33, 54, 64, 62, 58, 53, 42, 23, -5, -25, -35, -46, -54, -63, -67, -54, -33, -17, -7, 7, 30, 51, 61, 58, 55, 51, 43, 28, 3, -21, -30, -37, -46, -56, -63, -56, -39, -22, -12, -5, 16, 40, 57, 58, 55, 53, 48, 38, 19, -10, -27, -35, -45, -56, -66, -65, -49, -28, -14, -6, 8, 34, 57, 60, 55, 54, 50, 42, 26, -4, -28, -35, -42, -52, -62, -63, -51, -32, -14, -5, 3, 24, 47, 57, 53, 50, 47, 41, 33, 11, -20, -35, -40, -46, -56, -65, -58, -38, -17, -4, 1, 15, 41, 57, 55, 47, 45, 42, 35, 17, -13, -33, -38, -41, -49, -58, -55, -41, -21, -4, 0, 7, 29, 50, 52, 45, 42, 40, 37, 25, 0, -28, -38, -38, -44, -53, -58, -46, -26, -6, 3, 4, 18, 42, 53, 47, 41, 39, 37, 30, 10, -21, -41, -43, -41, -47, -54, -46, -29, -8, 7, 9, 13, 31, 46, 45, 37, 33, 33, 28, 15, -10, -35, -42, -38, -39, -45, -46, -32, -10, 6, 9, 8, 19, 38, 44, 38, 30, 29, 30, 19, -3, -29, -42, -38, -34, -40, -43, -32, -14, 3, 11, 11, 15, 30, 41, 39, 30, 25, 25, 19, 4, -21, -40, -42, -32, -30, -33, -29, -15, 2, 11, 10, 8, 17, 30, 35, 30, 23, 24, 23, 11, -11, -32, -43, -34, -26, -29, -29, -18, -3, 9, 12, 9, 12, 26, 35, 32, 21, 18, 18, 12, -6, -29, -43, -36, -22, -22, -25, -15, 1, 10, 11, 10, 8, 17, 29, 29, 21, 16, 17, 15, 2, -21, -39, -39, -24, -17, -20, -16, -5, 9, 13, 10, 7, 12, 24, 28, 23, 14, 12, 11, 4, -14, -33, -39, -28, -15, -14, -12, -6, 5, 11, 9, 7, 7, 16, 26, 25, 16, 10, 11, 6, -8, -24, -37, -32, -17, -12, -11, -5, 5, 11, 11, 10, 7, 12, 21, 21, 16, 7, 4, 3, -6, -20, -32, -32, -20, -8, -5, 0, 5, 11, 11, 9, 8, 8, 13, 17, 16, 9, 3, 2, -3, -13, -25, -31, -23, -9, -4, -2, 5, 11, 14, 11, 7, 6, 12, 15, 12, 5, -2, -2, -3, -11, -22, -29, -24, -9, 0, 3, 8, 13, 13, 12, 8, 4, 5, 7, 9, 6, -3, -5, -4, -5, -14, -24, -23, -13, 0, 4, 6, 10, 14, 14, 9, 3, 3, 5, 6, 4, -4, -6, -5, -5, -9, -18, -20, -15, -4, 6, 9, 11, 13, 13, 10, 5, 1, 0, -3, 0, -4, -6, -6, -5, -4, -11, -16, -16, -9, 3, 8, 11, 11, 10, 11, 8, 3, -2, -5, -4, -3, -5, -6, -6, -2, -5, -12, -15, -13, -2, 8, 9, 11, 11, 11, 7, 4, 0, -6, -6, -4, -4, -6, -6, -2, 0, -7, -13, -15, -5, 8, 13, 12, 9, 11, 9, 4, -5, -11, -11, -8, -5, -5, -5, 0, 4, 3, -4, -11, -8, 3, 11, 12, 8, 7, 4, 2, -2, -10, -14, -13, -7, -3, -4, -2, 3, 4, 1, -8, -8, 3, 13, 17, 12, 11, 7, 1, -6, -16, -21, -19, -13, -7, -2, 3, 7, 10, 10, 1, -6, -2, 8, 14, 12, 10, 4, -2, -6, -15, -21, -20, -15, -8, -2, 3, 5, 9, 14, 5, -6, 1, 12, 18, 14, 9, 7, 2, -4, -18, -28, -27, -22, -12, -5, 3, 9, 13, 18, 16, 5, 1, 7, 14, 13, 8, 5, -5, -9, -17, -26, -26, -23, -15, -4, 5, 8, 11, 17, 17, 7, 2, 7, 16, 18, 10, 4, -2, -6, -16, -31, -33, -27, -18, -9, 0, 7, 12, 18, 22, 16, 9, 9, 16, 20, 13, 5, -2, -9, -18, -33, -37, -29, -22, -13, -4, 7, 15, 21, 25, 21, 15, 13, 17, 20, 14, 5, -3, -8, -18, -35, -42, -36, -24, -16, -6, 5, 13, 23, 27, 25, 20, 17, 19, 20, 15, 5, -3, -8, -21, -35, -45, -39, -25, -18, -11, 3, 16, 25, 29, 27, 26, 24, 23, 21, 17, 8, -4, -12, -23, -35, -46, -46, -34, -22, -15, -3, 13, 25, 31, 33, 34, 31, 28, 25, 20, 11, -4, -12, -22, -38, -49, -51, -39, -26, -21, -11, 8, 24, 34, 35, 36, 37, 35, 29, 21, 13, 0, -11, -20, -36, -48, -52, -46, -31, -22, -14, 1, 19, 34, 38, 39, 40, 38, 34, 24, 15, 0, -14, -21, -34, -47, -53, -50, -35, -22, -17, -5, 13, 31, 37, 38, 42, 41, 37, 28, 21, 9, -8, -19, -30, -44, -50, -53, -46, -32, -23, -11, 7, 26, 39, 43, 49, 48, 42, 32, 20, 9, -9, -21, -31, -46, -52, -54, -50, -35, -24, -13, 4, 23, 40, 46, 48, 49, 46, 37, 26, 13, -4, -20, -29, -42, -50, -53, -54, -43, -31, -21, -2, 17, 36, 47, 53, 56, 51, 42, 29, 17, 3, -16, -30, -41, -51, -55, -57, -51, -35, -24, -9, 11, 30, 47, 53, 57, 55, 46, 34, 20, 6, -12, -29, -43, -52, -55, -55, -55, -42, -29, -12, 8, 25, 41, 55, 62, 59, 51, 37, 23, 10, -6, -24, -40, -51, -56, -58, -58, -48, -33, -19, 2, 22, 41, 55, 61, 61, 56, 45, 28, 11, -3, -19, -37, -51, -57, -58, -58, -54, -39, -23, -2, 20, 36, 52, 64, 65, 58, 48, 33, 19, 4, -13, -35, -51, -58, -61, -62, -60, -47, -29, -7, 17, 34, 50, 67, 70, 62, 50, 35, 20, 6, -8, -29, -47, -57, -62, -61, -60, -54, -37, -15, 10, 29, 44, 60, 68, 66, 56, 42, 24, 12, 1, -19, -41, -55, -60, -62, -61, -57, -43, -21, 7, 24, 36, 53, 66, 67, 59, 46, 30, 15, 5, -11, -32, -48, -58, -63, -62, -59, -50, -32, -3, 22, 35, 49, 60, 66, 63, 53, 38, 19, 8, -5, -25, -43, -57, -64, -64, -62, -54, -39, -13, 16, 32, 46, 59, 65, 66, 56, 45, 26, 11, 3, -17, -39, -56, -65, -67, -62, -56, -44, -21, 10, 29, 40, 54, 63, 68, 61, 49, 33, 13, 2, -14, -34, -50, -64, -67, -63, -56, -44, -26, 2, 27, 38, 49, 57, 64, 61, 50, 36, 17, 6, -7, -27, -44, -60, -67, -63, -57, -48, -32, -7, 22, 36, 44, 53, 60, 62, 55, 41, 21, 7, -3, -20, -40, -58, -68, -65, -57, -47, -34, -14, 16, 37, 42, 47, 55, 59, 53, 42, 27, 10, -2, -14, -30, -47, -60, -63, -57, -49, -38, -20, 5, 30, 40, 44, 52, 57, 57, 46, 31, 13, -2, -12, -27, -44, -57, -64, -61, -50, -38, -20, 2, 25, 39, 41, 49, 55, 54, 45, 32, 17, 0, -12, -23, -37, -50, -59, -61, -52, -38, -22, -6, 17, 35, 39, 42, 48, 53, 48, 36, 22, 4, -9, -18, -30, -45, -56, -59, -54, -42, -27, -10, 12, 29, 37, 38, 44, 50, 47, 37, 25, 9, -5, -13, -23, -38, -50, -55, -54, -45, -32, -17, 5, 25, 34, 35, 39, 46, 48, 40, 29, 13, -3, -11, -21, -33, -44, -51, -54, -47, -34, -17, 2, 21, 32, 34, 34, 38, 42, 39, 27, 15, 1, -7, -13, -25, -36, -45, -49, -46, -36, -23, -6, 15, 27, 31, 31, 34, 39, 38, 30, 18, 3, -6, -10, -19, -32, -40, -46, -45, -36, -24, -11, 8, 24, 29, 27, 29, 34, 36, 30, 18, 4, -5, -5, -12, -25, -34, -39, -41, -37, -24, -11, 4, 18, 24, 25, 25, 29, 29, 26, 19, 5, -6, -6, -6, -18, -28, -33, -37, -34, -24, -11, 2, 15, 24, 23, 20, 24, 27, 22, 14, 4, -4, -4, -5, -15, -24, -26, -29, -32, -27, -13, 2, 14, 21, 21, 18, 21, 23, 20, 13, 5, -3, -5, -4, -9, -16, -21, -25, -28, -25, -14, 1, 10, 16, 19, 16, 16, 18, 16, 11, 5, -2, -5, -4, -6, -12, -17, -20, -22, -22, -17, -4, 8, 13, 16, 15, 13, 15, 14, 10, 4, -4, -6, -6, -5, -7, -11, -15, -17, -17, -15, -3, 10, 13, 14, 11, 7, 8, 9, 5, -3, -8, -7, -4, -2, -2, -6, -10, -9, -10, -12, -5, 11, 15, 13, 11, 5, 6, 7, 3, -6, -10, -8, -6, -6, -2, 1, -2, -6, -6, -7, -5, 8, 14, 10, 7, 4, 0, 1, -2, -6, -12, -11, -6, -2, 4, 8, 4, -2, -2, -4, -5, 3, 12, 8, 5, 4, 0, 0, -2, -8, -13, -15, -12, -7, -3, 6, 10, 7, 5, 6, 4, 6, 14, 10, 3, 0, -6, -10, -7, -10, -16, -19, -15, -8, 0, 11, 17, 13, 10, 11, 7, 5, 8, 9, 2, -4, -7, -12, -10, -10, -16, -21, -19, -13, -4, 10, 21, 22, 17, 17, 14, 9, 9, 9, 3, -7, -12, -17, -16, -14, -20, -25, -21, -15, -5, 10, 23, 27, 25, 22, 18, 11, 8, 4, -2, -9, -14, -18, -19, -14, -15, -23, -25, -20, -10, 9, 22, 29, 29, 26, 23, 16, 12, 6, 1, -6, -14, -18, -22, -20, -19, -27, -28, -25, -18, 0, 19, 32, 36, 33, 31, 23, 14, 7, 1, -4, -15, -23, -25, -24, -19, -25, -32, -29, -20, -3, 16, 31, 40, 38, 36, 29, 16, 9, 1, -4, -12, -23, -26, -28, -24, -26, -34, -33, -24, -8, 12, 29, 41, 44, 44, 37, 22, 11, 4, -4, -11, -24, -31, -32, -31, -30, -36, -39, -30, -11, 11, 29, 43, 51, 50, 44, 32, 15, 4, -4, -11, -24, -32, -33, -33, -34, -38, -42, -35, -17, 4, 24, 42, 56, 60, 52, 38, 19, 7, 1, -13, -28, -37, -37, -35, -37, -39, -43, -37, -19, 3, 22, 41, 57, 64, 57, 44, 26, 7, -2, -11, -24, -35, -41, -40, -38, -39, -43, -40, -24, 0, 20, 37, 55, 65, 63, 50, 32, 9, -4, -10, -24, -36, -42, -42, -41, -41, -41, -39, -26, -2, 19, 34, 51, 64, 66, 55, 38, 15, -3, -8, -20, -34, -42, -44, -43, -44, -45, -45, -35, -12, 14, 31, 50, 66, 73, 65, 49, 28, 7, -6, -18, -35, -45, -49, -51, -53, -51, -47, -37, -16, 10, 30, 49, 69, 78, 72, 56, 35, 14, -4, -17, -33, -46, -51, -55, -56, -54, -51, -40, -20, 5, 26, 44, 64, 76, 77, 64, 41, 19, 1, -14, -30, -43, -50, -57, -60, -58, -54, -43, -24, -2, 21, 39, 61, 76, 79, 72, 52, 28, 9, -10, -26, -41, -49, -54, -61, -62, -59, -51, -33, -10, 14, 34, 55, 75, 81, 79, 63, 39, 19, -2, -23, -40, -51, -56, -64, -67, -64, -56, -39, -16, 9, 29, 51, 73, 83, 82, 73, 50, 27, 9, -18, -40, -52, -56, -63, -69, -69, -61, -43, -20, 2, 21, 42, 66, 81, 82, 76, 59, 36, 19, -6, -33, -50, -57, -61, -71, -76, -68, -52, -28, -2, 17, 36, 62, 83, 86, 82, 69, 43, 22, 2, -28, -51, -60, -63, -67, -76, -74, -57, -34, -7, 14, 29, 53, 76, 87, 84, 75, 54, 33, 14, -18, -46, -58, -62, -69, -80, -84, -68, -44, -18, 7, 26, 49, 75, 91, 92, 82, 64, 42, 21, -8, -43, -63, -68, -68, -75, -86, -76, -48, -22, 4, 23, 41, 66, 87, 92, 83, 69, 51, 31, 6, -31, -59, -67, -69, -74, -88, -87, -62, -34, -7, 17, 36, 62, 87, 96, 90, 76, 60, 39, 14, -23, -58, -70, -71, -73, -83, -89, -68, -37, -13, 9, 26, 51, 79, 94, 91, 80, 68, 52, 28, -8, -48, -67, -70, -73, -84, -96, -83, -49, -22, 0, 20, 44, 75, 96, 98, 88, 75, 61, 40, 6, -39, -67, -72, -75, -83, -95, -91, -60, -29, -7, 13, 36, 66, 89, 97, 92, 78, 65, 50, 22, -21, -58, -71, -73, -78, -91, -98, -79, -45, -15, 4, 25, 56, 84, 101, 99, 86, 73, 60, 35, -9, -53, -72, -77, -80, -90, -98, -85, -51, -20, -2, 18, 48, 77, 96, 99, 87, 75, 62, 46, 9, -39, -68, -75, -75, -83, -95, -94, -67, -30, -7, 8, 34, 68, 92, 102, 93, 82, 72, 58, 26, -24, -61, -75, -78, -85, -97, -99, -78, -42, -12, 6, 28, 59, 87, 102, 99, 86, 74, 62, 38, -7, -52, -76, -81, -83, -93, -100, -90, -57, -23, -2, 18, 48, 80, 102, 103, 92, 81, 71, 51, 9, -41, -72, -83, -85, -93, -100, -92, -65, -32, -7, 13, 39, 72, 97, 103, 95, 85, 73, 55, 25, -21, -61, -79, -83, -90, -99, -97, -77, -45, -17, 1, 24, 59, 93, 107, 103, 92, 85, 72, 42, -6, -54, -80, -86, -91, -104, -105, -87, -56, -23, 0, 18, 48, 85, 106, 106, 96, 87, 77, 52, 13, -35, -71, -84, -88, -98, -106, -96, -70, -40, -14, 6, 31, 70, 103, 111, 103, 95, 88, 68, 29, -19, -61, -84, -91, -99, -106, -101, -80, -51, -22, 2, 23, 56, 91, 109, 108, 98, 89, 76, 45, 1, -44, -76, -87, -92, -102, -104, -90, -64, -34, -11, 8, 37, 78, 108, 113, 106, 96, 85, 61, 19, -29, -68, -88, -94, -102, -104, -93, -73, -46, -21, 2, 28, 63, 98, 113, 109, 100, 89, 70, 33, -14, -55, -81, -91, -98, -104, -98, -79, -54, -30, -9, 18, 52, 89, 108, 110, 104, 96, 79, 46, 2, -40, -71, -90, -100, -104, -100, -86, -67, -44, -19, 7, 40, 77, 105, 115, 109, 99, 86, 58, 17, -29, -63, -86, -97, -101, -101, -92, -74, -50, -26, -4, 28, 66, 98, 114, 113, 102, 90, 68, 33, -15, -53, -76, -93, -101, -104, -96, -79, -57, -34, -15, 15, 56, 90, 110, 115, 105, 93, 75, 44, 0, -43, -68, -86, -98, -101, -98, -83, -65, -42, -22, 4, 41, 79, 104, 113, 107, 96, 81, 57, 16, -31, -59, -79, -95, -101, -100, -90, -71, -49, -30, -9, 28, 67, 97, 110, 107, 97, 86, 65, 30, -14, -47, -67, -84, -98, -102, -96, -79, -59, -41, -22, 14, 53, 90, 110, 111, 101, 90, 75, 45, 2, -39, -64, -79, -93, -102, -101, -87, -64, -44, -28, 0, 39, 81, 108, 110, 102, 93, 82, 58, 18, -25, -54, -70, -85, -101, -103, -94, -72, -53, -39, -14, 25, 70, 104, 112, 103, 96, 88, 70, 34, -13, -48, -65, -78, -97, -108, -101, -79, -55, -42, -24, 11, 56, 96, 111, 103, 94, 90, 77, 46, 5, -34, -56, -71, -92, -109, -109, -91, -64, -46, -30, 0, 44, 89, 112, 108, 95, 88, 80, 57, 16, -27, -54, -66, -82, -104, -112, -100, -71, -46, -34, -13, 29, 80, 111, 112, 97, 86, 84, 69, 32, -15, -48, -61, -72, -94, -109, -106, -82, -54, -37, -23, 11, 61, 101, 113, 101, 85, 80, 75, 48, 4, -37, -56, -64, -84, -107, -112, -90, -60, -37, -29, -7, 43, 91, 111, 103, 86, 80, 77, 58, 20, -24, -52, -61, -75, -100, -111, -99, -72, -44, -27, -12, 29, 77, 105, 106, 91, 80, 75, 64, 33, -9, -43, -58, -69, -94, -111, -104, -78, -49, -28, -18, 11, 62, 97, 107, 94, 80, 75, 69, 47, 6, -36, -55, -62, -81, -105, -108, -87, -59, -33, -18, 1, 46, 86, 103, 97, 83, 75, 69, 52, 19, -23, -50, -59, -74, -97, -106, -91, -64, -38, -21, -9, 26, 70, 95, 95, 80, 71, 69, 60, 35, -6, -40, -53, -64, -87, -102, -96, -72, -45, -25, -14, 13, 56, 87, 95, 86, 75, 69, 60, 41, 6, -32, -54, -62, -77, -95, -99, -79, -51, -23, -8, 6, 39, 75, 92, 87, 72, 64, 62, 49, 21, -17, -47, -57, -67, -86, -97, -87, -59, -32, -16, -4, 25, 63, 89, 92, 78, 67, 63, 53, 27, -10, -40, -55, -63, -78, -93, -89, -65, -36, -17, -7, 11, 44, 77, 89, 79, 65, 61, 58, 41, 8, -26, -50, -59, -67, -83, -90, -76, -47, -25, -13, 3, 30, 63, 85, 82, 70, 63, 58, 45, 14, -18, -43, -56, -63, -74, -84, -78, -52, -26, -13, -2, 19, 46, 73, 81, 68, 57, 55, 49, 27, -5, -32, -48, -54, -63, -77, -80, -60, -34, -17, -5, 10, 34, 62, 79, 71, 57, 52, 48, 31, 2, -26, -45, -50, -53, -65, -75, -63, -37, -16, -6, 4, 19, 45, 68, 70, 57, 49, 49, 39, 16, -11, -33, -45, -49, -56, -70, -71, -51, -26, -8, 2, 13, 35, 63, 76, 63, 48, 43, 38, 23, -7, -32, -45, -47, -47, -58, -67, -55, -30, -8, 0, 4, 20, 46, 68, 65, 47, 38, 38, 31, 8, -19, -37, -44, -42, -48, -63, -62, -41, -16, -2, 5, 16, 37, 61, 68, 53, 38, 34, 31, 14, -14, -33, -40, -38, -41, -54, -60, -46, -20, -5, -3, 6, 25, 49, 63, 55, 38, 32, 33, 24, 1, -23, -34, -35, -36, -45, -59, -55, -30, -9, -3, 2, 16, 39, 59, 59, 44, 32, 30, 26, 7, -20, -33, -33, -32, -40, -53, -54, -35, -12, -3, -2, 10, 29, 48, 55, 45, 32, 28, 27, 14, -10, -27, -30, -28, -34, -46, -53, -41, -17, -5, -5, 5, 24, 44, 54, 46, 32, 25, 25, 18, -4, -25, -31, -24, -27, -39, -47, -42, -21, -4, -2, 1, 15, 35, 46, 44, 31, 22, 23, 20, 6, -15, -26, -23, -20, -29, -41, -42, -29, -11, -4, -4, 7, 26, 42, 47, 37, 25, 21, 19, 9, -10, -25, -25, -18, -24, -38, -40, -29, -11, 1, 0, 3, 19, 34, 42, 33, 19, 14, 15, 10, -5, -21, -24, -15, -13, -26, -35, -31, -17, -2, 0, -2, 11, 26, 37, 34, 20, 14, 13, 12, 2, -17, -25, -17, -12, -21, -31, -30, -19, -4, 4, 1, 9, 22, 32, 32, 19, 9, 9, 10, 4, -11, -21, -16, -9, -14, -23, -26, -20, -8, 0, -2, 3, 15, 26, 31, 24, 12, 9, 10, 6, -5, -17, -19, -12, -11, -18, -25, -22, -10, 1, 2, 2, 11, 22, 29, 24, 10, 3, 5, 4, -4, -13, -15, -8, -5, -10, -16, -18, -14, -5, -2, 0, 6, 13, 20, 23, 16, 6, 5, 5, 0, -7, -12, -12, -8, -7, -12, -19, -18, -7, 0, 2, 7, 13, 18, 20, 13, 3, -2, 1, -2, -6, -8, -6, -3, -2, -2, -10, -14, -10, -6, -4, 0, 4, 9, 14, 15, 6, -2, -2, -2, -4, -4, -5, -3, 2, 3, -3, -10, -9, -5, 0, 0, 0, 3, 8, 10, 3, -5, -7, -6, -4, 0, -2, -2, 3, 7, 7, 2, -5, -6, -3, 2, 2, 0, 0, 2, 2, -4, -9, -9, -7, -3, 2, 4, 8, 9, 6, 2, -3, -4, -3, -2, -2, -2, 0, 1, -3, -8, -11, -8, -6, -4, 2, 6, 9, 10, 9, 8, 5, -4, -7, -3, 1, 1, -6, -7, -6, -6, -11, -14, -10, -5, 3, 9, 12, 14, 13, 10, 9, 1, -6, -5, -4, -3, -4, -6, -8, -12, -12, -13, -13, -11, -3, 9, 16, 18, 15, 13, 14, 11, -2, -6, -4, -3, -5, -11, -13, -12, -14, -15, -14, -10, -4, 6, 15, 22, 21, 16, 13, 12, 3, -7, -8, -7, -7, -10, -14, -17, -16, -13, -12, -10, -7, 3, 15, 24, 26, 19, 16, 18, 12, -3, -9, -10, -9, -11, -18, -22, -21, -17, -14, -14, -10, 0, 14, 26, 32, 28, 23, 22, 21, 5, -9, -12, -16, -18, -22, -27, -27, -23, -17, -13, -8, 2, 12, 25, 35, 36, 29, 21, 20, 11, -6, -14, -17, -19, -22, -27, -28, -24, -20, -15, -11, -4, 7, 19, 32, 39, 35, 28, 25, 19, 4, -10, -17, -24, -28, -31, -33, -30, -26, -19, -11, -3, 8, 19, 31, 42, 42, 34, 27, 21, 9, -9, -19, -26, -31, -35, -34, -30, -26, -23, -13, -4, 4, 14, 25, 42, 49, 41, 31, 27, 20, 3, -15, -28, -37, -38, -39, -38, -35, -29, -16, 0, 9, 17, 26, 41, 52, 48, 36, 26, 19, 6, -16, -30, -39, -43, -41, -39, -33, -29, -22, -5, 7, 13, 21, 36, 55, 56, 46, 34, 24, 15, -8, -29, -44, -54, -50, -44, -39, -35, -27, -7, 11, 20, 25, 34, 54, 63, 53, 38, 22, 14, 0, -27, -45, -56, -56, -46, -39, -36, -31, -14, 8, 19, 23, 29, 46, 63, 61, 47, 30, 20, 8, -15, -39, -56, -62, -54, -44, -41, -38, -23, -2, 16, 23, 28, 42, 63, 69, 58, 41, 25, 13, -7, -34, -56, -68, -64, -50, -45, -43, -29, -7, 15, 26, 29, 40, 58, 72, 67, 48, 30, 16, 0, -26, -53, -68, -69, -57, -47, -46, -36, -16, 9, 25, 30, 38, 53, 71, 74, 58, 37, 17, 2, -21, -49, -70, -76, -64, -49, -43, -38, -21, 3, 25, 33, 37, 49, 65, 74, 65, 45, 24, 8, -11, -40, -68, -79, -72, -57, -48, -42, -29, -6, 20, 34, 39, 48, 63, 77, 74, 56, 31, 11, -8, -33, -61, -79, -80, -68, -53, -45, -34, -16, 11, 31, 41, 51, 61, 75, 78, 64, 42, 19, -3, -27, -55, -78, -84, -73, -59, -48, -37, -20, 5, 27, 40, 49, 58, 71, 80, 71, 49, 23, 2, -20, -47, -72, -86, -82, -66, -52, -39, -26, -5, 20, 39, 51, 59, 69, 79, 77, 61, 34, 7, -16, -42, -68, -88, -90, -75, -58, -41, -26, -8, 17, 39, 52, 59, 65, 74, 77, 65, 41, 12, -12, -35, -60, -81, -89, -79, -60, -45, -33, -17, 6, 31, 49, 59, 64, 73, 80, 74, 51, 22, -5, -29, -54, -78, -92, -90, -70, -49, -35, -18, 3, 26, 48, 60, 64, 68, 75, 75, 58, 31, 1, -25, -48, -73, -88, -90, -77, -56, -41, -23, -3, 21, 43, 58, 64, 70, 75, 77, 64, 40, 12, -18, -44, -70, -87, -94, -87, -64, -42, -22, -4, 16, 39, 58, 65, 66, 67, 74, 68, 46, 18, -12, -38, -62, -82, -92, -89, -67, -45, -28, -9, 13, 31, 52, 64, 67, 66, 72, 71, 53, 29, -3, -34, -59, -79, -94, -96, -77, -50, -29, -8, 12, 30, 49, 63, 68, 67, 68, 70, 56, 34, 6, -29, -57, -77, -92, -99, -84, -56, -32, -10, 11, 29, 45, 61, 69, 69, 68, 70, 60, 37, 12, -20, -50, -73, -90, -100, -91, -64, -37, -14, 7, 25, 42, 57, 66, 67, 65, 67, 64, 45, 21, -9, -41, -66, -84, -98, -95, -74, -47, -21, 3, 23, 39, 54, 64, 69, 69, 67, 63, 50, 27, 0, -33, -63, -83, -94, -95, -79, -54, -26, -2, 18, 35, 49, 61, 67, 67, 65, 64, 55, 33, 6, -25, -55, -82, -95, -98, -84, -60, -32, -6, 17, 36, 48, 56, 64, 66, 65, 62, 55, 39, 14, -16, -46, -76, -92, -96, -88, -69, -41, -9, 15, 33, 46, 54, 62, 68, 66, 59, 54, 44, 20, -12, -41, -72, -92, -97, -90, -71, -46, -14, 15, 34, 48, 55, 59, 62, 63, 60, 51, 42, 24, -6, -34, -63, -87, -95, -89, -75, -52, -23, 10, 31, 45, 54, 58, 62, 66, 63, 51, 42, 30, 1, -32, -59, -84, -96, -93, -80, -58, -28, 7, 32, 45, 53, 60, 64, 67, 62, 52, 41, 31, 9, -25, -55, -78, -92, -91, -82, -65, -39, -2, 30, 43, 49, 56, 61, 65, 63, 54, 44, 33, 16, -15, -47, -72, -88, -91, -84, -70, -45, -12, 22, 42, 48, 54, 58, 61, 63, 56, 43, 32, 20, -4, -36, -65, -82, -87, -82, -72, -53, -23, 15, 40, 46, 48, 55, 61, 62, 55, 43, 32, 21, 4, -26, -57, -75, -82, -80, -73, -58, -30, 5, 35, 46, 47, 51, 57, 61, 57, 46, 34, 22, 9, -15, -47, -71, -81, -80, -75, -62, -36, -4, 28, 46, 47, 49, 56, 60, 57, 48, 35, 23, 12, -9, -39, -67, -78, -76, -71, -65, -45, -13, 21, 45, 50, 46, 50, 58, 59, 49, 35, 23, 12, -4, -31, -62, -78, -74, -70, -65, -49, -18, 18, 43, 51, 45, 48, 56, 56, 45, 30, 20, 12, 0, -24, -53, -71, -69, -63, -60, -51, -25, 9, 36, 50, 47, 44, 50, 52, 45, 32, 21, 12, 1, -18, -44, -66, -70, -64, -59, -51, -31, 2, 32, 50, 51, 46, 47, 52, 47, 32, 17, 9, 0, -14, -34, -57, -67, -62, -56, -50, -33, -6, 24, 44, 51, 48, 47, 48, 46, 34, 21, 12, 2, -13, -32, -51, -62, -62, -56, -51, -38, -13, 18, 40, 51, 50, 45, 47, 46, 36, 20, 9, -2, -14, -28, -45, -59, -61, -54, -48, -37, -15, 14, 36, 49, 52, 48, 44, 42, 33, 19, 10, 0, -13, -26, -39, -52, -58, -54, -47, -37, -19, 9, 30, 44, 52, 48, 40, 38, 31, 19, 7, -3, -12, -22, -31, -42, -51, -49, -43, -36, -22, 1, 22, 35, 45, 47, 41, 37, 31, 23, 13, 3, -11, -22, -28, -36, -48, -53, -46, -35, -23, -4, 17, 31, 45, 49, 41, 33, 29, 23, 13, 2, -11, -22, -26, -29, -38, -46, -45, -34, -21, -6, 14, 25, 38, 46, 43, 35, 27, 19, 10, 3, -7, -20, -28, -28, -32, -38, -41, -35, -23, -8, 10, 23, 33, 44, 44, 36, 27, 18, 10, 0, -9, -22, -28, -28, -28, -33, -37, -32, -21, -7, 8, 20, 28, 38, 41, 36, 27, 17, 8, -2, -6, -17, -28, -31, -28, -27, -30, -30, -22, -7, 9, 19, 26, 35, 41, 37, 26, 16, 6, -5, -11, -18, -28, -31, -28, -22, -23, -23, -18, -4, 11, 19, 24, 27, 33, 33, 24, 14, 3, -8, -11, -15, -23, -29, -29, -21, -18, -19, -15, -5, 9, 16, 21, 26, 30, 32, 25, 13, 2, -9, -13, -16, -21, -27, -27, -20, -12, -13, -14, -7, 9, 17, 20, 24, 25, 26, 27, 15, 2, -9, -17, -17, -20, -25, -28, -23, -11, -6, -8, -5, 7, 19, 23, 24, 24, 24, 25, 16, 0, -13, -22, -22, -22, -26, -28, -22, -8, 2, 1, 0, 8, 18, 24, 24, 20, 18, 20, 15, 1, -12, -22, -24, -22, -23, -25, -22, -13, 2, 7, 3, 8, 16, 25, 28, 21, 15, 15, 15, 4, -13, -25, -29, -24, -20, -24, -21, -12, 1, 12, 10, 9, 16, 23, 27, 21, 14, 12, 10, 3, -10, -21, -28, -27, -22, -22, -20, -14, -4, 10, 14, 11, 17, 23, 29, 26, 15, 11, 10, 4, -12, -25, -33, -33, -26, -23, -22, -12, 0, 13, 22, 19, 20, 25, 29, 25, 12, 5, 3, 0, -12, -25, -32, -34, -27, -21, -20, -11, -2, 7, 18, 21, 22, 26, 30, 29, 21, 11, 4, -5, -14, -29, -38, -38, -33, -27, -23, -10, 4, 12, 22, 29, 30, 30, 31, 30, 21, 10, 0, -11, -19, -30, -39, -40, -36, -28, -20, -9, 4, 12, 20, 29, 32, 30, 32, 32, 23, 12, 3, -8, -18, -27, -39, -44, -40, -32, -25, -15, 1, 13, 22, 30, 37, 38, 36, 34, 26, 14, 2, -11, -22, -31, -40, -45, -42, -35, -26, -14, 0, 12, 19, 26, 35, 39, 36, 33, 28, 18, 6, -7, -18, -28, -37, -43, -43, -37, -30, -19, -6, 8, 20, 25, 34, 42, 41, 37, 32, 22, 8, -7, -19, -32, -40, -44, -44, -38, -30, -20, -6, 8, 19, 24, 30, 40, 41, 36, 29, 23, 13, -3, -16, -28, -39, -43, -44, -41, -34, -23, -11, 2, 16, 25, 32, 41, 46, 42, 34, 26, 15, 0, -16, -29, -40, -45, -45, -40, -32, -24, -12, -2, 12, 22, 26, 37, 45, 44, 34, 24, 18, 6, -12, -24, -37, -41, -40, -40, -36, -30, -17, -4, 9, 18, 25, 37, 45, 45, 40, 29, 19, 8, -8, -22, -38, -43, -42, -42, -35, -28, -17, -4, 7, 17, 23, 33, 43, 43, 38, 28, 19, 12, -3, -19, -34, -40, -38, -40, -38, -31, -22, -8, 5, 14, 21, 31, 44, 47, 41, 31, 20, 13, 3, -15, -33, -45, -45, -41, -38, -31, -24, -10, 4, 15, 21, 29, 42, 47, 41, 33, 22, 13, 4, -13, -29, -40, -41, -41, -41, -36, -26, -14, -2, 8, 17, 29, 42, 50, 46, 37, 27, 17, 7, -9, -27, -41, -48, -45, -42, -38, -29, -15, -2, 10, 18, 26, 38, 50, 51, 40, 28, 17, 6, -7, -24, -36, -43, -45, -41, -38, -31, -18, -8, 2, 13, 26, 38, 44, 49, 42, 33, 22, 8, -4, -20, -32, -41, -46, -44, -37, -32, -21, -8, 2, 14, 25, 35, 42, 47, 44, 31, 19, 7, -4, -15, -28, -36, -42, -40, -34, -31, -24, -9, 0, 7, 18, 30, 40, 44, 42, 32, 22, 12, 2, -10, -23, -31, -38, -42, -38, -31, -26, -13, -3, 2, 14, 29, 40, 41, 40, 36, 26, 13, 1, -10, -19, -26, -35, -43, -41, -33, -27, -17, -6, 1, 12, 27, 43, 47, 42, 37, 29, 14, 0, -10, -21, -29, -34, -40, -42, -33, -26, -18, -5, 3, 10, 23, 39, 45, 39, 33, 30, 18, 3, -8, -15, -22, -29, -37, -43, -36, -27, -22, -13, -4, 6, 19, 36, 47, 47, 37, 33, 25, 6, -8, -15, -25, -31, -36, -43, -42, -32, -21, -11, 0, 5, 15, 32, 46, 45, 35, 31, 28, 12, -6, -13, -20, -24, -31, -41, -46, -38, -26, -18, -9, 1, 14, 31, 43, 48, 42, 33, 28, 15, -5, -15, -18, -24, -31, -38, -41, -34, -26, -19, -8, 1, 10, 23, 37, 43, 41, 32, 26, 19, 3, -12, -15, -18, -24, -34, -42, -38, -28, -20, -13, -4, 6, 21, 37, 44, 43, 36, 28, 21, 8, -9, -16, -19, -25, -34, -42, -39, -29, -21, -13, -3, 8, 19, 34, 42, 41, 36, 28, 20, 8, -7, -15, -16, -19, -30, -41, -42, -31, -23, -15, -8, 3, 19, 36, 43, 39, 36, 30, 23, 13, -6, -19, -21, -20, -26, -38, -43, -35, -25, -15, -7, 3, 14, 30, 42, 40, 35, 28, 23, 16, 0, -14, -20, -19, -22, -34, -42, -37, -26, -15, -8, 0, 12, 27, 40, 41, 35, 29, 22, 16, 4, -9, -19, -20, -20, -29, -39, -39, -30, -19, -10, -3, 10, 24, 37, 42, 37, 31, 25, 18, 7, -7, -17, -21, -20, -28, -38, -40, -33, -22, -11, -5, 9, 25, 37, 44, 40, 32, 24, 17, 10, -5, -18, -24, -23, -28, -35, -38, -35, -26, -14, -5, 5, 19, 34, 44, 42, 33, 23, 18, 13, 0, -15, -20, -22, -26, -33, -39, -35, -28, -18, -10, 1, 18, 33, 43, 45, 38, 28, 20, 11, 2, -12, -22, -24, -28, -31, -36, -35, -29, -21, -11, 0, 15, 30, 40, 44, 39, 31, 21, 13, 8, -5, -17, -20, -25, -28, -32, -36, -34, -27, -18, -7, 9, 26, 39, 46, 45, 36, 25, 14, 10, -2, -16, -24, -29, -31, -31, -36, -36, -27, -16, -7, 6, 23, 37, 45, 44, 36, 26, 14, 8, 1, -14, -22, -23, -29, -32, -35, -36, -29, -21, -14, 0, 16, 35, 46, 45, 39, 33, 20, 8, 3, -9, -21, -28, -32, -34, -35, -36, -32, -25, -15, 1, 17, 32, 45, 49, 44, 35, 23, 7, 0, -7, -17, -25, -30, -31, -32, -34, -31, -25, -18, -7, 10, 27, 43, 50, 45, 35, 24, 13, 3, -7, -17, -24, -28, -30, -30, -33, -34, -26, -19, -11, 5, 22, 39, 50, 48, 37, 26, 16, 5, -7, -18, -23, -27, -28, -28, -33, -34, -24, -16, -11, 2, 17, 33, 48, 48, 37, 27, 18, 7, -5, -14, -20, -25, -30, -31, -32, -37, -31, -20, -15, -3, 15, 30, 46, 53, 43, 31, 20, 11, 0, -12, -21, -27, -31, -30, -30, -36, -33, -20, -10, -5, 9, 25, 41, 52, 46, 34, 23, 15, 6, -9, -21, -27, -30, -31, -31, -37, -39, -25, -12, -7, 1, 18, 36, 52, 53, 40, 28, 22, 13, -2, -18, -29, -32, -35, -34, -39, -40, -28, -13, -7, -2, 12, 33, 50, 56, 44, 30, 24, 18, 4, -15, -29, -32, -33, -33, -35, -40, -35, -20, -7, -2, 8, 25, 43, 54, 49, 35, 25, 18, 8, -7, -23, -32, -32, -34, -34, -37, -36, -24, -11, -5, 2, 18, 36, 51, 51, 39, 30, 24, 14, 0, -19, -32, -35, -35, -37, -38, -39, -29, -12, -2, 3, 14, 29, 47, 54, 45, 33, 26, 17, 5, -12, -31, -37, -36, -38, -38, -38, -32, -17, -3, 3, 9, 25, 42, 53, 49, 39, 31, 23, 10, -9, -27, -38, -40, -41, -41, -41, -36, -23, -5, 5, 8, 18, 36, 51, 51, 43, 34, 26, 16, 1, -20, -36, -40, -41, -42, -40, -38, -28, -10, 4, 7, 14, 30, 48, 51, 45, 39, 31, 21, 4, -16, -33, -41, -43, -43, -39, -38, -32, -15, 1, 7, 13, 25, 42, 52, 48, 39, 31, 22, 9, -10, -29, -40, -40, -40, -38, -35, -34, -20, -2, 5, 9, 17, 33, 49, 50, 43, 34, 25, 13, -4, -21, -36, -44, -44, -40, -35, -34, -26, -8, 5, 11, 17, 26, 43, 51, 46, 36, 27, 16, 1, -16, -31, -42, -46, -43, -37, -35, -29, -12, 3, 11, 17, 23, 37, 50, 52, 41, 29, 20, 4, -15, -30, -43, -49, -46, -39, -37, -33, -15, 3, 13, 19, 23, 35, 52, 55, 44, 29, 20, 8, -12, -28, -40, -48, -45, -39, -35, -32, -20, -2, 12, 16, 19, 28, 45, 55, 49, 35, 24, 14, -3, -20, -36, -49, -53, -45, -38, -35, -27, -9, 8, 19, 23, 26, 40, 55, 55, 41, 25, 15, -2, -19, -33, -46, -53, -47, -39, -35, -29, -14, 6, 19, 24, 25, 35, 53, 59, 47, 29, 17, 7, -12, -30, -47, -58, -56, -47, -39, -35, -22, -2, 17, 28, 30, 34, 50, 63, 56, 35, 19, 8, -9, -26, -43, -56, -58, -49, -42, -38, -27, -9, 12, 26, 33, 34, 44, 60, 62, 44, 23, 9, -4, -20, -40, -56, -63, -56, -44, -39, -30, -14, 8, 26, 35, 35, 43, 60, 64, 50, 28, 13, 2, -16, -37, -53, -62, -61, -50, -42, -32, -17, 2, 18, 32, 40, 44, 54, 63, 55, 37, 17, 4, -10, -31, -48, -61, -67, -59, -45, -36, -24, -5, 17, 33, 43, 47, 54, 64, 59, 42, 20, 3, -10, -28, -49, -63, -68, -63, -50, -37, -25, -7, 13, 31, 44, 48, 54, 61, 59, 48, 27, 6, -10, -24, -43, -59, -67, -67, -56, -39, -28, -13, 8, 24, 42, 51, 54, 58, 58, 52, 37, 14, -6, -20, -38, -54, -65, -70, -63, -45, -29, -17, 2, 18, 37, 52, 56, 58, 56, 51, 42, 23, -2, -19, -34, -50, -62, -70, -69, -52, -30, -17, -3, 15, 33, 50, 58, 58, 56, 52, 46, 29, 3, -15, -31, -45, -58, -68, -71, -60, -38, -20, -5, 11, 25, 42, 58, 62, 58, 51, 44, 36, 15, -10, -29, -43, -53, -64, -72, -67, -45, -21, -8, 4, 20, 40, 60, 65, 57, 53, 48, 42, 21, -8, -27, -40, -50, -62, -71, -71, -54, -29, -9, 3, 18, 34, 54, 68, 65, 57, 48, 40, 28, 2, -23, -41, -52, -60, -71, -75, -60, -34, -12, 0, 13, 31, 52, 69, 66, 56, 50, 44, 33, 7, -21, -38, -47, -55, -65, -75, -67, -41, -15, 2, 11, 23, 41, 61, 68, 59, 49, 40, 34, 17, -11, -35, -47, -48, -55, -69, -72, -50, -21, 0, 8, 15, 33, 56, 69, 62, 52, 44, 40, 26, -4, -30, -44, -48, -56, -69, -77, -59, -28, -7, 7, 15, 30, 52, 68, 66, 55, 45, 38, 30, 6, -24, -43, -49, -52, -64, -75, -65, -35, -10, 4, 11, 25, 45, 65, 67, 55, 48, 43, 34, 13, -18, -39, -45, -49, -61, -75, -72, -45, -17, -2, 9, 20, 39, 61, 70, 62, 52, 45, 36, 18, -9, -34, -47, -52, -58, -69, -72, -52, -23, -5, 7, 17, 35, 54, 65, 63, 55, 45, 37, 23, 0, -27, -45, -49, -53, -63, -71, -59, -31, -8, 7, 15, 28, 47, 61, 65, 58, 47, 38, 27, 6, -21, -41, -49, -53, -62, -69, -62, -39, -14, 3, 14, 28, 46, 59, 64, 62, 51, 39, 29, 11, -16, -40, -52, -55, -58, -65, -65, -47, -20, 1, 14, 24, 39, 52, 59, 64, 56, 43, 33, 16, -8, -32, -49, -55, -58, -63, -65, -54, -29, -3, 12, 21, 36, 51, 60, 65, 59, 46, 35, 21, -4, -28, -48, -56, -57, -59, -60, -55, -37, -12, 9, 19, 32, 46, 54, 58, 58, 48, 36, 26, 7, -18, -41, -53, -53, -52, -57, -58, -45, -19, 6, 15, 26, 42, 54, 59, 59, 52, 39, 28, 10, -16, -40, -56, -56, -52, -51, -53, -45, -22, 4, 17, 24, 35, 46, 56, 57, 52, 40, 30, 18, -7, -33, -54, -58, -52, -49, -53, -51, -33, -5, 17, 26, 34, 43, 54, 58, 53, 42, 31, 19, 0, -24, -47, -60, -55, -46, -46, -50, -39, -13, 13, 25, 32, 38, 48, 56, 52, 41, 30, 20, 7, -15, -41, -58, -55, -44, -41, -44, -40, -19, 10, 25, 28, 32, 41, 53, 52, 42, 31, 21, 13, -5, -32, -55, -60, -47, -36, -38, -40, -26, 2, 24, 29, 28, 32, 46, 48, 40, 29, 21, 14, 1, -23, -48, -56, -46, -34, -33, -36, -29, -7, 20, 28, 25, 26, 37, 46, 42, 30, 19, 15, 7, -13, -39, -58, -54, -37, -27, -27, -29, -17, 13, 29, 28, 24, 31, 42, 42, 34, 21, 11, 5, -10, -32, -51, -52, -40, -28, -24, -24, -18, 6, 27, 30, 26, 28, 36, 38, 33, 22, 11, 6, -7, -26, -44, -49, -42, -30, -21, -17, -16, -5, 18, 29, 26, 25, 29, 33, 33, 25, 13, 7, 0, -18, -36, -46, -45, -31, -20, -16, -16, -9, 12, 28, 29, 24, 25, 29, 31, 26, 13, 2, -5, -15, -26, -39, -46, -37, -19, -9, -9, -11, 1, 21, 31, 26, 21, 23, 26, 25, 15, 4, -4, -10, -20, -32, -41, -38, -22, -10, -7, -9, -6, 11, 26, 29, 22, 20, 21, 24, 19, 7, -6, -12, -17, -23, -30, -36, -27, -12, -3, 0, -5, 3, 18, 28, 25, 18, 15, 16, 15, 7, -4, -10, -14, -19, -24, -30, -26, -13, -3, 2, -3, -2, 12, 23, 26, 18, 13, 13, 14, 9, 0, -11, -14, -15, -18, -24, -26, -16, -4, 4, 0, -5, 6, 17, 25, 21, 11, 7, 8, 8, 1, -11, -14, -11, -10, -13, -20, -18, -7, 5, 7, -3, -2, 8, 21, 23, 12, 4, 4, 8, 7, -5, -15, -14, -11, -9, -15, -20, -13, 1, 8, 3, 0, 6, 17, 24, 16, 3, -2, 1, 0, -10, -17, -14, -8, -4, -5, -11, -12, 0, 9, 6, -3, 1, 10, 18, 16, 5, -3, 0, 3, -4, -13, -15, -10, -6, -4, -8, -13, -8, 5, 8, 5, 3, 9, 17, 18, 13, 0, -7, -5, -5, -11, -14, -11, -6, 2, 2, -6, -9, 1, 8, 5, -2, 1, 8, 14, 12, 2, -6, -5, -2, -6, -12, -10, -2, 3, 4, -5, -11, -6, 5, 6, 0, 0, 7, 12, 14, 6, -7, -8, -6, -6, -9, -10, -5, 4, 8, 4, -7, -11, -2, 6, 3, -2, 2, 9, 15, 12, -2, -8, -6, -3, -5, -11, -9, 2, 10, 7, -5, -15, -10, 4, 6, -2, -2, 8, 14, 14, 3, -9, -8, -5, -4, -8, -10, 0, 8, 9, 3, -9, -12, -3, 6, 3, -3, 1, 8, 13, 5, -9, -13, -7, -2, -2, -6, -2, 9, 13, 6, -6, -13, -10, 2, 4, -3, -2, 7, 13, 9, -6, -12, -11, -6, 0, -5, -5, 7, 15, 13, 1, -10, -13, -4, 5, -2, -7, -2, 9, 9, -3, -11, -11, -8, 2, 1, -3, 7, 15, 12, 4, -7, -13, -11, -2, 1, -4, -3, 7, 11, 3, -8, -11, -10, 0, 1, -5, 2, 12, 17, 11, -2, -11, -11, -3, 4, -4, -9, 1, 10, 3, -9, -11, -8, 0, 5, 1, 2, 11, 14, 9, 1, -11, -15, -11, -3, 1, -3, 3, 12, 11, 1, -7, -9, -6, -3, -5, -5, 5, 12, 9, 4, -3, -8, -8, -5, 0, -4, -3, 5, 6, -3, -10, -7, -3, 0, 2, 3, 10, 14, 11, 4, -3, -11, -15, -15, -9, -5, -5, 5, 13, 5, -2, 0, 2, 4, 1, -3, 4, 12, 11, 2, -5, -10, -13, -13, -11, -6, -4, 3, 13, 9, 1, -2, 4, 5, 1, -5, 3, 12, 13, 4, -9, -12, -14, -16, -17, -12, -5, 5, 16, 17, 6, 3, 9, 9, 2, -8, -7, 2, 7, 4, -8, -12, -10, -13, -14, -13, -6, 4, 13, 19, 10, 0, 6, 14, 8, -6, -9, 0, 7, 5, -8, -17, -13, -9, -14, -18, -13, 2, 15, 23, 16, 4, 5, 16, 15, 0, -10, -6, 3, 6, -4, -15, -15, -10, -11, -16, -16, -5, 10, 21, 18, 7, 2, 12, 18, 6, -7, -9, 1, 7, 1, -14, -19, -15, -13, -16, -18, -8, 7, 19, 24, 16, 5, 8, 16, 9, -4, -9, -5, 3, 4, -9, -19, -18, -13, -12, -17, -12, 2, 16, 22, 17, 6, 4, 14, 13, 1, -8, -6, 2, 6, -5, -18, -20, -16, -14, -18, -17, -5, 12, 23, 24, 14, 9, 15, 19, 9, -5, -8, -3, 2, -6, -17, -23, -19, -14, -16, -17, -8, 7, 19, 24, 19, 10, 11, 17, 13, 3, -5, -3, -2, -4, -14, -24, -25, -20, -18, -16, -10, 3, 16, 26, 28, 18, 11, 15, 17, 9, -4, -7, -6, -6, -12, -24, -29, -22, -16, -15, -10, 0, 13, 24, 27, 22, 14, 13, 16, 13, 2, -6, -7, -9, -12, -21, -29, -27, -21, -15, -10, -3, 8, 21, 29, 26, 17, 13, 17, 19, 9, -5, -10, -9, -12, -21, -30, -29, -22, -14, -10, -4, 7, 17, 26, 23, 17, 13, 12, 18, 16, 5, -6, -10, -11, -19, -29, -32, -27, -18, -10, -4, 4, 13, 25, 26, 21, 16, 11, 16, 17, 8, -5, -12, -12, -16, -25, -30, -27, -19, -10, -6, 0, 10, 21, 24, 18, 15, 13, 16, 20, 14, 1, -10, -12, -15, -26, -31, -29, -22, -12, -5, 0, 8, 19, 25, 22, 17, 14, 14, 19, 17, 4, -10, -15, -15, -22, -30, -30, -26, -16, -6, 1, 7, 15, 23, 23, 18, 17, 17, 17, 17, 8, -6, -15, -18, -24, -31, -29, -26, -19, -8, 2, 7, 15, 23, 24, 21, 17, 15, 15, 17, 13, -4, -16, -20, -23, -30, -32, -27, -19, -8, 3, 7, 14, 23, 24, 20, 16, 16, 15, 14, 10, 0, -12, -20, -24, -31, -32, -25, -19, -10, 0, 9, 14, 22, 27, 23, 17, 17, 18, 12, 8, 1, -12, -18, -23, -31, -34, -26, -17, -9, -2, 6, 14, 22, 27, 22, 16, 15, 18, 17, 10, 3, -9, -17, -21, -31, -38, -32, -23, -13, -5, 4, 14, 21, 30, 30, 21, 17, 18, 17, 10, 3, -8, -20, -23, -29, -38, -34, -25, -12, 0, 3, 11, 17, 26, 31, 23, 15, 13, 16, 14, 5, -4, -15, -19, -23, -35, -38, -32, -19, -7, -5, 6, 16, 25, 36, 32, 22, 19, 19, 15, 3, -7, -16, -23, -26, -35, -42, -34, -19, -3, 1, 6, 18, 26, 37, 34, 20, 15, 14, 14, 5, -7, -15, -21, -23, -28, -39, -37, -22, -5, 1, 3, 15, 25, 35, 40, 27, 14, 14, 14, 6, -7, -14, -20, -25, -27, -36, -41, -28, -8, 2, 4, 14, 24, 33, 40, 32, 17, 13, 12, 5, -7, -14, -17, -24, -28, -34, -40, -32, -14, 1, 4, 13, 26, 33, 41, 40, 26, 15, 12, 4, -9, -17, -20, -25, -31, -34, -41, -38, -20, 0, 7, 12, 24, 32, 40, 41, 30, 17, 11, 4, -10, -18, -19, -21, -27, -31, -35, -36, -24, -5, 5, 9, 21, 31, 37, 41, 36, 21, 11, 4, -8, -15, -18, -21, -26, -31, -34, -37, -30, -12, 3, 9, 18, 30, 38, 44, 42, 29, 15, 7, -6, -18, -23, -24, -25, -31, -34, -36, -33, -15, 3, 9, 17, 28, 38, 44, 42, 34, 20, 8, -5, -18, -23, -22, -24, -30, -35, -35, -35, -24, -6, 6, 14, 25, 36, 42, 45, 42, 28, 13, 1, -15, -26, -27, -26, -29, -35, -39, -38, -28, -10, 5, 13, 21, 36, 47, 48, 45, 36, 21, 6, -11, -25, -31, -30, -29, -35, -41, -41, -34, -18, 1, 15, 24, 35, 47, 52, 51, 42, 26, 8, -9, -25, -32, -34, -32, -34, -40, -41, -35, -22, -5, 11, 21, 30, 44, 52, 51, 45, 32, 15, -3, -19, -28, -33, -34, -36, -42, -44, -41, -30, -13, 6, 20, 29, 43, 54, 56, 50, 37, 22, 4, -17, -31, -39, -39, -38, -40, -44, -41, -31, -14, 4, 18, 26, 37, 52, 57, 54, 44, 29, 11, -9, -26, -38, -42, -40, -41, -45, -46, -39, -24, -2, 17, 25, 35, 49, 59, 59, 52, 36, 19, -2, -22, -38, -46, -45, -43, -44, -47, -41, -28, -7, 12, 22, 32, 45, 58, 60, 52, 40, 26, 9, -14, -36, -46, -47, -44, -44, -50, -47, -34, -14, 8, 21, 30, 42, 58, 65, 58, 46, 32, 14, -7, -30, -47, -51, -50, -45, -50, -51, -38, -20, 4, 19, 28, 38, 53, 67, 63, 50, 40, 23, 2, -22, -43, -54, -55, -50, -53, -57, -48, -31, -6, 17, 28, 39, 53, 69, 72, 60, 47, 29, 7, -18, -39, -54, -59, -56, -53, -55, -52, -37, -16, 10, 25, 36, 48, 65, 75, 68, 54, 40, 20, -6, -31, -52, -61, -61, -59, -63, -62, -46, -24, 2, 20, 33, 50, 67, 79, 75, 62, 49, 30, 2, -29, -50, -63, -66, -65, -64, -64, -50, -28, -6, 18, 34, 48, 62, 74, 79, 70, 54, 38, 14, -19, -45, -62, -70, -71, -67, -68, -61, -39, -15, 10, 28, 45, 63, 77, 82, 77, 62, 47, 25, -9, -40, -61, -70, -73, -69, -70, -66, -47, -23, 2, 23, 41, 57, 71, 79, 83, 72, 55, 37, 6, -27, -51, -67, -76, -78, -77, -75, -60, -35, -12, 13, 37, 59, 75, 82, 86, 81, 66, 48, 17, -23, -50, -66, -77, -83, -83, -78, -66, -43, -18, 7, 31, 54, 73, 83, 87, 87, 74, 55, 29, -10, -41, -61, -76, -85, -88, -84, -72, -53, -28, -3, 22, 51, 75, 84, 88, 92, 87, 67, 40, 0, -38, -60, -77, -89, -94, -89, -77, -59, -34, -7, 17, 44, 73, 88, 90, 91, 88, 74, 49, 12, -29, -57, -73, -84, -93, -94, -84, -68, -44, -17, 8, 33, 64, 85, 90, 92, 91, 83, 63, 30, -15, -50, -71, -82, -92, -96, -90, -74, -52, -26, 0, 24, 56, 82, 92, 93, 92, 89, 74, 42, 0, -41, -67, -80, -93, -100, -97, -83, -62, -35, -8, 16, 43, 74, 91, 96, 96, 93, 83, 56, 16, -28, -61, -79, -92, -99, -99, -90, -71, -45, -16, 9, 36, 66, 88, 98, 97, 93, 87, 68, 31, -16, -52, -75, -89, -98, -103, -98, -81, -54, -23, 1, 25, 56, 83, 97, 98, 92, 88, 76, 46, 1, -42, -68, -81, -91, -99, -97, -82, -58, -30, -6, 15, 44, 73, 91, 94, 89, 85, 78, 55, 16, -28, -59, -77, -87, -93, -95, -85, -65, -40, -16, 6, 33, 62, 85, 94, 90, 86, 81, 66, 32, -15, -52, -73, -84, -90, -93, -87, -69, -45, -22, 0, 22, 48, 75, 88, 88, 85, 80, 67, 42, 4, -36, -62, -77, -87, -90, -85, -72, -52, -30, -11, 11, 36, 63, 83, 86, 86, 82, 74, 54, 17, -25, -55, -72, -81, -88, -87, -77, -57, -34, -16, 4, 26, 54, 77, 84, 84, 82, 75, 58, 27, -12, -45, -65, -76, -84, -84, -76, -61, -41, -24, -7, 15, 41, 67, 78, 81, 80, 76, 67, 42, 5, -30, -54, -67, -79, -85, -79, -67, -50, -32, -16, 6, 32, 58, 73, 77, 81, 78, 68, 49, 16, -19, -45, -63, -74, -80, -77, -67, -53, -35, -20, -3, 20, 45, 65, 72, 76, 75, 68, 56, 29, -6, -33, -52, -65, -75, -77, -70, -57, -42, -28, -13, 9, 34, 57, 70, 73, 75, 72, 63, 41, 7, -24, -46, -60, -70, -75, -72, -59, -45, -31, -18, 0, 25, 48, 63, 68, 70, 71, 65, 47, 17, -13, -33, -49, -62, -73, -73, -61, -48, -37, -25, -10, 14, 39, 57, 64, 67, 70, 69, 54, 28, -3, -27, -44, -57, -68, -74, -66, -50, -39, -26, -13, 5, 30, 50, 60, 62, 64, 65, 58, 38, 9, -17, -35, -46, -59, -69, -67, -52, -40, -31, -20, -6, 18, 42, 55, 58, 60, 65, 62, 47, 20, -10, -28, -39, -51, -66, -70, -58, -44, -34, -23, -10, 11, 34, 51, 57, 58, 62, 63, 51, 29, 2, -21, -34, -46, -60, -69, -63, -49, -37, -27, -15, 3, 26, 45, 55, 56, 58, 62, 55, 37, 11, -14, -29, -39, -52, -65, -66, -52, -40, -30, -18, -5, 17, 39, 52, 54, 55, 58, 57, 44, 21, -8, -24, -33, -45, -59, -66, -57, -43, -31, -20, -11, 7, 30, 47, 53, 51, 52, 55, 51, 33, 4, -20, -29, -36, -49, -64, -63, -50, -36, -24, -14, 0, 22, 43, 55, 53, 49, 52, 51, 39, 12, -16, -27, -33, -45, -60, -66, -53, -37, -25, -16, -6, 16, 40, 53, 53, 47, 49, 51, 43, 22, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, -2, -2, -2, -2, 0, -2, 0, 0, 1, 2, 3, 4, 4, 4, 5, 6, 7, 6, 3, 1, 0, -3, -5, -11, -17, -20, -20, -18, -16, -17, -17, -14, -10, -9, -13, -18, -19, -15, -13, -12, -13, -8, 1, 12, 25, 32, 40, 45, 50, 49, 41, 32, 24, 16, 9, 1, -12, -20, -23, -24, -20, -20, -18, -12, -11, -12, -7, 0, 10, 17, 23, 25, 24, 21, 22, 23, 21, 10, 1, -5, -8, -11, -19, -29, -33, -32, -26, -19, -16, -14, -12, -8, -7, -11, -19, -27, -29, -27, -25, -25, -24, -17, -4, 13, 26, 34, 43, 54, 59, 56, 46, 33, 23, 15, 5, -11, -23, -32, -35, -32, -30, -27, -23, -16, -11, -5, 3, 11, 23, 31, 36, 33, 28, 27, 26, 21, 11, 1, -9, -14, -18, -23, -28, -35, -33, -26, -18, -12, -11, -7, -4, -2, 0, -8, -19, -29, -33, -32, -30, -30, -25, -17, -4, 13, 26, 36, 47, 55, 59, 53, 43, 32, 23, 12, 0, -14, -23, -30, -35, -35, -35, -33, -28, -19, -11, -6, 3, 11, 22, 33, 39, 38, 34, 30, 27, 20, 11, 0, -9, -17, -21, -26, -31, -34, -29, -19, -8, -3, 0, -3, 1, 4, 1, -11, -25, -35, -37, -39, -35, -32, -27, -17, 0, 15, 29, 42, 55, 63, 62, 55, 47, 38, 27, 14, -4, -20, -31, -40, -44, -46, -45, -41, -34, -25, -14, -3, 8, 22, 32, 43, 44, 40, 36, 34, 26, 18, 8, -2, -11, -20, -25, -29, -33, -31, -21, -10, -2, -2, -2, 4, 6, 9, 0, -14, -28, -35, -39, -38, -38, -36, -30, -16, 0, 16, 29, 41, 55, 65, 67, 59, 49, 39, 28, 13, -3, -19, -32, -42, -48, -51, -53, -47, -36, -22, -12, 0, 10, 24, 38, 46, 48, 43, 39, 32, 26, 17, 6, -7, -16, -21, -26, -31, -34, -28, -16, -2, 3, 1, 2, 8, 16, 12, 2, -15, -27, -34, -37, -41, -47, -44, -33, -16, 1, 16, 31, 47, 65, 75, 73, 63, 52, 41, 27, 9, -14, -34, -47, -54, -55, -58, -57, -50, -35, -17, 0, 8, 20, 34, 47, 54, 49, 42, 36, 29, 21, 9, -4, -14, -21, -26, -30, -33, -28, -18, -5, 4, 6, 6, 8, 13, 17, 12, -4, -21, -33, -39, -44, -49, -50, -46, -35, -15, 4, 22, 36, 55, 72, 81, 78, 69, 54, 42, 27, 6, -19, -38, -52, -57, -62, -65, -64, -52, -35, -17, -3, 8, 19, 33, 45, 50, 48, 42, 35, 29, 18, 7, -5, -11, -20, -26, -29, -27, -20, -13, -4, 3, 8, 9, 11, 12, 12, 5, -8, -22, -33, -42, -50, -53, -51, -42, -27, -11, 9, 27, 45, 62, 75, 78, 73, 60, 48, 32, 14, -8, -30, -46, -54, -60, -64, -62, -53, -39, -23, -8, 5, 17, 30, 41, 46, 44, 38, 30, 22, 11, 4, -5, -12, -20, -25, -26, -24, -17, -7, 3, 8, 11, 12, 14, 15, 14, 9, -4, -17, -32, -44, -54, -57, -56, -48, -36, -22, -5, 18, 41, 61, 74, 79, 75, 67, 55, 39, 20, -2, -20, -37, -47, -56, -62, -63, -57, -44, -31, -18, -5, 7, 16, 28, 35, 38, 37, 32, 25, 16, 8, 3, -2, -5, -11, -19, -21, -16, -7, 3, 6, 8, 7, 8, 10, 9, 5, -4, -13, -23, -37, -49, -54, -54, -47, -38, -25, -9, 9, 30, 50, 67, 77, 75, 69, 58, 42, 26, 7, -12, -31, -46, -52, -56, -59, -58, -49, -36, -19, -5, 8, 14, 22, 28, 33, 35, 30, 23, 13, 4, 3, 3, 0, -8, -12, -13, -10, -6, 2, 8, 11, 12, 11, 9, 4, -2, -5, -12, -23, -35, -46, -52, -54, -48, -36, -22, -8, 9, 28, 46, 61, 70, 72, 68, 58, 45, 27, 9, -8, -22, -35, -43, -48, -48, -46, -39, -33, -23, -12, 1, 8, 11, 14, 16, 19, 19, 17, 11, 7, 8, 11, 13, 7, 5, 2, 2, 2, 4, 6, 6, 5, 2, -3, -5, -9, -11, -17, -23, -29, -34, -40, -45, -41, -32, -18, -5, 7, 19, 36, 54, 64, 67, 61, 55, 48, 36, 18, 3, -11, -23, -36, -45, -46, -42, -39, -34, -27, -20, -11, 0, 10, 13, 14, 12, 13, 13, 10, 7, 6, 9, 11, 11, 11, 10, 10, 8, 9, 9, 9, 6, 1, -4, -12, -16, -22, -25, -28, -29, -30, -39, -43, -39, -26, -11, 0, 8, 19, 33, 48, 58, 63, 61, 56, 50, 40, 25, 8, -5, -15, -24, -35, -41, -42, -39, -32, -29, -25, -21, -13, -6, 0, 4, 2, 2, 3, 6, 6, 7, 11, 17, 20, 22, 23, 24, 23, 21, 17, 12, 4, -5, -13, -22, -29, -37, -41, -40, -36, -31, -32, -34, -34, -22, -6, 8, 14, 20, 29, 41, 50, 56, 56, 49, 45, 39, 30, 17, 5, -8, -19, -28, -34, -35, -32, -27, -25, -25, -23, -19, -12, -7, -4, -6, -10, -11, -7, 0, 4, 10, 14, 19, 26, 32, 35, 34, 31, 25, 16, 6, -5, -17, -29, -39, -47, -51, -50, -44, -35, -28, -27, -25, -18, -6, 10, 18, 21, 25, 31, 40, 46, 49, 48, 44, 42, 37, 29, 19, 8, -5, -14, -21, -29, -30, -30, -27, -28, -32, -33, -31, -22, -17, -15, -17, -19, -19, -9, 5, 16, 22, 25, 31, 38, 44, 47, 43, 34, 20, 6, -9, -21, -35, -49, -59, -62, -60, -53, -42, -30, -22, -15, -6, 4, 14, 23, 27, 28, 27, 30, 35, 38, 39, 42, 38, 35, 30, 25, 20, 12, 4, -6, -18, -23, -22, -20, -22, -30, -37, -39, -34, -29, -27, -27, -26, -23, -16, -3, 10, 21, 29, 35, 43, 46, 50, 49, 41, 28, 15, -2, -19, -35, -50, -62, -67, -67, -60, -50, -36, -23, -14, -6, 3, 11, 21, 27, 27, 24, 25, 27, 29, 31, 36, 41, 42, 39, 33, 27, 22, 17, 8, -3, -11, -15, -15, -18, -25, -35, -42, -45, -42, -41, -41, -40, -38, -28, -12, 7, 22, 34, 43, 51, 59, 62, 59, 49, 37, 20, 1, -19, -38, -54, -65, -73, -74, -69, -55, -35, -19, -10, -2, 8, 18, 23, 25, 25, 22, 20, 19, 20, 22, 30, 39, 44, 42, 39, 35, 32, 29, 18, 4, -8, -13, -15, -17, -24, -33, -43, -47, -44, -42, -40, -40, -39, -32, -17, 3, 16, 28, 39, 47, 53, 56, 56, 52, 40, 24, 5, -12, -29, -43, -54, -65, -72, -71, -56, -36, -20, -13, -4, 5, 12, 18, 21, 23, 20, 18, 14, 16, 19, 27, 38, 45, 45, 42, 41, 42, 37, 27, 15, 1, -8, -12, -13, -17, -30, -40, -47, -48, -47, -46, -46, -45, -41, -28, -9, 11, 26, 38, 45, 51, 55, 58, 55, 47, 31, 10, -12, -27, -39, -49, -58, -67, -69, -62, -46, -26, -13, -4, 2, 7, 14, 18, 21, 20, 15, 11, 12, 14, 21, 32, 40, 44, 42, 42, 40, 37, 33, 22, 11, 1, -7, -11, -11, -19, -30, -39, -43, -43, -42, -43, -44, -44, -36, -20, 0, 14, 25, 35, 42, 46, 50, 50, 48, 36, 17, -3, -18, -30, -36, -43, -52, -59, -60, -49, -35, -20, -12, -7, -4, 2, 8, 12, 12, 9, 9, 12, 16, 23, 29, 39, 45, 46, 46, 43, 41, 37, 30, 20, 7, -5, -10, -11, -15, -25, -39, -46, -45, -43, -42, -45, -46, -39, -26, -8, 8, 20, 31, 41, 45, 48, 46, 44, 36, 21, 1, -20, -31, -33, -36, -44, -53, -59, -54, -41, -26, -17, -12, -6, -3, 5, 7, 9, 11, 11, 12, 15, 20, 29, 36, 42, 46, 45, 42, 40, 38, 33, 25, 13, 4, -7, -10, -11, -17, -29, -38, -38, -34, -35, -39, -41, -39, -31, -16, -6, 4, 14, 24, 30, 34, 34, 35, 32, 22, 8, -9, -16, -16, -17, -22, -33, -43, -46, -41, -34, -30, -25, -19, -14, -9, -6, -2, 5, 9, 13, 15, 21, 29, 36, 43, 47, 46, 46, 42, 39, 37, 31, 20, 10, 0, -6, -9, -14, -22, -29, -33, -31, -30, -34, -37, -37, -30, -21, -12, -5, 1, 10, 20, 28, 31, 31, 28, 20, 12, 0, -8, -10, -10, -16, -24, -33, -39, -44, -42, -35, -28, -23, -18, -14, -10, -4, 6, 12, 16, 17, 22, 29, 33, 35, 38, 41, 43, 41, 38, 34, 30, 24, 16, 9, 3, -4, -10, -15, -21, -23, -23, -23, -24, -28, -32, -31, -28, -22, -15, -10, -6, 2, 11, 20, 23, 25, 19, 14, 9, 5, 3, 2, -2, -8, -19, -28, -36, -42, -44, -39, -33, -28, -26, -20, -11, 0, 8, 15, 22, 28, 33, 35, 36, 37, 38, 41, 40, 38, 32, 27, 21, 17, 11, 4, -3, -8, -12, -17, -18, -16, -16, -15, -18, -22, -25, -26, -25, -23, -19, -15, -9, -2, 8, 13, 17, 18, 17, 16, 15, 13, 10, 6, 0, -9, -21, -32, -42, -47, -46, -43, -36, -30, -22, -15, -6, 4, 14, 22, 28, 33, 36, 37, 36, 35, 37, 36, 36, 32, 27, 23, 16, 10, 5, 0, -7, -10, -12, -11, -11, -11, -10, -9, -11, -16, -22, -27, -30, -30, -30, -25, -19, -9, 0, 7, 13, 18, 23, 27, 27, 26, 20, 12, 1, -13, -27, -40, -50, -54, -54, -49, -42, -33, -21, -10, 1, 14, 24, 30, 39, 44, 43, 38, 36, 38, 37, 34, 31, 28, 22, 13, 7, 5, -2, -7, -11, -14, -13, -13, -8, -6, -6, -10, -12, -14, -19, -26, -34, -38, -33, -26, -15, -7, 2, 7, 17, 26, 35, 40, 37, 29, 19, 7, -12, -31, -44, -53, -56, -61, -62, -59, -46, -27, -9, 5, 14, 25, 36, 47, 53, 51, 45, 37, 34, 32, 29, 26, 23, 18, 13, 5, 0, -3, -4, -6, -10, -12, -12, -6, 2, 6, 2, -6, -12, -17, -21, -31, -41, -47, -43, -32, -20, -11, -4, 9, 21, 40, 50, 48, 42, 34, 22, 5, -16, -36, -53, -58, -63, -69, -73, -63, -43, -19, -2, 9, 19, 34, 50, 60, 61, 53, 42, 37, 32, 30, 24, 21, 16, 11, 4, -4, -7, -6, -5, -5, -10, -14, -11, -4, 3, 2, -2, -8, -13, -19, -26, -36, -42, -40, -33, -21, -9, 1, 10, 22, 36, 49, 53, 47, 36, 19, 1, -18, -36, -51, -60, -65, -67, -67, -63, -47, -24, -4, 11, 20, 33, 48, 57, 57, 52, 42, 33, 30, 28, 25, 19, 16, 12, 8, 3, -2, -2, -2, -2, -5, -8, -10, -5, -2, 0, 0, -5, -8, -15, -23, -32, -39, -38, -33, -24, -15, -7, 5, 16, 30, 45, 52, 49, 40, 23, 4, -14, -29, -42, -55, -63, -67, -67, -61, -50, -35, -19, 0, 16, 31, 46, 56, 59, 56, 47, 38, 34, 31, 28, 23, 16, 10, 4, 0, -2, -2, 0, -5, -9, -12, -11, -7, -3, -3, -4, -5, -4, -7, -14, -26, -33, -32, -27, -20, -15, -7, 2, 13, 21, 34, 42, 46, 40, 25, 7, -13, -27, -35, -44, -54, -62, -64, -60, -51, -39, -26, -10, 8, 24, 40, 51, 58, 60, 54, 44, 36, 29, 24, 19, 13, 8, 0, -6, -5, 0, 1, 0, -4, -3, -2, 0, 1, -2, -5, -5, -4, -7, -17, -27, -31, -29, -24, -19, -15, -9, -3, 7, 18, 27, 34, 39, 37, 26, 9, -9, -24, -32, -39, -47, -55, -60, -57, -51, -42, -32, -20, -6, 14, 31, 48, 57, 60, 58, 52, 45, 35, 25, 21, 17, 9, 0, -8, -10, -8, -7, -6, -9, -9, -6, -2, 0, -3, -6, -6, -2, 1, -6, -15, -25, -25, -20, -17, -13, -11, -7, 1, 8, 16, 24, 31, 34, 29, 16, -3, -17, -28, -35, -41, -47, -54, -56, -54, -46, -37, -27, -15, 4, 23, 40, 50, 58, 60, 58, 50, 42, 34, 26, 19, 14, 4, -6, -13, -13, -13, -14, -16, -15, -12, -9, -7, -7, -4, -4, 2, 7, 5, 0, -8, -11, -13, -13, -11, -10, -11, -11, -9, 0, 8, 14, 22, 24, 19, 9, -3, -14, -23, -29, -32, -38, -47, -54, -52, -44, -32, -23, -9, 8, 23, 39, 52, 59, 58, 51, 46, 43, 33, 25, 16, 9, 4, -4, -11, -15, -16, -16, -15, -14, -15, -16, -13, -7, -5, 2, 5, 5, 5, 6, 3, -4, -6, -4, -5, -10, -16, -16, -13, -6, 4, 12, 15, 17, 14, 10, 4, -8, -17, -23, -30, -38, -46, -52, -51, -41, -30, -20, -8, 9, 29, 47, 56, 57, 55, 52, 50, 45, 34, 20, 10, 2, -2, -9, -16, -22, -24, -22, -21, -22, -19, -14, -7, -4, 1, 5, 11, 15, 20, 17, 9, 3, 3, 0, -6, -15, -21, -23, -16, -9, -3, 4, 10, 13, 15, 13, 4, -9, -15, -20, -27, -39, -48, -51, -47, -38, -29, -21, -7, 16, 36, 48, 51, 52, 55, 60, 59, 49, 33, 20, 12, 7, -2, -13, -24, -28, -27, -26, -30, -32, -29, -20, -9, 0, 3, 8, 16, 25, 28, 23, 17, 12, 6, -2, -14, -26, -31, -27, -18, -10, -3, 7, 15, 22, 24, 18, 9, 0, -9, -19, -34, -46, -57, -57, -51, -44, -38, -26, -5, 21, 42, 48, 53, 58, 67, 75, 71, 57, 37, 23, 12, 3, -12, -27, -39, -43, -43, -45, -47, -42, -28, -12, 2, 7, 12, 20, 32, 38, 37, 30, 21, 13, 1, -13, -26, -34, -33, -26, -17, -10, -3, 9, 20, 25, 22, 13, 5, -3, -13, -28, -43, -53, -56, -51, -46, -40, -31, -14, 10, 31, 41, 47, 56, 67, 76, 73, 63, 46, 30, 19, 9, -7, -25, -39, -47, -50, -54, -52, -50, -38, -22, -9, 4, 12, 22, 30, 39, 41, 39, 31, 22, 12, -3, -19, -30, -32, -29, -23, -17, -9, 1, 12, 20, 24, 18, 10, 2, -7, -19, -35, -50, -59, -59, -54, -49, -43, -31, -9, 15, 32, 41, 53, 70, 85, 87, 80, 64, 49, 37, 23, 2, -23, -42, -52, -59, -66, -69, -68, -56, -38, -18, -2, 9, 19, 31, 41, 49, 51, 44, 35, 21, 5, -9, -22, -29, -30, -26, -20, -14, -7, 5, 15, 17, 14, 9, 2, -4, -16, -29, -45, -55, -56, -50, -46, -44, -36, -19, 1, 19, 33, 46, 63, 79, 86, 84, 73, 60, 47, 32, 12, -10, -30, -48, -59, -68, -72, -73, -64, -49, -30, -12, 2, 12, 26, 35, 45, 51, 51, 44, 30, 15, 3, -9, -17, -20, -21, -19, -18, -14, 0, 10, 16, 15, 7, -4, -10, -14, -24, -38, -51, -58, -55, -50, -44, -36, -23, -7, 10, 26, 41, 57, 76, 89, 89, 81, 70, 59, 45, 25, 0, -24, -41, -56, -67, -75, -80, -76, -63, -45, -26, -9, 6, 20, 32, 44, 52, 54, 53, 47, 35, 18, 3, -6, -11, -14, -16, -19, -19, -12, -4, 5, 5, 0, -8, -12, -15, -21, -34, -47, -51, -45, -39, -34, -30, -23, -12, 4, 17, 31, 45, 60, 72, 78, 75, 69, 62, 53, 40, 18, -5, -24, -38, -50, -62, -73, -78, -74, -59, -41, -28, -17, -4, 14, 33, 47, 55, 58, 55, 48, 39, 29, 16, 4, -5, -11, -18, -21, -20, -15, -8, -7, -9, -13, -15, -16, -17, -23, -33, -43, -44, -41, -34, -28, -23, -16, -8, 5, 21, 36, 50, 62, 73, 76, 73, 68, 59, 48, 30, 9, -16, -35, -48, -59, -70, -77, -79, -72, -54, -38, -24, -8, 8, 29, 45, 56, 61, 62, 56, 51, 39, 27, 16, 4, -8, -16, -22, -23, -25, -19, -16, -17, -19, -20, -21, -18, -19, -25, -32, -38, -34, -24, -19, -15, -12, -7, 3, 15, 28, 39, 48, 56, 63, 63, 63, 57, 47, 32, 14, -5, -22, -36, -46, -58, -68, -73, -71, -61, -47, -35, -23, -9, 10, 29, 43, 52, 56, 56, 56, 52, 45, 33, 19, 6, -5, -15, -22, -25, -26, -26, -29, -29, -26, -24, -20, -19, -23, -27, -30, -27, -21, -18, -14, -10, -7, 0, 8, 18, 30, 40, 47, 52, 54, 54, 55, 49, 39, 22, 7, -9, -24, -37, -50, -58, -65, -71, -67, -59, -50, -39, -23, -6, 15, 32, 43, 51, 57, 61, 64, 61, 52, 37, 21, 4, -11, -20, -26, -30, -35, -37, -39, -35, -29, -22, -17, -20, -22, -20, -18, -17, -16, -13, -8, -3, 2, 7, 10, 17, 27, 35, 42, 43, 44, 45, 44, 38, 28, 16, 3, -10, -22, -33, -46, -57, -64, -64, -59, -53, -46, -34, -17, 3, 21, 32, 41, 48, 55, 60, 60, 54, 44, 31, 18, 3, -10, -19, -27, -30, -32, -34, -35, -30, -23, -17, -17, -20, -20, -20, -17, -15, -13, -11, -8, 1, 8, 12, 17, 23, 30, 39, 39, 37, 36, 35, 34, 27, 14, 0, -10, -15, -23, -34, -46, -56, -60, -56, -49, -39, -32, -23, -8, 8, 23, 32, 38, 44, 54, 58, 57, 48, 37, 29, 17, 4, -11, -21, -28, -29, -31, -34, -35, -27, -20, -15, -16, -16, -17, -13, -10, -10, -11, -10, -4, 5, 11, 13, 15, 21, 29, 33, 32, 28, 25, 25, 23, 16, 5, -6, -10, -16, -21, -30, -42, -48, -48, -43, -34, -29, -21, -13, -3, 11, 22, 27, 34, 39, 48, 53, 48, 42, 32, 23, 16, 4, -7, -18, -24, -24, -26, -28, -24, -19, -14, -13, -16, -18, -18, -16, -14, -15, -16, -15, -7, 3, 11, 14, 21, 27, 33, 36, 33, 30, 25, 22, 17, 9, -4, -15, -21, -24, -31, -39, -44, -44, -39, -30, -23, -16, -8, 4, 14, 21, 23, 25, 29, 37, 43, 42, 36, 31, 25, 18, 11, 4, -7, -11, -13, -16, -21, -22, -18, -14, -13, -16, -19, -21, -21, -19, -19, -20, -18, -11, -2, 8, 14, 18, 23, 30, 34, 35, 31, 27, 21, 13, 2, -11, -17, -23, -28, -36, -39, -40, -37, -31, -23, -14, -9, 0, 7, 13, 15, 15, 16, 22, 27, 30, 28, 29, 32, 29, 23, 16, 9, 4, 1, -2, -7, -14, -19, -14, -10, -10, -14, -18, -22, -24, -23, -26, -28, -27, -18, -8, -3, 2, 9, 22, 33, 40, 40, 36, 30, 25, 20, 8, -8, -22, -29, -32, -39, -48, -50, -42, -30, -19, -13, -8, 2, 11, 22, 25, 21, 17, 15, 20, 23, 21, 20, 20, 19, 19, 16, 11, 9, 7, 7, 3, 0, -3, -5, -5, -5, -7, -12, -22, -28, -32, -35, -35, -36, -30, -21, -12, -4, 3, 16, 29, 39, 46, 45, 40, 34, 26, 13, -2, -17, -28, -37, -48, -57, -60, -52, -36, -19, -12, -8, 2, 16, 28, 33, 28, 23, 21, 22, 21, 19, 18, 16, 14, 12, 8, 6, 5, 5, 7, 5, 4, 5, 7, 9, 7, 3, -5, -13, -22, -28, -35, -44, -49, -48, -38, -26, -14, -7, 4, 20, 38, 49, 54, 53, 49, 40, 26, 8, -11, -24, -33, -46, -61, -70, -67, -52, -31, -14, -5, 4, 14, 27, 36, 36, 33, 29, 26, 25, 21, 14, 10, 7, 8, 6, 5, 5, 6, 8, 9, 10, 14, 18, 17, 13, 5, -4, -12, -20, -28, -37, -49, -56, -56, -48, -36, -25, -15, -2, 16, 36, 51, 55, 57, 55, 48, 37, 20, 1, -17, -30, -43, -60, -73, -76, -63, -43, -24, -14, -6, 7, 23, 39, 44, 38, 34, 31, 32, 30, 24, 16, 8, 5, 6, 6, 5, 5, 6, 10, 10, 13, 16, 19, 19, 14, 5, -7, -18, -25, -34, -45, -55, -61, -59, -51, -39, -25, -12, 5, 27, 48, 58, 60, 61, 58, 49, 32, 14, -4, -20, -36, -54, -69, -79, -75, -57, -35, -21, -15, -4, 12, 28, 39, 42, 41, 38, 38, 38, 33, 23, 13, 8, 9, 11, 9, 5, 3, 6, 10, 13, 14, 15, 17, 16, 9, -6, -16, -21, -27, -40, -56, -65, -67, -57, -45, -33, -23, -5, 21, 44, 60, 66, 67, 65, 61, 47, 25, 2, -16, -34, -53, -72, -83, -82, -70, -51, -33, -20, -8, 8, 25, 39, 46, 43, 43, 43, 43, 38, 27, 17, 9, 8, 10, 11, 9, 5, 5, 8, 13, 14, 18, 20, 18, 12, -2, -13, -19, -25, -34, -48, -62, -69, -67, -58, -46, -32, -14, 9, 30, 48, 60, 69, 72, 69, 57, 36, 13, -6, -27, -47, -66, -79, -83, -77, -64, -46, -29, -13, 4, 17, 30, 39, 41, 46, 48, 45, 40, 31, 20, 12, 10, 13, 14, 12, 11, 10, 10, 15, 17, 20, 20, 17, 12, 0, -14, -24, -30, -37, -47, -60, -69, -68, -62, -51, -36, -18, 5, 25, 45, 58, 65, 68, 67, 59, 42, 20, -2, -22, -42, -61, -75, -81, -77, -66, -51, -35, -20, -4, 14, 28, 37, 38, 38, 42, 47, 43, 35, 24, 17, 14, 14, 17, 20, 20, 17, 13, 14, 17, 18, 18, 17, 11, -2, -15, -24, -31, -38, -46, -52, -58, -62, -61, -52, -38, -22, -4, 16, 35, 48, 55, 60, 62, 57, 46, 26, 6, -17, -35, -53, -68, -76, -75, -66, -51, -38, -23, -7, 10, 25, 35, 38, 37, 39, 40, 39, 30, 21, 16, 15, 15, 16, 20, 24, 26, 27, 27, 26, 24, 21, 19, 11, -3, -16, -29, -40, -44, -50, -54, -57, -58, -55, -48, -36, -21, -5, 13, 29, 41, 48, 52, 53, 50, 41, 26, 7, -14, -33, -49, -62, -70, -69, -61, -48, -36, -21, -5, 16, 30, 35, 35, 35, 32, 31, 29, 24, 17, 13, 13, 14, 15, 18, 26, 34, 39, 37, 32, 29, 26, 22, 13, 1, -15, -29, -40, -46, -51, -54, -55, -52, -46, -40, -32, -22, -10, 5, 19, 28, 33, 35, 37, 38, 33, 21, 8, -7, -20, -35, -50, -57, -57, -49, -37, -28, -21, -8, 10, 25, 32, 32, 31, 27, 24, 22, 20, 15, 13, 13, 15, 15, 19, 26, 36, 42, 43, 40, 33, 27, 22, 16, 3, -13, -26, -37, -44, -50, -55, -54, -48, -42, -32, -24, -18, -10, -3, 8, 20, 30, 31, 26, 22, 20, 15, 7, -7, -20, -32, -43, -52, -52, -46, -36, -25, -16, -5, 9, 24, 38, 42, 39, 30, 23, 19, 15, 11, 8, 6, 6, 6, 9, 18, 30, 42, 47, 45, 43, 38, 31, 22, 8, -9, -21, -33, -45, -55, -59, -56, -47, -37, -29, -21, -13, -5, 2, 8, 13, 19, 22, 20, 15, 9, 5, -3, -9, -20, -30, -39, -46, -45, -40, -31, -24, -16, -6, 7, 21, 35, 39, 36, 31, 24, 22, 15, 10, 8, 5, 6, 3, 4, 12, 25, 40, 48, 50, 48, 43, 37, 30, 17, -2, -18, -33, -45, -57, -64, -62, -53, -40, -31, -23, -13, -3, 4, 11, 16, 19, 18, 17, 13, 7, -3, -10, -16, -22, -31, -40, -45, -45, -41, -32, -24, -15, -5, 8, 24, 39, 47, 44, 38, 32, 26, 20, 12, 3, -4, -4, -5, -4, 1, 11, 29, 41, 49, 51, 49, 45, 38, 27, 9, -11, -27, -38, -52, -60, -64, -58, -45, -32, -21, -14, -5, 3, 10, 13, 13, 14, 14, 12, 4, -6, -12, -17, -21, -25, -31, -35, -40, -39, -33, -27, -19, -12, 1, 16, 29, 38, 42, 40, 36, 33, 30, 22, 11, 1, -2, -2, -3, -2, 2, 16, 32, 44, 48, 46, 44, 39, 31, 19, 1, -21, -36, -48, -58, -62, -59, -49, -38, -28, -20, -12, -2, 9, 16, 16, 15, 16, 14, 9, 2, -7, -14, -19, -25, -31, -36, -38, -38, -36, -34, -28, -20, -7, 8, 22, 33, 41, 46, 46, 42, 39, 33, 25, 14, 4, -4, -8, -8, -4, 4, 16, 30, 38, 42, 46, 45, 38, 25, 10, -7, -24, -39, -51, -58, -59, -53, -43, -34, -28, -21, -9, 5, 15, 17, 16, 15, 16, 15, 10, 2, -10, -17, -21, -26, -33, -38, -40, -37, -34, -33, -28, -17, 0, 15, 29, 40, 48, 50, 48, 44, 40, 34, 26, 15, 3, -6, -11, -11, -4, 7, 18, 24, 30, 36, 38, 35, 31, 24, 13, -7, -25, -40, -50, -53, -51, -47, -41, -38, -33, -25, -10, 4, 14, 19, 21, 22, 19, 19, 17, 7, -5, -15, -23, -31, -39, -46, -49, -49, -46, -41, -33, -19, 0, 21, 39, 53, 61, 64, 63, 56, 50, 42, 31, 15, -2, -13, -19, -19, -11, 0, 10, 15, 19, 27, 33, 37, 35, 25, 9, -13, -28, -38, -44, -46, -50, -53, -51, -46, -38, -23, -7, 10, 20, 21, 24, 25, 28, 28, 19, 8, -7, -18, -28, -36, -43, -52, -56, -57, -51, -44, -31, -13, 7, 29, 46, 60, 66, 71, 68, 61, 54, 45, 32, 13, -5, -17, -22, -20, -15, -8, -2, 8, 14, 24, 31, 35, 32, 21, 4, -13, -24, -34, -42, -49, -55, -58, -54, -48, -38, -23, -4, 14, 26, 32, 31, 32, 36, 34, 23, 7, -12, -25, -35, -47, -61, -68, -68, -61, -53, -42, -26, -7, 22, 45, 61, 71, 75, 78, 74, 66, 56, 42, 24, 7, -13, -24, -29, -25, -18, -11, -7, 2, 14, 27, 36, 38, 32, 19, 1, -14, -22, -33, -44, -56, -64, -65, -60, -47, -32, -16, 3, 18, 31, 37, 37, 38, 41, 35, 20, 0, -18, -31, -43, -56, -64, -69, -68, -60, -50, -36, -15, 6, 31, 50, 62, 71, 77, 78, 74, 66, 54, 38, 20, 2, -15, -23, -26, -24, -22, -17, -7, 8, 20, 29, 35, 33, 25, 13, -2, -14, -29, -42, -57, -67, -72, -67, -57, -42, -24, -5, 13, 31, 43, 46, 47, 48, 43, 32, 14, -5, -22, -40, -55, -63, -68, -69, -66, -57, -44, -25, -5, 18, 37, 55, 66, 75, 78, 75, 70, 62, 47, 28, 9, -7, -19, -27, -30, -27, -21, -11, 5, 18, 28, 34, 36, 32, 24, 12, -4, -20, -38, -55, -68, -75, -71, -65, -53, -35, -14, 6, 24, 39, 47, 50, 48, 44, 36, 22, 5, -16, -34, -47, -56, -60, -60, -59, -54, -45, -28, -9, 9, 25, 41, 53, 63, 67, 66, 65, 62, 54, 40, 22, 6, -8, -16, -22, -23, -20, -11, 1, 13, 22, 27, 29, 26, 24, 15, 2, -15, -33, -49, -64, -74, -74, -67, -55, -39, -20, -2, 16, 32, 45, 50, 49, 43, 35, 26, 11, -9, -25, -35, -44, -49, -52, -54, -50, -39, -26, -12, 1, 14, 27, 39, 48, 53, 55, 57, 56, 48, 36, 25, 15, 6, -5, -12, -17, -14, -8, 3, 14, 21, 26, 23, 21, 21, 14, 3, -11, -26, -44, -61, -72, -72, -68, -56, -42, -25, -11, 7, 24, 37, 44, 44, 40, 33, 25, 13, 0, -12, -24, -32, -39, -41, -39, -36, -30, -24, -18, -10, 1, 11, 21, 29, 36, 41, 47, 51, 51, 42, 35, 27, 19, 10, 1, -6, -10, -9, -2, 6, 11, 13, 13, 15, 14, 10, 4, -9, -19, -31, -45, -58, -67, -68, -56, -43, -31, -20, -9, 7, 21, 31, 35, 35, 33, 27, 18, 7, -3, -9, -13, -20, -27, -32, -33, -29, -23, -19, -16, -12, -4, 6, 15, 23, 30, 39, 47, 49, 42, 35, 31, 27, 22, 14, 2, -8, -9, -4, 5, 8, 8, 9, 7, 6, 3, 0, -5, -12, -22, -35, -50, -58, -58, -50, -39, -32, -26, -19, -8, 7, 21, 26, 27, 25, 22, 18, 11, 5, 2, 1, -3, -10, -19, -24, -23, -16, -15, -17, -20, -17, -10, -2, 6, 12, 21, 32, 44, 45, 38, 30, 27, 31, 31, 21, 8, 1, 0, 2, 8, 10, 7, 1, -3, -2, -4, -9, -12, -17, -25, -37, -47, -53, -50, -42, -32, -27, -26, -22, -11, 5, 15, 18, 20, 22, 23, 22, 18, 15, 14, 11, 7, -3, -14, -18, -17, -18, -22, -27, -27, -21, -14, -6, 3, 12, 24, 34, 40, 39, 35, 32, 31, 34, 30, 19, 10, 4, 2, 5, 7, 7, 1, -6, -10, -9, -8, -8, -11, -16, -25, -34, -41, -41, -36, -32, -33, -33, -29, -22, -11, -2, 6, 13, 17, 22, 23, 22, 22, 24, 23, 20, 12, 0, -7, -11, -14, -20, -26, -28, -26, -22, -15, -9, 2, 13, 25, 32, 33, 35, 36, 37, 38, 35, 29, 19, 9, 5, 7, 6, 4, -3, -9, -12, -11, -6, -4, -5, -10, -17, -26, -33, -37, -38, -38, -38, -41, -39, -31, -20, -9, -2, 6, 15, 23, 31, 31, 31, 30, 29, 28, 21, 13, 2, -9, -17, -20, -23, -26, -27, -26, -20, -14, -6, 6, 14, 22, 26, 32, 34, 35, 37, 37, 36, 27, 15, 6, 6, 7, 5, -3, -13, -17, -17, -11, -5, -5, -6, -11, -18, -24, -27, -30, -35, -40, -44, -44, -39, -28, -16, -6, 1, 9, 20, 31, 34, 36, 37, 36, 33, 23, 14, 5, -3, -10, -17, -23, -30, -34, -31, -22, -14, -8, 0, 7, 15, 20, 26, 30, 35, 40, 40, 34, 27, 18, 14, 9, 8, 5, -2, -11, -15, -13, -8, -4, 0, 1, -6, -12, -18, -23, -29, -38, -45, -52, -53, -47, -37, -28, -16, -5, 6, 17, 28, 37, 42, 43, 40, 37, 31, 19, 8, 1, -7, -14, -22, -27, -33, -34, -28, -18, -8, 0, 5, 10, 14, 19, 25, 33, 38, 39, 35, 27, 18, 13, 9, 8, 4, -3, -8, -12, -13, -10, -4, 4, 4, -2, -7, -14, -21, -28, -36, -45, -53, -54, -50, -44, -34, -20, -5, 7, 18, 28, 37, 39, 42, 40, 35, 28, 17, 7, 0, -7, -12, -18, -23, -28, -28, -23, -17, -8, 2, 8, 9, 10, 12, 17, 25, 32, 33, 28, 20, 13, 10, 10, 8, 6, 5, 1, -5, -6, -3, 3, 10, 10, 5, -6, -15, -21, -28, -38, -49, -59, -62, -59, -51, -39, -25, -8, 7, 17, 28, 37, 42, 44, 43, 38, 30, 17, 7, 0, -4, -10, -16, -24, -26, -27, -21, -14, -9, -2, 5, 11, 14, 12, 13, 19, 26, 29, 26, 19, 13, 8, 8, 9, 5, 2, 2, 4, 3, 1, 1, 5, 8, 7, 0, -10, -18, -25, -32, -42, -52, -56, -53, -48, -38, -29, -14, 1, 14, 23, 30, 33, 33, 35, 33, 26, 17, 9, 2, 1, 0, -5, -12, -19, -22, -21, -13, -8, -4, 5, 10, 12, 10, 10, 14, 21, 25, 24, 15, 5, 3, 5, 7, 5, 2, 5, 10, 12, 10, 9, 11, 13, 10, 2, -8, -18, -25, -32, -40, -50, -55, -53, -45, -35, -27, -17, -4, 11, 20, 28, 30, 28, 29, 30, 28, 19, 10, 6, 6, 5, 0, -10, -18, -20, -18, -14, -11, -10, -4, 6, 13, 13, 11, 13, 20, 25, 24, 15, 7, 3, 4, 5, 4, 0, 3, 9, 14, 15, 11, 9, 8, 8, 6, -5, -16, -24, -29, -35, -43, -48, -47, -42, -31, -23, -17, -7, 5, 17, 24, 26, 22, 19, 19, 20, 17, 11, 5, 2, 2, 0, -4, -10, -14, -14, -10, -8, -6, 1, 10, 19, 23, 22, 17, 16, 19, 18, 11, 1, -8, -11, -10, -7, -4, 1, 7, 15, 22, 22, 18, 17, 16, 12, 4, -8, -21, -29, -34, -39, -46, -49, -46, -37, -28, -19, -9, -2, 8, 19, 22, 20, 18, 18, 19, 19, 12, 6, 3, 2, 0, -5, -10, -16, -18, -14, -9, -8, -3, 6, 17, 25, 27, 26, 24, 25, 22, 15, 3, -8, -13, -13, -12, -11, -6, 0, 9, 16, 19, 19, 16, 13, 10, 6, -5, -14, -22, -26, -32, -37, -41, -39, -32, -23, -17, -14, -10, -3, 9, 17, 18, 10, 7, 10, 16, 18, 12, 5, 1, 1, -4, -13, -18, -18, -15, -12, -11, -10, 1, 15, 29, 37, 35, 31, 30, 30, 24, 11, -8, -18, -18, -15, -17, -20, -17, -6, 8, 15, 18, 16, 15, 11, 12, 8, 0, -10, -16, -20, -28, -35, -38, -33, -27, -23, -21, -19, -13, 0, 11, 14, 12, 9, 11, 18, 21, 19, 10, 2, -3, -5, -12, -21, -28, -26, -20, -15, -12, -6, 9, 25, 38, 43, 42, 40, 38, 34, 23, 6, -12, -18, -18, -18, -23, -25, -22, -13, 0, 7, 9, 8, 8, 11, 12, 9, 6, 2, -5, -14, -21, -24, -24, -22, -22, -21, -22, -20, -12, -3, 4, 5, 5, 6, 11, 15, 16, 10, 4, -2, -7, -11, -20, -25, -27, -21, -13, -11, -5, 6, 22, 37, 46, 50, 49, 44, 39, 31, 16, -3, -15, -21, -24, -27, -32, -33, -28, -17, -5, 5, 7, 7, 10, 15, 16, 15, 10, 4, -4, -11, -18, -22, -22, -20, -22, -21, -21, -17, -10, 1, 6, 9, 10, 15, 19, 18, 12, 5, 0, -9, -15, -23, -31, -36, -32, -24, -17, -11, -4, 12, 31, 47, 53, 58, 60, 56, 49, 35, 15, -4, -16, -21, -25, -32, -42, -45, -35, -23, -14, -8, 0, 6, 13, 20, 21, 19, 15, 9, 1, -6, -11, -13, -16, -18, -20, -23, -20, -14, -8, 0, 2, 5, 11, 18, 18, 14, 6, -2, -10, -18, -27, -34, -41, -40, -31, -20, -12, -7, 4, 23, 47, 64, 71, 71, 63, 56, 46, 30, 12, -7, -22, -35, -42, -49, -52, -48, -34, -22, -14, -7, 3, 15, 24, 27, 27, 24, 15, 6, -4, -8, -11, -13, -13, -15, -16, -14, -12, -7, -2, 3, 10, 12, 14, 15, 7, 0, -7, -16, -25, -32, -40, -44, -44, -36, -24, -11, 0, 6, 16, 36, 58, 72, 76, 71, 62, 51, 38, 24, 5, -13, -30, -42, -50, -52, -53, -46, -33, -21, -15, -6, 7, 20, 25, 25, 21, 18, 14, 7, 2, -5, -9, -9, -7, -8, -9, -10, -7, -3, 1, 6, 7, 8, 9, 6, -2, -13, -23, -30, -35, -41, -45, -44, -38, -26, -15, -3, 11, 19, 33, 52, 69, 75, 72, 65, 54, 42, 29, 13, -6, -25, -41, -49, -54, -55, -48, -38, -26, -18, -8, 1, 13, 24, 29, 26, 19, 11, 5, 2, -2, -6, -6, -6, -5, -7, -5, 1, 5, 9, 11, 8, 8, 7, 4, -6, -17, -28, -35, -42, -47, -48, -45, -39, -29, -16, -5, 7, 18, 32, 45, 57, 64, 67, 62, 54, 45, 35, 22, 5, -13, -28, -40, -47, -49, -46, -42, -32, -21, -11, -4, 6, 15, 21, 21, 16, 12, 6, 1, -3, -5, -3, 3, 8, 9, 8, 7, 7, 11, 12, 11, 6, -2, -9, -13, -20, -29, -40, -47, -47, -45, -42, -37, -29, -16, -5, 7, 17, 27, 38, 48, 56, 59, 53, 44, 40, 37, 30, 17, -2, -16, -25, -32, -35, -36, -35, -31, -23, -16, -10, -3, 4, 10, 11, 8, 1, 0, 0, 0, 0, 1, 6, 14, 20, 21, 19, 15, 14, 13, 11, 7, 0, -13, -21, -28, -37, -46, -51, -48, -43, -37, -32, -28, -21, -9, 4, 17, 27, 32, 40, 45, 50, 51, 46, 40, 38, 35, 27, 12, -3, -13, -23, -27, -29, -30, -29, -28, -23, -15, -10, -5, 2, 5, 5, 1, -2, -2, 1, 4, 4, 8, 14, 19, 25, 26, 21, 15, 13, 12, 12, 5, -9, -21, -30, -37, -43, -50, -51, -47, -42, -38, -34, -27, -17, -5, 10, 22, 30, 38, 44, 49, 50, 46, 40, 37, 38, 33, 19, 4, -8, -14, -18, -22, -24, -24, -22, -18, -16, -14, -10, -6, 1, 1, -6, -8, -9, -6, 0, 2, 8, 14, 21, 28, 31, 27, 24, 21, 20, 16, 9, -3, -16, -26, -33, -42, -50, -55, -56, -50, -43, -39, -38, -29, -13, 6, 18, 27, 33, 42, 51, 54, 53, 48, 41, 39, 38, 29, 12, -5, -15, -19, -20, -23, -24, -22, -18, -17, -13, -12, -10, -4, -3, -4, -7, -8, -9, -9, -7, 2, 9, 14, 21, 26, 27, 27, 22, 20, 19, 17, 12, 1, -14, -25, -35, -41, -45, -50, -53, -54, -51, -47, -41, -31, -18, -3, 12, 24, 35, 47, 55, 58, 57, 55, 49, 46, 40, 26, 11, -5, -17, -22, -23, -23, -22, -21, -21, -18, -15, -9, -5, -3, -4, -6, -7, -9, -12, -12, -8, 1, 7, 13, 14, 19, 23, 27, 26, 25, 25, 20, 13, 4, -9, -22, -36, -42, -48, -55, -61, -62, -59, -54, -43, -32, -18, 0, 18, 35, 49, 57, 60, 62, 63, 61, 57, 48, 33, 15, -2, -15, -24, -28, -27, -22, -23, -24, -21, -13, -4, 3, 3, 1, -2, -4, -4, -9, -15, -16, -13, -9, -5, 2, 7, 11, 19, 24, 28, 31, 29, 28, 24, 12, -4, -21, -33, -38, -48, -61, -72, -76, -71, -61, -47, -34, -20, 2, 26, 45, 58, 65, 69, 74, 75, 68, 55, 41, 28, 13, -7, -22, -32, -32, -29, -24, -23, -22, -19, -7, 6, 7, 2, -2, -3, 0, -3, -10, -20, -24, -19, -12, -5, 1, 5, 14, 23, 30, 33, 37, 39, 36, 24, 8, -10, -25, -33, -43, -55, -71, -82, -82, -71, -57, -44, -29, -11, 13, 34, 52, 64, 70, 73, 77, 76, 65, 50, 35, 20, 4, -13, -26, -31, -32, -27, -26, -25, -21, -10, 2, 8, 5, 3, 0, 1, 2, -3, -12, -22, -24, -21, -16, -9, -3, 6, 14, 22, 28, 34, 41, 42, 35, 23, 6, -10, -21, -32, -45, -61, -76, -85, -82, -70, -54, -43, -29, -7, 18, 40, 55, 64, 71, 77, 81, 76, 62, 48, 32, 19, 6, -10, -23, -30, -29, -28, -30, -27, -20, -10, -2, 3, 1, 0, 3, 6, 4, -9, -18, -24, -22, -18, -14, -8, 0, 8, 16, 24, 32, 38, 42, 42, 31, 15, -2, -14, -25, -38, -52, -67, -81, -85, -76, -63, -49, -37, -19, 3, 26, 43, 57, 67, 75, 82, 79, 70, 56, 41, 28, 15, 1, -12, -22, -27, -27, -28, -26, -21, -12, -3, 3, -2, -2, 1, 3, 1, -12, -22, -28, -29, -27, -23, -18, -11, 3, 16, 25, 34, 44, 51, 52, 43, 27, 12, -2, -17, -34, -51, -71, -82, -86, -83, -75, -61, -45, -27, -7, 16, 37, 53, 63, 72, 78, 77, 68, 60, 45, 33, 20, 10, -2, -9, -15, -18, -22, -23, -19, -15, -8, -5, -7, -8, -7, -4, -3, -10, -22, -29, -29, -24, -21, -18, -14, -3, 12, 23, 27, 35, 44, 49, 47, 34, 18, 1, -11, -23, -40, -57, -73, -81, -80, -74, -64, -50, -36, -19, 2, 22, 38, 49, 61, 69, 74, 69, 60, 50, 40, 29, 20, 10, 2, -5, -9, -12, -16, -18, -14, -9, -6, -10, -13, -12, -10, -11, -15, -23, -30, -31, -27, -25, -23, -19, -8, 8, 20, 28, 36, 45, 49, 49, 41, 29, 15, -2, -15, -31, -49, -65, -76, -79, -77, -67, -55, -43, -30, -13, 7, 25, 40, 51, 60, 66, 66, 62, 54, 45, 37, 29, 22, 14, 7, 3, -3, -7, -10, -12, -10, -8, -12, -18, -19, -16, -13, -15, -23, -31, -33, -29, -26, -25, -23, -15, 1, 14, 23, 31, 40, 50, 52, 46, 36, 21, 7, -8, -24, -41, -58, -70, -75, -74, -67, -57, -43, -30, -18, -3, 13, 26, 39, 48, 56, 60, 58, 51, 45, 42, 36, 29, 25, 20, 14, 9, 6, 3, 0, -5, -6, -12, -17, -22, -21, -20, -24, -33, -37, -38, -35, -30, -28, -24, -17, -3, 12, 24, 33, 43, 50, 52, 49, 40, 28, 13, -3, -18, -34, -51, -63, -71, -72, -67, -59, -49, -37, -24, -10, 3, 16, 27, 37, 46, 50, 53, 51, 49, 46, 43, 37, 32, 29, 25, 21, 17, 10, 4, -3, -8, -10, -11, -18, -25, -29, -31, -34, -37, -40, -40, -37, -31, -25, -20, -13, 0, 17, 31, 41, 48, 50, 49, 46, 36, 22, 8, -5, -20, -36, -49, -61, -67, -67, -61, -51, -44, -36, -23, -9, 4, 13, 20, 30, 38, 46, 48, 47, 44, 44, 44, 46, 42, 35, 31, 28, 24, 15, 5, -3, -6, -10, -18, -28, -35, -39, -41, -41, -43, -45, -42, -36, -29, -23, -15, 1, 15, 28, 40, 47, 51, 51, 46, 37, 27, 14, 2, -14, -29, -42, -49, -54, -62, -63, -57, -49, -41, -31, -21, -12, -3, 6, 17, 25, 32, 40, 45, 49, 50, 48, 49, 49, 48, 44, 39, 34, 26, 13, 4, -4, -11, -17, -23, -32, -41, -48, -48, -49, -48, -44, -39, -36, -31, -21, -5, 13, 24, 35, 44, 51, 52, 47, 39, 30, 21, 8, -6, -18, -34, -44, -50, -54, -59, -58, -53, -46, -38, -28, -18, -10, -4, 6, 16, 24, 30, 37, 42, 48, 49, 47, 48, 51, 51, 49, 45, 35, 27, 17, 9, 0, -12, -23, -32, -41, -48, -53, -55, -54, -53, -49, -43, -38, -27, -13, 5, 20, 33, 44, 52, 58, 57, 50, 40, 29, 16, 5, -11, -29, -43, -53, -56, -62, -65, -63, -54, -42, -33, -24, -16, -8, 3, 16, 23, 29, 33, 38, 44, 46, 45, 43, 45, 49, 52, 48, 42, 37, 28, 19, 10, 0, -13, -25, -36, -42, -47, -56, -58, -56, -53, -49, -48, -40, -26, -6, 13, 27, 39, 49, 59, 64, 62, 53, 42, 29, 16, 2, -18, -37, -52, -60, -65, -71, -75, -68, -55, -41, -30, -19, -10, 0, 14, 24, 33, 37, 38, 39, 42, 45, 45, 43, 45, 48, 47, 46, 41, 35, 28, 19, 8, -6, -20, -30, -38, -44, -50, -55, -57, -59, -57, -53, -46, -35, -19, 0, 17, 32, 45, 59, 66, 66, 59, 54, 46, 32, 15, -5, -24, -43, -57, -65, -71, -76, -78, -71, -58, -41, -27, -16, -5, 5, 15, 27, 37, 43, 43, 42, 42, 42, 43, 46, 46, 46, 45, 42, 41, 35, 28, 18, 7, -6, -18, -29, -37, -44, -51, -56, -59, -61, -60, -55, -45, -33, -18, -2, 18, 37, 50, 61, 67, 68, 65, 59, 47, 31, 10, -11, -32, -47, -58, -71, -81, -86, -83, -70, -52, -36, -21, -9, 2, 13, 25, 35, 41, 44, 43, 40, 39, 39, 40, 43, 43, 40, 39, 40, 40, 36, 28, 18, 9, -5, -18, -28, -36, -44, -52, -57, -61, -64, -63, -56, -43, -27, -13, 6, 26, 44, 56, 66, 71, 71, 64, 55, 42, 23, 3, -19, -38, -52, -66, -76, -82, -86, -81, -67, -49, -32, -19, -8, 3, 15, 28, 36, 42, 43, 43, 41, 41, 40, 40, 41, 40, 40, 41, 41, 36, 30, 24, 17, 10, -5, -19, -29, -37, -43, -50, -57, -64, -66, -60, -50, -40, -28, -10, 12, 32, 45, 54, 59, 64, 67, 63, 54, 35, 14, -6, -22, -35, -50, -64, -75, -82, -81, -73, -59, -46, -33, -21, -8, 5, 19, 27, 33, 40, 44, 44, 42, 40, 42, 41, 40, 38, 39, 38, 38, 35, 30, 21, 13, 4, -8, -16, -25, -35, -45, -53, -62, -65, -63, -56, -47, -39, -25, -6, 15, 32, 45, 53, 58, 64, 65, 60, 48, 30, 9, -7, -19, -31, -47, -60, -72, -79, -79, -73, -61, -50, -37, -24, -10, 3, 12, 22, 33, 43, 47, 46, 44, 43, 45, 46, 45, 45, 43, 41, 38, 34, 26, 16, 7, -2, -10, -19, -29, -39, -50, -59, -64, -62, -58, -51, -44, -34, -22, -2, 16, 30, 41, 52, 56, 57, 58, 54, 42, 29, 13, 2, -12, -27, -42, -56, -67, -71, -73, -70, -63, -55, -42, -26, -10, 2, 11, 20, 33, 41, 46, 45, 43, 49, 53, 52, 48, 44, 43, 42, 38, 33, 22, 12, 4, -5, -13, -23, -34, -43, -50, -57, -61, -60, -55, -49, -40, -29, -14, -2, 12, 25, 35, 44, 51, 56, 56, 49, 39, 30, 20, 10, -2, -17, -32, -48, -60, -67, -74, -77, -74, -66, -50, -36, -21, -9, 0, 14, 30, 43, 51, 53, 57, 62, 64, 62, 58, 53, 48, 42, 36, 25, 12, 4, -4, -12, -21, -31, -38, -43, -45, -47, -49, -47, -44, -40, -34, -28, -22, -11, 1, 11, 21, 28, 39, 49, 53, 52, 49, 44, 38, 29, 16, -4, -24, -41, -57, -74, -86, -90, -86, -73, -59, -44, -30, -16, 1, 21, 40, 54, 61, 66, 67, 71, 72, 65, 57, 49, 41, 33, 24, 12, 1, -8, -12, -15, -22, -31, -37, -35, -31, -33, -36, -39, -40, -38, -34, -32, -29, -24, -14, -2, 11, 24, 36, 48, 56, 61, 63, 59, 54, 44, 27, 6, -19, -46, -68, -84, -94, -99, -98, -90, -72, -51, -30, -15, 1, 22, 46, 64, 76, 78, 80, 81, 78, 72, 60, 45, 34, 24, 13, 0, -13, -18, -18, -18, -22, -28, -29, -24, -19, -19, -26, -33, -38, -40, -40, -41, -42, -41, -32, -15, 6, 22, 37, 50, 62, 74, 79, 76, 65, 50, 30, 6, -24, -54, -78, -94, -106, -110, -103, -89, -69, -49, -29, -10, 11, 36, 57, 73, 78, 80, 82, 83, 77, 66, 51, 37, 24, 14, 5, -5, -12, -17, -17, -17, -18, -19, -17, -13, -13, -19, -28, -37, -44, -44, -48, -53, -59, -54, -35, -12, 11, 29, 46, 61, 78, 88, 90, 84, 68, 49, 24, -6, -39, -71, -92, -104, -115, -116, -108, -89, -66, -43, -21, 1, 24, 49, 68, 78, 82, 81, 81, 79, 71, 56, 37, 24, 15, 6, -4, -9, -11, -9, -6, -6, -10, -11, -6, -4, -8, -20, -33, -44, -55, -61, -65, -70, -68, -55, -31, -6, 15, 38, 61, 82, 97, 101, 94, 80, 61, 37, 9, -25, -60, -88, -107, -119, -123, -116, -99, -77, -53, -30, -5, 20, 47, 68, 80, 82, 82, 80, 77, 70, 57, 40, 23, 10, 3, -2, -3, -4, -3, 2, 5, 7, 5, 5, 4, -4, -17, -32, -45, -60, -69, -74, -79, -80, -70, -47, -20, 9, 32, 55, 76, 94, 104, 103, 91, 71, 46, 16, -16, -48, -75, -97, -115, -121, -117, -101, -80, -57, -32, -8, 15, 39, 58, 68, 73, 73, 73, 69, 61, 50, 39, 26, 15, 7, 4, 7, 12, 18, 19, 20, 18, 17, 15, 10, -4, -20, -41, -57, -68, -77, -85, -91, -90, -76, -53, -25, 2, 28, 55, 79, 97, 106, 104, 94, 77, 52, 22, -9, -39, -67, -92, -111, -119, -115, -99, -79, -55, -33, -11, 15, 37, 55, 67, 71, 68, 61, 51, 44, 40, 35, 24, 10, 3, 4, 13, 25, 36, 42, 41, 34, 29, 20, 12, -2, -21, -43, -66, -84, -94, -96, -96, -93, -81, -55, -26, 4, 30, 56, 80, 98, 107, 106, 95, 77, 53, 24, -8, -38, -64, -85, -101, -109, -109, -100, -80, -55, -31, -8, 13, 31, 46, 56, 61, 59, 52, 43, 36, 30, 25, 16, 8, 7, 11, 23, 37, 48, 56, 59, 56, 48, 33, 17, -5, -29, -54, -79, -96, -106, -109, -105, -96, -82, -57, -25, 8, 38, 61, 79, 94, 103, 102, 92, 73, 46, 19, -10, -36, -62, -81, -95, -101, -100, -90, -71, -47, -25, -3, 18, 31, 41, 49, 53, 50, 42, 32, 21, 13, 9, 7, 8, 8, 12, 30, 49, 63, 71, 76, 75, 67, 48, 25, -3, -30, -59, -87, -107, -120, -124, -117, -105, -89, -63, -31, 5, 40, 63, 81, 92, 100, 100, 88, 69, 46, 20, -6, -31, -55, -73, -87, -91, -88, -80, -64, -45, -22, 1, 16, 27, 34, 39, 45, 41, 31, 20, 9, 4, 3, 1, 3, 6, 15, 32, 53, 71, 81, 85, 86, 78, 61, 35, 3, -29, -63, -93, -113, -124, -128, -124, -110, -89, -64, -32, 5, 38, 62, 80, 91, 98, 93, 80, 63, 42, 19, -5, -29, -51, -68, -78, -81, -79, -72, -58, -40, -19, 0, 13, 21, 29, 35, 35, 29, 21, 14, 8, 2, -2, -3, 1, 10, 20, 36, 56, 73, 84, 89, 89, 81, 65, 41, 6, -32, -63, -90, -110, -124, -127, -123, -110, -89, -61, -30, 2, 33, 56, 71, 81, 86, 85, 74, 58, 38, 17, -5, -21, -38, -52, -62, -69, -69, -64, -50, -34, -18, -5, 5, 13, 23, 28, 27, 22, 15, 10, 6, 1, 0, -2, 2, 9, 23, 41, 56, 72, 84, 88, 89, 81, 66, 45, 15, -20, -55, -84, -106, -119, -121, -116, -105, -89, -67, -38, -7, 21, 44, 58, 69, 75, 74, 64, 50, 36, 22, 8, -10, -26, -39, -47, -54, -56, -53, -47, -36, -25, -11, -2, 5, 14, 23, 24, 20, 12, 7, 6, 6, 6, 4, 5, 10, 22, 39, 57, 72, 80, 82, 80, 73, 62, 45, 18, -13, -48, -78, -96, -105, -105, -104, -97, -81, -64, -40, -15, 10, 28, 40, 49, 54, 53, 49, 42, 31, 22, 13, 2, -9, -17, -22, -30, -38, -40, -37, -33, -28, -22, -16, -10, -5, 5, 11, 11, 6, 3, 5, 11, 16, 16, 18, 22, 29, 40, 54, 68, 75, 74, 72, 63, 49, 35, 15, -10, -37, -63, -83, -94, -95, -89, -82, -73, -63, -46, -24, -2, 16, 25, 31, 35, 39, 41, 37, 30, 22, 15, 11, 4, -3, -11, -18, -25, -31, -35, -33, -28, -22, -18, -16, -13, -4, 5, 10, 11, 10, 5, 6, 14, 21, 23, 24, 27, 33, 45, 59, 68, 72, 67, 57, 46, 34, 19, 0, -24, -49, -70, -81, -82, -77, -70, -65, -60, -49, -34, -15, 2, 9, 13, 14, 18, 20, 21, 19, 18, 17, 16, 15, 13, 10, 5, -3, -12, -20, -26, -28, -27, -24, -26, -25, -18, -9, 3, 9, 10, 10, 11, 18, 27, 32, 33, 33, 35, 42, 51, 58, 59, 55, 46, 36, 25, 16, 3, -15, -33, -50, -61, -65, -64, -59, -57, -56, -52, -42, -29, -14, -5, -2, -3, 1, 8, 12, 13, 13, 16, 16, 18, 19, 19, 14, 4, -3, -10, -19, -24, -24, -22, -20, -24, -23, -16, -2, 10, 16, 14, 13, 16, 28, 35, 36, 35, 32, 33, 40, 45, 49, 47, 41, 31, 20, 12, 4, -8, -16, -29, -41, -50, -53, -50, -49, -51, -51, -48, -40, -30, -20, -13, -13, -12, -6, 2, 8, 12, 13, 16, 21, 26, 27, 23, 15, 8, 0, -10, -19, -23, -24, -24, -26, -25, -21, -9, 5, 15, 19, 20, 22, 28, 36, 39, 38, 36, 33, 33, 35, 37, 38, 36, 30, 20, 9, 4, -3, -10, -17, -26, -35, -40, -45, -47, -51, -52, -49, -46, -39, -30, -23, -19, -17, -12, -5, 1, 4, 7, 11, 18, 22, 22, 22, 20, 17, 12, 3, -8, -16, -18, -16, -17, -19, -18, -12, 3, 13, 19, 20, 24, 29, 34, 35, 33, 32, 31, 31, 30, 26, 24, 24, 25, 21, 14, 6, 0, -4, -5, -10, -19, -31, -37, -40, -47, -51, -50, -49, -45, -39, -31, -25, -19, -12, -6, -3, 0, 2, 6, 13, 17, 18, 16, 15, 16, 14, 7, -3, -10, -12, -13, -13, -14, -13, -6, 6, 18, 24, 25, 26, 29, 33, 32, 26, 24, 23, 23, 22, 18, 14, 15, 21, 24, 22, 14, 6, 4, 4, 1, -9, -21, -32, -41, -47, -50, -54, -54, -51, -47, -37, -30, -21, -10, -3, 1, 4, 6, 7, 8, 7, 7, 7, 7, 6, 6, 5, 2, -3, -8, -8, -6, -3, 1, 3, 9, 17, 25, 29, 32, 33, 29, 26, 24, 23, 20, 17, 14, 11, 8, 8, 14, 21, 22, 17, 13, 9, 9, 7, 1, -11, -25, -37, -44, -52, -53, -55, -55, -51, -43, -35, -24, -14, -4, 3, 4, 4, 6, 7, 6, 3, -2, -2, 2, 6, 5, 1, -4, -8, -7, -5, 3, 9, 9, 12, 17, 25, 32, 37, 37, 32, 25, 21, 19, 17, 15, 9, 6, 6, 6, 8, 14, 23, 24, 20, 15, 14, 11, 3, -6, -18, -31, -44, -53, -54, -57, -58, -55, -47, -37, -26, -16, -4, 7, 10, 10, 9, 7, 3, -2, -6, -8, -6, -5, -4, -7, -10, -8, -6, 0, 6, 12, 16, 20, 27, 33, 35, 35, 36, 34, 28, 21, 16, 10, 7, 7, 5, 3, 1, 5, 12, 21, 25, 23, 17, 14, 13, 9, -3, -17, -30, -41, -50, -54, -59, -61, -55, -46, -37, -26, -15, -4, 7, 14, 15, 12, 6, 1, -3, -7, -12, -14, -15, -13, -12, -12, -12, -8, 0, 8, 15, 20, 25, 31, 36, 40, 41, 41, 38, 33, 27, 21, 12, 4, 1, 0, -4, -5, -2, 5, 12, 17, 19, 19, 18, 14, 11, 2, -9, -21, -32, -42, -49, -55, -57, -56, -49, -39, -30, -20, -8, 3, 12, 17, 18, 12, 5, -2, -8, -14, -18, -21, -22, -21, -21, -19, -13, -7, 4, 14, 24, 32, 39, 44, 48, 47, 44, 41, 38, 33, 27, 17, 7, -3, -5, -5, -5, -5, -5, 3, 12, 17, 19, 16, 11, 7, 3, -6, -15, -26, -36, -42, -48, -53, -54, -50, -40, -31, -22, -12, -2, 11, 19, 20, 13, 6, 2, -5, -12, -21, -26, -29, -31, -30, -27, -21, -13, -2, 12, 25, 36, 48, 57, 62, 60, 51, 46, 43, 37, 28, 15, 3, -8, -12, -14, -12, -10, -7, -4, 8, 16, 20, 17, 14, 10, 6, -2, -12, -24, -32, -39, -45, -51, -54, -52, -43, -32, -21, -12, -2, 11, 22, 28, 24, 13, 4, -6, -14, -23, -32, -38, -41, -42, -39, -31, -20, -8, 6, 21, 37, 50, 63, 69, 68, 61, 55, 48, 39, 29, 20, 9, -6, -15, -17, -13, -11, -7, -4, 3, 11, 13, 16, 15, 10, 5, 0, -8, -15, -25, -31, -37, -42, -49, -52, -46, -37, -30, -21, -12, 0, 14, 25, 28, 25, 15, 2, -11, -22, -29, -36, -44, -49, -49, -43, -32, -18, -5, 13, 30, 50, 66, 74, 75, 71, 68, 61, 50, 37, 26, 15, 3, -13, -22, -22, -20, -16, -14, -9, 1, 9, 11, 11, 9, 9, 9, 6, -3, -15, -25, -32, -37, -41, -50, -53, -50, -41, -30, -20, -8, 6, 21, 31, 33, 26, 15, 0, -12, -23, -34, -46, -56, -60, -54, -44, -31, -19, -2, 21, 44, 66, 77, 81, 79, 75, 72, 63, 51, 35, 23, 10, -4, -16, -25, -28, -26, -22, -16, -12, -7, -2, 4, 8, 10, 14, 14, 7, -3, -12, -20, -28, -36, -42, -48, -53, -53, -43, -31, -19, -6, 12, 25, 31, 30, 26, 15, -2, -17, -28, -40, -52, -60, -61, -53, -40, -25, -9, 11, 32, 56, 74, 84, 85, 81, 76, 72, 61, 46, 29, 13, -2, -16, -23, -29, -33, -31, -25, -19, -14, -8, 2, 10, 14, 18, 19, 17, 8, 1, -12, -24, -35, -42, -49, -54, -57, -53, -43, -30, -13, 7, 22, 32, 34, 32, 26, 11, -8, -24, -40, -50, -60, -66, -63, -53, -36, -17, 2, 23, 45, 67, 84, 90, 91, 85, 78, 72, 62, 44, 24, 4, -9, -21, -32, -39, -41, -36, -30, -23, -17, -9, 2, 13, 23, 27, 26, 19, 12, 2, -12, -26, -38, -47, -54, -59, -59, -53, -41, -23, -5, 14, 28, 36, 36, 31, 21, 6, -13, -31, -46, -58, -66, -70, -65, -50, -28, -7, 14, 35, 58, 76, 89, 96, 94, 90, 82, 72, 54, 35, 16, -5, -21, -31, -40, -48, -47, -38, -28, -20, -13, 1, 15, 28, 33, 33, 27, 18, 8, -6, -21, -37, -52, -64, -66, -65, -58, -47, -30, -9, 13, 28, 38, 43, 40, 31, 15, -5, -24, -40, -57, -69, -75, -74, -65, -48, -26, -2, 24, 47, 66, 83, 97, 102, 102, 101, 91, 73, 51, 28, 7, -15, -33, -45, -56, -60, -54, -42, -28, -17, -4, 13, 26, 36, 38, 36, 29, 16, 2, -14, -34, -52, -62, -66, -65, -63, -53, -36, -15, 9, 27, 36, 41, 40, 35, 25, 8, -16, -37, -55, -68, -77, -81, -75, -60, -37, -12, 12, 35, 57, 75, 94, 105, 107, 103, 97, 84, 64, 41, 18, -6, -25, -40, -51, -57, -56, -46, -32, -19, -6, 7, 20, 30, 34, 32, 24, 12, 0, -17, -33, -47, -60, -65, -64, -58, -46, -31, -12, 8, 26, 37, 43, 44, 41, 28, 11, -12, -31, -49, -67, -81, -87, -85, -72, -52, -30, -6, 21, 45, 69, 87, 101, 110, 113, 110, 100, 77, 51, 27, 8, -11, -32, -49, -59, -59, -53, -41, -27, -11, 3, 14, 24, 28, 28, 24, 17, 5, -15, -32, -45, -54, -61, -58, -54, -44, -32, -13, 8, 26, 37, 41, 40, 36, 29, 16, -3, -24, -47, -66, -81, -89, -88, -76, -58, -37, -16, 10, 34, 58, 78, 94, 106, 111, 107, 97, 81, 58, 37, 17, 0, -17, -33, -45, -51, -48, -38, -26, -14, -3, 9, 16, 19, 17, 14, 10, 0, -15, -30, -42, -49, -52, -49, -44, -37, -25, -8, 9, 21, 29, 32, 35, 33, 29, 19, 1, -18, -38, -58, -75, -85, -85, -79, -70, -52, -29, -6, 20, 44, 67, 89, 101, 110, 114, 107, 93, 72, 49, 28, 10, -9, -25, -38, -48, -49, -42, -31, -20, -11, 0, 9, 13, 12, 7, 5, 0, -11, -24, -36, -42, -44, -43, -38, -28, -16, -4, 8, 16, 22, 29, 30, 29, 24, 13, 2, -14, -32, -51, -68, -79, -83, -77, -69, -56, -41, -19, 6, 31, 53, 74, 90, 101, 108, 109, 101, 83, 60, 38, 24, 9, -10, -25, -36, -40, -37, -29, -21, -13, -8, 0, 3, 0, -5, -6, -8, -16, -27, -35, -39, -40, -33, -27, -21, -11, 3, 14, 21, 24, 27, 26, 22, 19, 13, 3, -14, -32, -53, -66, -74, -80, -80, -75, -63, -47, -28, -4, 19, 41, 66, 85, 99, 105, 106, 104, 95, 76, 51, 29, 13, 2, -12, -27, -36, -38, -32, -22, -15, -12, -8, -3, -4, -9, -12, -14, -18, -26, -31, -35, -36, -29, -20, -10, -2, 7, 16, 25, 25, 24, 19, 15, 10, 4, -4, -16, -30, -44, -57, -67, -73, -75, -70, -60, -48, -34, -16, 5, 27, 51, 71, 85, 92, 99, 101, 95, 82, 64, 44, 28, 14, 1, -12, -22, -28, -27, -22, -18, -17, -15, -15, -15, -21, -23, -25, -24, -27, -31, -34, -30, -21, -6, 7, 13, 17, 22, 27, 28, 24, 16, 7, -3, -10, -17, -27, -35, -43, -50, -58, -68, -70, -65, -53, -42, -32, -22, -4, 15, 36, 54, 70, 83, 89, 92, 91, 82, 68, 54, 42, 29, 14, 2, -9, -17, -21, -22, -20, -21, -20, -23, -26, -30, -32, -32, -29, -27, -28, -30, -26, -15, 0, 15, 25, 25, 25, 26, 27, 21, 11, 0, -9, -17, -24, -30, -38, -45, -47, -49, -55, -59, -56, -48, -39, -28, -20, -9, 7, 26, 44, 55, 65, 72, 79, 80, 77, 66, 57, 49, 41, 30, 19, 7, -2, -7, -12, -17, -22, -25, -29, -33, -36, -39, -41, -36, -29, -26, -26, -22, -11, 2, 17, 28, 32, 31, 29, 28, 23, 11, -2, -9, -17, -24, -36, -44, -48, -49, -50, -53, -54, -54, -47, -36, -25, -17, -7, 7, 21, 36, 47, 55, 63, 70, 72, 69, 60, 52, 46, 42, 34, 23, 15, 8, 3, 0, -7, -14, -21, -24, -27, -32, -39, -44, -43, -37, -29, -25, -23, -16, -2, 14, 26, 32, 33, 32, 30, 25, 16, 4, -6, -16, -25, -36, -45, -50, -54, -51, -51, -54, -54, -48, -36, -23, -15, -6, 5, 17, 31, 42, 51, 59, 62, 63, 61, 56, 51, 43, 40, 38, 28, 20, 13, 9, 7, 2, -8, -16, -23, -27, -31, -36, -40, -43, -39, -31, -23, -20, -15, -4, 11, 24, 31, 32, 31, 30, 25, 17, 7, -3, -13, -23, -36, -48, -56, -58, -57, -53, -50, -52, -51, -40, -25, -12, 0, 7, 16, 25, 36, 49, 58, 60, 59, 57, 54, 49, 43, 36, 31, 26, 18, 13, 10, 6, 4, 0, -6, -12, -19, -22, -26, -31, -35, -35, -32, -27, -22, -16, -7, 4, 13, 21, 26, 30, 29, 27, 22, 15, 4, -7, -19, -31, -44, -55, -59, -59, -58, -54, -52, -49, -41, -28, -14, 0, 10, 18, 26, 33, 44, 50, 53, 51, 50, 48, 46, 41, 37, 30, 24, 21, 18, 15, 13, 8, 4, 0, -6, -9, -14, -19, -23, -27, -33, -33, -31, -25, -19, -11, -3, 3, 11, 20, 28, 31, 28, 22, 14, 8, -3, -15, -29, -40, -49, -57, -62, -60, -56, -50, -47, -42, -32, -18, -3, 11, 20, 25, 29, 35, 43, 49, 51, 47, 43, 41, 37, 33, 29, 24, 18, 15, 14, 13, 11, 8, 5, 1, 0, -5, -11, -19, -23, -24, -25, -25, -26, -22, -15, -9, -3, 4, 12, 19, 25, 26, 24, 17, 11, 2, -11, -26, -37, -45, -53, -58, -59, -57, -53, -47, -42, -35, -25, -10, 5, 15, 19, 22, 29, 37, 45, 48, 47, 44, 44, 43, 40, 33, 24, 19, 14, 13, 12, 8, 2, -2, 1, 1, 1, -4, -12, -15, -14, -13, -14, -18, -18, -15, -12, -8, -5, 2, 10, 18, 21, 20, 15, 10, 3, -7, -18, -31, -42, -47, -50, -53, -57, -57, -51, -42, -34, -25, -15, -5, 7, 16, 22, 30, 35, 40, 43, 42, 39, 39, 38, 38, 31, 22, 16, 14, 15, 17, 16, 12, 6, 4, 5, 7, 6, 0, -8, -12, -13, -15, -19, -21, -20, -17, -14, -11, -6, 2, 10, 18, 21, 21, 19, 11, -2, -17, -29, -37, -42, -46, -52, -55, -58, -52, -42, -34, -24, -15, -5, 5, 12, 17, 24, 32, 37, 37, 36, 33, 33, 35, 35, 32, 26, 22, 16, 17, 19, 19, 14, 7, 5, 5, 6, 5, 0, -7, -10, -9, -6, -7, -13, -17, -15, -11, -8, -7, -6, 1, 7, 12, 13, 11, 7, 0, -12, -25, -35, -40, -42, -43, -44, -47, -49, -43, -34, -22, -12, -7, 0, 4, 9, 17, 25, 31, 33, 33, 31, 30, 27, 28, 30, 29, 25, 20, 17, 20, 24, 22, 17, 11, 10, 9, 9, 5, -6, -11, -13, -9, -5, -9, -16, -19, -16, -9, -6, -6, -2, 4, 8, 11, 11, 6, -4, -11, -21, -34, -39, -41, -40, -38, -40, -44, -38, -28, -17, -10, -6, -5, -3, 3, 10, 15, 17, 20, 23, 26, 25, 24, 26, 28, 30, 30, 28, 25, 24, 23, 25, 22, 18, 14, 9, 5, 0, -7, -12, -13, -12, -7, -6, -9, -12, -10, -4, 2, 2, 3, 3, 3, 6, 7, 3, -9, -21, -28, -35, -40, -40, -37, -37, -36, -36, -29, -22, -11, -3, 2, 3, 0, 1, 3, 6, 9, 10, 10, 10, 13, 16, 21, 24, 29, 31, 33, 33, 33, 32, 30, 27, 23, 16, 12, 7, -2, -7, -14, -19, -16, -10, -5, -7, -9, -9, -6, 2, 6, 8, 7, 4, 3, 1, -3, -9, -16, -25, -34, -39, -41, -37, -33, -31, -31, -29, -22, -12, -4, 2, 7, 5, 1, -2, 0, 4, 4, 2, 2, 5, 10, 14, 19, 24, 28, 32, 36, 38, 36, 34, 31, 27, 23, 18, 11, 3, -5, -12, -15, -15, -11, -6, -5, -6, -8, -7, -3, 1, 4, 6, 3, -2, -7, -9, -12, -19, -24, -30, -34, -36, -35, -32, -29, -26, -22, -16, -10, -3, 4, 8, 9, 4, 0, -3, 0, 1, -5, -7, -5, 1, 7, 13, 14, 17, 27, 35, 38, 37, 35, 33, 31, 29, 25, 19, 11, 3, 0, -6, -10, -10, -7, -5, -5, -7, -7, -6, -3, 1, 4, 3, 0, -8, -15, -18, -20, -23, -27, -30, -32, -33, -29, -28, -25, -20, -16, -13, -6, 1, 6, 7, 4, 0, -5, -5, -5, -6, -7, -6, -2, 5, 10, 15, 20, 25, 32, 34, 34, 34, 32, 29, 24, 22, 19, 14, 9, 6, 4, 2, 0, 0, 2, 2, -2, -4, -6, -5, -5, -4, -4, -7, -12, -19, -25, -26, -26, -26, -26, -29, -28, -28, -25, -22, -18, -14, -10, -5, 0, 3, 4, 5, 4, 3, -2, -7, -10, -12, -9, -6, 0, 6, 11, 14, 16, 22, 30, 33, 34, 29, 25, 23, 21, 22, 22, 20, 18, 16, 14, 13, 11, 11, 11, 6, -4, -12, -16, -17, -16, -13, -16, -22, -26, -30, -30, -25, -21, -18, -17, -19, -18, -20, -19, -15, -13, -9, -7, -6, -5, -2, 3, 5, 4, 0, -5, -8, -6, -6, -6, -2, 4, 9, 11, 13, 15, 19, 23, 25, 22, 19, 16, 17, 20, 21, 22, 23, 24, 25, 24, 23, 22, 21, 16, 7, -4, -14, -21, -23, -24, -24, -28, -34, -38, -36, -31, -21, -13, -9, -8, -10, -11, -12, -14, -13, -12, -9, -10, -12, -11, -9, -4, 3, 4, 1, -3, -4, 1, 4, 7, 10, 10, 11, 12, 11, 8, 9, 11, 13, 11, 5, 4, 11, 20, 26, 29, 32, 35, 39, 39, 34, 30, 23, 15, 5, -10, -23, -31, -34, -32, -33, -37, -42, -41, -32, -21, -11, -6, -3, -3, -6, -8, -11, -14, -15, -14, -14, -14, -19, -20, -15, -7, 0, -2, -3, 0, 4, 10, 17, 19, 18, 18, 20, 18, 11, 5, 1, -2, -4, -7, -8, -4, 4, 14, 24, 32, 38, 46, 51, 52, 46, 37, 28, 19, 5, -12, -29, -39, -44, -46, -46, -50, -48, -39, -29, -14, -4, 6, 9, 8, 6, 0, -8, -13, -15, -18, -22, -28, -30, -26, -18, -9, -7, -4, 2, 10, 18, 24, 26, 26, 23, 22, 21, 14, 3, -5, -9, -14, -16, -16, -11, -4, 6, 14, 24, 37, 50, 58, 58, 53, 45, 36, 28, 17, 1, -18, -36, -47, -53, -54, -53, -51, -43, -33, -20, -8, 5, 15, 17, 13, 5, -4, -12, -14, -18, -23, -30, -34, -32, -24, -15, -10, -6, -3, 7, 18, 27, 32, 33, 30, 28, 24, 19, 12, 2, -10, -18, -24, -26, -23, -16, -6, 4, 12, 25, 39, 53, 60, 60, 58, 51, 42, 30, 16, 0, -20, -37, -49, -57, -61, -57, -50, -40, -29, -17, -4, 9, 17, 17, 11, 5, -3, -8, -13, -21, -30, -35, -34, -29, -22, -16, -11, -6, 1, 12, 24, 34, 39, 39, 35, 28, 21, 16, 8, -3, -16, -29, -35, -34, -26, -16, -9, 1, 14, 30, 46, 56, 60, 62, 59, 57, 46, 32, 15, -2, -17, -35, -51, -61, -61, -55, -46, -39, -30, -19, -4, 10, 14, 13, 7, 3, -2, -6, -15, -24, -31, -33, -31, -26, -23, -19, -11, -2, 6, 17, 30, 38, 41, 39, 34, 25, 18, 14, 6, -9, -24, -34, -38, -34, -28, -18, -9, 0, 14, 32, 44, 52, 58, 63, 66, 59, 45, 31, 18, 4, -17, -36, -53, -60, -59, -54, -46, -39, -30, -18, -3, 6, 8, 6, 3, 1, -3, -11, -22, -29, -28, -23, -20, -20, -18, -10, -2, 7, 17, 27, 34, 37, 38, 33, 26, 19, 15, 11, 0, -17, -31, -39, -40, -34, -27, -20, -11, 1, 16, 31, 43, 52, 59, 67, 70, 62, 47, 32, 19, 4, -18, -39, -53, -60, -57, -51, -44, -37, -30, -17, -6, 1, 2, 1, 0, -2, -7, -15, -23, -27, -25, -19, -16, -15, -12, -4, 5, 15, 25, 33, 37, 34, 31, 27, 22, 17, 11, 2, -11, -25, -35, -41, -41, -34, -23, -13, -4, 6, 18, 31, 43, 54, 61, 65, 62, 53, 44, 34, 22, 2, -20, -38, -47, -50, -47, -43, -42, -41, -32, -19, -13, -11, -10, -7, -5, -5, -9, -14, -18, -17, -12, -9, -8, -6, 1, 6, 12, 16, 21, 25, 25, 23, 19, 18, 14, 11, 8, 0, -10, -23, -34, -36, -32, -24, -16, -12, -6, 4, 15, 30, 42, 52, 59, 60, 58, 53, 46, 39, 27, 5, -19, -35, -43, -44, -43, -45, -49, -48, -39, -31, -27, -24, -19, -11, -6, -3, -4, -6, -8, -5, 3, 5, 7, 6, 7, 9, 12, 13, 15, 14, 12, 11, 11, 9, 8, 5, 4, 0, -12, -22, -28, -26, -21, -17, -13, -10, -5, 4, 14, 22, 32, 44, 56, 61, 59, 56, 48, 38, 25, 7, -10, -24, -33, -38, -44, -50, -51, -47, -41, -41, -41, -37, -26, -14, -6, 0, -2, -3, 5, 13, 19, 21, 16, 12, 9, 9, 10, 7, 3, 2, 2, 1, -2, 0, 3, 4, 1, -4, -12, -16, -16, -9, -9, -10, -9, -5, 2, 7, 11, 17, 27, 39, 51, 54, 52, 52, 49, 42, 28, 10, -4, -15, -25, -36, -48, -56, -58, -56, -52, -53, -54, -45, -28, -11, -2, 3, 8, 15, 24, 30, 34, 30, 22, 16, 12, 6, -4, -9, -9, -8, -12, -14, -12, -5, 3, 4, 2, -3, -4, 0, 3, 2, -4, -6, -6, -5, -4, -5, -3, 8, 21, 36, 44, 50, 55, 58, 55, 45, 33, 20, 5, -11, -27, -43, -55, -60, -61, -62, -64, -66, -58, -40, -20, -6, 3, 8, 16, 26, 34, 39, 38, 30, 21, 11, 2, -9, -14, -13, -13, -15, -16, -14, -6, 1, 4, 4, 3, 4, 7, 10, 10, 5, -3, -7, -8, -9, -12, -14, -11, 0, 13, 28, 40, 51, 58, 61, 60, 56, 47, 33, 15, -8, -28, -44, -55, -62, -72, -81, -83, -74, -58, -39, -21, -6, 8, 18, 30, 40, 47, 49, 44, 33, 19, 6, -6, -14, -19, -23, -26, -24, -19, -13, -5, -2, 2, 5, 8, 11, 14, 13, 9, 2, -4, -8, -12, -15, -19, -18, -13, -3, 14, 30, 44, 53, 62, 66, 66, 59, 48, 33, 12, -10, -31, -46, -58, -71, -79, -84, -81, -71, -54, -34, -14, 1, 14, 26, 37, 44, 48, 49, 41, 29, 12, -3, -13, -17, -19, -24, -26, -22, -16, -8, -3, -2, 3, 6, 10, 13, 12, 10, 6, 2, -4, -11, -18, -22, -22, -19, -14, -3, 13, 30, 46, 61, 68, 71, 70, 64, 52, 32, 10, -12, -31, -51, -67, -81, -88, -91, -84, -69, -51, -32, -12, 8, 25, 37, 43, 47, 52, 50, 40, 23, 5, -8, -13, -18, -23, -28, -26, -19, -12, -6, -4, -2, 2, 6, 11, 11, 5, 3, 4, 1, -9, -17, -21, -23, -22, -19, -14, 0, 17, 37, 54, 65, 70, 75, 76, 67, 50, 30, 6, -15, -35, -56, -75, -88, -93, -88, -78, -64, -47, -26, -3, 17, 31, 37, 42, 46, 48, 42, 27, 10, 0, -3, -7, -14, -21, -21, -13, -4, 1, -2, -3, 1, 5, 7, 4, -3, -8, -7, -7, -14, -19, -22, -23, -21, -20, -16, -6, 12, 32, 51, 63, 70, 76, 78, 75, 63, 44, 20, -5, -26, -46, -67, -83, -94, -93, -83, -69, -55, -40, -17, 8, 25, 34, 38, 43, 48, 45, 35, 20, 8, 2, 3, -2, -12, -18, -15, -8, 0, 0, -5, -6, -4, -3, -5, -11, -15, -14, -12, -13, -16, -19, -20, -20, -16, -10, -2, 11, 24, 42, 57, 64, 70, 73, 72, 64, 48, 26, 4, -15, -35, -50, -68, -81, -88, -81, -68, -55, -44, -29, -10, 9, 22, 25, 30, 37, 38, 35, 24, 14, 11, 13, 14, 9, 0, -5, -3, 3, 4, -2, -10, -15, -15, -15, -19, -25, -24, -20, -18, -19, -20, -18, -16, -13, -9, 1, 12, 25, 37, 53, 63, 69, 74, 73, 69, 56, 37, 15, -6, -25, -42, -59, -75, -82, -81, -72, -61, -50, -35, -17, -2, 13, 20, 27, 31, 34, 34, 28, 19, 14, 13, 15, 14, 8, 4, 3, 5, 5, 1, -6, -15, -18, -22, -27, -33, -34, -31, -25, -24, -20, -19, -17, -10, -2, 9, 18, 28, 39, 51, 60, 67, 71, 72, 67, 53, 35, 16, -4, -21, -40, -57, -70, -76, -74, -65, -55, -44, -34, -21, -7, 6, 15, 18, 20, 24, 24, 21, 16, 15, 16, 17, 17, 16, 13, 12, 13, 13, 9, 0, -12, -17, -22, -31, -40, -43, -40, -35, -30, -26, -24, -20, -11, -2, 9, 19, 29, 39, 46, 54, 60, 66, 67, 66, 58, 41, 21, 5, -11, -29, -47, -62, -68, -68, -65, -57, -49, -39, -27, -13, -2, 6, 11, 18, 23, 24, 21, 19, 19, 21, 21, 18, 15, 11, 13, 15, 15, 10, -2, -8, -14, -21, -30, -39, -44, -44, -40, -33, -29, -27, -21, -12, -3, 6, 16, 28, 40, 48, 54, 56, 59, 61, 62, 57, 44, 28, 12, -3, -22, -40, -55, -64, -63, -61, -56, -51, -41, -29, -15, -6, 1, 8, 15, 20, 20, 18, 17, 18, 23, 23, 20, 17, 15, 18, 20, 20, 15, 4, -5, -11, -20, -32, -43, -49, -48, -43, -36, -32, -29, -21, -13, 0, 11, 20, 30, 38, 46, 50, 51, 53, 56, 53, 48, 41, 30, 19, 5, -10, -26, -42, -50, -56, -57, -56, -53, -46, -38, -27, -18, -10, -2, 8, 16, 19, 24, 24, 22, 23, 25, 23, 17, 16, 15, 16, 14, 10, 3, -5, -11, -20, -28, -35, -42, -44, -42, -35, -29, -25, -19, -11, 0, 10, 20, 26, 31, 38, 45, 48, 46, 46, 44, 41, 37, 30, 22, 13, 1, -15, -27, -36, -44, -49, -51, -52, -49, -44, -37, -27, -20, -12, 1, 10, 19, 23, 28, 29, 28, 28, 24, 19, 17, 16, 15, 14, 10, 4, -3, -10, -15, -23, -31, -36, -41, -41, -39, -32, -24, -19, -11, -3, 5, 15, 24, 31, 36, 42, 45, 44, 41, 37, 33, 31, 29, 23, 14, 2, -8, -16, -22, -31, -40, -44, -46, -46, -46, -44, -37, -28, -20, -10, 2, 11, 20, 28, 32, 32, 29, 26, 22, 19, 17, 14, 12, 11, 8, 2, -5, -14, -20, -24, -30, -34, -37, -38, -36, -30, -21, -14, -6, 2, 11, 19, 26, 30, 34, 41, 44, 42, 38, 32, 27, 25, 24, 21, 11, 1, -9, -16, -25, -34, -40, -43, -45, -48, -50, -49, -40, -27, -15, -6, 4, 15, 27, 36, 40, 37, 32, 27, 22, 15, 11, 10, 8, 6, 0, -8, -14, -16, -17, -18, -24, -31, -33, -33, -27, -22, -17, -10, -4, 6, 13, 17, 22, 27, 33, 38, 39, 37, 35, 33, 31, 27, 23, 19, 11, 3, -7, -20, -30, -38, -42, -42, -46, -53, -58, -53, -41, -27, -13, -2, 10, 19, 30, 39, 43, 38, 29, 23, 18, 12, 8, 6, 6, 4, -3, -8, -12, -13, -10, -12, -17, -24, -25, -23, -23, -23, -19, -12, -4, 2, 5, 9, 14, 22, 32, 37, 39, 39, 37, 37, 33, 28, 27, 21, 12, 0, -14, -25, -33, -38, -43, -48, -54, -60, -59, -48, -36, -20, -8, 2, 12, 26, 39, 44, 40, 32, 27, 23, 16, 8, 3, 3, 2, 1, -4, -9, -9, -6, -6, -8, -13, -16, -18, -21, -22, -21, -16, -7, -2, 0, -2, 2, 13, 25, 30, 34, 34, 34, 34, 33, 33, 31, 26, 21, 11, -3, -15, -25, -31, -37, -48, -57, -62, -63, -56, -46, -35, -25, -12, 5, 18, 32, 40, 40, 36, 32, 29, 22, 15, 7, 3, 0, 0, 0, 1, -2, -2, 0, 0, -3, -4, -7, -13, -22, -28, -25, -17, -10, -10, -11, -10, -4, 12, 26, 36, 39, 40, 41, 40, 37, 35, 33, 28, 19, 3, -11, -22, -30, -37, -46, -56, -63, -65, -59, -52, -43, -29, -17, -4, 10, 23, 32, 36, 36, 34, 29, 24, 19, 12, 5, -2, 0, 4, 7, 10, 9, 6, 5, 5, 5, 0, -10, -20, -26, -29, -26, -20, -18, -19, -17, -9, 3, 16, 28, 36, 40, 42, 43, 41, 40, 36, 33, 26, 16, 3, -10, -21, -31, -42, -53, -61, -65, -63, -58, -52, -41, -31, -18, -4, 9, 21, 26, 29, 30, 31, 31, 28, 21, 12, 6, 5, 10, 13, 13, 14, 9, 8, 7, 5, 0, -8, -17, -24, -28, -27, -23, -17, -14, -12, -8, 2, 15, 26, 32, 36, 39, 38, 37, 36, 33, 28, 21, 16, 10, 1, -13, -25, -34, -41, -50, -59, -62, -62, -53, -44, -37, -28, -19, -6, 7, 14, 18, 22, 26, 28, 28, 21, 13, 6, 6, 15, 19, 21, 20, 20, 18, 16, 13, 7, -3, -12, -21, -27, -31, -30, -24, -15, -11, -8, 0, 10, 23, 29, 32, 34, 34, 34, 33, 32, 27, 23, 20, 17, 10, -2, -15, -25, -34, -43, -52, -61, -63, -58, -49, -43, -41, -33, -22, -9, 3, 11, 17, 21, 26, 30, 28, 23, 17, 15, 18, 22, 22, 20, 21, 21, 18, 12, 4, -5, -11, -16, -22, -28, -32, -24, -14, -7, -5, 1, 11, 20, 27, 30, 26, 25, 29, 30, 29, 22, 17, 18, 22, 20, 9, -8, -18, -25, -31, -40, -53, -60, -58, -54, -46, -45, -42, -32, -20, -10, -2, 5, 12, 19, 25, 27, 22, 18, 18, 21, 24, 25, 22, 24, 26, 27, 22, 10, 0, -7, -9, -12, -21, -28, -28, -20, -9, -4, -2, 5, 14, 22, 24, 21, 15, 18, 24, 28, 24, 19, 21, 26, 30, 22, 7, -6, -15, -23, -34, -50, -61, -66, -61, -52, -50, -49, -45, -36, -22, -10, 1, 11, 15, 20, 26, 26, 24, 21, 21, 27, 28, 24, 21, 22, 26, 24, 16, 5, -5, -7, -5, -11, -17, -22, -17, -7, 0, 1, 4, 9, 16, 19, 18, 13, 12, 16, 22, 24, 23, 23, 28, 33, 27, 16, 2, -12, -23, -33, -45, -57, -64, -64, -55, -51, -52, -49, -39, -25, -13, -6, 1, 6, 12, 16, 18, 20, 18, 20, 25, 28, 28, 29, 31, 36, 37, 28, 15, 7, 3, 0, -4, -14, -21, -23, -16, -7, -4, -3, 1, 10, 16, 17, 10, 7, 9, 18, 24, 24, 24, 28, 34, 34, 26, 12, -3, -15, -26, -40, -53, -61, -65, -62, -59, -57, -55, -49, -39, -27, -18, -6, 3, 8, 14, 17, 21, 25, 26, 27, 28, 30, 32, 32, 31, 32, 28, 22, 14, 6, 3, 0, -3, -8, -12, -12, -5, 0, 2, 1, 3, 6, 11, 11, 7, 4, 6, 13, 20, 24, 28, 31, 32, 28, 19, 7, -7, -20, -32, -44, -53, -58, -58, -55, -54, -53, -50, -46, -40, -27, -14, -6, -6, -5, 0, 8, 16, 20, 23, 25, 30, 37, 42, 43, 41, 39, 34, 28, 18, 9, 4, 3, 0, -10, -13, -12, -10, -5, 1, 1, 0, 4, 8, 7, 5, 6, 11, 19, 23, 27, 32, 33, 27, 20, 10, 0, -15, -30, -41, -49, -52, -54, -55, -55, -53, -50, -45, -40, -32, -24, -16, -11, -10, -8, -3, 6, 13, 17, 21, 29, 37, 43, 48, 47, 43, 38, 35, 30, 19, 11, 7, 2, -5, -9, -9, -5, 1, 1, 0, -2, 1, 3, 6, 5, 4, 5, 10, 16, 20, 24, 27, 25, 18, 10, 3, -9, -21, -31, -39, -44, -47, -47, -44, -46, -48, -48, -45, -39, -36, -30, -26, -25, -23, -19, -9, 4, 14, 24, 32, 41, 48, 54, 56, 57, 52, 47, 40, 28, 17, 10, 4, -3, -8, -10, -8, -6, -5, -5, -5, -3, 0, 3, 4, 4, 5, 7, 12, 19, 26, 27, 24, 18, 12, 5, -3, -12, -24, -34, -43, -46, -48, -48, -46, -46, -45, -44, -42, -38, -33, -29, -26, -26, -22, -14, -5, 5, 13, 23, 32, 40, 47, 52, 56, 57, 55, 52, 47, 36, 27, 19, 11, 3, -5, -6, -8, -10, -13, -15, -14, -13, -11, -6, 1, 4, 7, 11, 17, 21, 26, 28, 26, 19, 10, 2, -7, -17, -26, -36, -41, -45, -47, -45, -44, -44, -41, -39, -40, -40, -37, -33, -34, -32, -26, -18, -9, 2, 12, 26, 40, 47, 56, 63, 66, 66, 63, 60, 53, 40, 27, 14, 3, -8, -11, -12, -15, -19, -19, -18, -15, -12, -8, 0, 6, 11, 13, 14, 17, 23, 29, 27, 18, 9, 1, -7, -16, -25, -35, -43, -49, -47, -44, -43, -42, -40, -36, -34, -33, -33, -33, -35, -34, -30, -23, -16, -9, 2, 14, 27, 39, 49, 58, 66, 69, 68, 66, 61, 53, 45, 32, 18, 1, -11, -14, -17, -17, -20, -23, -21, -17, -13, -3, 4, 10, 13, 14, 17, 18, 21, 24, 22, 15, 6, -4, -12, -22, -28, -38, -49, -51, -48, -45, -43, -40, -38, -36, -35, -34, -33, -33, -34, -35, -33, -29, -18, -6, 6, 19, 33, 46, 59, 71, 78, 78, 78, 74, 67, 54, 39, 22, 6, -8, -16, -22, -25, -25, -26, -22, -17, -12, -3, 6, 15, 17, 16, 14, 14, 16, 17, 16, 13, 6, -2, -11, -20, -27, -34, -43, -49, -48, -44, -41, -39, -36, -33, -34, -33, -34, -32, -33, -35, -35, -30, -21, -11, 0, 9, 23, 38, 52, 65, 74, 76, 76, 74, 70, 62, 47, 28, 13, 2, -6, -14, -21, -23, -20, -18, -16, -13, -7, 1, 8, 10, 11, 9, 11, 11, 13, 15, 16, 13, 8, -2, -11, -19, -27, -37, -47, -52, -51, -48, -46, -43, -40, -38, -36, -35, -35, -38, -38, -33, -27, -21, -16, -7, 6, 21, 36, 49, 61, 70, 75, 79, 78, 73, 62, 49, 35, 22, 8, -3, -12, -17, -20, -18, -14, -13, -15, -12, -5, 4, 7, 8, 8, 9, 8, 9, 11, 14, 14, 10, 4, -6, -15, -25, -35, -41, -48, -54, -53, -47, -42, -38, -37, -35, -31, -31, -30, -30, -29, -26, -24, -19, -12, -2, 10, 22, 35, 48, 60, 70, 76, 76, 73, 67, 57, 44, 28, 14, 5, -3, -8, -13, -14, -13, -10, -11, -11, -8, -2, 4, 6, 5, 5, 5, 6, 10, 11, 10, 8, 4, -2, -9, -15, -24, -35, -44, -50, -52, -49, -45, -42, -42, -40, -37, -37, -37, -33, -29, -26, -24, -21, -16, -7, 6, 18, 30, 41, 54, 66, 75, 77, 79, 76, 67, 53, 37, 21, 8, 2, -5, -10, -14, -14, -12, -12, -11, -10, -5, 4, 7, 4, 1, 2, 6, 9, 9, 7, 5, 4, 0, -7, -14, -23, -32, -37, -43, -48, -50, -51, -47, -42, -34, -32, -32, -34, -32, -26, -21, -18, -17, -14, -11, -4, 5, 13, 24, 40, 55, 67, 72, 74, 76, 75, 67, 51, 37, 23, 11, 4, -4, -11, -15, -17, -17, -16, -14, -13, -8, -2, 1, 1, 1, 3, 5, 9, 7, 5, 4, 4, 3, -5, -14, -24, -32, -38, -41, -47, -52, -53, -49, -41, -35, -34, -35, -33, -29, -24, -19, -13, -10, -9, -7, -2, 8, 17, 29, 43, 56, 67, 74, 75, 75, 72, 64, 53, 38, 23, 13, 4, -5, -12, -16, -20, -21, -18, -16, -14, -11, -8, -5, -3, 0, 2, 6, 6, 6, 5, 5, 6, 3, -6, -19, -31, -37, -41, -45, -50, -52, -53, -48, -39, -32, -30, -26, -25, -22, -16, -10, -7, -11, -10, -8, -2, 6, 17, 31, 45, 58, 68, 78, 80, 76, 70, 65, 55, 37, 18, 5, -4, -10, -19, -25, -26, -24, -18, -13, -11, -9, -6, -2, 4, 6, 5, 4, 3, 4, 2, 1, -3, -4, -11, -20, -29, -38, -43, -45, -48, -51, -48, -44, -39, -35, -34, -31, -30, -25, -15, -8, -8, -10, -8, 1, 11, 22, 33, 42, 54, 66, 76, 80, 75, 70, 66, 59, 42, 23, 6, -4, -9, -17, -22, -27, -25, -19, -9, -7, -8, -5, 0, 4, 5, 2, -2, -5, -5, -4, -6, -7, -6, -10, -16, -21, -29, -34, -37, -38, -41, -44, -42, -36, -32, -33, -37, -39, -35, -27, -17, -12, -13, -12, -6, 6, 22, 36, 44, 54, 66, 77, 82, 80, 75, 68, 59, 47, 29, 10, -3, -13, -18, -23, -26, -27, -24, -16, -9, -5, -4, -2, 3, 6, 4, -2, -6, -8, -7, -8, -8, -9, -10, -13, -16, -22, -29, -31, -30, -34, -36, -36, -32, -28, -30, -36, -39, -38, -33, -28, -24, -24, -22, -15, -2, 13, 26, 38, 53, 67, 78, 84, 88, 85, 81, 71, 59, 39, 13, -5, -14, -19, -26, -32, -34, -30, -22, -13, -5, 0, 6, 7, 10, 8, 2, -4, -10, -12, -15, -18, -20, -20, -20, -22, -24, -26, -26, -23, -23, -23, -24, -21, -17, -18, -25, -31, -35, -37, -37, -36, -33, -29, -22, -10, 5, 19, 31, 45, 62, 75, 84, 86, 88, 87, 80, 66, 45, 22, 4, -9, -18, -26, -34, -37, -33, -24, -15, -9, -3, 6, 13, 15, 11, 2, -5, -10, -13, -20, -25, -27, -26, -25, -26, -29, -29, -23, -18, -16, -19, -18, -15, -9, -6, -12, -21, -32, -36, -36, -40, -39, -36, -30, -21, -10, 6, 20, 36, 55, 69, 79, 85, 90, 92, 88, 75, 56, 33, 12, -3, -15, -24, -33, -37, -35, -28, -20, -12, -4, 6, 14, 18, 16, 9, 0, -8, -15, -19, -27, -33, -35, -34, -34, -36, -36, -29, -19, -10, -10, -10, -8, -4, -2, -2, -8, -18, -28, -36, -43, -48, -46, -36, -25, -14, -4, 10, 27, 46, 65, 78, 86, 89, 87, 85, 78, 64, 42, 19, 0, -12, -20, -29, -34, -36, -30, -22, -12, -6, 1, 8, 16, 18, 13, 2, -7, -12, -17, -24, -33, -38, -39, -36, -36, -36, -34, -26, -18, -11, -7, -6, -5, -5, 1, 1, -5, -14, -24, -33, -41, -42, -37, -28, -19, -10, 3, 16, 30, 47, 64, 76, 83, 85, 83, 78, 69, 54, 37, 17, -2, -14, -21, -28, -32, -32, -27, -18, -11, -6, 2, 12, 18, 16, 5, -5, -11, -14, -19, -30, -40, -47, -45, -38, -36, -34, -33, -26, -15, -6, -2, 1, 1, 3, 5, 4, -3, -13, -26, -35, -41, -39, -33, -23, -13, -5, 7, 21, 36, 53, 68, 79, 82, 78, 72, 66, 59, 47, 30, 10, -6, -16, -21, -22, -25, -27, -25, -18, -10, -4, 4, 10, 11, 6, -4, -11, -13, -18, -25, -34, -43, -45, -41, -36, -34, -32, -27, -19, -10, -5, 0, 2, 5, 5, 5, 1, -7, -16, -25, -33, -38, -35, -25, -13, -6, 0, 11, 27, 46, 60, 69, 70, 68, 69, 68, 62, 52, 39, 22, 8, -2, -11, -18, -21, -22, -23, -24, -17, -10, -5, 1, 5, 5, 2, -3, -5, -9, -17, -28, -41, -46, -48, -43, -42, -42, -39, -30, -19, -9, -3, 6, 11, 15, 16, 12, 5, -2, -12, -23, -33, -37, -34, -25, -18, -8, 1, 15, 32, 48, 62, 69, 68, 67, 63, 62, 58, 50, 34, 15, -2, -8, -10, -11, -16, -24, -24, -19, -12, -6, -2, 2, 3, 1, 0, -6, -10, -17, -26, -37, -46, -48, -45, -44, -42, -38, -32, -22, -12, -6, 4, 10, 14, 16, 15, 11, 5, -2, -11, -23, -31, -29, -22, -18, -16, -11, 3, 17, 34, 50, 56, 59, 61, 63, 62, 59, 53, 44, 32, 16, 3, -8, -9, -13, -20, -26, -27, -21, -16, -11, -9, -6, 1, 7, 7, 0, -10, -15, -20, -30, -39, -45, -48, -48, -46, -41, -36, -29, -20, -11, 3, 11, 14, 19, 21, 19, 15, 6, -3, -13, -18, -18, -17, -20, -19, -12, 2, 15, 26, 36, 43, 51, 59, 61, 61, 57, 54, 49, 37, 21, 9, 1, -8, -17, -25, -29, -28, -27, -23, -19, -13, -5, 2, 8, 5, -4, -11, -13, -17, -27, -40, -49, -53, -53, -50, -44, -37, -28, -19, -7, 8, 18, 22, 26, 26, 23, 17, 10, 0, -8, -15, -20, -25, -23, -19, -11, 0, 13, 25, 34, 44, 54, 60, 62, 60, 58, 56, 52, 38, 21, 6, -6, -16, -26, -32, -33, -30, -26, -24, -17, -8, 3, 13, 16, 10, 1, -7, -12, -18, -34, -50, -61, -63, -58, -54, -50, -45, -33, -13, 6, 21, 27, 34, 37, 36, 30, 20, 11, -2, -13, -24, -32, -37, -34, -24, -10, 2, 12, 25, 41, 55, 61, 64, 65, 67, 64, 59, 48, 32, 16, 0, -12, -20, -27, -33, -33, -31, -28, -23, -12, 0, 10, 13, 9, 2, -2, -7, -13, -25, -41, -56, -65, -66, -62, -56, -53, -42, -25, -5, 13, 24, 34, 39, 42, 39, 32, 22, 11, -2, -15, -27, -36, -37, -31, -22, -13, 0, 12, 27, 43, 55, 61, 64, 65, 63, 60, 53, 42, 28, 10, -6, -20, -27, -28, -28, -25, -23, -20, -13, -2, 11, 16, 14, 8, 2, -6, -14, -25, -38, -53, -67, -73, -73, -67, -58, -46, -32, -14, 6, 24, 36, 43, 45, 44, 39, 30, 18, 5, -11, -25, -35, -39, -37, -28, -17, -7, 4, 16, 32, 48, 58, 64, 66, 63, 61, 56, 46, 31, 18, 3, -13, -21, -25, -23, -19, -15, -11, -7, -2, 6, 13, 14, 8, -3, -12, -21, -32, -40, -55, -70, -78, -75, -67, -56, -47, -29, -12, 10, 29, 40, 47, 49, 48, 43, 31, 15, 0, -16, -29, -39, -45, -41, -32, -18, -6, 3, 13, 27, 43, 57, 64, 65, 61, 58, 52, 43, 32, 18, 6, -9, -18, -20, -17, -12, -4, 1, 3, 7, 12, 17, 16, 9, -3, -15, -27, -39, -48, -60, -72, -82, -82, -73, -58, -45, -33, -14, 7, 28, 42, 49, 51, 51, 48, 38, 22, 2, -16, -30, -37, -42, -45, -40, -26, -11, 3, 11, 20, 34, 52, 65, 69, 64, 54, 46, 38, 28, 16, 4, -11, -18, -16, -10, -4, 3, 13, 21, 23, 22, 20, 18, 11, -2, -16, -34, -47, -59, -70, -76, -83, -83, -76, -64, -48, -31, -12, 10, 30, 42, 50, 53, 51, 46, 37, 25, 8, -13, -30, -41, -45, -43, -35, -23, -15, -5, 8, 17, 28, 40, 56, 64, 63, 55, 45, 34, 24, 14, 7, -4, -12, -13, -9, -2, 11, 23, 31, 33, 33, 31, 26, 17, 4, -14, -31, -48, -62, -75, -86, -90, -87, -79, -68, -54, -39, -18, 4, 23, 39, 47, 52, 52, 47, 39, 29, 15, -5, -23, -35, -41, -40, -34, -26, -16, -8, 2, 12, 22, 30, 43, 52, 58, 54, 45, 36, 25, 16, 7, -2, -7, -8, -3, 4, 13, 24, 32, 39, 42, 39, 30, 19, 6, -10, -25, -44, -62, -79, -88, -90, -85, -78, -70, -59, -45, -24, 0, 20, 35, 43, 48, 48, 46, 42, 33, 20, 2, -19, -32, -38, -41, -37, -29, -19, -8, 1, 11, 19, 26, 35, 43, 48, 48, 41, 35, 26, 16, 7, 0, 0, 3, 6, 10, 16, 24, 32, 40, 44, 43, 33, 21, 8, -5, -19, -37, -54, -72, -84, -87, -81, -75, -68, -61, -50, -33, -12, 8, 22, 29, 34, 40, 42, 41, 35, 24, 13, -2, -16, -27, -33, -33, -27, -22, -17, -13, -4, 9, 18, 25, 31, 36, 42, 44, 40, 32, 21, 12, 9, 7, 8, 9, 13, 17, 23, 29, 35, 40, 40, 35, 26, 13, 0, -11, -24, -41, -60, -74, -80, -79, -73, -68, -63, -56, -43, -27, -10, 6, 18, 24, 29, 34, 38, 37, 30, 20, 9, -3, -14, -24, -27, -27, -25, -23, -18, -9, 2, 10, 19, 25, 30, 37, 40, 41, 33, 22, 16, 10, 6, 6, 10, 16, 21, 28, 31, 35, 38, 44, 45, 34, 19, 5, -5, -17, -33, -52, -68, -76, -78, -75, -71, -67, -62, -51, -37, -20, -7, 4, 13, 21, 29, 34, 36, 33, 26, 17, 10, 0, -8, -13, -19, -21, -21, -17, -11, -6, 4, 10, 13, 19, 25, 30, 31, 28, 20, 14, 10, 7, 7, 11, 20, 26, 32, 36, 39, 41, 44, 46, 41, 30, 13, 0, -13, -27, -44, -62, -72, -74, -74, -74, -71, -66, -57, -47, -32, -19, -9, 2, 14, 24, 28, 32, 34, 33, 25, 17, 9, 2, -5, -10, -17, -22, -18, -13, -7, 0, 4, 10, 17, 23, 26, 25, 21, 15, 9, 9, 7, 4, 7, 16, 27, 34, 39, 43, 48, 49, 52, 49, 39, 24, 9, -3, -17, -32, -52, -67, -75, -75, -71, -70, -70, -66, -56, -43, -31, -21, -12, -2, 11, 21, 27, 30, 33, 31, 29, 22, 15, 8, 0, -6, -13, -14, -14, -11, -5, 0, 4, 8, 13, 16, 18, 15, 12, 10, 7, 7, 6, 7, 14, 24, 36, 44, 46, 46, 49, 52, 53, 47, 35, 21, 9, -6, -23, -43, -59, -68, -71, -74, -74, -76, -73, -64, -52, -39, -31, -25, -15, 0, 12, 20, 24, 29, 32, 30, 26, 21, 16, 10, 4, -2, -7, -7, -5, -3, 0, 3, 5, 6, 9, 8, 8, 6, 3, 2, 4, 5, 7, 14, 22, 34, 43, 49, 57, 57, 55, 52, 48, 43, 31, 17, 2, -13, -33, -49, -59, -63, -66, -72, -75, -76, -70, -61, -52, -44, -37, -30, -18, -4, 11, 20, 25, 28, 32, 32, 30, 26, 19, 13, 5, 0, -4, -5, -3, 1, 2, 1, -3, -2, 2, 6, 4, 2, -3, -2, 3, 10, 13, 18, 27, 40, 49, 56, 59, 60, 56, 52, 47, 41, 30, 17, 1, -19, -39, -55, -64, -67, -70, -76, -81, -78, -69, -56, -46, -40, -33, -24, -12, 3, 15, 22, 25, 26, 29, 27, 23, 19, 14, 9, 4, 0, -2, 1, 5, 9, 7, 2, -3, -3, 3, 3, -2, -10, -13, -10, -2, 7, 14, 22, 31, 45, 59, 65, 68, 65, 62, 58, 50, 41, 28, 12, -9, -31, -49, -59, -65, -70, -76, -84, -84, -77, -63, -50, -45, -40, -32, -21, -7, 7, 16, 24, 28, 29, 28, 23, 18, 15, 11, 6, 0, -4, -3, 4, 11, 14, 11, 6, 5, 7, 7, 2, -7, -12, -16, -13, -6, 1, 8, 17, 32, 50, 63, 68, 68, 69, 70, 65, 56, 43, 27, 7, -17, -38, -52, -62, -71, -78, -86, -88, -84, -73, -59, -50, -43, -34, -25, -11, 2, 11, 19, 23, 26, 26, 21, 17, 12, 9, 7, 5, 2, 2, 4, 11, 16, 14, 10, 9, 10, 9, 1, -8, -16, -19, -16, -11, -6, 0, 8, 24, 43, 57, 66, 70, 72, 72, 67, 63, 52, 37, 18, -5, -23, -41, -54, -62, -70, -78, -81, -82, -76, -67, -56, -45, -36, -31, -22, -12, 0, 10, 16, 20, 21, 17, 13, 7, 3, 3, 6, 6, 6, 9, 14, 20, 21, 20, 17, 17, 15, 9, -3, -15, -23, -27, -20, -14, -9, -4, 9, 31, 49, 64, 70, 75, 78, 76, 70, 60, 45, 31, 12, -11, -31, -46, -58, -66, -70, -73, -77, -74, -67, -59, -52, -44, -36, -29, -22, -14, -6, 1, 11, 14, 14, 11, 6, 6, 7, 10, 11, 12, 15, 18, 24, 23, 21, 19, 20, 18, 12, 0, -13, -20, -27, -27, -22, -16, -11, 1, 19, 36, 52, 64, 73, 79, 81, 77, 69, 56, 43, 26, 5, -16, -37, -54, -62, -66, -69, -72, -71, -65, -62, -56, -47, -39, -33, -26, -19, -14, -12, -3, 9, 9, 3, -6, -4, 5, 11, 12, 11, 12, 20, 29, 31, 29, 25, 25, 27, 24, 11, -6, -17, -25, -31, -32, -30, -26, -16, 0, 17, 35, 51, 66, 78, 87, 88, 84, 73, 57, 40, 23, 3, -20, -42, -57, -65, -69, -71, -70, -68, -63, -58, -52, -45, -38, -30, -26, -24, -23, -16, -8, -2, -5, -9, -6, 1, 9, 12, 13, 17, 24, 32, 37, 37, 34, 32, 33, 31, 19, 2, -15, -25, -31, -36, -38, -35, -27, -13, 4, 23, 40, 59, 76, 91, 96, 91, 80, 69, 55, 35, 13, -12, -35, -52, -61, -66, -71, -70, -63, -54, -48, -44, -42, -36, -31, -30, -34, -36, -33, -26, -20, -20, -21, -18, -9, 5, 13, 18, 21, 29, 40, 47, 50, 49, 44, 40, 34, 23, 6, -14, -27, -39, -45, -48, -45, -35, -23, -7, 11, 30, 51, 73, 89, 97, 96, 89, 80, 63, 44, 25, 4, -18, -39, -53, -59, -63, -61, -58, -55, -52, -49, -45, -39, -35, -37, -41, -46, -43, -38, -33, -29, -25, -18, -11, 3, 13, 20, 25, 30, 38, 46, 51, 50, 47, 43, 37, 26, 9, -7, -19, -32, -45, -52, -51, -40, -28, -12, 4, 19, 38, 61, 83, 94, 95, 89, 82, 67, 50, 30, 12, -8, -26, -40, -52, -57, -56, -52, -48, -46, -44, -40, -34, -32, -32, -37, -44, -47, -45, -41, -39, -35, -28, -17, -6, 7, 15, 23, 32, 40, 47, 52, 52, 51, 46, 39, 32, 17, 1, -14, -26, -37, -46, -50, -45, -35, -25, -11, 5, 24, 44, 62, 79, 88, 86, 79, 70, 59, 45, 25, 7, -13, -25, -36, -46, -50, -51, -50, -46, -43, -41, -37, -34, -33, -36, -40, -43, -46, -46, -41, -36, -31, -22, -10, 4, 13, 21, 30, 40, 47, 50, 53, 52, 47, 39, 30, 18, 3, -12, -22, -33, -42, -47, -45, -36, -25, -14, -2, 14, 34, 52, 67, 76, 77, 72, 65, 55, 43, 27, 12, -7, -21, -29, -36, -41, -44, -43, -39, -36, -32, -27, -26, -26, -29, -33, -36, -43, -49, -48, -44, -38, -32, -22, -11, 4, 15, 25, 34, 44, 50, 53, 54, 52, 44, 35, 23, 9, -4, -15, -27, -37, -43, -45, -42, -34, -21, -9, 5, 19, 34, 50, 63, 70, 69, 63, 54, 46, 35, 20, 4, -11, -23, -29, -33, -37, -41, -40, -33, -25, -20, -19, -21, -22, -23, -26, -34, -42, -47, -46, -43, -36, -30, -22, -11, 5, 17, 28, 37, 45, 52, 55, 53, 49, 41, 30, 19, 4, -12, -23, -33, -41, -45, -45, -40, -31, -18, -3, 11, 23, 38, 51, 63, 64, 58, 51, 45, 36, 25, 10, -4, -15, -24, -28, -32, -36, -35, -29, -19, -13, -13, -14, -13, -13, -13, -21, -33, -43, -45, -45, -41, -38, -34, -25, -11, 4, 17, 29, 39, 49, 57, 60, 55, 48, 39, 29, 16, 1, -14, -27, -35, -42, -47, -48, -42, -29, -15, -3, 10, 20, 34, 48, 56, 57, 51, 45, 38, 30, 20, 7, -7, -17, -22, -26, -32, -36, -31, -21, -9, -6, -8, -8, -4, 1, -4, -13, -26, -35, -39, -40, -42, -44, -40, -29, -13, 3, 16, 29, 43, 58, 67, 67, 59, 49, 39, 27, 11, -9, -28, -39, -47, -50, -53, -52, -44, -29, -12, 5, 13, 25, 38, 51, 57, 52, 45, 38, 30, 21, 9, -4, -14, -21, -26, -29, -33, -28, -18, -7, 2, 2, 2, 4, 8, 10, 5, -10, -25, -36, -42, -45, -49, -49, -45, -33, -14, 5, 22, 35, 54, 69, 78, 76, 67, 53, 41, 27, 6, -17, -36, -50, -55, -60, -63, -62, -51, -34, -16, -2, 9, 20, 34, 45, 50, 48, 42, 35, 29, 18, 7, 0, 0, 0, 0, 0, 0, 7, 0, -1, -7, -18, -16, 3, 6, -18, -29, -21, 6, 6, -12, -10, -10, -2, 4, 15, 21, 14, 4, 9, 29, 27, 15, 9, 13, 20, 0, -21, -11, 3, -11, -37, -36, -7, 11, -4, -26, -23, -4, 15, -4, -15, -11, -10, -1, 9, 23, 15, 8, 6, 24, 35, 19, 14, 6, 17, 10, -15, -26, -7, -1, -23, -40, -24, 4, 10, -16, -25, -13, 11, 10, -14, -15, -12, -6, 1, 19, 22, 6, 7, 15, 40, 31, 22, 7, 7, 15, 5, -22, -21, -5, -9, -33, -32, -15, 5, -4, -19, -20, 1, 17, -4, -15, -11, -12, -4, 9, 27, 13, 7, 11, 32, 44, 30, 14, 2, 7, 9, -8, -25, -18, -9, -19, -30, -21, -4, 2, -10, -21, -13, 15, 8, -11, -13, -16, -12, 0, 20, 24, 9, 9, 19, 44, 47, 25, 6, 2, 11, -1, -21, -27, -19, -17, -20, -23, -17, -5, -5, -14, -20, 0, 15, -4, -7, -17, -17, -8, 7, 25, 18, 7, 11, 31, 54, 41, 14, -1, 10, 3, -14, -27, -29, -21, -16, -16, -18, -17, -11, -10, -16, -16, 10, 6, -3, -9, -19, -16, -2, 18, 27, 16, 8, 19, 45, 54, 29, 5, 6, 4, -9, -18, -29, -30, -18, -10, -9, -14, -20, -12, -13, -17, -5, 12, 7, 2, -16, -22, -13, 8, 25, 23, 12, 11, 32, 53, 48, 17, 9, 9, -7, -16, -24, -37, -28, -12, -4, -2, -18, -21, -18, -23, -17, 7, 11, 10, -4, -16, -22, -7, 21, 28, 18, 9, 20, 43, 55, 37, 11, 11, 1, -14, -17, -31, -34, -21, -10, 4, -2, -20, -23, -26, -29, -3, 6, 13, 8, -5, -23, -27, 7, 28, 27, 15, 12, 32, 48, 50, 24, 9, 8, -12, -19, -26, -37, -35, -19, 3, 6, -12, -21, -31, -38, -17, 6, 4, 14, 6, -8, -35, -15, 19, 26, 21, 7, 23, 43, 52, 42, 14, 9, -2, -16, -21, -25, -33, -33, -4, 13, 3, -13, -30, -47, -37, 1, 6, 7, 12, 6, -15, -31, -1, 22, 30, 14, 9, 37, 48, 50, 26, 8, 6, -11, -22, -22, -25, -45, -22, 13, 15, 1, -22, -43, -56, -21, 7, 6, 10, 15, -7, -25, -21, 7, 28, 21, 2, 25, 47, 53, 39, 11, 10, 1, -20, -22, -18, -37, -42, 2, 15, 15, -8, -32, -57, -48, -9, 9, 5, 14, 8, -14, -20, -13, 17, 33, 8, 9, 37, 52, 55, 25, 7, 8, -11, -23, -15, -23, -47, -20, 12, 21, 10, -23, -50, -57, -31, 2, 10, 9, 11, -8, -10, -18, -3, 30, 22, 1, 22, 45, 57, 45, 11, 11, 0, -23, -22, -16, -36, -36, -6, 15, 18, -3, -43, -56, -49, -21, 5, 11, 12, -2, -8, -9, -15, 12, 31, 9, 10, 34, 48, 60, 29, 16, 10, -17, -24, -21, -27, -31, -17, 5, 14, 12, -22, -50, -48, -41, -9, 7, 13, -1, -8, -2, -11, -5, 26, 19, 6, 21, 37, 55, 49, 25, 22, -5, -20, -24, -26, -29, -23, -9, 8, 13, -1, -41, -48, -47, -30, -3, 12, 7, -12, -2, 1, -8, 10, 20, 11, 16, 26, 40, 54, 42, 36, 7, -13, -18, -26, -29, -26, -14, -2, 7, 8, -18, -45, -48, -45, -19, 6, 11, -10, -8, 5, -7, 2, 12, 17, 15, 16, 23, 45, 55, 48, 27, -7, -12, -18, -30, -31, -17, -5, -3, 4, 5, -24, -40, -50, -38, -8, 8, 1, -13, 1, -1, 3, 8, 15, 18, 15, 15, 28, 52, 59, 47, 9, -9, -10, -25, -40, -29, -3, -5, -13, 1, 3, -26, -47, -53, -23, -2, 5, -11, -6, 4, 6, 10, 10, 19, 11, 13, 15, 42, 61, 61, 32, 3, -5, -12, -35, -43, -14, 1, -16, -13, 9, -1, -33, -57, -46, -19, -3, -1, -16, -2, 5, 15, 6, 17, 9, 5, 9, 26, 54, 65, 52, 21, 3, -6, -21, -48, -33, -4, -7, -22, -2, 18, -4, -47, -58, -33, -11, 2, -13, -15, 3, 16, 15, 9, 15, -1, 5, 14, 48, 66, 65, 37, 23, 2, -11, -42, -48, -20, -4, -23, -18, 18, 19, -17, -61, -52, -27, -2, -5, -24, -7, 9, 20, 14, 18, 2, -3, 7, 34, 63, 68, 50, 37, 19, -9, -25, -49, -38, -14, -14, -28, 6, 25, 9, -40, -62, -45, -17, 3, -21, -16, -3, 12, 18, 18, 10, -6, 0, 16, 56, 69, 63, 43, 38, 2, -20, -42, -44, -33, -14, -25, -10, 22, 18, -11, -55, -57, -37, -3, -10, -26, -10, 2, 17, 21, 20, -3, -2, 5, 39, 67, 73, 56, 47, 22, -17, -35, -43, -36, -28, -18, -20, 9, 22, 8, -33, -56, -53, -26, -2, -23, -24, -11, 4, 23, 30, 4, -3, 0, 27, 60, 71, 69, 58, 43, -6, -35, -43, -35, -36, -27, -18, -2, 19, 17, -9, -41, -51, -45, -10, -12, -31, -21, -9, 8, 33, 17, 0, 2, 8, 50, 69, 75, 70, 64, 16, -31, -47, -35, -32, -34, -25, -14, 10, 16, 5, -26, -42, -50, -32, -8, -22, -31, -22, -8, 22, 32, 7, 6, 4, 28, 63, 69, 71, 78, 43, -20, -51, -41, -23, -34, -30, -22, 2, 13, 9, -10, -31, -45, -44, -21, -19, -27, -36, -26, 2, 29, 24, 12, 11, 13, 45, 69, 68, 81, 70, 6, -47, -52, -28, -23, -27, -26, -14, 11, 10, -2, -18, -33, -43, -34, -25, -22, -36, -44, -14, 14, 29, 27, 22, 18, 29, 60, 65, 71, 86, 41, -32, -57, -41, -23, -22, -22, -24, -4, 10, 0, -11, -21, -31, -37, -37, -29, -29, -53, -33, -3, 16, 33, 31, 27, 23, 46, 64, 65, 85, 71, -4, -48, -47, -31, -20, -15, -15, -19, 1, 0, -5, -14, -21, -26, -40, -39, -28, -51, -50, -18, 4, 26, 38, 36, 30, 32, 61, 64, 70, 80, 31, -35, -43, -40, -25, -19, -6, -17, -11, 0, -6, -11, -17, -15, -31, -47, -39, -45, -62, -34, -8, 12, 36, 38, 41, 37, 51, 65, 60, 71, 56, -7, -36, -38, -35, -27, -11, -5, -17, -8, -8, -9, -17, -13, -20, -37, -47, -50, -62, -49, -16, 1, 25, 34, 43, 53, 49, 62, 58, 62, 65, 22, -23, -31, -34, -35, -19, -3, -8, -18, -7, -4, -14, -17, -9, -27, -40, -56, -68, -64, -27, -4, 9, 28, 37, 54, 60, 61, 59, 54, 63, 43, -1, -25, -23, -37, -28, -8, 4, -10, -15, -3, -7, -26, -15, -11, -29, -51, -71, -71, -49, -8, 5, 14, 30, 48, 66, 68, 63, 51, 56, 51, 18, -18, -20, -25, -39, -23, -5, 3, -13, -6, -5, -21, -28, -10, -18, -43, -67, -78, -64, -25, 1, 8, 15, 38, 60, 75, 74, 58, 54, 57, 28, -7, -18, -8, -31, -34, -15, 4, -2, -4, 0, -15, -32, -21, -8, -28, -57, -77, -75, -44, -12, 6, 8, 20, 49, 68, 77, 71, 53, 61, 41, 3, -18, -4, -14, -36, -28, -7, 1, 7, 6, -8, -34, -35, -16, -15, -41, -66, -75, -59, -31, -4, 10, 11, 31, 56, 72, 85, 63, 58, 55, 14, -17, -10, -1, -24, -30, -22, -6, 11, 16, 9, -27, -43, -27, -15, -26, -53, -63, -66, -46, -21, 3, 13, 15, 40, 63, 83, 78, 60, 67, 38, -9, -20, 4, -7, -23, -25, -22, 6, 24, 20, -8, -48, -43, -24, -16, -39, -55, -57, -57, -36, -10, 9, 11, 22, 50, 73, 88, 71, 65, 59, 14, -24, -9, -3, -15, -18, -31, -14, 25, 28, 10, -36, -56, -41, -21, -29, -48, -47, -51, -50, -26, -2, 11, 6, 30, 57, 82, 83, 69, 65, 35, -12, -16, -3, -10, -12, -21, -26, 11, 33, 26, -7, -56, -54, -32, -26, -41, -39, -37, -52, -41, -16, 5, 7, 11, 37, 72, 91, 78, 66, 55, 11, -19, -14, -15, -9, -7, -19, -8, 22, 30, 13, -32, -62, -44, -31, -34, -40, -29, -40, -46, -29, -8, 2, 1, 18, 49, 84, 86, 72, 67, 39, -6, -21, -25, -16, 2, -6, -12, 6, 23, 18, -7, -51, -56, -39, -33, -41, -30, -24, -41, -36, -17, -8, -5, 7, 32, 66, 84, 78, 75, 58, 20, -15, -29, -33, 2, 4, -1, 1, 11, 17, 4, -27, -56, -46, -36, -37, -39, -22, -24, -38, -23, -16, -16, -7, 18, 46, 72, 82, 81, 72, 44, -1, -25, -41, -18, 14, 8, 10, 0, 5, 2, -11, -40, -50, -42, -38, -37, -33, -11, -27, -26, -20, -22, -13, 0, 31, 52, 73, 82, 80, 61, 26, -16, -37, -40, 0, 18, 17, 12, -5, -8, -10, -21, -41, -43, -44, -36, -35, -20, -12, -23, -14, -32, -21, -12, 15, 38, 58, 76, 82, 72, 46, 4, -26, -41, -23, 14, 25, 18, 2, -23, -18, -14, -29, -35, -45, -42, -35, -29, -15, -19, -3, -23, -32, -19, -1, 27, 40, 67, 81, 76, 61, 26, -11, -33, -36, -6, 28, 28, 13, -15, -38, -19, -20, -26, -36, -46, -35, -32, -20, -21, -4, -4, -28, -25, -16, 13, 31, 49, 74, 79, 69, 48, 8, -16, -33, -21, 7, 33, 24, 5, -32, -38, -22, -21, -22, -41, -43, -32, -25, -23, -16, 6, -9, -29, -28, -5, 20, 39, 58, 75, 71, 60, 22, 0, -18, -27, -10, 16, 30, 15, -14, -49, -34, -19, -16, -27, -43, -31, -25, -27, -24, -1, 7, -15, -32, -22, 3, 28, 50, 61, 67, 59, 38, 13, 5, -17, -16, -3, 21, 23, 3, -34, -49, -28, -17, -19, -34, -34, -18, -26, -32, -16, 14, 6, -23, -34, -11, 14, 44, 54, 56, 60, 44, 25, 18, 2, -18, -9, 3, 21, 9, -14, -45, -39, -24, -22, -28, -32, -18, -17, -36, -30, 5, 21, -5, -31, -27, 1, 30, 56, 46, 50, 47, 32, 29, 20, -4, -9, -9, 4, 10, -2, -28, -38, -31, -33, -26, -26, -19, -9, -24, -38, -11, 24, 10, -17, -36, -14, 14, 48, 49, 37, 43, 39, 33, 32, 11, 1, -5, -11, -6, -3, -16, -29, -28, -40, -38, -27, -20, -6, -11, -31, -29, 15, 22, 0, -25, -25, 2, 31, 51, 38, 35, 41, 41, 34, 27, 8, 6, -7, -20, -14, -7, -20, -19, -34, -52, -35, -23, -11, -5, -18, -33, -5, 26, 5, -11, -27, -11, 17, 43, 43, 30, 29, 46, 45, 38, 17, 6, 2, -22, -27, -16, -16, -18, -18, -53, -48, -23, -19, -3, -10, -21, -19, 18, 12, -6, -20, -21, 6, 29, 42, 31, 23, 37, 54, 48, 31, 13, 13, -13, -31, -25, -16, -16, -11, -38, -62, -33, -28, -7, -3, -12, -17, 6, 16, 2, -11, -17, -5, 15, 35, 34, 25, 23, 44, 55, 41, 22, 14, 2, -29, -32, -23, -11, -13, -18, -60, -50, -32, -16, -6, -11, -4, 3, 11, 3, -1, -14, -8, 5, 20, 39, 31, 24, 26, 54, 57, 37, 16, 8, -19, -32, -27, -17, -17, -17, -36, -58, -40, -32, -11, -11, -2, 6, 10, 2, 0, -4, -12, 1, 8, 33, 42, 26, 17, 35, 63, 53, 26, 6, -9, -27, -30, -25, -17, -23, -24, -47, -51, -38, -17, -11, -6, 12, 17, 8, -8, -1, -10, -7, 4, 18, 40, 33, 18, 22, 49, 70, 46, 12, -11, -16, -23, -27, -19, -28, -26, -36, -50, -48, -31, -13, -13, 10, 20, 21, 0, -6, -1, -7, 3, 15, 32, 40, 24, 17, 31, 58, 67, 28, -2, -21, -14, -31, -18, -24, -33, -33, -49, -49, -41, -18, -20, -2, 20, 23, 19, -12, -7, -2, -3, 10, 22, 33, 37, 21, 23, 39, 72, 51, 10, -17, -18, -20, -29, -17, -33, -36, -49, -48, -47, -24, -16, -15, 11, 24, 30, 6, -12, -2, -2, -1, 18, 29, 35, 27, 25, 25, 56, 63, 23, -5, -19, -14, -23, -21, -21, -38, -52, -54, -40, -32, -15, -23, -7, 18, 31, 22, -2, -7, 3, 0, 12, 21, 34, 31, 28, 22, 35, 66, 40, 2, -19, -19, -15, -21, -16, -30, -60, -62, -42, -33, -18, -18, -22, 4, 29, 29, 14, -2, -4, 5, 6, 16, 28, 36, 24, 29, 26, 52, 49, 14, -13, -24, -19, -14, -15, -17, -53, -75, -54, -32, -18, -11, -26, -18, 18, 28, 25, 13, -6, 4, 13, 9, 17, 37, 24, 28, 33, 37, 49, 26, 1, -19, -26, -16, -11, -7, -33, -77, -71, -45, -15, -8, -18, -30, 1, 25, 21, 26, 3, 5, 17, 14, 11, 33, 27, 17, 34, 38, 42, 33, 6, -11, -28, -22, -12, -3, -16, -60, -81, -62, -25, -2, -14, -27, -17, 20, 18, 24, 18, 6, 16, 21, 12, 24, 28, 12, 26, 44, 42, 35, 13, -5, -21, -31, -18, -2, -2, -42, -77, -76, -47, -10, -6, -22, -24, 4, 16, 18, 25, 18, 18, 24, 20, 20, 32, 14, 11, 40, 49, 41, 21, -6, -13, -27, -28, -5, 5, -18, -59, -79, -63, -30, -6, -11, -28, -11, 8, 10, 23, 27, 17, 24, 25, 25, 28, 19, 8, 25, 47, 46, 27, -5, -15, -18, -33, -20, -5, -3, -35, -70, -66, -51, -22, -7, -21, -19, -3, 6, 17, 29, 26, 23, 28, 25, 32, 23, 14, 11, 39, 50, 38, 3, -19, -10, -21, -29, -12, -3, -12, -55, -65, -56, -42, -14, -10, -23, -11, -3, 10, 23, 32, 26, 28, 28, 35, 29, 22, 13, 18, 41, 43, 18, -16, -18, -14, -29, -21, -11, -8, -32, -61, -52, -52, -30, -11, -18, -16, -10, 2, 22, 35, 30, 25, 32, 34, 40, 27, 19, 11, 23, 39, 32, -1, -22, -14, -22, -23, -14, -11, -17, -45, -52, -51, -51, -22, -17, -19, -17, -10, 11, 35, 39, 29, 26, 34, 43, 43, 27, 16, 12, 25, 31, 18, -13, -20, -19, -22, -12, -14, -15, -28, -44, -47, -53, -33, -15, -22, -24, -20, 5, 27, 38, 31, 21, 27, 46, 51, 40, 18, 8, 13, 23, 24, 3, -21, -22, -22, -8, -9, -22, -26, -31, -40, -51, -44, -17, -15, -26, -31, -10, 24, 35, 37, 25, 21, 42, 57, 53, 30, 11, 7, 11, 21, 12, -11, -23, -25, -12, 0, -18, -32, -31, -30, -45, -46, -26, -13, -25, -39, -25, 15, 36, 29, 25, 20, 37, 58, 63, 46, 15, 3, -2, 19, 16, -2, -19, -25, -23, 4, -4, -31, -36, -29, -32, -43, -37, -17, -16, -39, -43, -2, 34, 31, 21, 17, 30, 62, 67, 62, 27, 9, -9, 3, 26, 8, -18, -26, -26, -5, 9, -23, -44, -33, -26, -33, -40, -28, -12, -30, -52, -24, 23, 33, 15, 14, 22, 54, 75, 68, 47, 14, -9, -12, 19, 23, -12, -20, -20, -13, 11, -6, -40, -41, -19, -23, -34, -34, -14, -13, -48, -48, 4, 35, 23, 7, 13, 40, 77, 78, 57, 31, -3, -18, 3, 27, 7, -24, -19, -16, 1, 5, -29, -49, -28, -13, -26, -34, -26, -4, -30, -57, -24, 22, 30, 6, 7, 31, 63, 86, 68, 42, 10, -19, -13, 15, 25, -10, -22, -14, -7, 6, -11, -45, -40, -14, -24, -35, -31, -12, -8, -51, -44, -2, 29, 11, -1, 22, 47, 74, 78, 49, 25, -8, -26, -4, 26, 12, -16, -19, -11, -1, -1, -28, -45, -22, -13, -29, -29, -23, -1, -26, -55, -26, 14, 20, -3, 13, 39, 63, 80, 61, 33, 8, -22, -25, 10, 22, -1, -14, -15, -7, -1, -14, -37, -26, -13, -25, -28, -26, -2, -5, -48, -44, -7, 18, 3, 9, 30, 49, 71, 70, 45, 23, -13, -33, -5, 22, 11, -7, -17, -14, -6, -8, -29, -29, -15, -19, -26, -31, -15, 6, -25, -52, -30, 7, 7, 2, 21, 40, 60, 67, 52, 33, 7, -29, -19, 16, 22, 4, -8, -15, -11, -6, -23, -24, -10, -11, -23, -27, -22, 1, 0, -34, -45, -14, 2, 1, 15, 35, 52, 62, 49, 36, 21, -16, -26, 1, 20, 12, -7, -10, -20, -10, -19, -28, -9, -8, -15, -26, -27, -11, 2, -15, -41, -34, -10, -7, 6, 32, 48, 56, 51, 35, 26, 1, -24, -10, 15, 18, 2, -9, -17, -18, -11, -32, -6, 2, -9, -18, -22, -17, -3, -2, -21, -34, -26, -13, -8, 20, 47, 53, 52, 38, 24, 5, -14, -15, 9, 14, 4, -6, -14, -21, -14, -28, -22, 12, 0, -10, -23, -24, -13, 2, -10, -23, -34, -26, -13, 4, 39, 58, 51, 45, 28, 6, -9, -11, 3, 17, 7, -3, -10, -18, -15, -22, -35, 2, 18, 2, -11, -23, -20, -1, 0, -15, -24, -39, -25, -6, 17, 52, 56, 47, 35, 6, -10, -8, 0, 13, 13, -2, -9, -13, -13, -25, -43, -16, 21, 19, -3, -21, -25, -10, 2, -5, -14, -30, -40, -13, -1, 34, 58, 51, 44, 18, -10, -9, -2, 6, 12, 7, -7, -12, -12, -18, -40, -33, 9, 32, 19, -9, -23, -15, 1, 3, -9, -18, -40, -28, -4, 7, 47, 59, 49, 24, 1, -13, -5, 1, 10, 11, 5, -12, -12, -15, -35, -42, -9, 23, 33, 9, -22, -24, -5, 1, -5, -12, -30, -40, -7, -3, 22, 56, 58, 35, 11, -12, -9, -5, -1, 7, 13, -4, -13, -13, -25, -43, -29, 10, 34, 32, -6, -27, -8, 3, -5, -13, -22, -40, -18, -3, -1, 37, 61, 46, 23, -5, -13, -4, -4, -7, 12, 14, -10, -18, -22, -34, -35, -10, 22, 39, 23, -15, -14, 5, 3, -8, -15, -36, -23, -1, -7, 14, 51, 57, 37, 8, -13, -7, -2, -14, -6, 20, 3, -21, -26, -27, -30, -27, 1, 28, 36, 7, -10, 0, 5, -8, -14, -30, -29, -3, -10, -5, 31, 56, 46, 19, -7, -10, 3, -11, -21, 9, 19, -10, -30, -29, -19, -24, -20, 10, 35, 29, 8, -1, 5, -2, -13, -28, -33, -3, -1, -13, 12, 49, 55, 31, -1, -12, 2, -3, -26, -2, 21, 2, -28, -34, -21, -17, -29, -12, 23, 34, 19, 6, 7, 4, -4, -23, -40, -10, 7, -12, -2, 34, 55, 36, 8, -10, 1, 3, -19, -18, 15, 15, -10, -33, -30, -9, -19, -25, 4, 32, 30, 16, 11, 10, 3, -15, -35, -27, 9, -4, -10, 16, 52, 42, 12, -7, -6, 4, -6, -21, -2, 17, 0, -20, -41, -13, -9, -31, -16, 18, 34, 23, 14, 9, 10, -7, -26, -34, -3, 10, -10, 2, 42, 51, 16, -8, -11, -2, -2, -11, -9, 9, 2, -8, -36, -31, 3, -23, -30, -1, 27, 27, 23, 15, 18, 3, -17, -31, -19, 8, 1, -4, 24, 51, 30, -11, -16, -6, -3, -5, -10, 3, 1, -10, -22, -41, -4, -6, -29, -18, 12, 25, 26, 23, 20, 11, -10, -21, -27, -4, 7, 0, 13, 41, 40, 3, -24, -11, -1, -2, -3, 5, 5, -14, -15, -35, -20, 0, -19, -24, -4, 11, 23, 31, 24, 16, -3, -13, -23, -14, 2, 3, 18, 32, 38, 21, -20, -29, -5, -2, 0, 5, 11, -14, -22, -25, -26, -3, -11, -26, -11, -2, 8, 32, 34, 24, 2, -8, -16, -13, 1, 1, 10, 31, 31, 33, 1, -36, -22, 0, 0, 8, 18, -3, -27, -22, -22, -10, -9, -24, -16, -5, -16, 16, 40, 34, 8, -3, -13, -12, 1, 1, 3, 30, 30, 24, 18, -28, -35, -13, -2, 6, 19, 10, -25, -28, -15, -9, -10, -19, -20, -3, -15, -8, 27, 42, 25, 1, -14, -18, 7, 9, -1, 19, 37, 19, 23, -10, -41, -26, -9, 2, 20, 19, -17, -35, -21, 0, -9, -18, -20, -7, -8, -24, 6, 37, 43, 14, -10, -22, 3, 18, 4, 6, 36, 23, 16, 4, -32, -37, -19, -3, 17, 27, 0, -37, -34, -3, 7, -17, -27, -19, -1, -20, -13, 17, 44, 35, 2, -22, -9, 19, 20, 2, 26, 32, 15, 5, -17, -40, -29, -9, 10, 28, 17, -23, -41, -21, 9, -2, -27, -30, -5, -7, -21, -4, 27, 47, 27, -14, -21, 11, 29, 14, 15, 32, 20, 4, -11, -31, -38, -15, 2, 22, 22, -3, -32, -34, -6, 8, -13, -38, -19, 0, -16, -14, 6, 37, 39, 11, -18, -4, 25, 25, 16, 24, 27, 7, -10, -24, -38, -25, 0, 12, 23, 8, -16, -31, -23, 0, 0, -27, -33, -2, -9, -16, -11, 17, 41, 32, 5, -15, 12, 25, 24, 21, 27, 14, -4, -21, -31, -29, -4, 9, 19, 9, -9, -19, -25, -10, -5, -15, -38, -13, -6, -13, -17, -1, 30, 36, 27, -2, 2, 20, 24, 25, 24, 19, 2, -16, -32, -29, -13, 8, 18, 16, -6, -13, -21, -15, -14, -13, -26, -22, -6, -11, -14, -14, 11, 30, 37, 17, 1, 13, 20, 23, 24, 21, 5, -10, -32, -31, -15, 0, 17, 22, -3, -15, -17, -11, -15, -19, -23, -22, -8, -8, -13, -18, -8, 18, 40, 38, 12, 12, 15, 21, 23, 24, 7, -9, -22, -34, -19, -6, 11, 30, 9, -17, -20, -16, -11, -22, -30, -27, -8, -7, -10, -19, -16, -2, 32, 52, 31, 17, 16, 13, 21, 19, 19, -9, -17, -30, -25, -7, 3, 29, 25, -9, -21, -20, -11, -14, -29, -37, -14, 2, -5, -14, -22, -12, 13, 50, 49, 27, 23, 15, 13, 9, 18, 7, -22, -22, -28, -11, -5, 19, 35, 13, -20, -24, -18, -8, -22, -38, -31, 2, 3, -6, -26, -22, -3, 38, 56, 42, 34, 21, 12, 6, 11, 17, -15, -24, -20, -15, -6, 9, 29, 29, -4, -28, -23, -14, -13, -30, -39, -16, 9, 6, -12, -33, -16, 19, 57, 49, 41, 30, 13, 4, -1, 6, -4, -27, -21, -13, -6, 2, 12, 34, 12, -24, -24, -20, -16, -24, -38, -33, 2, 12, -2, -30, -31, 2, 45, 59, 46, 41, 24, 8, -3, -6, 1, -15, -25, -16, -3, 5, 2, 21, 28, -11, -26, -23, -18, -20, -32, -40, -14, 14, 11, -10, -40, -20, 30, 60, 55, 42, 34, 15, 6, -12, -12, -4, -19, -21, -9, 8, 4, 10, 28, 6, -25, -22, -20, -22, -29, -38, -27, 5, 16, 4, -24, -39, 12, 51, 61, 51, 41, 27, 10, -7, -25, -9, -10, -17, -15, 0, 9, 5, 21, 15, -13, -27, -17, -21, -23, -38, -33, -11, 10, 6, -4, -38, -17, 36, 55, 55, 45, 35, 21, 4, -27, -25, -2, -10, -14, -13, 3, 5, 14, 16, 0, -24, -21, -18, -22, -36, -39, -17, -3, 5, 3, -15, -28, 16, 50, 53, 52, 43, 29, 13, -14, -36, -10, -1, -15, -15, -6, 6, 5, 13, 4, -11, -24, -17, -18, -27, -43, -18, -12, -7, 4, 3, -17, -4, 38, 53, 52, 48, 41, 23, 0, -31, -30, 2, -7, -14, -13, -5, 3, 11, 7, -4, -21, -25, -21, -19, -39, -23, -9, -19, -8, 5, -1, -10, 24, 46, 48, 46, 44, 32, 10, -18, -37, -7, 0, -12, -14, -13, -4, 8, 9, 1, -16, -29, -28, -17, -33, -31, -6, -21, -21, -4, 12, 3, 13, 41, 46, 44, 46, 44, 20, -7, -36, -27, 6, -3, -18, -21, -12, 2, 12, 6, -5, -27, -36, -21, -20, -34, -12, -8, -29, -16, 11, 15, 10, 28, 47, 46, 41, 45, 35, 5, -24, -30, -5, 3, -14, -26, -16, -7, 7, 8, -3, -18, -39, -32, -16, -28, -26, -8, -23, -26, 0, 19, 16, 20, 42, 55, 45, 38, 39, 20, -11, -24, -13, -2, -6, -25, -22, -7, -5, 13, 0, -11, -36, -41, -20, -16, -29, -16, -14, -28, -12, 13, 17, 15, 32, 50, 57, 41, 38, 30, 2, -14, -9, -3, -3, -19, -33, -10, -7, 7, 7, -13, -30, -42, -28, -13, -17, -26, -14, -22, -15, 7, 19, 15, 26, 46, 59, 51, 34, 33, 12, -7, -11, -4, -5, -13, -38, -23, -3, 3, 15, -7, -32, -45, -34, -21, -11, -27, -25, -21, -19, -1, 13, 15, 22, 37, 53, 62, 46, 34, 15, -2, 0, -4, -8, -9, -34, -38, -8, 4, 17, 3, -25, -50, -44, -26, -12, -13, -32, -24, -20, -7, 11, 18, 17, 33, 50, 65, 57, 41, 24, 0, 5, 5, -9, -11, -25, -44, -25, -1, 17, 13, -18, -42, -51, -33, -20, -7, -27, -29, -23, -16, 0, 14, 14, 28, 48, 60, 66, 51, 34, 4, 0, 15, -3, -14, -20, -35, -37, -12, 12, 27, -7, -37, -50, -40, -29, -15, -15, -30, -24, -15, -7, 6, 17, 25, 46, 59, 68, 63, 43, 20, -6, 14, 10, -8, -20, -30, -34, -22, -2, 24, 15, -30, -49, -49, -37, -28, -15, -26, -28, -18, -11, -7, 7, 27, 42, 58, 70, 70, 53, 35, 4, 0, 18, -1, -15, -32, -31, -26, -12, 12, 28, -4, -44, -53, -44, -39, -25, -23, -28, -19, -11, -12, -16, 13, 42, 56, 71, 71, 57, 45, 23, -3, 10, 11, -6, -27, -35, -25, -22, -1, 23, 17, -29, -54, -46, -44, -39, -29, -28, -21, -15, -15, -26, -12, 39, 57, 70, 73, 60, 49, 41, 13, 1, 11, 0, -16, -32, -25, -15, -14, 10, 23, -5, -48, -46, -42, -49, -43, -31, -24, -15, -13, -24, -32, 18, 59, 71, 77, 67, 57, 47, 33, 3, 5, 5, -9, -23, -33, -16, -14, -5, 17, 12, -29, -44, -35, -50, -57, -43, -30, -18, -11, -22, -39, -9, 44, 68, 82, 69, 61, 49, 42, 18, 5, 5, -8, -12, -26, -14, -7, -9, 5, 16, -6, -36, -32, -42, -62, -55, -39, -29, -15, -14, -34, -30, 20, 59, 82, 79, 66, 58, 45, 38, 9, 1, -7, -11, -16, -19, -3, -6, -6, 9, 5, -22, -32, -32, -58, -70, -56, -42, -24, -16, -25, -39, -9, 41, 72, 86, 73, 65, 46, 40, 30, -4, -7, -14, -12, -20, -3, 4, -5, 1, 8, -9, -27, -25, -40, -67, -67, -55, -38, -24, -17, -25, -28, 16, 61, 81, 82, 71, 60, 37, 42, 17, -14, -17, -11, -13, -8, 10, 2, -2, 1, -1, -17, -20, -26, -54, -69, -70, -58, -34, -25, -16, -23, -9, 37, 70, 87, 80, 68, 44, 38, 39, -5, -27, -19, -12, -6, 13, 10, 4, 1, 1, -5, -19, -20, -37, -59, -71, -71, -54, -35, -17, -9, -20, 11, 49, 80, 86, 72, 54, 36, 45, 23, -25, -34, -16, -9, 11, 17, 8, 5, -4, -2, -15, -19, -26, -50, -69, -77, -71, -51, -29, -7, -11, -6, 26, 64, 87, 78, 60, 40, 42, 45, 2, -38, -34, -12, 10, 24, 10, 11, 3, -1, -6, -20, -16, -31, -61, -81, -80, -69, -41, -16, -5, -8, 10, 47, 81, 86, 70, 44, 36, 48, 32, -21, -48, -31, -3, 24, 24, 10, 15, 0, 2, -17, -21, -18, -45, -81, -87, -80, -57, -33, -11, -6, 2, 30, 74, 86, 77, 55, 34, 42, 48, 13, -39, -50, -20, 15, 34, 14, 16, 12, 4, -5, -26, -16, -19, -64, -92, -91, -65, -43, -26, -12, -1, 16, 47, 83, 76, 66, 40, 33, 45, 33, -8, -52, -41, -5, 32, 30, 15, 25, 13, 8, -22, -28, -11, -34, -85, -101, -86, -52, -36, -25, -13, 15, 32, 69, 80, 69, 52, 32, 37, 39, 19, -30, -54, -24, 10, 38, 25, 25, 22, 18, -6, -35, -20, -14, -59, -98, -99, -68, -41, -30, -23, 5, 28, 52, 74, 67, 59, 43, 32, 35, 32, -2, -47, -38, -13, 23, 33, 31, 26, 27, 16, -29, -37, -15, -33, -80, -104, -89, -54, -35, -31, -11, 17, 42, 63, 68, 60, 59, 37, 27, 33, 22, -28, -37, -26, 3, 32, 38, 30, 25, 30, -3, -41, -29, -23, -55, -90, -98, -76, -39, -32, -21, 4, 36, 52, 61, 61, 63, 48, 24, 28, 34, -10, -31, -29, -14, 15, 37, 37, 28, 31, 19, -27, -40, -24, -38, -69, -95, -96, -60, -32, -26, -10, 19, 45, 53, 58, 59, 58, 29, 23, 39, 14, -21, -25, -23, 1, 27, 43, 34, 34, 21, 0, -36, -32, -31, -49, -84, -102, -83, -41, -22, -19, -1, 35, 49, 52, 53, 56, 39, 23, 34, 33, -3, -23, -22, -10, 17, 36, 36, 39, 26, 8, -16, -34, -29, -36, -61, -93, -95, -58, -26, -18, -11, 22, 48, 53, 53, 51, 41, 31, 33, 37, 16, -15, -24, -14, 4, 29, 34, 41, 32, 8, -7, -19, -28, -30, -54, -83, -101, -76, -40, -20, -21, 1, 36, 54, 55, 44, 33, 32, 35, 36, 30, 7, -26, -19, -5, 22, 36, 37, 37, 15, -3, -5, -15, -24, -43, -75, -94, -87, -47, -29, -25, -14, 26, 48, 62, 49, 29, 23, 35, 45, 38, 19, -16, -28, -7, 10, 29, 32, 38, 23, -2, -10, -6, -12, -28, -67, -90, -98, -59, -32, -28, -25, 3, 43, 56, 59, 25, 16, 24, 46, 43, 31, 0, -31, -14, 5, 25, 29, 32, 29, 6, -13, -6, -3, -8, -49, -85, -97, -75, -31, -30, -30, -12, 31, 50, 61, 40, 12, 14, 34, 53, 43, 20, -23, -20, -3, 21, 29, 23, 24, 15, -10, -8, -1, 2, -25, -75, -98, -92, -42, -31, -35, -24, 14, 41, 50, 49, 22, 11, 20, 45, 52, 39, 0, -26, -12, 9, 35, 25, 18, 14, 1, -13, -6, 4, 3, -49, -89, -102, -61, -27, -30, -27, -4, 34, 46, 46, 32, 17, 13, 26, 47, 50, 29, -19, -22, -4, 30, 37, 15, 7, 7, -5, -10, -4, 9, -20, -72, -100, -86, -41, -33, -31, -16, 18, 43, 34, 32, 27, 23, 15, 31, 47, 48, 9, -24, -16, 12, 43, 25, -2, 0, 9, -9, -15, 2, 8, -40, -87, -99, -69, -37, -31, -19, 6, 38, 35, 25, 31, 35, 26, 18, 36, 49, 40, -10, -22, -9, 29, 40, 6, -12, 6, 6, -16, -11, 9, -6, -61, -95, -90, -58, -35, -26, -5, 23, 36, 18, 21, 36, 41, 28, 22, 38, 52, 23, -17, -17, 7, 39, 21, -12, -13, 16, -8, -22, -5, 6, -25, -77, -93, -79, -46, -30, -11, 15, 36, 22, 5, 29, 47, 47, 24, 22, 41, 48, 7, -15, -4, 22, 33, 6, -23, 4, 8, -21, -15, -1, -5, -49, -79, -92, -71, -43, -20, 11, 31, 29, 4, 16, 40, 55, 41, 22, 31, 50, 25, -9, -2, 8, 23, 16, -17, -6, 8, -10, -15, -6, -4, -29, -56, -80, -86, -61, -42, 0, 30, 33, 12, 2, 24, 47, 55, 37, 28, 39, 40, 4, -1, 6, 6, 16, -4, -13, 1, -2, -9, -11, -11, -21, -35, -55, -82, -80, -64, -24, 27, 36, 23, 3, 10, 35, 61, 55, 40, 35, 35, 19, 6, 12, 4, 1, 3, -12, -3, -2, -4, -4, -14, -23, -30, -37, -58, -83, -84, -58, 8, 37, 33, 11, 3, 20, 46, 62, 55, 50, 28, 16, 12, 15, 9, -4, -9, -9, -4, -5, -7, 2, -7, -28, -35, -31, -36, -67, -90, -86, -23, 28, 38, 25, 5, 13, 34, 58, 58, 69, 50, 15, 10, 20, 16, -3, -14, -14, -2, 1, -12, -3, 3, -20, -36, -39, -26, -46, -81, -98, -61, 6, 27, 30, 16, 12, 25, 50, 57, 66, 74, 31, 4, 16, 21, 8, -13, -21, -10, 8, -5, -11, 6, -8, -31, -40, -29, -30, -66, -93, -84, -22, 17, 22, 26, 16, 20, 43, 56, 56, 70, 60, 17, 8, 18, 15, -10, -26, -21, 6, 7, -12, -1, 1, -20, -33, -34, -31, -51, -79, -92, -52, -6, 9, 19, 23, 21, 40, 57, 59, 60, 72, 43, 17, 13, 18, 3, -23, -32, -5, 14, -7, -11, 7, -12, -26, -31, -37, -46, -66, -85, -67, -21, -5, 3, 16, 22, 37, 54, 59, 55, 60, 58, 30, 16, 13, 11, -15, -34, -23, 9, 7, -12, -2, -4, -19, -16, -31, -49, -64, -76, -72, -35, -12, -14, 0, 15, 34, 53, 60, 58, 53, 57, 43, 30, 18, 12, -4, -27, -28, -8, 14, -3, -9, -2, -13, -9, -17, -49, -66, -70, -69, -44, -15, -19, -11, 2, 21, 53, 64, 68, 55, 48, 44, 36, 28, 15, -1, -18, -23, -19, -4, 5, -3, 1, -9, -7, -1, -35, -70, -74, -70, -50, -21, -14, -22, -7, -1, 39, 66, 77, 69, 46, 38, 36, 38, 22, 5, -12, -16, -12, -17, -8, -5, 2, 1, -6, 5, -13, -64, -78, -73, -60, -31, -14, -17, -16, -10, 7, 61, 79, 81, 57, 38, 28, 32, 24, 9, -4, -10, -4, -11, -20, -13, -2, 11, 4, 4, -2, -41, -76, -76, -69, -43, -22, -12, -17, -14, -14, 25, 74, 92, 79, 47, 31, 26, 26, 11, 3, -5, 0, 0, -20, -26, -11, 9, 14, 9, 4, -24, -61, -76, -74, -53, -30, -13, -8, -12, -25, -8, 51, 90, 93, 63, 42, 21, 18, 13, 6, 2, 1, 8, -12, -30, -27, -2, 14, 18, 11, -13, -48, -68, -79, -70, -44, -19, -2, -5, -21, -31, 18, 77, 100, 81, 55, 29, 7, 8, 6, 7, 4, 14, 0, -26, -34, -13, 9, 16, 17, 1, -35, -58, -70, -82, -62, -29, -2, 1, -14, -36, -15, 50, 89, 95, 71, 46, 5, -6, 4, 11, 3, 11, 14, -12, -31, -22, -2, 8, 16, 16, -15, -53, -56, -80, -81, -41, -5, 9, -3, -30, -34, 17, 73, 97, 86, 63, 25, -12, -6, 11, 13, 1, 15, 4, -19, -25, -5, 2, 9, 19, 10, -39, -48, -61, -95, -67, -17, 12, 8, -23, -43, -9, 49, 85, 91, 76, 50, 1, -23, 2, 22, 5, 2, 14, -5, -23, -12, 0, -2, 13, 17, -15, -48, -43, -83, -88, -38, 5, 17, -11, -41, -28, 27, 67, 83, 82, 65, 29, -21, -18, 21, 19, -7, 3, 6, -8, -14, 1, 0, 0, 13, 2, -34, -42, -59, -99, -63, -12, 17, 0, -35, -42, 1, 53, 69, 79, 72, 53, -1, -34, 2, 32, 3, -8, 1, 2, -2, -3, 8, -2, 3, 7, -18, -40, -39, -76, -81, -35, 9, 17, -22, -46, -24, 34, 59, 68, 74, 66, 27, -26, -22, 31, 24, -10, -11, 0, 14, 1, 5, 8, -5, -2, -10, -34, -35, -48, -77, -59, -13, 20, -4, -37, -35, 8, 47, 55, 68, 74, 49, -4, -34, 10, 39, 1, -13, -11, 14, 14, 3, 20, 6, -9, -14, -29, -37, -28, -56, -66, -42, 9, 9, -25, -38, -14, 27, 45, 54, 72, 61, 21, -25, -14, 31, 19, -10, -15, -2, 22, 6, 22, 24, -4, -20, -28, -38, -24, -28, -54, -57, -20, 14, -10, -29, -26, 2, 29, 39, 61, 66, 39, -6, -25, 16, 30, 0, -16, -8, 12, 13, 18, 38, 10, -20, -36, -34, -31, -16, -33, -56, -42, 0, 0, -21, -22, -12, 11, 25, 49, 68, 53, 14, -20, -3, 29, 15, -11, -12, 3, 13, 13, 42, 34, -12, -39, -37, -27, -22, -18, -44, -50, -21, 3, -12, -15, -18, -5, 9, 27, 60, 60, 32, -6, -12, 21, 25, -4, -12, -2, 7, 8, 33, 53, 8, -37, -41, -25, -22, -16, -27, -47, -34, -10, -10, -15, -15, -15, -5, 5, 41, 63, 44, 12, -11, 10, 32, 10, -14, -8, 8, 5, 19, 53, 34, -24, -43, -25, -14, -15, -19, -35, -35, -20, -12, -8, -14, -17, -19, -13, 19, 55, 53, 22, -8, 4, 31, 26, -8, -13, 6, 10, 7, 39, 50, -2, -41, -31, -10, -13, -23, -31, -33, -24, -15, -7, -13, -16, -22, -23, -6, 38, 55, 34, 1, -1, 23, 34, 9, -18, -3, 14, 9, 20, 51, 24, -28, -37, -6, 2, -20, -30, -27, -21, -22, -6, -12, -17, -21, -32, -27, 9, 49, 43, 12, -4, 14, 34, 24, -9, -12, 12, 19, 13, 30, 37, -3, -35, -15, 12, -10, -31, -30, -15, -18, -13, -3, -19, -20, -31, -35, -17, 28, 44, 22, 0, 7, 28, 27, 5, -15, 1, 20, 20, 17, 28, 19, -21, -23, 12, 8, -22, -32, -20, -8, -15, 0, -13, -23, -25, -43, -36, 4, 37, 30, 11, 4, 22, 28, 15, 0, -10, 9, 23, 14, 11, 24, 5, -21, 2, 17, -8, -27, -27, -7, -10, -6, -1, -20, -26, -39, -53, -20, 23, 36, 17, 7, 14, 28, 16, 12, -3, 2, 19, 16, 2, 14, 19, -8, -5, 17, 4, -15, -26, -10, -4, -12, 1, -8, -23, -38, -58, -41, 0, 29, 23, 11, 16, 21, 15, 9, 11, -6, 11, 20, 4, 3, 24, 5, -5, 10, 17, -6, -15, -15, 6, -15, -8, 0, -11, -37, -54, -56, -24, 13, 29, 12, 15, 20, 19, 6, 16, 5, -2, 10, 11, -3, 22, 18, 0, 6, 20, 10, -6, -12, 1, -6, -23, 0, 1, -23, -56, -60, -43, -10, 19, 22, 15, 22, 18, 6, 11, 17, -2, -5, 10, 4, 7, 23, 1, 3, 16, 22, 5, -1, 0, 5, -21, -14, 6, -6, -46, -64, -54, -29, 1, 17, 18, 24, 25, 10, 1, 17, 9, -8, -1, 15, 6, 20, 11, 2, 14, 25, 16, 9, 5, 7, -11, -26, -5, 4, -27, -62, -62, -40, -17, 8, 11, 21, 29, 17, -2, 10, 17, -8, -16, 6, 13, 11, 15, 3, 8, 24, 26, 14, 12, 12, 4, -26, -15, 1, -12, -50, -64, -48, -27, -10, 5, 8, 32, 31, 1, -1, 18, 0, -23, -6, 18, 14, 11, 5, 3, 17, 35, 25, 16, 18, 14, -11, -27, -8, -6, -30, -55, -53, -36, -20, -5, 5, 14, 43, 13, -6, 11, 11, -22, -22, 7, 19, 13, 10, 1, 7, 30, 36, 22, 23, 23, 6, -28, -20, -6, -23, -43, -49, -43, -29, -19, 3, 1, 34, 29, -4, 3, 13, -13, -32, -3, 20, 14, 11, 5, 2, 23, 42, 34, 22, 23, 21, -13, -26, -14, -19, -32, -38, -43, -32, -29, -6, 4, 16, 35, 9, -4, 11, 0, -33, -22, 9, 13, 12, 9, 3, 14, 35, 47, 34, 23, 27, 8, -22, -19, -16, -30, -29, -42, -33, -32, -23, 4, 9, 24, 20, -1, 3, 10, -20, -36, -5, 13, 9, 11, 8, 8, 21, 43, 48, 27, 22, 23, -7, -25, -20, -28, -25, -31, -36, -28, -33, -8, 11, 14, 14, 6, -8, 7, -5, -39, -25, 7, 14, 9, 10, 12, 15, 29, 55, 41, 23, 22, 9, -12, -23, -28, -24, -23, -34, -26, -31, -21, 9, 19, 9, 1, -3, -1, 7, -32, -38, -9, 13, 11, 9, 11, 14, 21, 46, 53, 32, 24, 12, -2, -16, -26, -24, -17, -34, -33, -25, -24, -4, 17, 14, -3, -4, -7, 3, -13, -46, -25, 2, 17, 5, 8, 12, 18, 32, 56, 38, 29, 15, 8, -4, -22, -30, -14, -22, -42, -25, -15, -10, 6, 17, 1, -5, -7, -10, -2, -38, -37, -7, 15, 9, 2, 8, 21, 26, 43, 44, 29, 18, 7, 12, -9, -25, -24, -11, -35, -43, -17, -5, 3, 10, 9, -3, -3, -23, -9, -23, -45, -22, 7, 15, 2, 4, 17, 33, 31, 45, 35, 23, 8, 17, 6, -16, -26, -14, -20, -48, -27, -2, 6, 11, 9, -1, 6, -15, -28, -18, -39, -32, -7, 11, 7, 6, 7, 33, 30, 31, 41, 27, 7, 13, 24, -3, -18, -22, -9, -40, -41, -10, 4, 9, 17, 3, 5, -4, -37, -29, -29, -35, -19, 1, 10, 3, 7, 25, 41, 19, 31, 32, 13, 5, 27, 14, -6, -19, -12, -23, -48, -22, 7, 8, 16, 11, 1, 6, -29, -46, -32, -32, -20, -5, 7, 4, 3, 21, 43, 32, 15, 29, 16, 8, 19, 26, 3, -9, -22, -13, -42, -37, -8, 11, 14, 25, 9, 4, -17, -50, -44, -30, -25, -14, -1, 11, 1, 18, 36, 41, 12, 14, 18, 14, 15, 20, 17, 6, -14, -18, -27, -39, -19, 5, 12, 24, 27, 8, -13, -49, -53, -32, -27, -19, -12, 7, 7, 12, 31, 43, 26, 2, 8, 14, 22, 13, 17, 18, 6, -17, -26, -36, -28, -6, 14, 25, 35, 20, -6, -42, -57, -37, -23, -23, -20, 0, 9, 8, 25, 41, 40, 7, -4, 1, 23, 21, 14, 22, 20, -2, -24, -34, -31, -13, 8, 24, 37, 33, 8, -32, -62, -44, -20, -22, -27, -9, 9, 7, 16, 31, 42, 20, -10, -13, 10, 26, 7, 13, 25, 18, -11, -35, -39, -20, 0, 17, 37, 37, 19, -17, -58, -55, -26, -18, -25, -21, 0, 14, 12, 20, 38, 35, 0, -19, -9, 24, 19, 3, 21, 31, 17, -24, -42, -30, -3, 13, 34, 42, 28, -2, -45, -62, -38, -22, -19, -20, -12, 12, 17, 11, 29, 42, 18, -16, -20, 3, 24, 2, 4, 26, 36, 0, -38, -45, -13, 12, 27, 41, 34, 14, -27, -62, -55, -30, -19, -15, -16, -2, 18, 11, 14, 37, 31, -6, -22, -12, 15, 10, -10, 12, 36, 30, -19, -46, -33, 11, 24, 28, 35, 28, -5, -44, -65, -44, -23, -11, -9, -8, 5, 14, 10, 25, 37, 14, -17, -18, -2, 14, -7, -6, 23, 43, 10, -33, -38, -9, 24, 24, 28, 30, 11, -21, -57, -61, -39, -12, -5, -5, -3, 7, 10, 17, 31, 30, -3, -20, -14, 6, 1, -16, 2, 38, 38, -5, -30, -24, 13, 25, 21, 28, 15, 1, -34, -64, -62, -23, 0, 2, -1, -1, 5, 14, 24, 33, 14, -12, -23, -4, 7, -18, -18, 18, 43, 25, -9, -22, -2, 21, 19, 24, 20, 11, -13, -47, -69, -46, -7, 5, 6, -1, -4, 9, 21, 31, 25, 5, -15, -20, 3, -8, -33, -7, 29, 37, 20, -10, -10, 9, 15, 17, 14, 12, 1, -23, -55, -70, -30, 5, 13, 2, -8, -1, 15, 25, 30, 15, -1, -20, -8, -3, -31, -28, 8, 31, 41, 15, -6, 0, 9, 14, 12, 9, 8, -10, -28, -63, -55, -12, 17, 11, -7, -13, 8, 22, 26, 19, 9, -7, -13, -5, -23, -39, -10, 17, 41, 38, 8, 0, 5, 7, 12, 5, 7, -6, -8, -39, -60, -35, 7, 19, 6, -10, -6, 15, 26, 22, 15, 9, -8, -13, -24, -45, -29, -1, 29, 48, 30, 2, 6, 5, 9, 5, -1, -5, -4, -13, -51, -51, -16, 20, 13, 0, -11, 7, 25, 22, 18, 17, 10, -8, -22, -50, -43, -13, 15, 46, 42, 16, 7, 8, 7, 7, -1, -6, -10, -4, -27, -45, -36, 5, 16, 7, -5, -5, 20, 22, 19, 19, 22, 7, -15, -43, -62, -29, 3, 35, 43, 27, 11, 9, 8, 4, 2, -9, -13, -7, -15, -30, -43, -16, 12, 13, 4, -8, 12, 24, 17, 16, 24, 25, -3, -38, -72, -52, -9, 25, 42, 30, 21, 8, 14, 4, 6, -3, -13, -12, -13, -18, -36, -34, 3, 14, 9, -9, 5, 26, 18, 13, 26, 34, 13, -31, -69, -68, -16, 19, 35, 29, 22, 6, 16, 3, 2, 6, -5, -15, -20, -19, -21, -34, -17, 8, 16, -2, -3, 24, 27, 16, 23, 34, 32, -10, -56, -80, -45, 6, 29, 29, 22, 10, 14, 13, -4, 6, 7, -8, -27, -27, -18, -20, -28, -8, 14, 8, -7, 11, 29, 21, 17, 25, 35, 16, -36, -77, -67, -14, 25, 30, 22, 11, 10, 19, 5, 2, 6, 5, -18, -34, -25, -13, -23, -19, 4, 13, 0, 7, 24, 32, 24, 22, 31, 30, -12, -62, -76, -41, 9, 28, 24, 15, 6, 18, 16, 6, 6, 7, -7, -32, -37, -16, -18, -24, -8, 11, 7, 7, 20, 31, 35, 25, 24, 33, 9, -40, -72, -58, -16, 17, 27, 16, 6, 10, 22, 12, 8, 8, 2, -23, -43, -26, -16, -24, -18, 2, 6, 7, 21, 29, 36, 32, 21, 27, 22, -21, -57, -67, -38, -4, 26, 21, 9, 3, 18, 25, 18, 10, 2, -11, -42, -36, -24, -27, -23, -9, 5, 2, 17, 32, 42, 36, 27, 18, 25, -2, -39, -58, -51, -27, 11, 27, 11, 1, 9, 24, 25, 21, 5, -8, -31, -37, -30, -33, -24, -15, 0, -2, 13, 31, 48, 47, 33, 15, 18, 10, -27, -50, -52, -44, -12, 21, 21, 5, -1, 13, 33, 30, 16, -6, -26, -39, -33, -35, -28, -20, -10, -8, 4, 27, 51, 61, 45, 21, 13, 14, -11, -39, -40, -44, -36, 1, 25, 16, 1, 2, 27, 40, 28, 3, -22, -38, -38, -32, -33, -21, -18, -14, -8, 18, 50, 66, 60, 27, 7, 12, -3, -31, -36, -37, -46, -27, 18, 26, 5, -3, 8, 35, 43, 16, -14, -36, -43, -32, -32, -25, -16, -23, -14, 6, 46, 64, 74, 49, 9, 4, 7, -23, -37, -34, -41, -44, -8, 31, 19, -5, 0, 21, 47, 33, -2, -33, -43, -43, -32, -29, -14, -22, -23, -6, 34, 62, 75, 71, 30, 0, 8, -13, -37, -34, -35, -45, -34, 18, 31, 5, -5, 7, 35, 44, 12, -23, -45, -49, -40, -29, -18, -18, -27, -15, 22, 57, 74, 80, 57, 15, 4, -1, -39, -34, -34, -40, -46, -4, 25, 13, -3, 2, 22, 44, 25, -10, -38, -44, -50, -34, -20, -14, -31, -21, 5, 47, 63, 81, 76, 38, 8, 9, -30, -45, -35, -36, -43, -20, 9, 14, 5, 3, 7, 36, 32, 3, -32, -43, -50, -40, -28, -13, -24, -28, -2, 35, 56, 73, 86, 58, 23, 21, -10, -49, -45, -33, -39, -25, -3, 5, 5, 8, 5, 18, 32, 17, -19, -45, -49, -41, -35, -22, -19, -31, -12, 28, 52, 59, 76, 74, 41, 31, 10, -39, -58, -41, -32, -27, -5, -3, 3, 8, 8, 10, 24, 22, -4, -39, -52, -42, -35, -30, -18, -28, -22, 20, 53, 52, 60, 73, 62, 43, 31, -18, -56, -61, -35, -28, -9, -6, -3, 3, 9, 10, 12, 18, 8, -23, -53, -50, -31, -35, -24, -28, -26, 3, 48, 55, 52, 59, 66, 57, 46, 7, -37, -67, -53, -24, -11, -4, -6, 0, 3, 13, 10, 7, 10, -6, -38, -58, -36, -30, -30, -26, -26, -11, 33, 60, 56, 49, 59, 67, 58, 32, -15, -58, -69, -34, -14, -8, -6, 1, -4, 7, 8, 2, 4, 4, -21, -54, -49, -30, -30, -28, -29, -18, 13, 53, 60, 50, 44, 63, 61, 49, 11, -33, -71, -49, -19, -9, -10, 5, 2, -1, 4, -1, 4, 5, -5, -38, -55, -40, -28, -21, -25, -26, -2, 40, 61, 56, 39, 53, 66, 54, 33, -4, -55, -63, -29, -18, -12, 3, 11, -4, -4, -9, -3, 4, 4, -18, -49, -49, -35, -18, -18, -25, -16, 24, 51, 60, 42, 43, 66, 57, 42, 21, -23, -63, -44, -26, -18, -10, 13, 9, -8, -18, -17, 5, 5, -4, -35, -47, -42, -24, -11, -20, -21, 5, 36, 56, 53, 37, 60, 59, 40, 34, 11, -34, -52, -33, -21, -15, 1, 21, 2, -19, -33, -10, 8, 3, -20, -42, -41, -33, -14, -16, -18, -7, 21, 43, 54, 39, 47, 61, 44, 31, 27, -4, -41, -47, -28, -23, -9, 11, 15, -9, -34, -34, 1, 10, -2, -30, -38, -34, -18, -15, -17, -10, 10, 27, 43, 42, 42, 53, 54, 36, 24, 14, -15, -42, -36, -32, -22, 1, 13, 7, -26, -48, -24, 11, 10, -14, -35, -32, -19, -16, -15, -11, 5, 18, 31, 34, 41, 48, 51, 46, 28, 26, 8, -26, -36, -33, -35, -12, 7, 12, -8, -45, -47, -9, 13, 5, -24, -32, -17, -14, -16, -11, 6, 14, 20, 26, 27, 47, 49, 49, 34, 25, 22, -6, -31, -27, -39, -30, -10, 13, 6, -28, -57, -31, -3, 12, -7, -28, -19, -8, -21, -18, -2, 18, 17, 17, 19, 34, 47, 53, 42, 34, 30, 13, -22, -20, -30, -44, -32, -4, 15, -7, -45, -49, -18, 4, 10, -14, -18, 0, -11, -26, -7, 15, 23, 10, 10, 20, 34, 51, 49, 38, 41, 30, -8, -28, -15, -39, -47, -28, 5, 10, -26, -55, -34, -9, 10, 3, -13, -4, 1, -21, -19, 3, 25, 13, 5, 9, 18, 36, 54, 39, 40, 46, 16, -27, -17, -23, -47, -47, -18, 9, -2, -47, -51, -23, 0, 4, 0, 1, 9, -11, -20, -9, 20, 23, 4, 2, 8, 20, 45, 46, 38, 53, 41, -13, -30, -19, -36, -52, -40, -9, 5, -23, -53, -35, -6, 4, 3, 6, 10, 5, -16, -17, 6, 30, 12, 0, -4, 9, 32, 47, 43, 55, 57, 16, -27, -30, -28, -44, -52, -31, -6, -8, -43, -43, -15, -1, -1, 8, 10, 13, 2, -18, -11, 21, 23, 6, -5, 0, 19, 33, 41, 56, 67, 44, -5, -34, -35, -32, -46, -47, -27, -7, -30, -44, -23, -2, -2, 3, 7, 14, 18, -1, -19, 4, 20, 16, -5, -9, 10, 27, 30, 46, 65, 63, 26, -22, -42, -34, -41, -46, -40, -18, -25, -39, -28, -4, 1, -1, 5, 10, 24, 19, -8, -6, 11, 20, 4, -13, 2, 22, 24, 36, 59, 70, 51, 5, -39, -39, -43, -47, -45, -31, -30, -39, -33, -7, 1, -2, 1, 4, 19, 25, 5, -5, 1, 12, 13, -12, -12, 18, 25, 21, 46, 68, 69, 36, -17, -39, -44, -51, -43, -33, -35, -41, -38, -15, 8, 0, 0, 0, 13, 26, 19, 5, 0, -1, 10, -2, -14, 5, 25, 19, 29, 54, 71, 59, 9, -31, -43, -56, -50, -32, -38, -47, -42, -26, 8, 10, -3, -3, 7, 20, 23, 16, 8, -5, 3, 2, -17, -6, 22, 20, 18, 40, 66, 71, 37, -13, -36, -52, -61, -38, -32, -47, -51, -38, -7, 19, 6, -6, 4, 14, 19, 21, 19, 2, -5, 0, -13, -12, 14, 21, 13, 27, 53, 71, 57, 12, -25, -42, -61, -54, -33, -38, -52, -50, -22, 13, 17, -4, 1, 16, 17, 19, 25, 11, -2, -2, -11, -18, 6, 21, 15, 18, 43, 66, 67, 34, -7, -30, -49, -58, -42, -36, -42, -54, -36, -2, 20, 4, -4, 11, 16, 17, 26, 17, 4, 1, -8, -22, -8, 17, 16, 17, 27, 55, 66, 48, 10, -25, -36, -49, -52, -42, -39, -47, -46, -18, 13, 14, -1, 3, 13, 19, 27, 18, 2, 5, 1, -14, -17, 6, 13, 16, 26, 44, 64, 54, 27, -15, -30, -33, -49, -50, -43, -44, -45, -30, -1, 13, 3, 6, 10, 22, 30, 21, 3, 2, 2, -3, -18, -9, 8, 11, 23, 35, 55, 58, 37, 1, -25, -18, -33, -51, -48, -46, -41, -30, -17, 6, 3, 7, 9, 16, 30, 27, 9, 3, 3, 1, -10, -18, 0, 3, 12, 37, 46, 52, 40, 15, -23, -16, -14, -39, -48, -48, -45, -31, -20, -7, 1, 4, 14, 13, 21, 26, 16, 2, 1, 1, 1, -16, -12, 1, 5, 29, 50, 47, 39, 21, -11, -21, -3, -23, -41, -45, -47, -37, -21, -13, -6, 1, 16, 20, 22, 22, 18, 10, 2, 1, 6, -7, -16, -10, 0, 16, 51, 53, 38, 22, -1, -21, -1, -4, -30, -41, -45, -45, -28, -13, -13, -8, 13, 24, 26, 15, 13, 15, 8, -4, 1, -2, -11, -15, -11, 2, 40, 56, 44, 21, 1, -16, -10, 5, -16, -32, -38, -41, -36, -22, -14, -15, 4, 24, 32, 18, 7, 14, 14, 4, -2, -1, -8, -12, -15, -6, 24, 50, 51, 28, 1, -13, -14, 4, 1, -18, -31, -35, -36, -33, -21, -21, -5, 19, 38, 23, 3, 5, 17, 15, 2, -3, -7, -8, -18, -14, 12, 39, 50, 35, 2, -14, -14, -3, 6, -6, -24, -27, -32, -40, -25, -22, -12, 8, 35, 34, 10, 2, 5, 19, 9, -6, -4, -3, -15, -18, 4, 30, 42, 40, 13, -17, -16, -7, 3, 5, -14, -21, -24, -41, -37, -23, -18, -1, 22, 37, 17, 4, -1, 11, 17, 1, -7, -4, -12, -22, -6, 24, 35, 33, 25, -7, -26, -15, 2, 14, 3, -16, -19, -33, -42, -27, -23, -10, 15, 28, 27, 8, 2, 5, 20, 11, -4, -6, -7, -19, -11, 17, 31, 26, 25, 6, -24, -25, -6, 11, 14, -3, -13, -25, -39, -33, -23, -17, 7, 19, 26, 19, 4, 1, 15, 14, -1, -5, -10, -14, -22, 8, 33, 28, 20, 16, -13, -26, -17, 9, 22, 5, -8, -18, -37, -35, -28, -23, -4, 12, 16, 28, 12, 1, 12, 18, 3, -2, -9, -10, -27, -10, 29, 34, 18, 16, 2, -26, -29, -3, 27, 19, -4, -10, -29, -36, -30, -29, -12, 9, 3, 18, 21, 7, 12, 17, 3, -2, -7, -7, -19, -26, 15, 36, 21, 12, 9, -15, -30, -18, 19, 30, 6, -5, -21, -32, -25, -29, -22, 6, 0, 3, 20, 14, 12, 18, 12, 0, -9, -12, -9, -26, -4, 31, 28, 11, 10, -6, -24, -29, 3, 35, 19, -3, -15, -26, -19, -23, -31, -6, 4, -7, 13, 19, 17, 20, 18, 9, -9, -19, -5, -17, -20, 16, 34, 18, 9, 0, -16, -25, -10, 30, 29, 3, -10, -19, -19, -16, -29, -19, 3, -9, -5, 13, 21, 24, 16, 13, 1, -23, -14, -12, -19, -2, 28, 21, 8, 1, -11, -23, -19, 16, 41, 14, -8, -13, -9, -13, -18, -27, -4, -5, -12, -1, 19, 31, 18, 10, 16, -20, -22, -13, -14, -12, 18, 26, 12, 4, -4, -17, -18, -1, 38, 31, -5, -14, -7, -7, -14, -24, -13, -3, -13, -12, 7, 30, 34, 14, 18, -5, -33, -18, -10, -14, 1, 19, 14, 6, -8, -13, -15, -2, 19, 40, 8, -13, -9, -4, -8, -18, -20, -9, -14, -16, -7, 22, 37, 23, 16, 10, -26, -28, -13, -9, -5, 14, 14, 9, -9, -17, -13, -1, 8, 31, 26, -6, -10, -4, -2, -12, -19, -11, -11, -17, -12, 6, 34, 29, 15, 16, -7, -35, -25, -9, -6, 8, 14, 12, 1, -15, -14, 3, 10, 19, 29, 8, -10, -9, 1, -7, -20, -10, -9, -17, -17, -1, 30, 35, 18, 15, 5, -28, -33, -17, -6, -4, 8, 13, 5, -14, -19, 1, 14, 14, 20, 17, 0, -8, -2, -3, -14, -18, -9, -12, -18, -6, 21, 37, 26, 7, 10, -13, -33, -24, -6, -2, 0, 9, 11, -5, -19, -7, 16, 18, 13, 18, 11, -2, -6, -3, -6, -22, -10, -11, -16, -11, 17, 34, 32, 9, 9, 2, -26, -30, -14, -2, -5, 3, 8, 3, -16, -12, 8, 21, 13, 13, 15, 2, -3, -5, -5, -20, -16, -8, -16, -20, 6, 32, 34, 14, -4, 6, -12, -26, -20, -7, -6, -4, 4, 7, -2, -15, 1, 17, 15, 9, 15, 10, 0, -3, -7, -15, -22, -4, -7, -19, -7, 29, 36, 20, -6, -1, 0, -17, -19, -12, -9, -7, -1, 2, 6, -3, -8, 10, 18, 9, 8, 21, 4, -2, -8, -13, -20, -12, -2, -16, -14, 14, 39, 26, -3, -17, 1, -6, -16, -12, -7, -9, -9, 0, 3, 11, -3, 0, 15, 13, 3, 19, 12, -8, -6, -14, -19, -16, 0, -6, -17, 3, 33, 35, 5, -18, -9, 1, -15, -11, -8, -8, -16, -8, 1, 15, 15, 3, 11, 19, 2, 12, 26, 0, -10, -13, -21, -11, 1, -1, -18, -2, 23, 35, 17, -12, -21, -2, -8, -9, -8, -9, -12, -17, -5, 10, 22, 8, 7, 18, 7, -1, 23, 13, -13, -19, -23, -14, 5, 2, -15, -13, 17, 30, 22, -3, -24, -7, -2, -9, -6, -10, -8, -21, -19, 5, 22, 22, 13, 15, 13, -3, 11, 18, -4, -20, -28, -20, 4, 11, -10, -18, 6, 26, 17, 3, -20, -12, -2, -11, -7, -8, -8, -16, -27, -7, 19, 30, 21, 19, 15, 4, 3, 18, 2, -17, -33, -24, 0, 17, 1, -16, -6, 24, 19, 5, -17, -18, 1, -8, -12, -7, -11, -10, -22, -14, 10, 29, 29, 32, 23, 13, 0, 9, 6, -12, -28, -36, -7, 13, 12, -8, -17, 12, 24, 6, -10, -20, 1, 1, -13, -9, -12, -16, -20, -17, 0, 21, 27, 31, 35, 20, 7, 0, 2, -13, -19, -37, -19, 8, 18, 9, -16, -9, 20, 11, -2, -25, -13, 8, -4, -16, -13, -18, -23, -17, 0, 14, 29, 27, 43, 35, 17, -1, -4, -13, -22, -29, -31, -2, 17, 20, -5, -21, 6, 16, 5, -16, -25, 4, 11, -12, -17, -20, -27, -19, -2, 13, 26, 27, 36, 46, 32, 7, -8, -18, -26, -25, -32, -16, 12, 26, 11, -18, -11, 4, 13, -1, -27, -12, 14, 2, -21, -23, -31, -26, -11, 10, 24, 30, 29, 43, 50, 24, -4, -16, -34, -28, -28, -27, -1, 27, 24, -5, -21, -12, 6, 16, -13, -28, 1, 13, -9, -23, -33, -32, -18, 2, 24, 34, 33, 34, 50, 49, 12, -11, -34, -37, -28, -25, -14, 14, 28, 10, -10, -25, -9, 21, 15, -27, -15, 12, 2, -18, -33, -36, -24, -7, 13, 30, 39, 42, 35, 54, 36, 1, -29, -45, -35, -26, -17, -1, 20, 19, 2, -23, -30, 1, 30, -5, -32, 1, 7, -8, -27, -37, -25, -12, -1, 23, 37, 51, 38, 41, 49, 16, -15, -41, -40, -31, -21, -11, 4, 19, 15, -8, -33, -19, 22, 20, -21, -13, 2, -6, -17, -36, -32, -11, -8, 9, 28, 48, 54, 36, 48, 30, 3, -30, -41, -34, -24, -15, -6, 2, 17, 8, -19, -37, 0, 31, 3, -20, -6, -4, -7, -31, -35, -9, -3, -4, 16, 37, 62, 44, 41, 33, 13, -11, -36, -39, -29, -21, -11, -11, 6, 14, -2, -28, -24, 15, 22, -5, -10, -11, -10, -20, -35, -13, 2, -5, 2, 21, 55, 64, 46, 37, 19, 2, -23, -36, -28, -23, -17, -18, -17, 10, 11, -12, -32, -7, 23, 16, -7, -14, -17, -8, -27, -23, 1, 1, 0, 6, 31, 63, 60, 46, 21, 7, -12, -29, -24, -18, -24, -23, -27, -11, 11, 5, -16, -19, 11, 21, 4, -9, -21, -15, -17, -30, -5, 7, 2, -1, 9, 48, 65, 59, 30, 13, -4, -25, -19, -6, -22, -33, -32, -31, -3, 7, -3, -20, -4, 14, 11, -1, -11, -19, -13, -20, -16, 9, 7, 2, -3, 27, 60, 69, 44, 12, 7, -18, -20, 1, -4, -35, -38, -34, -22, -9, 4, -2, -11, 8, 8, 2, -6, -19, -23, -14, -16, 3, 13, 2, 2, 12, 47, 65, 62, 22, 10, -3, -21, -9, 9, -17, -46, -40, -34, -23, -6, 4, -1, 3, 7, 2, -4, -13, -25, -18, -11, -4, 18, 3, -2, 5, 30, 58, 66, 39, 12, 9, -10, -18, 8, 5, -41, -49, -38, -33, -18, -4, 2, 7, 8, 2, -7, -12, -18, -23, -12, -6, 18, 15, -8, 0, 21, 44, 62, 48, 22, 14, 7, -16, -7, 18, -18, -52, -44, -42, -32, -18, -1, 12, 10, 6, -8, -20, -11, -18, -19, -10, 14, 24, 2, -5, 14, 34, 57, 51, 27, 19, 20, -1, -13, 15, -1, -42, -45, -49, -38, -28, -15, 13, 19, 10, -1, -23, -16, -11, -24, -10, 6, 21, 14, -5, 3, 24, 48, 58, 29, 17, 24, 18, -6, 4, 8, -28, -38, -46, -50, -36, -29, 3, 22, 15, 4, -18, -31, -7, -20, -17, 5, 11, 18, 4, -2, 15, 37, 58, 35, 11, 26, 31, 11, -2, 6, -13, -32, -39, -55, -45, -38, -17, 21, 23, 11, -10, -31, -18, -11, -25, 1, 9, 14, 15, 0, 7, 26, 49, 49, 13, 10, 33, 26, 8, 4, -5, -25, -35, -46, -53, -41, -35, 5, 24, 17, 0, -25, -26, -14, -24, -9, 6, 5, 17, 6, 6, 20, 38, 55, 30, 3, 25, 38, 18, 10, -4, -16, -30, -42, -51, -46, -41, -16, 21, 23, 14, -16, -30, -16, -17, -17, 0, 2, 12, 16, 3, 17, 28, 46, 49, 14, 13, 39, 30, 17, 4, -9, -20, -38, -49, -50, -50, -34, 4, 21, 20, 4, -29, -23, -15, -15, -8, -3, 7, 19, 8, 9, 26, 35, 47, 29, 6, 29, 35, 26, 13, -5, -18, -29, -42, -49, -51, -50, -16, 11, 23, 18, -17, -34, -14, -15, -9, -10, -2, 17, 14, 5, 21, 33, 44, 38, 14, 23, 37, 30, 20, 6, -8, -26, -34, -47, -52, -54, -34, 0, 16, 19, 5, -29, -20, -13, -10, -9, -10, 4, 19, 11, 13, 29, 37, 36, 22, 22, 39, 32, 23, 10, 2, -18, -32, -40, -54, -56, -49, -23, 8, 17, 11, -15, -26, -11, -13, -9, -15, -11, 14, 17, 10, 23, 34, 36, 24, 21, 35, 42, 26, 12, 2, -4, -23, -31, -47, -57, -50, -33, -7, 17, 11, -2, -18, -12, -12, -11, -10, -21, -6, 18, 19, 21, 33, 35, 28, 23, 34, 51, 40, 12, -2, 1, -9, -27, -43, -59, -53, -39, -23, 4, 15, 1, -10, -14, -9, -8, -10, -22, -18, 5, 19, 16, 27, 34, 28, 23, 27, 47, 53, 27, -3, -4, -1, -13, -33, -53, -57, -45, -31, -13, 14, 4, -4, -11, -9, -9, -11, -19, -28, -16, 10, 24, 23, 35, 24, 26, 26, 38, 60, 44, 2, -13, -3, -5, -19, -44, -58, -49, -33, -26, 1, 14, 1, -4, -5, 0, -7, -14, -29, -26, -11, 20, 27, 30, 32, 21, 27, 34, 59, 58, 22, -11, -10, -6, -10, -29, -55, -53, -38, -34, -16, 12, 9, -5, -8, 5, 1, -16, -31, -32, -28, 0, 26, 26, 33, 23, 24, 33, 49, 61, 37, 3, -15, -8, -11, -19, -43, -56, -44, -34, -25, -2, 17, 5, -11, 2, 12, -2, -23, -32, -35, -23, 14, 26, 27, 35, 23, 32, 45, 58, 47, 19, -5, -9, -10, -16, -27, -46, -48, -41, -34, -18, 11, 20, -6, -10, 12, 9, -18, -34, -38, -29, -7, 17, 27, 32, 30, 30, 46, 52, 51, 28, 6, -8, -9, -15, -24, -32, -41, -45, -40, -30, -1, 23, 10, -12, 2, 17, -2, -31, -39, -32, -18, -6, 18, 29, 38, 32, 45, 54, 54, 33, 11, 2, -9, -11, -19, -32, -33, -41, -45, -40, -18, 16, 19, 2, -6, 13, 12, -20, -43, -35, -21, -18, -5, 21, 35, 36, 46, 58, 52, 38, 17, 9, -5, -9, -13, -29, -32, -28, -41, -43, -36, 0, 22, 18, -4, -3, 17, 2, -33, -43, -25, -18, -16, 4, 27, 38, 47, 64, 57, 40, 18, 10, 5, -7, -10, -22, -39, -24, -30, -42, -39, -22, 13, 28, 14, -9, 3, 17, -16, -51, -36, -17, -23, -18, 8, 35, 50, 66, 68, 43, 23, 12, 13, -1, -11, -17, -32, -27, -22, -40, -38, -37, -10, 22, 34, 1, -10, 8, 6, -39, -48, -27, -19, -25, -10, 18, 49, 66, 78, 54, 26, 17, 16, 3, -7, -15, -25, -29, -12, -32, -37, -35, -28, 3, 38, 26, -7, -4, 11, -15, -46, -42, -26, -23, -24, -2, 34, 66, 81, 70, 30, 19, 21, 10, -5, -11, -25, -29, -12, -20, -37, -33, -39, -17, 25, 46, 6, -11, 2, 0, -29, -44, -41, -30, -27, -17, 12, 58, 79, 84, 46, 19, 22, 19, 2, -7, -26, -35, -12, -1, -29, -33, -39, -36, 3, 46, 31, -11, -6, -1, -14, -38, -46, -39, -32, -22, -5, 40, 76, 88, 64, 23, 22, 30, 12, -8, -20, -39, -22, 0, -13, -29, -33, -43, -20, 24, 49, 13, -12, 2, -6, -26, -45, -45, -39, -32, -15, 19, 68, 85, 77, 32, 22, 35, 27, 0, -18, -36, -38, -6, 3, -17, -29, -44, -37, -2, 40, 34, -8, -6, 3, -18, -44, -47, -44, -43, -21, 3, 49, 76, 80, 53, 21, 35, 39, 15, -18, -35, -42, -23, 2, -3, -19, -33, -42, -23, 16, 46, 16, -8, 2, -6, -37, -45, -47, -51, -33, -8, 31, 68, 74, 66, 33, 35, 45, 36, -3, -33, -40, -34, -7, 5, -8, -18, -35, -39, -13, 32, 32, 3, -1, 5, -26, -46, -50, -52, -44, -20, 15, 59, 68, 69, 50, 32, 42, 48, 21, -26, -42, -42, -24, 2, 2, -8, -20, -38, -35, 6, 33, 17, -2, 5, -6, -41, -55, -57, -46, -33, -6, 40, 64, 62, 63, 45, 38, 54, 40, -4, -42, -50, -40, -11, 6, -2, -8, -24, -41, -19, 17, 28, 10, 0, 1, -26, -52, -64, -51, -40, -23, 19, 54, 56, 61, 60, 38, 52, 55, 24, -30, -50, -47, -27, 4, 8, -6, -11, -30, -36, -6, 19, 25, 4, 1, -9, -38, -64, -61, -42, -36, 0, 44, 55, 51, 66, 50, 49, 62, 46, -5, -48, -51, -40, -11, 11, 4, -14, -15, -36, -25, 1, 19, 15, -1, -2, -18, -53, -69, -48, -42, -20, 21, 51, 45, 56, 62, 51, 60, 59, 23, -32, -53, -49, -28, 5, 17, -12, -18, -22, -32, -12, 9, 20, 1, -6, -5, -29, -70, -62, -48, -32, 2, 36, 45, 44, 62, 62, 60, 64, 47, -10, -45, -54, -42, -11, 21, 5, -19, -18, -23, -20, -1, 15, 4, -6, -2, -6, -51, -72, -57, -44, -13, 19, 40, 41, 51, 65, 66, 69, 63, 14, -32, -47, -50, -30, 10, 14, -12, -16, -18, -16, -14, 7, 8, -6, -8, -1, -21, -65, -67, -54, -29, 1, 26, 38, 44, 53, 69, 77, 73, 37, -17, -41, -46, -37, -10, 13, -1, -11, -14, -14, -10, -6, 9, -5, -6, -11, -3, -43, -67, -68, -42, -15, 12, 27, 40, 47, 65, 80, 83, 55, 7, -34, -43, -34, -22, -5, 2, -3, -2, -13, -10, -11, 3, -2, -4, -13, -5, -15, -51, -72, -63, -31, -3, 16, 29, 42, 55, 78, 91, 68, 25, -11, -40, -32, -22, -21, -9, -1, 8, -1, -19, -11, -3, 1, -5, -11, -12, -3, -29, -58, -70, -48, -18, 6, 15, 35, 50, 68, 89, 84, 37, 11, -27, -38, -19, -20, -23, -8, 10, 18, -10, -19, -8, 4, 0, -11, -14, -7, -20, -42, -63, -60, -37, -4, 7, 23, 41, 67, 82, 90, 53, 19, -4, -34, -23, -20, -31, -22, 5, 25, 8, -17, -20, 0, 10, -5, -20, -9, -12, -31, -47, -60, -53, -26, -3, 12, 32, 58, 81, 85, 70, 27, 9, -19, -26, -19, -28, -31, -8, 24, 21, -2, -26, -11, 14, 10, -20, -18, -8, -24, -33, -53, -56, -44, -23, 3, 22, 44, 77, 85, 74, 40, 17, -3, -21, -21, -24, -36, -25, 11, 22, 15, -13, -28, 5, 23, 0, -28, -12, -19, -26, -42, -56, -48, -39, -17, 12, 34, 62, 84, 73, 52, 26, 9, -12, -21, -22, -31, -30, -1, 15, 16, 6, -25, -14, 23, 19, -17, -21, -13, -24, -34, -54, -44, -39, -36, -9, 27, 46, 79, 79, 59, 38, 16, -2, -17, -25, -25, -27, -10, 5, 10, 15, -4, -24, 5, 29, 5, -24, -18, -19, -28, -48, -50, -35, -38, -28, 10, 33, 62, 82, 62, 46, 27, 4, -8, -23, -24, -25, -15, -3, 0, 8, 6, -12, -9, 22, 25, -6, -21, -22, -28, -45, -53, -39, -30, -37, -11, 20, 43, 75, 66, 53, 41, 10, -8, -16, -25, -23, -15, -2, -4, -5, 4, 1, -7, 8, 29, 19, -9, -21, -24, -42, -55, -48, -30, -31, -19, 5, 23, 61, 74, 58, 53, 26, -7, -11, -18, -25, -14, 0, 1, -16, -8, 4, 0, 3, 20, 28, 11, -16, -19, -38, -58, -55, -35, -27, -16, -1, 5, 32, 63, 61, 56, 44, 3, -17, -13, -22, -19, -4, 5, -8, -21, -6, 7, 8, 12, 25, 25, 2, -17, -26, -54, -64, -47, -32, -11, 5, 3, 16, 40, 60, 58, 56, 26, -16, -19, -16, -20, -8, 0, -4, -20, -22, 1, 12, 9, 17, 30, 20, -2, -15, -42, -68, -57, -44, -19, 11, 6, 10, 19, 42, 58, 58, 45, 6, -23, -18, -13, -13, -3, -3, -10, -26, -14, 9, 15, 12, 26, 27, 10, -7, -25, -61, -68, -54, -36, 10, 15, 13, 16, 19, 42, 55, 52, 31, -9, -25, -18, -15, -7, -3, -9, -23, -26, -2, 15, 19, 19, 26, 18, 7, -10, -41, -72, -60, -51, -8, 25, 22, 20, 13, 19, 45, 51, 44, 19, -15, -28, -15, -7, -4, -9, -19, -28, -14, 6, 18, 18, 24, 22, 12, 1, -17, -55, -67, -56, -35, 19, 33, 30, 20, 9, 23, 44, 48, 39, 6, -22, -25, -9, -8, -9, -15, -29, -21, -3, 10, 16, 20, 23, 13, 7, -4, -31, -63, -61, -50, -11, 33, 37, 30, 12, 7, 24, 44, 48, 28, -4, -28, -14, -4, -14, -14, -27, -27, -8, 5, 13, 15, 19, 19, 11, 3, -12, -44, -64, -58, -31, 17, 40, 39, 24, 8, 3, 30, 46, 42, 16, -18, -21, -6, -16, -18, -26, -32, -15, 1, 6, 10, 10, 15, 12, 10, -3, -23, -51, -63, -50, -4, 34, 41, 33, 17, -4, 10, 35, 42, 32, 5, -15, -8, -10, -18, -21, -30, -22, 0, 3, -2, -2, 6, 5, 4, 3, -7, -25, -45, -45, -18, 25, 33, 32, 21, 7, 8, 20, 30, 31, 20, 3, -7, -10, -14, -17, -23, -29, -12, 6, -2, -11, -11, -4, 2, 3, -7, -10, -27, -33, -21, 13, 27, 23, 19, 8, 15, 17, 18, 21, 23, 19, 2, -12, -10, -9, -15, -27, -28, -2, 9, -8, -18, -17, -4, 9, -6, -7, -10, -17, -13, 2, 21, 20, 14, 4, 15, 25, 15, 11, 14, 19, 13, -13, -17, -6, -5, -20, -36, -23, 4, 6, -18, -28, -20, 6, 6, 0, 3, 5, 5, 28, 31, 31, 49, 55, 35, 11, 27, 26, 4, 7, 11, 31, 54, 38, 26, 34, 35, 20, -10, -32, -43, -47, -43, -20, -7, -37, -55, -62, -61, -63, -34, -21, -35, -28, -10, 15, 24, 23, 5, -31, -38, -6, 23, 19, 15, 24, 20, 31, 57, 54, 28, 13, 33, 20, 1, 4, 17, 38, 44, 33, 31, 43, 36, 10, -14, -34, -53, -53, -46, -22, -22, -38, -46, -54, -60, -58, -29, -25, -39, -29, -12, 11, 25, 27, 6, -31, -33, -3, 27, 32, 21, 13, 16, 38, 60, 53, 26, 18, 28, 11, -2, 8, 26, 37, 34, 36, 42, 47, 31, 6, -14, -41, -61, -54, -49, -26, -30, -41, -40, -44, -54, -48, -23, -28, -41, -33, -7, 14, 26, 29, 3, -32, -27, 6, 33, 35, 18, 5, 21, 45, 61, 49, 25, 30, 22, 0, -5, 9, 37, 39, 27, 33, 47, 50, 31, 1, -22, -51, -65, -59, -45, -31, -40, -36, -29, -35, -49, -41, -28, -39, -44, -26, -8, 6, 27, 31, -5, -31, -18, 14, 33, 31, 17, 4, 25, 48, 57, 45, 32, 27, 9, -6, -5, 14, 43, 36, 29, 39, 51, 50, 31, 0, -32, -65, -73, -62, -37, -36, -46, -36, -23, -26, -37, -32, -35, -46, -42, -22, -11, 2, 30, 28, -8, -29, -12, 22, 33, 32, 15, 4, 25, 49, 58, 50, 36, 20, 2, -9, -3, 21, 43, 37, 32, 44, 55, 53, 33, -7, -42, -67, -72, -64, -43, -43, -46, -35, -17, -17, -24, -31, -40, -47, -39, -18, -15, 0, 33, 22, -14, -22, 5, 29, 29, 28, 11, 7, 23, 49, 54, 50, 37, 13, -6, -11, -6, 25, 44, 38, 26, 40, 57, 54, 28, -12, -48, -70, -73, -66, -43, -43, -43, -29, -12, -15, -16, -32, -48, -51, -38, -24, -19, 4, 31, 12, -16, -14, 21, 34, 24, 24, 13, 10, 27, 49, 53, 53, 33, 6, -9, -16, -4, 33, 48, 37, 24, 45, 61, 54, 23, -15, -60, -76, -76, -60, -48, -45, -38, -26, -11, -3, -5, -33, -49, -52, -35, -25, -21, 7, 24, 1, -15, -1, 34, 30, 23, 29, 17, 5, 26, 49, 55, 53, 26, -3, -16, -16, 4, 38, 43, 33, 33, 49, 59, 45, 19, -18, -63, -78, -79, -58, -50, -39, -31, -21, -11, -2, -3, -30, -49, -51, -35, -29, -20, 8, 12, -10, -11, 17, 37, 27, 29, 29, 13, 2, 33, 56, 55, 38, 18, -7, -19, -17, 13, 40, 42, 33, 35, 52, 58, 40, 10, -28, -68, -84, -78, -56, -47, -36, -30, -17, -7, 5, -4, -30, -49, -51, -34, -30, -18, 10, 1, -18, -9, 30, 39, 26, 32, 28, 9, 7, 38, 51, 45, 35, 16, -13, -28, -11, 27, 41, 41, 34, 45, 58, 54, 29, 7, -33, -69, -80, -78, -59, -43, -31, -24, -15, -3, 9, -4, -29, -51, -51, -33, -27, -8, 8, -13, -24, -1, 40, 41, 29, 31, 22, 7, 15, 46, 48, 38, 33, 11, -19, -28, -7, 26, 42, 36, 39, 54, 54, 48, 20, 3, -39, -68, -79, -78, -54, -37, -32, -27, -16, 5, 11, -6, -31, -50, -49, -33, -24, -3, -3, -29, -26, 13, 44, 36, 30, 32, 17, 7, 28, 43, 37, 31, 28, 4, -17, -27, -5, 24, 46, 43, 48, 56, 50, 41, 20, -1, -47, -64, -82, -78, -48, -35, -34, -26, -14, 6, 9, -10, -31, -46, -43, -33, -21, 1, -16, -38, -15, 24, 38, 35, 44, 33, 10, 15, 37, 43, 30, 22, 18, 4, -20, -29, 0, 30, 43, 48, 54, 52, 46, 35, 19, -9, -41, -60, -83, -73, -44, -29, -37, -27, -12, 6, 8, -10, -28, -45, -43, -25, -9, -3, -33, -43, -4, 32, 35, 37, 49, 24, 7, 26, 47, 35, 17, 11, 14, 3, -21, -30, 6, 30, 44, 60, 56, 44, 37, 33, 15, -11, -40, -63, -82, -61, -36, -33, -39, -26, -13, 0, 4, -9, -29, -42, -37, -18, -7, -13, -39, -34, 2, 30, 34, 45, 49, 16, 11, 37, 45, 26, 11, 8, 9, -1, -26, -25, 17, 31, 46, 62, 52, 42, 29, 26, 15, -12, -45, -64, -71, -48, -34, -35, -33, -27, -16, 1, 2, -10, -23, -41, -32, -12, -6, -29, -46, -28, 12, 26, 36, 54, 43, 10, 23, 52, 43, 18, -2, 5, 5, -7, -25, -11, 19, 22, 49, 61, 50, 40, 24, 20, 15, -10, -47, -62, -62, -45, -34, -30, -30, -23, -16, -6, -1, -8, -25, -38, -29, -9, -10, -39, -42, -19, 5, 23, 48, 57, 33, 7, 32, 57, 39, 8, -7, 3, -2, -16, -16, 1, 20, 22, 48, 55, 46, 39, 17, 16, 17, -9, -48, -58, -54, -40, -37, -28, -26, -22, -23, -5, 2, -11, -28, -37, -27, -10, -18, -44, -35, -18, 3, 31, 54, 52, 25, 13, 45, 61, 29, -4, -10, 0, -5, -16, -8, 4, 21, 21, 50, 54, 45, 31, 4, 20, 18, -15, -43, -48, -48, -39, -33, -28, -25, -22, -21, 0, -1, -19, -29, -29, -22, -11, -29, -42, -30, -17, 3, 38, 61, 46, 24, 25, 53, 58, 20, -10, -9, -5, -16, -12, 4, 11, 22, 17, 48, 51, 43, 16, 2, 18, 13, -15, -35, -46, -43, -38, -31, -23, -27, -24, -13, 3, -8, -25, -29, -27, -22, -18, -36, -38, -31, -19, 6, 46, 60, 36, 24, 33, 56, 44, 10, -8, -9, -12, -24, -7, 14, 23, 18, 11, 45, 47, 39, 13, 5, 16, 1, -19, -22, -39, -45, -45, -31, -20, -24, -16, -6, -3, -19, -24, -25, -26, -22, -24, -39, -35, -25, -13, 8, 54, 64, 36, 29, 41, 56, 36, 5, -12, -11, -14, -26, -6, 24, 33, 7, 12, 45, 44, 30, 13, 10, 17, -4, -17, -16, -34, -46, -50, -30, -20, -23, -12, 1, -11, -26, -27, -24, -21, -19, -34, -48, -32, -23, -10, 13, 66, 65, 33, 32, 48, 55, 25, 0, -8, -1, -18, -36, -4, 40, 33, -1, 17, 37, 35, 25, 10, 14, 10, -13, -15, -9, -26, -46, -51, -32, -18, -15, -4, 3, -17, -31, -28, -25, -20, -26, -48, -48, -27, -20, -13, 19, 71, 61, 28, 33, 56, 50, 12, -8, -2, 5, -24, -41, 2, 52, 29, -1, 24, 36, 26, 16, 14, 19, 6, -19, -12, 1, -21, -49, -50, -28, -12, -3, 2, -2, -25, -32, -29, -24, -14, -31, -61, -44, -17, -15, -9, 28, 72, 61, 25, 38, 61, 41, 7, -7, 4, 3, -32, -36, 9, 45, 21, 4, 30, 33, 15, 11, 18, 17, -1, -18, -7, -4, -22, -47, -45, -24, -6, 2, 5, -7, -27, -34, -28, -21, -14, -42, -69, -40, -11, -16, -3, 41, 68, 53, 29, 48, 61, 32, 0, -5, 8, 2, -33, -28, 9, 31, 16, 16, 34, 22, 0, 10, 24, 10, -9, -19, -6, -8, -26, -38, -34, -20, -10, 1, 11, -9, -33, -31, -32, -25, -18, -50, -65, -40, -15, -8, 13, 47, 65, 50, 33, 54, 62, 24, -2, 2, 12, -6, -31, -20, 12, 21, 10, 28, 34, 9, -5, 20, 20, -2, -13, -10, -4, -18, -33, -26, -16, -19, -14, 6, 8, -14, -31, -32, -29, -29, -31, -51, -69, -47, -12, 2, 21, 49, 56, 43, 45, 62, 54, 16, -2, 7, 9, -13, -22, -4, 12, 7, 13, 37, 33, 7, -4, 23, 9, -8, -8, -2, -8, -33, -38, -7, -1, -22, -19, 11, 7, -21, -29, -29, -29, -31, -32, -55, -80, -49, -7, 16, 31, 43, 45, 44, 56, 66, 45, 12, 2, 10, 3, -18, -13, 7, 9, -2, 17, 38, 22, 1, 5, 17, 4, -14, -12, -1, -11, -43, -38, 6, 5, -22, -15, 12, 0, -23, -26, -28, -31, -32, -36, -60, -82, -46, 3, 24, 35, 38, 41, 46, 59, 62, 41, 13, -1, 3, -6, -18, 3, 22, 2, -9, 20, 36, 18, 10, 7, 4, -5, -17, -9, -2, -18, -55, -30, 17, 6, -20, -10, 6, -5, -16, -26, -32, -27, -30, -42, -69, -84, -41, 13, 31, 42, 37, 38, 45, 63, 65, 41, 12, 3, 1, -18, -10, 23, 27, -2, -12, 17, 36, 26, 13, 4, -2, -5, -14, -14, -11, -26, -54, -19, 21, 8, -16, -8, 6, -7, -20, -30, -33, -24, -33, -50, -74, -82, -32, 18, 34, 42, 38, 34, 50, 69, 58, 34, 16, 7, -9, -29, -2, 41, 32, -7, -15, 11, 34, 30, 9, 2, -3, -7, -23, -21, -15, -30, -52, -10, 18, 10, -8, -4, 5, -4, -25, -33, -26, -22, -42, -59, -79, -72, -20, 23, 36, 41, 37, 34, 54, 74, 53, 22, 17, 15, -17, -34, 10, 52, 37, -8, -11, 12, 33, 23, 8, 4, -1, -16, -31, -25, -18, -38, -49, -3, 19, 11, -4, 0, 7, -8, -34, -31, -19, -26, -52, -62, -79, -55, -7, 23, 41, 47, 41, 33, 61, 75, 43, 22, 21, 13, -26, -33, 17, 58, 39, -6, -8, 13, 27, 10, 5, 13, -2, -32, -43, -32, -19, -38, -36, -3, 12, 4, 4, 13, 6, -22, -41, -31, -13, -33, -59, -71, -76, -35, 2, 20, 39, 53, 47, 39, 60, 62, 37, 26, 22, 5, -33, -29, 26, 64, 40, 0, -5, 12, 21, 8, 16, 10, -13, -39, -49, -37, -25, -41, -30, -6, 9, 9, 13, 23, 0, -30, -44, -26, -13, -45, -67, -76, -68, -20, 10, 19, 39, 55, 50, 46, 57, 50, 37, 30, 16, -3, -34, -22, 34, 65, 40, 13, -2, 6, 19, 12, 21, 5, -23, -49, -52, -38, -33, -36, -24, -9, 10, 12, 25, 23, -11, -29, -43, -27, -21, -55, -73, -77, -50, -2, 19, 19, 35, 59, 59, 49, 45, 40, 36, 27, 4, -10, -24, -12, 31, 59, 44, 22, -5, 4, 19, 20, 12, -4, -27, -52, -50, -45, -39, -24, -23, -13, 16, 20, 30, 15, -16, -28, -37, -30, -36, -64, -79, -73, -28, 17, 24, 14, 36, 65, 68, 45, 33, 39, 40, 22, -2, -5, -11, -11, 28, 58, 57, 20, -13, 0, 27, 23, 1, -15, -35, -58, -55, -52, -39, -20, -22, -9, 20, 29, 30, 10, -15, -31, -39, -32, -48, -72, -86, -59, -4, 27, 19, 17, 44, 77, 69, 31, 26, 40, 38, 14, -6, 0, 1, -11, 26, 67, 62, 10, -18, 6, 31, 20, -5, -22, -44, -66, -61, -50, -31, -17, -24, -7, 24, 34, 31, 3, -17, -31, -36, -40, -61, -73, -76, -46, 11, 34, 20, 22, 56, 83, 60, 22, 24, 46, 32, 5, -4, 9, 0, -8, 31, 73, 53, 0, -13, 16, 28, 14, -15, -31, -51, -74, -64, -43, -25, -22, -25, -1, 30, 37, 20, -2, -20, -36, -39, -55, -69, -75, -69, -32, 21, 36, 22, 31, 63, 76, 50, 22, 25, 49, 29, 3, 4, 9, 2, 0, 43, 74, 37, -8, -1, 28, 24, 8, -22, -42, -65, -80, -60, -31, -25, -31, -24, 8, 41, 37, 10, -3, -22, -40, -45, -60, -69, -69, -55, -15, 32, 37, 25, 42, 72, 70, 37, 21, 32, 41, 20, 5, 15, 8, 0, 9, 46, 62, 26, -7, 8, 28, 21, 4, -29, -53, -79, -82, -57, -25, -27, -32, -21, 14, 48, 35, -1, -7, -24, -44, -52, -70, -69, -60, -38, 1, 34, 33, 32, 57, 70, 58, 34, 26, 31, 31, 16, 14, 14, 3, 8, 25, 47, 47, 18, -2, 13, 25, 19, -2, -33, -64, -87, -83, -53, -24, -29, -32, -17, 21, 46, 27, -4, -12, -30, -51, -61, -73, -60, -46, -17, 9, 25, 32, 47, 69, 61, 48, 41, 30, 26, 24, 18, 24, 15, 2, 14, 37, 42, 34, 17, 9, 19, 20, 11, -7, -35, -79, -97, -79, -45, -21, -29, -33, -12, 26, 43, 27, -3, -15, -43, -58, -66, -69, -52, -37, -2, 16, 24, 38, 61, 72, 56, 43, 41, 32, 28, 22, 22, 26, 12, 1, 23, 45, 34, 21, 8, 17, 22, 19, 4, -18, -47, -93, -97, -70, -40, -29, -33, -22, -5, 24, 44, 19, -6, -23, -53, -60, -74, -63, -41, -20, 10, 18, 19, 40, 70, 70, 47, 41, 43, 37, 27, 14, 24, 32, 10, 1, 29, 44, 27, 12, 7, 28, 32, 9, -11, -27, -56, -100, -94, -64, -43, -38, -31, -7, 0, 27, 41, 11, -7, -35, -60, -62, -75, -54, -29, -5, 17, 22, 14, 46, 80, 72, 46, 42, 44, 42, 24, 16, 31, 32, 9, 4, 33, 45, 22, 5, 8, 41, 34, 0, -22, -36, -69, -100, -92, -65, -40, -44, -25, 0, 5, 28, 36, 4, -12, -50, -64, -64, -68, -46, -19, 2, 25, 28, 19, 44, 72, 67, 46, 45, 44, 39, 21, 21, 38, 29, 1, 9, 39, 39, 13, -4, 9, 54, 41, -11, -38, -51, -76, -91, -92, -65, -44, -47, -17, 12, 11, 21, 27, 6, -24, -59, -65, -67, -61, -40, -17, 8, 31, 26, 20, 49, 74, 65, 45, 48, 47, 36, 25, 28, 36, 25, 5, 19, 42, 28, 6, -2, 21, 56, 27, -22, -45, -62, -83, -92, -84, -65, -49, -37, -8, 15, 16, 22, 23, -1, -38, -65, -66, -65, -51, -35, -15, 20, 42, 26, 25, 51, 70, 60, 45, 52, 47, 25, 25, 39, 33, 24, 16, 31, 37, 14, 3, 2, 33, 55, 14, -35, -55, -67, -84, -88, -84, -68, -47, -28, -1, 17, 22, 24, 17, -14, -54, -66, -64, -61, -46, -32, -10, 26, 45, 24, 29, 52, 66, 57, 49, 56, 41, 16, 29, 46, 31, 22, 24, 37, 30, 12, -1, 5, 40, 39, 1, -41, -63, -72, -89, -89, -77, -62, -48, -17, 5, 13, 26, 31, 10, -29, -62, -64, -65, -54, -41, -25, -4, 32, 52, 29, 32, 55, 61, 55, 56, 57, 35, 17, 33, 40, 28, 27, 37, 36, 26, 14, -3, 13, 41, 22, -13, -45, -65, -78, -90, -87, -70, -56, -47, -12, 9, 18, 35, 27, -5, -41, -63, -61, -65, -52, -37, -17, 5, 35, 52, 34, 38, 55, 58, 53, 60, 54, 31, 21, 33, 34, 30, 35, 40, 32, 29, 15, -4, 18, 30, 11, -25, -53, -69, -85, -91, -82, -66, -54, -36, -7, 6, 20, 40, 19, -17, -52, -63, -60, -65, -50, -32, -11, 9, 34, 50, 40, 46, 51, 56, 60, 60, 50, 28, 23, 33, 33, 31, 40, 43, 38, 38, 13, -6, 13, 19, -2, -34, -57, -78, -91, -85, -73, -63, -55, -28, -1, 6, 26, 39, 13, -28, -56, -61, -55, -61, -43, -27, -13, 12, 38, 48, 49, 54, 46, 52, 64, 64, 48, 27, 22, 28, 33, 36, 44, 42, 39, 44, 15, -3, 10, 6, -19, -46, -60, -81, -92, -83, -73, -52, -44, -22, -5, 5, 38, 37, -6, -41, -55, -54, -49, -53, -45, -28, -9, 19, 41, 47, 56, 57, 41, 56, 69, 64, 42, 26, 23, 27, 36, 39, 44, 39, 48, 53, 12, -4, 2, -8, -33, -61, -72, -84, -87, -80, -73, -49, -36, -12, -5, 9, 42, 24, -15, -44, -50, -51, -51, -51, -45, -26, -4, 20, 40, 47, 64, 58, 38, 61, 71, 55, 37, 32, 23, 30, 34, 39, 50, 43, 58, 53, 9, 4, -3, -27, -49, -71, -79, -79, -79, -82, -70, -44, -26, -7, -5, 16, 36, 9, -18, -40, -47, -49, -45, -42, -43, -20, 1, 21, 40, 53, 72, 54, 36, 64, 66, 41, 30, 36, 26, 28, 31, 44, 57, 48, 62, 45, 13, 3, -14, -47, -65, -77, -87, -78, -71, -75, -68, -43, -16, -2, -1, 18, 20, -4, -18, -37, -46, -50, -36, -39, -46, -15, 7, 23, 41, 62, 72, 49, 41, 69, 59, 33, 29, 38, 24, 28, 31, 52, 59, 49, 61, 45, 21, 2, -31, -64, -73, -78, -89, -79, -71, -77, -62, -36, -8, 3, 5, 15, 5, -10, -17, -34, -49, -50, -27, -37, -43, -12, 14, 25, 45, 67, 68, 48, 48, 64, 48, 27, 33, 41, 25, 24, 32, 64, 66, 51, 62, 41, 21, -7, -43, -77, -81, -83, -87, -74, -71, -77, -54, -29, -1, 7, 13, 12, -6, -9, -18, -38, -54, -44, -21, -37, -41, -8, 16, 28, 53, 73, 61, 46, 52, 60, 35, 25, 34, 38, 20, 25, 42, 73, 62, 60, 58, 39, 22, -19, -54, -85, -88, -95, -88, -65, -69, -73, -47, -22, 3, 14, 15, -5, -14, -6, -23, -42, -52, -34, -19, -42, -38, 0, 18, 30, 62, 76, 61, 49, 52, 49, 26, 23, 34, 33, 22, 21, 50, 78, 68, 66, 47, 40, 22, -23, -66, -95, -102, -97, -74, -61, -77, -68, -36, -12, 9, 15, 13, -18, -14, -5, -31, -50, -44, -21, -25, -49, -25, 8, 16, 30, 70, 82, 56, 45, 55, 39, 21, 25, 31, 24, 21, 28, 64, 81, 68, 64, 47, 44, 15, -30, -77, -101, -104, -96, -71, -66, -76, -53, -22, -9, 6, 22, 10, -22, -15, -13, -38, -48, -32, -9, -33, -49, -14, 10, 11, 37, 77, 85, 51, 44, 48, 30, 18, 21, 26, 16, 21, 36, 71, 76, 73, 68, 48, 35, 4, -38, -81, -103, -109, -91, -67, -71, -69, -40, -15, -12, 3, 23, 7, -23, -17, -24, -41, -45, -24, -11, -46, -46, -1, 10, 8, 49, 84, 83, 48, 50, 48, 27, 16, 18, 20, 14, 26, 44, 72, 75, 82, 71, 47, 26, -6, -45, -80, -107, -110, -88, -70, -69, -58, -28, -9, -12, 2, 23, 2, -21, -19, -35, -38, -33, -13, -17, -50, -35, 8, 9, 10, 57, 89, 74, 45, 52, 41, 24, 15, 11, 14, 13, 22, 54, 72, 74, 86, 72, 41, 13, -14, -47, -86, -113, -111, -88, -72, -67, -42, -18, -11, -11, 2, 18, -2, -17, -27, -44, -37, -28, -12, -26, -49, -22, 9, 3, 21, 69, 87, 63, 46, 49, 36, 24, 13, 11, 11, 8, 26, 64, 68, 76, 89, 74, 38, 3, -17, -44, -86, -117, -114, -86, -65, -58, -38, -19, -7, 0, 8, 9, -5, -20, -37, -45, -29, -19, -15, -36, -39, -10, 6, 4, 33, 79, 81, 55, 48, 42, 30, 23, 10, 13, 10, 3, 27, 62, 60, 76, 88, 68, 30, -5, -21, -49, -89, -120, -115, -81, -54, -46, -34, -14, -1, 7, 9, 1, -6, -18, -45, -52, -29, -16, -17, -35, -36, -12, 5, 11, 47, 81, 72, 53, 51, 39, 28, 24, 9, 13, 7, 5, 36, 57, 55, 82, 90, 62, 31, -10, -29, -55, -91, -121, -115, -76, -47, -38, -34, -13, 1, 13, 9, -4, -9, -17, -49, -56, -26, -9, -12, -33, -40, -17, 12, 25, 57, 71, 62, 52, 50, 35, 22, 21, 14, 11, -2, 10, 41, 50, 48, 85, 87, 66, 29, -15, -34, -64, -97, -121, -108, -73, -43, -37, -28, -7, 7, 16, 6, -7, -5, -15, -59, -56, -19, -4, -14, -37, -42, -10, 21, 38, 66, 63, 57, 52, 49, 28, 22, 28, 16, 5, -3, 22, 47, 38, 45, 79, 85, 68, 23, -16, -34, -70, -100, -122, -107, -62, -39, -38, -25, -4, 15, 18, 2, -3, 0, -27, -70, -51, -17, -3, -16, -44, -40, -1, 27, 45, 67, 57, 54, 48, 39, 17, 18, 28, 17, 3, -3, 27, 49, 37, 42, 69, 86, 66, 16, -17, -37, -72, -99, -117, -101, -55, -39, -36, -24, 1, 20, 13, 4, 4, -5, -46, -74, -43, -9, -4, -28, -49, -33, 6, 33, 63, 68, 54, 53, 49, 33, 18, 21, 24, 15, 7, 9, 33, 42, 35, 39, 70, 85, 55, 10, -16, -40, -75, -98, -113, -92, -47, -38, -35, -21, 1, 21, 15, 8, 7, -14, -62, -70, -30, -11, -15, -34, -49, -23, 9, 39, 64, 58, 51, 56, 42, 20, 16, 19, 16, 16, 4, 13, 40, 46, 33, 31, 65, 83, 49, 3, -24, -41, -73, -98, -105, -77, -45, -41, -30, -13, 7, 19, 12, 13, 8, -26, -68, -61, -22, -14, -25, -38, -40, -18, 12, 47, 68, 59, 49, 51, 42, 19, 17, 17, 12, 13, 5, 18, 41, 47, 26, 26, 67, 78, 44, -2, -31, -47, -71, -97, -96, -67, -44, -42, -29, -11, 13, 21, 13, 17, 8, -34, -68, -54, -17, -18, -36, -43, -35, -12, 14, 50, 69, 56, 49, 44, 35, 16, 13, 17, 13, 13, 6, 27, 46, 50, 24, 28, 66, 64, 28, 0, -25, -49, -75, -99, -87, -54, -42, -38, -28, -8, 20, 19, 11, 17, 1, -41, -62, -49, -18, -27, -41, -39, -29, -8, 15, 55, 73, 55, 42, 42, 33, 16, 12, 12, 9, 6, 14, 40, 52, 48, 21, 31, 60, 50, 23, 0, -32, -60, -76, -90, -73, -44, -39, -36, -32, 1, 29, 20, 6, 13, -3, -41, -53, -43, -21, -34, -47, -38, -22, -2, 22, 54, 65, 49, 38, 42, 32, 17, 12, 7, 6, 3, 21, 48, 53, 42, 24, 39, 53, 38, 15, -3, -38, -65, -76, -85, -59, -36, -35, -40, -26, 15, 26, 12, 6, 10, -12, -40, -49, -33, -26, -41, -53, -36, -12, 5, 28, 50, 61, 46, 34, 37, 31, 20, 12, 1, 0, 5, 32, 53, 56, 41, 23, 39, 48, 35, 13, -10, -44, -72, -81, -79, -50, -27, -34, -41, -18, 20, 27, 12, 5, 1, -19, -36, -40, -22, -34, -50, -55, -33, -3, 14, 33, 52, 54, 35, 27, 36, 37, 25, 7, -13, 1, 19, 41, 50, 50, 38, 32, 43, 41, 32, 6, -17, -46, -69, -79, -75, -43, -20, -34, -38, -8, 23, 26, 12, 6, -8, -23, -30, -30, -23, -46, -56, -52, -29, 6, 23, 35, 44, 47, 31, 25, 33, 40, 26, -4, -22, 3, 28, 39, 40, 50, 40, 28, 34, 37, 28, 0, -22, -50, -70, -81, -72, -34, -22, -36, -33, 2, 24, 25, 12, 4, -15, -24, -26, -25, -23, -46, -56, -50, -24, 10, 33, 36, 40, 35, 21, 25, 43, 47, 25, -13, -25, 11, 40, 36, 40, 56, 38, 27, 31, 33, 24, -4, -24, -53, -71, -80, -59, -34, -27, -31, -27, 8, 24, 25, 17, 2, -22, -25, -26, -19, -24, -51, -58, -40, -9, 14, 37, 36, 35, 27, 14, 28, 48, 46, 19, -19, -24, 18, 40, 29, 41, 50, 29, 29, 27, 33, 18, -12, -29, -53, -71, -75, -48, -33, -32, -25, -14, 13, 24, 19, 17, 2, -25, -28, -28, -18, -28, -55, -59, -30, -3, 20, 41, 34, 24, 15, 15, 36, 49, 39, 17, -17, -17, 22, 41, 33, 45, 38, 26, 30, 24, 27, 10, -11, -34, -58, -70, -66, -38, -32, -36, -21, -2, 14, 28, 19, 14, 0, -25, -29, -28, -17, -30, -57, -51, -22, 3, 23, 39, 34, 15, 11, 17, 38, 46, 39, 15, -18, -14, 27, 40, 37, 45, 32, 28, 30, 29, 28, 1, -16, -38, -55, -65, -62, -37, -31, -34, -17, 9, 18, 27, 18, 9, -1, -22, -35, -29, -17, -32, -57, -45, -17, 15, 30, 30, 25, 8, 10, 19, 35, 46, 37, 4, -19, -8, 31, 33, 33, 42, 28, 22, 24, 29, 23, -6, -21, -43, -54, -59, -55, -32, -34, -39, -10, 19, 30, 25, 9, 2, -2, -20, -38, -30, -23, -41, -51, -35, -12, 24, 32, 22, 12, 8, 16, 23, 32, 48, 33, 1, -16, 0, 29, 30, 33, 36, 24, 23, 22, 33, 14, -14, -20, -42, -55, -50, -44, -27, -38, -41, -3, 31, 35, 23, 5, -2, -4, -15, -34, -33, -38, -47, -40, -26, -3, 31, 31, 9, 2, 13, 14, 20, 38, 53, 27, -6, -14, 11, 30, 23, 32, 28, 25, 22, 24, 32, 5, -20, -26, -45, -49, -40, -36, -37, -48, -40, 8, 40, 37, 16, -3, -6, -2, -9, -27, -42, -52, -48, -32, -21, 8, 39, 28, -2, -5, 13, 17, 23, 40, 45, 19, -4, -3, 18, 15, 19, 33, 30, 29, 22, 21, 22, 0, -17, -27, -46, -48, -33, -31, -38, -53, -33, 23, 43, 31, 11, -7, -5, -3, -8, -26, -49, -59, -48, -25, -14, 15, 41, 23, -8, -6, 11, 10, 26, 49, 41, 12, 0, 10, 19, 4, 22, 31, 25, 25, 24, 20, 12, -4, -10, -37, -50, -37, -23, -26, -43, -55, -18, 34, 41, 28, 10, -9, -6, -3, -8, -27, -57, -62, -37, -15, -8, 24, 44, 23, -10, -6, 3, 8, 39, 55, 30, 12, 11, 20, 8, 3, 27, 26, 20, 21, 24, 19, -1, -10, -14, -42, -47, -25, -14, -28, -49, -50, -5, 38, 38, 23, 9, -11, -9, -1, -5, -33, -64, -59, -34, -14, -2, 32, 49, 17, -11, -6, -2, 11, 46, 46, 19, 16, 23, 24, -3, 3, 29, 29, 16, 17, 22, 11, -12, -12, -18, -50, -43, -15, -11, -30, -53, -38, 10, 31, 31, 25, 3, -16, -3, 3, -8, -41, -67, -53, -24, -14, 3, 35, 46, 17, -2, -7, -9, 16, 49, 41, 20, 22, 34, 21, -5, 5, 31, 29, 12, 14, 18, 8, -22, -17, -20, -52, -38, -13, -19, -32, -48, -25, 11, 23, 29, 26, 1, -14, 1, 1, -18, -47, -60, -47, -31, -11, 13, 45, 39, 8, -2, -2, -11, 16, 43, 35, 25, 34, 40, 18, -7, 6, 34, 28, 14, 7, 11, 2, -23, -25, -29, -51, -30, -11, -24, -38, -40, -15, 9, 18, 29, 32, -1, -10, 0, -9, -27, -48, -52, -46, -30, -2, 27, 47, 30, 10, 7, -6, -15, 12, 35, 28, 30, 45, 42, 19, -4, 11, 29, 21, 6, 1, 3, -3, -27, -31, -34, -40, -22, -18, -31, -35, -30, -18, 5, 19, 32, 28, -9, -7, 1, -14, -30, -42, -45, -47, -28, 7, 38, 45, 23, 14, 20, -2, -24, 7, 32, 30, 37, 43, 41, 22, 7, 18, 22, 14, 4, -7, 4, -7, -36, -37, -37, -27, -15, -26, -34, -34, -29, -18, 4, 19, 31, 20, -4, 0, -3, -21, -32, -37, -41, -40, -25, 14, 49, 44, 18, 19, 25, -1, -19, 5, 26, 35, 38, 46, 41, 18, 18, 16, 13, 12, 2, -5, -3, -23, -44, -37, -32, -20, -20, -33, -28, -32, -32, -16, 1, 17, 31, 17, -2, 2, -3, -22, -33, -39, -40, -34, -23, 15, 56, 44, 15, 27, 23, -4, -14, 2, 22, 38, 37, 48, 40, 25, 24, 15, 11, 2, -2, -3, -15, -31, -40, -37, -33, -17, -17, -28, -29, -41, -34, -7, 1, 13, 31, 17, -2, 4, 1, -20, -35, -47, -37, -24, -10, 22, 52, 38, 26, 35, 26, -2, -9, 4, 23, 40, 38, 46, 39, 32, 31, 16, 2, -7, -8, -2, -21, -38, -44, -38, -31, -18, -15, -29, -35, -45, -32, -1, -3, 4, 30, 16, 3, 8, 4, -20, -42, -48, -30, -17, -8, 21, 49, 41, 30, 38, 23, -2, -5, 1, 21, 35, 37, 44, 40, 40, 33, 17, 1, -13, -10, -9, -35, -41, -41, -39, -33, -19, -12, -27, -40, -48, -28, -4, -10, 10, 28, 15, 9, 12, 5, -24, -43, -43, -23, -18, 0, 26, 47, 43, 35, 40, 20, -1, 1, 4, 20, 28, 37, 42, 42, 46, 31, 22, 8, -17, -15, -15, -42, -41, -37, -44, -37, -16, -13, -33, -41, -41, -20, -11, -17, 10, 18, 13, 16, 17, 1, -24, -38, -38, -27, -21, 9, 29, 46, 44, 43, 38, 18, 3, 6, 6, 12, 19, 38, 41, 47, 44, 28, 29, 11, -26, -25, -27, -45, -39, -39, -48, -41, -18, -13, -33, -38, -36, -21, -19, -14, 13, 11, 11, 26, 17, -6, -25, -32, -32, -35, -14, 21, 31, 38, 49, 49, 34, 19, 13, 10, 4, 9, 20, 37, 41, 45, 39, 29, 35, 6, -28, -28, -35, -43, -37, -42, -50, -44, -20, -20, -37, -37, -27, -16, -23, -11, 10, 5, 17, 36, 16, -16, -23, -21, -33, -38, -5, 23, 28, 35, 55, 55, 31, 17, 18, 12, 3, 4, 21, 33, 41, 45, 31, 32, 39, 3, -29, -35, -41, -40, -38, -45, -55, -45, -26, -31, -36, -26, -22, -22, -29, 1, 9, -1, 24, 39, 8, -19, -17, -14, -32, -34, 5, 29, 29, 35, 58, 51, 32, 29, 23, 11, 1, 6, 29, 37, 38, 36, 24, 43, 39, -2, -32, -44, -45, -36, -36, -45, -55, -51, -37, -35, -30, -22, -20, -32, -24, 6, 2, 3, 30, 36, 3, -17, -16, -18, -29, -24, 10, 31, 25, 34, 58, 44, 33, 37, 26, 8, 5, 10, 37, 36, 35, 29, 22, 47, 36, -6, -36, -51, -49, -34, -38, -48, -58, -53, -46, -42, -24, -23, -22, -32, -13, 4, -7, 8, 35, 30, 6, -14, -20, -19, -21, -20, 14, 34, 29, 43, 52, 37, 39, 43, 24, 8, 7, 15, 45, 33, 36, 24, 25, 43, 25, -10, -39, -53, -47, -34, -39, -53, -56, -54, -56, -42, -21, -23, -29, -25, -5, 1, -10, 12, 35, 27, 7, -14, -25, -19, -11, -10, 13, 31, 37, 44, 42, 37, 45, 44, 24, 14, 13, 24, 40, 28, 35, 23, 31, 35, 15, -16, -38, -53, -45, -37, -48, -56, -54, -63, -63, -40, -23, -24, -27, -19, 3, 1, -11, 14, 33, 24, 5, -16, -28, -17, -6, -1, 15, 38, 39, 38, 29, 36, 54, 42, 20, 20, 19, 32, 38, 30, 31, 23, 33, 23, -1, -17, -35, -44, -43, -47, -51, -51, -56, -71, -67, -45, -28, -23, -23, -13, 12, -1, -15, 15, 33, 20, -2, -22, -25, -17, -3, 10, 24, 46, 44, 31, 26, 41, 53, 42, 23, 23, 26, 39, 37, 32, 24, 28, 36, 11, -7, -19, -38, -39, -37, -49, -54, -51, -62, -76, -68, -51, -28, -19, -21, 1, 22, -3, -11, 14, 25, 16, -5, -25, -25, -15, -2, 20, 36, 51, 42, 19, 19, 43, 58, 43, 25, 21, 35, 46, 41, 34, 17, 26, 33, 5, -15, -25, -39, -34, -37, -55, -50, -49, -69, -80, -67, -50, -31, -18, -12, 12, 17, -5, -5, 14, 17, 6, -15, -27, -22, -14, 3, 37, 49, 48, 40, 22, 22, 36, 51, 44, 29, 22, 42, 49, 41, 29, 16, 29, 31, -9, -30, -33, -35, -29, -38, -55, -45, -54, -79, -80, -65, -51, -34, -16, -2, 18, 18, 5, 7, 8, 6, 3, -19, -21, -22, -19, 12, 51, 53, 48, 39, 22, 18, 36, 46, 42, 35, 31, 44, 46, 42, 31, 24, 35, 21, -25, -39, -33, -30, -24, -41, -53, -47, -60, -81, -81, -63, -53, -40, -14, 6, 24, 20, 8, 7, 0, -1, -4, -21, -23, -29, -16, 30, 60, 55, 50, 37, 19, 19, 35, 43, 46, 37, 29, 43, 49, 43, 32, 27, 31, 13, -35, -46, -36, -26, -28, -44, -52, -47, -65, -84, -84, -68, -49, -27, 0, 10, 15, 19, 15, 9, -3, -10, -16, -20, -26, -28, -2, 41, 59, 62, 56, 37, 16, 15, 31, 43, 50, 42, 30, 41, 49, 49, 38, 28, 23, 5, -42, -55, -42, -21, -22, -40, -49, -54, -71, -86, -81, -62, -44, -21, 5, 17, 16, 25, 23, 0, -13, -17, -17, -24, -32, -21, 15, 45, 58, 66, 52, 33, 15, 9, 35, 42, 44, 44, 36, 38, 50, 52, 40, 28, 16, -11, -48, -60, -43, -22, -21, -40, -53, -58, -78, -90, -79, -61, -42, -9, 14, 15, 16, 22, 21, -4, -20, -21, -19, -30, -31, -10, 26, 54, 63, 69, 51, 33, 12, 13, 40, 42, 45, 42, 33, 36, 53, 57, 44, 24, 3, -24, -53, -63, -45, -21, -15, -39, -57, -63, -78, -89, -76, -55, -34, 3, 18, 9, 16, 21, 15, -8, -26, -28, -25, -32, -24, 4, 34, 56, 67, 75, 48, 22, 7, 23, 44, 39, 40, 40, 35, 40, 59, 59, 44, 18, -6, -31, -54, -58, -44, -20, -13, -43, -63, -69, -80, -88, -71, -48, -21, 12, 16, 12, 18, 13, 6, -12, -27, -32, -30, -34, -20, 13, 46, 63, 74, 73, 40, 15, 13, 39, 46, 33, 32, 35, 36, 48, 58, 61, 43, 16, -13, -36, -57, -62, -41, -22, -16, -42, -66, -73, -79, -85, -65, -38, -7, 13, 9, 7, 16, 11, -2, -18, -36, -39, -26, -25, -16, 21, 53, 64, 74, 68, 36, 19, 22, 38, 44, 32, 28, 32, 38, 52, 60, 56, 43, 13, -25, -39, -54, -52, -35, -30, -27, -46, -70, -79, -80, -79, -58, -26, 3, 15, 6, 0, 12, 6, -8, -27, -45, -39, -17, -16, -13, 28, 57, 67, 71, 57, 37, 22, 25, 41, 46, 29, 24, 34, 44, 56, 55, 52, 44, 7, -27, -38, -48, -44, -35, -31, -29, -46, -77, -83, -73, -70, -48, -15, 6, 9, 1, 1, 9, -3, -20, -41, -48, -30, -5, -14, -9, 39, 63, 70, 66, 47, 36, 25, 32, 40, 43, 26, 21, 36, 47, 59, 50, 49, 35, 0, -26, -36, -44, -41, -36, -35, -33, -50, -79, -79, -66, -63, -36, -8, 6, -3, -9, 2, 3, -13, -30, -49, -46, -18, -2, -15, 4, 42, 58, 65, 61, 50, 38, 28, 37, 40, 38, 28, 30, 38, 48, 50, 42, 46, 28, -3, -28, -37, -36, -36, -39, -36, -37, -59, -79, -69, -62, -52, -24, -2, 3, -12, -11, 4, -5, -29, -42, -53, -39, -12, -4, -4, 14, 37, 52, 63, 58, 50, 37, 34, 37, 36, 37, 38, 36, 35, 47, 46, 44, 42, 18, -7, -30, -34, -32, -34, -41, -37, -45, -66, -74, -64, -57, -36, -12, 1, -8, -23, -7, 6, -18, -39, -49, -53, -29, -5, -1, 10, 19, 30, 46, 59, 58, 50, 36, 37, 37, 32, 40, 46, 38, 34, 44, 42, 41, 36, 9, -9, -27, -29, -26, -34, -40, -40, -56, -69, -66, -56, -46, -22, -7, -7, -19, -21, 3, 1, -35, -48, -53, -49, -22, -3, 12, 23, 18, 22, 46, 66, 59, 47, 38, 43, 35, 30, 46, 51, 39, 33, 41, 37, 42, 24, 2, -8, -22, -23, -24, -33, -39, -50, -66, -69, -59, -49, -31, -13, -10, -17, -25, -16, 1, -17, -50, -55, -58, -42, -17, -1, 20, 31, 14, 15, 48, 70, 59, 42, 38, 45, 33, 33, 51, 53, 36, 35, 37, 36, 37, 12, 0, -9, -16, -18, -22, -33, -42, -59, -67, -62, -52, -40, -20, -11, -15, -23, -23, -11, -3, -28, -51, -59, -61, -38, -14, 4, 26, 30, 10, 18, 53, 71, 56, 40, 42, 45, 32, 34, 53, 52, 37, 36, 32, 37, 32, 10, -3, -10, -10, -11, -17, -31, -46, -62, -63, -54, -44, -30, -14, -14, -23, -27, -22, -11, -11, -35, -51, -65, -59, -32, -11, 11, 29, 25, 8, 24, 63, 73, 51, 38, 46, 44, 29, 34, 51, 51, 39, 34, 27, 34, 23, 3, -5, -9, -6, -10, -18, -33, -51, -66, -60, -50, -35, -20, -10, -21, -33, -29, -17, -9, -20, -39, -55, -71, -57, -26, -7, 11, 23, 22, 11, 35, 70, 71, 46, 39, 48, 42, 29, 33, 51, 47, 38, 31, 28, 35, 17, 0, -12, -7, 0, -4, -15, -36, -56, -67, -56, -42, -26, -15, -12, -29, -36, -28, -15, -13, -25, -40, -58, -70, -49, -23, -6, 8, 19, 17, 18, 49, 76, 66, 40, 42, 49, 39, 25, 35, 51, 43, 40, 30, 31, 32, 15, -1, -14, -7, 1, -2, -17, -40, -59, -61, -51, -38, -21, -10, -17, -34, -35, -28, -18, -17, -24, -40, -64, -65, -40, -18, -8, 5, 13, 17, 31, 61, 75, 60, 41, 43, 47, 34, 20, 36, 47, 43, 41, 31, 32, 26, 7, -7, -16, -6, 0, -3, -22, -44, -60, -56, -47, -34, -19, -8, -20, -39, -40, -27, -18, -20, -29, -44, -63, -56, -38, -23, -11, 4, 14, 21, 42, 65, 71, 59, 45, 42, 34, 21, 20, 42, 48, 44, 41, 31, 34, 24, 6, -10, -20, -11, 4, 0, -20, -48, -57, -47, -39, -30, -17, -4, -24, -43, -40, -26, -19, -24, -29, -45, -59, -51, -37, -25, -14, 3, 15, 27, 51, 72, 76, 61, 44, 38, 23, 12, 21, 43, 46, 45, 40, 31, 35, 21, 5, -17, -22, -13, 3, 1, -24, -51, -52, -43, -37, -28, -8, -7, -38, -46, -36, -21, -21, -31, -33, -45, -51, -47, -40, -30, -13, 4, 14, 33, 60, 76, 76, 61, 47, 30, 16, 8, 20, 40, 45, 48, 37, 37, 37, 22, 3, -19, -20, -10, 4, -6, -30, -49, -44, -41, -38, -23, -1, -14, -41, -44, -36, -22, -26, -35, -33, -45, -52, -48, -40, -32, -9, 6, 18, 35, 65, 85, 80, 62, 46, 24, 6, -1, 23, 41, 48, 45, 31, 42, 40, 23, -6, -21, -15, -6, 0, -13, -31, -44, -41, -38, -32, -15, 0, -22, -40, -41, -36, -24, -31, -28, -32, -46, -49, -47, -43, -30, -6, 9, 19, 46, 77, 87, 77, 61, 42, 18, -2, -7, 22, 39, 51, 41, 32, 43, 35, 13, -18, -18, -10, -5, -8, -21, -29, -39, -42, -41, -23, -3, -3, -32, -39, -38, -34, -31, -35, -23, -32, -46, -50, -51, -46, -26, 0, 12, 20, 54, 87, 91, 72, 60, 38, 13, -10, -11, 24, 44, 52, 43, 39, 45, 34, 2, -19, -8, -1, -8, -19, -19, -25, -35, -42, -39, -17, 7, -7, -38, -36, -36, -37, -37, -31, -20, -34, -49, -53, -50, -43, -19, 6, 10, 25, 66, 91, 84, 67, 60, 36, 1, -18, -10, 27, 48, 52, 42, 42, 38, 25, -3, -18, -5, -2, -13, -22, -24, -28, -35, -45, -35, -4, 14, -17, -41, -36, -33, -35, -41, -29, -20, -38, -51, -54, -46, -33, -14, 6, 14, 37, 74, 87, 76, 65, 64, 29, -9, -22, -7, 23, 52, 55, 46, 42, 25, 17, -5, -12, -4, -3, -17, -25, -33, -36, -33, -39, -30, 5, 12, -25, -37, -33, -34, -42, -41, -25, -22, -41, -52, -53, -40, -25, -10, 11, 21, 43, 72, 78, 74, 69, 58, 15, -13, -15, -4, 22, 54, 58, 53, 41, 15, 6, -2, -1, -3, -6, -18, -24, -42, -40, -29, -32, -20, 13, 8, -25, -35, -34, -29, -42, -43, -27, -27, -42, -51, -50, -30, -14, -5, 17, 26, 46, 70, 72, 72, 69, 48, 2, -13, -9, -3, 19, 55, 59, 53, 30, 1, -1, 5, 8, -7, -15, -19, -25, -48, -45, -31, -28, -10, 15, 1, -24, -35, -35, -22, -37, -43, -36, -35, -41, -47, -45, -18, -6, -1, 24, 32, 51, 65, 65, 67, 63, 37, -3, -13, -9, 1, 29, 54, 60, 50, 18, -4, -4, 13, 9, -10, -15, -17, -30, -54, -47, -29, -20, -8, 4, -8, -15, -29, -35, -21, -37, -43, -46, -37, -33, -48, -39, -10, 3, 13, 31, 34, 54, 56, 57, 63, 56, 32, -3, -16, -6, 14, 38, 48, 53, 40, 11, -3, 1, 6, -2, -11, -9, -11, -28, -54, -54, -29, -8, 2, -8, -16, -13, -27, -31, -21, -32, -45, -54, -36, -27, -44, -33, 1, 16, 25, 29, 39, 56, 48, 51, 57, 48, 22, 3, -14, 0, 22, 39, 42, 46, 36, 7, -7, 0, 0, -3, -8, -8, -15, -34, -50, -49, -27, -3, 0, -15, -14, -16, -28, -26, -21, -34, -56, -55, -32, -30, -41, -23, 8, 20, 31, 33, 45, 53, 38, 42, 54, 40, 18, -3, -9, 14, 33, 37, 34, 34, 27, 8, -5, -1, -9, -3, -1, -8, -19, -35, -43, -42, -28, -7, 1, -18, -13, -17, -29, -24, -21, -34, -55, -52, -34, -30, -26, -9, 15, 28, 28, 32, 55, 50, 29, 38, 45, 35, 17, -3, -1, 18, 36, 40, 27, 24, 19, 0, -5, -1, -14, -7, -2, -12, -20, -30, -40, -42, -25, -5, -5, -24, -14, -16, -25, -20, -26, -38, -52, -49, -35, -31, -13, 8, 16, 28, 29, 42, 57, 40, 23, 32, 35, 30, 12, -5, 9, 22, 40, 38, 19, 17, 16, -1, -9, -7, -12, -6, -5, -13, -18, -29, -39, -39, -18, -3, -19, -26, -11, -18, -24, -19, -30, -40, -51, -45, -30, -24, 0, 19, 22, 28, 36, 49, 54, 41, 22, 30, 31, 26, 10, 2, 10, 26, 43, 28, 14, 16, 7, -6, -12, -9, -9, -5, -12, -19, -16, -29, -35, -34, -8, -8, -35, -20, -7, -26, -23, -23, -30, -39, -53, -38, -25, -12, 11, 24, 24, 29, 47, 50, 48, 36, 20, 29, 24, 15, 5, 8, 12, 32, 40, 21, 17, 11, 0, -3, -15, -14, -7, -4, -13, -17, -16, -28, -31, -23, -6, -20, -37, -15, -12, -29, -22, -28, -30, -38, -54, -34, -20, -4, 21, 33, 24, 33, 50, 45, 40, 33, 27, 28, 14, 8, 8, 11, 11, 30, 33, 26, 20, -1, -8, -4, -17, -16, -2, -7, -22, -20, -20, -26, -26, -15, -10, -27, -35, -12, -19, -31, -21, -23, -23, -42, -57, -31, -11, 9, 35, 33, 23, 39, 53, 47, 40, 31, 31, 21, 10, 9, 11, 10, 13, 26, 35, 33, 13, -11, -10, -4, -19, -22, 3, -2, -28, -26, -16, -21, -24, -12, -12, -31, -34, -17, -27, -34, -25, -17, -19, -48, -59, -29, -2, 27, 46, 26, 22, 43, 54, 44, 38, 30, 29, 16, 6, 15, 15, 6, 9, 22, 36, 37, 9, -20, -10, -5, -21, -21, 2, -5, -29, -31, -18, -11, -17, -11, -15, -32, -34, -23, -30, -30, -25, -15, -22, -52, -50, -17, 9, 36, 42, 26, 29, 50, 53, 40, 33, 32, 27, 14, 7, 9, 7, 4, 12, 22, 36, 36, 3, -27, -16, -9, -20, -21, -1, -12, -31, -27, -13, -12, -18, -12, -17, -33, -39, -29, -34, -35, -23, -7, -25, -55, -42, -10, 20, 43, 40, 27, 33, 51, 51, 37, 34, 31, 21, 9, 8, 5, 2, 11, 16, 18, 34, 35, 3, -22, -17, -16, -20, -17, -7, -20, -32, -28, -14, -12, -10, -8, -17, -34, -41, -35, -34, -31, -19, -8, -27, -48, -29, -4, 26, 50, 44, 32, 37, 50, 49, 40, 36, 22, 11, 11, 12, 5, 3, 14, 12, 13, 34, 37, 9, -23, -24, -16, -21, -16, -17, -30, -27, -27, -20, -10, -10, -9, -18, -39, -46, -42, -35, -31, -14, -9, -33, -42, -19, 1, 36, 55, 41, 32, 46, 55, 47, 35, 32, 18, 6, 7, 9, -2, 7, 17, 8, 13, 34, 32, 10, -22, -27, -14, -20, -21, -26, -31, -23, -27, -22, -6, -5, -11, -21, -39, -46, -46, -37, -30, -14, -12, -33, -31, -8, 6, 41, 55, 40, 38, 54, 57, 39, 30, 33, 17, 2, 1, 4, 7, 14, 14, -2, 11, 37, 31, 11, -26, -30, -16, -20, -18, -21, -27, -32, -28, -12, 0, -4, -11, -23, -40, -46, -43, -33, -26, -16, -15, -29, -19, -1, 13, 44, 58, 41, 49, 68, 59, 36, 28, 36, 18, -9, -9, 4, 17, 20, 7, -6, 18, 36, 22, -1, -30, -26, -19, -25, -26, -31, -35, -33, -21, -3, -8, -10, -14, -24, -40, -45, -43, -35, -20, -18, -20, -22, -12, 0, 15, 48, 58, 41, 58, 77, 57, 30, 27, 33, 7, -23, -16, 11, 23, 21, 2, -5, 24, 33, 10, -10, -24, -19, -25, -37, -30, -30, -34, -29, -14, -5, -16, -8, -8, -26, -50, -47, -41, -30, -16, -25, -24, -14, -6, 3, 23, 50, 51, 49, 69, 81, 56, 29, 33, 30, -2, -29, -14, 15, 26, 18, 2, -1, 31, 28, 0, -20, -21, -21, -32, -43, -34, -33, -36, -23, -4, -8, -20, -8, -11, -25, -44, -41, -39, -32, -17, -30, -22, -4, 1, 6, 31, 48, 47, 63, 80, 82, 52, 31, 38, 23, -13, -33, -11, 20, 29, 14, -1, 9, 34, 19, -12, -26, -13, -23, -46, -46, -38, -39, -35, -24, -3, -7, -17, -15, -16, -25, -45, -37, -37, -33, -26, -36, -20, 5, 3, 4, 32, 42, 50, 76, 83, 75, 49, 34, 36, 17, -24, -33, -12, 23, 32, 10, 1, 23, 30, 7, -17, -22, -8, -27, -49, -50, -42, -38, -28, -18, -3, -8, -13, -14, -15, -24, -43, -35, -33, -29, -27, -34, -15, 16, 8, 5, 32, 43, 62, 84, 84, 73, 53, 40, 30, 6, -26, -34, -15, 25, 28, 8, 9, 38, 27, -4, -26, -21, -12, -33, -54, -47, -48, -38, -21, -14, -2, -3, -11, -25, -18, -26, -32, -34, -34, -29, -31, -35, -10, 18, 11, 7, 33, 47, 68, 83, 81, 71, 58, 42, 20, -5, -25, -36, -15, 23, 23, 7, 20, 40, 21, -14, -35, -21, -16, -40, -58, -52, -52, -31, -11, -9, -6, -1, -15, -26, -15, -29, -31, -36, -31, -29, -36, -32, -4, 17, 8, 15, 36, 48, 66, 77, 83, 77, 59, 38, 9, -11, -20, -34, -12, 22, 20, 14, 33, 39, 16, -22, -36, -23, -21, -40, -56, -52, -47, -24, -10, -4, 3, 1, -17, -22, -18, -28, -26, -32, -30, -32, -30, -22, 1, 15, 15, 27, 42, 52, 62, 75, 85, 80, 59, 35, 1, -16, -20, -35, -12, 18, 17, 18, 40, 34, 5, -34, -38, -27, -28, -42, -60, -58, -48, -18, -4, 0, 3, -4, -18, -20, -22, -35, -29, -27, -34, -42, -28, -12, 3, 8, 19, 31, 40, 45, 60, 75, 79, 76, 62, 37, -2, -20, -22, -31, -11, 13, 15, 31, 43, 27, 0, -28, -33, -36, -37, -43, -58, -61, -47, -13, 1, 1, 3, -5, -12, -17, -25, -36, -27, -25, -39, -45, -24, 1, 0, 8, 25, 43, 45, 42, 57, 76, 76, 73, 60, 37, -8, -25, -22, -25, -6, 9, 21, 41, 41, 15, -6, -18, -33, -48, -40, -38, -57, -64, -46, -6, 9, -4, 1, -1, -9, -18, -28, -33, -24, -27, -42, -45, -18, 2, 3, 13, 31, 49, 43, 37, 60, 74, 68, 68, 60, 30, -12, -28, -23, -19, -8, 5, 26, 48, 37, 11, -12, -17, -37, -54, -40, -41, -58, -65, -42, 5, 12, -8, 0, 2, -6, -22, -29, -30, -28, -37, -44, -42, -9, 6, 7, 17, 33, 44, 42, 40, 61, 72, 57, 63, 61, 24, -16, -34, -21, -15, -12, 3, 31, 47, 28, 7, -10, -15, -43, -51, -38, -45, -61, -61, -31, 10, 8, -3, 6, 5, -8, -24, -27, -28, -31, -44, -42, -29, -3, 6, 10, 24, 40, 44, 45, 46, 57, 62, 56, 65, 56, 16, -13, -32, -18, -12, -10, 11, 32, 39, 25, 6, -10, -19, -48, -44, -38, -49, -63, -61, -19, 12, 3, 4, 6, 3, -9, -25, -26, -27, -38, -46, -39, -18, 1, 12, 20, 29, 33, 36, 49, 47, 54, 59, 49, 63, 51, 8, -12, -25, -18, -18, -6, 20, 33, 28, 19, 4, -9, -27, -43, -41, -45, -55, -64, -51, -13, 7, -3, 0, 7, 3, -12, -28, -27, -33, -46, -51, -33, -10, -5, 15, 31, 34, 26, 32, 47, 51, 53, 47, 50, 61, 41, 1, -8, -12, -21, -20, 5, 27, 29, 16, 13, 8, -9, -28, -40, -40, -44, -55, -62, -40, -8, 5, -2, 4, 11, 4, -15, -26, -26, -37, -49, -47, -27, -8, -3, 22, 45, 38, 22, 34, 47, 55, 52, 39, 44, 58, 32, 2, 0, -7, -25, -21, 10, 29, 30, 9, 0, 0, -7, -26, -38, -40, -53, -61, -53, -30, -5, 1, -2, 5, 10, 3, -18, -25, -33, -43, -51, -46, -20, -10, -8, 26, 52, 35, 19, 32, 47, 56, 46, 33, 44, 48, 20, 10, 11, -7, -29, -20, 15, 35, 28, 2, -9, -8, -6, -26, -32, -36, -54, -64, -52, -22, 1, 3, 2, 3, 15, 2, -22, -24, -34, -41, -45, -39, -19, -9, 1, 35, 57, 37, 18, 27, 46, 52, 41, 37, 44, 40, 18, 16, 13, -7, -29, -14, 23, 36, 17, -6, -17, -2, 1, -24, -38, -43, -59, -62, -44, -22, -4, 7, 2, 5, 16, -2, -24, -27, -36, -43, -48, -37, -20, -5, 14, 40, 52, 36, 20, 26, 43, 46, 40, 41, 42, 28, 19, 19, 9, -4, -21, -10, 27, 32, 10, -6, -16, -4, -5, -14, -37, -48, -59, -58, -36, -24, -1, 13, -3, 7, 16, -5, -19, -32, -38, -46, -43, -32, -22, -7, 22, 49, 57, 37, 22, 20, 37, 41, 36, 46, 41, 21, 19, 16, 9, -2, -25, -9, 27, 24, 8, -12, -11, -2, -9, -10, -39, -51, -59, -59, -35, -21, 2, 15, -5, 10, 11, -12, -19, -35, -39, -46, -35, -29, -26, -5, 37, 60, 53, 36, 26, 19, 33, 37, 33, 48, 41, 18, 17, 19, 11, -8, -23, -3, 30, 21, -5, -14, -2, -6, -9, -9, -42, -59, -64, -54, -33, -16, 6, 14, 0, 15, 4, -14, -17, -35, -45, -46, -33, -27, -22, 2, 42, 56, 49, 37, 26, 19, 26, 23, 36, 58, 44, 11, 8, 23, 10, -7, -15, 3, 26, 12, -10, -8, 3, -10, -7, -13, -46, -58, -60, -57, -40, -11, 9, 9, 3, 13, -6, -12, -17, -42, -53, -45, -28, -23, -14, 11, 49, 60, 49, 40, 27, 14, 16, 13, 43, 62, 46, 6, 8, 22, 7, -9, -10, 11, 23, 4, -17, 2, 6, -6, -7, -21, -51, -58, -58, -55, -38, -12, 12, 10, 13, 1, -15, -7, -14, -47, -62, -45, -29, -19, -2, 21, 51, 63, 46, 37, 31, 16, 0, 4, 43, 64, 43, 6, 9, 24, 4, -15, -2, 14, 9, -9, -15, 14, 7, -11, -10, -29, -53, -54, -57, -48, -35, -9, 13, 9, 11, -5, -6, -2, -22, -57, -60, -39, -24, -11, 5, 30, 52, 62, 49, 42, 38, 11, -9, 7, 45, 61, 44, 10, 15, 21, -4, -15, 3, 13, 1, -13, -9, 13, 7, -9, -13, -32, -51, -53, -56, -44, -35, -9, 15, 11, 7, -8, 0, -2, -34, -65, -56, -31, -24, -7, 20, 37, 49, 56, 47, 47, 39, -3, -16, 12, 40, 53, 45, 16, 23, 17, -7, -8, 7, 8, -5, -12, -7, 7, 7, -4, -17, -38, -56, -60, -50, -37, -33, -8, 7, 9, 0, -6, 7, -8, -47, -71, -50, -25, -23, 0, 33, 41, 46, 52, 53, 54, 35, -6, -9, 13, 32, 50, 48, 23, 25, 13, -4, -3, 0, -1, -7, -7, -8, 3, 6, -3, -22, -41, -55, -62, -46, -30, -24, -5, 0, 5, 2, 3, 10, -20, -57, -69, -41, -19, -16, 5, 37, 47, 46, 49, 54, 58, 29, -4, -6, 7, 21, 49, 49, 24, 24, 12, -2, -5, -9, 0, 0, -10, -15, 2, 8, -4, -23, -42, -57, -66, -43, -22, -16, -11, -8, 3, 5, 7, 4, -28, -61, -61, -36, -19, -11, 10, 45, 51, 43, 46, 52, 54, 26, 3, -8, -3, 15, 52, 48, 27, 30, 15, -1, -9, -14, 0, -2, -15, -17, -2, -1, -5, -23, -37, -62, -64, -34, -17, -15, -19, -8, 4, 7, 8, -8, -37, -55, -50, -33, -19, -5, 16, 49, 54, 44, 45, 52, 53, 32, 3, -12, -5, 14, 46, 46, 38, 34, 21, 6, -13, -21, -2, -3, -18, -19, -14, -9, -2, -14, -44, -74, -56, -26, -15, -16, -18, -6, -1, 7, 6, -20, -43, -48, -35, -32, -24, 1, 23, 51, 54, 41, 42, 52, 49, 32, 3, -14, -5, 19, 42, 47, 43, 38, 27, 10, -18, -19, -5, -7, -18, -27, -23, -9, 2, -8, -51, -75, -41, -19, -15, -13, -15, -11, -5, 10, 1, -30, -37, -40, -30, -33, -24, 6, 30, 49, 49, 45, 43, 52, 39, 24, 7, -10, -7, 12, 33, 44, 48, 43, 36, 7, -29, -18, -6, -14, -23, -36, -32, -12, 2, -16, -60, -65, -27, -22, -22, -9, -6, -14, -6, 11, -10, -38, -35, -27, -26, -35, -15, 18, 39, 47, 48, 51, 55, 51, 28, 22, 13, -5, -6, 5, 27, 46, 57, 49, 39, 1, -29, -12, -7, -15, -28, -48, -39, -11, -1, -28, -61, -51, -22, -30, -22, -3, -4, -21, -6, 8, -23, -45, -29, -18, -27, -32, -11, 24, 44, 40, 46, 56, 61, 44, 17, 18, 19, 1, -11, -2, 24, 48, 57, 54, 45, 2, -27, -12, -11, -18, -32, -49, -41, -16, -10, -32, -47, -33, -25, -34, -13, 6, -5, -24, -13, -4, -29, -43, -29, -18, -25, -21, -1, 25, 44, 40, 49, 67, 60, 31, 12, 18, 24, -2, -18, -5, 22, 45, 62, 65, 46, -5, -21, -12, -12, -17, -36, -57, -48, -23, -15, -29, -35, -28, -33, -31, -3, 12, -16, -32, -12, -19, -36, -33, -25, -22, -29, -10, 14, 30, 41, 35, 51, 73, 57, 27, 16, 21, 14, -4, -12, -2, 21, 41, 62, 71, 43, -7, -12, -19, -22, -23, -46, -57, -51, -35, -20, -17, -22, -26, -37, -27, 7, 12, -24, -31, -14, -29, -34, -30, -22, -20, -21, 2, 15, 26, 40, 45, 55, 66, 52, 28, 20, 17, 10, -1, -12, -4, 21, 43, 65, 74, 39, 1, -9, -25, -27, -24, -45, -61, -55, -43, -22, -9, -12, -24, -32, -26, 9, 7, -25, -31, -30, -40, -31, -26, -19, -20, -11, 14, 18, 27, 45, 54, 52, 61, 49, 33, 24, 15, 5, 0, -14, -2, 24, 44, 62, 67, 37, 12, -9, -30, -29, -33, -49, -66, -58, -51, -25, -2, -6, -19, -31, -24, 6, 3, -21, -37, -43, -42, -31, -25, -17, -19, -5, 15, 19, 30, 52, 56, 45, 54, 52, 38, 22, 11, 8, 0, -16, 2, 27, 44, 63, 60, 34, 16, -10, -25, -31, -38, -55, -68, -62, -53, -18, 5, -2, -17, -31, -16, 5, -4, -22, -43, -50, -38, -32, -21, -16, -11, 8, 10, 19, 32, 60, 60, 43, 46, 51, 37, 24, 13, 8, -6, -17, 4, 32, 52, 56, 52, 39, 23, -5, -23, -41, -48, -64, -65, -63, -57, -14, 9, 3, -18, -28, -9, 0, -11, -25, -47, -53, -38, -30, -19, -11, 0, 10, 11, 23, 42, 66, 60, 42, 49, 53, 36, 24, 20, 9, -17, -18, 3, 39, 59, 49, 41, 39, 26, 1, -24, -53, -59, -70, -61, -66, -58, -12, 17, 7, -20, -26, -7, -7, -16, -30, -51, -60, -45, -26, -11, -5, 5, 8, 10, 23, 48, 66, 55, 40, 48, 48, 33, 30, 25, 2, -21, -15, 10, 41, 51, 44, 37, 41, 27, 6, -28, -60, -65, -70, -63, -70, -55, -6, 21, 1, -20, -15, -2, -15, -24, -32, -54, -66, -45, -22, -8, 6, 13, 5, 15, 31, 51, 64, 58, 41, 42, 44, 35, 36, 29, 0, -20, -9, 14, 43, 53, 46, 39, 39, 24, 7, -33, -69, -75, -73, -70, -75, -46, 4, 17, -2, -18, -6, 3, -18, -32, -38, -61, -65, -39, -17, -2, 10, 10, 5, 19, 33, 55, 61, 54, 39, 40, 41, 41, 40, 30, -6, -25, -6, 22, 44, 48, 42, 42, 37, 23, 11, -42, -73, -77, -75, -74, -75, -39, 4, 8, -5, -15, 1, -1, -30, -33, -38, -69, -66, -40, -14, 3, 16, 8, 5, 21, 39, 60, 59, 48, 40, 38, 39, 42, 42, 30, -8, -20, 0, 26, 48, 51, 48, 43, 29, 21, 1, -47, -70, -80, -83, -80, -70, -25, 0, -2, -9, -6, 9, -7, -29, -33, -49, -72, -59, -29, -3, 3, 11, 6, 14, 27, 47, 61, 54, 47, 43, 34, 42, 45, 39, 21, -10, -17, 4, 29, 53, 54, 47, 39, 29, 22, -11, -53, -70, -83, -86, -77, -61, -19, -6, -7, -12, -2, 9, -14, -29, -35, -61, -70, -54, -25, -8, 2, 11, 8, 17, 27, 54, 60, 50, 45, 42, 40, 43, 39, 35, 18, -9, -7, 8, 28, 55, 56, 49, 32, 30, 15, -21, -53, -71, -88, -87, -74, -45, -12, -11, -15, -14, 6, 12, -12, -30, -48, -66, -60, -44, -18, -8, 5, 13, 15, 21, 31, 51, 57, 48, 43, 42, 40, 43, 37, 29, 16, -3, -1, 7, 35, 60, 54, 38, 26, 29, 5, -30, -54, -72, -93, -87, -69, -34, -14, -19, -25, -12, 13, 6, -17, -37, -56, -66, -49, -38, -18, -11, 1, 17, 24, 26, 32, 47, 52, 50, 49, 45, 39, 40, 33, 32, 13, 4, 3, 3, 47, 65, 52, 29, 27, 20, -5, -35, -56, -76, -90, -79, -63, -27, -17, -26, -24, 0, 12, -2, -16, -33, -61, -61, -42, -33, -17, -16, -6, 22, 30, 25, 29, 45, 50, 46, 53, 41, 37, 37, 33, 28, 17, 15, 2, 15, 54, 64, 46, 21, 25, 9, -12, -39, -58, -77, -87, -75, -46, -21, -23, -34, -24, 9, 9, -7, -17, -40, -67, -53, -33, -27, -22, -26, -4, 34, 34, 25, 27, 46, 44, 52, 59, 37, 30, 35, 32, 26, 25, 16, 2, 30, 62, 57, 33, 19, 17, -7, -25, -43, -58, -80, -82, -64, -36, -26, -26, -33, -17, 11, 4, -9, -18, -45, -62, -44, -30, -24, -28, -29, 5, 38, 32, 25, 30, 48, 41, 53, 57, 35, 28, 26, 27, 31, 29, 14, 12, 47, 63, 48, 35, 24, 4, -19, -32, -46, -55, -76, -77, -58, -31, -30, -33, -36, -8, 12, -4, -9, -22, -51, -57, -30, -23, -27, -40, -31, 18, 36, 31, 30, 33, 39, 36, 56, 51, 32, 27, 20, 24, 39, 30, 16, 29, 55, 53, 43, 36, 21, -5, -28, -39, -45, -55, -71, -70, -47, -27, -35, -36, -25, -2, 1, -4, -6, -23, -48, -48, -25, -16, -25, -46, -23, 24, 30, 35, 34, 29, 33, 37, 51, 41, 30, 21, 12, 27, 47, 33, 19, 38, 51, 43, 39, 36, 15, -17, -35, -35, -42, -55, -68, -62, -45, -33, -40, -36, -19, -5, -4, -3, -6, -24, -47, -38, -17, -13, -37, -48, -13, 26, 30, 36, 32, 27, 29, 36, 48, 38, 27, 9, 5, 34, 47, 31, 30, 49, 47, 36, 38, 28, 11, -21, -32, -32, -47, -56, -60, -54, -40, -39, -42, -31, -12, -5, -7, -1, -4, -21, -39, -28, -11, -13, -45, -42, -2, 23, 25, 42, 33, 26, 26, 33, 44, 34, 20, 1, 5, 36, 47, 38, 40, 47, 37, 35, 38, 20, 1, -23, -26, -35, -49, -56, -55, -48, -40, -46, -42, -28, -12, -12, -10, 2, -6, -25, -32, -25, -13, -22, -43, -30, 5, 18, 24, 45, 35, 29, 21, 27, 39, 28, 16, 2, 9, 39, 40, 44, 55, 45, 25, 31, 34, 15, -1, -18, -25, -41, -49, -50, -52, -46, -42, -48, -40, -23, -9, -18, -13, 9, -1, -24, -27, -22, -14, -30, -41, -26, 8, 15, 25, 40, 36, 26, 15, 26, 35, 21, 11, 2, 17, 44, 37, 54, 63, 37, 16, 31, 27, 12, -3, -12, -24, -45, -47, -46, -45, -40, -44, -55, -40, -17, -12, -22, -7, 19, -2, -22, -24, -15, -17, -36, -36, -11, 16, 10, 17, 38, 43, 25, 15, 25, 26, 14, 7, 2, 25, 39, 38, 63, 67, 30, 16, 25, 18, 14, -5, -9, -26, -43, -45, -47, -42, -38, -52, -57, -35, -14, -22, -27, 0, 23, -5, -24, -22, -12, -21, -40, -31, 1, 19, 6, 11, 35, 44, 22, 18, 28, 14, 4, 4, 11, 32, 34, 38, 70, 68, 22, 18, 17, 15, 17, 0, -10, -31, -45, -43, -42, -34, -36, -62, -61, -25, -11, -28, -29, 3, 25, -3, -26, -15, -12, -28, -34, -21, 9, 17, 2, 10, 31, 40, 24, 23, 28, 5, -3, 6, 19, 35, 33, 42, 72, 59, 22, 22, 12, 17, 17, 2, -11, -31, -40, -40, -36, -28, -40, -66, -57, -18, -15, -32, -22, 9, 22, -3, -23, -8, -12, -31, -32, -12, 18, 15, -1, 9, 25, 36, 26, 27, 20, -7, -5, 12, 23, 29, 33, 45, 70, 48, 25, 20, 8, 16, 9, 4, -11, -33, -39, -37, -34, -30, -46, -65, -50, -23, -22, -30, -19, 13, 22, -4, -21, -6, -15, -32, -28, -3, 18, 9, 0, 9, 21, 30, 28, 30, 12, -14, -1, 17, 19, 27, 41, 51, 63, 35, 28, 22, 12, 10, 6, 9, -14, -31, -36, -31, -27, -38, -49, -62, -48, -29, -25, -27, -13, 13, 13, -3, -9, -9, -21, -30, -20, 4, 12, 4, 5, 12, 19, 27, 33, 29, 6, -12, 2, 21, 17, 31, 45, 54, 55, 31, 31, 25, 14, 3, 5, 11, -14, -27, -33, -24, -27, -41, -49, -63, -53, -37, -26, -22, -7, 11, 8, 0, -3, -14, -19, -27, -14, 8, 5, 2, 9, 12, 20, 25, 31, 18, 0, -6, 8, 20, 14, 27, 43, 59, 48, 24, 28, 25, 14, 2, 8, 6, -15, -26, -30, -16, -28, -44, -53, -61, -58, -37, -27, -21, -4, 8, 3, 1, -2, -18, -21, -24, -11, 3, -4, 3, 15, 17, 20, 22, 29, 15, 3, -2, 8, 17, 18, 30, 46, 56, 40, 21, 29, 26, 14, -1, 5, 4, -6, -22, -29, -13, -27, -46, -51, -62, -61, -37, -28, -14, 2, 7, 0, 5, -2, -16, -17, -19, -10, -7, -9, 11, 20, 22, 18, 17, 25, 19, 4, -1, 10, 19, 25, 32, 44, 53, 36, 19, 29, 24, 10, -4, 5, 4, -2, -22, -24, -13, -31, -48, -56, -63, -60, -40, -31, -11, 8, 8, 2, 8, -6, -20, -17, -12, -10, -20, -12, 14, 30, 26, 10, 14, 24, 24, -1, -7, 12, 25, 27, 30, 40, 52, 34, 17, 28, 24, 7, -9, 1, 8, 3, -20, -20, -16, -33, -53, -59, -62, -61, -47, -29, -5, 15, 5, 1, 9, -8, -20, -14, -5, -12, -30, -11, 20, 37, 25, 10, 19, 25, 19, -5, -2, 18, 28, 26, 29, 41, 49, 31, 20, 30, 24, 1, -8, 4, 10, 3, -17, -12, -18, -40, -57, -61, -62, -59, -48, -23, 0, 18, 5, 5, 12, -9, -19, -9, -2, -20, -37, -7, 25, 39, 23, 11, 25, 26, 10, -10, 5, 23, 24, 26, 30, 40, 42, 27, 23, 31, 18, -7, -5, 2, 7, -1, -10, -10, -22, -45, -59, -63, -62, -58, -45, -21, -1, 17, 10, 13, 7, -18, -21, -5, -3, -27, -38, -7, 26, 38, 21, 20, 31, 23, 0, -9, 15, 25, 21, 28, 33, 35, 35, 29, 28, 31, 12, -5, 0, 0, 4, 0, -3, -14, -27, -48, -57, -69, -66, -61, -40, -19, 1, 16, 13, 16, -3, -18, -17, -4, -9, -30, -33, -1, 24, 35, 28, 34, 31, 16, -4, -2, 22, 29, 20, 27, 38, 33, 30, 30, 31, 33, 9, 1, -3, -7, 2, 6, -1, -22, -31, -50, -61, -74, -67, -52, -34, -25, 1, 19, 21, 14, -8, -18, -14, -10, -14, -27, -26, -5, 21, 35, 38, 40, 31, 12, -1, 5, 22, 29, 19, 31, 41, 28, 30, 28, 31, 28, 12, 7, -13, -11, -2, 13, -5, -26, -32, -52, -67, -80, -65, -46, -34, -26, 2, 15, 25, 9, -8, -14, -16, -10, -18, -25, -25, -9, 20, 37, 46, 35, 26, 10, 7, 8, 18, 27, 18, 31, 39, 25, 29, 29, 34, 26, 20, 2, -18, -10, -5, 12, -9, -22, -31, -48, -74, -79, -66, -42, -34, -22, -1, 14, 25, 13, -6, -19, -16, -8, -19, -22, -21, -5, 21, 41, 51, 32, 25, 14, 19, 13, 14, 21, 21, 32, 34, 26, 26, 30, 32, 25, 25, -3, -19, -13, -2, 8, -12, -24, -32, -46, -75, -79, -67, -43, -33, -18, -7, 12, 25, 18, 0, -23, -13, -7, -23, -18, -15, -4, 21, 48, 51, 27, 27, 23, 22, 12, 12, 19, 22, 28, 28, 28, 28, 31, 28, 23, 28, -3, -20, -22, -5, 0, -14, -23, -28, -50, -78, -81, -63, -44, -34, -19, -14, 10, 25, 18, -6, -19, -5, -11, -30, -17, -8, 2, 21, 54, 45, 25, 28, 33, 25, 9, 12, 21, 26, 23, 24, 33, 37, 35, 20, 23, 32, -1, -21, -25, -12, -11, -12, -19, -27, -53, -78, -79, -55, -42, -31, -26, -18, 12, 24, 13, -9, -12, 0, -20, -33, -13, 1, 6, 26, 55, 38, 25, 33, 45, 26, 7, 13, 21, 26, 16, 18, 38, 44, 33, 14, 25, 30, 4, -24, -32, -21, -18, -19, -19, -25, -54, -79, -78, -53, -43, -29, -28, -20, 6, 20, 12, -3, 0, -3, -35, -28, 1, 9, 8, 25, 46, 34, 30, 37, 44, 19, 13, 20, 17, 20, 12, 18, 49, 49, 23, 13, 28, 33, 3, -34, -37, -28, -30, -21, -10, -26, -57, -77, -74, -52, -40, -25, -32, -22, 3, 17, 12, 3, 8, -15, -40, -18, 10, 10, 4, 32, 39, 27, 38, 48, 39, 11, 18, 28, 17, 15, 5, 23, 61, 46, 21, 23, 35, 26, -3, -31, -37, -39, -38, -23, -3, -29, -60, -74, -68, -58, -37, -27, -35, -22, -7, 15, 23, 14, 8, -27, -41, -6, 19, 14, 9, 35, 31, 31, 48, 54, 35, 11, 27, 26, 4, 7, 11, 31, 54, 38, 25, 34, 35, 20, -10, 19, 3, -8, -45, 64, -15, -41, 23, 40, -58, 22, 29, -27, -28, 42, -36, 21, -12, -19, 39, -14, 3, -18, 32, -27, 18, -8, -43, 43, 25, -52, 6, 19, 13, -7, -50, 55, 5, -46, -22, 94, -53, -33, 35, 27, -45, -2, 20, 19, -30, -23, 47, 8, -58, 5, 76, -67, -22, 42, 30, -54, 8, 23, 11, -51, 3, 47, -33, -7, 5, 27, -33, 34, -35, 17, 4, -26, 5, 17, -30, 33, 5, -29, -5, 44, -18, -50, 60, -33, 10, -5, 10, -7, 1, -5, 19, -36, 3, 37, -17, -51, 52, 37, -64, 9, 4, 37, -44, -13, 25, 45, -75, -9, 79, -34, -57, 53, 24, -59, 18, 22, -3, -24, 10, -2, 18, -53, 29, 35, -20, -43, 37, 18, -17, -31, 8, 45, -49, 8, 11, 9, -23, 30, -24, -22, 29, 14, -43, 27, 13, -22, -1, 2, 22, -37, 5, -5, 38, -43, 6, 36, -21, -20, 20, 0, -5, -27, 27, 21, -53, 4, 52, -2, -84, 70, 5, -29, -19, 36, -6, -8, -12, 3, 35, -32, -25, 48, 6, -60, 49, 4, -27, -13, 31, -15, -9, -4, 31, -13, -25, 29, 12, -34, -6, 30, -41, 36, -23, 6, 31, -30, 0, 17, -45, 47, -5, -47, 19, 28, -8, -30, 27, -6, 15, -54, 34, 21, -27, -9, 25, 3, -45, 26, 27, -52, 22, 20, -29, 34, -46, 22, 40, -69, -27, 108, -49, -54, 69, -11, -3, -18, 3, 15, -12, -23, 29, -8, 4, -23, 50, -38, -8, 33, -32, -2, 26, -27, 12, 13, -39, 56, -31, -22, 28, 2, -39, 54, -20, -36, 51, -6, -34, 15, 2, 1, 2, -36, 42, 2, -10, -39, 64, -36, -16, 24, 1, -1, -18, -10, 54, -27, -54, 80, -18, -61, 51, 27, -76, 64, -30, -1, 9, -19, 24, 13, -29, -13, 49, -18, -46, 43, 6, -47, 42, -28, 14, 18, -18, 2, 14, -39, 25, 16, -58, 33, 29, -49, 16, 41, -62, 43, -17, -17, 25, -10, -28, 41, -5, -30, 27, 14, -53, 27, 35, -63, 16, 30, 0, -30, -10, 22, 31, -57, 0, 68, -59, 2, 37, -30, 6, -3, -19, 35, -29, 1, 20, 22, -68, 33, 39, -71, 21, 27, -22, -1, 3, 0, 18, -16, -13, 17, 4, -37, 44, -15, -26, 48, -29, -11, 34, -25, -4, 25, -48, 43, 4, -49, 28, 42, -72, 7, 59, -36, -28, 45, -9, -28, 25, -19, 23, -9, -40, 47, 18, -85, 78, -2, -53, 39, -17, 2, 14, -36, 10, 63, -78, 17, 59, -66, -8, 54, -49, 14, 1, 5, 2, -18, 16, -12, 30, -58, 22, 53, -83, 17, 79, -84, 19, 17, -34, 44, -33, -27, 82, -62, -19, 91, -93, 22, 49, -51, -25, 48, -12, -6, 1, -2, -1, 22, -32, -1, 59, -78, 12, 58, -49, -26, 70, -40, -8, 16, -8, 12, 10, -65, 74, -1, -97, 90, 0, -56, 23, 25, -17, 11, -23, 14, 9, -24, -31, 77, -41, -48, 95, -38, -46, 59, -1, -57, 49, -33, 19, 18, -46, 34, 31, -79, 47, 11, -38, 10, 19, -14, -10, 26, -29, 28, -17, -27, 48, -15, -51, 78, -14, -73, 64, 12, -55, 29, 3, -24, 52, -65, 26, 50, -75, -5, 81, -76, 0, 42, -6, -26, 10, 18, -14, 4, -24, 33, 2, -69, 61, 43, -101, 40, 54, -73, 22, 18, -41, 44, -19, -43, 94, -69, -13, 65, -26, -46, 35, 24, -34, -2, 23, -13, 6, -19, 4, 38, -56, 14, 40, -37, -19, 66, -57, -9, 50, -47, 21, 6, -31, 55, -34, -50, 98, -44, -47, 44, 28, -51, 6, 31, -3, -34, 8, 11, 6, -18, -27, 78, -48, -28, 55, -2, -60, 57, -37, 14, 15, -48, 49, 22, -96, 74, 23, -83, 36, 18, -17, -25, 41, -12, -4, -2, 1, 9, -14, -18, 36, 12, -77, 54, 32, -67, 20, 38, -67, 61, -53, 32, 21, -60, 27, 41, -74, 27, 33, -30, -6, 22, -1, -30, 20, 1, -4, -22, 9, 8, 37, -65, 18, 61, -69, -3, 37, -19, -15, 15, -16, 57, -78, 20, 66, -67, -27, 76, -37, -16, 11, 11, -5, -18, 10, 16, -5, -38, 36, 9, -20, -32, 73, -41, -36, 62, -33, -9, 34, -41, 35, -7, -40, 65, -35, -26, 33, 2, -43, 42, -4, -9, 5, -11, 19, -10, -16, 11, 16, -28, -9, 41, 2, -70, 67, -3, -55, 23, 33, -26, 6, -29, 43, 16, -85, 51, 28, -54, 7, 27, -9, 2, -18, 27, -4, -42, 31, 10, -19, -9, 18, 8, -24, -3, 45, -57, 25, 0, -7, 15, -28, 10, 33, -46, -6, 52, -36, -15, 46, -29, -4, 12, -14, 34, -57, 16, 40, -41, 3, 16, 8, -32, 16, 15, -17, -27, 47, -30, -1, 14, -5, 16, -17, -33, 70, -44, -42, 84, -34, -27, 18, 15, 3, -20, -22, 55, -35, -22, 31, 10, -11, -27, 27, 13, -28, -10, 41, -21, -3, -22, 41, -21, -13, 6, 34, -68, 46, 25, -65, 50, -21, -1, 10, -33, 34, 1, -43, 58, -34, -2, 13, 8, -25, 0, -2, 34, -29, -26, 45, -12, 4, -34, 32, 15, -54, 17, 53, -76, 41, 4, -17, 13, -26, 13, 31, -47, 1, 52, -53, 11, 8, 14, -31, -7, 19, 30, -60, 26, 27, -22, -10, 0, 18, -13, -24, 52, -38, -17, 68, -60, 26, -9, -25, 41, -29, -8, 40, -25, -9, 26, -28, 15, -9, -3, 11, -21, -1, 44, -47, 19, 0, 3, -14, -12, 38, -22, -23, 37, -10, -13, 9, -6, 21, -14, -39, 61, -4, -68, 60, 6, -43, 28, -14, 21, -22, -13, 36, -7, -40, 46, -14, -5, -18, 20, 22, -49, 22, 10, -18, 21, -30, 9, 34, -54, 19, 22, -34, 27, 7, -45, 30, 0, -20, 23, -23, 29, -10, -21, 25, 3, -23, -1, 5, 16, -33, 14, 25, -21, -11, 16, 3, -22, 5, 6, 32, -73, 27, 62, -72, 5, 26, -21, 30, -37, 4, 40, -45, 5, 18, -18, -1, 12, -3, 0, -18, 28, -8, -14, 11, -11, 13, -15, -3, 27, -17, -30, 65, -45, -5, 28, -25, 1, 20, -36, 38, -11, -20, 35, -23, -20, 27, 11, -42, 13, 17, 1, -25, 20, 10, -33, 10, 6, -7, 9, -26, 40, -3, -63, 74, -30, -11, 10, -10, 5, 17, -47, 53, -10, -47, 29, 31, -45, 4, 16, 14, -15, -33, 40, -11, -3, -10, 2, 18, -20, 9, 22, -44, 19, 20, -42, 25, -5, -11, 25, -25, -3, 47, -63, 28, 20, -42, 7, 39, -41, 2, 13, 10, -24, -8, 41, -26, -1, -13, 9, 42, -60, 0, 61, -54, -4, 19, -6, 11, -19, -13, 52, -37, -26, 66, -38, -30, 49, -18, -11, 5, 7, 10, -30, 4, 17, 2, -12, -15, 38, -19, -20, 30, -16, -23, 38, -13, -16, 29, -22, 26, -17, -35, 62, -30, -35, 51, -16, -27, 40, -16, 3, -8, -4, 9, 4, -26, 11, 20, -11, -38, 56, -19, -29, 31, 7, -39, 17, 10, 6, -8, -41, 45, 26, -79, 36, 42, -58, 21, 6, -10, 7, -19, 17, -1, -15, -12, 53, -22, -32, 24, 25, -59, 24, 22, -36, 10, 18, -27, 44, -45, 0, 42, -45, -2, 30, -27, 12, 23, -38, 13, 5, 4, -4, -20, 1, 43, -27, -36, 43, 14, -51, 12, 40, -41, 5, 18, -11, -1, -5, -11, 53, -56, -29, 91, -41, -45, 57, -7, -18, -3, -4, 29, -20, -19, 20, 26, -57, 31, 17, -22, -13, 28, -31, 3, 36, -33, 9, 17, -39, 42, -9, -54, 58, 6, -69, 44, 30, -50, 24, 3, -17, 9, -20, 17, 8, -23, 1, 46, -50, 1, 27, 1, -49, 37, 5, -17, 4, -5, 7, 18, -55, 39, 36, -85, 37, 48, -63, 5, 27, -13, -6, -4, 5, 24, -26, -12, 42, -25, -34, 33, 20, -33, -13, 29, -2, 7, -34, 12, 37, -50, 1, 47, -46, -1, 56, -54, -18, 59, -35, -6, 12, -16, 20, -2, -27, 43, -12, -34, 22, 25, -41, -7, 43, -20, -18, 19, -1, 1, -6, -20, 54, -55, -12, 67, -24, -56, 56, -8, -12, -7, -3, 16, 20, -48, 20, 32, -46, 8, 23, -17, -38, 54, 1, -34, 2, 30, -1, -21, -18, 38, -14, -35, 41, 3, -36, 19, 22, -45, 40, -32, 12, 12, -26, 2, 35, -54, 34, 14, -25, -30, 47, 10, -53, 24, 13, -4, -18, 3, 5, 27, -61, 38, 15, -39, 6, 40, -36, 0, 2, -6, 28, -40, 7, 46, -37, -30, 59, -21, -29, 6, 48, -55, 12, 30, -21, -6, 5, -2, 1, -14, -7, 46, -41, -4, 35, -8, -33, 29, -20, 26, -31, -10, 63, -46, -4, 12, 7, -11, -15, 26, -14, -22, 54, -47, 12, 9, -1, -8, -7, -8, 41, -12, -60, 77, -21, -26, 11, 13, 1, -26, -9, 59, -45, -16, 38, -3, -27, -1, 28, -8, -19, 11, 20, -41, 34, -23, 22, -20, -9, 6, 51, -79, 40, 18, -40, 23, -5, -19, 13, 2, 3, -4, -35, 71, -39, 5, -30, 33, 6, -29, -3, 38, -29, -5, 18, -9, -4, -11, 16, 15, -32, -14, 77, -83, 30, 10, -10, -19, 20, 15, -17, -19, 29, 7, -32, 6, -1, 14, -14, -6, 5, 36, -58, 47, -18, -14, 4, 8, 8, -24, -15, 60, -36, -20, 43, -32, 3, -2, 1, 9, -5, -8, 30, -33, 6, 6, 2, -12, -11, 24, 1, -22, 9, 34, -61, 25, 11, -5, -18, -1, 38, -19, -33, 49, -19, -21, 18, -7, 1, 5, -4, -3, 13, -30, 25, -5, -12, 2, 8, 17, -37, 0, 50, -38, -26, 40, -15, 7, -24, 31, -11, -8, 6, -6, -3, 1, 9, -8, 6, -20, 25, 0, -21, 7, 22, -48, 29, -4, 10, -22, 7, 22, -9, -34, 45, -15, -31, 30, -2, 0, -30, 46, -18, -6, -17, 31, -6, -7, -21, 8, 45, -47, -7, 31, -17, -11, 25, -20, 17, -30, 47, -38, -2, 5, 16, -36, 24, -2, 3, -7, 6, 10, -23, 5, -11, 35, -42, 17, 0, 21, -35, 11, 16, -18, -15, 36, -24, -3, 9, 5, 13, -49, 36, -11, -2, -14, 37, -32, 13, -1, 0, -2, -2, -8, 17, -11, -21, 30, -1, -1, -41, 72, -65, 14, 14, 12, -41, 21, 4, 15, -32, -1, 25, -9, -18, 3, 29, -38, 35, -22, 14, -20, 16, -6, -6, -13, 29, -4, -17, 7, 14, -6, -38, 54, -32, 3, -16, 36, -39, 42, -40, 36, -22, -13, 17, 14, -36, 12, 23, -25, 6, -25, 53, -33, -12, 5, 37, -46, 6, 20, 9, -53, 52, -16, -22, 24, -9, 10, -17, 12, -20, 48, -73, 40, 18, -30, -20, 52, -34, 11, -6, 0, 1, -15, 24, -16, 16, -30, 44, -27, -10, 0, 34, -52, 24, 3, 2, -6, 12, -25, 35, -38, -14, 72, -73, 7, 31, 15, -50, 20, 12, -5, -25, 23, 3, -10, -9, 15, 9, -41, 28, 6, -5, -36, 44, -13, 10, -19, 2, 14, -10, -29, 56, -27, -35, 58, -19, -27, 17, 16, -30, 10, -7, 15, -12, -3, 11, 18, -30, -13, 38, -17, -16, 3, 32, -37, 23, -24, 30, -12, -26, 40, -14, -52, 59, 12, -55, 16, 35, -20, -30, 39, -24, 21, -26, 12, 13, -10, -19, 23, 2, -35, 17, 33, -30, -17, 39, -15, 12, -53, 50, -13, -25, 2, 50, -42, -1, 25, -22, 6, -5, 3, -4, 2, -18, 39, -25, -3, 1, 29, -57, 22, 26, -22, -18, 34, -10, -10, -11, 13, 31, -77, 46, 23, -22, -35, 61, -24, -13, 7, -3, 0, 4, -24, 27, 12, -50, 35, 13, -19, -37, 69, -46, -4, 13, 5, -8, 6, -25, 40, -26, -13, 38, -12, -28, 21, 22, -57, 40, -15, 11, -19, 4, 19, 9, -36, 3, 42, -35, -30, 46, 0, -50, 59, -26, 9, -16, 12, -10, 10, -33, 44, -8, -29, 8, 42, -43, -6, 26, -19, 14, -30, 34, 4, -21, -17, 49, -31, -24, 34, 14, -53, 32, 13, -26, 12, -22, 26, -3, -22, -11, 66, -59, 0, 43, -27, -23, 42, -32, 7, -7, 11, 9, -19, -1, 15, 16, -58, 43, 1, -32, 11, 36, -44, 18, 0, 4, -4, -7, -22, 50, -22, -44, 67, -14, -43, 37, 2, -32, 15, 7, 8, -22, -1, 14, 19, -43, 0, 40, -30, -14, 28, 10, -32, 11, 1, 21, -33, -9, 31, 15, -72, 61, 4, -40, 21, 14, -37, 22, 4, -4, -9, 5, -8, 23, -16, -22, 35, -24, 0, 12, 3, -17, 15, 2, -10, -6, -8, 21, 7, -58, 40, 43, -75, 25, 28, -25, -18, 28, -15, 6, -5, -4, 22, -5, -39, 37, 1, -30, 12, 23, -27, -8, 34, -22, 0, -12, 15, 10, -28, 2, 45, -45, -9, 36, -22, -7, 13, -7, 6, 2, -18, 17, 10, -34, 9, 18, -22, -1, 22, -9, -17, 23, -1, -22, 21, -20, 20, -17, -6, 38, -33, -18, 55, -32, -21, 26, -5, -9, 5, -8, 16, 9, -47, 36, 11, -36, -3, 38, -7, -48, 44, -2, -11, 2, -16, 15, 11, -36, 33, -3, -18, 9, 19, -46, 26, -1, -11, 20, -24, 12, 16, -16, -17, 37, -32, -6, 13, 13, -33, 25, 14, -27, 8, 1, -18, 22, -5, -15, 32, -46, 37, -2, -19, -13, 38, -32, 8, 2, -4, 15, -12, -4, 19, -25, -10, 37, -19, -11, -10, 57, -54, 19, -17, 18, 3, -18, -9, 27, -6, -36, 57, -23, -21, 14, 11, -23, 32, -53, 56, -24, -5, -3, 11, -16, 16, -7, -20, 17, 11, -3, -31, 42, -33, 14, -6, -2, -8, 39, -56, 48, -21, -20, 30, -8, -20, 12, 15, -32, 41, -36, 29, -25, 14, -22, 22, -19, 9, 4, 10, -31, 17, 11, -14, -1, -7, 17, -16, 6, -18, 64, -88, 47, 6, -20, -5, 22, -13, 18, -28, 2, 25, -19, -10, -3, 29, -23, 11, -22, 39, -25, 13, -27, 20, -2, -18, 15, -3, 3, 9, -17, -8, 38, -57, 35, 1, -9, -24, 43, -32, 30, -30, -3, 19, -3, -21, 12, 14, -12, 2, -5, 11, -37, 37, -3, -13, -4, 10, 11, -4, -38, 41, -9, -27, 37, -37, 16, 17, -7, -15, 22, -40, 33, -2, -16, 4, 3, 8, -4, -20, 21, -3, -10, 8, -26, 37, -21, 8, 0, -3, -3, 0, -8, 20, -15, -32, 54, -10, -26, 17, -12, 10, 24, -71, 51, 3, -21, 9, -3, 17, -22, 2, 15, -21, -11, 39, -25, 11, -27, 28, 3, -11, -26, 45, -43, 24, 7, -39, 47, -24, -15, 27, -13, -15, 35, -27, 15, -17, 9, 0, -7, 0, 4, -9, 13, -3, -16, 28, -29, 21, -23, 11, -4, 10, -30, 64, -63, 13, 28, -30, 16, -13, 0, 25, -39, -2, 53, -40, 5, -19, 41, -25, -6, -3, 37, -40, 6, 8, 0, 6, -34, 32, 4, -27, 13, 15, -34, 52, -63, 40, -5, -22, 5, 24, -32, 22, 11, -26, 14, -22, 26, -21, 10, -8, 5, -10, 46, -66, 44, -20, 14, -7, -27, 23, 30, -53, 24, 10, -37, 44, -40, 21, -11, 3, 6, 20, -47, 27, 5, -2, -18, -4, 29, -13, -20, 27, 9, -47, 43, -37, 55, -62, 14, 33, -13, -28, 24, -9, 23, -35, -4, 32, -14, -13, 28, -10, -30, 46, -43, 43, -46, 13, 13, -10, 7, -3, -20, 39, -19, -19, 14, -15, 39, -31, -10, 25, 2, -34, 41, -35, 15, -4, -3, 22, -18, -27, 46, -1, -36, 10, -4, 42, -56, 13, 31, -19, -18, 28, -29, 27, -32, 24, 10, -44, 20, 32, -32, -17, 32, -13, 13, -35, 20, 32, -53, 20, 9, -16, 16, -36, 39, -3, -33, 43, -26, 2, 2, 2, -17, 24, -22, 14, -3, -12, 31, -28, -8, 26, -29, 19, -4, -15, 33, -39, 22, 16, -37, 6, 17, -4, -13, -12, 37, 9, -65, 34, 25, -27, -9, 7, 5, 10, -36, 45, -11, -41, 42, -6, -21, 7, -5, 31, -5, -57, 62, -12, -15, -16, 23, 4, -24, 12, 26, -35, -11, 44, -25, -8, -1, -4, 28, -11, -37, 61, -48, 23, -1, -30, 29, -8, -2, 6, -19, 18, 15, -41, 30, -4, -11, -11, 28, -10, -4, -37, 81, -45, -43, 61, -19, 1, -11, 0, 31, -30, -25, 68, -43, -11, 0, 27, -1, -33, -7, 77, -54, -30, 44, -6, -5, -14, 17, -6, -10, 6, 30, -68, 50, -16, 5, 5, -30, 30, 26, -69, 36, 8, -34, 37, -28, 11, 0, -1, 9, 1, -41, 53, -22, -24, 23, 5, -9, -11, 12, 28, -61, 28, 36, -68, 51, -33, 25, -6, -26, 7, 53, -65, 2, 47, -25, -23, 17, 20, -4, -51, 38, 29, -67, 31, 1, 22, -35, -8, 40, -9, -46, 47, -13, -8, 5, -15, 37, -27, -20, 45, -16, -45, 59, -37, 19, -6, 2, 1, -11, -3, 34, -42, 0, 33, -30, 16, -13, 13, 2, -23, 18, -5, -26, 43, -24, 15, -26, 4, 35, -15, -62, 64, 19, -75, 50, -8, 8, -14, -12, 31, -19, -30, 45, -10, -12, -10, 36, 3, -53, 14, 45, -37, -22, 42, -25, 21, -36, 21, 37, -61, 5, 47, -49, 19, -4, 5, 1, -12, 7, 3, -11, 2, 18, -28, 13, -4, 18, -13, -20, 33, -22, -8, 21, -12, -10, 24, -9, 2, -27, 15, 33, -41, -18, 56, -40, 9, -5, 6, 20, -44, 11, 39, -35, -22, 50, -7, -36, -6, 41, -10, -30, 15, 20, -22, 7, -11, 16, 6, -51, 59, -21, -26, 24, 12, -24, 8, -7, 12, 3, -36, 27, 18, -42, 22, 9, -22, 11, -2, 15, -40, 38, -13, -16, 8, 24, -33, 15, -13, 4, 23, -42, 17, 30, -34, -5, 28, -22, 11, -23, 30, -14, -28, 37, 12, -46, 11, 31, -23, -12, -7, 36, -17, -6, -4, 25, -18, 4, -29, 53, -48, 4, 24, -9, -21, 30, -1, -20, 2, -13, 51, -51, -1, 39, -23, -18, 33, -23, 3, 3, 2, -13, 11, 4, -13, 15, -14, -3, 1, 24, -53, 55, -24, -17, 36, -1, -49, 45, -7, -12, -2, -4, 24, -23, 1, 6, 23, -51, 30, -8, 14, -29, 17, 12, -9, -21, 21, 1, 3, -32, 21, 30, -59, 27, 25, -21, -26, 36, -24, 16, -23, 15, 10, -15, 11, -11, -3, 14, 1, -30, 32, -24, 27, -25, 10, -12, 29, -33, 7, -5, 25, -29, 14, 15, -42, 20, 18, -27, 1, 21, -19, 17, -18, 2, 19, -12, -34, 47, -21, -6, 9, -2, 14, -32, 32, -23, 14, -21, 21, 0, -13, -8, 42, -35, -19, 33, 4, -34, 23, -5, -6, 22, -31, 21, -8, -5, -3, 15, -22, 10, 2, 7, -17, 11, 3, -10, 2, -1, -2, -9, 25, -20, 11, -18, 17, -3, -12, 2, 9, -1, -10, 5, 0, 15, -40, 36, -5, -28, 16, 24, -34, 16, -1, 13, -32, 11, 9, 5, -26, 5, 32, -32, 4, -1, 29, -38, 8, 7, -6, 5, -2, -5, 18, -26, -2, 39, -42, 0, 26, 2, -43, 45, -30, 20, -11, -6, -3, 16, -7, -6, 3, 12, -13, 5, -7, -21, 47, -29, -11, 9, 36, -45, 8, 0, 22, -28, -7, 32, -22, -9, 20, 12, -40, 24, -8, 14, -28, 10, 9, 12, -29, 15, -7, 15, -23, 5, 14, -24, 12, 8, 4, -38, 36, -4, -7, -30, 47, -13, -24, 16, 23, -46, 29, -3, -10, 20, -43, 35, 0, -4, -30, 47, -18, -21, 16, 19, -35, 11, 19, -21, -11, 27, -12, -9, 16, -21, 23, -32, 30, 3, -22, -15, 51, -38, -1, -2, 11, 15, -28, -1, 16, 13, -42, 23, 4, -6, -32, 61, -24, -35, 34, 29, -55, 4, 13, 9, -6, -26, 35, -6, -11, -11, 19, -6, -3, -15, 43, -41, 4, 22, -1, -34, 18, 15, -35, 18, -1, 23, -35, 18, -2, -9, 1, 10, -18, 17, -18, 21, -8, -17, 24, -1, -20, -7, 26, -11, 6, -33, 42, 0, -40, 9, 46, -48, -6, 24, 13, -39, 8, 41, -43, 3, 6, 6, -7, -6, -8, 42, -37, -11, 39, -16, -26, 25, 3, -24, 9, 11, 6, -34, 17, 14, -12, -22, 20, 0, 14, -38, 27, 10, -37, 22, -1, -5, -7, 11, 4, -3, -29, 38, -5, -26, 4, 20, -17, 6, 2, 11, -17, -10, 40, -49, 10, 26, -8, -24, 11, 12, 5, -36, 21, 20, -22, -29, 28, 30, -30, -24, 31, 25, -70, 39, 4, -16, 3, 9, -13, 16, -26, 23, 19, -46, 1, 29, 6, -37, 8, 27, -8, -33, 36, -24, 5, 14, -8, -8, 1, 4, 15, -27, -11, 44, -38, 6, 12, -3, -12, 20, -17, 16, -35, 28, -4, 0, -13, 8, 23, -24, -16, 28, 11, -58, 48, 6, -39, 11, 24, -9, -8, -25, 42, -16, -14, 12, 2, 13, -31, 6, 26, -10, -48, 64, -22, -21, 6, 28, -15, -11, -2, 22, -30, 11, 15, -25, 13, 2, -1, -7, -4, 6, 17, -37, 17, 0, 1, 14, -23, 4, 16, -23, 6, 12, -31, 30, 6, -18, -25, 45, -7, -20, -15, 44, -38, 9, 22, -37, 24, 6, -20, 14, -17, -8, 44, -27, -22, 16, 30, -33, -18, 20, 31, -50, 11, 27, -21, -4, -3, 26, -15, -24, 15, 20, -27, 16, -12, 9, 5, -24, 3, 26, -27, 5, 15, -19, 9, -9, 26, -25, -5, 10, -4, -6, 31, -45, 18, 24, -23, -23, 27, -3, 2, -18, 9, 13, -18, 19, -17, 7, -1, -24, 31, 5, -49, 31, 32, -40, -7, 10, 14, -12, -12, 5, 21, -30, 25, -12, 4, -18, 9, 11, -13, -20, 37, -8, -3, -13, -3, 33, -21, -32, 44, -7, -22, 28, -24, 5, 12, -19, 2, 6, 2, -16, 11, 10, -6, -23, 31, -25, 7, 6, -16, 18, 1, -35, 40, -9, -18, 12, 4, -2, -25, 20, 19, -16, -35, 46, -14, -8, -3, -1, 24, -12, -25, 26, -4, -6, 3, -12, 20, -24, 18, 9, -20, -2, 18, -13, -1, -16, 8, 26, -35, 12, 10, -11, 6, 2, -30, 46, -43, 16, 6, 1, -20, 26, -18, 8, -13, 9, -3, 3, 1, -25, 29, 13, -50, 12, 41, -47, 15, 14, -12, 2, -3, -1, 14, -25, -3, 26, -23, 19, -35, 41, -5, -23, -1, 31, -30, 8, -15, 32, -29, -7, 22, 10, -35, 12, 6, -2, 20, -50, 36, 7, -17, -4, -1, 7, 2, -21, 19, -12, 1, 28, -25, -5, 9, -3, -12, 32, -45, 16, 21, 0, -43, 21, 28, -19, -38, 45, -15, -8, 28, -43, 39, -12, -23, 13, 19, -39, 23, -3, 17, -32, 6, 20, -5, -32, 23, 8, -15, -1, 11, 9, -28, 5, 20, -18, -6, 9, -18, 50, -50, -8, 49, -30, -5, -4, 14, -19, 28, -21, 2, 4, 11, -20, 6, 3, -5, -24, 54, -34, -14, 26, -4, -2, -16, 5, 20, -23, 1, 6, -9, 32, -37, 1, 25, -22, -8, 31, -6, -37, 31, 0, 3, -37, 24, 25, -27, -20, 27, 1, 4, -26, 13, 3, -14, 12, -6, 6, -3, -6, 18, -14, -27, 38, 5, -36, 14, 13, -22, 26, -13, -22, 36, -23, -5, 3, 18, -12, -23, 31, -5, -24, 23, -15, 17, -7, -23, 20, 6, -4, -19, 20, -8, 15, -32, 13, 17, -30, 17, 13, -19, -8, 4, 24, -18, -29, 36, 7, -21, -20, 28, 13, -17, -31, 36, -9, -7, 7, 6, -9, -4, 7, -6, 10, -32, 41, -26, 12, -10, -12, 35, -10, -39, 36, -9, -7, 7, 6, -9, -4, 11, -14, 5, -7, 9, -13, 24, -27, 4, 14, 7, -31, 19, -14, 17, -5, -34, 57, -31, -7, -6, 28, -15, -11, 2, 25, -21, -14, 15, 18, -35, 12, 1, 9, -20, -2, 32, -37, 26, -17, 7, 1, -10, -18, 54, -37, -16, 23, 11, -13, -23, 34, -5, -16, -10, 25, -28, 30, -10, -7, -5, 18, -24, 25, -24, 18, -11, 0, 3, -19, 34, -12, -12, 2, 3, -13, 32, -37, 20, 4, -6, -25, 29, -3, -2, -11, -2, 28, -38, 18, 7, -5, -7, 0, -4, 21, -36, 30, -19, 25, -29, -15, 48, -11, -43, 33, 33, -64, 17, 26, -12, -18, 9, -1, 18, -33, 23, -13, 21, -18, -13, 18, -2, -20, 20, 6, -15, 4, -12, 28, -27, 1, 10, -5, 3, 0, -17, 15, 17, -30, 2, 5, -8, 17, -11, -2, 9, -20, 23, -27, 23, -10, -3, 7, -3, -25, 31, 9, -28, -9, 30, -5, -28, 15, 29, -36, -9, 29, -11, -20, 33, -27, 21, -14, -12, 21, -3, -9, -2, 12, -5, -27, 27, 7, -20, -11, 32, -9, -15, -1, 9, 20, -42, 12, 9, -4, 3, -6, -3, 6, 0, -12, 15, -25, 27, -6, -6, -6, 6, -2, -4, 5, 9, -20, 12, 8, -17, -10, 30, -12, -24, 25, -15, 18, -21, 21, -8, -6, -9, 12, -6, 15, -33, 26, 8, -32, 13, 21, -12, -28, 20, 11, -6, -28, 27, 11, -21, -10, 22, -1, -11, -7, 24, -12, -27, 35, -8, 0, -20, 23, -10, 9, -30, 32, -15, 3, -7, 6, -2, 10, -17, 1, 8, -4, -5, -3, 14, -9, 1, -11, 18, -13, 15, -33, 22, 14, -32, 11, 9, -1, -17, 14, 0, -3, -16, 29, -21, -4, -1, 28, -24, -2, -11, 41, -25, -23, 24, 6, -18, -13, 37, -21, -2, -4, 29, -40, 11, 12, 4, -25, 12, -9, 23, -17, -14, 27, -2, -26, 9, 18, -14, -1, -15, 29, -18, -4, 5, 12, -26, 18, -3, -7, 3, 13, -10, -25, 44, -38, 11, 8, -2, -25, 28, -9, 12, -13, -13, 10, 27, -53, 19, 16, -4, -20, 12, 12, -21, 5, 12, 3, -35, 22, 8, 0, -28, 18, 16, -25, -3, 9, 8, -3, -19, 8, 24, -34, -4, 38, -16, -30, 29, -1, -2, -25, 28, -1, -21, 11, 10, -18, -1, 10, 1, -7, 0, 1, -7, 15, -15, -5, 16, 2, -22, 8, 0, -1, 26, -34, -22, 56, -26, -11, 12, 9, -9, -9, 4, 7, -8, -1, 8, 0, -21, 10, 19, -8, -25, 17, 10, -18, 3, -4, 26, -15, -29, 30, 9, -46, 36, 12, -33, 1, 18, -2, -16, 4, 16, -10, -16, 11, 2, 8, -19, 5, 1, 10, -21, 20, -8, -1, -3, 1, 7, -19, 7, 11, -12, 5, 5, -26, 29, -11, -5, -2, 12, -13, 9, -22, 23, 3, -20, 4, 17, -16, -13, 17, 15, -16, -34, 37, -5, 8, -32, 23, 17, -36, -2, 36, -25, -4, 28, -18, -20, 15, 4, 7, -12, -24, 43, -19, 0, -11, 25, -9, -12, -7, 10, -1, 11, -2, -12, 13, -27, 30, -9, -15, 8, 17, -28, 18, -9, 3, 7, -8, -10, 16, -26, 35, -22, -10, 37, -35, 1, 11, 11, -19, -2, 9, 17, -37, 11, 10, 9, -16, -12, 27, -11, -22, 16, 24, -48, 25, -1, -3, 4, -20, 13, 39, -72, 34, 1, 2, -6, 4, -1, -8, 2, -8, 18, -10, -1, -5, 19, -30, 5, 30, -16, -26, 36, -26, 3, 21, -27, 10, 4, -10, 0, -4, 15, 9, -41, 32, -11, 2, -11, 15, -3, -7, -8, 16, -3, -21, 23, -2, -9, -4, -2, 20, -5, -37, 49, -20, -6, -9, 17, 17, -36, -8, 40, -24, -5, 3, 8, 5, -12, -6, 15, 2, -27, 28, -4, -23, 16, 5, -1, -26, 29, 11, -38, 22, -12, -8, 38, -34, -3, 10, 4, -2, -5, -8, 24, -16, -20, 21, 1, -7, 11, -7, -4, -15, 15, 15, -21, -6, 10, -1, 17, -45, 23, 29, -42, 2, 18, -5, -6, -1, 22, -20, -19, 16, 21, -20, -18, 23, 2, 5, -41, 36, 10, -34, 12, 12, -25, 11, 1, 6, -6, -11, 20, -11, 10, -11, -12, 13, 8, -21, 5, -1, 14, 3, -26, 5, 27, -39, 18, 7, -27, 34, -20, 13, -20, 7, -4, 25, -23, -16, 7, 47, -35, -29, 37, 10, -35, 4, 12, -1, 0, -15, 25, -23, -12, 35, 7, -51, 28, -1, 16, -33, 5, 27, -21, 2, -5, 13, -3, 0, -20, 27, -30, 8, 16, -4, -13, 14, -15, 19, -12, -6, 8, -9, 19, -27, 4, 20, -9, -12, 21, -37, 41, -22, 1, 1, 13, -33, 20, 14, -30, -2, 22, 21, -51, 3, 38, -7, -35, 17, 6, 11, -43, 33, 9, -36, 10, 31, -24, -13, 16, -6, 24, -36, -1, 16, 19, -45, 20, 11, 2, -30, 31, -21, -14, 29, -4, -12, 3, -6, 9, 15, -37, 20, -4, 8, -18, 12, -7, 17, -8, -12, -9, 23, 8, -28, 1, 29, -19, -18, 27, -2, -8, -28, 44, -4, -36, 15, 33, -30, -13, 13, 14, -20, -7, 25, -11, -5, -8, 21, -1, -8, -37, 50, 1, -53, 27, 28, -21, -10, 4, 16, -24, 10, 6, -12, 0, 2, 6, 1, -13, 2, 21, -26, 3, 13, -19, 10, 9, -18, -3, 22, -18, -1, -2, 14, -1, -23, 21, -6, -2, -9, 20, 5, -35, 1, 34, -21, -16, 22, 1, -8, -5, 1, 18, -12, -23, 18, 5, -17, -7, 37, -6, -35, 6, 47, -44, -7, 20, 5, -10, -23, 35, -6, -12, -12, 39, -27, -10, 9, 21, -21, -6, 2, 5, 1, 6, -28, 17, 20, -31, -3, 15, 7, -26, 31, -40, 43, -32, 23, -19, 11, -22, 26, -6, -1, -25, 33, 2, -25, -7, 9, 26, -16, -30, 29, 20, -47, 13, 16, -9, -19, 18, 23, -32, -17, 32, 21, -38, -13, 14, 43, -66, 19, 23, 5, -50, 47, -20, 2, -11, 22, -5, -6, -21, 4, 38, -15, -32, 12, 35, -35, -4, 7, 18, -17, -1, -7, 6, 5, 0, 0, -7, 0, -8, 21, -10, 5, -28, 30, 3, -17, -29, 57, -16, -17, -10, 28, -9, -20, 26, -12, 3, -20, 27, -3, -7, -42, 65, -9, -45, -3, 63, -33, -11, -6, 28, -17, -1, -6, 6, 7, -12, 0, 25, -21, -30, 54, -9, -37, 1, 28, 7, -42, 18, 11, 17, -46, 24, -9, 27, -38, 22, -20, 23, -21, 11, -6, 42, -71, 20, 32, -11, -43, 44, -3, -4, -27, 12, 24, -8, -18, -8, 30, -19, -23, 44, -8, -30, 0, 45, -39, 0, -1, 28, -16, -17, -15, 44, -13, -11, -13, 36, -24, -11, 12, 17, -30, 8, 17, -10, -18, 9, 22, -18, -15, 3, 25, -25, 11, -6, 5, 7, -18, -3, 15, -1, -17, 8, 28, -32, -17, 36, 8, -41, 12, 7, 13, -22, -14, 18, 41, -57, -1, 25, 10, -40, 18, 11, -8, -23, 25, -16, 37, -45, 17, 10, 2, -60, 64, -15, -3, -16, 22, -9, 9, -27, 30, -7, -21, 3, 20, -10, 6, -12, 15, -19, 14, -19, 3, 22, -8, -29, 37, -28, 29, -26, 11, -15, 15, -17, 21, -26, 18, 5, -5, -11, 2, 16, -10, -10, -5, 29, -30, 4, 3, 18, -21, 4, 1, 8, -13, -10, 1, 40, -35, -26, 44, 5, -38, 8, 30, -24, 0, -1, 0, 12, -18, -1, 18, -8, -28, 39, -18, 24, -35, 24, -36, 46, -41, 12, -3, 24, -37, 31, -28, 32, -16, 2, -27, 39, -34, 7, 24, -19, -6, 14, -10, -1, 14, -16, -4, 25, -26, -4, 8, 22, -40, 33, -30, 22, -15, 36, -63, 39, 1, 10, -54, 36, 9, 5, -51, 49, -13, 5, -7, -7, 15, -9, -10, 2, 12, -18, 6, 3, 18, -29, 9, 10, -10, 1, -20, 20, -3, -1, -13, 21, -26, 41, -36, 2, 23, -23, -10, 39, -41, 17, -10, 8, 7, -13, 23, -54, 66, -26, -50, 54, 17, -66, 59, -46, 30, -10, 6, -8, -18, 19, 16, -32, 12, 6, -2, 3, -36, 33, -6, -7, 12, -16, 6, 14, -21, 14, 16, -58, 37, 3, 0, -35, 44, -16, 17, -38, 28, -14, 25, -45, 28, -21, 32, -31, 11, 17, -24, 11, 5, -24, 18, -6, -3, 0, -3, 21, -33, 24, 20, -78, 66, -8, -24, 3, 17, -14, 24, -41, 34, -25, 27, -32, 17, -5, 13, -26, 28, -29, 22, -8, -16, 33, -30, 2, 25, -27, 1, 31, -36, -7, 31, -8, -12, -5, 17, -7, 5, -26, 32, 1, -18, -16, 27, -7, -10, 2, 21, -42, 30, -3, -19, 33, -40, 19, 6, -13, -5, 17, -10, 28, -63, 40, 6, -10, -9, 7, -3, 12, -20, -1, 17, -1, -6, -14, 18, 1, -19, 12, 5, -9, -2, -14, 33, -3, -44, 51, -17, -6, -16, 36, -35, 29, -31, 31, -24, 15, -23, 33, -35, 20, -4, -1, -19, 27, -1, -29, 25, 1, -20, 25, -23, -13, 62, -50, -18, 43, -20, 1, -4, 16, -18, 4, -16, 36, -42, 42, -42, 38, -28, 9, -10, 31, -40, 30, -39, 30, 8, -28, 11, 9, -7, -6, -8, 10, 22, -36, -5, 26, 4, -41, 30, 12, -11, -10, -14, 37, -29, 3, -6, 9, -5, 15, -30, 40, -26, 12, -25, 25, -21, -12, 46, -17, -39, 47, 7, -57, 45, -14, 1, -13, 21, -21, 14, -7, 7, -11, 18, -34, 25, 7, -28, 22, 1, -12, 11, -24, 4, 38, -44, 17, 2, -12, 19, -17, 0, 9, 17, -55, 29, 3, 3, -27, 48, -38, 16, -17, 24, -19, 26, -49, 29, 9, -18, -25, 50, 2, -31, -20, 43, -3, -35, 23, 13, -34, 9, 20, -15, -8, 29, -37, 29, -21, 4, -8, 36, -52, 29, -8, 6, -18, 35, -34, 22, -21, 10, 5, -11, -13, 35, -26, -3, 12, -17, 13, 1, -12, -4, 24, -18, -6, 18, -7, -13, 17, -4, -30, 48, -41, 10, 34, -39, -22, 73, -48, -12, 12, 22, -14, -31, 18, 29, -17, -21, 22, -3, -8, -12, 25, -11, 13, -41, 36, -3, -2, -27, 37, -6, -36, 17, 18, -7, -10, 4, -5, 10, -21, 13, 15, -21, 2, -1, -5, 8, -1, -16, 29, -24, 14, -18, 26, -24, 17, -26, 21, -18, 24, -49, 82, -52, -11, 36, -22, -17, 30, -21, 1, 1, -1, 8, -2, -7, 2, 17, -9, -36, 37, -5, -15, -4, 27, -20, 11, -31, 46, -18, -13, -11, 58, -67, 19, -4, 40, -43, 9, -14, 41, -32, -16, 46, -19, -13, 5, -5, 6, 2, -16, 10, -9, 18, -13, 3, 24, -37, 11, 1, 0, -8, -9, 28, -1, -41, 40, -10, 6, -13, 1, -11, 30, -28, -10, 30, 1, -36, 17, 28, -54, 51, -24, 1, -6, 6, -12, 33, -48, 23, 18, -17, -23, 27, 11, -23, -13, 27, -7, -1, -24, 35, 3, -48, 35, 8, -20, -3, 3, 16, -11, 8, -35, 32, 7, -27, -22, 81, -85, 36, -7, 16, -16, 2, 0, 13, -28, 12, -16, 24, 6, -25, -14, 47, -15, -25, 3, 37, -41, -5, 32, -25, 11, 6, -16, 25, -34, 14, 8, 13, -52, 30, 6, 13, -56, 56, -27, 13, -11, -6, 16, -12, -1, 18, -40, 18, 19, -13, -11, 7, -2, 9, 10, -39, 9, 46, -48, -18, 59, -32, -3, 14, -10, 10, -13, 10, -13, 14, -11, -10, 5, 31, -43, 10, 23, -16, 3, -29, 50, -23, -19, 16, 15, -19, 3, -20, 39, -19, -14, -6, 54, -44, -12, 18, 30, -56, 28, -15, 22, -16, -15, 31, -8, -9, -1, 1, 1, 2, -8, 9, 10, -43, 41, -9, 8, -48, 62, -30, -9, 13, 6, -24, 32, -31, 8, -4, 16, -27, 27, -19, -1, -6, 37, -40, 14, -3, 0, 25, -59, 34, 18, -18, -21, 17, 13, -11, -8, -11, 43, -40, 1, 6, 24, -37, 10, 14, -4, -12, -2, 17, 11, -40, 10, 16, 17, -51, 24, 14, -4, -31, 22, 18, -32, 15, -24, 46, -38, 9, 2, -2, 14, -15, -12, 15, 3, -28, 29, -7, -6, 13, -7, -6, 2, 3, -17, 28, -28, -9, 37, -17, 0, 3, 10, -19, -5, 19, -17, 12, -25, 30, -19, 8, -27, 49, -15, -27, 9, 10, 7, -31, 6, 30, -12, -45, 41, 24, -42, -1, 28, -2, -38, 29, -18, 23, -4, -43, 35, 26, -54, 23, 7, 6, -30, 17, -14, 32, -40, 24, -13, 17, -15, -11, 16, 16, -20, -26, 47, -10, -26, -6, 41, -19, -22, 36, -41, 33, 5, -32, 12, 28, -51, 19, 27, -40, 7, 35, -34, 9, -22, 42, -20, -15, -3, 43, -55, 15, 23, -10, -11, 3, 14, -32, 31, -26, 21, 7, -44, 15, 40, -22, -41, 54, -17, -17, 8, -6, 10, 11, -17, -6, 15, -2, -20, 31, -19, 4, -17, 22, 0, 2, -36, 39, 0, -31, 23, -38, 59, -15, -29, -13, 69, -50, -22, 43, -11, -16, 0, 16, -9, -10, 13, 5, -8, -18, 27, -8, -2, -12, 13, -1, -16, 16, -18, 27, -11, -19, 39, -28, -26, 28, 36, -85, 72, -40, 24, -10, 0, -9, 30, -29, -11, 22, -13, -7, 23, -10, -14, 6, 13, -15, 22, -31, 12, 0, 0, -3, -15, 19, 14, -21, -22, 27, 35, -72, 36, -3, 18, -54, 50, -29, 38, -47, 14, 19, -11, -25, 27, 9, -23, -2, 2, 16, -6, -24, 22, 10, -27, 7, 16, -30, 11, 24, -40, 31, -28, 29, 1, -28, 7, 17, 3, -45, 40, -11, -7, 4, 19, -45, 24, 24, -50, 48, -35, 11, 9, -12, -14, 30, -23, 8, 7, -15, -7, 53, -59, 13, 5, 15, -46, 49, -48, 57, -36, -20, 34, 1, -10, -15, 15, 20, -36, -9, 35, 6, -39, 7, 14, 27, -81, 70, -21, 5, -22, 21, -6, 1, -13, 19, -19, 4, -10, 35, -43, 31, -3, -7, -15, 40, -56, 33, -1, -33, 51, -35, -2, 24, -18, 5, 0, 4, -16, 10, -6, 9, -28, 37, -38, 45, -35, 0, 37, -38, 7, 19, -32, 3, 17, -2, -23, 19, 15, -23, 5, -2, 13, 1, -37, 8, 59, -80, 26, 13, 15, -31, -8, 30, -7, -7, -19, 22, -2, -9, -2, 12, -7, 3, 1, -25, 47, -53, 35, -5, -27, 21, 15, -25, 13, -24, 42, -41, 19, 2, -13, 1, 23, -40, 37, -45, 46, -8, -41, 44, -11, -17, 23, -9, -20, 22, -3, -15, 22, -23, 19, -7, 2, -34, 65, -56, 7, 28, -8, -37, 37, 3, -8, -34, 39, -11, 9, -29, 6, 35, -14, -49, 48, 5, -25, 5, -25, 66, -47, -9, 28, -7, -12, 0, 17, -20, -2, 21, -12, -23, 54, -50, 20, 7, -20, 7, -2, 3, 4, -26, 26, -6, -14, 15, -3, -10, 12, -10, -4, 23, -33, 14, -12, 38, -55, 36, 0, -6, -5, 0, -4, 7, 0, -14, 2, 8, -11, 13, 5, -33, 41, 4, -62, 40, 8, -6, -8, -31, 52, -4, -44, 25, 20, -18, -24, 32, -11, -9, -4, 30, -37, 34, -31, 7, 30, -29, -14, 28, -10, -9, 6, 0, -5, 14, -9, -3, -2, 10, -22, 29, -22, -2, 6, -5, 16, -25, 6, 27, -19, -9, -11, 29, -13, -5, -6, 16, 5, -20, -1, 30, -20, -8, 7, -8, -2, 3, 14, -9, -24, 35, -7, -14, -12, 32, -5, -18, -15, 35, -7, -13, -1, -4, 27, -20, -30, 58, -15, -29, 9, 15, -16, -3, 1, 4, 5, -4, -11, 17, 3, -29, 28, -10, -18, 20, -7, -2, 4, 2, -17, 22, -3, -31, 23, 23, -32, -14, 34, -3, -14, -13, 11, 21, -26, -16, 36, -7, -13, 15, -8, -3, -1, -11, 15, -8, -4, -4, 24, -21, 1, 11, 3, -22, 5, 15, -24, 0, 37, -31, 7, -18, 15, 16, -15, -19, 26, 0, -10, -26, 31, 6, -19, -6, 21, -19, 20, -13, -3, 13, -2, -32, 24, 2, -8, -10, 36, -29, -10, 19, 10, -25, 5, -9, 31, -23, -21, 21, 26, -25, -9, -5, 35, -17, -34, 17, 42, -44, -11, 30, 11, -40, 18, 8, -6, -11, 11, -26, 39, -18, -23, 37, -12, -32, 45, -8, -22, 5, 16, -15, -10, 6, 17, -15, -3, 9, -22, 41, -22, -25, 29, 5, -30, 6, 12, 17, -32, 7, 20, -26, 9, 9, -10, 7, -17, 10, 11, -16, -7, 12, 5, -4, -26, 25, 24, -46, -4, 50, -39, -11, 8, 35, -36, 2, -9, 33, -7, -22, -26, 76, -37, -41, 33, 28, -43, 14, 6, 2, -8, 2, -20, 34, -19, -2, -4, 15, -6, -23, 28, -3, -32, 33, -16, 7, -11, 14, 9, -10, -30, 35, -25, 17, -14, 1, 14, 12, -38, 16, 15, -7, -30, 15, 18, -24, -6, 47, -38, 6, 7, -9, -2, -3, 1, 12, -8, -23, 20, 35, -47, -14, 51, -9, -48, 19, 20, 0, -25, -2, 20, 16, -29, -25, 60, -17, -23, -8, 31, -4, -30, 12, 20, -14, -4, -1, 17, -11, -9, 7, 7, -17, 1, -12, 25, -5, -20, 15, 19, -29, 2, 5, 11, -19, -18, 31, 1, -27, 18, -17, 51, -53, -2, 29, 4, -37, 17, 11, -11, -23, 41, -17, -10, 13, -4, -8, 18, -27, 17, 1, -19, -7, 51, -37, -28, 53, 4, -47, 5, 18, 17, -32, -8, 14, 36, -46, 3, 11, 11, -24, 4, 0, 16, -7, -26, 25, 20, -44, 7, 20, -12, 2, -14, 4, 33, -38, 1, 8, 20, -34, -12, 61, -46, -19, 44, -10, -4, -18, 12, 12, -8, -26, 16, 22, 2, -51, 18, 53, -56, -5, 30, -9, -22, 32, -11, -18, 18, 13, -25, -7, 8, 9, 3, -20, 1, 32, -27, -9, 5, 19, -20, -13, 18, 8, 3, -35, 22, 31, -47, -2, 16, -8, 15, -10, -22, 54, -20, -23, -6, 51, -52, -13, 48, -23, -11, 28, -30, 38, -6, -50, 28, 33, -58, 2, 34, 16, -53, -1, 55, -13, -42, 15, 23, -7, -33, 13, 21, -14, -6, 2, -2, 27, -43, 27, 11, -19, -16, 26, -16, -4, 16, -17, 1, 20, -17, 8, -17, 6, 26, -25, -24, 40, -13, 6, -14, -14, 29, 3, -32, -5, 46, -21, -28, 38, -30, 6, 28, -47, 3, 65, -67, -5, 61, -34, -27, 31, 12, -30, -7, 11, 19, 0, -43, 18, 47, -52, -20, 52, -14, -9, -10, -5, 55, -45, -29, 55, 16, -83, 28, 36, -23, 6, -8, -13, 37, -17, -30, 32, -9, -6, 10, -19, 16, 4, 9, -35, 22, -1, -17, 3, 8, 10, -10, -21, 40, -27, -5, 16, -6, -27, 47, -23, -26, 48, -18, -19, 14, -1, -9, 5, 1, -20, 58, -57, -14, 55, -16, -40, 37, -6, 11, -19, -22, 43, 2, -55, 27, 37, -38, -29, 58, -6, -11, -22, 4, 26, -7, -67, 67, 21, -56, 19, 15, -5, 0, 2, -41, 37, 10, -65, 49, 8, 1, -19, 1, 9, 8, -20, -9, 22, -14, -3, 4, -1, 13, -6, -11, 15, -8, -15, 13, 16, -38, 14, 24, -39, 20, 9, -17, 14, -15, 7, 3, -12, -3, 30, -25, -24, 43, -1, -40, 18, 17, 0, -22, -14, 31, 20, -68, 35, 32, -43, -9, 35, -16, 4, 2, -35, 35, 27, -81, 40, 31, -21, -30, 29, -12, 13, 10, -42, 26, 17, -33, -1, 16, 12, -29, 6, 4, 21, -27, -9, 39, -6, -54, 40, -14, 15, -4, -17, 20, 4, -18, -4, 23, -24, -3, 30, -41, 15, 17, -4, -29, 19, 4, -9, -10, 12, 17, -21, -7, 26, -19, -17, 17, 3, 1, -3, -30, 47, 16, -62, -4, 68, -29, -54, 43, -1, -4, 20, -42, 22, 34, -32, -43, 63, -12, -26, 8, -6, 10, 22, -66, 55, 25, -65, 15, 9, 21, -22, -28, 36, 5, -16, -51, 102, -49, -12, 6, 21, -12, -23, 24, -15, 11, -14, -8, 31, 4, -53, 64, -35, 13, -28, 23, -23, 22, -16, 13, -22, 23, 27, -51, -8, 41, 6, -66, 36, 13, 4, -26, 7, 11, 9, -34, 0, 35, -21, -15, 10, 34, -57, 60, -69, 60, -22, 1, -27, 27, 14, -27, 1, -13, 35, -2, -51, 36, 35, -49, 5, -1, 31, -42, 25, -26, 34, -7, -60, 98, -46, -22, -1, 49, -45, -2, 10, 26, -33, 25, -36, 37, -19, 4, -3, -7, 9, 7, -8, -29, 48, -23, 0, -33, 45, 0, -23, -16, 47, -7, -31, -9, 38, -2, -36, 18, -8, 43, -55, 16, -1, 41, -72, 54, -35, 24, 4, -46, 47, -11, 6, -40, 24, 10, 8, -38, 16, 16, 24, -98, 80, 2, -28, -28, 44, 11, -47, 31, -7, 35, -42, -25, 41, 12, -64, 34, 14, -2, -21, 24, -14, 11, -3, -24, 22, -28, 46, -51, 38, -22, 35, -40, 2, 11, 22, -48, 23, -9, 34, -35, -24, 52, -7, -37, 9, 36, -21, 0, -32, 61, -44, 6, -1, -16, 41, -28, 19, -37, 49, -11, -38, -8, 65, -53, 9, -21, 59, -37, 8, -33, 59, -13, -80, 67, 19, -39, -28, 70, -21, -25, -3, 23, 17, -29, -44, 83, -41, 0, -23, 53, -27, -12, 21, -19, 21, -21, 13, -4, -12, -5, 38, -58, 34, 10, -22, -16, 47, -8, -39, 19, 12, 4, -46, 39, -24, 48, -69, 45, -18, 10, -5, -2, -4, 10, -5, 7, -17, -3, 20, 0, -40, 26, 40, -64, 11, 34, 1, -49, 11, 35, -22, -14, -32, 98, -47, -37, 9, 76, -70, -8, 7, 63, -92, 56, -49, 77, -64, 2, 41, -28, -25, 37, 0, -26, 35, -40, 16, 3, 14, -46, 22, 18, -6, -9, -11, 22, 26, -44, -46, 94, -60, 18, -37, 69, -33, 5, -20, 42, -32, -20, 24, -1, -10, -12, 39, -31, 13, 1, 9, -47, 42, -26, 39, -73, 48, 48, -73, -13, 56, 14, -78, 38, 11, 12, -50, 8, 39, 3, -79, 73, 2, -25, -17, 23, 27, -58, 26, -37, 67, -49, 11, -12, 62, -82, 64, -41, 3, 26, -17, -45, 55, -4, -22, 10, -2, 38, -54, 8, 5, 47, -79, 7, 54, -7, -64, 41, 49, -73, 29, -24, 54, -51, -4, 14, 33, -84, 82, -46, 17, -25, 57, -44, -2, 11, 8, 15, -66, 46, 19, -25, -44, 58, 10, -38, -23, 77, -48, -3, -12, 24, 24, -70, 37, 21, -15, -48, 81, -66, 44, -29, 6, 4, 9, -30, 31, -24, 5, 19, -51, 34, 21, 11, -92, 78, 19, -44, -54, 104, -47, -8, -19, 29, 45, -78, 6, 55, -11, -75, 66, -10, 8, -38, 24, 10, 4, -57, 66, -20, -25, 20, 6, 9, -71, 100, -60, -6, 8, 28, -37, 29, -42, 78, -58, -22, 42, 10, -69, 34, 33, -36, 29, -54, 81, -54, 0, 7, 1, -19, 22, -14, 4, -3, 32, -13, -59, 86, -54, 4, 0, 21, -35, 43, -68, 91, -31, -53, 38, 48, -72, -15, 50, 3, -11, -72, 96, -1, -49, -23, 81, -21, -57, 15, 63, -67, 5, 25, -27, 34, -48, 49, -26, 12, -33, 66, -73, 14, 35, -20, -27, 45, -24, 12, -12, 0, 24, -50, 33, -26, 45, -65, 47, -7, -4, -9, 19, -19, -2, 15, -17, 30, -39, 25, 2, -3, -57, 109, -86, 10, 14, 31, -53, 7, 32, 5, -44, -20, 84, -35, -34, -6, 99, -97, 1, 23, 40, -65, 15, 9, 36, -45, -22, 55, 4, -55, -3, 73, -80, 63, -49, 28, 2, -10, -19, 24, -13, 8, 1, -15, 5, 22, -4, -57, 72, -41, 16, -45, 76, -57, 30, -26, 38, -16, -34, 32, 12, -53, 22, 47, -46, -4, 6, 45, -65, 32, -21, 45, -44, -22, 69, -44, -16, 29, 19, -59, 40, -7, 42, -77, 39, -4, 29, -74, 27, 38, -12, -60, 69, 7, -32, 1, -9, 50, -56, -15, 19, 47, -75, 44, 5, -22, 27, -7, -22, 0, 23, -30, 1, 4, 33, -44, 29, -24, 57, -67, 17, 18, 4, -59, 32, 48, -72, 28, -2, 13, -10, -21, 16, 58, -117, 85, -14, -5, -34, 21, 29, -27, -20, 31, 23, -49, 16, -14, 51, -74, 24, 38, -38, -16, 56, -33, -7, 3, 0, 36, -80, 49, 23, -19, -48, 76, -61, 43, -41, 27, -11, 23, -30, 8, 3, 15, -14, -22, 16, 3, 15, -39, 11, 38, -13, -70, 88, -41, 2, 4, -30, 80, -84, 15, 37, -6, -61, 58, -19, 27, -72, 64, -6, -16, -30, 59, -21, -21, -12, 44, 22, -101, 78, -10, -16, -11, 20, -21, 31, -36, 37, -18, -20, 46, -24, -23, 10, 21, -36, 32, -38, 68, -50, 12, -6, 19, -33, 14, -16, 20, -11, -14, 47, -59, 56, -14, -27, 5, 29, -43, 49, -96, 106, -35, -41, 28, 35, -30, -29, 37, 12, -11, -58, 79, -31, -16, -11, 43, -13, -25, 3, 71, -76, -13, 64, -39, 3, -45, 66, -13, -1, -45, 80, -40, 6, -29, 26, -12, 6, -19, 21, -4, 9, 0, -37, 44, -28, 11, -22, 19, 7, 1, -45, 60, -13, -42, 32, -16, 31, -50, 35, 10, -22, -23, 60, -62, 21, -2, 39, -49, -4, 24, 30, -53, -23, 66, -33, 2, -34, 69, -33, -10, 7, 24, -51, 28, 0, 9, -24, -3, 38, -24, -16, -9, 68, -81, 38, -16, 35, -34, -4, 16, 20, -43, 10, 7, -3, 14, -30, 38, -39, 38, -20, -12, -20, 78, -79, 22, -4, 44, -48, -6, 37, -2, -25, -24, 60, -41, 15, -30, 50, -43, 7, 9, 27, -64, 45, 5, -15, -17, 1, 49, -56, 3, -11, 69, -78, 37, -5, 38, -60, 26, -2, 9, -51, 53, -20, -3, 9, -1, 38, -74, 40, 6, -13, -54, 69, -24, 6, -22, 31, 0, -17, 12, -13, 8, -9, 20, -53, 56, -27, 29, -63, 41, 8, 11, -73, 59, 15, -25, -21, -1, 61, -69, 10, 17, 28, -59, 34, -14, 32, -54, 17, 22, -11, -47, 63, 7, -56, 46, -28, 50, -96, 60, 2, 0, -37, 36, -11, 15, -38, 41, -19, -31, 46, -12, -25, 9, 49, -67, 47, -48, 51, -30, -15, 23, 19, -43, 8, 17, 4, -11, -29, 54, -48, 38, -28, 10, -9, 38, -48, 27, -47, 55, 3, -59, 22, 41, -5, -59, 38, 5, 31, -101, 72, 11, -36, -18, 54, -25, -1, -30, 54, -28, -34, 61, -27, 13, -46, 55, -21, -10, -21, 52, -34, -8, 30, -21, 20, -11, -21, 22, -2, -46, 79, -84, 60, -9, 13, -57, 51, 2, -16, -38, 34, 15, -23, -7, -6, 53, -38, -22, 29, 23, -63, 65, -34, -21, 34, -7, -19, -8, 24, 13, -8, -63, 110, -56, -8, -37, 79, -56, -3, -3, 62, -57, 19, 9, 8, -20, -29, 27, 13, -28, -19, 79, -80, 58, -31, 24, -16, -35, 46, 0, -52, 36, 21, -29, 16, -23, 26, -29, 38, -42, 26, -41, 60, -29, -16, -4, 42, 7, -85, 53, 47, -54, -29, 67, -53, 39, -58, 45, -5, 5, -37, 61, -56, 27, 17, -40, 1, 15, 17, -43, 19, 4, 30, -49, 12, -1, 49, -64, -27, 96, -41, -47, 45, 8, -38, 35, -50, 74, -81, 54, -14, 24, -64, 57, -5, -25, -19, 27, 16, -27, 4, 16, 2, -25, 26, -31, 22, -35, 56, -54, 0, 55, -23, -29, 9, 38, -38, 12, -41, 74, -28, -29, -3, 61, -71, 36, -32, 43, -19, -14, 21, 0, -10, -19, 32, -42, 20, 11, 23, -94, 107, -13, -53, 5, 35, -17, -11, -25, 32, 40, -76, 29, 32, -9, -65, 80, -42, 6, -22, 42, -27, -2, 10, -2, 13, -41, 32, 10, -17, -26, 53, -50, 40, -42, 30, -19, 41, -50, 33, -20, -1, 40, -67, 8, 29, 15, -58, 25, 32, 15, -81, 46, 14, -8, -51, 24, 40, -44, 17, 10, 2, -26, 47, -68, 49, -49, 50, -27, -3, -20, 84, -62, -32, 52, 12, -52, 0, 42, -30, 24, -47, 45, -16, 11, -51, 74, -47, -9, 45, -19, -18, -5, 41, -39, 11, -33, 56, -20, -14, -8, 64, -85, 60, -23, -13, -3, 33, -20, -25, 57, -34, 2, -23, 42, -21, 3, -49, 85, -35, -27, 1, 54, -34, -31, 24, 15, 6, -45, 54, -30, 12, -27, 40, -61, 39, 1, -5, -18, 17, 14, 7, -33, -27, 83, -44, -40, 21, 66, -82, 32, -7, 33, -54, 27, 3, 2, -13, -15, 52, -57, 14, 14, -6, -27, 54, -45, 23, -11, 16, -27, 27, -33, -3, 36, -46, 47, -15, -8, -7, 67, -93, 12, 34, 17, -73, 32, 15, 29, -44, -17, 47, 2, -40, -31, 81, -43, 3, -24, 52, -32, 4, 1, 20, -48, 20, 40, -68, 23, 14, 19, -64, 46, -8, 17, -48, 55, -29, 23, -59, 48, -2, -27, 11, 1, 21, -30, 25, -24, 29, -41, 21, 0, -15, -17, 64, -47, 1, 31, -22, 2, -11, 22, -56, 69, -53, 32, -30, 31, -16, 32, -68, 29, 42, -39, -49, 80, 17, -74, 17, 0, 55, -88, 25, 29, 14, -72, 56, 0, 0, -33, 20, 5, -34, 35, -33, 45, -37, 23, -9, 10, -54, 67, -22, -13, -15, 41, -14, -16, 8, 0, 19, -51, 56, -51, 39, -20, 19, -34, 26, -18, 19, -31, 23, 0, 12, -31, 7, 45, -65, 22, 4, 24, -73, 74, -13, -34, 18, 23, -16, -25, -2, 40, 5, -84, 76, -4, 6, -74, 75, -7, -10, -51, 60, -13, 0, -45, 50, 18, -57, 20, 21, -7, -26, 47, -51, 28, -19, 12, -13, 3, -1, 20, -23, 1, 28, -18, 3, -41, 67, -72, 34, -11, 33, -47, 47, -9, -20, -2, 28, -21, -27, 11, 26, -15, -25, 57, -44, 46, -67, 49, -5, -30, 1, 42, -36, -9, 22, 7, -13, -34, 67, -29, -16, -26, 84, -49, -21, -11, 77, -53, -43, 62, 0, -3, -32, 23, 13, -5, -69, 88, -42, 7, -17, 37, -35, 27, -6, -13, -11, 31, -17, -28, 45, -17, 8, -32, 41, -48, 39, -35, 41, -16, -28, 41, -3, -13, -26, 23, 12, -22, -50, 104, -57, 9, -28, 67, -53, -7, 0, 45, -41, -22, 50, -8, -21, -9, 38, -19, -18, -2, 55, -76, 38, -12, 39, -49, -14, 64, -24, -45, 25, 50, -66, 23, -15, 32, -36, 32, -46, 44, -14, 2, -16, 22, -7, -11, 14, -28, 21, 4, -10, -18, 63, -66, 30, -20, 36, -35, -16, 26, 12, -37, 6, 50, -35, -15, 6, 48, -64, 4, 12, 46, -85, 33, 12, 25, -49, -11, 77, -53, -18, 19, 29, -41, -1, 3, 39, -70, 55, -6, -1, -23, 38, -22, -12, 1, -11, 36, -39, 5, 15, 33, -55, 32, -8, 6, -37, 39, -32, 4, 27, -23, 11, -1, 10, -28, 19, -24, 52, -69, 27, 21, 11, -72, 52, 17, -35, -13, 16, 33, -44, 4, 19, 18, -60, 13, 35, 12, -93, 82, 9, -35, -20, 26, 40, -74, 14, 18, 28, -66, 37, 4, 9, -43, 34, -15, 17, -35, 38, -11, -14, 14, -5, 2, -36, 54, -35, 2, 1, 29, -35, 9, -4, 24, -32, -5, 31, -19, -17, 28, 34, -86, 49, 13, -16, -52, 71, -29, 3, -30, 51, -1, -36, 6, 25, 4, -75, 56, 10, -21, -18, 37, -16, 17, -53, 60, -7, -38, -9, 63, -18, -70, 67, 1, -19, -32, 50, -20, 11, -23, 24, -10, -3, -21, 32, -26, 7, 12, -19, 35, -29, 26, -41, 32, -22, 14, -43, 41, 7, -16, -24, 57, -20, -35, 25, 7, -11, -20, 31, -18, 10, -34, 44, -7, -22, -9, 49, -33, -18, 26, -4, 12, -63, 51, 11, -16, -40, 80, -28, -37, 5, 61, -78, 22, 16, -3, -10, -5, 26, -8, -2, -43, 68, -42, -24, 39, 11, -31, 15, -9, 18, -20, -1, 7, -17, 26, -30, 31, -31, 42, -28, -1, -15, 49, -51, -2, 26, 3, -12, -11, 7, 22, -9, -51, 70, -27, -14, -13, 53, -37, -12, 9, 44, -57, -14, 51, -6, -27, -10, 60, -55, 2, 14, 18, -45, 32, -19, 29, -27, -12, 31, 14, -54, 17, 41, -62, 51, -40, 40, -40, 12, -8, 28, -39, 16, 10, 10, -46, 37, 12, -42, 17, -4, 2, -17, 35, -34, 38, -30, 21, -6, -36, 36, 13, -56, 14, 53, -36, -13, -1, 61, -64, 7, -3, 54, -63, 5, 14, 34, -67, 10, 46, -27, -18, 26, 20, -41, 14, -13, 40, -66, 20, 38, -34, -11, 39, -16, 11, -26, 7, 28, -58, 26, 0, 30, -61, 44, 11, -30, -17, 66, -40, -33, 35, 6, -21, -2, 9, 16, -13, -39, 79, -71, 27, 9, -9, -29, 28, 4, -17, 1, 14, 2, -20, -2, 16, 24, -67, 20, 37, -4, -80, 75, 18, -46, 2, 10, 25, -31, -28, 43, 19, -75, 59, -13, 14, -40, 29, 7, -22, -20, 44, -20, -16, 10, 32, -21, -42, 61, -19, -29, 12, 39, -55, 32, -4, 0, -2, -24, 40, -19, -38, 34, 22, -33, 11, -3, 31, -49, 21, -16, 40, -54, 12, 29, -19, -8, 17, 17, -52, 28, 22, -39, -2, 45, -42, 23, -46, 51, 11, -68, 26, 55, -34, -44, 45, 9, -19, -43, 57, -16, -5, -9, 40, -24, -12, 8, 29, -54, -4, 50, -37, 0, 11, 7, -4, 0, -25, 57, -62, 19, 18, -7, -22, 12, 19, -27, 9, -5, 15, -19, 2, 15, 4, -45, 36, -5, 8, -48, 60, -13, -35, 36, -19, 21, -24, -7, 23, -24, -22, 73, -58, -5, 34, 25, -71, 19, 30, 0, -43, -4, 50, -9, -21, -21, 69, -28, -46, 24, 29, -45, 12, 3, 21, -13, -28, 47, -9, -37, 21, 22, -46, 21, 8, -1, -32, 42, -22, 14, -27, 19, 16, -29, 3, 17, -1, -39, 28, 21, -42, 8, 47, -45, 2, -16, 50, -20, -54, 50, 9, -25, -12, 41, -29, 8, -3, -5, -13, 25, -16, 19, -30, 15, 15, -2, -52, 38, 38, -69, 12, 37, 9, -54, 10, 36, 5, -79, 27, 57, -35, -40, 48, 21, -41, 13, -3, 10, -29, 4, 18, 4, -50, 52, 1, -28, -6, 41, -25, -22, 34, -22, 10, -5, 3, -6, -1, 2, 26, -48, 24, 12, 5, -54, 36, 18, -32, -6, -3, 48, -28, -21, 22, 35, -63, 6, 43, -28, -27, 42, -7, -22, 6, 21, 8, -56, 31, 23, -10, -73, 76, 18, -49, -26, 70, -21, -23, -8, 35, 0, -42, 7, 42, -26, -28, 47, -31, 0, 13, 11, -25, 14, -6, 10, -13, -26, 40, -14, -5, -8, 42, -36, 1, 15, -10, -34, 47, -24, 5, -22, 38, 14, -39, -10, 53, -26, -67, 72, 0, -15, -25, 29, 19, -29, -25, 50, -14, -31, 10, 42, -44, -24, 81, -40, -32, 12, 45, -41, -5, -1, 47, -27, -54, 54, 32, -64, 4, 26, 1, -1, -41, 44, 4, -22, -22, 47, -30, 7, 5, 3, -37, 45, 1, -53, 44, -1, -20, 7, 12, -13, 9, -23, 26, -2, -47, 32, 37, -61, 6, 42, 0, -25, -43, 76, -23, -38, -10, 73, -24, -57, 47, 45, -70, 3, 19, 7, -19, -8, 10, 24, -12, -36, 66, -60, -1, 50, -32, -19, 8, 26, 2, -44, 11, 53, -42, -26, 20, 42, -52, 14, 16, -26, -11, 42, -41, 16, 16, -23, 13, 1, -6, 17, -18, -41, 71, -39, -23, 40, 13, -30, 2, 19, 0, -39, 10, 24, -15, -25, 12, 66, -81, 6, 47, 9, -69, 12, 47, -9, -36, -27, 76, 9, -107, 58, 53, -68, 19, -10, 39, -49, 8, 14, -11, -17, 21, 18, -25, -17, 47, -4, -48, 32, -9, -4, -3, 8, -5, 29, -40, 13, 14, -31, 24, 7, -48, 27, 37, -61, 22, 15, 7, -46, 17, 10, 22, -45, -9, 56, 1, -73, 43, 34, -51, -15, 40, 2, -47, 35, 8, 27, -87, 31, 86, -94, -27, 67, 10, -44, -15, 43, 11, -46, 6, 9, 33, -71, 35, 26, -30, -18, 37, -18, -9, 20, -15, 1, 5, 9, -2, -23, -11, 50, -42, -3, 24, 6, -21, 17, -5, -8, 11, -26, 24, -19, -9, 33, 22, -78, 38, 44, -48, -53, 80, 6, -66, 14, 36, 8, -37, -15, 66, -24, -75, 87, -14, -27, -10, 45, -12, -38, 13, 33, 7, -67, 20, 75, -55, -67, 85, 8, -52, -11, 45, -10, 13, -34, 12, 26, -36, 7, -1, -1, -7, 23, -27, 18, 15, -12, -28, 27, -6, 9, -52, 40, 26, -50, 3, 51, -10, -71, 67, 10, -59, 4, 56, -27, -20, -19, 58, 6, -81, 38, 49, -39, -39, 47, 14, -25, -40, 54, -2, -20, -38, 82, -25, -51, 44, 24, -60, 8, 51, -47, -2, 6, 22, 9, -34, -20, 78, -56, -25, 36, 19, -49, 17, 32, -50, 44, -29, 4, -11, 14, 3, -13, -11, 19, 13, -24, 28, -32, 33, -37, 39, -61, 119, -76, 120, -70, 99, -122, 89, -113, 91, -123, 122, -123, 77, 86, -116, 6, -118, 123, -23, 64, -93, 17, 24, -125, 124, -125, 124, -24, -12, 56, 87, -54, 38, -91, 64, -2, -41, 126, -127, 20, 8, -48, -62, 127, -128, 88, -43, -18, 86, -100, 44, -32, -26, 71, -13, 6, 51, -33, -50, 106, -59, 33, 5, -20, 69, -56, 54, -48, -6, 38, -5, -38, 35, -1, 12, -1, 4, 23, -56, 19, -7, 5, -4, 31, -38, 3, -12, -9, -25, -7, 24, -32, 17, -21, -22, 24, -20, 6, -18, 0, -15, 5, -16, 15, 3, 2, -10, 3, 27, -31, 37, -12, 32, -5, 2, -21, 27, -14, 20, -8, 5, 15, -7, -11, 20, -37, 7, -23, 17, -22, 11, -14, 8, -44, 39, -52, 26, 3, 14, -10, 51, -45, 29, -19, 19, -3, 41, -21, 46, -23, 10, 16, -25, 3, 7, -30, 19, -9, -5, -1, 1, -19, 1, -24, -23, 51, -48, -10, 17, -34, -38, 60, -71, 26, -43, 65, -59, 70, -26, 61, -51, 63, -51, 42, -25, 58, -36, 31, 10, -14, -9, 8, -18, 8, 4, 8, 7, 31, -52, 39, -53, 53, -56, 24, 11, 1, -20, -8, -32, -18, -10, -25, 4, 1, 37, -37, 42, -42, 53, -57, 52, -18, 30, 11, 20, -52, 55, -61, 56, -50, 24, -26, 38, -42, 36, -1, -43, 58, -46, 6, 18, -35, 31, -36, 28, -55, 55, -98, 52, -41, 26, -24, 48, -31, 48, -26, 30, 19, -17, 23, -8, 13, 15, 19, -7, -23, 41, -36, 20, -39, 65, -64, 66, -38, -9, 7, -14, -10, -3, 6, 15, -19, -40, 53, -67, -11, -12, -25, 23, -11, -12, 46, -48, 39, -20, 20, -14, 31, -54, 71, -25, 2, -8, -5, -9, 1, 7, 27, 17, -14, 43, -31, 27, 11, -33, 20, -2, -33, 45, -38, 17, -9, -11, -17, -22, -19, 20, -25, 4, 29, -35, 14, -17, 1, -7, 19, 2, 16, 32, -3, -17, 4, 0, -9, 17, 5, -8, 52, -32, 40, -39, -5, -18, 14, -21, 31, 10, -17, 8, -34, -7, 1, -44, 7, 10, -8, -6, -18, -25, -1, -19, 16, -29, 62, 6, 9, 21, 0, -14, 4, 5, 20, 13, 27, -1, 18, -5, 21, -31, 11, 2, -9, -4, 21, -27, 8, -21, -28, -19, 14, -12, 5, -20, 20, -36, 4, -18, -27, -4, -4, 15, 4, 48, -7, -11, 20, -6, 7, 20, 1, 20, 0, 35, -35, 28, -37, 7, -43, 21, -22, 23, -18, 12, -22, -13, -20, -11, 7, 23, -10, 19, -18, 17, -41, 4, -16, -8, 21, 11, -4, 10, 30, -24, 32, -15, 15, -13, 28, -5, 38, -10, 0, -22, -13, -12, 24, -18, 30, -7, 4, -16, 27, -28, -3, -1, 18, -14, 31, -24, -3, -13, -19, -36, -2, -31, 9, -2, -12, 17, 12, -50, 46, -49, 43, -15, 13, 22, 15, -25, 10, -8, -6, 14, -2, 24, 15, 9, 17, -13, 5, 14, -15, 7, 20, 4, 4, 18, -16, 3, -47, 31, -46, 19, -24, 5, -19, -1, -42, 14, -44, 18, -7, -1, 15, 9, -35, 32, -44, 39, -46, 23, -16, 36, -25, 45, -34, 32, -8, 10, 5, 28, 0, 12, 11, 3, 20, -23, 6, -8, 16, 7, 17, -19, 32, -44, 3, -8, -21, -8, -5, 2, -29, 2, -3, -19, -14, 3, 7, -23, 10, 1, 3, 8, 13, -44, 20, 21, -16, 23, 3, 5, 10, -11, 32, -11, 13, -7, 30, 4, 16, -7, -6, -7, 14, -40, 4, -16, -26, 3, -1, 0, -6, 5, -50, 37, -27, 18, -16, -14, 6, -1, -4, -15, 8, -12, 14, 9, -22, 42, -10, 23, -11, 36, -15, 13, 30, 1, 47, -20, 33, -14, -12, 1, -20, -9, -9, -11, -13, 7, -37, 25, -47, 14, -13, 4, -12, 9, -32, 18, -48, -1, -35, -1, -7, 35, -20, 53, -4, 34, -7, 13, 19, 9, 30, 6, 45, -22, 23, -18, -6, -1, 3, -30, 14, -15, 9, -39, 10, -33, -13, -24, 10, 14, 14, -10, 2, -34, -4, -20, -21, -14, 40, -10, 17, -14, 28, -17, 37, -26, 69, -15, 38, 2, 21, -25, 37, -61, 13, -9, 5, -17, 18, -41, 22, -57, -1, -9, -13, 24, -10, 38, -5, 8, -16, -2, 1, 12, -25, -2, -13, 2, 2, -16, -19, 32, -30, 22, 20, -4, 12, 11, -17, 19, -17, -3, 20, -33, 65, -27, 32, -14, 8, -8, 13, -19, 9, -2, 7, 33, -40, 18, -18, -18, 6, -23, -11, -11, -28, 4, -11, -15, -14, -8, -5, 34, -6, 19, 1, -3, 9, -1, 5, 5, 14, -11, 40, -3, 18, -20, 16, -7, 2, -5, 9, -16, 9, -17, 0, -17, 4, -17, -3, 3, 8, -14, -19, 12, -21, -7, 1, -2, -8, 16, 3, -6, 35, -23, 33, -13, 11, 12, 3, -7, 26, -11, 19, -18, 23, -22, 39, -49, 39, -50, 11, -38, 26, -29, 10, -6, -22, 15, -8, 15, -37, 36, -43, 39, -43, 18, -26, 1, 11, 4, -2, 9, 7, 2, 7, 19, 1, 1, -4, 16, -5, 16, -9, -3, 4, -4, -1, -17, 0, 11, 16, -27, 12, -15, 15, -3, 0, 10, -3, -5, 12, -13, -7, -13, -31, -1, -3, -17, 15, -31, 25, -10, 15, -1, 2, 4, 10, 7, 32, -13, 7, -22, 2, -10, 16, 1, -15, 19, -24, 16, -18, -12, 18, -9, 9, 24, -8, 8, 11, 0, -31, 17, -55, 21, -43, 40, -40, 29, -54, 44, -34, 22, 11, 16, 7, 19, 21, -6, 2, -7, -16, 22, 0, -1, -4, 5, -8, 26, -42, 4, -6, -21, 35, -16, 8, 0, -22, -13, 11, -31, 7, -28, 4, 17, -12, -18, -2, -23, 23, -1, 19, 34, 7, 7, 35, -19, 11, -8, -17, 8, 4, 16, -16, -13, 9, -15, -5, -1, -6, 7, 3, 11, 1, -7, -24, 21, -31, 36, -3, -10, 8, 2, -17, 12, -24, 6, -3, 9, 15, 3, 13, -8, -13, -3, 6, -19, 14, -33, 16, -17, -5, -31, 3, -29, 24, -7, -6, 35, -20, -5, 34, -20, 25, -3, 10, 25, 8, 14, -13, 0, 1, 17, -33, 51, -38, 45, -32, 39, -3, -2, -24, 3, -18, 14, -4, -44, 2, -25, -15, -2, -23, 3, -2, -2, 20, -14, 8, -10, -4, 21, 11, -13, 32, -4, 8, 19, -16, -2, -2, -2, 14, -2, -1, 27, -26, 20, 11, -13, 10, -3, -7, 12, -13, -3, -30, -16, 10, -26, -3, -10, -2, -9, 15, -17, 1, -2, -7, 14, -8, 12, -3, -1, 2, 47, -26, 22, -19, 16, 2, 13, -3, 21, -10, 22, -32, 43, -24, 16, 0, 5, -2, 12, -44, -12, 1, -26, 1, -36, 5, 2, 9, -17, 20, -37, 14, -9, -5, 6, -3, -13, 23, -19, 25, -33, 6, 17, 10, 19, 15, -4, 12, 5, -9, 33, -20, 26, -9, 11, -2, 11, -21, -7, -13, -4, -8, -12, 0, -10, -9, 8, -33, 9, -26, 8, 6, -8, 12, 7, -8, 0, 7, -16, 25, -8, 27, 12, 0, 9, -9, 4, -17, 14, -16, 11, -8, 18, -2, 4, 2, -20, -18, 22, -16, -5, 3, -24, 13, -10, -12, -10, 2, -16, 33, -15, 21, -15, -4, -19, 29, -22, 18, 2, 20, 12, 18, -22, -7, -16, 7, -19, 14, 1, -17, 33, -22, 38, -8, 3, -3, 21, -17, 51, -43, 15, -22, -23, -6, -12, -14, 14, 9, 6, 4, -31, 3, -16, -14, 22, -22, 5, 13, -25, 17, -2, -18, 7, 1, 5, 36, -16, 23, 4, -15, 29, -20, 10, 1, 24, 17, 16, -4, -16, -37, -11, 1, -33, 27, -36, 17, -22, 2, -33, 16, -29, 32, -7, 24, -12, 14, -12, 22, -16, 15, -20, 19, 9, 14, 12, -1, -24, 13, -6, -1, 32, -19, 24, 12, -26, 4, -31, -38, 18, -16, -13, 3, -14, -1, 11, -15, 15, 0, -2, 30, -6, 35, -23, 10, -35, 5, -14, 17, -21, 20, 4, 7, 8, -5, -15, 20, -25, 26, 6, -3, 3, 5, -24, 26, -35, 4, 0, -6, 13, -23, 8, -25, 1, -2, 9, 3, 17, 4, 0, 13, -15, 3, -21, -16, 4, -5, -10, 11, -2, 7, 23, -22, 25, -19, 18, 25, -9, 14, -21, -7, 11, -24, 22, -12, -7, 6, 9, -33, 11, -20, 2, -9, 2, 3, -13, 12, -15, 23, -21, 16, -16, -2, 8, 13, -12, 18, -10, 16, -12, 20, -18, 18, -1, 21, -21, 20, -30, -6, 10, -2, 13, -6, -15, 6, 2, -1, 1, -19, 9, -15, -3, -11, 0, -5, 1, 5, 1, -4, -8, 1, -16, 23, 0, -23, 2, 8, -6, 38, -4, 2, 13, -17, 31, -4, -8, 22, -14, 0, 12, -22, 7, -7, 11, 4, -4, -12, -9, -22, 2, -17, -17, -11, 7, -17, 19, -24, 9, -8, -6, 29, -4, 10, 4, 4, 23, -1, 9, -6, -12, 23, 16, -6, 33, -29, 12, -7, -10, 17, -4, -18, 21, 0, -14, -2, -20, -21, 10, -28, 5, -18, -4, 0, -11, 1, 5, -17, 3, 9, 20, 6, 1, -7, 2, -7, 3, 9, -22, 29, 6, -1, 25, -10, 6, -1, 4, 12, 18, -13, 28, -11, 6, -15, -14, -22, -7, 5, -14, 1, -16, -12, -5, 5, -9, 4, -1, -14, 21, -10, -5, 0, -17, -7, 2, -10, 6, 11, 1, 37, -17, 6, 21, -24, 41, 2, 23, 0, 10, -18, 16, -26, 14, -21, -19, 18, -9, -14, -1, -9, -14, -3, -7, -10, 7, -7, 19, -11, 15, -25, -3, -6, 2, 8, -10, 4, 12, -3, 11, -2, -2, 5, 31, -9, 39, -21, 14, -23, 18, -16, -1, -3, -6, 0, 22, -9, -5, -17, -4, -12, 2, -3, -7, 10, -10, 7, -20, -19, -10, 0, -14, 32, -15, -18, 13, -9, 2, 17, -14, 6, 36, -9, 28, 1, 0, 17, -10, 5, 17, -8, 12, -2, 3, 2, -22, -6, -14, 6, 8, -11, -14, 2, -23, 25, -35, 3, -18, 1, -14, 22, -1, -12, -7, -9, 13, -4, 12, 4, -3, 18, 0, 1, 8, -14, 14, -2, 1, 17, -3, -14, 35, -17, 19, -14, -6, 1, -9, 18, -17, -4, -13, -2, -14, 10, -10, -6, 0, 3, 5, -12, -13, -3, -6, -6, 11, -13, -7, 13, -2, 6, 13, -7, 11, -5, 23, 1, 29, -17, 23, -10, 18, -16, 12, -20, 10, 7, -9, -5, -21, -9, 5, -13, -2, 0, -15, -11, 3, 0, -18, 5, -25, -2, 3, -2, -3, 4, 8, 14, -7, 15, 4, 8, 19, 9, 11, 7, -3, 14, -11, 1, 15, -35, 3, 3, -10, -16, 0, -15, 2, 3, -12, 27, -23, 32, -15, 10, -14, 3, -27, 10, -15, 12, -24, 7, 2, 9, -2, -2, -1, 3, 1, 1, 8, -4, 0, 6, -6, 1, 1, -1, 8, -11, 31, -27, 13, 4, -3, 5, -1, 0, 2, 9, 0, 12, -31, 4, -27, 1, -25, 20, -21, -14, 12, -14, 0, -5, -23, 18, -1, 15, 19, -5, 20, -8, 14, -7, 16, 3, 0, 8, 10, 0, -8, -10, 3, -8, 9, -12, 4, 15, -6, 2, -12, -29, -3, -16, -11, 35, -18, -1, -28, 7, -12, 0, 7, -5, 22, 10, 10, -4, 6, -13, 21, -23, 20, 8, -13, 11, 15, -6, -6, -22, -1, 3, 14, 7, 11, -27, 12, -17, -12, 8, -15, 3, -8, 12, -12, 5, -30, 12, -18, 9, -2, 3, 4, 15, 1, 5, -9, 0, -8, 24, -2, 21, 5, -4, -4, 14, -15, 0, -1, 3, 17, -5, 13, -19, -10, -4, -6, -4, -7, 18, -27, 8, 1, -12, -21, -13, 1, -9, 11, 1, -3, -1, 22, -21, 9, 6, -3, 20, -2, 17, 7, -12, 1, 4, 4, -9, 9, -20, 24, 7, -9, -3, -7, -6, 10, 7, 3, 9, -2, -3, -4, 1, -19, -8, -16, 0, -12, 0, -25, 4, -22, 10, -9, 0, -3, 15, -1, 8, 11, -15, 10, 13, 1, 22, -5, 15, 1, 24, 6, 0, -6, 5, 5, 10, 8, -1, -11, -14, 3, -31, 2, -22, -4, -8, -15, -2, -31, -12, 6, -7, 5, 2, 3, -4, 19, 3, 4, 7, 7, -8, 31, -6, 26, 1, -2, 2, -3, -10, -4, -4, 9, 3, 12, -16, 16, -9, -1, 5, 4, -7, 13, -17, 0, -11, -13, -22, 1, -9, 4, -7, 7, -10, 5, -1, -6, -3, -21, 7, -10, 18, -3, 1, -7, -11, 11, -8, 12, 20, 3, 13, 16, -1, 3, 13, -3, 23, 16, -3, 15, -14, 12, -6, -8, -28, 0, -33, 4, -11, -12, -13, -21, -17, -16, -5, -12, 16, -7, 15, -6, -5, 3, -9, 21, 17, 13, 14, 11, 21, -12, 31, -18, 7, 12, 8, 9, 7, 1, -3, -7, -14, 17, -35, -10, -2, -18, -8, -10, -20, -22, 2, -10, -3, 1, -1, 4, -5, 11, -20, 11, -6, 27, 7, 18, 8, -1, 2, 3, 11, -9, 5, 5, -7, 29, -6, 20, -21, 23, -15, 19, -19, 2, -22, 11, -26, -7, -10, -30, -1, -3, -6, 15, -22, 16, -7, -9, -2, -7, -5, 11, 17, -13, 2, 8, -5, 6, 27, -6, 12, -6, 4, 15, 3, 14, -3, -12, 11, -2, 6, 5, 4, -6, -12, 0, -32, 2, -22, 22, -12, -5, -7, -11, -7, 6, -1, -3, -3, -16, 2, -1, 0, 0, -7, -2, 1, 12, -4, 5, 20, 1, 16, -2, 14, -1, 19, 8, 29, -8, 7, -14, -2, 3, -13, 8, -40, 22, -18, 2, -14, -8, -11, -8, 12, -21, -1, -10, -12, -6, -4, -14, 6, -19, 7, 14, 1, 11, 11, -11, 25, 1, 14, -5, 31, 0, 22, 4, 1, 3, 6, -3, 4, -2, -20, -7, -26, 1, -12, -7, -10, 2, -1, -5, -7, -8, -10, 6, -7, -6, 10, -17, 6, 3, 15, -8, 15, -7, 12, 1, 9, -4, -2, 10, 9, -1, 10, -4, 9, -8, 17, 0, -13, -7, -2, -11, 3, -2, -15, -4, -11, -5, -9, 1, 8, -10, 8, -8, -6, -18, 21, -19, 26, -19, -1, -11, 10, 4, 12, -10, 16, -10, 17, 8, 13, -1, 17, 1, 5, -1, 11, -8, 9, 16, -17, 3, -26, -17, -14, 6, -17, 4, -20, 0, -1, -6, -4, 2, -15, 13, -3, -1, 0, -2, -8, 11, 7, -3, -8, 5, 14, -1, 28, -19, 13, -4, 8, 1, 11, 7, 6, -8, -2, -13, -10, -22, 6, 11, -1, -1, -5, -13, 18, 3, -10, 9, -17, -8, 9, -9, 1, -17, -4, -16, 18, -6, 15, -10, 17, 5, 0, -5, 0, -11, 12, 15, 4, 8, 5, -4, 0, -2, 3, -17, -2, -1, 11, -6, -7, 2, -33, 23, -6, -1, -2, -2, -1, -8, 3, -29, -2, -34, 16, -3, 16, 1, 10, -12, 23, 0, -3, 16, 12, 19, 23, -1, 8, -26, 16, -32, 26, -13, 2, -11, 5, -1, -15, -9, -16, 7, -6, 14, -15, 5, -10, -7, -9, -9, 6, -17, 13, 18, -5, -3, -4, -4, -18, 28, -6, 13, 17, 24, -2, 9, -14, 1, -11, 7, 17, 1, -15, 10, -23, -4, -12, 5, -20, 17, -10, 6, 0, -9, 4, -8, -15, 6, -16, 7, 9, 3, 6, -12, -17, 0, 4, 13, 22, -4, 10, -8, 7, -12, 5, 5, 1, 11, 2, 10, -3, -2, 3, -10, -5, -7, -4, -18, 17, -2, -14, -16, -7, -10, -3, 6, -1, 14, -11, 15, -18, 2, -6, 0, -1, 0, 20, -17, 1, 6, 2, 6, 12, -3, 7, 25, -5, 17, -14, 0, -6, 0, -2, -5, -1, -10, 8, 2, -9, -19, -7, -17, 5, 3, -7, 4, -15, -5, 9, -12, -1, -5, 3, -5, 26, -2, 3, -4, 5, 3, 7, 10, 5, 6, 6, 26, -17, 0, -1, 3, -3, 10, -7, -7, -9, 11, -18, 0, -16, -6, -5, 3, 7, -14, -14, 0, -21, 14, -8, -1, -12, 2, 1, 2, -3, -1, -3, 18, 5, 5, 9, 12, 7, 18, 8, 5, -25, 16, -15, 16, -7, 9, -22, 1, 14, -13, -5, 2, -6, -8, 13, -17, 6, -16, 1, -5, -14, -6, -6, -15, -2, 9, -9, -18, 15, -19, 12, 7, 4, 8, 14, 15, 6, 10, -3, 9, -7, 23, -17, 21, -20, 7, 0, -9, 8, -10, 1, 4, 2, 3, -9, -9, -15, -6, -21, -16, -6, 0, -11, 19, -8, -9, 5, -6, 0, 5, 14, 7, 1, 12, 8, 7, -5, 12, 8, -4, 19, 4, -7, 2, 3, -12, -8, -1, 0, 5, 7, -5, -8, -22, -8, -21, -2, -9, 10, -20, 13, -6, 8, -17, -9, -6, 2, 5, 8, 6, -3, 10, -9, -2, 15, -6, 20, 7, 11, 10, -3, -4, -8, 25, -25, 18, -12, 17, -6, 20, -22, -1, -17, -10, 5, -10, 9, -13, -9, -6, 10, -25, -5, -2, -5, 13, 2, -5, -8, -10, 11, -27, 10, -4, 11, 0, 33, -4, 10, -14, 1, 12, -2, 27, -8, 6, 11, 9, -12, -4, -10, -13, 12, 5, 1, -10, -14, -15, -8, -7, -9, 3, -5, 10, 3, -11, -12, -13, -3, -3, 3, 2, 9, 17, -6, 25, -3, -3, -8, 19, 3, 30, -10, 12, -22, 7, -5, -10, -3, 21, -8, 12, 6, -5, -13, -13, -9, -9, -1, -23, 13, -17, 15, -22, -11, -18, 8, -14, 20, 1, 4, -5, 3, 3, 5, 11, 1, 2, 27, 1, 10, -7, -8, -2, -2, 7, -1, 17, -5, 24, -7, 5, -10, -20, -6, 5, -4, -5, -1, -18, -5, -14, -1, -20, 1, 7, -7, 12, -4, -2, -4, 2, 8, 0, 7, 1, 6, -2, 18, -5, -7, 4, 3, -2, 13, 4, 0, 2, -3, 2, -10, -6, 1, -6, 6, -7, -3, -21, -2, -12, 5, -1, -9, 7, -3, 13, 5, 5, -8, 0, -8, 19, -5, 13, 13, -7, 3, 0, -10, 0, -8, 20, -8, 13, -20, -5, -7, 3, 5, -7, 2, -5, -4, -14, 11, -23, -13, 2, -1, 12, 13, 5, -6, 23, -9, 9, -6, -9, 18, -13, 16, -3, -7, -17, 3, -13, 12, -9, 4, 0, 0, 13, -18, -1, 3, -13, 20, -5, 1, -20, 15, -23, 18, -4, -8, 5, -7, 16, 4, 6, -3, 7, -21, 19, -17, -7, 9, 5, 3, -5, -3, -16, -9, 25, -9, 12, -5, 10, -5, 9, -4, -6, -3, 4, 10, -2, 11, -12, -2, -14, 8, -23, -5, 0, -8, 9, -2, -11, -3, -9, 9, 2, 2, 4, -5, 7, 11, -16, 0, -6, 7, 6, 25, 5, 6, -4, 3, 4, 3, 2, -8, -3, 5, -1, -11, -4, -9, -3, -15, 10, -12, -5, 11, -4, -7, 6, -29, -5, 6, 11, 3, 9, -18, 13, -14, 19, -1, -2, 4, 5, 12, 1, 5, -8, 3, 1, 20, -6, 2, 3, -16, 10, -10, -18, -11, -7, -7, 9, -4, -8, 9, -15, 13, -13, -3, -7, 3, 8, 11, -6, -16, 1, -8, 20, 4, 15, -5, -3, 11, -5, 6, 0, -5, 10, 13, 0, -6, -11, 0, 11, -11, 10, -7, -8, 1, 16, -9, 2, -22, -9, 0, 4, 5, -12, -22, 2, -8, -8, 14, -16, 0, 13, 0, 9, -7, 2, -1, 7, 8, -3, -3, 2, 15, 5, 10, -7, 12, -4, 22, -4, -3, -12, -2, -15, 8, -2, -22, 7, -10, 5, 12, -20, -9, -11, -2, -12, 2, -9, 5, -3, 11, 7, -9, 4, -4, 24, -7, 21, -15, -3, 2, 14, -1, 5, 18, -12, 13, 3, 5, -10, -11, 0, -8, -2, -4, 2, -15, 9, -10, -16, -9, -7, 0, -1, 3, -8, -10, 5, -8, 4, -3, 8, -2, 20, 1, 6, -4, -9, 4, 14, 7, -1, 3, -5, 18, -7, 20, -6, -10, 8, 1, -2, 3, -4, -5, -3, -6, 0, -16, -7, 12, 0, -17, 4, -31, -7, 1, 1, -4, 8, -11, 6, -1, 11, -5, -7, -4, 2, 4, 15, -3, 21, -5, 20, 3, -12, 21, -1, 10, 5, 6, -20, -1, -18, 2, 3, -4, -5, -1, 6, -2, -11, -17, -15, -13, 0, 6, -18, 7, -18, 7, -7, 6, 7, -10, 18, 16, 2, -1, 3, -11, 6, 14, 1, 15, -2, 29, -8, 17, -14, 2, -19, 12, 8, -6, -1, -23, 6, -11, 7, -19, -18, 0, 1, -8, -8, -4, -20, 8, -8, 4, 10, -12, 13, 0, 18, -10, -3, -4, 6, 4, 17, 7, -2, 18, -9, 14, -10, -4, -11, 4, 3, 23, -17, -6, -2, -7, -7, 9, -10, 1, 2, -4, -14, -7, -6, -8, -4, 7, 2, -3, 3, 0, 13, -10, -4, -9, -6, 18, 11, -4, 16, -8, -4, 1, -1, 7, 3, 3, 3, 10, -15, -2, -9, 9, 0, 2, 2, -9, 12, -7, 0, -23, -7, -19, 2, -1, 0, 4, -15, 7, 3, -3, 0, 9, -12, 19, 4, 8, -13, -6, 5, -1, 14, 10, 9, 13, -3, 16, -18, 13, -18, 7, -10, 13, -6, -11, -3, 7, -23, -6, -11, -21, 9, -1, 4, -3, -16, 0, -12, 7, 14, -5, 15, 0, 6, -5, -3, -9, 9, 4, 10, 4, -2, -7, 10, -1, 10, -6, -14, 15, -4, 13, -4, -4, -14, 5, -2, 4, -9, 3, -14, 2, 3, -10, -1, -9, 0, 3, -6, 12, -16, 0, 4, 10, -25, 6, -5, 2, 8, 3, -2, -4, 15, 4, 7, 2, -1, -6, 10, 11, 2, -2, -14, 6, -3, 0, -3, -9, -10, 1, -1, -15, 9, -29, 9, -10, 7, -3, -3, -10, -2, 14, 4, -6, 0, 1, 12, 4, 18, -15, 19, 1, 15, 1, 1, 3, -10, 8, -1, 7, -30, 8, -19, -2, -5, -9, -10, 0, -1, 6, -4, -12, 1, -18, 10, -1, -12, 2, 7, 12, 11, 0, -4, -1, 6, 10, 17, -8, 1, -12, 5, -2, 1, -7, -1, 4, 3, -3, -1, -18, 8, -9, 0, -2, 8, -12, 12, 7, -5, -2, -16, -7, 9, -5, 11, -9, -4, 3, 1, -9, -1, -2, -6, 7, 12, 0, -8, 9, -10, 3, 0, 2, -3, 11, 14, 4, 3, -12, 3, -3, 2, 12, -4, -2, -2, 9, -21, -5, -28, -6, -10, 6, 7, -6, -3, -24, 7, -11, 10, 0, 8, 13, 10, 6, -7, -2, -5, 7, -1, 9, 18, -2, 12, -4, 7, -26, 13, -6, 19, 6, 6, -5, -16, -6, -8, -18, -2, 1, -11, 3, 4, -16, -8, -10, -3, 2, -3, 5, 5, 0, 11, 0, -14, 0, 1, 14, 11, 13, 0, -2, 5, -1, -4, -2, -4, 5, 21, 3, 14, -5, -22, 5, -11, -3, -6, -3, -11, 0, -5, -13, -10, -18, 3, 9, -10, 2, 3, -11, 11, -11, 5, -19, 23, -1, 20, 18, 4, -3, -6, 9, 4, -3, 8, 4, 6, 2, 5, -14, -6, -3, 2, -6, -4, -3, -11, 0, -5, 0, -21, -2, -10, 11, 5, -4, -5, -5, -8, 10, -10, 4, -1, 6, 12, 9, 2, 8, -20, 8, -2, 11, -11, 1, -4, 5, 6, -6, 6, -14, 14, 4, -2, 12, -3, -10, 8, -5, -15, -9, -1, 5, 8, -3, 0, -23, -9, -11, 4, -12, 3, -4, 4, 1, 15, -12, 3, 13, 2, 5, 8, -8, 7, 11, -3, 17, -11, 5, 3, 19, 13, 3, -11, -11, -2, -9, -7, -4, -24, -1, -17, -3, -17, 0, -15, 2, -1, -5, -4, 3, 2, 2, 11, -4, 3, -6, 11, 8, 3, 6, 3, 7, 7, 6, -6, 2, 0, 14, 14, 3, 8, -6, 4, -3, 6, -13, -2, -9, -4, 5, -13, -5, -21, -1, -6, -1, -5, -14, 8, -7, 5, -7, -17, -11, 7, 3, 20, 7, 1, -3, 4, 5, 14, -3, 5, 3, 10, 8, 6, -6, -2, 6, 3, 7, -6, -3, -3, -6, -1, -27, -11, -17, 0, 11, 7, 1, -7, -9, -13, 5, -11, 0, -10, 15, 2, 5, -2, -5, 1, 6, 6, -6, -5, 6, 2, 5, 3, 10, -16, 11, 8, 18, 3, 13, -11, 7, 5, -7, -6, -20, 15, -1, 10, -1, -13, -17, -11, -3, -13, -4, -14, -3, -2, -6, 6, -28, 9, -8, 10, 0, 12, -2, 10, 9, 1, 3, -6, 5, 17, 24, 18, 3, 4, -9, -4, 2, -8, -4, -2, -11, 1, -8, -12, -9, -10, 5, 0, -7, -9, 7, -18, 6, -10, -12, -1, -1, 13, 1, 18, 2, -3, 4, 3, 3, -3, 3, 10, 9, 7, 5, -8, -7, 0, 3, -7, 7, -2, -2, 5, -10, 2, -5, -3, -1, 4, 1, -2, -10, 4, -9, -5, -12, -18, 3, 6, -3, 3, -15, -1, -13, 6, -2, 8, 0, 8, 16, -2, 17, -4, 8, 3, 23, -1, 11, -8, 10, -4, -5, -3, -13, -2, -1, -2, 2, -9, -13, -13, -2, -11, -2, -20, -5, 0, 3, 2, -1, -10, 1, 8, 3, 9, 6, 4, -3, 13, 3, 4, 11, 2, 11, 8, -2, -1, -2, -2, -2, -1, -21, -1, -14, 8, 6, -8, -10, 2, -16, 4, -3, -1, -10, 7, -1, 4, -4, -12, 3, -2, 13, 2, -3, -9, -2, 6, -7, 8, -8, -5, 12, 7, 8, -3, 6, -1, 16, 0, 7, -8, 3, -7, -1, 0, -6, -4, -8, 6, -1, 4, -19, 2, -3, -8, -3, -12, 4, -6, 2, -7, 1, -13, 2, 9, -1, 17, -19, 3, -3, 23, 9, 6, 3, 6, 6, -5, 11, -11, 1, 0, -5, 6, -6, -4, -5, -7, 3, -4, -14, -9, -7, -1, 5, -11, 4, -19, 14, -4, 3, 4, 2, 0, 9, -2, -3, 2, -2, 10, 15, -3, 14, -6, -4, 6, 1, -8, 11, -9, 4, 3, -9, 2, 2, -2, 2, -2, -9, -2, -2, 1, -6, -6, -22, -16, -10, 12, 0, 5, -8, -2, -4, -2, 5, -1, 7, 7, 9, 1, 7, 6, -1, 10, 11, 5, -3, 8, 1, -1, 8, -15, -6, -10, 12, 0, 2, -5, -9, -12, -7, -4, -14, -4, 0, -1, 5, -7, -8, -12, 0, 2, 16, -3, 11, -4, 16, 11, 2, -3, 2, 8, -1, 7, -13, 4, -3, -1, 3, -10, -2, -11, 3, 2, 3, -7, -10, -5, -10, 12, -8, 5, -7, 15, 1, -10, 7, -16, 1, 3, 4, -5, 7, -7, 4, -2, -1, -8, 0, -2, 17, 10, -2, 6, -5, 3, 10, -7, 2, -3, 4, 5, 5, -3, -8, -8, -1, 1, 7, -5, -11, -2, -10, -4, -15, -7, -10, -2, 2, -4, -10, -8, 0, 2, 6, 3, 2, 3, 10, 14, 8, 7, 3, 5, -5, 20, -6, -1, -2, 0, 1, -2, -2, -8, 3, -3, 10, -14, 3, -3, -2, 0, -5, 0, -15, 4, -2, 0, 4, -7, 3, -8, 7, -14, -2, -6, 4, 2, 3, -10, -2, 5, -3, 12, -2, -5, -9, 1, 4, 1, 11, -12, 15, 5, 20, 10, -5, 1, 5, 3, -13, 6, -16, 5, 1, -5, -8, -3, -14, -6, -2, -5, -8, -17, -9, 3, -6, -2, -3, -3, 1, 14, 2, 4, 5, 3, 8, 7, 12, 0, 11, 4, 16, 2, -3, -9, -1, 1, -1, -3, -6, -14, 4, -6, 2, -14, -9, -11, -1, 0, 0, -5, -6, -10, 5, -5, 2, -3, 2, 2, 17, -2, -1, -3, 3, 11, 1, 10, 2, 7, 6, 5, -5, -3, -3, -2, 7, 2, 1, -18, -5, -2, -3, -5, 0, -2, 0, 8, -9, -10, -15, -7, -2, -1, 6, -8, 16, -10, 13, -4, 2, -4, 4, 7, 9, 6, -5, -2, 8, -1, 11, -6, -1, 5, 8, 0, 9, -20, 0, -9, 4, -3, 1, -4, -11, 2, -6, 0, -12, 0, 1, 5, -2, 1, -7, -4, 3, -1, -10, 3, -3, 7, 4, 8, -9, -6, -10, 0, 0, 2, -4, 6, 9, 10, 2, 0, -1, 2, 14, 3, 7, -7, 2, -2, -2, -6, -9, 2, -3, 6, -3, -7, -9, -10, -2, 2, -1, -11, 2, 1, 7, -4, -7, -19, 3, -1, 6, 6, 6, 6, 0, 6, 7, 3, -1, 3, 8, 3, 4, -10, -5, -7, 5, -4, -14, 2, -8, 5, -2, 2, -16, -4, -11, 2, 4, -1, 2, -1, 0, 5, 4, -12, 3, 9, 7, 13, -3, -7, 2, 6, -1, 7, -1, -1, 5, -5, 7, -11, -9, -13, 2, 5, 2, -2, -7, 5, 4, -4, -2, -15, -4, 3, 0, 0, -5, 2, -7, -1, 9, -2, -1, 5, 1, 1, -4, -5, -4, 6, 8, 7, -5, 4, -7, 4, 0, 1, -6, -5, -2, 5, -1, 0, 1, 1, 3, 9, -4, -2, -4, -9, -1, 4, -17, 1, -13, 11, -1, 6, -9, -1, 5, 1, 8, -3, 4, -5, 1, 7, -5, 1, -3, 5, 3, 4, -7, -11, -7, 1, 5, -13, 11, -11, 1, 3, 6, -9, 6, -5, -7, 4, -13, 5, -7, 10, 5, 6, -15, -1, 6, 4, 18, -7, -7, -3, -4, 2, -5, 3, -4, 9, -4, 3, 3, -3, -10, 0, -1, 2, 5, -3, 7, 3, 2, -6, -11, -2, -1, 4, -5, 4, -5, 0, -5, 5, -5, -4, 2, 4, 2, 5, -8, -13, -3, 0, -1, -2, 4, 6, 9, 1, 3, -7, -1, 1, 12, 1, 1, -1, -5, -1, 2, -8, -9, -7, -2, 3, 10, -6, -7, -12, -7, -4, -5, 6, 0, 10, 5, 7, -4, -2, -8, 10, 5, 9, 4, -1, -1, -1, -1, -1, -2, -3, 3, 9, -2, 9, -14, -13, -8, -10, 1, 1, 3, 3, 1, -3, -12, -5, -7, 1, 6, 6, -2, -7, -3, -3, 2, 2, 4, -9, 14, 8, 11, -3, 5, -11, 1, -1, 5, 3, 8, 2, 8, -2, -6, -13, -10, 0, 4, 3, 4, -3, -9, 1, -5, -5, -6, 1, -2, 2, -10, -6, -15, 1, -5, 4, -1, 2, 2, 4, 10, 4, 2, -13, 0, 4, 8, 17, 2, 5, 4, 2, -6, 5, -5, 0, 8, -2, -1, -5, -4, -5, -1, -5, -4, -5, 0, 0, 1, -9, -15, -3, -12, 1, -1, -7, 10, 2, 5, -1, 2, -6, 2, 2, 10, 10, -1, 2, -2, 4, 5, 0, -6, 12, 5, 3, -1, -8, -8, -4, -4, 3, -11, 0, -1, -1, 0, -2, -14, -6, -9, 2, 1, 7, -4, 3, -1, 0, -3, 1, 2, 7, 5, 4, 3, -2, -3, 1, 6, -1, 6, -11, 7, 2, -6, 2, -4, 0, 2, 3, -7, -9, 3, 0, 4, -6, 0, -21, 0, -5, -1, 0, -1, 1, -6, -1, -1, 0, -7, 5, 7, -2, 8, -4, -1, 3, 9, -6, 10, -6, 7, 9, 10, 9, -6, 5, -14, 6, -5, 1, 2, -3, 0, -9, -10, -14, -2, -3, 6, -8, -15, 3, -9, 0, -3, 0, -6, -1, 3, 9, 10, 3, 3, -10, 6, 1, 3, -1, 9, 12, 4, 4, -9, -7, -5, 8, 6, 1, 1, -4, -5, -5, -1, -11, -3, -4, 1, -1, 1, -10, -7, -2, -3, -4, -3, -6, 11, 5, 3, 2, -8, -5, -2, 3, 9, 13, 5, 4, 4, 0, -5, -1, -5, 9, 2, 3, -9, -4, 3, -6, 2, 1, -9, 5, -2, 3, -2, -9, -8, -15, -5, -3, 3, -13, 11, 6, -3, 1, -6, -6, -1, 6, 4, 6, 7, 1, 5, 0, 8, -6, 7, 2, 6, 2, -5, 0, -3, -1, 3, -7, -1, -3, 5, 7, 6, -18, -10, -11, -7, -3, 10, -4, 3, -4, -8, -5, -12, -3, -4, 12, 10, 2, -4, 6, 3, 1, 2, 0, -3, 3, 7, 7, -5, 2, -4, 1, 3, 11, 2, 3, 4, -2, -7, -5, -17, -11, 4, -3, 5, -7, -7, -6, -1, -8, -5, -5, 1, 7, 1, 2, -1, -9, 7, 1, 7, 3, 3, 6, 9, 6, 1, -6, -4, 2, 5, 7, 4, -2, 1, 3, -11, -1, -16, -2, -6, 1, 3, -8, -15, -11, 4, -1, 9, -2, -5, 0, 6, 0, -7, 0, -8, 4, 2, 6, 2, 0, 2, 6, 2, -2, 4, -2, 4, 14, 2, 2, -6, -6, -3, 4, -4, -1, -4, 1, -3, -6, -1, -13, -1, -2, 7, -8, -7, -10, 0, 4, 3, -8, -3, 1, 4, 6, 4, 6, -3, 5, 3, 4, 0, 6, 1, 4, 7, -3, -10, 8, -1, 9, -1, 1, -11, -7, -3, -3, -6, -8, -9, -6, 1, -3, -6, -6, -5, 0, 0, 2, -3, 0, 6, 4, 3, 2, 7, 4, 11, 14, 5, -1, -5, 1, -2, 7, 3, 0, 1, 2, -5, -7, -10, -12, -10, -5, -5, -6, -6, -9, 1, -8, -2, -1, -9, 1, 8, 2, -5, -2, -5, 0, 5, 6, 6, 7, 8, 10, 2, 0, -3, -1, 2, 13, 3, 0, -6, 0, 1, -3, 0, -12, -2, 4, -4, 4, -8, -11, -1, -2, 1, -1, 2, -12, 3, -6, 1, -12, -7, -7, 3, 0, 9, 0, 1, 6, 1, -1, 2, 1, 2, 8, 9, -3, -1, 0, 7, 3, 8, -1, -4, -1, 1, 3, -9, -1, -17, -3, -2, -4, -4, -3, -4, -6, -11, -15, -2, -5, 6, 10, 1, 3, -1, -3, 13, 7, 1, 6, 4, 4, 9, 5, -3, -5, 9, 3, 5, -3, 1, -3, 3, 0, -7, -5, -7, 0, -5, 0, -1, -15, -11, -4, -5, -10, 2, -7, 5, -4, 1, -9, 2, 1, 8, 7, 10, 2, 2, 0, 4, 3, -2, 0, 4, 2, 6, 8, -2, 4, 4, -2, 5, -3, -6, 3, -3, -5, -9, -8, -11, -5, -1, -1, -5, -7, -5, -8, 0, -3, 5, -7, 11, 1, 0, 2, -3, -1, 3, 9, 6, -3, 8, 1, 11, 2, 8, -3, -3, 6, 2, 1, 2, -7, -3, -2, -4, -8, -3, -3, 5, -10, -10, -4, -12, -2, 3, -5, 3, -6, -8, -2, 5, -3, 0, 1, 4, 8, 4, 5, 0, 4, 8, 1, 7, -3, 0, 3, 4, 4, -5, -2, -7, -3, 0, 5, -5, -9, 3, -2, -1, -2, -5, -1, -4, -3, -11, -4, -5, -6, 0, 5, 0, -5, 5, 3, 8, -1, 3, 3, 2, 5, 7, -4, 3, 1, 3, 10, 2, -7, 1, 0, 6, -4, -3, -5, -7, -2, -4, -3, -6, 0, -10, 4, -6, -4, -7, -2, 1, -4, -1, -3, -1, 2, 6, 2, 4, -2, 2, 4, 2, 5, -3, 4, 2, 1, 0, 8, -3, 2, 5, -5, 3, -5, -2, 5, -5, 3, -1, -4, -3, 4, -10, -5, -7, -4, -4, 0, 0, -7, -1, -1, 2, 1, -2, -12, -4, -1, 0, 4, -5, 2, 0, 3, 12, 11, 3, 11, -1, -3, 6, -6, 1, 1, 7, 6, -7, -1, -7, -4, -4, -7, -8, -1, -6, -6, -2, -3, -5, 0, -4, 8, -7, 1, 4, -3, 6, 1, -7, 3, 5, 6, 5, 13, 2, 2, -4, 4, -3, 1, 4, -4, 2, -3, -10, -10, -7, -2, -2, -2, 0, -6, -2, 1, -3, -4, -2, -5, -2, 7, 1, 6, -5, 6, -1, -1, 2, -3, 4, 11, 2, -1, 2, -7, -5, 8, 0, 3, -3, -5, -1, -2, 3, 1, -4, 4, 7, 0, 2, 3, -3, 0, 1, -5, -15, -5, -3, 1, 3, -3, -11, -4, -7, 1, -2, -1, -1, 0, 1, 1, -5, -1, 3, -2, 7, 1, -4, -1, 0, 4, 5, 3, 3, -1, 8, 11, 1, 4, 1, -5, 7, -6, -4, -2, -4, -2, 3, -8, -3, -13, -6, 3, -3, -7, -4, -7, 3, 3, -3, 2, -1, 1, -4, -2, -2, -5, 1, 11, 9, -2, 6, -3, 7, 7, 1, 1, -7, 2, -3, 1, 4, -4, -4, 5, 1, 0, -3, -6, 2, -3, 0, -8, -12, -6, -2, -3, 6, -1, -9, 0, -1, 1, 3, -2, -1, 0, 1, 6, 0, -3, 5, 1, 6, 1, -1, 4, 1, 7, -3, -1, -1, -4, 4, 14, -1, -1, 2, -4, -1, -6, -8, -8, -3, -2, 2, -9, -5, -7, -12, 5, 0, -3, -4, -3, 5, 4, 3, -2, -6, 4, 7, 3, 5, 7, -3, 8, 0, -5, -1, -1, 11, 10, 3, 4, -8, -3, -3, 1, -3, 0, -4, -3, 1, -7, -8, -16, -7, -6, -2, 3, -7, -2, 1, -4, 0, -5, -5, 1, 5, 10, 5, 0, 3, 0, 1, 13, 0, 5, 9, 6, 8, -1, -4, 0, -3, 6, 4, -4, 0, -3, -15, -2, -12, -15, -3, -6, 2, 1, -3, -4, -9, -9, -3, -3, -2, 3, 4, 9, 0, 2, 1, 2, 14, 5, 3, 8, 2, 7, 4, -4, -4, -1, -9, 9, -5, -1, -7, -10, -2, -7, -4, 0, -5, 2, 5, 1, 0, -5, -5, -1, -1, -3, 4, -8, 5, 3, -4, 4, -5, -3, 9, 4, 8, 0, 0, 2, 0, -2, 0, -2, -7, 12, -1, 5, -4, 2, -3, 0, 2, -2, -4, -2, 2, -5, 3, -7, -9, -4, -3, -2, -6, -6, -2, -6, -1, -7, -8, 1, 3, 6, 10, 4, 5, 0, 5, 8, 1, 3, 8, 5, 11, 12, -7, 4, 0, -3, 2, -1, -8, -7, -4, -2, -6, -9, -6, -13, -4, -1, 0, -9, -5, -3, -4, -2, 3, 1, 1, 9, 4, 2, 6, -1, 3, 6, 2, 0, -3, 3, 2, 6, 3, -1, -4, 4, 1, 2, 2, -5, -8, -1, -3, -1, -9, -4, 1, -5, 5, -7, -4, 0, 3, -10, 3, -3, -5, 1, 5, 4, 1, -5, 1, -5, 4, 1, -6, 0, 5, 8, 8, 1, 6, 0, 3, 4, 2, -3, 1, -3, -3, 3, -10, -6, -8, -2, -1, -3, -6, -6, -5, -6, -6, -5, 5, -3, 5, 6, -2, -1, -1, -4, 6, -2, 6, 6, 2, 12, 8, -2, 3, -6, -2, 5, 4, -3, -2, -5, -4, -7, -6, 1, -5, 2, 2, 0, 1, -7, 0, -4, -2, -1, -2, -5, 7, -5, -2, -3, -2, -3, 4, 4, 9, 0, 1, 1, -5, -3, -4, -4, 4, 3, 6, 1, -2, -2, -7, 4, 1, 1, -3, 3, -1, 2, 0, -7, 0, 0, -1, -3, -2, -1, -5, -2, -3, -8, -5, -5, -1, 5, 5, 2, 2, -3, 4, 3, 4, 6, 3, -1, 10, -4, -3, -2, -3, 0, -4, 0, -2, -2, 0, 2, -5, -2, -5, -9, 8, -2, -1, -1, -3, -3, -2, -6, 2, 1, 2, 9, 0, 1, 4, -5, 2, 4, -6, -1, 2, -1, 6, 3, 0, -5, -3, -1, 0, 3, -3, 0, -6, -2, -3, -4, -2, 0, 3, 2, 2, 0, -10, 1, -6, -5, -1, -2, 5, 3, 6, -2, -6, -1, -3, 2, 4, 1, -1, 0, 1, 1, 3, -1, 5, -1, 7, 6, 1, -2, 0, -6, -2, -2, -8, -2, -2, -3, -5, -5, -8, -3, -1, 5, -3, 1, 2, 1, 2, -3, -2, -3, 2, 6, 2, 6, 0, 0, -2, 9, -1, 3, -2, 3, 0, 0, 0, -6, -6, -1, -5, -7, 1, -3, -6, 2, -2, -1, -5, -2, 1, 4, 2, 2, -3, -1, 6, -2, 2, 4, -3, 2, 2, 2, -3, 1, 0, -4, 2, -1, -2, 3, 1, 1, -1, -5, -8, -2, -5, 0, 1, -6, 3, -4, 2, 3, -6, 3, 0, 2, -2, -1, -4, -2, -4, 4, 0, -3, 0, -6, -3, 10, -3, 3, 0, 4, 7, 3, 0, 5, 1, 5, 1, -3, -2, 0, -6, 3, -1, -7, -5, -7, -1, -2, -2, -2, -3, -2, 2, -2, -1, -3, -3, 2, -2, -6, -3, -3, 4, 3, 2, 0, -1, 5, 5, 8, 2, 2, -2, 4, 0, 5, -5, -3, -1, -3, -3, -6, -4, -2, 3, 0, -2, -2, -5, 5, -1, 3, -1, -1, -3, 0, 0, -5, -4, -3, -2, 5, 0, -4, -4, 1, 2, 6, 0, -3, -1, 2, 3, 7, -3, 0, -4, -2, 4, 3, 0, 1, 3, -3, 1, -7, -4, 0, 1, 1, -4, -4, -4, -9, -1, -2, -3, -2, -3, -3, 4, 3, -1, -4, 2, 4, 4, 3, 2, -1, 0, 9, -1, 4, 2, 7, -1, 6, -2, -2, -5, -1, -9, -2, -2, -6, -1, -1, 1, -8, -6, -5, -1, -1, 1, -4, -5, 3, 1, 5, 3, -3, 0, -2, 7, 0, 1, -2, 3, -1, 5, -1, -5, 7, -1, 3, 2, -5, -6, -2, 4, 2, -1, -3, -1, -1, -1, -1, -2, -4, 1, -5, 3, -1, -3, -5, 2, 6, -6, -1, -5, -4, 4, -1, -1, -2, -1, 2, 0, 3, 1, 4, 2, 7, -1, 2, 0, -2, 1, 4, -5, -3, -7, -2, 0, -1, -1, -3, 0, 0, -2, -6, 2, -4, 2, -4, 1, -7, -2, -1, 5, 3, -2, -7, -4, 1, 6, 4, 5, 1, 4, 0, 5, 1, -1, 2, 0, -3, -3, -5, -6, 3, -1, 5, -1, -2, 1, 1, 4, 2, -6, -3, -4, -3, 2, -2, -8, -3, -6, -4, -2, -11, 0, 0, 1, 6, -3, -2, 1, 2, 10, 8, 4, -2, -1, 2, 2, 1, -2, 3, 1, 5, 3, -1, 0, -4, 4, -7, -2, -7, -8, -4, -3, -2, -7, -7, -3, -1, 5, -2, 0, -7, 2, -1, 3, 1, 4, 6, 5, 8, 3, 2, -1, 3, -3, 0, 0, -5, -1, 1, 1, -5, -3, -2, 6, 4, 5, -4, -8, -4, -3, -2, -5, -4, -4, -4, 2, -3, -2, -4, -4, -4, 6, 1, 0, 1, 3, 3, 5, 2, 1, 0, 6, 2, -1, 1, -3, -3, 2, -1, 0, 1, 3, 1, 4, -4, -5, -10, -8, 1, -6, -3, -4, -6, -3, 0, 2, -3, -1, 2, 0, 8, 1, 4, 4, 3, 6, 3, 1, 3, 5, 1, 2, -4, -7, -3, -3, 3, 0, -7, -5, 0, -3, -1, -2, -4, 0, -5, 1, -6, -1, -5, -3, 1, 4, -1, -3, 3, 3, 5, -1, -2, 2, -1, 2, 1, -1, -5, 5, 1, 2, 2, -4, 0, -1, 3, 0, -2, -1, 2, 1, 5, 4, -3, -5, 0, -2, -2, -6, -3, -3, -4, -1, -5, -4, -1, -2, 0, 2, -2, -6, -3, 1, 1, 1, -1, 3, 4, 7, 2, 3, 4, -1, 7, 2, 3, 1, -1, 1, -2, 0, -4, -5, -6, 0, -2, -7, -2, -5, -5, 1, -4, -5, -5, 3, -1, 1, 2, -2, 0, 1, 4, 1, -4, 2, 2, 0, 9, 2, 0, 4, 3, 1, 2, -4, -2, -4, 3, -4, -2, -6, 0, -1, 5, 2, -4, 0, -4, -4, -1, -5, -4, -7, -3, 1, 0, -2, -1, -5, 1, 0, -1, 0, 2, 4, 0, 3, -2, 1, 2, 6, 0, 1, 5, 0, 3, 3, 2, -5, -2, 1, 5, 2, -2, -5, -9, 0, -6, -1, -6, -7, -5, -4, 0, -2, -5, -3, 2, -2, 3, 2, 0, 9, 2, 0, 4, -3, 4, 5, 8, 6, -2, -4, -1, 0, -2, -2, 1, -5, 2, -5, -1, -4, -3, -4, 0, -2, -7, -3, -1, 0, -1, 0, -6, 3, -2, 5, 2, -1, -2, 1, 0, 1, -1, -3, 2, 3, 1, 2, -4, -3, -1, 5, 5, 3, -4, 0, 1, 2, 5, -5, 1, -5, 2, -2, 2, -4, -3, 0, -4, -3, -9, -7, -4, 2, -2, 1, -6, -3, 0, 1, 5, 1, -5, 0, 0, 2, 1, 2, 0, 6, 4, 6, 3, 2, 3, 1, -2, -2, -9, -4, -1, 4, 0, -1, -5, -8, -5, -4, 0, -4, -1, -3, 0, 0, -4, -3, -1, 1, 2, 0, -2, -3, 1, 3, 2, 3, 3, 0, 8, 2, 7, -1, 3, -2, 4, 0, 0, 1, -4, 5, -1, -3, -3, -6, -4, 2, 1, -5, -4, -7, -4, -4, -7, -2, -10, 1, 0, 1, -3, 4, -2, 5, 2, 1, -3, -1, 2, 8, 4, 5, 0, 1, 4, 5, 2, 2, -2, 1, -4, 0, -3, -3, -1, 0, 2, -4, -4, -5, -1, -7, 0, -4, -5, -1, -3, 2, -2, 0, 3, 0, 2, 0, 1, -2, 2, 4, -1, 0, -3, -1, 1, 3, 2, -3, 2, 0, 2, 2, -1, 2, -2, -3, 0, 0, -2, 2, -2, 4, -3, -6, -7, -6, 2, -1, -4, -1, -7, -1, -3, 3, -1, 0, -2, 2, 2, -3, 3, -4, 5, 7, 6, 3, 1, -1, 6, 2, 1, 0, -1, -1, 1, -3, 1, -3, -5, -5, -3, -8, -3, -11, -1, -1, 0, -8, -2, -5, 3, 4, 0, 1, -2, 2, 0, 6, 4, 1, 4, 1, 5, 0, 0, 1, 2, 5, 0, 1, -10, 0, -5, 2, 0, -6, -6, -2, -2, 2, -3, 0, -4, 2, -4, 1, -3, -4, 1, -2, 2, 1, -2, 0, 3, 2, -3, -1, -5, -3, 4, 2, 3, -1, 4, 1, 5, -1, 2, -3, 2, -3, 0, -3, -2, 1, 1, 5, 1, -2, -5, 1, -1, -4, -3, -7, 0, -5, -4, -4, 0, -4, 4, 0, -1, 1, -8, 1, 0, 9, 1, 2, -2, 5, 5, 1, 6, -1, 6, 3, 1, 1, -2, -2, -4, -3, -2, -3, -7, -4, -4, -1, -3, -8, -1, -8, 4, -5, 0, -3, 1, 0, 4, -1, 0, 1, 3, 3, 4, -4, 6, -2, 2, 5, 4, -3, 4, -3, 5, 0, -4, 0, 0, -1, 0, -4, -4, 3, -1, -2, -4, -8, -9, -5, -4, 4, -4, 1, -4, 1, 1, -1, -1, -1, 3, 2, 3, 0, 1, 2, 1, 5, 3, 1, 0, 5, 3, 3, 0, -5, -4, -2, 5, 0, -2, -5, -2, -6, -2, -5, -8, -2, 1, -1, -3, -7, -8, -6, 0, 4, 7, -2, 7, -1, 7, 3, 2, -5, 0, 2, 0, 1, -3, 2, 2, 3, 3, -3, 0, -2, 3, -1, -1, -4, -6, -2, -3, 4, -4, 0, -4, 6, -2, -6, -2, -7, 1, 2, -1, -3, -2, -2, 3, -1, 0, -3, -1, 4, 7, 4, 0, 2, -1, 0, 6, -2, 1, 1, 5, 4, 1, -3, -3, -2, 2, 2, 1, -6, -6, -3, -4, -2, -6, -5, -4, -5, -2, -8, -8, -3, 0, 4, 0, 1, -1, 2, 5, 4, 2, 2, 3, 3, 4, 10, 0, 2, 0, 3, 1, 1, 0, -3, 1, -3, 1, -7, 0, 1, -2, 1, -6, -4, -10, -1, -4, -2, -2, -3, 2, -4, 1, -5, -4, -4, 2, 1, 1, -4, -1, 3, 1, 6, 2, -2, -2, 3, 3, 2, 7, -5, 5, 0, 8, 1, -1, 2, 3, -1, -6, 0, -10, 3, -1, -1, -5, -6, -8, -2, 0, -3, -5, -8, -4, 2, -3, -1, -2, 0, -1, 7, -1, 3, 2, 4, 7, 3, 4, -1, 5, 1, 9, 1, -2, -1, -1, 1, -3, -2, -6, -7, 1, -3, -1, -9, -4, -6, 0, 2, -3, -2, -4, -3, 0, -4, -1, -4, 0, 1, 6, -1, 1, -1, 3, 5, -1, 3, 4, 5, 7, 4, -2, 0, -2, 0, 3, 1, -1, -8, -2, -1, -2, -5, -1, -2, -2, 2, -5, -7, -9, -2, -3, -2, 1, -5, 4, -4, 5, -1, -1, -3, 2, 3, 7, 3, -1, 3, 4, -1, 5, -4, 0, 4, 4, 3, 4, -9, 1, -5, 2, -2, -2, -3, -7, -1, -2, -2, -5, -3, -1, 1, -2, -1, -4, -4, 1, -1, -7, 0, -1, 2, 5, 4, -4, -5, -4, 0, 2, 1, -1, 3, 5, 4, 0, 0, -1, 3, 8, 3, 3, -4, 0, 1, 0, -2, -6, -2, -4, 3, -2, -3, -5, -6, -3, -1, -1, -7, 0, 0, 3, -5, -4, -11, 0, 0, 3, 3, 1, 1, 1, 4, 6, 1, 1, 2, 9, 3, 3, -4, -4, -3, 2, -1, -6, 1, -5, 2, 0, -1, -8, -5, -6, 1, 0, -2, -1, -2, -1, 2, 0, -9, 0, 5, 4, 7, -3, -3, 3, 4, 2, 4, 0, -1, 3, 1, 5, -5, -6, -7, 0, 3, 0, -2, -4, 3, 3, -3, -4, -7, -2, 4, 1, -1, -4, -1, -6, -2, 3, -2, -3, 1, 4, 1, -1, -4, -3, 3, 4, 5, -2, 2, -3, 4, 0, 3, -3, -3, 0, 3, 1, -2, -1, -3, 2, 4, -2, -2, -3, -1, -1, 3, -11, -2, -8, 5, -1, 3, -5, -2, 2, -1, 3, -3, 0, -1, -1, 5, -2, 0, -2, 3, 2, 3, -2, -6, -3, 2, 4, -6, 5, -6, 1, 2, 3, -6, 2, -3, -4, 3, -9, 2, -6, 3, 4, 2, -9, -1, 1, 2, 8, -3, -4, -1, -2, 2, -2, 2, -3, 3, -1, 1, 2, -1, -6, 1, 2, 2, 1, -2, 2, 3, 1, -3, -6, -3, 0, 1, -3, 0, -3, -1, -4, 2, -4, -3, -1, 4, 0, 5, -6, -7, -1, 0, 0, -3, -1, 2, 4, 0, 3, -4, -1, 1, 7, 4, 2, -1, -4, 0, 2, -4, -5, -5, -1, 1, 4, -5, -4, -6, -3, -2, -3, 2, -2, 5, 2, 3, -4, -2, -5, 6, 3, 4, 2, -3, 1, 0, 0, 1, -3, -1, 1, 7, 0, 6, -6, -7, -2, -7, 0, -1, 0, 2, 1, -2, -7, -2, -5, 0, 2, 0, -3, -5, -1, -3, 0, -1, 0, -6, 8, 4, 5, -1, 1, -4, 1, 1, 4, 2, 5, 3, 6, 0, -2, -9, -4, -1, 0, 0, 1, -1, -4, -1, -5, -5, -5, 0, 0, 1, -6, -5, -9, 0, -3, 0, -2, 0, 0, 3, 4, 2, 1, -7, 1, 3, 4, 9, 1, 4, 4, 2, -4, 2, -2, 1, 5, -2, 0, -3, -4, -3, -2, -4, -4, -4, 1, -1, 2, -6, -8, -3, -8, -1, -2, -4, 5, 2, 3, -1, 0, -4, 2, -1, 5, 5, -1, 3, 0, 3, 3, 0, -4, 9, 4, 2, -1, -6, -4, -2, -2, 2, -7, 0, 0, -2, -2, -2, -10, -4, -7, 0, -2, 2, -2, 2, 1, 0, -3, 0, 1, 6, 3, 2, 0, 0, -1, 2, 3, -1, 4, -5, 6, 2, -3, 0, -3, 0, 1, 0, -5, -6, 1, 0, 1, -5, -2, -14, 0, -4, -1, -1, -1, 1, -3, 0, -2, -1, -4, 4, 5, -1, 5, -1, 3, 3, 5, -3, 5, -3, 5, 5, 6, 4, -6, 2, -9, 4, -4, 0, 1, -2, -1, -8, -6, -11, -2, -3, 3, -6, -8, 3, -5, 1, -3, 1, -3, 1, 3, 5, 6, 2, 1, -6, 4, -1, 1, 0, 7, 7, 2, 3, -6, -4, -4, 3, 3, 0, 1, -1, -2, -4, 0, -8, -2, -3, 1, -2, 1, -5, -2, -1, -3, -3, -4, -3, 7, 4, 1, -1, -6, -5, -3, 2, 5, 8, 3, 3, 2, 1, -4, -1, -2, 6, 3, 2, -4, -1, 1, -5, -1, -1, -5, 2, -2, 1, -2, -7, -5, -11, -4, -3, 3, -8, 8, 4, -2, -2, -4, -4, -1, 4, 3, 5, 5, 2, 4, -1, 6, -3, 6, 2, 3, 0, -4, 0, -2, -2, 0, -5, -2, -1, 4, 3, 1, -13, -8, -8, -5, -3, 7, -2, 3, -2, -5, -3, -8, -2, -3, 8, 6, 1, -2, 5, 3, 1, 2, 0, -1, 2, 4, 3, -5, 1, -3, 0, 1, 7, 1, 2, 3, -1, -4, -4, -10, -7, 3, 0, 2, -5, -5, -4, -1, -7, -3, -3, 1, 3, 0, 0, -1, -6, 6, 1, 4, 1, 2, 5, 6, 4, -1, -4, -3, 1, 2, 5, 2, -1, 1, 3, -8, -1, -10, -2, -5, 0, -1, -6, -10, -7, 2, -2, 6, -1, -2, 1, 4, -1, -5, -1, -5, 4, 1, 4, 2, 1, 3, 4, 0, -2, 1, -1, 3, 8, 2, 1, -4, -3, -3, 3, -3, -1, -4, 0, -4, -6, -2, -8, 1, -2, 5, -6, -5, -6, 0, 3, 1, -6, -3, 1, 2, 4, 2, 4, -2, 3, 3, 3, 1, 5, 1, 2, 3, -2, -6, 6, -1, 6, -2, 1, -7, -5, -2, -3, -6, -6, -6, -4, 0, -2, -4, -4, -3, 0, -1, 1, -3, -1, 3, 1, 1, 0, 6, 4, 8, 10, 5, 0, -3, 1, -2, 5, 2, 1, 1, 1, -4, -6, -8, -8, -8, -5, -4, -5, -4, -5, 0, -5, -3, 0, -7, 0, 4, 1, -4, -1, -4, -2, 4, 4, 5, 6, 6, 7, 0, 0, -1, 0, 2, 9, 2, 1, -3, 0, 1, -3, 1, -9, -1, 3, -4, 3, -6, -7, -2, -1, -1, -1, 1, -9, 2, -5, 1, -8, -6, -6, 1, -1, 6, 0, 2, 5, 2, 0, 2, 1, 2, 6, 5, -2, -1, 0, 4, 1, 6, 0, -2, 1, 0, 3, -7, -1, -13, -4, -3, -3, -3, -2, -3, -5, -9, -11, -2, -3, 4, 7, -1, 2, 0, -2, 8, 5, 1, 4, 3, 2, 7, 3, -2, -4, 7, 2, 3, -2, 1, -1, 2, 0, -5, -4, -4, 0, -4, 0, -1, -10, -9, -3, -5, -8, 1, -5, 3, -3, 0, -7, 1, 0, 5, 4, 7, 1, 1, 0, 2, 2, -2, -1, 2, 1, 4, 6, -1, 4, 3, -1, 4, -2, -3, 3, -1, -2, -6, -6, -7, -3, -1, 0, -4, -6, -5, -6, 0, -3, 3, -5, 7, 0, -1, 1, -3, -1, 1, 6, 3, -3, 7, 1, 10, 1, 6, -1, -2, 5, 2, 1, 1, -4, -2, 0, -3, -7, -2, -4, 4, -8, -8, -4, -10, -2, 2, -4, 1, -5, -7, -1, 3, -1, 1, 1, 4, 6, 2, 2, 0, 4, 7, 0, 5, -2, 0, 3, 3, 3, -3, -1, -5, -2, 0, 3, -4, -6, 2, -1, 0, -2, -4, 0, -4, -3, -9, -3, -4, -4, 0, 3, -1, -4, 3, 1, 5, -2, 1, 2, 2, 4, 5, -3, 2, 1, 3, 7, 1, -5, 1, 0, 5, -3, -2, -3, -4, 0, -3, -2, -5, 0, -8, 3, -6, -4, -6, -2, 2, -4, -2, -3, -2, 1, 4, 2, 3, -2, 2, 4, 1, 4, -2, 3, 2, 1, 1, 7, -1, 2, 4, -4, 2, -4, -2, 5, -4, 3, -1, -3, -2, 3, -8, -4, -6, -3, -3, -1, 0, -6, -1, 0, 1, 1, -2, -10, -3, -1, 0, 2, -5, 1, 1, 2, 10, 8, 2, 8, -1, -2, 4, -5, 2, 2, 7, 6, -6, -1, -5, -4, -3, -6, -7, 0, -5, -5, -1, -2, -5, 0, -4, 6, -6, 0, 3, -3, 4, 0, -6, 2, 5, 5, 4, 10, 0, 2, -3, 3, -2, 0, 3, -3, 2, -3, -8, -8, -5, -1, -1, -1, 0, -5, -2, 0, -3, -4, -1, -5, -2, 5, 0, 5, -4, 4, -1, -1, 1, -3, 3, 9, 2, -1, 1, -6, -3, 7, 1, 3, -2, -4, 0, -1, 3, 1, -3, 4, 6, 0, 1, 2, -3, 0, 0, -5, -13, -4, -2, 1, 2, -3, -10, -4, -7, 1, -2, -2, -1, 0, 1, 1, -4, -1, 2, -2, 7, 1, -3, 0, 0, 4, 5, 2, 2, -1, 6, 9, 1, 3, 1, -5, 5, -6, -5, -2, -4, -2, 2, -7, -4, -11, -5, 3, -3, -6, -4, -6, 3, 3, -3, 2, 0, 1, -3, -1, -2, -4, 1, 10, 8, -2, 4, -3, 6, 6, 1, 0, -7, 2, -2, 1, 3, -4, -4, 4, 1, 0, -2, -5, 2, -2, 0, -7, -11, -5, -2, -2, 5, -1, -8, -1, -1, 1, 2, -2, -1, 1, 1, 5, 0, -3, 5, 1, 6, 1, -1, 3, 1, 6, -3, -1, -1, -3, 4, 12, -1, -1, 2, -4, -1, -6, -8, -7, -3, -2, 1, -9, -5, -6, -10, 5, 1, -2, -3, -2, 5, 4, 3, -1, -5, 4, 6, 3, 4, 6, -2, 7, 0, -4, -1, -1, 9, 8, 2, 2, -8, -3, -3, 0, -2, 0, -4, -2, 0, -6, -7, -14, -6, -5, -1, 3, -6, -2, 1, -3, 0, -4, -5, 1, 5, 9, 4, 0, 3, 0, 1, 12, 0, 4, 8, 5, 7, -1, -4, 0, -3, 5, 4, -4, 0, -3, -13, -2, -10, -14, -3, -5, 2, 1, -3, -4, -8, -8, -3, -2, -2, 3, 4, 8, 0, 2, 1, 2, 12, 5, 3, 8, 2, 6, 3, -4, -4, -2, -8, 8, -5, -2, -6, -10, -2, -6, -4, 0, -4, 2, 5, 1, 0, -4, -4, -1, -1, -3, 4, -7, 4, 3, -3, 4, -4, -3, 8, 4, 7, 0, 0, 2, -1, -2, -1, -2, -7, 11, -1, 5, -4, 2, -2, 0, 2, -2, -4, -2, 1, -5, 3, -6, -9, -3, -3, -2, -5, -5, -2, -6, -2, -7, -8, 1, 3, 5, 9, 4, 4, 0, 5, 8, 1, 3, 7, 5, 10, 11, -7, 3, 0, -3, 1, -1, -7, -7, -3, -2, -6, -9, -6, -12, -4, -1, 0, -8, -5, -3, -3, -2, 3, 1, 1, 9, 4, 2, 5, -1, 2, 6, 2, 0, -3, 2, 2, 5, 2, -1, -4, 4, 1, 1, 2, -5, -8, -1, -3, -1, -9, -4, 1, -4, 5, -6, -4, 0, 3, -9, 3, -3, -5, 1, 4, 4, 1, -4, 1, -4, 4, 1, -6, 0, 5, 7, 8, 1, 6, 0, 3, 4, 2, -3, 1, -3, -3, 3, -9, -6, -7, -2, -1, -3, -5, -6, -5, -5, -6, -5, 4, -3, 5, 5, -2, -1, -1, -3, 6, -2, 5, 6, 2, 11, 8, -1, 3, -6, -2, 5, 4, -3, -3, -5, -3, -7, -5, 0, -5, 2, 1, 0, 1, -7, 0, -3, -2, -1, -2, -5, 7, -4, -2, -3, -2, -3, 4, 4, 9, 0, 1, 1, -5, -3, -4, -4, 4, 3, 6, 0, -2, -2, -6, 4, 1, 1, -3, 3, -1, 2, 0, -7, 0, 0, -1, -3, -2, -1, -5, -2, -3, -8, -5, -5, -1, 5, 5, 2, 2, -3, 4, 3, 3, 6, 3, -1, 10, -4, -3, -2, -3, 0, -4, 0, -2, -2, 0, 1, -4, -2, -5, -9, 8, -2, -1, -1, -3, -3, -2, -6, 2, 1, 2, 9, 0, 1, 3, -4, 2, 4, -6, -1, 2, -1, 6, 3, 0, -5, -3, -1, 0, 3, -3, 0, -6, -2, -3, -4, -2, 0, 3, 2, 2, 0, -10, 1, -6, -5, -1, -2, 5, 3, 6, -2, -6, -1, -3, 2, -1, 0, 0, -1, 0, 0, 0, 1, -2, 2, -2, -5, -1, -2, 16, 12, -18, -10, 3, -14, -10, 16, -1, -3, -16, 28, 3, -1, -1, 12, -5, -6, 6, 7, -7, -18, -28, 11, 0, 6, -2, 26, -21, -10, -1, 24, -3, 20, -19, 15, -14, -3, -3, 15, -35, -2, 6, -14, 30, 6, -36, -8, 17, 0, -27, 26, 16, -38, 8, -14, 57, 3, -31, -14, 34, -20, 33, 2, -6, -7, -28, 20, -24, 8, 13, 8, -39, 17, 40, -42, -11, 13, -46, 1, 28, -22, 11, -3, -14, 5, 20, -12, -4, 49, -22, -24, 39, -11, -1, -9, 37, -30, 13, 34, 4, -11, -25, 18, -22, 1, 29, -17, -3, -26, -16, -21, 12, -18, 7, -17, -6, 51, 0, -21, 10, 24, -45, 8, 14, 31, -10, -37, 6, 0, 24, 3, -18, -13, 14, 11, 0, 7, -1, -38, -29, -21, 32, -30, 22, -26, 14, -40, 55, -36, 30, -12, 8, 31, -16, 19, -15, 23, -48, 36, 1, 63, 3, 24, 0, -3, 14, 26, -21, 15, 47, -21, -80, 14, -4, -25, -33, 11, 25, -35, -44, 13, -2, -48, -11, -23, -7, 27, -4, -15, -22, 5, 26, -36, 50, 23, 11, -23, -14, 19, 32, 14, 38, -66, 56, -11, 26, 18, -12, 17, -30, -6, -54, 22, 77, -62, -12, -16, 34, -25, 2, 14, -62, 12, 20, -22, -50, 58, -29, -58, 4, 28, 30, 13, 25, -78, 38, 45, -19, -7, 52, -61, 27, 17, -21, -4, 6, 37, -24, -38, 73, 8, -16, 21, -2, -15, -19, -19, 18, 3, 7, -48, -10, -10, 10, 4, 13, -13, -4, 0, 46, -12, 6, -18, -25, 4, 14, 27, -22, -37, 14, -6, -17, 55, 40, -111, 63, 9, -38, -16, 46, -35, 4, 0, -10, -8, -12, 58, -69, 1, 66, -38, 21, -33, -6, 10, 0, 10, -11, 18, -16, 32, -7, -10, -25, 65, -42, 42, -62, 18, -3, -2, -8, 21, 4, -71, 13, 40, -3, 18, -19, -29, 15, -66, 60, -50, -6, 67, -80, 17, 66, -21, -20, -15, 68, -16, 72, -4, -23, 4, 53, -8, 8, -4, 0, 27, -26, -22, 25, -31, 7, -39, -18, 27, -43, -25, -33, -6, 17, -16, 0, -55, 6, 26, -3, -67, 7, 60, -83, 25, 15, 45, -8, 51, -55, 28, 42, 42, -17, 37, -6, 17, 8, 11, -1, 59, -7, -45, 14, -41, 107, -49, -50, -25, 63, -58, -27, -57, 19, 13, -13, -27, 19, -42, 63, -113, -1, 44, 8, 1, -10, -33, 0, 55, -41, 15, 0, 76, -17, -39, 60, -20, 28, 54, -93, 15, 83, -30, 4, -56, 49, -58, 30, -28, 2, 54, -64, 83, -128, 86, 24, -40, -27, -66, 51, 11, -51, 59, 6, 20, -58, -24, 78, -7, -23, -27, 1, -3, -24, 10, -6, -16, 34, 39, -37, -17, 26, 52, -69, -7, 11, 24, -62, 38, -13, 41, 5, -2, -5, -12, 15, 77, -49, -10, 74, -12, -11, -38, 32, -24, 25, -6, 19, -24, -2, -38, 63, -91, 64, -27, -11, -56, -43, 27, -41, -55, -15, 1, -4, 27, 8, 37, -57, 3, 28, -11, -4, 46, -39, 3, 12, 100, -33, 39, 17, 6, 49, 5, 38, -12, 10, 21, -35, 23, -6, -36, 10, -9, 3, -1, 13, -65, -40, 36, -25, -28, 5, -37, -20, -14, 31, -16, -32, -16, 4, 15, -11, 26, -16, 29, -42, 46, 7, 39, -1, -5, -9, 33, -31, 35, -33, -7, 17, 56, -24, 22, 14, -22, -34, 44, 16, 11, -46, 43, -48, -27, 43, 36, -45, 21, 11, 0, -98, -22, 87, -126, 52, -45, 34, -28, -17, -31, 23, -38, 23, 25, -11, 25, -63, 21, 13, 19, 47, 28, -23, 20, 21, -5, -14, 112, -30, -67, 37, 43, -12, -57, 34, -9, -29, 52, -19, 14, -51, 0, 26, -69, 3, -18, -24, -34, 31, -15, -33, -36, 10, -20, -38, 63, 0, 44, -50, 72, 25, -16, -6, 6, 15, 23, 31, 3, -20, -9, 19, 63, 17, -18, -5, -12, -87, 31, 26, -37, -29, 49, -42, -15, 14, 11, -16, -31, 46, -19, -13, -37, 59, -91, 47, 4, -11, -26, 39, -29, -24, 48, 10, 39, -11, 45, -51, -1, -24, 47, -19, 39, -34, -29, -17, 1, 56, -25, -16, -13, 0, 48, -71, 49, 2, -2, -45, -10, 59, -17, -25, 9, 9, 44, 42, -32, -23, -49, 46, -11, -50, 76, -43, -45, -1, 41, -8, 2, 71, -36, -61, 35, 21, -13, -36, 44, -45, 26, -45, -21, 28, -37, 39, -29, 15, 4, -5, 24, -7, 7, 3, 68, -80, 26, 24, -22, 8, 26, 28, 10, -26, -3, 16, -51, 85, -8, -14, -54, 39, -28, -9, -25, 46, -39, -20, 34, 11, -25, -7, -12, -41, 12, -17, -5, -43, -8, 0, 18, 13, 9, 28, -40, 34, 0, 13, 40, -20, 5, 22, -25, -13, 51, 9, -34, 43, -16, -18, 2, 35, -4, -28, 14, -37, 6, -8, 31, -49, 9, -31, 61, -55, 35, -46, -37, -12, 32, 74, -59, -30, -21, 5, 38, 3, 48, -35, -42, 2, 29, 81, -8, -37, 24, 42, -31, 18, -11, -21, -67, 98, -18, 11, -26, -14, -76, 11, 71, -70, 30, -52, 37, -45, 61, 6, -33, -44, 58, 24, -16, -51, 49, -28, 51, -6, -15, 46, 10, -24, 36, -4, 6, -30, 46, -66, 54, 27, -16, -34, -23, 90, -61, -49, 22, -3, -22, 17, -35, -11, -59, 23, 2, -25, 69, -24, -26, -28, 37, 12, 11, -63, 27, 18, 3, 34, -25, 9, -14, 29, 4, 24, 21, -77, 12, 14, 37, 1, 45, -63, 1, 49, -14, -23, -7, -4, -42, 48, -57, 18, -36, 17, 15, -37, 47, 1, -41, -14, 11, 49, -32, 32, -36, -19, 21, -11, 39, -31, 43, 0, -24, 15, 6, 9, -46, 5, 21, -23, 2, -28, -15, 59, -13, -29, 50, -7, -45, -12, 23, -1, 27, 6, -17, 7, -4, -3, -3, 53, -10, 17, -52, 19, 24, -8, -7, 19, -51, -30, 55, -22, -22, 29, -38, -25, 39, 3, 34, -84, 26, -37, 42, 15, 4, -4, -16, -33, 29, 17, 43, -93, 24, -6, -20, -14, 107, -29, -36, 69, -21, 10, -7, 74, -67, 38, -23, -8, 27, -35, -49, 29, -8, -4, 7, -8, 5, -38, -28, -33, 22, 70, -37, -10, -56, 26, 5, 7, 59, -21, -58, 10, -2, 6, 49, -16, -9, -38, 60, 13, 43, -43, 23, -14, -9, 38, 17, -38, -15, 29, 6, -5, -11, -3, -4, -65, 45, -13, 26, -13, -4, -5, -38, 48, 0, 4, -40, 40, -48, 23, 21, 23, -42, 5, -17, 13, -9, 12, -3, 5, -25, 34, -24, -3, -18, 16, -44, 13, 27, -30, 44, -54, 6, -18, -3, 4, 21, -25, -13, 22, -20, -12, 37, -10, -10, 5, 24, -17, 23, 9, 0, 4, 3, 12, 26, -27, 17, 9, -41, 69, -1, 15, -37, 15, -6, 0, -1, 3, -13, -23, -18, 27, -5, 21, -16, -41, -2, 20, 13, -27, 6, -21, 8, 6, 0, 6, -5, -21, -22, 73, -40, 4, 6, 21, -8, -5, 29, -47, -1, 1, 19, 3, -10, -1, 2, -48, -11, 45, -27, 11, -33, -21, 21, 7, 12, -22, 21, -40, 13, 27, -20, 37, 5, -18, -18, 35, 40, -11, 20, -25, 10, -4, 33, 12, -29, 9, -20, -30, 34, 24, -9, -10, -24, -16, 8, 22, 6, -58, -5, -13, 18, 5, -43, 10, -16, -25, 13, 70, -25, -7, -25, -19, 16, 58, -46, -5, 6, -5, 40, -24, 22, 50, -73, -7, 7, 32, 39, -27, -23, -23, 56, -35, 21, 17, -40, 40, -52, 4, 0, 49, -29, -42, 24, 9, 31, 2, -46, 0, -9, -5, 9, -31, 64, -5, -45, -26, 42, -4, -34, -8, -3, 32, -15, -8, 22, -24, 13, -31, -2, 31, 10, -10, -18, 8, 24, 20, -29, 2, 14, 23, 25, -4, -19, 20, -25, -5, -3, 23, -8, 52, -42, -17, -7, 29, -26, 2, -19, 55, -50, -28, 1, -10, -7, 7, -41, 16, 21, 1, -20, 0, 16, -19, 14, -39, 86, -17, -34, -64, 73, 0, 20, -28, 30, -22, 9, 58, -4, -8, -18, -20, 31, -21, 1, 26, -49, 5, 41, -25, -13, -6, -7, 6, 10, 42, -30, -26, -43, 11, 44, -54, 31, -10, -11, -17, 25, 32, -43, 64, -23, 3, -37, 33, -30, -4, -35, 47, -29, 9, 23, -34, -5, 64, -37, 32, -11, -44, 21, 25, -19, 8, 6, -25, 34, 2, -18, -23, 38, 20, 7, 21, 1, -32, -37, 50, -9, -25, 34, -61, 55, -32, 7, -48, 20, 13, 0, -35, 17, 9, -42, -28, 14, 42, -33, -25, -5, 21, 41, -60, 32, -7, 38, -9, -3, 20, -4, 29, -69, 62, -16, 35, -64, 45, 10, 5, -1, -18, -18, -1, 5, 32, 0, -21, -12, -23, 29, -15, 13, -39, -3, -3, 6, 35, -24, -23, -7, -2, 44, -10, -37, 25, 25, -25, -23, 7, 40, 4, -40, -18, 21, -2, -3, 1, -16, 45, -26, -2, -16, 18, 41, -64, 8, -26, 40, 5, -32, 8, 18, -1, 15, -1, 9, 2, 2, -13, -12, 35, -9, 13, -62, -29, 72, 18, 7, -30, 26, -7, -29, 39, -38, 31, -56, -25, -3, 17, 2, -3, -46, 35, 6, 27, -39, -3, 3, 31, -25, -19, -2, 38, 26, -77, 22, 18, 40, 3, -22, 65, -48, 33, -16, -37, 78, -34, 1, -52, 23, 16, 1, -37, 17, 12, 1, -4, 8, -27, -1, -11, -18, 27, -23, -10, -11, -19, -6, -7, 51, -74, 16, 20, 17, -14, 7, 7, -13, -8, -5, -11, 39, 21, -5, -44, 31, 64, -38, -18, 20, 40, -4, -10, 10, -23, 23, -6, -20, 11, 9, 10, 6, -23, -11, 1, 17, -56, 56, -40, 0, -17, -60, 84, -80, 16, -13, 4, -25, 12, 17, -42, -26, 54, -29, 12, -5, 37, 16, -62, 94, -5, -2, -2, -2, -9, 5, 51, -25, -5, -11, 5, 16, -14, -9, 43, -44, -8, 27, 2, -1, 9, -18, -6, 5, 23, -46, -9, 13, 16, -10, -10, -23, 59, -47, -14, 23, 29, -15, -14, -30, 21, -21, 0, 14, -3, 25, -16, -35, -2, -8, 32, -19, 22, -23, -37, 30, -33, -19, 11, 12, -32, 47, -4, 27, 11, 9, -35, 39, 29, -18, -2, -11, 27, -2, 13, 0, 18, -26, 15, -25, 26, -4, 21, -29, -33, 18, -8, -31, -5, 21, -1, -38, -28, 41, -18, -4, -22, 47, -12, -44, 55, -79, -5, 19, -10, 25, 4, 21, 15, -28, 13, -6, 45, -24, 25, 10, -26, 4, 2, 31, 3, -7, 3, 5, -23, 51, -9, -32, -5, 35, -32, -21, -20, 35, -40, -10, 20, -8, 7, -5, -38, -1, -24, 39, -26, 20, -16, -9, -27, 25, 34, -32, 1, 12, -13, 3, 37, 13, 3, -31, 27, 30, 5, -15, -21, 2, 10, -13, 16, 36, -9, -59, 41, -10, 61, -60, -35, -11, 7, 5, -28, 30, 5, -23, -66, 34, 50, -26, -19, -10, 11, 8, 8, -35, -5, -11, 56, -24, 10, 35, 16, -10, -19, 30, 4, -11, 23, 0, -6, 6, 36, -15, 0, 15, -14, -26, -8, -5, 15, -31, -45, 42, -30, 0, -9, 6, -22, 9, -22, 7, -8, 15, -19, -3, -13, 29, -14, 9, -16, 3, -5, -10, 63, 0, 4, 4, 20, 16, -21, 18, 31, -24, -19, 31, 54, -39, -7, -16, 5, -3, 0, -29, 16, 6, -29, -25, -52, 49, -9, -66, -3, 50, -3, -2, -14, 4, -8, 33, -40, 2, 15, -6, -17, -4, 10, 48, -16, 14, -9, 27, 10, 2, 2, 40, -35, 5, -10, 7, 28, 1, 4, -30, -4, 0, 1, -14, -13, -11, 26, -17, 13, -44, -9, -6, -23, 17, 11, 11, -21, -11, 0, 9, 8, 8, -30, 29, 10, -26, -12, 15, 17, 4, -26, 14, 19, 20, -9, -24, 39, 23, -10, -35, 8, -6, 18, -25, 15, -17, 41, -48, -31, -5, 47, -14, -20, -4, -7, 5, -19, 3, 21, 12, -23, 15, -24, 8, 3, -25, 2, 28, 14, 21, 25, -72, 15, 26, -6, 45, -27, 29, -30, -17, 23, 6, -2, 27, -46, 13, 9, 15, -57, 27, 1, -18, 1, -11, -2, -20, -16, -23, 24, 18, -21, -5, -15, -14, 26, -12, 30, -48, 37, -24, -3, 23, 9, -5, 9, 8, -43, 23, 26, 6, 28, -29, 30, -8, -12, 25, -18, 33, -48, -4, 29, 1, -8, -4, -20, 41, -22, 1, 12, -33, 0, -17, -16, 29, -3, -2, -36, 6, -1, -11, 4, -24, 40, -24, -5, 26, -2, -28, 13, -11, 35, -9, -2, -3, -6, 13, 10, 1, 11, -22, 22, -27, -5, 20, 11, -1, 8, -23, 8, 7, -7, 17, -6, 16, -9, -10, 3, 13, -3, -17, 19, -21, 6, -13, -15, -7, 22, -15, -7, 11, -20, -19, -6, 0, 28, -10, -7, -13, 9, 7, 1, -11, -6, 21, -33, -4, 52, -11, -1, -2, -2, -4, 32, 17, -31, 7, 12, 2, -5, 11, -1, -6, 1, 3, -11, 5, 4, -15, -8, 10, 5, -18, 5, -26, -11, 22, -15, -23, 22, 19, -30, 3, 1, -5, 10, -17, 10, -2, 10, 7, -17, -5, 36, -12, -24, 27, 22, -3, -11, -6, -7, 20, 5, -21, 0, 23, -31, -27, 14, 2, 8, 7, -15, 0, 13, -7, -3, -21, 33, -4, -26, 7, 5, -7, -7, 1, 3, 4, 11, -24, 6, 11, -7, 14, -9, -11, -1, 34, -22, 11, 1, -18, 17, 4, -19, 28, -15, -7, -11, 12, 1, -7, -9, -12, 17, -20, 6, 5, 2, -10, 12, -23, -3, 26, -1, 4, 6, -25, 12, -3, -26, 2, 15, 14, -18, -6, -17, 14, 4, -10, 21, -13, 5, -15, -20, 27, 6, 8, -11, 18, 15, -34, 17, -2, -13, 41, -9, -10, -6, -2, 7, -11, -4, 28, -26, -6, 25, 17, -36, -2, 33, -39, -15, 11, -2, 26, -32, -31, 21, 26, -11, -24, 12, -17, 4, -33, 24, 14, -10, 12, -19, -3, 28, 11, -8, 0, 26, -17, -7, 8, -6, 20, 26, -29, -27, 25, -14, -2, 10, -16, 39, -24, -17, -4, -13, 24, -10, -3, -20, 25, -1, -24, 24, -20, -5, 21, -26, 7, 21, -26, 15, 17, 6, -34, 5, 11, -27, 20, 17, -13, -8, -16, 9, 33, -36, 19, 5, 4, -2, -33, -12, 38, -17, -10, -4, 19, 14, -4, -32, -41, 64, 5, -38, 28, 6, -2, -11, -22, 11, 17, 17, -24, 23, -7, 9, 10, -38, 0, 25, -9, -6, -27, 20, 2, -27, 34, -23, 17, -22, 4, 12, -43, 29, -8, 25, -19, 13, -17, -11, 27, -8, 14, -19, 12, 9, -22, -6, 11, -10, 17, -4, 2, -3, 15, -47, 32, -18, 11, 14, 0, 8, -33, -14, -12, 23, 17, -12, -4, 13, -27, 10, -17, 20, -2, -11, -11, 27, 18, -21, -6, 26, -18, 9, -7, 27, -12, 3, -9, -9, 22, 7, -38, -2, 14, -16, 12, -21, -10, 22, 1, -28, 20, 31, -11, -49, 9, 16, -4, -7, -4, -5, 46, -39, 9, -18, 16, 22, -24, -13, 14, 29, -10, 3, -23, 4, 11, -33, 30, 18, -9, 5, -11, 4, -20, 30, -9, -14, -7, -9, 4, 0, 4, -15, -11, 23, 5, -24, 26, -6, -8, -17, 21, 0, 3, 13, -10, -13, 19, -16, -10, -5, 10, 8, 22, -19, 4, -8, 0, -24, 38, 12, -33, 10, -9, 5, -13, 11, 3, 7, -18, -12, 11, -4, 8, -17, -7, 16, -9, -2, -9, 0, 10, -2, -1, -1, 12, -6, 13, -18, 18, -6, 10, 1, -3, 9, -2, -30, 23, -9, 29, -11, -31, 10, 6, -21, -19, 54, -30, 18, -12, -26, 23, -10, -31, 23, -5, 49, -34, 4, -18, 3, 11, -24, 27, 12, -24, 3, -13, 3, 16, -6, -7, 1, 19, -8, -3, -11, 13, -14, 19, 10, 17, -21, 14, -40, 12, 13, -5, -3, 21, -14, -29, 16, -24, 1, 10, -1, -3, 6, -15, -16, 16, -4, 2, 23, -32, -1, 7, -5, 13, 4, -15, 33, 1, -7, -7, -12, 13, 6, -8, 2, 21, 2, -21, 17, -14, -19, 36, -2, -16, -4, 3, 9, 15, -39, 3, 9, -10, -3, -12, -7, 28, -19, 8, -18, 22, -18, -11, -2, 17, 23, -15, -24, 11, 13, -14, -10, 9, 4, 14, -10, -13, 13, -3, -12, 25, 6, -12, 12, -19, -3, 19, -10, -13, 19, 10, 18, -31, -15, 19, -9, -14, -6, 25, -18, 2, 17, -41, 11, 16, -20, 3, -10, 16, 9, 14, -27, -1, -3, 9, -19, 36, -6, -4, -4, -16, 5, -7, 24, -1, -30, 13, -8, -4, -9, 47, -37, 3, 21, -24, 1, 3, 11, 5, -10, -8, 20, -31, 16, 10, -1, 0, -9, -1, -6, 14, -6, 6, -17, 20, 3, -23, 10, -14, 17, -16, -2, 26, 7, -20, -10, 9, -18, 31, -35, 3, 14, -8, 13, -27, -4, -4, 26, -20, -9, 14, 22, -27, -4, 18, 9, 9, 3, -13, -20, 15, -13, 6, 12, -5, -6, -12, 0, 4, -10, 18, -7, -8, -15, 1, -11, 17, 5, -11, 14, -6, -11, 4, 10, -5, 13, 0, -7, 15, -2, -16, 2, -3, 9, -6, 2, 34, -11, -17, -8, 21, 13, -21, -4, 14, -7, -7, -19, 13, -7, 4, -25, 7, 16, -14, -40, -11, 36, 3, -10, 4, -10, 7, -1, -1, 4, 14, 6, -14, -14, 17, 23, -13, -2, -1, -12, 9, 8, 1, -7, 22, -29, 7, 7, 0, -24, 13, -10, 18, -1, -3, 13, -24, 30, -32, -5, 18, -2, -6, -8, 11, -18, -12, 17, -11, 0, 5, -4, -14, 31, -15, -16, 13, 12, -4, 4, -4, -1, -11, -15, 26, -18, 29, -15, -3, -8, 6, 6, -34, 22, 0, 11, -18, 16, 20, -19, -21, -5, 11, 21, 10, 10, -27, -5, 3, 2, -5, 9, -9, -1, 1, -11, -3, 8, 4, 1, -1, -11, 19, -1, -21, -5, -2, 11, -2, -8, 10, -7, -1, 2, -18, 3, 0, 7, 2, 7, 1, 1, -28, -14, 10, 19, 12, -21, 7, -19, 20, -2, -3, -1, 17, -11, -13, -16, 32, 4, -5, -3, 4, -4, 18, -2, -17, -6, 16, -3, 4, -12, 4, -2, 2, 6, -18, 20, -24, 17, -10, 19, -16, -17, 8, -7, -5, 16, -12, -18, 11, 9, 2, -8, 17, -9, -3, -13, 7, -6, 30, -15, -11, 5, 14, -2, -15, -5, 14, 13, -12, -24, -10, 22, -2, -8, -1, 21, -5, -19, -16, 8, 42, -6, -27, -12, 23, 10, -17, -14, 16, 14, -16, -2, 9, -2, 16, -9, -31, 22, 0, -2, 3, 4, -5, 20, -24, -5, 13, -1, -5, -10, -6, 8, -11, 2, 8, -8, -5, -9, 1, -6, 16, -1, -18, 4, 9, -3, 6, -4, 6, 9, -7, -9, -1, 10, -7, 4, 3, -3, 4, -8, -5, 3, -4, 10, 6, -15, 2, 3, -5, -2, -3, -12, 18, 2, -16, 7, 13, 0, -19, -8, 11, -6, -1, -9, 5, 13, -8, -6, 6, 7, 11, -11, -6, 13, -2, -5, -1, 9, -2, -7, -15, 10, 5, -1, -13, 8, 0, -6, -2, -2, 18, -16, -7, 2, 3, -4, 6, -11, 4, 6, 1, -5, 22, -11, -5, -6, -3, 11, -1, -1, 4, 1, -4, -13, -4, 11, -9, 1, 9, -1, -8, 1, -5, -7, 5, -14, 18, -1, -12, 11, -12, 16, -5, -11, 11, -2, 15, -7, -18, -10, 0, 18, -12, 8, 3, 6, -16, -3, 3, 6, 0, -1, -3, 4, 9, 3, -17, -7, 11, 11, -19, 5, 15, -12, -3, -12, 4, 11, -19, 0, 0, -14, 21, -15, 2, 8, 3, 8, -8, 5, -18, 9, -2, -8, 23, -5, -16, 5, 3, -20, 13, 11, -6, -15, 5, 4, -12, 2, 10, -5, -12, 5, -14, -2, 18, 11, -14, 0, 28, -10, -20, 4, 7, 9, -13, -6, 15, 11, -9, -6, 14, -8, 10, 4, -12, 11, -18, 13, -17, -9, 16, -4, -14, -7, 17, -24, -5, 4, 6, -6, 14, 2, -24, -22, 11, 13, 8, -16, 6, 13, -28, 10, -2, 11, 8, -1, -8, -14, 22, 3, -5, -13, 18, 7, -26, 15, 20, -6, -10, 4, 11, 5, -8, -3, -5, 0, -1, -6, 0, 4, 4, -14, -1, 1, 8, -14, -10, -4, 6, 4, -8, 3, -9, 0, 11, -4, -7, 5, 4, 6, -29, 18, 22, -19, -16, -11, 17, 7, -4, 3, -23, 20, 8, -19, 3, 13, 13, -16, -18, 15, -6, 0, 3, 17, -7, -4, 2, -22, 21, -1, -2, -1, -15, 13, 3, -7, 4, 0, -7, 8, -7, 11, 3, -2, -8, 10, -15, 0, 9, -14, -8, 8, -2, -9, 10, -13, 9, 7, -6, 2, -12, -4, 6, -12, 8, 12, 3, -10, 6, 7, 1, -2, -11, -1, 7, -7, 8, -13, -10, 11, -9, -10, -8, 20, 9, -11, 8, -5, -4, 6, -3, 5, 13, -13, -7, -7, 6, 19, 0, -9, 9, -1, -3, 4, -7, 0, -2, -4, -5, 5, 0, -5, 14, -19, -14, 18, -1, -5, 3, -12, 18, -19, 4, -15, -10, 10, 10, -17, -4, 19, -6, -2, 5, 11, -4, -3, 9, -22, 28, -6, -5, 0, -1, 11, -11, -13, 22, 3, -8, -9, 1, 3, 0, 1, 2, 7, -5, -25, 10, 6, 6, 2, -11, 8, -16, 15, -20, 5, 9, -6, -13, -5, 14, 6, -21, 22, -7, -14, 4, 26, -8, -13, 8, 1, -10, -13, 11, 10, -10, 2, -13, -9, 15, 0, 10, -30, 14, 7, -13, -5, -12, 8, 10, -4, 10, 12, -15, -7, 5, 2, 2, 10, -13, -3, 0, 21, -2, -16, 9, 3, -1, 6, 15, -3, -21, 10, -8, 5, 1, 1, 2, -19, 10, -7, -3, -1, 8, 6, -26, -10, 18, -28, -3, -3, 4, 0, -7, 6, -10, -2, 25, -19, 5, -11, -2, 14, 4, -5, -3, 4, -5, 6, -2, -3, 11, -1, 13, -12, 5, 20, -15, -3, 17, 4, -14, -5, 11, 3, 1, 6, 11, -20, 10, -4, -4, -4, -4, -18, -7, 5, 10, -25, 7, -9, -15, 1, -4, 4, 4, -4, -1, -18, 9, -6, 4, 7, -19, 10, 0, 3, -6, 12, 18, -5, 2, 4, -4, 11, 2, 5, 2, 1, 3, -4, 3, 4, -3, -2, -8, 11, 5, -10, -12, 12, -6, 6, -9, -6, 4, 9, 0, -9, 4, 3, -7, -5, -12, 19, 2, -28, 1, 0, 9, -10, -6, 3, 3, -11, -4, 6, 7, -7, -3, 5, -12, 9, 10, -12, 7, 5, 5, -6, -9, 16, 6, -16, 3, 8, -17, 12, -5, 2, 1, 21, -25, -10, 5, -2, 15, -6, 1, 3, 5, -16, -2, -16, 32, -17, 7, -13, 6, -1, -4, 0, -4, 10, -2, -17, -7, 29, 0, -13, -1, -1, 2, 12, -4, 3, -2, 4, -19, -1, 18, 2, -3, -15, -2, 10, -4, 1, -2, -5, 20, -5, -6, -7, 9, 0, -2, -24, 5, 15, -2, -11, 1, 0, -2, -14, -2, -4, 7, 4, -4, -9, 2, 4, -8, 8, -1, 2, 10, -13, 4, 10, -4, 27, -22, 17, -18, -2, 5, 8, -1, 4, -6, 2, -1, 9, 1, -3, 16, -21, -18, 2, 10, -14, 9, 3, -14, -9, 0, -16, 9, -10, 11, -12, -3, 1, -10, 3, -2, 2, -13, 13, 10, -1, 4, 4, 1, -3, 9, 0, 4, 8, -14, 10, -4, 0, 8, 11, -2, 2, -11, 3, -13, -8, 11, 4, 1, -7, 4, -21, 0, 1, -4, -22, 17, -8, -16, 10, 4, -2, 0, -4, 2, -2, 2, -6, 10, 3, 3, 5, -1, 6, 5, 2, -6, -3, -2, 7, -4, -4, 12, 1, -30, 12, -7, 3, 4, -6, -7, -9, 9, -1, 7, -10, 12, -16, 2, -8, 23, -5, -5, -1, -8, 10, 3, -14, -12, 25, 7, -13, -6, 4, 15, -3, -23, 9, 12, -9, -13, 18, -9, 5, 1, -17, -4, 13, -10, 11, -10, -1, 6, 0, -7, -2, 9, -4, 9, -24, 7, 6, -5, 4, 15, -15, 11, -5, -24, 9, 11, -16, 2, 0, -9, -2, 10, 7, -12, 8, -12, -6, 10, 6, 10, -14, -5, 20, -16, 7, 8, -1, -19, 24, 2, -10, 15, 6, -6, -21, 3, -3, 15, -9, -3, 3, -2, -4, -3, -9, 5, 0, -5, -3, -15, -4, -1, 1, -14, 33, -12, -18, 9, -2, -10, 9, 9, -1, -1, -5, 10, -3, 2, 4, 2, -9, -1, 25, -2, -3, 15, -17, -7, 8, -7, 0, 10, -13, 9, -11, 0, -3, 18, -15, -11, 5, 0, -12, -2, 7, -6, -4, -9, 11, -6, 8, 1, -14, 3, 16, -10, -3, 2, 6, 4, 9, -9, -2, 0, 2, -3, 15, 3, -10, -4, -8, -1, 10, -13, -9, 16, -9, -3, -2, 5, -6, -6, -9, 10, 8, -4, 14, -7, -19, 12, 1, 2, 1, 4, -1, -6, -3, -3, 5, 7, -2, 0, 0, -5, 0, -6, 1, 6, -5, -4, 5, -6, 5, -4, -8, 15, -5, -7, 0, 3, -8, 0, 3, -8, -4, 6, -4, -4, 15, -5, -8, -7, 4, 7, -10, -6, 15, -4, -13, 7, 2, 2, 1, -4, 5, 0, 0, 1, 4, -7, 4, 4, -2, 4, 5, 1, -18, 12, 4, -3, -6, 11, 0, -13, -1, 1, -12, 3, 13, -9, -15, 7, 0, -4, -8, 0, 5, 0, -9, 1, 1, -3, 0, 3, 5, -10, 6, -1, -4, 4, 15, -15, -5, -9, 18, -2, 0, 15, -11, -9, 0, 6, -2, 8, 1, -8, -9, 7, 3, -7, -3, 6, 1, -5, 0, -5, -5, 0, -3, 11, 1, -3, -8, -4, -4, 5, 9, -6, -7, 4, 15, -13, 5, -4, 2, -6, -2, 0, 5, 4, -4, 0, -6, 8, 3, -2, -4, -4, -11, 4, 10, -1, -4, -2, -1, -3, 1, -4, -2, 3, 1, -4, -11, 12, -4, 5, -2, 7, -12, -2, 4, -4, 5, 8, 1, -8, 14, -11, -1, 1, 4, 0, 5, -5, 2, -7, -7, 10, 3, 1, -13, 0, -4, 5, -9, -1, 1, -11, -5, 5, 2, -6, 5, -5, -8, 12, -2, 7, -1, -10, -5, -7, 14, 9, 3, -5, -2, 5, 4, -2, 0, -5, 2, 3, 3, -12, 6, 3, 2, -9, -1, 24, -13, -9, -1, -2, 0, 7, -6, -17, 14, -12, -5, 10, 1, -4, -1, -1, 1, -3, 2, -2, -11, 1, -1, -1, 1, 10, -3, 2, 1, 5, -7, 1, -1, -5, 7, 1, 7, -4, 5, -11, -8, -8, 7, 8, 6, 0, -15, -1, 7, 0, -6, -3, 7, -4, -3, -2, 1, 5, 8, -6, -4, 11, 3, -14, -6, -3, -6, 9, -5, 4, -5, 2, 3, -13, -3, 1, -4, -3, 11, -1, 0, 7, -16, -6, 11, 5, 0, 4, 5, -2, -3, -2, 8, 7, -16, 1, 2, 6, 3, -17, 11, -2, -2, -9, 6, 0, -7, 6, -22, -2, 14, 3, -11, 0, -6, -2, -7, -7, 1, 4, 14, -1, -6, 0, 7, 3, -14, 4, 15, -4, -9, -2, 12, 14, -10, 5, 9, -11, -2, -9, 2, -9, 11, 2, -21, 7, 6, -11, -1, 0, 0, 1, -9, 4, 0, -10, 1, 3, -3, -7, 12, -9, -2, 4, 6, 3, -8, 0, 1, -2, -14, 12, 11, -5, 10, -3, -1, 3, -6, 1, 0, -3, 8, -1, -18, 12, 5, -13, -4, 17, -1, -6, 1, -11, 0, -6, 2, -2, -2, 5, 3, -17, 2, -5, 11, -4, 8, 8, -19, -6, 14, -6, -6, 0, 5, 0, -8, 7, 13, -6, -5, 6, -2, -9, -1, 8, 3, -4, -4, 10, -10, -9, 7, 2, -6, 14, 0, -15, 3, 5, -4, -10, 8, 0, -6, -11, 3, 10, -9, 1, 8, -7, 2, -1, -6, -8, 6, 2, -8, -2, 16, -3, -3, -1, 5, -3, -8, 6, 9, -6, 1, -1, -1, 2, -6, 6, -1, -9, 3, 9, -10, 1, 5, -4, -14, 2, 1, 7, -5, 3, -2, -13, 5, 10, -9, -8, 14, -6, -19, -3, 19, -3, -3, 6, -4, -10, 3, -1, -4, 5, 5, 1, 0, -1, 11, 4, -10, 3, -5, 4, -7, 1, 8, -3, 1, 2, 0, -10, 2, 5, -15, -3, 8, -8, -6, 5, -2, -5, -5, 11, 0, -12, -7, 5, 2, -5, 2, -1, -4, 2, 7, -12, 5, 6, -3, 5, -1, 12, 7, -13, -3, 0, 3, 0, 13, -1, -4, 0, -9, 5, -6, 5, -2, -10, -6, -2, 9, -8, 5, -6, -10, 5, 4, -6, -2, 1, 1, 6, -14, 10, -3, -4, -5, 1, 8, -16, 7, 7, -1, 0, 3, -5, 2, -1, -3, 11, -11, 9, 8, -18, 3, 8, 13, -4, -5, -9, 4, -2, -4, 9, 5, -6, -5, -15, -3, 17, -6, 2, -8, 4, 4, -4, -12, -3, -2, -2, -4, 5, -4, 1, 7, -12, -6, 8, 6, -2, 1, -3, 3, 10, -3, 7, -11, 12, 4, -1, -1, 1, 0, -11, 11, 4, 0, -2, -9, -2, -2, -8, -1, 5, -4, -5, -5, 1, 10, -8, -11, -5, -4, 5, -1, 1, 6, -2, -5, -5, 3, 6, -2, 6, -3, 0, 4, 5, 2, 4, -2, 1, 5, -2, -6, 11, -1, -5, 8, -14, 6, -2, -6, -11, 4, 2, -14, 6, -9, 5, -4, -3, 4, -12, -2, 2, -5, 4, 7, -5, 3, 6, -1, -3, -6, 0, 7, 0, 1, 6, 9, 4, -2, -7, -4, 7, 4, 4, -5, -5, 0, 3, -6, -1, 7, -2, -18, -1, 3, -15, 5, -2, -2, 0, 4, -10, -4, 3, 4, -10, 4, -1, 5, 4, -7, 8, -7, 0, 3, 2, -7, 13, 0, -2, -6, -6, 5, 10, -10, 4, -1, 2, -1, -5, 7, 5, -3, -7, 1, -5, 10, 1, -11, 7, 6, -10, -15, 12, 2, -4, 1, 0, -5, 3, 0, -2, 6, -5, -4, -13, -2, 3, 1, 4, 3, 3, -10, -7, -7, 11, -2, 2, 2, -7, 4, -1, 6, 2, 0, 8, 3, 0, -7, 8, 3, 5, -8, -3, -2, 2, 3, -12, -4, -3, 12, -12, -4, 7, -3, -10, -10, -4, 6, -2, -8, 9, 1, 1, 1, -3, -6, 12, -5, -6, -1, 11, -7, 5, 6, 2, 9, -11, 6, -2, 8, 1, -6, 4, 3, -6, -3, 5, -4, 4, 1, -19, -1, 3, 4, 0, 0, -10, -1, -3, -5, -3, 0, 11, -1, -12, -2, 6, 0, -3, 3, 4, -1, -7, 1, -2, -1, 2, -1, 0, 2, -2, 4, -5, -4, 11, -4, -5, -3, 7, 5, -8, 3, 6, -9, 0, 9, -5, -2, 5, -4, -6, 0, 7, -1, -2, 0, -1, -6, -9, -6, -1, 8, 4, -1, -9, -5, 13, 2, -11, -5, 9, 0, -8, -1, 5, -2, -5, -3, -2, 7, 5, -4, -13, 3, 11, -8, 3, 0, 2, 5, -12, -6, 6, 3, -4, -1, 8, 1, -5, -7, -6, 2, 8, 5, -2, -9, 7, -6, -2, 13, -7, 2, 1, -1, -5, 3, 7, -1, -11, 9, -6, -4, -2, -5, -1, 2, -1, 3, 8, -7, -1, -9, 0, 0, -1, 2, 5, -2, 1, -2, -3, 6, 6, -3, -6, -5, 4, -1, 1, 5, 1, -1, -2, -3, -4, 4, 3, 1, -7, 5, -1, 0, -8, -6, 1, 7, -3, -6, -2, 3, -1, -3, 2, 2, 0, -9, 1, -2, 4, 4, -5, 1, -1, 1, 6, -2, 2, -5, -4, -1, 14, -3, 2, -9, 1, -2, -4, 1, -1, 7, -9, 5, 2, -3, 2, -2, -9, -2, 4, -1, 2, -2, -2, 0, -1, -1, -2, 3, 1, -1, -3, -6, 3, 7, -5, -3, 9, -5, -4, -5, 8, -4, 2, 2, 8, -10, -1, 8, -14, 0, 6, -7, -1, 2, -3, 2, -4, 5, 2, -5, -4, 5, 1, -6, 3, 6, -4, -1, -3, 3, -7, 0, 1, 0, -4, 7, 6, -13, -3, 3, 2, -15, 8, 3, -3, -6, 9, -4, -1, 9, 1, -6, -6, 7, 1, 1, -2, 6, -1, -4, -1, -1, -7, 5, 3, 0, -5, -2, 8, -2, -8, 6, 7, -16, -5, 6, -6, -1, 1, 7, -4, -3, -6, 3, -10, -3, 8, -9, -1, 5, -1, -7, 5, 2, -1, 1, 5, 1, 2, -4, -5, 1, 1, 3, 1, -5, -2, 3, 2, -7, -1, 7, 5, -5, -7, 5, 0, 3, -1, -4, -4, 4, 0, -4, 1, 6, -3, -7, 0, -3, -3, -1, 0, -2, -4, 2, 1, -2, 3, -1, 0, -1, -6, 9, -5, 4, -1, -1, 4, -2, 5, -8, 2, -3, -2, 2, -3, 10, 2, -3, -5, 2, -4, -1, -3, -7, 9, 1, 0, 0, -5, 1, -2, -12, 6, 8, -18, 4, -1, 4, -1, 5, -5, -3, 3, -1, 4, -5, 9, -5, -4, -5, 2, 5, -1, -4, 0, -3, -2, 8, -5, 2, 1, -13, 3, 1, 4, 5, -8, 2, 8, 1, -1, 1, -9, 1, -2, -4, 1, 4, -3, 4, -4, -5, 6, 5, -6, -3, -3, 1, 1, -7, 1, 2, 1, -5, -4, -2, 2, -6, 6, 3, 7, -10, -9, 4, 1, -5, 6, 9, 3, 1, -2, -4, 3, 4, -1, -6, 3, 1, -2, -9, 4, 4, -5, 4, -10, 2, -4, -5, -1, 1, 2, 0, 2, -8, 1, 3, -4, -13, 0, 10, -1, -4, 5, 0, -4, 5, -3, 2, -5, 2, 1, 2, 4, 2, 2, -10, 5, 3, -11, -2, 3, 3, 0, -6, -2, 1, 1, 2, -1, -8, -1, -5, -4, -3, 5, 8, -4, -4, 2, 0, -2, -2, 1, -5, 0, 13, -8, -6, 4, 8, -6, -1, 6, -2, 4, -5, 3, 5, -7, -8, -2, -3, 7, 8, -8, -3, 1, 5, -5, -5, 9, -4, -7, -5, 4, 3, -6, 5, 1, -1, 3, 0, -6, -9, 0, -6, 1, 4, 10, 5, -13, 0, 6, -2, -4, 2, -2, 6, -1, -4, 0, -11, 6, 3, -1, -3, 14, -1, -15, 1, 2, 3, -1, 4, -3, -6, 0, 3, 0, -6, 10, -3, -14, -2, 10, -3, -9, -4, 0, 6, -1, 7, -3, -5, -6, 1, 0, -5, 11, -2, 1, -2, 5, -1, -4, -1, -3, -4, 2, 11, 2, -4, 1, 2, -12, 7, 3, -1, -11, 3, 15, -8, -11, 0, 0, 2, -7, 1, -3, -4, -3, -5, -4, 6, 11, -7, -8, -1, 6, -5, -3, 6, 8, 3, -6, 1, -1, -1, -1, -5, -3, 8, 7, 4, -9, 1, -2, -4, -6, 9, -4, 3, -8, 0, 6, -2, -4, -2, -2, -6, 8, -7, 3, 1, 3, -1, -3, 2, 1, -6, -9, 3, -5, 8, 5, -10, 7, 5, -3, -2, -1, -3, -1, -4, -7, 6, 6, 3, -7, 0, 0, 1, 0, -7, 3, -1, 0, 1, 2, 2, 2, -11, -8, 9, 6, 2, -6, -1, 1, -3, 3, 1, -6, 2, -3, -2, -1, 2, -4, 0, -4, -2, 0, -3, -2, -6, 5, 2, 0, -1, -3, -1, 3, 1, -2, 0, 2, 2, 0, 1, 7, 1, -4, -2, -6, 4, 3, -1, -4, -1, 3, 3, -9, -2, 0, -2, -1, -5, 6, 1, -5, 1, -5, 9, -10, -4, 0, -4, 6, 1, -3, -5, 9, -2, -5, 2, 0, 6, -6, 2, 5, 10, -8, -3, -2, -1, 4, -3, -1, -4, 0, -1, 1, -4, 0, 5, -8, -1, -5, -1, -1, 3, 3, 3, 2, -14, -5, 1, 2, 3, 1, -1, 2, 5, -2, 2, -5, 2, 3, -2, -2, -3, 4, 4, 4, -6, 3, 1, -10, 1, -6, 6, -2, -3, 0, -3, 1, -3, 1, -1, -4, -5, -4, 7, -2, -2, -3, 6, -5, -5, 2, -6, 1, 4, 3, -8, 11, 4, -4, -1, 2, 3, -5, -2, 1, 7, -4, 2, 4, -10, 7, -7, -1, 0, -3, 5, -4, -1, -4, 5, -7, 3, 3, -11, -2, -1, 5, 1, -1, 0, 6, -11, 0, 1, -2, 1, 0, -1, -4, 2, 9, -2, -9, -4, 2, 0, 2, -1, 1, 1, -7, 5, -3, 4, -1, -3, -8, 5, 7, -1, -1, -3, 3, -7, 0, 4, -3, -3, 1, 6, 0, -1, 0, -5, -1, 0, -4, 0, 0, -3, 1, -4, 1, 7, -3, -13, -2, -2, -1, 3, 5, 2, -6, 1, 6, -2, -6, 8, -1, -6, 0, 4, 6, -2, 0, -2, -4, 3, 5, -4, -7, 2, 5, -3, -3, 3, 1, -10, -7, 3, 1, -3, 2, 4, -7, -3, 0, 2, -5, -3, 3, -2, 0, 3, 5, -6, -1, 4, -2, 0, 5, 1, -2, -2, 3, 2, -1, -3, -3, -7, 7, 3, -1, -2, 0, 0, 1, -2, 1, 0, -15, -1, 3, 2, -3, 4, 0, -7, 0, -1, -1, -4, -3, 2, -1, -1, 11, -3, -1, -5, -1, 2, 2, 0, 1, 2, 3, 4, -6, -3, -2, 1, 0, -4, 2, 1, -1, -5, 1, -1, -7, 2, -2, -5, 0, 2, -2, 3, 5, 0, -2, -6, 6, -7, 3, -4, -6, 1, 6, 3, 1, -2, -3, -4, -6, -1, 7, -2, 0, -3, 0, 9, -3, -5, -1, 3, 0, -1, -3, 6, 1, -6, -3, 3, 6, 0, -6, -4, 2, 1, -1, 2, -5, 4, 1, -2, -5, 0, 7, -9, 3, -1, 1, -6, 0, -5, -1, 1, -1, 0, -4, 2, -2, -2, 1, 6, -1, -5, 0, 0, 0, 1, 3, 2, 2, -1, -3, 0, 1, 5, 1, -5, -7, 2, 6, -3, -3, -3, 2, -7, -5, 5, 0, 0, -3, -4, -1, 3, -4, -5, 1, 5, -1, -2, -4, 0, 5, 2, 0, 2, 2, -1, -1, -5, 5, 3, -1, -4, 1, 0, -1, -2, -1, 2, 2, -4, -4, 2, -2, -3, -4, -3, 0, 3, -3, -2, -2, 4, 1, -2, -2, 1, 2, -6, -1, 2, 6, 1, -2, 0, 4, -3, -1, -2, -1, 5, 1, -11, 4, 3, -1, -6, 2, -2, 3, -4, -8, -2, -1, 4, 0, 3, -2, -1, -2, -2, 1, 3, 3, -7, 0, 2, 10, 0, -4, 3, -3, 0, 0, 3, -4, 6, -4, -8, 2, 1, 3, -14, 1, -1, -2, 0, 0, -5, -1, 2, -6, -1, 3, 0, -5, -3, 3, 1, 6, -2, 0, 6, 2, -7, 1, 3, -5, 5, 8, 0, -1, 1, -4, -6, -2, 6, 4, -4, -1, 1, -10, 0, -4, 0, -3, 2, 0, -8, 3, -3, 0, 2, -1, 1, -8, -1, -1, -3, -1, 4, 1, 6, 1, 0, 0, -2, 0, -2, 7, -4, 3, -1, 2, 0, -2, -2, -8, 3, 2, -1, -4, 3, 0, -3, -5, 2, -3, -3, -2, 5, 2, 1, 1, -4, 1, -1, 4, 6, -4, 0, -6, -4, 1, 3, 3, -1, -2, -7, -1, -3, 6, -6, 2, 1, 5, -8, -5, -1, 2, -1, -3, -1, -1, 5, -7, 3, 3, 1, 4, -4, -3, -3, 8, 1, -2, 4, 4, -2, -8, 2, 1, 0, 2, 0, -6, 3, -2, -8, -2, 5, -1, -6, 0, 2, -1, -5, -2, -2, 6, 0, -5, -2, 3, 0, -5, -1, 6, 7, 2, -8, -4, 6, 2, -6, -4, 12, 2, -5, -2, -6, 1, 1, -3, -7, -3, 11, -3, -6, -1, 3, -2, -4, -4, 4, -3, 4, -2, -3, 1, 7, 0, -8, 7, 1, -2, -4, -6, 13, 0, -3, 1, 2, -1, -4, -3, 1, 3, -2, -3, -1, 0, 3, -1, -10, -1, 2, -8, -3, 3, 2, 1, 4, -6, -2, 1, -3, -1, -4, 6, 5, -1, -5, -1, 9, -2, 0, -4, 0, 1, -3, 4, -5, 1, 3, -4, -6, 0, 4, -2, -6, 9, -1, -3, 2, -4, 0, 4, -7, -4, -1, 1, 4, 0, -1, 6, -2, -2, 4, -3, -1, -6, -2, 2, 3, 1, -3, 8, -10, -10, 7, 0, -2, -1, -4, 3, -6, 0, -5, -5, 5, 3, -6, 1, 5, 0, -1, 1, -1, 0, 0, 0, -5, 7, -2, -1, 2, -1, 3, 0, -6, 4, -3, -2, -3, -2, 1, 3, 3, 0, -2, -1, -9, 2, 2, -1, 4, -4, 4, -10, 7, -8, 2, 1, -1, 0, -1, 4, 2, -7, 7, -6, -4, 3, 11, -5, -6, 1, 3, -4, -6, 2, 2, -2, -3, -7, -4, 6, 0, 7, -13, 6, 2, -9, -2, -5, 3, 8, 0, 0, 5, -5, -4, 3, 0, 2, 4, -7, 0, -1, 10, -3, -6, 7, 2, -1, 0, 6, -2, -7, 4, -2, -1, -2, 1, -3, -9, 6, 0, -4, 0, 3, 3, -11, -4, 7, -16, -2, 0, 2, 1, -2, 2, -5, -1, 12, -6, 2, -7, 2, 6, 0, -4, -1, 1, -3, 2, -1, 0, 7, -2, 2, -6, 2, 7, -9, -4, 8, 2, -9, -3, 8, 1, -1, 4, 5, -11, 2, 1, -1, 0, 0, -6, -2, 2, 6, -13, 2, -3, -8, 1, 1, 3, -2, -3, -2, -7, 4, -6, -2, 3, -10, 5, -2, 1, -3, 5, 8, -4, -1, 2, -1, 6, 2, 3, 2, -2, 0, -1, 0, 4, 1, -1, -2, 7, 1, -7, -5, 7, -5, 2, -5, -4, 0, 3, 3, -2, 0, -1, -9, -4, -9, 10, 1, -14, 0, -1, 6, -8, -3, 3, -1, -6, -1, 5, 3, -5, -1, 3, -6, 5, 7, -10, 5, 5, 2, -4, -3, 9, 4, -11, 0, 5, -11, 7, -6, 2, 2, 12, -15, -8, 2, -3, 7, -5, 3, 3, 1, -10, 0, -9, 17, -11, 7, -6, 2, 1, -3, 0, -1, 5, -2, -10, -4, 16, -1, -7, -1, -3, 1, 11, -3, 1, -3, 2, -12, -2, 12, 3, -1, -10, -2, 6, -3, 1, -1, -4, 12, -1, -2, -7, 6, -1, -1, -16, 5, 11, -3, -7, 1, -1, -2, -6, -4, -5, 3, 4, -3, -8, -1, 3, -5, 3, 1, 2, 6, -10, 1, 7, 0, 21, -15, 11, -12, 0, 1, 4, 1, 4, -4, -1, 3, 7, 0, -5, 10, -15, -14, 2, 6, -11, 5, 3, -10, -6, -1, -11, 4, -9, 6, -9, -2, 2, -8, 3, 0, 2, -9, 7, 7, 2, 2, 0, 3, 1, 6, 0, 3, 6, -10, 6, -4, 1, 7, 9, -1, 0, -7, 1, -11, -8, 9, 4, 0, -6, 2, -16, 0, 1, -2, -16, 10, -7, -12, 7, 4, -1, -1, -4, 2, -1, 2, -5, 8, 3, 3, 4, -2, 4, 3, 2, -4, -2, -1, 5, -5, -3, 9, 2, -22, 8, -6, 1, 3, -5, -4, -6, 7, 0, 5, -8, 9, -13, 0, -6, 18, -3, -3, -1, -6, 7, 3, -11, -9, 19, 6, -10, -6, 3, 12, -2, -18, 7, 8, -7, -10, 14, -8, 5, 1, -15, -4, 11, -6, 9, -8, -1, 5, 1, -6, -2, 7, -3, 7, -20, 6, 5, -4, 3, 12, -12, 11, -4, -22, 7, 9, -13, 1, 0, -8, -1, 9, 6, -10, 5, -9, -5, 8, 5, 8, -12, -4, 16, -14, 7, 6, -1, -16, 21, 2, -9, 13, 5, -4, -19, 2, -3, 12, -7, -2, 3, -2, -4, -3, -8, 4, 1, -4, -4, -14, -3, -1, 1, -11, 30, -11, -16, 8, -2, -9, 8, 8, -1, -1, -5, 10, -4, 1, 4, 3, -8, -1, 23, -2, -2, 14, -15, -7, 7, -7, 0, 9, -12, 8, -10, 0, -3, 16, -13, -11, 5, -1, -10, -2, 6, -5, -4, -9, 10, -6, 7, 1, -13, 2, 14, -9, -3, 2, 6, 4, 8, -8, -2, 0, 2, -3, 14, 3, -10, -4, -8, -1, 10, -13, -8, 15, -9, -3, -2, 5, -5, -6, -9, 9, 7, -4, 14, -7, -18, 12, 1, 2, 1, 4, -2, -6, -3, -2, 5, 7, -2, 0, 0, -4, 0, -6, 1, 5, -5, -4, 5, -6, 5, -4, -8, 15, -5, -6, 0, 3, -8, 0, 3, 0, -1, 0, -4, 6, -16, 22, -7, 3, -5, 2, 2, 1, -3, 4, -8, 4, 4, 0, -5, -9, 4, -5, -4, 3, 2, 1, 3, -4, 6, -15, -1, 4, 1, -9, 3, 1, -8, 3, -6, 11, -5, 6, -11, 17, -15, -2, -19, -11, 1, -4, 8, 0, 5, 18, -11, 0, 13, -4, 6, -13, 4, -11, -1, -7, -7, 11, 10, -9, 17, -11, 20, -6, 7, -14, 23, -7, -2, -2, 7, -10, 2, 0, 2, 5, 6, -8, 5, -4, -10, 9, -4, 6, 0, -7, 8, -7, 1, -20, -4, -1, -3, 6, -10, -6, -15, -11, 10, -5, 19, 3, 1, -19, -11, -1, -9, 9, 22, 24, 10, -5, -18, -8, -23, 14, 11, 0, 31, 43, -9, 0, -7, -15, -28, -35, -30, 3, 5, -5, 11, 52, 55, 7, -5, -10, -12, -25, -43, -12, 4, -37, -47, -21, -5, 4, -11, 1, 31, 27, 34, 46, 48, 61, 10, 16, 8, 7, -14, -40, -47, -36, -51, -42, -15, 4, 12, -32, -42, -10, -4, 10, 1, 15, 50, 31, 5, 15, 38, 37, 29, 15, 22, 11, -4, -35, 10, 3, -18, 1, -14, -33, -5, -47, -25, -13, -2, 15, -6, 5, -29, -17, -19, -1, 3, 7, 2, 17, 28, -8, -23, 7, 7, 36, 15, 2, 1, -2, -9, 1, 6, 20, 6, 14, -3, 21, -11, -12, -35, 11, -20, -18, -36, -23, -27, -19, 1, 10, 14, 27, 6, 44, 14, -9, 3, 20, 27, 45, -8, -13, 16, -16, 24, -10, -9, -3, -38, -19, -14, -38, -38, -41, 13, 40, -37, 5, -7, -7, -4, 4, -31, 32, 22, 15, 9, 13, 10, 10, -17, 22, 30, 9, -6, 27, 66, 47, -17, -21, -20, -9, -36, -73, -3, 22, -35, -12, 6, 7, 4, -17, -45, 22, 17, -17, 3, -9, -4, 11, -10, 13, -4, 8, 38, 3, 20, 42, -22, 9, 23, -28, -21, 3, 10, 1, 26, -28, -18, -9, 7, -30, -41, -24, -9, 10, -6, 31, -5, 2, 29, -9, 1, -27, -24, 7, -19, -5, 10, -13, 21, 21, 3, 30, -11, -17, 34, -11, 8, 7, -8, 1, 11, -1, 7, -13, 1, -3, 23, -12, 8, -19, -3, 20, -78, 42, -23, 4, -29, -16, -5, 38, -49, 30, -26, 26, 16, 8, -33, 53, 19, -20, 12, 5, 23, -11, 4, -6, 42, -111, 67, -40, 29, -32, -20, -77, 113, -46, -12, 8, -5, -14, 35, -52, 94, -5, -61, 58, -36, 41, -83, 21, -19, 61, -68, 37, -37, 12, 66, -69, -16, 100, -88, 48, 21, -39, 73, -24, -2, 45, 65, -59, 53, -103, 95, -97, 1, -14, -4, -41, 9, -13, -18, 16, -26, 9, 26, -15, 25, -16, 6, 8, 26, -52, 35, -21, 4, -2, -11, -4, 22, 0, 21, -40, 65, -6, -13, -11, -7, 32, -46, -48, 16, -26, -3, 0, -42, 87, -68, 34, 17, -14, 43, 23, -15, 30, 20, 47, -19, -33, -12, 15, 1, -37, 15, -12, -11, -7, 15, -75, 36, -41, 27, -8, -7, -12, 10, -4, 49, -6, 42, -32, 4, 20, 33, -65, 24, -52, 10, 13, -17, -15, 60, -14, -55, 35, -16, 50, -83, -3, 29, 58, -75, 71, -46, 47, -32, 44, -57, 10, -43, 33, 22, -48, 51, -41, 6, 7, 39, -3, -41, 7, -9, 37, -66, 22, 26, -13, 74, -87, 127, -39, -16, -29, -11, -8, -57, -15, -45, 52, -74, -5, -2, 103, -126, 85, 20, 28, -7, 53, -38, 58, -10, -11, 33, -70, 20, 1, 40, -36, 26, -58, 58, -23, 61, -71, -7, -39, 43, 22, -18, -1, -61, 90, -37, 35, -58, 30, -62, 27, -45, 47, -59, -6, -35, 70, -49, 9, -30, 92, -15, 21, 1, 26, 6, -19, 90, -43, 49, -46, 10, 6, 15, -90, 67, -51, -11, 4, 28, -36, 24, 41, -68, 24, -34, 63, -40, 17, -30, 18, -39, 14, -38, 15, 9, -54, 54, -20, 36, -21, -14, -13, 11, 23, 11, -54, 56, -25, 37, -46, 49, -74, 81, -40, 51, -44, 57, -69, 51, -50, 61, 27, -112, 111, -114, 106, -85, 49, -61, 75, -18, 26, -68, 32, -15, -25, 21, -15, 38, -46, 80, -119, 126, -85, 41, -40, 77, -65, 28, -6, -39, 45, -87, 39, -63, 81, -32, 4, -32, 44, -25, 42, -12, -15, 21, -1, -56, 21, 23, -30, 33, -28, -3, 32, 4, -36, 60, -20, 13, -3, 22, -43, 101, -88, 59, -53, 18, 8, 22, -33, -52, 34, -32, 35, -90, 112, -107, 56, -59, 43, -60, -18, -4, -21, 45, 11, -48, 11, 38, -27, 58, -49, 65, 19, 54, -38, 35, -37, 24, -11, 44, -62, 41, -16, -48, -8, 31, -68, 17, -3, -5, 52, -51, -10, 16, -26, 18, -29, 56, -41, 3, 5, -10, -37, 61, -14, -10, -9, 20, -8, 8, -2, -16, 44, -17, 14, -33, 30, -2, -27, 16, 3, 0, 51, -42, 32, -20, 8, -11, -24, 10, 12, -15, 6, -32, 10, 21, -38, -11, -12, 23, 13, -64, 19, 34, -23, -23, 16, 10, 39, 2, -36, 55, -31, 0, -29, 18, 8, 12, -61, 73, -28, 54, -34, 21, 9, 7, 53, -34, -29, 19, -7, -44, 7, 15, -16, -18, -31, 10, -29, 36, -69, 7, 4, 33, -72, 45, 14, 0, -8, 35, -13, 26, 16, -28, -3, -32, 45, -4, 8, -20, 65, -24, 2, -24, 40, -16, -16, 20, 8, 2, -3, -2, 23, -15, -11, -30, 19, -51, -19, -5, -36, 18, 24, -4, -1, 46, -90, 60, 4, 23, -17, 16, 60, -24, 0, 18, 0, 5, -6, -24, 27, -34, -28, -7, -4, 22, -30, -11, -3, -1, -44, 36, -38, -6, -9, 55, -34, 16, 27, 28, -65, 62, 22, -32, 36, 7, 2, 27, -19, 50, -71, 44, -19, -67, 13, -3, -14, -30, 33, 5, -12, -48, 60, -47, -28, 9, -6, 24, -11, -1, 13, 62, -53, 26, 7, -9, 6, 58, -38, -10, 0, 5, -23, 23, 8, -14, -19, 21, -9, 35, -17, -28, 14, 27, -17, -14, -29, 24, 6, -85, 74, -16, -18, -2, -19, 47, -29, -18, -15, 52, 0, 7, -10, -23, 45, 13, -11, 12, -28, 27, -26, 19, -69, 74, -55, 35, -21, 41, -24, -11, 39, -19, 7, 0, 7, -31, 10, 7, -45, -17, 25, -12, 9, -19, 3, 28, -53, 76, -19, -25, 49, -2, 6, -11, 24, -12, -23, 17, -1, -15, -10, -36, 26, -25, 0, -44, 59, -67, 45, -31, 5, 15, 56, -12, -14, 12, 10, 24, -52, 37, 5, -35, 52, 23, -55, -6, 24, -49, 26, 31, -24, 10, -33, 33, -11, 1, -49, 8, 7, 6, -78, 12, -22, 10, -11, 13, 13, -18, 38, 50, -18, -5, 64, -52, 59, 33, 3, -9, -6, -6, 26, -64, 18, -38, -47, 18, -33, 4, -39, 40, -31, -1, -23, 48, -30, 18, 17, 32, -20, 32, 19, 24, -58, 49, -38, -9, 15, -28, 16, -3, -2, -28, 33, -22, 23, -1, -34, 33, -48, 67, -55, 21, 51, -66, -2, 21, -5, -17, 24, -63, 53, 8, -19, 9, -11, 36, -37, -35, 43, -35, -3, -44, 68, -43, 53, -24, -5, 45, -16, -7, 14, 49, 3, -16, 22, -10, 2, -28, -9, -6, -5, 32, -76, -22, 35, -26, -35, -12, 0, 3, 13, 6, 36, 7, -32, 69, -15, 45, -20, -21, 35, 35, 1, -25, 11, 34, -24, -33, -9, 5, -25, -49, 31, -41, 15, -42, 25, -30, 42, -80, 32, 2, -18, 33, -12, -9, 43, -1, 4, -12, 54, -51, 22, -1, 18, 28, -29, 18, 7, 10, -19, 8, -1, 12, -21, -6, -11, 4, 4, -28, -8, 22, -27, -5, 9, -25, 20, -19, -36, 41, -8, 20, -32, 16, -29, 29, -13, 13, 4, 1, 17, 8, 0, 9, 22, -1, -3, 28, -11, -39, 36, -31, 5, -11, -27, 22, -39, 7, 15, -24, 19, 8, -37, 75, -52, 54, -65, 22, -13, 23, -26, 32, -19, 10, -8, -3, 12, 16, -44, 25, -23, 14, 9, -46, 20, 2, -4, -8, -6, 18, 4, -2, -3, -15, 4, 16, -9, -5, 34, -29, 27, -54, 98, -65, 11, -18, 16, -13, 0, -2, 0, 22, -43, 31, -46, 58, 2, -25, -2, 16, -2, -29, 17, 18, -26, 21, -17, 5, -4, -9, 0, -34, 50, -27, -3, 4, 31, -3, -47, 32, -25, 36, 6, -47, 33, -28, 39, -36, 42, -28, 5, -3, -2, 25, 27, -47, 20, 22, -5, -15, 1, -9, 16, -25, -10, -43, 40, -12, -19, 22, -24, -5, 14, -44, 42, -32, 32, -45, 40, 41, -17, 27, -44, 38, -16, 15, -36, 39, -13, -19, -4, 34, 1, -9, 9, -16, -2, -29, 31, -31, -4, 35, -21, -52, 63, -41, 2, -7, 30, -35, 13, 9, 15, -4, 14, -36, 18, -14, 55, -50, -6, 22, -23, -11, -5, 12, 17, -13, -43, 44, -33, 41, -42, 45, 3, -12, 26, 11, -11, 35, -76, 39, 2, 0, 3, -4, 15, -19, -6, -33, 11, 5, 16, -25, -2, 19, -7, -43, 30, 20, -27, -18, 12, 14, 33, -50, 14, -15, 23, 8, 2, -10, -4, 53, -86, 24, -9, 41, -34, -21, 22, 24, -54, 27, 13, 2, -9, 14, -29, 21, 40, -43, -9, -3, 27, -3, -22, 18, 10, -23, -15, 1, 14, -12, 3, -30, 30, -22, -28, 36, -15, 39, -57, 21, 3, -3, 33, -13, -2, 6, 20, -6, 4, -13, -5, -18, 13, -7, 7, 26, -26, 16, 7, -64, 37, -7, 10, -20, 12, -11, 7, -34, 37, -12, -24, 34, -18, -18, 39, 9, -42, -24, 43, 2, -16, 25, 12, -16, 8, 12, -44, 32, -9, 23, 1, -37, 40, -23, -17, 18, -42, 23, -12, -7, 10, -6, 6, -13, -13, 30, -23, 36, -4, 7, 17, -18, 18, -3, 8, 5, -1, -13, -15, 2, -5, -16, 7, -52, 23, -38, 30, -30, 16, -26, 21, -22, 24, 3, 20, -28, 22, 22, -31, 42, -16, -11, 32, -26, 0, 31, -14, 11, -15, 14, -17, -9, 10, 11, 27, -38, -4, 14, -18, 36, -44, 0, -11, 16, -14, -2, 16, -34, -23, 22, 4, -24, 14, -13, 16, 31, -28, -10, -6, 51, -27, 13, -49, 3, 68, -38, 1, 8, -27, 26, -16, 0, 15, -36, 7, -6, 38, -11, 0, -14, 10, -4, 22, -48, 31, -1, 23, -38, 1, 15, -7, 10, -1, -3, 4, -1, 10, -2, -12, 3, -22, 5, 9, 8, 4, -14, 12, -3, -7, 22, -20, 3, -6, 13, -15, -8, -7, 16, -14, -1, -3, 6, -17, 12, 22, -44, 68, -67, 50, 13, -20, -11, -4, -20, -3, 22, -13, -20, 28, -7, 2, 11, -9, -23, 5, 5, -26, 24, -31, 2, 20, 15, 2, -7, 4, 19, -6, 41, -51, -3, 24, 27, -30, 25, -37, 1, -7, -2, -4, -26, -1, 12, 5, -12, 9, -30, 5, 11, 26, -18, -32, 42, 7, 0, -23, 10, 10, -20, 53, -49, 6, -39, 18, 3, -27, 41, -21, 16, 28, 14, -24, -15, 19, 5, 16, -31, -1, 45, -25, -6, -16, -4, -19, 37, -47, 21, 2, -14, -7, 30, -35, 13, -30, 14, 21, 11, -18, -28, 37, 12, -18, 9, 5, -1, 33, -41, 3, -7, -19, 8, -14, 12, 15, -18, -4, 44, -25, 22, -46, 19, 40, -25, -12, -5, 17, 7, -53, 25, 4, -10, 14, 16, -31, 40, -27, -11, -4, 28, -40, -5, -9, -3, 34, -47, 33, -5, 11, -33, 33, 0, -14, 35, -18, -27, 11, 14, -37, 35, -20, 7, 15, 2, 27, -17, 15, -31, -1, 11, -27, 24, -26, 14, 13, -35, 20, -13, -2, 16, 16, -6, 2, 15, -7, -22, 51, -36, -2, 20, -19, 23, -20, -19, -9, -14, 8, -4, -13, 35, -66, 36, -37, 3, 19, -1, 15, 32, -45, 71, -15, -5, 12, 34, -33, 24, -5, 20, -43, 42, -59, 13, -12, -69, 66, -29, -34, 17, 7, -28, 24, 5, -27, 51, -40, -9, 46, 3, -17, 36, -56, 63, -7, -31, -19, 53, -12, -10, 4, 19, -47, 35, 0, -40, 17, -14, 13, -11, 11, 3, -39, 22, 5, 21, -19, -11, 25, -4, -5, 20, -13, 25, -6, -16, -16, 29, -61, 25, -33, 12, -17, 7, -19, 34, -27, 15, -19, 32, -26, 54, -46, 6, 9, 14, -6, -6, 23, -32, 58, -19, -5, 15, 46, -42, 39, -7, -23, -7, -14, -22, 42, -66, 0, 4, -8, -11, -4, -3, -7, 7, -23, 30, -14, 19, 8, -9, 20, 36, 5, -24, 25, 12, -20, 16, -53, 60, -49, -26, 24, -87, 67, -49, 13, -7, 5, -14, 5, 11, 38, -3, -15, 27, 26, -36, 20, 30, -47, 29, -5, 9, -10, 38, -65, 47, -49, -4, -10, -6, 1, -1, -28, 16, -14, 3, -14, 27, -8, 1, 2, 23, 21, -53, 40, 24, -16, -12, -2, 11, 17, -8, -18, 8, -25, 28, -10, -12, 13, -51, 10, 35, -10, -8, -9, 8, 10, 14, -20, 4, -9, 37, -5, -2, 2, 4, -9, -5, 16, -16, -23, 13, 7, -9, 14, -49, 13, 8, -3, -13, -9, 22, -8, 12, -13, 36, -36, 35, -17, 23, -12, 0, -37, 50, -31, -8, -31, 43, -4, -11, 0, 3, -7, -19, 16, -16, -28, 46, -28, 27, -13, 33, -21, -1, 39, -13, 3, -4, 4, -39, 74, -30, -17, 33, -3, -20, -12, 24, -94, 75, -63, 54, -62, 23, 4, 12, -33, 22, -35, 16, 12, -28, 34, 2, -12, -3, 22, 23, -31, -6, 26, 4, -41, 8, 37, -15, 21, -7, 18, -51, 42, -27, 35, -45, 35, -30, 18, 9, -20, 1, 18, -12, -51, 61, -61, 24, -20, 1, 11, -5, -2, -12, 11, 20, -35, -2, 37, -21, 23, -15, -2, 19, -51, 82, -50, 20, 29, -26, -34, 49, -2, -16, 11, -17, -4, 6, 15, -35, 13, -15, -10, -17, 15, 4, -42, 43, -31, 34, -30, 53, -43, 40, -22, 9, 9, -24, 64, -41, 29, -17, 8, -15, 8, 2, -27, 7, 10, -28, 0, 30, -50, 6, -13, -14, -21, 11, 9, 13, -47, 35, -11, 32, 28, -28, 1, 32, 2, -19, 28, -24, 9, 0, 19, -6, 16, -33, 6, -23, 33, -31, -1, -4, 26, -22, -22, -10, -11, 18, -26, 19, -8, -4, 21, -14, 36, -2, 12, -48, 49, -1, -13, -5, 8, -3, 9, -4, -18, 15, 28, -50, 10, 4, -7, 4, -39, 37, -39, 11, 2, -20, 13, 4, -6, 0, 35, -17, -9, 6, 38, -21, -1, -1, 12, -2, -16, 15, 7, -22, 18, -23, 11, 3, -9, -39, 29, -31, 44, -41, 0, 5, 21, -9, -25, 25, -6, 38, -55, 38, -14, 6, -26, 38, -24, 39, -39, -15, 17, 16, -20, -27, 17, 24, -20, -20, 33, 8, -31, 2, 2, 27, 11, -4, -7, 31, -20, -9, 4, -4, 17, -32, 2, -18, 31, -35, 38, -52, 42, -1, -28, -26, 25, 3, -51, 42, -35, 35, -39, 44, -38, 20, 20, -51, 34, 45, -10, -7, 27, -19, 33, -49, 22, 2, -7, -5, -27, 59, -24, -20, 21, -8, -15, 24, -51, 3, 9, -23, 24, -30, 2, 29, -26, -2, 4, 10, 0, -18, 50, 3, 9, -14, 17, -18, 24, -13, -33, 7, 25, -50, 2, -2, 30, -58, 31, -8, 23, -11, -1, -24, 21, 1, -41, 47, -30, 28, -39, 56, -16, -20, 51, -45, 33, 6, 23, -12, -19, -2, 7, 1, -14, -5, -11, -20, 25, -17, 7, -22, 21, -19, 34, -47, -2, 1, 33, -30, 14, 20, 6, -9, 17, 13, -22, 19, -58, 23, 26, -15, -52, 2, 18, 10, -13, 46, -5, -8, -6, 4, -14, 5, 11, -13, -7, 42, -25, 8, -37, 35, -10, 6, -25, 16, 15, -15, -9, -20, 18, -23, 26, -34, 35, -22, -10, 9, 14, -6, -21, 27, -8, 4, 1, 3, -19, 28, 2, -7, 30, -8, -13, 11, -9, -9, -19, 12, 0, -23, -1, -23, -6, 27, -31, 41, -28, 13, 5, 9, -21, 6, 2, -2, 18, -16, 31, -25, 40, -38, 39, -13, 8, 14, -3, 9, -30, 6, -12, -7, -15, 30, -64, 6, -22, 13, -8, 14, -40, 9, 32, -35, 14, -1, 12, -25, 63, -25, 35, -2, 19, -5, -3, 20, -29, -1, 35, -37, 53, -46, 4, -14, 22, -27, 23, -64, 8, 5, -25, 41, -18, 14, -42, 53, -56, 35, -42, 71, -63, 45, -38, 29, -12, 33, -22, 0, 24, -13, 3, 13, 1, -10, -19, 11, 19, -38, 5, -2, -18, -21, 33, -54, 41, 9, 4, -1, -21, 3, 3, 37, -31, 34, -40, 34, -19, 30, -26, 23, -53, 55, -8, -13, -16, 7, -13, 46, -38, 2, -3, 17, -1, -26, 18, -57, 68, -27, 23, -19, 32, -39, 2, 2, -18, 12, -16, 4, -23, 38, -65, 40, -5, 13, 19, -26, -13, 60, -25, 7, 1, 10, 22, -24, 23, -20, -16, -17, 14, -32, 26, -4, 17, -15, 9, -29, 4, -29, 11, 36, -18, -19, -2, 5, 28, -23, 31, 6, 4, 18, -14, 4, -7, 0, -45, 61, -31, 5, -15, -23, -21, 52, -62, 4, 22, 1, -9, 15, -24, -27, 60, -49, 38, 0, -6, 1, 13, 7, 4, 19, 6, 0, 27, -28, -14, -21, 17, -1, -30, 23, 10, -36, 18, -19, 2, -18, 0, 6, -1, 7, -1, -37, 26, 15, -35, 41, -24, 10, 10, -9, -12, 12, 7, 3, 10, -11, 11, -14, 27, -49, 71, -55, 25, 8, -11, 11, -5, -22, 7, 15, -17, -11, 18, 4, -54, 43, -38, 27, -1, 7, -13, 19, 10, -41, 50, -41, 13, 9, 10, -41, 38, -13, 13, -2, -2, -4, 9, -36, -5, 22, -31, -18, 8, 21, -22, 21, -24, 12, 3, 16, -24, 25, -16, 22, -35, 14, 3, 11, 12, -22, 40, -11, -25, 14, 0, 14, -2, 2, -10, -12, 14, -51, 11, -21, 55, -27, 9, 3, 38, 7, -25, 5, -19, 6, -14, 0, -10, 21, -57, 35, 18, -21, 21, -40, -13, 24, -24, -12, 10, -1, 11, 10, -12, -5, 38, -45, 23, 26, -13, -9, 32, 6, -3, 30, -28, -28, 27, 3, -10, -11, -10, 16, -28, 21, -12, -3, -1, -33, 14, -30, 12, -20, 40, -15, 7, 19, -18, -1, -1, 9, 4, -23, 32, 17, -19, 12, 16, -45, 4, -6, 18, -28, 36, -44, 44, -29, 10, 4, 14, -8, -13, 9, -30, 39, -17, -5, 10, -10, 5, -1, -16, 17, -7, -9, -10, 15, -21, 9, 10, 8, -10, -6, 3, -21, 34, -3, 6, -4, 15, 3, -2, 4, 26, -44, 30, -43, 2, 9, -5, -7, -18, 16, -28, 0, 5, -7, 0, 7, 0, -7, 21, -14, 17, 15, 2, -40, 7, 44, -30, 55, -33, -19, 40, -30, 17, -1, -20, -20, -20, 5, 14, 1, -7, -32, 26, -11, -11, 24, -23, 17, 17, 8, -19, 18, 11, -6, 17, -4, -13, 14, -9, 21, 9, -16, -8, 2, -16, 3, -9, -32, 6, -36, -4, 0, 10, -36, 26, -11, 3, 31, -20, 1, 7, 4, 45, -35, 39, 0, 4, 28, -21, 29, -39, 27, 15, -6, -14, 17, -25, -33, 16, -15, 18, -43, 28, -61, 33, 1, -27, 13, -19, -20, 26, 11, -27, 16, -21, 33, -13, 43, -44, 13, 24, -10, 35, -39, 36, 20, -39, 68, -68, 23, -16, -7, 0, 36, -30, -13, -27, 42, -21, -4, -23, -2, 23, 0, -3, -3, 2, 4, -15, -5, 28, -10, -20, 24, -7, 27, -58, 31, -7, -29, 39, -40, 41, -35, 8, -25, 30, 31, -17, -9, 3, 36, -8, -18, -11, 29, -2, 6, -25, 21, -5, -8, -17, -24, 20, -26, 20, -23, 46, -26, -13, 8, 13, 2, -15, 4, -9, 28, -25, -19, 49, 18, -50, 45, -11, -17, 5, -61, 15, 4, -22, -1, 22, 23, 33, -55, 46, -25, 37, 18, 2, -9, 11, -47, 23, -8, -25, 37, -32, 2, 5, 12, -18, -5, 19, -27, -7, 20, -40, 32, -44, -21, -29, 58, 8, -9, 57, -28, 29, -32, 14, -14, 4, 23, -33, 16, -4, -16, 21, 38, -37, 23, 10, -32, 17, 17, -12, -59, 9, -3, -12, 22, -13, -8, -26, 16, 1, 33, -9, -17, 16, -7, 21, -44, 26, 5, 35, -36, -1, 13, 36, -36, 39, -36, 17, -13, 2, -33, 20, -13, -51, -2, 9, -2, 35, -21, 19, -20, 18, -19, -5, 30, -39, 30, 22, -35, 74, -52, 33, -15, 17, -21, -13, 11, 6, -25, 25, -31, 29, -18, 18, -52, 40, -11, -17, -26, 56, -56, 69, -53, -14, 32, -10, -8, -2, 18, -14, 20, -18, 20, 22, -27, 0, -25, 56, -46, 16, -28, 52, -5, -33, 76, -75, 36, -1, -42, 42, -46, 13, -13, 25, -7, 35, -55, 5, 63, -56, 11, -24, 13, -8, -10, -27, 15, -15, 44, -66, 52, -3, -6, 0, 23, -33, 79, -55, 30, -27, 37, -18, -6, -2, -19, 52, -22, -50, 60, -32, 28, -56, 44, -28, 15, -37, -9, -28, 63, -75, 9, 39, 28, -21, 5, -17, 15, 2, -13, 30, 13, -14, 10, -12, 30, -22, -10, 4, -8, -9, 14, 6, -39, 34, -6, 4, 1, -5, 0, 33, -73, 34, -12, 23, -9, 53, -47, 17, 3, -18, -6, 2, -19, -12, -7, -45, 72, -9, -71, 55, -58, 50, -18, -36, 37, 19, -11, 13, -35, 32, 6, 5, 18, -6, 19, -26, 32, 16, 20, -43, 20, -10, -7, 16, -7, -68, 21, -36, 7, 19, -22, 19, -3, -35, -37, 25, 21, -57, 67, -9, 9, 32, -11, 28, -18, 35, -41, 60, -19, 29, 0, -38, 29, -6, -35, 0, 25, -37, -1, -31, -42, 30, -19, -21, 36, -66, 53, -33, 15, 16, -13, 20, -35, 73, -4, 18, 39, 4, 1, 3, 21, -2, -12, -18, -51, 44, -17, -50, 48, -30, -16, -13, -35, -7, 25, -33, -14, 14, 0, 8, -30, 45, -13, 50, -53, 28, 60, -33, 23, -7, -2, 15, 36, -11, 9, 19, -44, 4, -21, 19, -5, -27, -45, 48, 9, -47, -23, 12, 3, -25, -8, -21, 63, 1, -29, 31, -18, 19, 16, -24, -17, 50, -65, 65, -56, 93, -45, -17, -25, 45, -18, 23, -53, 50, -15, -12, -39, 51, -11, 11, 13, -31, 54, -14, -29, 22, -11, 10, -41, -19, 52, 10, -51, -60, 72, -13, 12, -38, 19, -2, 31, -56, 37, -4, -10, 22, -14, -33, 48, -40, 38, -14, 27, -24, 19, 29, 17, -31, -2, -41, 34, -17, 2, 5, 5, -13, -30, 14, 9, -9, 7, -11, 15, 5, -28, -2, 0, 45, -30, -25, 1, 10, 29, -55, -24, 52, -5, 5, 20, -25, 20, -15, 14, -64, 95, -53, 32, 13, -26, 31, -8, -27, 18, 48, -57, -3, -10, 25, -24, -32, -9, 18, 18, -33, -15, 27, -22, 14, -5, 10, 51, -21, -25, 19, 5, -15, -29, 16, 1, 33, -39, -12, 56, 14, -63, 36, -2, -17, 52, -11, -37, 5, 19, -52, 38, -23, -60, 93, -75, 52, -30, -2, -11, 49, -11, -25, 1, 42, -35, 26, -35, -9, 24, -1, 10, -6, -12, 7, 4, 22, -10, 41, -25, -8, -4, -2, 28, -43, 19, -32, 4, -27, 9, -47, 51, -16, 12, -52, 49, 8, 7, -37, 27, -33, 80, -44, 6, 5, 28, -15, 16, 15, 2, -12, 50, -77, 38, -38, -45, 30, 8, -37, -13, -8, -18, 50, 3, -54, 29, 29, -20, 4, 52, -57, 62, -52, -2, -9, 62, -64, -5, 24, 23, 0, -7, -23, 48, 25, -78, -9, 38, 18, -46, 30, -51, 39, 4, -48, 22, 15, 13, -39, 8, 10, 31, -20, -22, 21, -17, 17, -23, 22, 22, -24, -36, 11, 31, -16, -28, 34, -4, 0, -20, 6, -2, 35, -13, -60, 36, 24, -45, 21, -2, 36, 0, -73, 66, -37, 39, -66, -18, 22, 17, -17, -25, 24, 36, -47, 3, 25, 7, 8, 0, 1, 14, 20, -21, 4, 21, 12, -77, 17, -4, -12, 31, -57, 38, -11, -4, -31, -6, 29, -34, 11, 13, -20, 82, -36, -36, 40, -28, 77, -68, 12, 2, 34, -23, 5, -31, 11, -5, 44, -105, 79, -31, -29, -16, 37, 8, 18, -14, -9, 32, -10, -11, -7, 0, 41, 34, -56, 7, 13, -2, -31, 33, -67, 42, -31, -2, 22, -49, 18, -34, -11, 38, -40, 56, -16, 14, -2, 24, 0, 0, 41, -21, -8, 6, -11, 11, 11, -45, 26, 4, -17, -7, -26, -30, 7, -21, -29, 56, -29, 37, -3, 2, -8, -3, 22, 11, 40, -13, 58, -6, -38, 48, -23, 15, -52, -14, -6, 49, -66, -20, -11, 34, -32, -44, 41, 4, 20, -59, -24, 77, 23, -24, -17, 42, 19, -3, -19, -34, 54, 17, -22, -17, 46, -24, -9, 3, -22, 40, -47, -49, 72, 4, -18, -48, -33, 55, -4, -41, -51, 105, -26, -3, -22, 64, 28, -51, 31, 2, 15, 27, -62, 18, 21, 6, -15, -54, 52, -14, -46, 7, -30, 32, -1, 6, -37, 39, -3, -23, -20, 24, 23, 17, -25, -6, 67, -36, -11, -37, 56, -79, 3, 30, 45, -39, -17, -2, 21, 2, -4, -3, 3, 1, 16, -16, 9, 30, -37, 8, -6, 46, -65, 3, 14, -59, 104, -60, 2, 46, -29, -30, -2, -10, 24, -52, 63, -31, 81, -85, 18, 35, 16, -32, -18, -24, 45, -16, -15, -13, 37, -15, -20, -42, 91, -45, -15, -9, -16, 64, -11, -23, 31, -18, 38, -42, 3, 12, 1, 5, -5, 22, -44, 69, -31, -18, 15, 21, -64, -13, 34, -37, 30, -26, -15, 6, -3, 44, -28, 11, -3, -1, 16, -18, 25, -14, -26, 69, -56, -5, 31, -51, 24, 3, -36, 9, 52, -34, 31, 21, -11, -68, 31, -24, 53, -25, -29, 31, 23, -20, 9, -15, -11, 19, 12, -47, 84, -60, -16, -11, 17, -4, -15, 30, -45, 32, 34, -63, -7, 68, 0, -35, 17, 7, 33, -31, -8, 7, -32, 43, -13, -18, 15, 31, -32, -34, 5, 8, -16, 20, -26, -29, 32, -9, -20, 17, 33, -31, -13, -5, 86, -52, 23, -19, 2, 13, 14, -7, -20, 36, -16, -3, 8, 0, 14, -69, 76, -77, 25, -14, -17, 3, 39, -14, -46, 31, -2, -7, 37, -45, -6, 24, 28, -37, 22, 13, -35, 4, 8, 23, 7, -43, 53, -59, 23, 16, 4, -25, -15, 23, -9, -20, 26, -18, -1, 25, -3, -48, 53, 2, -43, 7, 14, -34, 15, 28, -33, 53, -2, -59, 31, -34, 40, 19, -27, 20, -2, 8, 2, 3, -8, -8, 4, -57, 62, 24, -72, -4, 17, -17, -3, -10, -26, 42, -30, 12, -29, 31, -10, 3, 24, 2, 21, -1, -36, 52, -7, 21, 14, -32, -18, 73, -45, -6, 8, -12, -66, 21, 25, -17, -6, -35, -14, 27, 26, -47, 40, -51, 56, -19, -24, 31, 6, 4, 11, -3, 37, -47, 41, -32, 50, 0, -72, 25, 16, -19, -1, -2, -4, -41, 20, 6, 9, -3, -44, 32, -54, 83, -30, -26, -8, 46, -47, 29, 5, -19, 37, -9, -20, 65, -14, -21, -4, 10, 28, -28, 18, -29, 35, -25, 3, -17, -31, 4, -4, 0, -9, 41, -42, -34, 40, -15, 8, -24, -8, 36, 22, -18, -27, 70, -39, 39, 1, -5, 57, -54, 12, 36, 3, -13, -1, -32, 69, 6, -64, -50, 13, -13, -34, 22, -13, 0, -10, -38, 41, -11, -22, -3, 11, 4, 38, 22, -10, 24, 32, -23, 23, -6, 8, -4, 21, -61, 66, -35, -41, 7, 5, -29, -19, -45, 23, -2, 46, -84, 78, -59, 40, -10, -18, 79, -35, -5, -1, 36, 16, 13, -21, -31, 52, 2, -50, 34, -5, -36, -37, 65, -42, 1, 16, -42, 35, -8, -50, -6, 41, -16, 27, -41, 22, 64, -50, -11, 31, -18, -17, 5, -3, 34, 34, -40, -41, 66, -37, 20, -11, -20, 29, -5, -14, -15, 45, -33, -37, -11, 36, -25, 18, -8, 20, 1, -23, 60, -32, 0, 34, -24, -32, 64, -39, -35, 48, -7, -13, 4, -39, 32, 0, 1, -31, 2, -12, 43, -38, -8, 26, 0, -57, 53, 19, -22, -10, 17, -30, 57, 6, -31, 33, 10, 0, -48, 29, -4, -23, 6, -7, 31, -39, 15, -41, 38, -19, 5, -37, 23, 11, -28, -14, 59, -48, 8, 22, -20, 50, 15, -34, -26, 67, -8, -15, -21, 53, -27, -9, 13, -24, -35, -10, 9, -15, -13, 18, -38, 28, 22, -14, 2, -22, 42, -20, 22, 12, -20, 45, -16, 17, -16, 22, 34, -27, -13, -7, 1, -21, -1, 13, -44, 36, -51, -8, 16, -7, -30, -46, 90, -54, 35, 1, 11, 9, 5, 1, -19, 20, 11, 21, -1, -49, 41, -6, 0, 37, -74, 9, 20, -12, -47, 65, -68, 28, -5, -26, 15, 14, -3, -23, 8, 18, -22, 13, 3, 31, -21, -5, 8, 24, -21, 48, -20, -21, 41, -43, 4, 18, 21, -60, 9, -27, 1, 13, -15, -33, 15, 23, -48, -8, 53, -50, 1, 6, -40, 90, -10, -15, 51, -52, 53, 29, -68, 50, 52, -30, -21, 7, -1, -8, -29, 11, -47, 6, 18, -12, -25, 53, -34, -23, -6, 19, -7, -13, 7, 5, -2, 14, 11, -15, 51, -29, 6, 12, 20, -27, 29, -12, 4, -18, -5, 2, -17, 10, -19, 2, -8, -5, 56, -82, 49, 0, -42, 48, -25, 19, 6, -41, 17, 35, -18, -17, -29, 26, 10, 4, -24, 26, -35, 47, -36, 2, 2, -23, 27, -42, 55, 0, -21, 19, 21, -8, 1, -3, -15, 7, 12, -23, -29, 47, -12, 4, -28, 17, 16, -7, -31, -8, 25, -6, 0, 13, -20, 6, 3, -7, 19, -21, -37, 27, 41, 7, -14, 12, -59, 57, 6, -49, -2, -8, 0, 19, 13, -20, -5, 16, 23, 4, -15, -33, 14, 2, 15, -26, -28, 10, 45, -17, -24, 14, 17, -39, 22, -8, 48, -51, -1, -16, 52, -34, -21, 11, 13, 18, -57, 26, 15, 27, -36, -12, 40, -7, -14, 15, -86, 91, -20, -13, -7, 53, -43, 33, -25, 13, 3, -38, -19, 28, 28, -18, -74, 58, -3, 40, -27, -34, 30, 28, -1, -22, 2, 9, -8, -12, 12, 21, -35, -2, -17, 17, 2, -27, 22, -36, 38, -11, 2, -20, 7, 20, -29, 39, 11, -3, 9, -24, 47, -36, 28, -14, -16, 38, -37, 12, -15, 18, -69, 56, -31, 17, -16, -18, -13, 21, -6, -9, -25, 37, 6, -1, -2, 5, -1, -26, 39, 6, -3, -10, 0, 12, 30, -12, -31, 24, 13, -14, 9, -23, 31, -43, -17, -2, 13, -23, -14, -21, 21, 19, -22, -12, 24, 41, -26, 10, 12, 19, -3, 9, -12, 26, 12, -52, -4, 16, -3, 0, -43, 7, 5, -14, -9, 12, -28, 15, -23, -2, 35, -12, -8, -10, 24, 57, -55, 26, -18, 19, 44, -30, 0, -5, 50, -56, -1, 8, -5, -39, 9, 19, -39, 38, -73, 30, -1, 2, 16, -24, 6, 29, -71, 70, -18, -6, 8, 31, 4, -13, 23, -11, 31, -56, 57, -25, 10, 15, -44, -10, 16, -17, -44, 18, -28, 10, 8, -21, -4, -9, 28, 20, -16, 17, -17, -6, 30, 0, 11, -21, 25, 25, -1, 31, -56, 31, 14, -32, 2, -19, 4, -17, -26, -13, 42, -59, 15, -29, 53, -4, 1, -23, 13, 31, 5, -22, 3, 30, -28, 2, -24, 37, 1, -3, -18, 18, 41, -40, 3, -40, 48, -31, -5, -20, 5, 9, 0, -30, -1, 26, -15, -5, -6, 51, -25, -27, 7, 44, -11, 10, -32, 14, 46, -31, 6, -11, 37, -33, -14, 19, -4, 22, -50, 26, -45, 21, 1, -23, 10, -15, 17, -63, 53, -14, -18, 56, -49, 21, 25, -7, 4, -21, 52, -33, 19, 3, 11, -9, -7, 0, -49, 22, -17, 25, -10, -11, 5, -19, 35, -26, 20, -7, -21, 37, -25, 29, -23, 3, 6, 17, -26, 27, 5, -16, 10, -9, -24, 11, -4, -17, 9, -5, -13, 1, -2, 10, 5, -13, 21, 0, 8, 9, -22, 12, 13, -24, -3, -22, 42, -18, 3, -4, -15, 1, -2, 8, -17, -13, -2, 1, 23, 10, -2, -31, 23, 17, -15, -9, -24, 31, 2, 19, -24, 4, -22, 28, -5, -20, 34, -57, 26, 71, -51, 28, -24, -12, 28, 10, -35, -4, -6, 7, -7, 8, -52, 61, -52, 7, -9, -21, 9, 18, -19, 3, 34, -53, 56, -29, 20, -11, 22, 4, -1, 23, 2, 1, 24, -15, 3, -32, 13, 21, -37, 6, -11, -25, 22, 7, -2, -41, 4, 10, -30, 39, -24, -7, 8, 12, 9, -1, -35, 13, 3, 9, -18, 21, 26, -14, 41, -8, -35, 31, -29, 17, -20, -12, 20, -30, 27, -26, 21, -9, -6, 5, -14, 3, -11, 15, 2, 8, -14, -5, 20, 4, 0, -31, 9, 4, 25, -24, 5, -5, -13, 27, -7, -32, 1, -5, -10, 28, 7, -4, 11, 10, 22, -3, -22, -15, 6, -3, -3, -27, -25, 5, 8, -10, -17, 18, -18, 12, 32, -18, 1, 25, -25, 50, 7, 2, 0, -3, -3, 16, -20, 9, -14, -15, 21, -27, -3, -17, 23, -31, -4, -18, 31, -21, 6, 0, 18, -16, 27, 3, -7, -17, 17, -15, -11, 19, -16, 6, 1, 12, -18, 5, -6, 24, 0, -19, 22, -23, 43, -35, 18, 22, -40, 1, 12, -4, -18, 26, -53, 34, 1, -10, 1, -18, 27, -25, -24, 33, -31, 9, -43, 53, -29, 33, -17, 5, 23, -7, 2, 23, 29, 1, -8, 20, -10, -1, -22, -3, -17, 4, 22, -61, -23, 31, -26, -29, -12, 2, -3, 12, 10, 26, 5, -29, 61, -9, 32, -18, -14, 29, 31, 2, -19, 9, 31, -20, -31, -7, 5, -22, -47, 31, -40, 15, -39, 22, -27, 40, -78, 31, 4, -19, 33, -13, -8, 41, -1, 5, -12, 53, -51, 22, -1, 18, 28, -29, -1, 0, 0, 11, 13, -2, -7, -5, -3, -3, 1, 2, -6, 0, 3, 8, 9, 5, 0, 14, -5, -28, -39, -39, -36, -37, -27, -43, -49, -13, 4, 6, -7, 0, -1, 3, 23, 39, 29, 35, 41, 21, 35, 0, 0, 21, 59, 67, 31, 21, 13, -3, 18, 34, 28, 5, 3, 13, 3, 0, 12, -7, -33, -27, -39, -14, -34, -50, -30, -37, -35, -53, -74, -70, -61, -62, -62, -50, -44, -61, -36, -3, -23, -15, -12, -17, -20, -6, 11, -6, -12, -6, -17, 7, 46, 71, 87, 79, 70, 77, 104, 109, 66, 37, 34, 27, 31, 40, 43, 31, 23, 17, 2, 10, 24, 32, 66, 56, 17, -13, -55, -54, -21, 19, -19, -56, -77, -37, -27, -10, -6, -38, -36, -37, -3, 23, 25, 25, 19, 35, 34, -7, -5, 28, 60, 66, 65, 51, 34, 22, 53, 51, 15, 20, 11, 21, 21, 16, 24, -2, -23, -36, -35, -21, -29, -51, -51, -47, -57, -85, -80, -70, -100, -97, -82, -78, -76, -64, -51, -56, -54, -49, -70, -62, -53, -54, -60, -57, -65, -78, -76, -62, -39, 0, 31, 13, 6, 31, 54, 55, 43, 30, 13, 9, 31, 23, 43, 28, 24, 36, 36, 24, 30, 54, 70, 113, 103, 75, 4, -3, 40, 55, 50, 23, 9, 25, 29, 48, 41, 29, 14, 6, 40, 63, 49, 39, 71, 80, 64, 21, 12, 17, 29, 68, 71, 52, 36, 24, 37, 24, 1, 5, 3, -6, -4, 1, 13, -3, -22, -35, -31, -27, -58, -59, -43, -55, -71, -76, -71, -88, -103, -95, -98, -85, -77, -68, -71, -58, -50, -47, -52, -46, -40, -47, -44, -48, -56, -60, -91, -96, -68, -15, -6, -16, 9, 3, 29, 31, 29, 8, 10, -6, 5, 10, -6, -4, -6, 15, 7, -2, 2, -5, 30, 91, 107, 74, 8, -3, 14, 27, 32, 26, 17, 21, 18, 34, 49, 20, -3, 2, 30, 42, 20, 36, 68, 79, 81, 52, 27, 22, 37, 80, 95, 77, 77, 72, 74, 57, 55, 56, 41, 35, 22, 40, 58, 32, 23, 24, 26, 0, -7, 6, -2, -16, -26, -31, -45, -46, -64, -77, -79, -73, -72, -75, -59, -49, -56, -35, -48, -44, -50, -43, -59, -58, -40, -78, -119, -123, -95, -73, -40, -52, -45, -29, -18, -3, -1, -11, -21, -28, -12, -24, -29, -21, -29, -16, -3, -5, -30, -40, 1, 69, 96, 78, 31, 14, 23, 17, 19, 33, 20, 9, 9, 45, 50, 14, 3, 12, 13, 16, 7, 14, 35, 54, 75, 56, 24, 1, 18, 47, 47, 60, 62, 66, 69, 46, 54, 53, 38, 11, 18, 44, 41, 28, 33, 37, 22, 14, 15, 13, 13, 1, -1, -13, -6, -11, -38, -33, -47, -40, -46, -31, -29, -22, -9, -5, -9, 9, 4, -23, -14, -4, -3, -26, -69, -87, -74, -60, -42, -49, -33, -28, -16, 9, 2, -16, -22, -25, -25, -33, -32, -44, -58, -41, -11, -19, -51, -77, -43, 24, 47, 49, 34, 21, 5, -9, 5, 18, -10, -14, 2, 23, 26, -3, -7, -4, 2, -3, -10, -4, -6, 38, 64, 50, 25, 1, 11, 17, 21, 36, 58, 62, 46, 46, 61, 56, 27, 11, 20, 18, 27, 15, 31, 26, 23, 17, 7, 16, 0, -9, -10, -3, -8, -14, -25, -36, -56, -41, -39, -50, -30, -12, -23, -8, 10, 23, 17, -2, 3, 14, 26, 7, -33, -48, -53, -52, -35, -30, -30, -23, 3, 21, 17, 8, 7, -8, -1, 0, -6, -29, -50, -26, 10, 5, -38, -64, -41, 5, 22, 49, 63, 38, 20, 13, 26, 15, -7, -9, -1, 28, 9, 1, -4, -12, -1, -5, -20, -38, -32, 6, 38, 36, 16, 10, 0, -8, -13, 15, 41, 25, 30, 30, 52, 35, 17, 8, 3, -5, -5, -6, 4, 7, 4, 4, 3, 3, -20, -25, -23, -28, -22, -18, -47, -50, -54, -62, -67, -62, -48, -43, -44, -31, -10, 17, 10, -8, 1, 22, 24, 17, -1, -21, -40, -39, -26, -38, -32, -21, 2, 17, 26, 29, 18, 5, 15, 35, 19, -11, -37, -9, 33, 17, -6, -30, -23, -10, 22, 65, 73, 71, 47, 57, 66, 38, 15, 16, 23, 34, 35, 27, 10, 11, 21, 32, -4, -26, -29, 4, 29, 28, 38, 32, 17, -6, -6, 17, 32, 21, 31, 39, 49, 36, 27, 25, 13, -1, -11, -8, -1, -15, -11, 4, -7, -9, -14, -38, -46, -35, -31, -43, -53, -54, -72, -84, -88, -86, -79, -73, -86, -69, -40, -16, -23, -28, -13, -9, 5, 5, -10, -34, -45, -48, -52, -61, -59, -42, -38, -9, 13, 19, 8, -14, 18, 42, 28, -18, -31, -3, 11, 21, 13, -9, -17, -22, 9, 57, 71, 62, 68, 83, 82, 65, 38, 38, 31, 52, 57, 45, 23, 25, 51, 56, 21, -2, -8, 7, 21, 28, 55, 55, 37, 15, 17, 30, 30, 30, 48, 55, 65, 55, 54, 61, 42, 24, 22, 13, 6, 6, 4, 4, 17, 19, 1, -20, -23, -25, -27, -26, -44, -44, -62, -79, -91, -83, -76, -99, -104, -87, -63, -51, -40, -42, -40, -29, -16, -6, -31, -40, -47, -63, -68, -81, -76, -81, -75, -49, -15, -5, -34, -38, 2, 15, 8, -29, -43, -33, -18, -11, 8, -9, -42, -45, -14, 25, 33, 41, 54, 67, 75, 71, 46, 30, 23, 52, 55, 38, 20, 25, 53, 59, 35, 17, 6, 3, 5, 27, 64, 61, 49, 40, 40, 45, 36, 38, 63, 69, 69, 77, 85, 78, 76, 63, 48, 38, 42, 28, 15, 30, 35, 41, 27, 14, 0, -4, -2, -14, -16, -15, -35, -65, -63, -56, -64, -80, -94, -77, -71, -46, -34, -42, -37, -21, -6, -5, -16, -20, -35, -44, -62, -66, -66, -96, -94, -58, -26, -32, -44, -50, -14, 2, -9, -26, -41, -53, -49, -27, -5, -28, -59, -65, -47, -20, -11, 7, 15, 28, 51, 57, 32, 7, 2, 30, 32, 15, 0, 7, 30, 30, 24, 21, -2, -19, -20, 6, 37, 40, 31, 40, 45, 30, 29, 35, 49, 52, 69, 74, 78, 89, 79, 72, 62, 60, 51, 37, 29, 29, 42, 51, 46, 30, 32, 18, 2, 8, 13, 15, -13, -35, -35, -38, -40, -53, -71, -70, -58, -34, -38, -32, -28, -9, 10, 10, 7, 11, -7, -28, -21, -26, -47, -80, -84, -49, -18, -28, -38, -32, -8, -4, 4, 3, -23, -46, -44, -19, -5, -22, -42, -55, -56, -35, -25, -12, -8, 11, 43, 51, 33, 1, 0, 24, 18, 1, -5, 0, 1, 9, 15, 21, -2, -38, -36, -19, 2, 2, 19, 26, 19, 20, 10, 11, 20, 31, 37, 49, 62, 64, 61, 60, 61, 50, 51, 32, 10, 16, 27, 31, 33, 33, 36, 7, -6, 3, 14, 12, -10, -21, -40, -34, -33, -47, -65, -67, -60, -40, -40, -44, -25, -10, -4, 14, 26, 22, 4, -7, 8, 8, -22, -67, -65, -33, -19, -24, -20, -18, -8, 1, 26, 30, -2, -22, -25, -6, 5, -1, -13, -38, -43, -31, -21, -16, -16, 9, 47, 61, 35, 22, 22, 31, 24, 10, 13, 5, -2, 0, 28, 34, 1, -21, -30, -28, -18, -5, 5, 18, 20, 14, 6, 6, 12, 9, 20, 33, 39, 51, 51, 42, 51, 51, 48, 20, 9, 7, 5, 7, 15, 28, 19, -1, -16, -15, -4, 4, -16, -30, -41, -45, -41, -50, -79, -77, -69, -65, -64, -56, -45, -40, -28, -4, 21, 17, -8, -9, 21, 16, -18, -56, -58, -44, -39, -24, -22, -28, -22, -4, 29, 31, 13, -9, -16, -3, 11, 13, 1, -18, -33, -15, -11, -23, -22, 11, 52, 58, 50, 46, 50, 49, 36, 40, 40, 17, 6, 20, 37, 45, 29, 9, -7, -12, -11, -6, 9, 30, 25, 26, 26, 17, 19, 15, 21, 24, 46, 55, 47, 43, 56, 64, 52, 33, 25, 13, -3, 2, 10, 21, 26, 4, -15, -16, -13, -2, -11, -32, -43, -37, -44, -61, -77, -78, -82, -82, -80, -71, -61, -72, -59, -21, 5, -2, -27, -10, 15, 7, -14, -44, -59, -67, -55, -37, -38, -50, -45, -23, 5, 23, 9, -6, -19, -15, 5, 14, 2, -22, -22, -10, -17, -35, -38, -3, 35, 38, 43, 57, 51, 44, 49, 57, 46, 25, 14, 24, 35, 54, 41, 31, 22, 1, -7, -4, 12, 23, 34, 37, 35, 35, 36, 26, 24, 33, 55, 62, 53, 58, 70, 70, 73, 62, 51, 38, 14, 6, 20, 31, 32, 27, 4, -9, -1, 9, -8, -21, -22, -27, -33, -53, -64, -67, -82, -86, -83, -67, -75, -97, -77, -36, -15, -27, -32, -18, -1, -1, -6, -31, -62, -73, -68, -52, -52, -68, -69, -50, -21, -2, 4, -10, -33, -29, -4, 2, -10, -29, -22, -8, -27, -55, -49, -27, -6, 12, 31, 43, 31, 38, 44, 54, 48, 25, 11, 19, 30, 36, 41, 41, 29, 11, -1, -9, 0, 15, 27, 34, 36, 46, 46, 26, 27, 39, 51, 59, 62, 62, 73, 76, 77, 85, 78, 58, 35, 23, 21, 37, 53, 37, 22, 15, 16, 20, 3, 0, -2, -2, -14, -33, -35, -45, -69, -77, -59, -53, -76, -96, -74, -41, -30, -25, -26, -19, -4, 7, 11, -8, -40, -62, -62, -51, -55, -69, -74, -71, -44, -15, -2, -14, -36, -38, -8, -7, -27, -33, -17, -12, -38, -51, -57, -58, -41, -14, 8, 19, 15, 15, 31, 46, 40, 21, 9, 7, 10, 20, 25, 33, 28, 16, 1, -18, -13, 0, 6, 12, 30, 39, 39, 26, 20, 32, 41, 45, 53, 64, 63, 62, 80, 84, 87, 81, 51, 29, 21, 44, 52, 41, 33, 29, 31, 27, 12, 8, 16, 10, -4, -7, -7, -29, -62, -57, -37, -44, -68, -81, -70, -48, -33, -23, -22, -17, -5, 16, 31, 14, -15, -33, -42, -41, -37, -53, -65, -74, -54, -16, 2, -12, -33, -19, -1, -10, -22, -17, -8, -8, -18, -33, -48, -62, -57, -31, -1, 7, 0, 9, 22, 40, 40, 27, 14, 4, 3, 10, 14, 21, 31, 20, 0, -13, -19, -17, -15, -7, 12, 29, 28, 13, 20, 18, 18, 31, 38, 47, 49, 51, 56, 67, 87, 84, 56, 30, 20, 31, 41, 31, 24, 32, 33, 20, 7, 14, 15, -2, -1, 13, 4, -28, -53, -45, -34, -38, -59, -75, -72, -58, -44, -26, -26, -29, -8, 14, 34, 28, 10, -9, -22, -26, -24, -30, -54, -78, -56, -13, -4, -17, -16, -5, 1, -6, -9, -8, -1, 3, -2, -4, -28, -53, -58, -37, -10, 1, -1, 6, 20, 34, 46, 40, 25, 19, 11, 7, 10, 23, 33, 28, 16, -3, -3, -17, -31, -14, 4, 15, 20, 20, 16, 10, 14, 19, 23, 37, 45, 35, 37, 53, 76, 83, 62, 34, 20, 27, 28, 13, 17, 29, 21, 7, 9, 13, -4, -17, -4, 13, 2, -27, -53, -47, -39, -46, -56, -77, -87, -77, -58, -45, -46, -47, -33, -6, 17, 22, 16, 1, -20, -25, -10, -21, -57, -79, -57, -32, -24, -23, -18, -3, -1, -6, -4, -4, -5, 3, 13, 14, -6, -38, -51, -39, -22, -4, -1, 3, 14, 32, 45, 46, 46, 33, 25, 15, 9, 28, 38, 32, 28, 26, 14, -9, -21, -15, -5, 10, 24, 22, 22, 21, 15, 15, 23, 36, 42, 35, 31, 41, 72, 87, 68, 46, 42, 34, 19, 14, 25, 25, 11, 14, 18, 14, -7, -24, -7, 12, 4, -19, -41, -47, -44, -41, -52, -74, -92, -88, -72, -59, -63, -68, -53, -34, -11, 12, 19, -7, -27, -15, -5, -22, -54, -76, -66, -52, -47, -41, -29, -17, -12, -12, -10, -11, -19, -7, 12, 19, 3, -23, -42, -48, -31, -19, -14, -6, 1, 20, 35, 39, 50, 51, 33, 16, 17, 30, 31, 32, 41, 39, 28, 14, -7, -14, -5, 8, 18, 27, 34, 29, 22, 21, 26, 38, 51, 39, 27, 43, 75, 84, 73, 75, 68, 46, 32, 31, 35, 27, 15, 23, 36, 26, 0, -13, -4, 12, 14, 1, -23, -36, -36, -32, -36, -60, -83, -84, -70, -67, -70, -66, -67, -62, -27, 8, 13, -11, -22, -7, 4, -16, -44, -63, -67, -63, -63, -53, -42, -33, -25, -15, -10, -22, -27, -18, -1, 16, 9, -13, -32, -46, -42, -31, -30, -24, -8, 5, 11, 25, 49, 50, 33, 25, 20, 21, 24, 29, 34, 41, 41, 26, 5, -5, -7, -4, 12, 23, 33, 37, 29, 19, 24, 49, 53, 33, 33, 49, 65, 73, 80, 89, 85, 63, 48, 50, 46, 30, 20, 35, 46, 39, 17, 0, 2, 15, 23, 18, -2, -20, -24, -12, -19, -45, -60, -66, -70, -66, -56, -61, -74, -74, -38, 0, 6, -8, -15, 3, 13, -1, -24, -42, -52, -65, -64, -54, -54, -47, -31, -19, -12, -21, -32, -27, -12, 7, 13, -2, -24, -36, -37, -44, -47, -32, -20, -18, -9, 12, 30, 38, 35, 26, 18, 17, 16, 13, 25, 36, 37, 32, 18, 2, -11, -10, -5, 3, 28, 38, 20, 8, 25, 42, 40, 28, 30, 40, 46, 54, 70, 87, 82, 66, 61, 59, 48, 28, 20, 32, 43, 43, 24, 8, 1, 7, 23, 25, 3, -13, -9, -8, -15, -28, -40, -58, -71, -60, -49, -58, -80, -82, -50, -17, -5, -13, -12, 6, 13, 8, -3, -24, -42, -54, -59, -57, -60, -59, -43, -24, -15, -20, -30, -35, -25, 1, 11, -2, -12, -18, -33, -48, -49, -41, -37, -32, -21, -8, 13, 27, 27, 27, 23, 16, 8, 7, 15, 22, 32, 35, 22, 9, 0, -18, -26, -8, 20, 25, 11, 4, 18, 32, 29, 22, 29, 30, 27, 38, 60, 75, 70, 68, 69, 67, 52, 30, 19, 27, 36, 40, 34, 10, -2, 6, 21, 20, 4, -2, -4, -7, -9, -12, -25, -52, -66, -53, -42, -53, -79, -86, -58, -33, -23, -16, -12, 0, 12, 17, 13, -5, -24, -38, -44, -50, -59, -61, -51, -33, -15, -11, -28, -36, -23, -4, 5, 5, 7, -3, -17, -31, -40, -38, -37, -36, -29, -14, 4, 15, 25, 34, 30, 24, 19, 9, 8, 22, 33, 31, 30, 31, 16, -14, -26, -13, 14, 17, 7, 8, 18, 24, 23, 28, 31, 23, 18, 30, 50, 62, 61, 63, 75, 73, 59, 40, 23, 20, 30, 43, 35, 11, 0, 8, 15, 12, 6, 3, -6, -10, -3, -1, -15, -46, -62, -47, -38, -54, -77, -84, -70, -53, -40, -30, -21, -12, 1, 16, 20, 5, -12, -21, -33, -44, -52, -64, -64, -44, -17, -15, -27, -30, -26, -15, -3, 6, 12, 9, -2, -17, -26, -29, -36, -41, -32, -21, -10, 6, 18, 27, 34, 37, 25, 11, 14, 21, 26, 27, 37, 48, 33, -1, -19, -8, 7, 8, 8, 16, 16, 17, 25, 34, 36, 23, 16, 28, 44, 53, 54, 61, 74, 79, 75, 56, 30, 19, 31, 45, 35, 15, 9, 9, 9, 11, 9, 5, -8, -14, 0, 9, -10, -40, -53, -44, -38, -51, -72, -84, -80, -69, -58, -45, -38, -30, -13, 5, 13, 8, 0, -14, -25, -30, -46, -67, -72, -55, -34, -26, -28, -31, -31, -26, -17, -4, 9, 11, 2, -4, -12, -22, -33, -38, -40, -34, -18, -7, 2, 17, 33, 38, 29, 19, 20, 22, 17, 19, 38, 57, 43, 15, 2, -1, 1, 3, 10, 18, 15, 14, 25, 38, 40, 27, 21, 28, 38, 46, 50, 55, 66, 81, 90, 71, 40, 30, 37, 44, 39, 26, 18, 12, 8, 14, 19, 8, -11, -13, 5, 15, -2, -28, -42, -36, -34, -45, -60, -76, -83, -77, -65, -59, -55, -43, -28, -13, 5, 11, 2, -9, -11, -17, -37, -61, -71, -65, -49, -38, -36, -34, -35, -36, -32, -16, -2, 1, 3, 0, -7, -13, -25, -39, -46, -42, -30, -22, -15, 2, 21, 30, 24, 22, 28, 19, 5, 11, 33, 50, 45, 31, 17, 6, -1, 0, 8, 16, 12, 11, 23, 37, 40, 33, 29, 29, 33, 45, 48, 46, 58, 83, 97, 84, 59, 45, 46, 47, 46, 42, 31, 16, 12, 23, 29, 16, -5, -9, 10, 21, 10, -12, -24, -25, -25, -29, -42, -64, -73, -70, -66, -63, -58, -52, -42, -22, 0, 8, 4, 1, 3, -1, -19, -44, -61, -63, -57, -50, -39, -33, -37, -39, -36, -27, -14, -4, 0, 0, 0, -1, -13, -30, -42, -43, -37, -36, -30, -10, 8, 12, 15, 26, 31, 16, 1, 4, 21, 37, 41, 38, 29, 13, 0, -1, 6, 8, 3, 7, 17, 26, 34, 35, 27, 24, 32, 40, 37, 32, 45, 72, 89, 86, 70, 57, 48, 45, 49, 50, 37, 16, 11, 25, 34, 20, -3, -7, 7, 18, 15, 2, -14, -20, -15, -17, -32, -49, -61, -67, -65, -60, -61, -63, -54, -33, -12, -1, 1, 2, 10, 12, -3, -26, -43, -57, -60, -54, -45, -38, -38, -39, -39, -35, -23, -13, -6, -3, 2, 7, -2, -20, -30, -34, -42, -47, -38, -19, -9, -5, 7, 24, 31, 19, 3, 0, 10, 23, 33, 40, 36, 18, 5, 4, 4, 0, 0, 0, 5, 16, 29, 30, 22, 22, 31, 36, 27, 21, 32, 54, 74, 81, 77, 65, 49, 44, 50, 55, 40, 16, 10, 24, 31, 20, 3, -6, -1, 11, 16, 5, -9, -13, -12, -14, -22, -36, -53, -63, -62, -59, -63, -69, -67, -48, -25, -14, -10, -1, 10, 16, 10, -6, -26, -45, -54, -55, -50, -42, -39, -39, -40, -39, -29, -19, -15, -8, 4, 11, 3, -6, -11, -21, -38, -48, -40, -26, -21, -16, -3, 18, 30, 24, 12, 6, 4, 11, 29, 41, 39, 28, 18, 11, 8, 5, 1, -4, -2, 11, 25, 25, 19, 23, 33, 35, 25, 17, 23, 39, 57, 74, 81, 72, 53, 47, 56, 60, 44, 23, 16, 22, 29, 25, 10, -4, -3, 7, 11, 6, -3, -9, -11, -9, -12, -26, -42, -56, -59, -55, -61, -73, -75, -60, -42, -32, -23, -12, 0, 12, 15, 7, -10, -30, -46, -53, -53, -46, -41, -43, -45, -41, -32, -30, -26, -14, -1, 5, 2, 3, 3, -9, -30, -43, -40, -31, -31, -28, -12, 8, 20, 25, 22, 9, 0, 6, 21, 34, 39, 35, 26, 18, 16, 14, 4, -7, -5, 9, 21, 19, 16, 23, 35, 37, 28, 20, 20, 26, 43, 67, 82, 74, 57, 54, 62, 63, 52, 33, 21, 23, 30, 28, 14, 1, -1, 3, 8, 7, -1, -7, -9, -6, -5, -15, -34, -49, -51, -51, -60, -72, -76, -70, -57, -46, -37, -25, -13, 3, 14, 14, 3, -15, -33, -48, -52, -47, -45, -49, -49, -41, -37, -39, -35, -21, -10, -5, -2, 6, 12, 1, -19, -32, -34, -36, -39, -34, -23, -9, 9, 23, 25, 14, 3, 2, 12, 25, 36, 37, 30, 24, 25, 24, 10, -5, -4, 9, 18, 15, 14, 23, 34, 38, 36, 30, 19, 15, 32, 61, 78, 75, 63, 60, 67, 71, 62, 42, 29, 30, 33, 32, 20, 8, 4, 6, 8, 8, 3, -5, -9, -2, 3, -7, -25, -37, -42, -45, -54, -66, -74, -74, -67, -58, -49, -40, -27, -9, 5, 13, 13, 0, -21, -39, -45, -44, -49, -54, -50, -44, -44, -47, -42, -29, -21, -19, -11, 5, 12, 4, -8, -18, -28, -36, -40, -40, -36, -24, -4, 14, 21, 17, 7, 0, 3, 17, 32, 34, 29, 28, 34, 33, 17, 0, 0, 9, 13, 12, 14, 20, 27, 38, 46, 39, 21, 11, 24, 51, 71, 74, 66, 64, 73, 78, 71, 54, 40, 38, 41, 38, 28, 17, 11, 9, 12, 14, 7, -3, -5, 3, 9, 2, -12, -23, -28, -35, -45, -55, -65, -71, -68, -62, -57, -50, -37, -22, -7, 10, 20, 12, -8, -24, -32, -39, -48, -52, -49, -45, -49, -52, -44, -34, -33, -30, -18, -3, 5, 5, 1, -8, -19, -29, -37, -43, -45, -37, -18, 0, 13, 18, 10, -1, -3, 10, 24, 26, 23, 29, 38, 37, 21, 8, 5, 6, 8, 10, 12, 11, 16, 34, 49, 46, 27, 10, 15, 38, 59, 67, 63, 63, 72, 81, 77, 61, 48, 45, 45, 42, 35, 23, 13, 11, 17, 18, 9, -3, -5, 3, 10, 6, -3, -12, -19, -24, -34, -46, -57, -64, -65, -66, -63, -56, -48, -39, -22, 1, 17, 16, 3, -8, -17, -30, -44, -47, -44, -47, -53, -52, -44, -41, -41, -38, -28, -14, -3, 3, 3, -2, -9, -17, -28, -42, -49, -46, -34, -17, 3, 14, 9, -3, -6, 5, 15, 13, 15, 26, 36, 35, 25, 16, 8, 2, 4, 9, 6, 1, 4, 22, 43, 48, 31, 11, 7, 24, 45, 55, 54, 55, 68, 79, 77, 66, 54, 48, 47, 47, 41, 27, 14, 11, 18, 20, 10, -2, -6, 0, 7, 8, 2, -6, -12, -14, -23, -38, -49, -55, -62, -66, -63, -60, -59, -53, -37, -12, 8, 13, 10, 7, -4, -21, -35, -37, -39, -47, -53, -51, -45, -44, -44, -42, -36, -24, -10, 0, 2, 1, 1, -3, -15, -30, -42, -49, -45, -30, -6, 10, 7, -2, -3, 5, 9, 6, 11, 23, 32, 35, 33, 25, 14, 6, 9, 12, 8, -2, -4, 13, 36, 48, 39, 18, 7, 17, 34, 43, 45, 50, 62, 74, 78, 71, 59, 51, 49, 52, 48, 32, 16, 12, 19, 21, 13, 1, -6, -5, 2, 6, 2, -4, -6, -9, -18, -29, -40, -51, -60, -65, -63, -63, -68, -68, -53, -30, -12, 0, 10, 13, 3, -14, -25, -29, -35, -45, -52, -52, -49, -47, -47, -47, -46, -35, -20, -10, -5, -1, 4, 4, -4, -15, -30, -47, -54, -41, -15, 1, 0, -2, 2, 6, 4, 3, 7, 16, 26, 35, 38, 32, 20, 12, 14, 18, 12, -1, -8, 3, 27, 46, 44, 26, 14, 17, 28, 35, 38, 44, 55, 69, 78, 77, 66, 55, 54, 60, 58, 41, 24, 17, 19, 23, 20, 7, -4, -4, 0, 2, 1, 0, -2, -4, -10, -17, -28, -42, -55, -59, -56, -61, -72, -74, -63, -47, -32, -14, 5, 13, 7, -4, -12, -19, -28, -38, -46, -51, -50, -46, -47, -51, -52, -43, -30, -20, -13, -5, 0, 4, 4, 2, -13, -40, -55, -47, -25, -12, -8, -3, 3, 5, 4, 2, 3, 7, 18, 32, 41, 36, 25, 18, 21, 25, 21, 5, -9, -3, 19, 41, 45, 34, 24, 23, 27, 30, 33, 38, 47, 62, 78, 82, 72, 61, 61, 67, 66, 54, 37, 24, 23, 28, 25, 15, 5, 0, 0, 0, 1, 2, 2, -1, -4, -5, -15, -34, -47, -49, -49, -58, -69, -73, -70, -63, -51, -30, -8, 5, 7, 3, -4, -11, -20, -29, -41, -49, -50, -46, -49, -54, -56, -50, -42, -33, -22, -13, -10, -6, 5, 12, -1, -30, -50, -50, -38, -27, -18, -10, -3, 1, 2, 2, -2, -4, 6, 24, 36, 36, 27, 19, 22, 30, 28, 10, -8, -10, 9, 30, 39, 35, 30, 26, 26, 28, 29, 29, 35, 53, 73, 80, 74, 65, 63, 69, 72, 64, 47, 33, 28, 29, 28, 21, 12, 6, 2, -2, 1, 4, 1, -2, 2, 6, -4, -23, -35, -38, -42, -51, -60, -66, -70, -71, -63, -45, -23, -5, 4, 6, 3, -2, -7, -18, -32, -42, -43, -43, -47, -52, -54, -53, -51, -42, -27, -20, -21, -14, 4, 17, 10, -13, -35, -45, -44, -37, -26, -17, -11, -3, 3, 3, -3, -9, -4, 13, 31, 35, 27, 19, 23, 34, 36, 19, -3, -10, 2, 19, 31, 35, 33, 29, 30, 32, 28, 22, 26, 43, 63, 76, 75, 67, 65, 71, 75, 70, 57, 43, 36, 34, 30, 26, 21, 14, 5, 1, 4, 3, -2, -2, 6, 11, 3, -11, -22, -29, -36, -43, -50, -57, -67, -74, -72, -60, -40, -19, -5, 2, 4, 6, 3, -8, -23, -32, -35, -40, -45, -47, -51, -57, -58, -47, -33, -30, -32, -24, -5, 13, 14, 1, -18, -36, -45, -42, -35, -27, -20, -11, 0, 3, -3, -12, -12, 1, 21, 31, 25, 16, 20, 34, 40, 26, 5, -7, -6, 7, 21, 27, 26, 27, 31, 33, 27, 17, 15, 28, 50, 65, 68, 64, 62, 68, 74, 72, 61, 51, 44, 35, 29, 28, 25, 15, 7, 5, 5, -1, -8, -5, 3, 8, 4, -4, -12, -22, -32, -38, -42, -50, -61, -72, -77, -73, -57, -36, -20, -11, -2, 7, 8, -3, -14, -22, -30, -38, -41, -42, -49, -60, -62, -52, -41, -40, -41, -34, -18, 0, 11, 10, -3, -23, -38, -42, -40, -36, -31, -20, -6, 2, -1, -13, -19, -9, 12, 25, 20, 12, 17, 30, 39, 34, 17, -2, -8, 1, 13, 19, 21, 23, 31, 37, 32, 18, 10, 18, 36, 55, 62, 60, 60, 67, 73, 72, 68, 61, 51, 41, 35, 34, 28, 18, 12, 11, 8, -2, -9, -7, 0, 4, 5, 3, -3, -14, -24, -31, -36, -41, -50, -64, -77, -80, -68, -51, -37, -26, -11, 3, 6, 2, -3, -13, -24, -32, -33, -34, -46, -60, -62, -54, -47, -46, -47, -43, -31, -13, 4, 12, 6, -9, -23, -34, -39, -40, -38, -29, -14, 0, 2, -11, -22, -15, 4, 17, 16, 11, 13, 25, 39, 41, 28, 9, -3, 0, 9, 15, 15, 19, 30, 40, 39, 26, 12, 11, 28, 45, 54, 56, 60, 66, 70, 73, 74, 69, 58, 49, 45, 42, 32, 22, 18, 19, 14, 3, -6, -7, -4, 0, 5, 6, 3, -5, -14, -24, -30, -32, -38, -53, -71, -78, -72, -63, -54, -39, -22, -8, 1, 6, 6, -4, -18, -25, -23, -25, -39, -54, -58, -54, -49, -49, -50, -49, -42, -26, -7, 7, 9, 2, -9, -20, -30, -38, -43, -39, -22, -2, 3, -9, -20, -16, -2, 11, 14, 10, 10, 20, 36, 46, 40, 22, 8, 6, 11, 13, 12, 15, 26, 41, 46, 36, 20, 14, 24, 38, 47, 54, 60, 64, 69, 76, 81, 76, 66, 60, 58, 53, 40, 30, 27, 27, 22, 12, 3, -3, -4, -1, 4, 8, 8, 5, -4, -15, -21, -21, -25, -41, -58, -69, -71, -70, -64, -51, -35, -23, -9, 5, 10, 1, -13, -17, -15, -19, -32, -46, -54, -54, -51, -50, -52, -55, -53, -40, -22, -6, 3, 4, -2, -10, -19, -32, -47, -49, -32, -11, -3, -10, -20, -20, -10, 2, 7, 5, 2, 10, 28, 42, 41, 29, 16, 10, 11, 11, 7, 6, 17, 35, 45, 39, 26, 18, 19, 26, 37, 47, 53, 56, 61, 73, 81, 76, 68, 65, 65, 59, 46, 36, 31, 28, 25, 19, 9, -1, -6, -4, -1, 2, 8, 9, 0, -10, -15, -14, -18, -32, -46, -57, -68, -74, -71, -61, -51, -41, -23, -2, 8, 2, -8, -11, -10, -13, -23, -37, -48, -53, -51, -49, -53, -59, -60, -53, -37, -19, -7, -3, -2, -1, -6, -22, -43, -52, -42, -21, -9, -12, -20, -23, -16, -4, 3, -1, -6, 0, 18, 34, 40, 33, 22, 16, 16, 13, 5, 0, 9, 27, 39, 40, 32, 24, 18, 19, 29, 40, 44, 46, 55, 69, 77, 75, 71, 70, 70, 65, 55, 45, 37, 32, 30, 26, 17, 7, 0, -5, -6, -1, 8, 11, 4, -5, -7, -7, -13, -21, -30, -44, -59, -69, -69, -65, -63, -56, -36, -13, 1, 1, -4, -6, -5, -6, -12, -25, -40, -47, -47, -46, -50, -56, -62, -61, -48, -30, -18, -12, -6, 4, 6, -7, -32, -49, -46, -30, -16, -12, -19, -25, -20, -7, 0, -3, -9, -7, 8, 26, 36, 34, 27, 24, 24, 19, 7, -2, 4, 18, 31, 38, 38, 30, 20, 18, 26, 34, 35, 38, 48, 62, 71, 73, 72, 73, 72, 70, 64, 53, 43, 38, 35, 30, 23, 16, 7, -4, -10, -4, 6, 8, 3, -1, -2, -4, -9, -12, -19, -33, -51, -61, -65, -69, -73, -70, -52, -30, -13, -6, -5, -7, -5, -2, -5, -17, -31, -41, -45, -44, -45, -53, -64, -67, -58, -43, -31, -26, -17, -1, 10, 3, -19, -41, -48, -39, -23, -16, -21, -27, -24, -12, -3, -5, -13, -15, -3, 16, 28, 29, 26, 28, 31, 24, 10, 0, 0, 8, 20, 33, 38, 32, 22, 19, 24, 28, 28, 30, 40, 52, 61, 68, 71, 72, 73, 73, 69, 59, 51, 45, 39, 32, 28, 26, 15, 0, -9, -5, 2, 4, 2, 1, -1, -4, -6, -5, -10, -24, -41, -50, -56, -66, -76, -77, -66, -47, -27, -15, -11, -10, -5, 0, -1, -8, -20, -33, -40, -40, -40, -48, -62, -70, -64, -51, -43, -39, -29, -11, 7, 10, -5, -28, -43, -41, -28, -20, -22, -29, -28, -17, -6, -5, -14, -20, -12, 6, 19, 22, 23, 30, 35, 31, 20, 8, 0, 1, 13, 29, 37, 33, 26, 25, 27, 27, 25, 26, 33, 43, 54, 63, 67, 70, 74, 76, 72, 66, 61, 54, 44, 37, 36, 34, 24, 8, -3, -4, -2, 0, 2, 3, -1, -5, -3, 2, -2, -16, -29, -36, -44, -57, -70, -79, -76, -60, -41, -27, -19, -14, -8, -1, 3, 0, -10, -24, -33, -33, -32, -40, -55, -65, -63, -56, -51, -48, -40, -23, -1, 12, 7, -13, -32, -37, -29, -21, -21, -28, -29, -19, -6, -2, -12, -20, -14, 0, 11, 16, 22, 30, 37, 38, 33, 21, 7, 0, 9, 26, 36, 35, 32, 32, 32, 31, 28, 27, 30, 38, 50, 58, 63, 70, 78, 79, 76, 74, 72, 64, 53, 46, 45, 44, 34, 20, 9, 3, -1, 1, 7, 7, 0, -4, 2, 8, 5, -5, -15, -23, -30, -41, -58, -73, -77, -68, -53, -38, -28, -21, -14, -5, 4, 7, -1, -15, -25, -25, -24, -32, -48, -59, -61, -59, -57, -57, -54, -39, -16, 4, 8, -5, -24, -33, -30, -24, -24, -32, -35, -26, -11, -6, -14, -20, -19, -10, -2, 5, 13, 21, 29, 37, 40, 30, 11, 0, 4, 17, 27, 30, 31, 31, 32, 32, 29, 23, 23, 31, 40, 45, 52, 63, 72, 74, 73, 75, 75, 67, 56, 51, 50, 46, 38, 29, 18, 6, -3, -1, 5, 3, -4, -7, -2, 4, 5, -2, -11, -17, -21, -30, -47, -66, -78, -77, -66, -53, -42, -34, -27, -16, -3, 6, 1, -12, -21, -21, -21, -28, -42, -54, -60, -60, -61, -65, -67, -57, -35, -11, 1, -3, -18, -30, -30, -25, -27, -36, -41, -32, -19, -13, -17, -22, -22, -19, -14, -6, 2, 7, 17, 31, 41, 34, 17, 3, 1, 8, 17, 23, 25, 26, 30, 32, 28, 22, 21, 25, 30, 34, 42, 54, 63, 66, 70, 77, 77, 69, 61, 57, 55, 49, 44, 39, 28, 11, 2, 2, 5, 3, -3, -8, -4, 3, 6, 2, -4, -9, -11, -16, -31, -52, -68, -75, -71, -61, -50, -43, -38, -26, -8, 5, 4, -6, -13, -14, -13, -19, -31, -44, -51, -52, -55, -64, -71, -67, -49, -24, -4, -1, -12, -22, -21, -18, -22, -33, -39, -33, -22, -16, -16, -17, -19, -20, -16, -9, -4, -2, 5, 18, 31, 37, 32, 21, 11, 9, 12, 17, 20, 24, 28, 32, 31, 28, 26, 26, 26, 28, 34, 43, 51, 57, 65, 74, 77, 75, 72, 68, 63, 59, 56, 53, 44, 31, 19, 12, 11, 8, 3, -2, -3, 0, 4, 5, 2, 0, -1, -3, -11, -25, -42, -58, -66, -65, -59, -54, -51, -42, -27, -11, -2, -3, -6, -7, -7, -9, -16, -27, -36, -40, -44, -52, -63, -70, -66, -49, -28, -15, -13, -16, -16, -13, -16, -24, -31, -33, -29, -24, -19, -17, -19, -20, -18, -14, -13, -12, -6, 7, 22, 33, 35, 28, 18, 12, 12, 14, 17, 21, 27, 31, 31, 30, 30, 28, 25, 25, 30, 36, 42, 49, 58, 67, 74, 76, 75, 71, 66, 62, 60, 59, 53, 41, 29, 19, 14, 11, 7, 1, -3, -2, 1, 3, 3, 1, 0, 0, -3, -11, -26, -44, -59, -65, -63, -60, -57, -52, -41, -25, -11, -4, -4, -6, -6, -6, -9, -17, -27, -35, -39, -44, -53, -65, -71, -65, -47, -28, -16, -15, -16, -15, -14, -17, -25, -32, -33, -29, -24, -19, -17, -19, -20, -18, -14, -13, -12, -6, -2, 1, 6, 5, 21, 46, 42, 15, 0, 5, 34, 48, 29, -4, -31, -33, -17, 26, 49, 32, 0, -21, -15, 14, 24, 24, 16, 0, 3, 11, 11, 11, 5, 9, 9, 8, 11, 30, 27, 22, 7, -3, -3, 10, 2, -2, -4, -13, -4, -4, -2, -2, -3, -7, -6, -14, -15, -14, -14, -13, -3, -14, -16, -18, -13, -15, -16, -22, -20, -14, -3, -6, -4, -14, -11, -6, -10, -15, -15, -16, -9, -10, -19, -3, -5, -17, -15, -18, -16, -14, -14, -12, -15, -7, -22, -19, -17, -20, -11, -17, -14, -11, -8, -10, -13, -12, -11, -6, -6, -9, 1, 1, -3, 0, 6, -2, -9, 7, -8, 8, 4, 3, 1, -6, -2, -2, 2, -5, -7, -4, -7, -8, -9, -6, -6, 0, -8, -12, -12, -13, -8, -4, -7, -3, -11, -6, -15, -7, -9, -9, -3, -10, -8, -9, -15, -10, -2, 2, -7, -16, -17, -15, -13, -9, -6, -5, -7, -9, -15, -17, -12, -19, -12, -8, -8, -4, -6, -3, 0, -4, -11, -13, -7, -6, -2, 4, 4, 8, 10, 4, 3, 3, 4, 7, 12, 11, 14, 15, 20, 20, 18, 16, 17, 15, 14, 15, 22, 23, 28, 34, 29, 28, 17, 22, 24, 23, 25, 28, 28, 30, 24, 19, 16, 13, 18, 20, 15, 8, 2, 3, 0, 2, 0, -3, -2, -9, -20, -23, -25, -24, -23, -27, -33, -38, -39, -44, -36, -42, -44, -48, -53, -54, -56, -52, -50, -40, -35, -44, -43, -44, -39, -28, -24, -23, -22, -15, -9, 2, 11, 19, 28, 31, 31, 32, 35, 43, 61, 70, 78, 81, 73, 78, 78, 78, 85, 82, 85, 88, 87, 84, 83, 83, 79, 74, 62, 49, 45, 42, 43, 44, 38, 30, 18, 6, -5, -15, -17, -15, -22, -28, -38, -46, -48, -50, -58, -59, -72, -80, -83, -89, -88, -89, -87, -81, -84, -93, -105, -110, -109, -110, -102, -96, -82, -65, -62, -60, -60, -60, -51, -43, -37, -28, -16, 1, 15, 28, 35, 41, 46, 53, 56, 60, 66, 77, 91, 101, 102, 101, 99, 104, 103, 97, 91, 86, 90, 91, 86, 85, 79, 75, 71, 59, 48, 39, 35, 33, 32, 28, 22, 15, 13, 7, 3, -7, -15, -16, -18, -19, -23, -28, -29, -33, -37, -47, -52, -56, -63, -61, -70, -67, -70, -72, -72, -80, -93, -91, -99, -103, -96, -108, -105, -109, -112, -94, -81, -73, -67, -71, -77, -69, -63, -57, -38, -27, -15, 0, 4, 6, 19, 26, 41, 53, 49, 56, 58, 69, 84, 91, 95, 101, 103, 98, 93, 85, 87, 102, 102, 103, 95, 81, 78, 78, 71, 66, 60, 51, 50, 44, 39, 34, 34, 32, 27, 15, 0, -6, -8, -3, -3, -11, -10, -18, -21, -26, -35, -39, -38, -44, -48, -53, -63, -61, -61, -71, -63, -86, -89, -86, -107, -99, -109, -108, -109, -108, -121, -128, -105, -102, -83, -67, -88, -82, -76, -78, -62, -47, -41, -19, -6, 1, 7, 13, 33, 44, 64, 61, 59, 68, 73, 93, 98, 107, 114, 109, 123, 107, 100, 105, 100, 111, 117, 100, 93, 92, 86, 85, 80, 70, 59, 58, 47, 38, 41, 33, 40, 38, 25, 16, 1, -2, -3, -3, -4, -10, -16, -12, -21, -28, -28, -36, -38, -39, -52, -61, -61, -67, -63, -65, -76, -77, -86, -95, -95, -107, -109, -112, -112, -121, -121, -122, -105, -79, -80, -71, -80, -84, -73, -70, -56, -43, -28, -10, 6, 11, 17, 31, 43, 63, 69, 69, 65, 77, 88, 101, 113, 112, 127, 122, 122, 115, 104, 112, 116, 122, 117, 106, 99, 97, 96, 94, 86, 75, 70, 61, 53, 44, 41, 46, 47, 45, 28, 19, 9, 5, 9, 1, -8, -14, -20, -24, -26, -28, -29, -36, -39, -42, -45, -41, -42, -45, -46, -49, -47, -50, -55, -53, -61, -63, -67, -83, -78, -89, -91, -88, -100, -93, -108, -110, -110, -115, -90, -100, -91, -80, -91, -73, -62, -60, -41, -33, -36, -25, -16, -9, 8, 18, 35, 40, 57, 61, 66, 95, 94, 106, 114, 105, 117, 111, 117, 118, 115, 120, 111, 109, 111, 104, 102, 106, 93, 88, 76, 66, 63, 52, 53, 31, 27, 25, 5, 12, 1, -5, 0, -15, -17, -23, -27, -27, -31, -31, -37, -44, -41, -43, -43, -35, -45, -43, -41, -50, -49, -51, -57, -58, -62, -72, -76, -79, -81, -82, -86, -92, -94, -100, -109, -110, -102, -99, -96, -83, -96, -83, -67, -73, -45, -41, -42, -27, -27, -19, -5, 7, 14, 30, 44, 46, 57, 75, 84, 98, 108, 102, 112, 114, 110, 120, 115, 116, 117, 108, 112, 107, 104, 108, 99, 96, 90, 73, 69, 66, 57, 48, 36, 26, 18, 13, 6, -3, 3, -8, -14, -15, -26, -25, -26, -33, -33, -40, -45, -45, -45, -42, -43, -44, -45, -48, -46, -55, -57, -58, -62, -67, -73, -78, -80, -81, -82, -89, -93, -99, -106, -108, -115, -100, -95, -103, -77, -91, -85, -59, -63, -48, -32, -36, -33, -18, -14, -6, 11, 21, 27, 47, 55, 56, 81, 92, 96, 114, 106, 111, 116, 110, 121, 113, 115, 115, 105, 111, 106, 101, 103, 100, 92, 84, 74, 66, 60, 58, 43, 29, 29, 13, 9, 10, -6, -2, -6, -16, -18, -22, -27, -30, -30, -35, -44, -43, -46, -46, -42, -44, -48, -45, -46, -50, -54, -51, -61, -63, -61, -85, -76, -80, -94, -75, -98, -97, -93, -111, -103, -106, -97, -97, -90, -79, -93, -73, -64, -67, -39, -38, -41, -20, -20, -12, 11, 10, 30, 40, 48, 62, 62, 85, 91, 99, 111, 101, 112, 111, 113, 120, 112, 119, 111, 108, 114, 101, 102, 104, 89, 91, 79, 63, 67, 56, 52, 41, 29, 26, 12, 14, 3, -5, 1, -14, -15, -19, -27, -24, -30, -31, -34, -43, -43, -45, -48, -40, -48, -48, -45, -51, -49, -53, -56, -57, -63, -69, -76, -86, -80, -86, -90, -87, -98, -101, -101, -108, -103, -88, -96, -88, -77, -89, -70, -60, -56, -39, -34, -30, -26, -11, -4, 6, 26, 27, 42, 54, 57, 72, 86, 95, 105, 107, 108, 112, 109, 116, 118, 112, 117, 108, 109, 107, 104, 103, 99, 97, 83, 77, 71, 57, 60, 49, 35, 30, 21, 11, 11, 4, -2, -3, -13, -17, -22, -24, -28, -29, -29, -39, -39, -44, -44, -41, -45, -44, -50, -49, -49, -56, -50, -60, -62, -55, -82, -70, -82, -90, -80, -95, -95, -100, -105, -112, -112, -93, -102, -91, -81, -91, -77, -60, -65, -45, -33, -40, -25, -21, -14, 5, 10, 30, 35, 49, 61, 61, 87, 94, 102, 109, 109, 112, 112, 116, 117, 116, 118, 116, 106, 113, 108, 101, 110, 96, 91, 84, 69, 66, 58, 54, 38, 29, 26, 12, 11, 6, -2, -2, -8, -16, -20, -23, -27, -28, -33, -34, -44, -43, -43, -47, -39, -44, -47, -43, -47, -49, -50, -52, -57, -58, -68, -75, -76, -83, -86, -86, -91, -97, -98, -103, -109, -102, -91, -99, -84, -81, -93, -65, -66, -60, -37, -42, -33, -25, -18, -9, 6, 16, 28, 41, 49, 57, 68, 84, 93, 102, 106, 106, 110, 107, 116, 114, 111, 119, 106, 111, 108, 101, 104, 99, 94, 85, 76, 68, 61, 56, 49, 34, 28, 21, 10, 10, 2, -3, -3, -13, -15, -24, -26, -28, -34, -31, -42, -45, -43, -48, -44, -43, -47, -47, -47, -48, -51, -57, -57, -63, -70, -72, -80, -86, -81, -92, -88, -96, -103, -100, -113, -110, -96, -101, -96, -79, -91, -82, -59, -68, -47, -34, -39, -29, -18, -13, -5, 18, 22, 32, 54, 52, 64, 83, 90, 100, 108, 109, 110, 113, 113, 116, 113, 117, 113, 106, 111, 103, 100, 101, 98, 86, 82, 73, 59, 61, 53, 36, 34, 24, 12, 10, 5, -5, -3, -8, -17, -18, -24, -27, -29, -30, -35, -40, -41, -45, -43, -43, -42, -45, -46, -44, -50, -49, -55, -58, -55, -71, -70, -79, -87, -77, -92, -88, -95, -104, -100, -115, -107, -91, -105, -85, -83, -97, -67, -68, -65, -37, -43, -33, -29, -21, -9, 0, 18, 23, 35, 55, 48, 69, 87, 86, 108, 107, 103, 117, 106, 117, 118, 113, 122, 109, 111, 111, 102, 110, 101, 98, 92, 77, 73, 62, 59, 54, 34, 34, 21, 11, 15, 2, 2, 2, -14, -12, -23, -26, -26, -33, -30, -40, -44, -42, -49, -41, -41, -44, -43, -46, -49, -51, -59, -54, -63, -67, -64, -84, -79, -76, -91, -82, -87, -100, -100, -101, -118, -101, -89, -107, -81, -82, -93, -65, -57, -57, -36, -26, -39, -17, -9, -13, 14, 21, 26, 45, 53, 54, 76, 88, 95, 111, 106, 111, 114, 109, 120, 115, 115, 116, 110, 105, 109, 104, 98, 105, 94, 83, 81, 68, 60, 62, 49, 32, 33, 18, 9, 12, 0, -3, -3, -13, -18, -20, -24, -27, -26, -31, -37, -40, -42, -42, -43, -42, -44, -48, -48, -47, -51, -54, -52, -56, -64, -68, -75, -84, -79, -89, -91, -93, -104, -105, -110, -114, -97, -97, -96, -78, -89, -81, -58, -66, -47, -34, -40, -31, -23, -14, -6, 14, 22, 31, 54, 55, 63, 87, 91, 103, 113, 105, 111, 113, 109, 119, 112, 117, 114, 106, 113, 106, 105, 105, 99, 93, 81, 74, 61, 58, 55, 36, 30, 25, 10, 11, 6, -5, 1, -8, -16, -19, -25, -27, -32, -32, -37, -44, -41, -47, -43, -39, -43, -44, -45, -46, -46, -56, -53, -55, -72, -64, -74, -91, -72, -88, -97, -80, -100, -105, -100, -111, -111, -88, -100, -99, -74, -97, -79, -54, -68, -43, -32, -41, -26, -10, -16, 6, 22, 19, 41, 51, 49, 69, 86, 88, 103, 107, 100, 119, 110, 111, 125, 110, 115, 115, 104, 108, 106, 99, 98, 98, 82, 76, 71, 60, 60, 52, 34, 30, 25, 9, 11, 3, -6, 0, -15, -18, -21, -27, -27, -30, -31, -38, -39, -43, -43, -39, -43, -44, -46, -47, -47, -54, -53, -59, -58, -65, -71, -75, -81, -75, -90, -83, -90, -100, -95, -111, -109, -101, -97, -100, -84, -86, -89, -62, -64, -50, -34, -37, -30, -21, -11, -8, 10, 19, 26, 47, 49, 59, 76, 89, 99, 107, 109, 110, 115, 113, 119, 115, 114, 115, 106, 111, 103, 103, 101, 98, 94, 81, 78, 65, 63, 59, 43, 34, 25, 17, 10, 7, -4, -3, -6, -14, -16, -23, -24, -28, -29, -33, -41, -41, -46, -43, -40, -44, -44, -46, -46, -47, -50, -54, -56, -58, -69, -70, -76, -83, -75, -87, -87, -91, -100, -100, -109, -108, -97, -98, -93, -83, -88, -76, -61, -59, -43, -36, -33, -28, -18, -11, -4, 14, 21, 31, 52, 51, 63, 84, 90, 101, 111, 104, 113, 113, 111, 118, 112, 114, 109, 108, 109, 102, 106, 101, 98, 94, 79, 74, 66, 58, 55, 39, 29, 24, 13, 11, 5, -4, 0, -10, -15, -17, -24, -25, -28, -29, -34, -41, -41, -47, -42, -44, -46, -45, -50, -45, -50, -55, -48, -60, -60, -65, -76, -77, -83, -84, -91, -92, -94, -106, -103, -109, -106, -89, -101, -82, -81, -88, -63, -66, -54, -36, -40, -31, -25, -16, -7, 6, 17, 30, 41, 55, 56, 73, 89, 92, 109, 104, 106, 114, 104, 117, 113, 110, 116, 105, 108, 106, 100, 102, 98, 94, 85, 74, 67, 59, 55, 48, 31, 28, 19, 10, 12, 0, 2, -2, -11, -11, -21, -21, -26, -30, -30, -40, -43, -43, -44, -40, -39, -41, -43, -42, -46, -52, -52, -58, -63, -65, -75, -79, -83, -80, -89, -85, -88, -101, -94, -104, -114, -93, -97, -104, -78, -92, -89, -60, -68, -48, -36, -36, -26, -21, -8, -5, 12, 23, 26, 47, 50, 54, 77, 85, 96, 109, 102, 114, 112, 109, 125, 112, 114, 118, 102, 110, 103, 99, 101, 96, 92, 79, 76, 66, 59, 61, 43, 32, 31, 14, 10, 9, -5, -2, -9, -17, -18, -28, -25, -31, -31, -31, -42, -38, -43, -41, -39, -43, -44, -47, -45, -48, -51, -53, -54, -61, -64, -67, -77, -76, -82, -81, -89, -93, -97, -106, -108, -105, -96, -99, -88, -82, -92, -67, -64, -60, -38, -38, -36, -24, -20, -16, 4, 11, 21, 36, 46, 53, 66, 85, 88, 103, 108, 102, 115, 107, 112, 115, 109, 114, 104, 106, 106, 99, 102, 101, 92, 89, 81, 67, 66, 58, 47, 39, 28, 21, 11, 12, 2, -2, 2, -12, -12, -17, -25, -24, -29, -30, -36, -39, -41, -41, -41, -39, -41, -44, -44, -47, -51, -52, -54, -59, -63, -65, -75, -79, -75, -90, -81, -89, -99, -92, -109, -109, -105, -99, -97, -92, -80, -90, -71, -58, -60, -37, -32, -37, -19, -15, -14, 9, 14, 23, 42, 46, 56, 67, 83, 96, 100, 111, 106, 111, 114, 111, 117, 111, 112, 109, 103, 107, 100, 99, 103, 92, 88, 82, 65, 66, 59, 48, 39, 27, 22, 12, 9, 5, -5, 0, -12, -16, -17, -26, -25, -26, -31, -34, -40, -41, -41, -41, -40, -42, -47, -43, -46, -46, -52, -50, -52, -61, -59, -74, -75, -77, -83, -84, -91, -92, -105, -100, -106, -109, -81, -103, -86, -73, -96, -64, -62, -59, -38, -39, -36, -28, -15, -11, 3, 18, 25, 37, 53, 53, 67, 89, 85, 106, 103, 98, 115, 99, 114, 115, 103, 116, 103, 104, 109, 98, 101, 98, 91, 84, 75, 67, 60, 55, 50, 31, 28, 20, 7, 15, 0, -3, 2, -15, -12, -19, -25, -24, -32, -32, -38, -44, -44, -45, -42, -41, -44, -43, -46, -44, -44, -58, -48, -63, -67, -63, -87, -75, -83, -90, -81, -94, -95, -95, -107, -109, -99, -95, -99, -85, -85, -90, -68, -62, -60, -36, -34, -39, -15, -13, -9, 14, 15, 29, 42, 50, 55, 68, 87, 91, 101, 107, 106, 110, 113, 114, 115, 114, 112, 108, 105, 106, 98, 98, 100, 88, 84, 75, 63, 63, 57, 46, 34, 28, 18, 10, 8, 0, -5, -5, -15, -19, -20, -26, -26, -26, -31, -36, -40, -42, -43, -42, -39, -44, -44, -42, -44, -47, -51, -52, -54, -65, -63, -76, -81, -68, -93, -84, -85, -104, -92, -105, -109, -95, -95, -96, -84, -82, -84, -64, -64, -52, -39, -37, -33, -23, -11, -9, 10, 20, 25, 49, 46, 60, 76, 82, 98, 101, 104, 110, 108, 108, 116, 111, 111, 113, 104, 108, 106, 101, 98, 99, 92, 80, 79, 63, 61, 59, 41, 35, 27, 18, 13, 9, 2, 0, -5, -12, -15, -20, -22, -26, -27, -30, -38, -39, -42, -40, -39, -40, -40, -45, -43, -47, -49, -54, -53, -57, -70, -59, -80, -77, -72, -93, -75, -91, -99, -93, -105, -108, -97, -92, -99, -80, -84, -84, -61, -59, -49, -35, -28, -34, -14, -9, -10, 19, 17, 27, 47, 47, 61, 72, 87, 95, 105, 104, 110, 111, 109, 117, 109, 111, 109, 103, 103, 102, 97, 95, 100, 85, 81, 77, 61, 64, 55, 42, 34, 26, 17, 10, 9, -3, -2, -5, -13, -15, -20, -23, -27, -27, -32, -37, -38, -41, -40, -41, -39, -43, -43, -40, -48, -47, -49, -55, -61, -59, -70, -80, -69, -87, -83, -79, -97, -89, -98, -101, -107, -96, -93, -101, -77, -90, -84, -62, -63, -49, -36, -34, -30, -15, -12, -2, 11, 20, 32, 39, 53, 56, 71, 87, 89, 103, 101, 109, 109, 109, 118, 106, 114, 111, 101, 107, 102, 93, 99, 94, 84, 85, 71, 65, 62, 54, 45, 32, 30, 16, 12, 8, -5, -2, -9, -14, -16, -24, -22, -27, -29, -31, -38, -41, -38, -44, -42, -41, -47, -45, -44, -48, -50, -50, -52, -62, -57, -69, -79, -69, -83, -88, -78, -99, -97, -92, -109, -106, -91, -100, -93, -76, -91, -80, -60, -66, -48, -37, -38, -32, -18, -15, -4, 11, 14, 31, 42, 48, 60, 69, 85, 94, 96, 102, 107, 103, 109, 115, 104, 112, 109, 100, 106, 103, 95, 97, 96, 84, 82, 73, 60, 62, 54, 41, 33, 27, 17, 14, 7, 0, 0, -8, -11, -16, -23, -23, -29, -29, -32, -39, -40, -40, -40, -41, -40, -46, -48, -45, -50, -51, -54, -56, -64, -63, -71, -78, -73, -84, -82, -87, -95, -93, -102, -102, -108, -95, -96, -95, -76, -90, -77, -57, -61, -42, -33, -35, -26, -13, -14, 3, 15, 17, 36, 45, 54, 60, 80, 89, 96, 108, 101, 111, 110, 109, 118, 107, 110, 109, 102, 103, 103, 95, 97, 96, 83, 82, 70, 60, 61, 51, 38, 28, 23, 11, 8, 4, -7, -3, -10, -16, -17, -22, -25, -27, -29, -35, -38, -43, -42, -41, -40, -39, -43, -42, -44, -45, -46, -53, -51, -55, -68, -65, -75, -79, -77, -88, -83, -94, -93, -101, -105, -96, -96, -92, -85, -85, -83, -71, -64, -57, -41, -41, -31, -27, -17, -7, 2, 18, 23, 38, 48, 51, 68, 78, 91, 98, 102, 106, 108, 110, 112, 115, 110, 115, 107, 107, 108, 99, 102, 97, 94, 87, 76, 70, 63, 60, 49, 39, 30, 22, 16, 8, 4, 0, -4, -10, -14, -20, -24, -25, -31, -30, -37, -41, -40, -41, -38, -39, -40, -42, -41, -43, -48, -44, -55, -58, -57, -71, -71, -73, -78, -79, -80, -88, -89, -95, -99, -103, -101, -88, -98, -85, -79, -90, -62, -60, -54, -35, -35, -27, -21, -9, -3, 7, 22, 26, 38, 52, 54, 67, 87, 89, 101, 105, 103, 114, 107, 117, 112, 107, 116, 100, 105, 103, 94, 98, 93, 87, 80, 73, 65, 59, 56, 45, 31, 28, 19, 6, 10, -3, -5, -4, -17, -16, -22, -24, -25, -30, -28, -39, -37, -40, -44, -40, -44, -46, -46, -47, -51, -50, -55, -55, -60, -67, -65, -81, -75, -78, -93, -78, -97, -101, -94, -113, -104, -92, -96, -91, -79, -86, -79, -58, -58, -49, -34, -34, -33, -14, -12, -5, 20, 19, 34, 49, 49, 66, 76, 91, 98, 98, 105, 104, 107, 111, 110, 109, 108, 108, 103, 101, 102, 97, 95, 96, 80, 75, 71, 56, 58, 49, 33, 28, 20, 13, 7, 4, -4, -7, -9, -18, -22, -22, -28, -30, -30, -38, -41, -41, -43, -40, -41, -40, -44, -43, -45, -48, -49, -55, -55, -59, -67, -66, -82, -70, -81, -86, -78, -101, -92, -98, -111, -98, -95, -95, -89, -76, -91, -70, -56, -61, -38, -34, -33, -25, -12, -10, 1, 21, 15, 39, 47, 48, 68, 75, 90, 97, 101, 103, 106, 106, 110, 111, 104, 111, 101, 99, 103, 96, 94, 95, 92, 75, 79, 64, 55, 64, 43, 36, 30, 17, 13, 9, 3, -4, -3, -12, -16, -18, -23, -25, -26, -29, -35, -38, -42, -40, -39, -41, -38, -48, -42, -45, -50, -49, -52, -57, -63, -57, -78, -76, -67, -94, -75, -88, -100, -92, -103, -106, -97, -88, -96, -81, -77, -85, -60, -55, -51, -35, -30, -33, -19, -9, -10, 17, 16, 30, 46, 48, 64, 72, 86, 96, 101, 104, 105, 111, 104, 116, 109, 107, 110, 104, 101, 104, 100, 93, 100, 86, 77, 78, 59, 60, 54, 40, 32, 23, 18, 9, 9, 0, -5, -6, -14, -17, -20, -23, -25, -26, -31, -35, -39, -40, -36, -40, -37, -40, -45, -42, -45, -48, -51, -50, -57, -64, -62, -76, -78, -71, -90, -84, -88, -101, -97, -105, -108, -94, -97, -92, -81, -87, -76, -63, -58, -42, -36, -33, -27, -15, -10, -2, 18, 19, 34, 49, 47, 66, 78, 86, 102, 104, 104, 111, 109, 112, 115, 112, 110, 108, 106, 101, 102, 98, 96, 97, 86, 79, 72, 62, 61, 51, 39, 32, 20, 15, 10, 2, 1, -4, -9, -13, -18, -22, -24, -25, -29, -33, -37, -41, -39, -37, -39, -39, -43, -46, -46, -49, -49, -56, -54, -57, -68, -66, -73, -77, -79, -83, -90, -96, -95, -107, -110, -98, -97, -98, -76, -87, -83, -56, -68, -49, -34, -43, -28, -26, -18, -8, 3, 14, 22, 39, 47, 54, 70, 83, 90, 101, 100, 104, 107, 102, 113, 103, 106, 109, 95, 106, 99, 95, 101, 92, 93, 83, 74, 66, 60, 56, 44, 33, 26, 17, 12, 8, 1, 2, -4, -11, -10, -21, -19, -25, -29, -28, -39, -38, -41, -41, -37, -40, -42, -43, -42, -45, -47, -48, -56, -52, -59, -69, -67, -78, -78, -79, -88, -86, -95, -100, -99, -112, -95, -92, -101, -77, -86, -86, -62, -65, -51, -39, -35, -31, -26, -8, -11, 7, 26, 21, 45, 53, 50, 76, 86, 90, 105, 102, 105, 109, 108, 115, 107, 112, 110, 100, 108, 100, 96, 100, 93, 89, 79, 72, 64, 58, 56, 42, 31, 28, 14, 10, 9, -5, -2, -6, -14, -15, -22, -22, -27, -28, -31, -41, -37, -41, -42, -37, -41, -45, -43, -45, -47, -48, -49, -58, -53, -64, -71, -68, -82, -75, -83, -91, -87, -103, -97, -104, -111, -90, -98, -95, -77, -91, -76, -61, -63, -43, -41, -35, -29, -23, -7, -7, 13, 22, 24, 50, 50, 59, 82, 82, 99, 102, 100, 110, 105, 111, 113, 104, 114, 103, 104, 107, 96, 102, 97, 92, 90, 77, 73, 64, 58, 53, 38, 31, 23, 13, 12, 3, 0, -2, -11, -10, -17, -21, -20, -29, -27, -33, -40, -38, -44, -39, -39, -43, -41, -42, -42, -46, -42, -53, -53, -52, -71, -67, -73, -83, -80, -81, -89, -93, -91, -100, -106, -97, -96, -93, -88, -81, -85, -79, -59, -58, -48, -30, -36, -28, -11, -9, -2, 21, 22, 32, 50, 52, 58, 79, 89, 90, 104, 104, 100, 113, 111, 109, 114, 109, 107, 103, 104, 99, 94, 97, 91, 78, 79, 65, 58, 61, 47, 37, 30, 23, 14, 10, 7, -7, -4, -8, -21, -17, -23, -30, -26, -30, -36, -37, -39, -38, -38, -36, -38, -45, -41, -45, -49, -51, -56, -57, -63, -64, -69, -78, -70, -80, -84, -84, -91, -100, -98, -106, -108, -90, -103, -90, -80, -93, -65, -64, -52, -38, -37, -27, -26, -12, -6, 3, 18, 22, 36, 48, 54, 69, 84, 89, 105, 103, 106, 117, 105, 117, 113, 106, 113, 101, 105, 101, 99, 98, 93, 94, 83, 75, 70, 60, 55, 49, 33, 27, 19, 10, 8, -2, -2, -7, -13, -12, -22, -20, -23, -28, -28, -35, -39, -40, -41, -40, -42, -40, -43, -42, -42, -44, -46, -49, -52, -59, -60, -70, -74, -71, -84, -82, -88, -96, -98, -100, -105, -102, -88, -95, -83, -79, -87, -62, -62, -52, -40, -39, -31, -27, -14, -10, 7, 17, 25, 42, 49, 59, 72, 85, 92, 103, 103, 102, 111, 104, 113, 110, 104, 112, 102, 107, 103, 101, 99, 97, 92, 81, 76, 64, 61, 54, 42, 33, 24, 17, 11, 8, -2, -2, -5, -13, -12, -22, -23, -26, -31, -32, -38, -40, -43, -39, -40, -41, -40, -44, -41, -44, -47, -51, -49, -62, -55, -68, -78, -68, -89, -79, -81, -96, -85, -101, -100, -103, -98, -91, -97, -79, -83, -87, -61, -64, -55, -31, -41, -29, -15, -19, 3, 9, 18, 33, 36, 56, 54, 71, 87, 87, 103, 103, 103, 110, 107, 113, 112, 108, 111, 101, 104, 103, 92, 101, 92, 84, 84, 66, 65, 59, 51, 45, 31, 27, 16, 10, 6, -3, -3, -9, -15, -16, -22, -24, -25, -30, -28, -36, -40, -36, -42, -38, -41, -45, -44, -47, -47, -49, -51, -52, -54, -62, -68, -73, -78, -81, -84, -83, -97, -94, -101, -113, -100, -99, -96, -87, -83, -85, -75, -60, -60, -43, -36, -38, -27, -20, -15, 0, 14, 19, 33, 47, 49, 67, 78, 90, 100, 103, 105, 107, 108, 110, 112, 109, 109, 107, 102, 105, 100, 99, 98, 95, 84, 80, 69, 59, 60, 48, 36, 31, 18, 14, 9, 3, -2, -5, -10, -15, -19, -24, -25, -28, -31, -34, -39, -41, -40, -38, -40, -38, -43, -43, -42, -48, -47, -53, -54, -58, -67, -63, -79, -73, -78, -90, -80, -98, -97, -101, -109, -105, -93, -98, -90, -76, -93, -66, -60, -59, -33, -42, -32, -26, -18, -9, 0, 17, 21, 38, 48, 53, 69, 82, 93, 101, 107, 102, 112, 108, 111, 115, 105, 112, 103, 105, 104, 96, 103, 95, 95, 85, 76, 68, 63, 59, 47, 38, 26, 19, 13, 7, 1, -3, -4, -14, -12, -19, -23, -21, -29, -29, -35, -40, -41, -42, -39, -43, -42, -46, -43, -47, -45, -48, -54, -47, -66, -61, -68, -85, -66, -90, -84, -84, -103, -91, -106, -105, -96, -90, -92, -81, -79, -86, -59, -59, -53, -34, -36, -33, -19, -10, -10, 17, 20, 26, 52, 48, 60, 75, 85, 95, 102, 104, 102, 111, 107, 113, 110, 109, 111, 103, 107, 102, 97, 96, 95, 85, 77, 73, 56, 60, 52, 37, 33, 22, 16, 11, 7, -3, -4, -6, -16, -14, -21, -24, -24, -28, -32, -37, -38, -42, -36, -37, -39, -39, -43, -40, -42, -48, -50, -50, -64, -57, -70, -84, -63, -90, -81, -77, -101, -85, -99, -105, -102, -100, -92, -99, -79, -89, -86, -58, -65, -49, -29, -41, -26, -11, -19, 6, 12, 14, 39, 37, 52, 60, 68, 90, 90, 104, 102, 106, 111, 108, 118, 109, 109, 111, 98, 106, 101, 90, 101, 90, 82, 86, 63, 65, 63, 48, 47, 29, 25, 16, 10, 6, -6, -3, -13, -18, -16, -26, -25, -25, -32, -30, -39, -43, -37, -43, -39, -39, -48, -44, -46, -53, -50, -56, -59, -59, -67, -72, -77, -76, -84, -83, -84, -100, -95, -103, -115, -98, -93, -103, -82, -82, -91, -60, -62, -54, -34, -35, -31, -23, -13, -11, 7, 19, 21, 43, 48, 55, 73, 85, 94, 104, 102, 109, 110, 105, 118, 107, 109, 113, 98, 106, 103, 96, 99, 98, 90, 82, 79, 62, 62, 58, 41, 34, 26, 14, 10, 8, -3, -2, -5, -14, -13, -20, -20, -24, -26, -28, -38, -39, -42, -42, -41, -41, -42, -48, -41, -43, -50, -41, -49, -59, -50, -68, -74, -67, -82, -80, -89, -87, -101, -101, -93, -121, -85, -90, -105, -65, -93, -82, -55, -69, -49, -38, -46, -32, -27, -19, -5, 3, 19, 26, 41, 53, 52, 81, 81, 95, 104, 90, 113, 101, 105, 118, 99, 113, 109, 100, 109, 104, 98, 104, 96, 89, 83, 71, 66, 57, 56, 38, 28, 29, 8, 17, 6, -2, 3, -24, -13, -79, -103, -120, -116, -104, -87, -76, -63, 63, 82, 97, 108, 119, 99, 70, 69, 80, 91, 92, 98, 115, 124, 127, 113, 82, 42, 4, -44, -70, -82, -100, -87, -62, -58, -71, -65, -79, -60, -102, -113, -62, -44, -31, -31, -22, -18, -3, 4, 11, 20, 28, 11, 15, 18, 27, 18, 7, 13, 26, 11, -19, -69, -108, -84, -51, -21, -3, -6, -18, -17, -31, -33, -18, 2, 4, 26, 47, 48, 77, 117, 127, 127, 127, 121, 110, 86, 72, 62, 46, 11, 17, -2, -7, -13, -44, -60, -61, -61, -63, -72, -79, -99, -116, -127, -128, -128, -124, -81, -51, -4, 5, -6, 7, 8, 9, 31, 31, 16, 34, 28, 34, 34, 46, 78, 84, 93, 69, 47, 40, 64, 44, 27, 22, 0, -29, -8, 15, -6, -36, -66, -68, -42, 0, 6, 1, 13, 24, 41, 64, 58, 50, 40, 4, 0, 3, -24, -3, 21, 28, 26, 9, -30, -42, -61, -85, -92, -91, -96, -87, -74, -31, -20, -38, -14, -44, -17, 18, -25, -9, 7, 1, 11, -2, -19, 12, 47, 76, 72, 58, 68, 69, 82, 86, 76, 58, 9, -23, -12, -7, -22, -2, 0, -9, -2, -15, -10, -3, -22, -17, -38, -44, -33, -24, -27, -16, 0, -15, 20, 19, 18, 1, 10, 41, -1, -25, -25, -11, 30, 37, 9, 45, 37, -30, -30, 21, 5, -26, -43, -56, -42, -48, -48, -29, -62, -76, -42, -23, -12, -14, 8, 45, 36, 40, 25, 14, 11, 40, 46, 55, 65, 30, 17, 30, 36, 33, 18, 13, 16, 15, 46, 37, 2, -1, -26, -36, -19, -21, -36, -62, -51, -48, -20, -2, 3, -12, -12, -10, -35, -37, -49, -22, 14, 61, 40, 60, 75, 33, 41, 48, 38, 29, -32, -45, -56, -64, -61, -30, -20, 30, 10, -46, -37, -35, -30, -24, -12, -23, -34, -29, -22, -20, -14, 4, 44, 77, 49, 10, 8, 24, 20, 28, 31, 27, 40, 35, 69, 39, 54, 38, 26, 22, 43, 36, 7, 14, 2, -25, -50, -51, -56, -42, -55, -46, -36, -44, -36, -35, 1, 23, 11, -3, -34, -66, -33, -12, -31, -27, -13, -1, 21, 31, 23, 0, -11, -3, -2, 9, 27, 5, -8, -2, -17, -13, 10, 9, 3, 35, 32, 43, 24, 15, 2, -15, -9, -5, 2, 5, 27, 25, 42, 76, 61, 17, 25, 14, -5, -17, -24, -6, 11, 23, 7, -8, 5, -11, -23, -27, -48, -30, -12, -26, -36, -37, -39, -46, -61, -55, -23, -20, -22, -14, -10, -16, -16, -22, -11, -3, -14, -34, -16, 9, 28, 25, 50, 63, 52, 56, 46, 50, 54, 56, 45, 54, 29, 20, 21, 0, 0, 6, 16, 28, 14, -1, -9, -10, -4, -9, -13, -7, -21, -27, -29, -40, -41, -35, -42, -64, -11, 9, 2, -12, -24, -37, -40, -34, -29, -34, -12, -26, -20, -6, -4, 5, 5, 27, 1, -17, 2, 21, 12, 8, 9, 15, 23, 24, 1, 5, 22, 25, 28, 57, 55, 41, 33, 36, 27, 5, 1, 15, 34, 23, 4, 20, 18, -1, -21, -22, -15, -17, -8, -6, -6, -12, -15, -26, 1, 29, -8, -40, -52, -55, -19, -21, -36, -48, -56, -29, -15, -29, -39, -46, -35, -14, -11, -16, 1, 27, 22, -10, -14, -7, -12, -12, 23, 55, 48, 65, 42, 20, 46, 45, 49, 42, 38, 34, 25, 33, 21, 10, 38, 40, 26, 22, 37, 33, 12, 4, 7, -14, -49, -41, -36, -53, -40, -35, -44, -31, -22, -19, -50, -78, -80, -78, -48, -31, -18, -27, -28, -7, -17, -11, 5, 32, 39, 19, 14, 22, 34, 37, 23, 20, 40, 40, 27, 14, 11, 7, 29, 34, 19, 32, 7, -15, -12, -24, -12, 8, 6, 21, 34, 29, -6, -22, -15, 1, -1, 24, 27, 20, 36, 42, 45, 27, -14, -50, -34, -14, -26, -25, -10, 10, -4, -28, -30, -34, -69, -91, -85, -74, -51, -38, -24, -19, -9, -7, -30, -35, -30, -36, -12, 25, 32, 44, 50, 45, 51, 68, 94, 90, 74, 60, 52, 64, 48, 30, 11, 11, 11, 2, 14, 24, 16, 13, -7, -17, -9, -12, -20, -32, -45, -54, -58, -35, -23, -46, -51, -33, -28, -29, -24, -36, -30, -24, -22, -20, -13, -9, -14, -7, 10, 26, 22, 9, 9, 10, -2, -9, -15, -11, -1, 19, 27, 33, 28, 5, 3, 5, 6, 10, 14, 24, 32, 36, 40, 41, 37, 19, 11, 3, -7, -10, -7, 6, 27, 38, 28, 23, 16, 18, 15, -7, -33, -20, -13, -24, -25, -19, -15, -26, -52, -56, -48, -41, -36, -30, -32, -30, -15, -38, -49, -47, -32, -17, -17, -11, -3, 3, 8, 24, 28, 16, 6, 1, 7, 28, 41, 42, 69, 87, 78, 73, 62, 30, 14, 9, 7, 15, 32, 20, 10, -8, -20, 2, 9, -2, 5, 12, -4, -12, -19, -32, -37, -29, -24, -28, -39, -43, -40, -44, -28, -25, -33, -39, -37, -34, -29, -28, -25, -19, -1, -5, -22, -12, 2, 6, 38, 46, 25, 30, 41, 47, 37, 21, 7, -7, -8, 11, 39, 48, 43, 35, 27, 25, 22, -1, -22, -11, 13, -4, -13, -3, -8, -7, -11, -17, -5, 5, 9, 8, 15, 25, 16, 22, 20, 5, -16, -27, -29, -30, -9, 9, 9, 3, -14, -50, -56, -56, -79, -92, -80, -57, -24, 12, 10, 11, 4, -22, -21, -13, -2, 4, 10, 15, 8, 35, 72, 53, 44, 25, 25, 48, 56, 69, 53, 50, 75, 85, 71, 33, 12, -16, -32, -25, -14, -5, -16, -23, -19, -22, -39, -41, -47, -45, -33, -35, -39, -38, -35, -34, -29, -28, -28, -23, -10, -7, -9, -11, -18, -5, 13, 1, -13, -8, -5, 6, 27, 46, 43, 25, 8, 11, 16, 18, 23, 30, 12, 5, 10, 7, 5, -6, -4, -5, 1, 10, 9, 15, 21, 17, 10, -8, -16, 10, 33, 34, 23, 13, 17, 17, 9, 11, 7, -4, -8, -8, -22, -27, -26, -19, -7, -18, -16, -16, -47, -62, -55, -36, -16, -25, -33, -30, -34, -42, -49, -41, -43, -31, -20, -3, 28, 48, 66, 64, 36, 20, 26, 21, 22, 39, 51, 45, 39, 40, 53, 56, 39, 24, 16, 12, 16, 24, 27, 16, 13, 7, -18, -33, -50, -47, -33, -24, -20, -26, -32, -31, -46, -53, -58, -56, -29, -13, -11, -2, 8, -11, -24, -11, -9, -6, -2, -6, 1, 4, 5, 11, 6, 7, 16, 30, 28, 19, 15, 7, 4, 11, 27, 22, 6, 9, 11, 3, 4, 17, 27, 18, 11, 12, 5, 2, -2, -6, -7, -2, 10, 12, 9, 1, -2, 3, 4, 11, 21, 30, 28, 6, -9, -18, -22, -22, -38, -41, -27, -18, -18, -27, -27, -23, -32, -35, -32, -34, -30, -25, -24, -18, -9, -5, 5, -5, -26, -19, -11, -4, 11, 37, 48, 46, 50, 53, 50, 45, 45, 37, 18, 24, 44, 38, 43, 47, 29, 15, 11, 10, 12, 4, -8, -6, -4, -17, -27, -28, -36, -34, -37, -53, -53, -46, -38, -38, -37, -28, -24, -23, -37, -42, -30, 0, 20, 18, 12, 14, 9, 2, 6, 15, 13, 10, 14, 12, 2, 12, 29, 21, 1, 7, 21, 19, 14, 15, 15, 4, -1, 5, -1, -4, 0, -2, 3, 6, 6, 13, 21, 15, 7, 3, 5, 2, -3, 3, 3, 5, 8, 10, 16, 14, -1, -7, 2, 11, 12, -10, -35, -42, -26, -21, -37, -44, -44, -47, -42, -27, -27, -23, -15, -16, -20, -21, -14, -12, -9, -7, -6, 0, 13, 30, 32, 37, 38, 31, 24, 25, 43, 54, 49, 46, 44, 40, 41, 30, 9, -1, 6, 22, 31, 22, 9, 0, -14, -23, -29, -29, -28, -35, -39, -39, -39, -33, -25, -30, -44, -49, -45, -45, -35, -19, 2, 16, 16, 9, 0, 0, 6, 2, -1, 11, 27, 40, 32, 16, -2, -2, 1, 3, 1, 7, 12, 6, 8, 11, 5, -1, -2, -1, 1, 8, 10, 5, 4, 14, 17, 6, -1, 0, 4, 4, 17, 23, 19, 25, 20, 5, -8, -9, -2, -1, -6, -3, 13, 16, 1, -13, -19, -21, -26, -34, -37, -23, -13, -13, -24, -40, -42, -40, -39, -29, -22, -21, -18, -12, -2, 18, 24, 10, 0, -6, -4, 15, 33, 34, 34, 44, 41, 31, 33, 44, 43, 31, 22, 20, 17, 16, 23, 22, 19, 21, 10, -5, -6, -9, -8, -2, -5, -16, -28, -36, -47, -53, -39, -23, -21, -24, -32, -43, -39, -34, -24, -18, -14, -11, -12, -6, 10, 29, 41, 40, 27, 14, 10, 4, 1, 3, 2, 9, 19, 21, 9, -10, -16, -10, 8, 18, 20, 13, -3, -8, -4, -1, 2, 5, 5, -1, 3, 9, 12, 16, 16, 14, 9, 3, 5, 10, 4, -6, 1, 6, 5, 13, 20, 11, 1, -7, -21, -30, -25, -12, -9, -13, -19, -24, -29, -34, -30, -32, -39, -33, -24, -20, -22, -24, -13, 3, 6, 2, 1, 3, 5, 16, 30, 35, 35, 24, 16, 15, 19, 31, 37, 33, 28, 29, 29, 30, 26, 20, 15, 13, 10, 10, 12, 9, 7, -3, -21, -39, -44, -43, -42, -34, -26, -23, -18, -12, -18, -32, -36, -31, -27, -20, -10, -7, -9, -11, -5, 2, 12, 19, 19, 25, 24, 11, 3, 15, 29, 30, 20, 9, 1, -1, 1, 5, 2, -3, -2, 0, -6, -18, -27, -20, -3, 8, 13, 15, 11, 7, 10, 18, 16, 10, 6, 3, -1, 1, 11, 19, 19, 15, 14, 5, -2, -2, -7, -12, -15, -20, -16, -10, -5, 2, 1, -13, -29, -33, -24, -10, -6, -13, -18, -23, -31, -32, -26, -22, -18, -13, -3, 2, 3, 7, 8, 10, 19, 27, 32, 33, 33, 35, 38, 43, 41, 29, 9, -4, -9, 2, 16, 17, 13, 15, 17, 13, 10, 5, -1, -8, -18, -29, -32, -27, -21, -22, -30, -31, -31, -33, -31, -27, -18, -7, -6, -15, -16, -8, -1, 4, 12, 18, 22, 20, 16, 11, 10, 14, 18, 16, 15, 14, 9, 6, 4, 3, 3, 0, -5, -13, -18, -15, -13, -9, -7, -8, -5, -2, -5, -1, 5, 8, 10, 11, 12, 17, 19, 16, 10, 4, 4, 8, 8, 8, 13, 14, 9, 3, 0, -1, 0, 0, -7, -19, -24, -20, -15, -12, -15, -21, -23, -24, -26, -28, -29, -28, -21, -10, -1, 5, 6, -3, -12, -14, -11, -1, 12, 16, 17, 28, 36, 28, 20, 25, 27, 24, 25, 28, 21, 15, 11, 3, 4, 12, 11, 0, -7, -5, -1, -1, -5, -8, -11, -17, -23, -22, -19, -21, -20, -20, -22, -24, -22, -17, -20, -24, -20, -10, 2, 10, 13, 14, 14, 11, 8, 8, 12, 17, 18, 20, 20, 14, 4, -1, -2, -1, 3, 11, 12, 6, 0, -9, -20, -25, -18, -9, -8, -13, -18, -19, -14, -6, 0, 4, 11, 19, 22, 20, 19, 15, 13, 14, 18, 17, 12, 7, 9, 14, 9, -1, -4, -1, -5, -10, -12, -16, -23, -19, -7, -5, -10, -10, -11, -19, -27, -24, -14, -6, -3, -10, -21, -24, -15, -6, 0, 9, 15, 12, 8, 6, 9, 9, 11, 20, 26, 31, 35, 30, 21, 16, 16, 13, 6, 2, 4, 5, 3, -2, -10, -13, -11, -8, -9, -13, -16, -18, -18, -19, -22, -18, -8, -3, -1, 0, -5, -11, -10, -9, -11, -9, -2, 2, 4, 10, 15, 18, 19, 21, 21, 22, 22, 15, 4, -4, -8, -7, -6, -10, -14, -18, -23, -20, -15, -8, -1, 0, -4, -7, -9, -9, -6, -2, 2, 6, 7, 4, 1, 0, 7, 13, 11, 14, 22, 22, 15, 8, 2, 4, 10, 16, 17, 13, 10, 9, 6, -3, -13, -23, -26, -21, -17, -14, -12, -13, -16, -14, -9, -8, -8, -11, -18, -18, -12, -4, 0, 2, 6, 6, -1, -6, 0, 8, 11, 13, 11, 6, 6, 9, 13, 16, 16, 15, 10, 7, 10, 10, 4, 0, -2, -3, -1, 2, 2, -1, -5, -13, -21, -27, -30, -26, -16, -4, 5, 8, 6, 2, -3, -5, -1, 4, 8, 9, 11, 11, 6, 0, 0, 7, 12, 13, 11, 7, 1, -4, -3, 0, 5, 6, 5, -2, -10, -13, -13, -10, -5, -4, -9, -18, -28, -31, -24, -14, -10, -4, 2, 5, 4, 2, 4, 13, 20, 21, 19, 14, 11, 11, 12, 13, 14, 15, 17, 18, 18, 14, 5, -3, -5, -8, -11, -11, -12, -15, -15, -13, -13, -15, -13, -12, -15, -16, -11, -7, -6, -4, -1, 4, 6, -1, -10, -11, -7, -4, -1, 4, 9, 11, 12, 9, 7, 8, 8, 7, 9, 13, 15, 12, 4, 1, 1, -2, -9, -10, -7, -1, 3, 3, -1, -9, -12, -9, -5, 1, 3, -2, -10, -10, -7, -4, 2, 8, 6, 4, 6, 5, -1, -1, 7, 17, 20, 17, 16, 19, 16, 7, -3, -8, -9, -9, -11, -15, -24, -27, -20, -15, -12, -11, -7, -3, -4, -6, -7, -6, -8, -14, -18, -18, -15, -10, -5, 3, 12, 18, 20, 17, 11, 10, 16, 21, 22, 23, 23, 22, 17, 9, 0, -3, 2, 10, 15, 16, 11, 2, -9, -19, -23, -22, -15, -10, -8, -11, -13, -15, -17, -19, -18, -15, -10, -3, 1, -2, -6, -3, 0, -3, -3, 0, 6, 10, 9, 7, 4, -1, -4, 0, 10, 17, 16, 11, 5, 0, -1, 2, 5, 1, -6, -10, -10, -8, -6, -4, -2, -4, -7, -9, -9, -6, 2, 12, 17, 16, 11, 8, 7, 6, 5, 7, 9, 12, 14, 14, 9, 3, -1, -3, -5, -4, 0, 4, -1, -10, -18, -24, -29, -28, -20, -14, -13, -12, -8, -5, -5, -9, -13, -14, -11, -10, -9, -4, 1, 3, 2, 3, 8, 16, 20, 18, 13, 10, 14, 24, 29, 29, 27, 23, 17, 14, 16, 17, 15, 9, -1, -7, -10, -14, -18, -16, -11, -8, -7, -8, -12, -18, -26, -29, -26, -19, -11, -5, -3, -3, -2, 0, 2, 0, -3, -3, -2, -3, -4, -2, -1, 3, 7, 9, 8, 7, 3, 1, 4, 5, 2, 3, 5, 5, 0, -7, -9, -6, -1, 5, 9, 8, 3, -2, -6, -5, 3, 9, 12, 11, 8, 4, 3, 4, 6, 11, 13, 8, 1, 0, 4, 9, 13, 12, 5, 2, 3, 3, 0, -6, -16, -26, -30, -28, -26, -22, -18, -17, -19, -22, -24, -19, -12, -7, -2, 1, 0, -2, -4, -5, -2, 4, 10, 14, 15, 15, 16, 16, 17, 19, 22, 26, 25, 19, 13, 10, 7, 9, 11, 10, 7, 4, 1, -5, -8, -8, -4, 0, 1, -4, -11, -16, -17, -16, -14, -12, -10, -11, -14, -15, -16, -13, -9, -3, 1, 2, 1, 0, 0, -3, -9, -13, -10, -8, -7, -4, 0, 3, 6, 9, 9, 5, 3, 3, 5, 8, 12, 12, 6, -1, -2, 2, 8, 8, 4, -2, -5, -1, 4, 10, 13, 14, 13, 13, 14, 14, 12, 10, 8, 8, 8, 6, 6, 9, 6, -1, -9, -15, -19, -22, -24, -23, -25, -25, -23, -20, -19, -19, -21, -20, -20, -21, -19, -11, -2, 2, 1, 0, 3, 9, 13, 15, 16, 14, 10, 5, 3, 8, 14, 16, 18, 20, 22, 24, 21, 15, 9, 6, 8, 14, 18, 15, 9, 4, 1, 0, -2, -4, -4, -3, -3, -4, -7, -11, -13, -12, -11, -15, -19, -22, -25, -25, -21, -14, -11, -15, -19, -18, -14, -7, -1, 4, 2, -3, -6, -4, 0, 5, 10, 16, 17, 12, 7, 2, -1, -3, 0, 3, 6, 10, 14, 12, 6, 2, 5, 10, 15, 18, 18, 16, 14, 11, 6, 4, 3, 1, 1, 2, 6, 9, 9, 3, -2, -3, -4, -6, -8, -10, -15, -19, -20, -19, -18, -17, -15, -16, -17, -18, -20, -22, -21, -16, -11, -4, 1, 0, -4, -4, -1, 1, 2, 4, 4, 3, 3, 4, 7, 11, 16, 21, 20, 15, 11, 9, 12, 16, 21, 24, 23, 21, 17, 13, 11, 9, 4, 0, 0, 1, 3, 4, 0, -4, -7, -7, -9, -13, -17, -20, -22, -23, -21, -16, -12, -12, -15, -17, -17, -15, -12, -10, -10, -11, -12, -15, -15, -10, -4, 0, -1, -1, 1, 4, 7, 13, 19, 22, 23, 21, 19, 18, 17, 11, 5, 2, 5, 10, 13, 15, 15, 14, 13, 10, 5, 1, 0, 2, 5, 8, 10, 9, 6, 4, 2, -1, -5, -7, -8, -7, -8, -11, -13, -14, -16, -19, -21, -22, -22, -24, -23, -20, -17, -16, -16, -15, -16, -16, -15, -13, -11, -9, -5, 0, 6, 12, 15, 18, 18, 17, 17, 19, 20, 19, 19, 20, 23, 25, 25, 23, 20, 17, 13, 11, 9, 9, 8, 6, 3, 1, -2, -5, -5, -2, -1, -3, -7, -6, -3, 0, -2, -9, -21, -29, -32, -32, -30, -27, -27, -29, -30, -28, -24, -23, -21, -16, -7, 0, 1, 2, 2, 4, 7, 10, 14, 16, 14, 12, 13, 15, 18, 20, 22, 23, 20, 15, 8, 3, 2, 7, 13, 15, 13, 7, 2, 0, 0, -1, -2, -1, 1, 2, 1, 0, 2, 3, 4, 4, 6, 7, 5, 0, -10, -21, -30, -36, -36, -33, -28, -23, -18, -15, -14, -17, -19, -19, -17, -12, -5, -2, -2, -3, -1, 2, 6, 10, 12, 14, 13, 12, 13, 18, 25, 29, 28, 24, 19, 14, 10, 6, 6, 9, 12, 13, 15, 17, 18, 18, 14, 7, 0, -1, 1, 1, -2, -6, -8, -10, -11, -13, -17, -19, -18, -17, -16, -14, -14, -15, -17, -19, -22, -26, -26, -24, -20, -17, -14, -13, -12, -10, -7, -4, 1, 5, 7, 9, 10, 13, 15, 17, 18, 21, 24, 22, 21, 19, 17, 15, 13, 14, 14, 16, 17, 18, 16, 12, 10, 8, 6, 5, 3, 0, -3, -6, -7, -5, -4, -4, -5, -5, -4, -4, -4, -8, -13, -19, -24, -27, -28, -27, -25, -25, -27, -27, -25, -19, -14, -8, -3, 1, 6, 9, 8, 3, -3, -6, -4, -1, 4, 9, 14, 18, 20, 22, 22, 23, 23, 22, 21, 20, 20, 21, 21, 19, 15, 9, 3, -2, -4, -3, 0, 2, 2, 2, 3, 3, 1, -4, -10, -15, -19, -19, -16, -11, -7, -7, -9, -13, -17, -23, -28, -30, -29, -24, -20, -18, -19, -20, -19, -18, -19, -18, -13, -5, 1, 6, 9, 11, 13, 16, 21, 26, 29, 30, 29, 29, 28, 26, 23, 20, 20, 21, 21, 20, 18, 15, 9, 2, -4, -6, -5, -3, -3, -4, -6, -7, -9, -10, -10, -10, -10, -11, -13, -12, -11, -8, -6, -6, -10, -17, -26, -32, -35, -35, -34, -32, -27, -19, -9, -3, -1, -2, -5, -7, -6, -1, 7, 14, 18, 21, 23, 25, 26, 26, 23, 20, 20, 23, 24, 24, 21, 19, 14, 8, 2, -1, 0, 1, 2, 3, 6, 8, 8, 5, 2, -2, -5, -5, -4, -1, 1, 1, -1, -6, -9, -11, -13, -17, -20, -24, -26, -27, -26, -23, -21, -20, -23, -26, -27, -26, -24, -20, -15, -9, -2, 4, 8, 10, 13, 16, 19, 21, 23, 25, 28, 33, 36, 38, 38, 35, 32, 29, 24, 16, 11, 6, 2, -2, -6, -6, -5, -4, -4, -7, -11, -14, -13, -10, -8, -8, -8, -9, -11, -12, -12, -11, -11, -12, -14, -17, -19, -19, -18, -18, -20, -22, -23, -21, -18, -14, -11, -8, -4, -1, 5, 11, 13, 11, 8, 6, 7, 9, 11, 13, 15, 19, 22, 23, 25, 27, 27, 22, 17, 11, 6, 4, 5, 9, 13, 15, 15, 11, 6, 0, -4, -7, -8, -6, -3, -2, -3, -6, -9, -13, -18, -22, -23, -20, -15, -11, -10, -11, -14, -19, -24, -27, -28, -28, -27, -26, -23, -19, -15, -10, -6, -1, 4, 8, 10, 11, 11, 13, 15, 17, 20, 23, 24, 24, 26, 28, 28, 28, 27, 26, 24, 22, 20, 16, 13, 10, 8, 6, 3, -3, -9, -15, -17, -16, -15, -13, -13, -14, -17, -19, -20, -20, -17, -14, -12, -13, -14, -13, -13, -14, -15, -14, -13, -12, -12, -12, -10, -8, -7, -8, -9, -9, -7, -4, 0, 3, 6, 8, 10, 12, 14, 18, 22, 25, 26, 27, 28, 28, 27, 24, 20, 16, 13, 11, 9, 6, 3, 0, -3, -3, -2, 1, 3, 5, 3, 0, -4, -8, -12, -17, -21, -22, -20, -17, -15, -14, -14, -13, -15, -19, -22, -21, -18, -14, -13, -15, -16, -17, -17, -19, -19, -16, -11, -4, 1, 6, 10, 13, 17, 20, 23, 24, 24, 24, 25, 28, 33, 37, 38, 35, 30, 24, 20, 16, 13, 9, 2, -4, -8, -8, -8, -7, -7, -9, -12, -16, -18, -18, -16, -15, -16, -16, -16, -13, -10, -10, -11, -13, -15, -15, -15, -15, -16, -17, -16, -14, -13, -13, -13, -13, -12, -9, -5, -2, 1, 3, 6, 12, 18, 22, 22, 21, 18, 16, 16, 19, 23, 29, 32, 30, 24, 18, 13, 9, 6, 3, 0, -2, -4, -6, -8, -10, -11, -10, -6, -3, -2, -3, -5, -5, -6, -6, -7, -6, -5, -4, -5, -8, -10, -11, -12, -14, -16, -18, -20, -21, -21, -22, -23, -24, -24, -22, -18, -11, -4, 1, 4, 5, 6, 8, 11, 15, 20, 24, 26, 27, 28, 31, 32, 31, 30, 28, 27, 24, 20, 17, 14, 12, 9, 3, -3, -9, -12, -15, -16, -17, -15, -13, -10, -10, -11, -13, -14, -15, -17, -19, -21, -23, -24, -22, -18, -13, -9, -8, -8, -8, -9, -9, -9, -7, -4, 0, 2, 3, 5, 5, 3, 3, 4, 5, 6, 7, 10, 14, 17, 20, 20, 20, 21, 22, 20, 18, 16, 15, 14, 12, 9, 7, 6, 4, 2, -2, -5, -7, -9, -9, -8, -5, -2, 0, 0, -1, -3, -7, -12, -16, -16, -15, -13, -12, -13, -13, -12, -11, -11, -12, -15, -19, -23, -24, -22, -19, -16, -13, -10, -5, -1, 3, 6, 7, 8, 8, 10, 13, 17, 21, 25, 27, 28, 28, 26, 24, 24, 25, 27, 28, 29, 28, 25, 19, 12, 4, -3, -10, -15, -19, -22, -24, -25, -26, -25, -23, -21, -20, -18, -17, -16, -14, -12, -11, -12, -14, -14, -13, -13, -15, -16, -16, -16, -15, -11, -4, 0, -2, 0, 0, 3, 14, 34, 24, -3, -14, -12, 6, 6, -11, -23, -5, 15, 20, 15, -19, -12, 3, 19, 11, -5, 1, 4, 7, -13, -3, 5, -13, 0, -2, 8, 0, -6, 16, 23, 13, 6, 2, 14, 25, 2, 11, 3, -7, -8, -24, -6, -4, -18, 6, 30, 14, 9, 0, 0, 13, -7, 0, -3, 9, 8, -6, -14, -15, -23, -19, -7, 0, -3, 1, -8, -10, -10, -17, -12, -7, -10, 1, -12, -13, 0, -15, -20, -25, -16, -6, -7, -6, -6, -2, -4, -13, -12, -6, -6, -5, 2, 8, -5, -13, -3, -4, -11, -16, -3, 12, -2, -8, -4, -4, 4, -15, -17, -6, -2, 5, -4, 3, -2, -10, -4, -5, -7, -8, 4, 17, 1, -3, -14, -4, -2, -7, -4, -6, 10, 5, -6, -7, -8, 10, -5, -3, 3, -8, 11, 7, -5, -3, -13, -7, 0, -6, 4, 0, -7, 12, -9, -17, -7, 5, 2, -3, -4, -7, 7, -2, -13, -5, -2, 5, 4, 0, 7, -3, 4, 1, -2, -4, 6, 8, 8, 0, -2, 2, 3, 2, 1, -2, 5, 12, 6, 3, 2, -3, 2, 3, 1, 8, 6, 7, 2, -5, -3, 1, 5, 2, 0, -3, 2, 7, 2, 0, -9, 0, 5, 1, 3, 1, 4, 6, -5, -3, -2, 2, 6, 4, 6, 1, 2, 4, 4, -2, 2, 5, 5, 7, 7, 2, 6, 0, 3, 0, -3, 8, 4, 4, 9, -3, 2, 1, 1, 2, 1, 5, 5, 4, 6, 1, -6, -2, 3, 5, 6, 4, 3, 4, 1, 2, -4, 0, 6, 2, 2, 4, 3, 5, -3, -2, -5, -3, 5, 2, 1, 3, 1, -2, -3, -4, -6, 3, 5, 1, -2, 1, 2, -2, -2, -2, -3, 3, 5, 3, 4, 2, 2, 1, 0, 1, 4, 9, 9, 5, 2, 1, 6, 4, 4, 5, 5, 7, 8, 4, 5, 1, 2, 3, 1, 1, 4, 2, 3, 0, -4, -7, -5, 0, -3, -3, -3, -5, 0, -8, -7, -8, -5, -3, -6, -3, -4, -5, 0, -7, -4, -5, -3, 1, 1, -2, 1, -2, 2, 0, 0, -2, 3, 5, 4, 5, 4, 2, 4, 2, 4, 5, 6, 5, 6, 4, 4, 4, 4, 3, 4, 2, 4, 4, 2, -2, -2, 0, -3, -3, -3, -4, -2, -7, -6, -7, -9, -7, -10, -9, -10, -10, -8, -11, -9, -9, -12, -10, -13, -12, -7, -8, -6, -6, -9, -6, -5, -3, 0, 0, 1, 1, 4, 3, 4, 8, 6, 8, 7, 6, 10, 9, 12, 12, 11, 12, 8, 13, 10, 11, 10, 8, 9, 8, 6, 9, 4, 5, 0, -3, -5, -5, -6, -7, -9, -12, -15, -17, -21, -18, -22, -21, -23, -25, -24, -27, -27, -26, -30, -27, -27, -28, -20, -22, -19, -14, -15, -12, -10, -10, -2, 3, 4, 12, 12, 14, 20, 17, 25, 27, 29, 33, 35, 35, 40, 38, 41, 39, 36, 38, 36, 36, 38, 31, 33, 25, 21, 14, 8, 1, 2, 0, -3, -5, -15, -23, -28, -40, -39, -43, -46, -43, -52, -53, -59, -66, -62, -69, -63, -64, -64, -50, -56, -44, -45, -43, -38, -36, -31, -20, -8, 4, 12, 19, 18, 28, 31, 40, 52, 57, 68, 73, 73, 77, 73, 81, 79, 82, 82, 77, 82, 77, 75, 69, 59, 53, 42, 33, 24, 22, 17, 11, 1, -17, -25, -36, -42, -46, -55, -60, -64, -73, -77, -88, -90, -92, -97, -98, -100, -100, -92, -85, -79, -80, -76, -79, -69, -56, -50, -32, -24, -15, 0, -2, 11, 15, 29, 45, 55, 67, 72, 82, 88, 95, 101, 102, 109, 109, 112, 109, 110, 110, 106, 104, 91, 81, 77, 68, 66, 54, 42, 32, 14, 6, -6, -12, -20, -29, -43, -55, -65, -76, -76, -85, -89, -97, -105, -107, -114, -115, -117, -117, -113, -112, -104, -101, -91, -85, -84, -70, -72, -55, -42, -34, -14, -8, 5, 16, 22, 35, 44, 57, 69, 78, 89, 94, 101, 104, 109, 109, 119, 118, 117, 120, 110, 114, 114, 99, 102, 84, 74, 72, 57, 52, 43, 32, 22, 10, -7, -20, -28, -34, -47, -54, -60, -67, -71, -80, -87, -90, -105, -105, -110, -120, -115, -120, -123, -113, -111, -109, -97, -98, -92, -83, -82, -76, -63, -61, -48, -39, -30, -16, -3, 10, 22, 32, 42, 49, 61, 67, 76, 84, 91, 101, 105, 115, 116, 117, 125, 115, 119, 116, 106, 111, 102, 97, 92, 84, 79, 70, 64, 50, 45, 31, 19, 14, -2, -9, -19, -30, -35, -47, -54, -62, -67, -73, -82, -86, -96, -100, -105, -109, -116, -118, -120, -120, -117, -111, -110, -97, -96, -90, -84, -78, -73, -64, -55, -50, -39, -25, -20, 1, 11, 19, 37, 40, 51, 61, 68, 76, 85, 94, 97, 105, 114, 112, 120, 122, 119, 121, 117, 110, 106, 105, 92, 90, 84, 69, 71, 57, 48, 45, 29, 22, 14, -2, -9, -22, -31, -40, -47, -59, -62, -68, -76, -80, -87, -97, -96, -111, -111, -116, -124, -119, -123, -120, -109, -109, -98, -95, -93, -84, -81, -75, -66, -55, -51, -37, -28, -16, 1, 12, 23, 39, 40, 55, 59, 68, 77, 86, 94, 103, 104, 116, 117, 118, 125, 122, 117, 120, 107, 108, 104, 95, 92, 85, 72, 70, 60, 48, 43, 29, 18, 10, -7, -12, -22, -30, -38, -49, -58, -63, -72, -75, -84, -90, -93, -100, -110, -103, -121, -115, -115, -124, -110, -112, -111, -92, -98, -86, -81, -77, -69, -61, -53, -48, -34, -27, -13, 1, 9, 28, 37, 45, 58, 59, 76, 78, 85, 97, 98, 109, 114, 111, 123, 120, 119, 121, 116, 111, 110, 101, 93, 92, 79, 73, 68, 55, 52, 40, 30, 21, 10, 0, -13, -23, -29, -41, -47, -58, -64, -69, -75, -84, -89, -93, -103, -105, -110, -120, -115, -117, -128, -105, -114, -109, -88, -102, -86, -76, -84, -64, -63, -56, -43, -37, -25, -10, 4, 11, 31, 36, 46, 56, 58, 74, 78, 84, 100, 95, 110, 114, 110, 124, 120, 116, 121, 110, 105, 108, 97, 96, 91, 79, 75, 66, 57, 51, 38, 29, 17, 5, -3, -13, -20, -28, -40, -46, -55, -66, -68, -76, -85, -88, -97, -102, -106, -110, -117, -115, -120, -122, -108, -117, -103, -98, -96, -86, -79, -77, -66, -59, -54, -46, -33, -31, -10, -2, 11, 27, 36, 47, 58, 62, 74, 78, 86, 94, 96, 106, 109, 115, 120, 118, 121, 119, 112, 114, 104, 98, 94, 85, 77, 72, 63, 56, 49, 37, 31, 20, 6, -2, -15, -24, -33, -44, -50, -58, -63, -68, -76, -82, -89, -95, -105, -105, -116, -118, -117, -126, -114, -111, -118, -92, -105, -92, -83, -88, -72, -71, -65, -51, -50, -31, -25, -9, 2, 16, 29, 35, 50, 53, 67, 73, 75, 92, 88, 104, 112, 108, 122, 117, 119, 123, 114, 116, 110, 104, 98, 94, 86, 80, 75, 63, 59, 47, 36, 29, 13, 9, -5, -16, -21, -36, -40, -50, -61, -61, -73, -77, -85, -93, -95, -103, -108, -117, -120, -118, -125, -117, -108, -116, -96, -98, -97, -83, -82, -78, -66, -61, -54, -43, -32, -25, -2, 3, 16, 33, 36, 52, 56, 66, 75, 78, 94, 91, 103, 113, 108, 122, 119, 119, 121, 116, 112, 110, 106, 93, 96, 83, 76, 74, 59, 58, 47, 34, 28, 14, 6, -6, -17, -27, -36, -44, -54, -61, -63, -70, -76, -86, -90, -99, -102, -108, -117, -115, -121, -123, -111, -120, -102, -100, -101, -84, -91, -76, -74, -70, -54, -56, -41, -30, -20, -3, 8, 23, 31, 46, 47, 59, 70, 71, 83, 89, 90, 108, 108, 115, 120, 121, 122, 118, 118, 109, 110, 102, 93, 93, 82, 78, 72, 62, 57, 45, 37, 22, 15, 4, -10, -18, -30, -36, -42, -54, -57, -63, -68, -77, -86, -91, -102, -103, -108, -117, -114, -119, -117, -115, -110, -106, -100, -91, -99, -79, -81, -77, -59, -61, -50, -36, -33, -16, -4, 10, 16, 35, 39, 48, 62, 64, 76, 85, 89, 98, 105, 110, 113, 120, 119, 118, 123, 112, 111, 110, 100, 98, 93, 82, 78, 70, 58, 54, 45, 30, 24, 12, 0, -7, -20, -28, -36, -45, -55, -61, -66, -73, -79, -88, -93, -103, -105, -112, -119, -115, -124, -123, -109, -119, -103, -98, -102, -92, -84, -83, -75, -62, -59, -50, -34, -34, -12, 1, 7, 26, 33, 42, 50, 62, 67, 76, 88, 90, 101, 110, 108, 118, 121, 119, 122, 121, 111, 113, 110, 98, 98, 91, 80, 78, 66, 58, 53, 40, 29, 20, 8, -4, -11, -22, -33, -37, -49, -57, -61, -68, -77, -81, -90, -96, -101, -110, -112, -116, -120, -116, -121, -119, -104, -111, -96, -91, -96, -79, -79, -76, -59, -57, -46, -33, -25, -14, 5, 11, 26, 39, 42, 55, 61, 70, 81, 86, 94, 101, 105, 114, 116, 120, 121, 119, 119, 115, 111, 107, 102, 94, 90, 82, 73, 68, 59, 50, 41, 28, 20, 7, -4, -12, -22, -30, -41, -48, -56, -62, -69, -75, -83, -90, -98, -100, -107, -111, -119, -112, -124, -120, -107, -119, -101, -93, -104, -80, -85, -83, -61, -65, -55, -40, -38, -25, -7, -3, 13, 29, 34, 45, 57, 59, 74, 79, 87, 98, 98, 108, 111, 112, 122, 117, 119, 119, 111, 110, 107, 96, 96, 89, 76, 74, 63, 54, 51, 35, 27, 19, 5, -3, -12, -25, -29, -43, -52, -58, -64, -71, -78, -82, -92, -98, -101, -108, -110, -114, -120, -119, -118, -115, -110, -106, -95, -97, -82, -84, -76, -62, -63, -51, -42, -39, -20, -12, 2, 15, 29, 36, 47, 58, 62, 74, 80, 85, 95, 101, 106, 111, 116, 118, 117, 122, 113, 115, 111, 99, 103, 90, 85, 80, 68, 63, 56, 46, 36, 28, 17, 5, -5, -19, -25, -35, -43, -52, -58, -62, -72, -75, -83, -94, -94, -105, -105, -115, -115, -116, -122, -114, -112, -108, -98, -99, -89, -86, -82, -72, -69, -58, -52, -44, -31, -21, -6, 4, 17, 28, 39, 48, 53, 66, 72, 80, 88, 92, 104, 108, 113, 116, 119, 121, 116, 119, 112, 108, 107, 94, 94, 85, 79, 72, 62, 57, 48, 37, 25, 17, 8, -8, -15, -26, -35, -42, -55, -59, -65, -73, -75, -87, -89, -97, -104, -109, -116, -116, -121, -120, -120, -109, -108, -103, -90, -97, -78, -78, -77, -60, -64, -50, -41, -34, -16, -7, 9, 19, 33, 42, 52, 60, 65, 77, 79, 87, 96, 99, 109, 113, 118, 124, 117, 121, 117, 109, 110, 99, 94, 93, 83, 77, 73, 63, 55, 50, 32, 26, 18, 0, -6, -20, -29, -34, -49, -53, -57, -63, -71, -76, -83, -91, -97, -108, -112, -114, -122, -115, -124, -112, -105, -112, -89, -99, -90, -78, -89, -72, -66, -61, -49, -41, -28, -16, 2, 6, 25, 35, 36, 53, 54, 67, 77, 79, 93, 97, 105, 112, 111, 122, 118, 119, 117, 112, 109, 108, 99, 95, 92, 82, 76, 71, 59, 56, 43, 30, 24, 10, 0, -9, -18, -26, -36, -45, -55, -59, -68, -75, -81, -88, -94, -99, -106, -109, -110, -119, -117, -119, -116, -111, -105, -101, -91, -92, -83, -75, -75, -61, -52, -52, -35, -29, -18, 0, 9, 22, 36, 41, 51, 64, 68, 78, 88, 90, 101, 103, 109, 113, 115, 121, 117, 118, 116, 109, 109, 102, 94, 90, 80, 71, 67, 57, 47, 42, 30, 19, 14, -4, -9, -19, -31, -36, -50, -55, -61, -68, -74, -79, -87, -93, -101, -107, -107, -115, -118, -118, -123, -112, -110, -109, -92, -93, -94, -74, -83, -71, -57, -61, -45, -34, -31, -10, 0, 12, 27, 37, 42, 55, 61, 70, 77, 87, 95, 96, 106, 112, 113, 123, 122, 117, 122, 112, 109, 110, 96, 96, 92, 76, 74, 68, 55, 50, 40, 28, 20, 7, -6, -10, -23, -31, -42, -51, -59, -65, -70, -76, -82, -88, -92, -104, -104, -105, -122, -113, -122, -126, -106, -119, -103, -91, -99, -82, -80, -76, -66, -59, -54, -46, -34, -30, -9, 1, 13, 33, 34, 51, 57, 63, 76, 77, 91, 95, 95, 110, 108, 115, 122, 120, 120, 123, 112, 110, 110, 94, 95, 87, 70, 74, 62, 55, 50, 39, 29, 20, 7, -5, -13, -26, -35, -44, -56, -61, -65, -69, -75, -83, -86, -98, -104, -104, -121, -115, -119, -128, -110, -117, -116, -92, -100, -90, -78, -83, -75, -63, -64, -55, -41, -39, -20, -7, 1, 21, 31, 40, 51, 55, 67, 72, 77, 91, 93, 99, 110, 109, 118, 125, 118, 124, 119, 108, 114, 101, 93, 96, 81, 75, 73, 59, 57, 48, 35, 27, 15, 1, -7, -20, -29, -37, -49, -56, -61, -65, -69, -74, -83, -91, -98, -107, -113, -117, -120, -122, -118, -115, -111, -103, -101, -92, -89, -85, -80, -77, -65, -61, -51, -41, -33, -16, -4, 8, 21, 34, 40, 49, 57, 63, 73, 82, 89, 98, 104, 109, 117, 118, 123, 122, 119, 116, 110, 108, 100, 97, 93, 83, 80, 70, 64, 55, 45, 34, 22, 12, -2, -10, -20, -30, -35, -48, -55, -62, -67, -71, -78, -86, -91, -101, -104, -110, -117, -117, -120, -123, -111, -111, -110, -90, -99, -90, -76, -85, -71, -58, -63, -45, -37, -33, -14, 1, 4, 27, 34, 41, 53, 59, 66, 79, 84, 92, 100, 103, 110, 115, 116, 123, 118, 118, 117, 107, 110, 101, 95, 93, 79, 76, 68, 57, 52, 43, 30, 23, 11, -3, -8, -20, -30, -34, -48, -55, -60, -69, -74, -81, -89, -92, -101, -105, -108, -114, -117, -118, -122, -112, -113, -108, -95, -101, -87, -82, -83, -68, -60, -56, -45, -38, -28, -17, -2, 6, 23, 33, 40, 54, 60, 68, 80, 85, 94, 96, 103, 109, 110, 119, 118, 118, 121, 113, 112, 110, 100, 98, 90, 77, 73, 66, 55, 51, 41, 29, 25, 8, 1, -9, -23, -28, -42, -51, -59, -64, -67, -75, -79, -86, -94, -98, -105, -111, -115, -117, -121, -123, -111, -120, -102, -95, -100, -79, -84, -81, -61, -69, -55, -46, -42, -27, -14, -3, 11, 30, 35, 49, 57, 60, 76, 76, 86, 95, 95, 109, 108, 116, 122, 121, 123, 120, 116, 114, 106, 100, 94, 88, 78, 73, 65, 59, 52, 38, 33, 20, 10, -2, -15, -22, -32, -42, -51, -58, -62, -67, -77, -80, -86, -94, -100, -106, -113, -115, -119, -122, -118, -117, -107, -106, -98, -89, -89, -78, -76, -71, -57, -56, -46, -36, -25, -12, 0, 16, 26, 39, 49, 54, 67, 72, 80, 88, 94, 101, 104, 115, 113, 121, 125, 116, 123, 116, 110, 109, 98, 93, 88, 78, 69, 65, 56, 47, 42, 27, 20, 8, -6, -15, -27, -33, -43, -53, -58, -64, -68, -74, -86, -87, -96, -106, -103, -117, -116, -117, -123, -117, -106, -114, -97, -96, -96, -81, -81, -80, -62, -64, -49, -45, -34, -19, -8, 4, 17, 28, 40, 47, 54, 66, 73, 79, 93, 95, 102, 113, 110, 117, 123, 119, 121, 117, 113, 111, 106, 96, 95, 88, 78, 72, 63, 55, 47, 35, 26, 14, 4, -9, -19, -24, -35, -43, -51, -61, -65, -72, -79, -88, -88, -99, -107, -107, -120, -114, -120, -122, -113, -116, -102, -106, -95, -89, -95, -72, -80, -70, -50, -58, -37, -30, -20, -5, 6, 18, 29, 44, 45, 57, 72, 68, 89, 89, 97, 109, 104, 120, 113, 118, 124, 112, 120, 112, 107, 106, 96, 91, 87, 78, 66, 65, 52, 40, 39, 17, 17, 4, -13, -13, -30, -35, -44, -58, -59, -66, -72, -78, -85, -93, -97, -106, -114, -110, -120, -120, -118, -120, -109, -110, -98, -100, -89, -81, -87, -68, -68, -59, -44, -46, -29, -18, -5, 5, 22, 32, 39, 54, 56, 68, 79, 79, 94, 98, 102, 110, 112, 117, 119, 124, 117, 116, 116, 104, 106, 97, 89, 86, 74, 67, 60, 53, 41, 34, 24, 12, 4, -9, -19, -28, -38, -47, -58, -60, -68, -73, -77, -88, -93, -96, -111, -109, -115, -124, -118, -122, -120, -107, -109, -102, -91, -95, -82, -78, -78, -60, -59, -51, -36, -35, -14, -3, 6, 24, 34, 41, 56, 59, 67, 81, 82, 92, 103, 102, 112, 119, 114, 123, 123, 116, 121, 112, 106, 107, 93, 91, 84, 74, 69, 61, 52, 43, 32, 21, 13, -2, -10, -22, -31, -38, -51, -56, -59, -69, -71, -76, -87, -90, -100, -107, -110, -119, -118, -120, -123, -108, -118, -101, -92, -102, -77, -85, -83, -63, -71, -58, -45, -44, -27, -15, -2, 10, 30, 32, 46, 57, 56, 74, 73, 84, 93, 95, 109, 108, 117, 117, 124, 119, 119, 119, 112, 109, 100, 96, 90, 81, 75, 65, 59, 51, 41, 33, 22, 12, 0, -12, -23, -30, -40, -51, -57, -64, -71, -73, -83, -84, -95, -102, -102, -116, -117, -118, -128, -116, -114, -116, -102, -99, -95, -86, -80, -80, -71, -58, -61, -46, -38, -30, -10, -4, 12, 26, 37, 47, 54, 67, 68, 79, 89, 86, 104, 104, 111, 118, 118, 123, 121, 119, 116, 112, 109, 99, 96, 88, 80, 75, 66, 58, 49, 41, 29, 19, 10, -5, -10, -25, -35, -39, -53, -58, -64, -69, -75, -81, -87, -100, -99, -112, -116, -118, -126, -123, -115, -120, -111, -102, -100, -93, -86, -85, -76, -69, -64, -56, -47, -38, -25, -10, 4, 16, 31, 40, 46, 61, 65, 70, 83, 86, 93, 103, 105, 114, 125, 118, 124, 125, 112, 120, 111, 98, 103, 91, 86, 83, 71, 66, 61, 49, 38, 32, 16, 7, -4, -17, -26, -36, -44, -54, -60, -59, -71, -75, -79, -94, -95, -103, -117, -112, -120, -127, -120, -118, -117, -104, -102, -99, -88, -84, -86, -73, -70, -64, -51, -47, -37, -17, -10, 7, 19, 32, 40, 52, 56, 67, 73, 80, 87, 92, 103, 109, 110, 123, 119, 121, 126, 111, 113, 112, 98, 98, 91, 80, 80, 71, 60, 61, 47, 36, 30, 13, 5, -5, -19, -27, -35, -43, -52, -58, -62, -71, -76, -84, -96, -100, -105, -118, -115, -121, -123, -121, -114, -117, -110, -98, -105, -91, -83, -90, -71, -68, -64, -48, -43, -33, -17, -5, 3, 23, 32, 38, 54, 59, 66, 79, 82, 92, 100, 105, 108, 116, 119, 117, 126, 116, 115, 118, 106, 105, 99, 91, 85, 78, 67, 60, 54, 41, 33, 24, 11, 0, 3, 10, 14, -8, 46, 7, -20, -23, -28, 17, 9, 47, -7, -15, -35, -1, -26, 44, 34, -31, 31, -47, -32, 30, -2, 32, 15, -15, -17, -39, 16, -2, 26, 23, 3, -43, 11, -37, 14, 37, 7, 4, -21, -30, -9, 14, 18, 38, -13, -16, -21, -24, 8, 38, 3, 16, -29, -11, -26, 20, 15, 24, -9, 0, -34, -21, 32, -16, 41, -1, -20, -7, -7, -7, 27, 0, -2, -2, -11, -11, 19, -16, 32, -19, -4, 11, -40, 49, -13, -12, 12, -32, 12, 17, 1, 23, -34, -20, 14, -20, 33, 44, -51, 7, -21, -38, 46, 19, 37, -28, -29, -17, -40, 63, 36, -33, 42, -45, -57, 16, 37, -3, 54, 0, -64, -25, -7, 15, 37, 34, -2, -65, -12, -3, -7, 76, -2, -6, -28, -22, -30, 40, 11, 12, 21, -43, -6, -1, -31, 73, -35, 33, -1, -67, 29, -24, 16, 42, 4, -26, 17, -71, 32, 0, 0, 72, -56, 4, -2, -75, 76, -25, 39, 24, -42, -6, -20, -31, 56, 1, 3, 49, -63, -12, -16, -10, 49, 12, 29, -32, -59, 35, -39, 35, 45, -33, -21, 46, -68, 13, 16, 12, 0, 2, 32, -70, 12, 30, -62, 64, 5, -31, 22, -30, 11, -30, 43, 2, -8, 16, -3, -60, 39, -11, -13, 63, -32, 8, -6, -45, 39, -38, 30, 49, -89, 96, -84, 0, 43, -51, 52, -4, -6, 7, -31, -10, 12, -22, 62, 8, -57, 65, -101, 1, 69, -46, 76, -18, -34, -24, -33, 50, -6, 55, 16, -70, -19, 2, -33, 59, 61, -40, 7, -44, -33, -7, 61, 31, -15, 5, -32, -70, 47, 34, 8, 22, -16, -44, -47, 56, -6, 12, 56, -46, -32, -3, 7, -4, 42, 19, -41, -35, 41, -59, 43, 45, -44, 9, -9, -7, -19, 36, 2, -50, 49, -6, -34, 33, -1, -38, 17, 44, -33, 5, 28, -68, -13, 62, -25, 15, 45, -57, -32, 23, -14, 37, 11, 29, -56, -48, 46, -55, 48, 94, -74, 22, -40, -59, 36, 9, 75, -19, -31, 6, -104, 39, 80, -23, 59, -12, -104, 10, -12, 24, 59, 5, 9, -78, -12, 24, -47, 116, -6, -51, 34, -71, -26, 55, 3, 11, 38, -31, -9, -45, 21, -11, 4, 92, -79, 16, -16, -41, 29, 27, 19, -5, -19, -13, -35, 29, 22, -7, 20, -35, 6, -21, 30, -2, 6, -8, -20, -12, 30, -13, 8, 23, -52, 21, 8, -16, 40, -20, -7, -15, -38, 62, -33, 48, 5, -66, 28, -25, 15, 39, 5, -46, 8, -46, 32, 12, 37, -9, -49, 43, -78, 43, 46, -43, 39, -41, -36, 13, 19, 48, -21, 9, -37, -54, 45, 32, -14, 41, -32, -66, 42, -8, 37, 12, -10, -12, -74, 71, -30, 16, 65, -64, -1, -13, -12, 17, 24, 10, -16, -31, -1, -3, 1, 68, -47, -7, -8, -41, 74, -16, 32, -27, -42, 22, -49, 80, -11, 0, 23, -84, 34, -24, 31, 48, -37, 23, -55, -25, 22, 14, 22, 59, -78, -11, -1, -45, 90, -35, 32, 0, -75, 63, -65, 34, 52, -71, 70, -56, -14, 30, -22, 10, 55, -74, 41, -19, -47, 88, -62, 50, -11, -57, 44, -54, 59, 17, -23, 12, -40, -41, 60, 3, 15, 28, -71, -1, -17, 11, 61, -28, 47, -59, -48, 35, -18, 51, 27, -20, -35, -36, 14, 6, 44, 23, -30, -33, -17, -1, 14, 49, -2, -32, -12, -20, 5, 29, 34, -33, 9, -34, -26, 36, -2, 40, -28, 5, -26, -39, 65, -27, 19, 31, -54, 0, -8, 12, 2, 30, -5, -25, -22, 24, -29, 26, 52, -57, 7, 5, -56, 46, 1, 8, 4, -5, 1, -51, 28, 14, -21, 48, -17, -46, 4, 11, -6, 35, 7, -16, -31, -10, 25, -49, 95, -28, -29, 19, -46, -5, 32, 21, 8, -1, -24, -36, -17, 59, -7, 33, 10, -76, -14, 19, -1, 56, 16, -23, -64, -8, 7, 8, 85, 0, -57, -21, -35, -7, 72, 23, 28, -66, -16, -47, 2, 68, 24, 5, 0, -69, -26, 22, -7, 72, 0, -12, -20, -51, 15, -11, 44, 44, -46, 36, -59, -38, 32, 19, -3, 71, -45, -28, -29, -17, 36, 8, 79, -47, -53, 18, -65, 38, 75, -24, 20, -36, -34, -26, 38, 39, -7, -3, 7, -85, 44, 26, -17, 42, -20, -29, -26, 26, 18, -8, 36, -17, -73, 40, 4, -1, 52, -16, -47, -15, 14, 4, 29, 30, -41, -44, 15, -2, 16, 60, -26, -54, 17, -33, 22, 48, -5, -15, -20, -13, -15, 31, 37, -28, 6, -17, -22, -10, 64, -43, 16, 22, -71, 41, 3, -1, 6, -12, 12, -38, 11, 38, -49, 37, 24, -64, 27, 18, -73, 81, -33, 14, -3, -32, 43, -60, 53, 24, -76, 70, -29, -33, 50, -18, -34, 48, -38, 37, -15, -5, 25, -80, 70, -4, -45, 89, -72, -3, 13, -23, 28, 21, -9, -9, -25, -11, 24, -26, 62, -14, -49, 67, -97, 57, 12, -23, 46, -46, 9, -20, -4, 25, -1, 5, 18, -31, -25, 38, -43, 44, 17, -42, 37, -66, 37, -16, 26, 18, -16, -17, -4, -17, 7, 38, -11, 4, -3, -51, 32, -17, 38, 18, -34, 23, -58, 4, 25, 0, 26, 3, -35, -11, -10, 16, 24, 8, 4, -33, -30, 22, -2, 14, 52, -61, 10, -23, -4, 20, 10, 32, -44, -2, 1, -36, 37, 32, -25, 2, 0, -40, 14, 24, -5, 13, -28, 20, -51, 41, 15, -23, 25, -12, -41, 30, -2, -11, 40, -34, 14, -24, 3, 22, -31, 44, -22, -31, 57, -55, 28, 0, -9, 1, 11, -10, 8, -13, 3, -2, -23, 60, -49, 23, 10, -59, 36, -3, -3, 35, -23, 5, -42, 15, 7, -2, 35, 0, -45, 8, -4, -27, 63, -4, -14, 9, -39, 1, 1, 27, 19, -27, 24, -49, -6, 34, -5, 10, 19, -32, -20, 14, -12, 16, 26, -9, -19, -9, -8, 8, 7, 40, -29, -14, -4, -25, 7, 56, -15, 6, -20, -36, 3, 10, 33, 20, -23, -5, -42, -18, 54, -17, 63, -5, -59, 2, -44, 12, 57, 17, 15, -33, -44, -16, -17, 65, 40, -9, 10, -72, -51, 39, 10, 65, 19, -25, -47, -51, 17, 20, 53, 30, -35, -35, -34, -16, 36, 48, 12, -3, -35, -42, -9, 28, 34, 12, 15, -42, -39, 7, 8, 24, 28, 1, -31, -36, 9, -1, 28, 29, -14, -34, 14, -43, 23, 34, -7, 24, -44, 10, -28, -5, 53, -29, 29, -7, -33, 2, -1, 5, 19, 10, -17, 2, -33, 14, 1, 8, 32, -36, 17, -28, -18, 36, -22, 29, 2, -25, 5, -17, 13, 1, 16, -1, -10, -12, 3, -9, 10, 19, -22, 16, -3, -20, 24, -22, 15, -3, -14, 22, -30, 31, -14, -11, 12, -11, 8, 17, -9, -4, -13, -13, 7, 10, 19, -6, -7, -2, -32, 24, 8, 0, 17, -20, -10, -15, 13, 10, 11, 4, -1, -40, 19, -4, -6, 42, -31, -1, -5, -12, 19, 6, 7, -5, -26, 10, -12, 15, 20, -8, -19, 12, -40, 31, 15, -3, 16, -23, -27, 7, -5, 31, 6, 3, -6, -41, 14, -2, 7, 38, -10, -29, 11, -44, 17, 29, 6, 20, -26, 1, -45, 9, 31, -18, 40, -1, -47, 8, -10, -4, 29, 33, -25, 1, -31, -12, -9, 35, 30, -25, 31, -48, -28, 20, 17, 9, 30, -19, -39, -13, 6, 8, 38, 15, -10, -42, 0, -24, 15, 49, -9, -12, 5, -44, -5, 42, 4, 6, 8, -27, -29, 5, 24, -2, 10, 28, -56, 1, 23, -29, 29, 15, -19, -11, 1, -4, -8, 24, 6, -15, 2, 7, -27, 12, 21, -40, 36, -15, -12, 22, -16, 17, -17, 15, -6, -18, 23, -3, -26, 39, -27, -5, 26, -20, 8, 5, -11, 7, -21, 19, -11, -8, 35, -25, 2, 18, -35, 9, 16, -21, 29, -16, 1, -13, -13, 28, -18, 23, 13, -36, 6, -1, -23, 26, 12, -15, 17, -20, -2, -7, 3, 22, -22, 27, -11, -34, 36, -30, 11, 17, 2, -12, 13, -22, -11, 11, -5, 26, -17, 26, -25, -32, 44, -47, 39, 25, -31, 16, -35, -1, -4, 26, 16, 3, -16, -10, -23, -8, 55, -27, 26, 0, -63, 41, -26, 28, 22, -23, 14, -42, 5, 20, -13, 28, 3, -42, 20, -6, -17, 52, -32, 6, -2, -37, 42, -27, 29, 15, -51, 40, -38, 2, 33, -19, 6, 11, -43, 25, 0, -19, 57, -54, 31, -9, -43, 58, -52, 36, 11, -44, 50, -44, 8, 23, -24, 12, 6, -34, 25, -9, -15, 50, -55, 35, -7, -25, 49, -48, 32, -23, -18, 37, -30, 28, 8, -27, 7, -2, -19, 22, 10, -11, 10, -27, 4, -16, 18, 29, -19, 20, -22, -36, 16, -2, 18, 14, 3, -24, -15, -5, 12, 13, 20, 4, -40, 2, -23, 8, 29, 7, 9, -23, -10, -13, 5, 19, 9, -3, -14, -7, -19, 21, 6, 5, 10, -20, 0, -14, 12, 0, 2, 5, -13, 1, -3, 12, -12, 20, -13, -7, 6, -11, 5, 0, 5, -5, -4, 10, -10, 2, 6, -5, -12, 18, -13, -9, 19, -17, 11, -1, 8, -5, -22, 26, -26, 1, 29, -17, -7, 16, -22, -8, 23, -3, 4, -3, -2, -15, -20, 42, -21, 4, 40, -55, 8, 8, -22, 21, 20, -17, 2, -14, -7, -2, 10, 31, -25, 10, -3, -54, 40, 5, -12, 42, -17, -37, 13, -12, 7, 24, 10, -6, -36, 12, -9, -25, 74, -24, -19, 38, -64, 5, 25, 0, 16, 1, -9, -25, -23, 36, -8, 6, 50, -58, -12, 22, -53, 52, 18, -12, 16, -51, 15, -30, 25, 46, -37, 31, -26, -49, 30, 9, -1, 42, -19, -28, -13, -5, 16, 4, 42, -18, -40, 20, -30, 1, 49, -4, -15, 0, -21, -19, 21, 26, 0, -9, 9, -43, -1, 26, -5, 21, -7, -6, -32, 9, 12, -3, 34, -17, -12, -17, -4, 9, 7, 28, -19, -3, -13, -11, 7, 15, 15, -19, 15, -38, -5, 17, -1, 29, -20, 15, -39, -11, 41, -33, 45, -8, -21, -11, -3, 7, 0, 28, -7, -19, -8, 7, -20, 23, 24, -40, 24, -17, -16, 26, -9, 21, -27, 13, -11, -22, 29, -7, 0, 22, -22, -16, 14, -12, 12, 11, -5, -6, -17, 14, -15, 9, 30, -28, 5, 1, -26, 8, 18, -7, 1, 6, -12, -15, 9, 13, -13, 13, 13, -42, 14, 3, -16, 20, 7, -3, -22, 25, -26, 4, 16, -7, 3, -8, 17, -33, 14, 9, -21, 25, -3, -11, -1, 1, -13, 1, 23, -20, 26, -18, 0, -18, 3, 24, -25, 36, -15, -29, 22, -22, 3, 24, -5, -1, 0, -18, 2, -11, 20, 10, -17, 30, -37, -15, 29, -33, 39, 11, -23, 7, -34, 8, 0, 11, 36, -27, -12, 9, -47, 29, 31, -29, 40, -37, -14, 3, -17, 45, -11, 8, 12, -60, 20, -2, -2, 41, -12, -18, 3, -37, 27, 12, -4, 37, -56, 17, -21, -5, 44, -20, 14, -2, -40, 20, 0, 3, 22, -13, -10, -6, -16, 29, -12, 14, 15, -49, 24, -11, -7, 39, -18, 3, -20, -12, 19, -10, 32, 2, -34, 10, -13, -13, 37, 1, -7, 3, -33, 4, 2, 18, 25, -25, 8, -33, -13, 34, -7, 24, 4, -33, -10, -2, 2, 25, 12, -1, -25, -12, 3, -18, 34, 12, -15, 4, -9, -25, 10, 17, -3, 9, 2, -13, -23, 9, 8, -13, 37, -10, -15, 1, -13, -1, 0, 31, -15, 0, 5, -29, 6, 5, 15, -9, 16, -9, -29, 15, -10, 3, 15, 9, -11, -12, 11, -29, 17, 14, -7, 6, -6, -7, -24, 30, -11, 9, 18, -20, -8, -6, 6, -10, 22, 10, -29, 14, -13, -8, 13, 17, -13, 2, 1, -24, 5, 5, 12, -10, 15, -7, -28, 21, -2, -8, 22, -9, -14, -2, 6, -5, 5, 12, -7, -15, 14, -4, -16, 27, -10, -14, 13, -5, -9, 10, 5, -8, -5, 16, -20, 2, 13, -14, -3, 17, -18, 2, 10, -12, 9, -6, -2, -16, 13, 10, -15, 33, -24, -17, 10, -4, 15, 1, 9, -23, -9, 6, -5, 5, 21, -10, -13, 11, -21, -2, 19, -10, 23, -20, 10, -16, -21, 33, -17, 17, 18, -30, 1, -14, -1, 20, -2, 18, -15, -24, 6, -5, 6, 36, -26, 6, -18, -23, 34, -12, 25, 1, -30, -1, -11, 10, 22, -1, 4, -19, -28, 21, -11, 22, 25, -33, 4, -21, -7, 22, 7, 19, -23, -13, -3, -13, 21, 17, -11, 7, -19, -12, 12, -10, 30, -13, -5, 4, -30, 27, -9, 17, -3, -25, 13, -23, 13, 27, -15, -5, 3, -35, 17, 19, -8, 29, -37, 1, -15, -10, 48, -20, 26, -7, -49, 22, -23, 21, 33, -10, -8, -17, -34, 11, 19, 12, 40, -39, -14, -13, -36, 64, -4, 20, 9, -55, 3, -24, 21, 31, 10, -1, -22, -30, -7, 12, 18, 29, -10, -7, -28, -22, 22, 3, 26, 4, -13, -18, -16, 21, -9, 28, -1, -21, 0, -12, 5, 6, 5, 10, -20, 1, 3, -20, 21, 7, -23, 24, -25, -6, 21, -13, 25, -19, -8, 2, -14, 20, 13, -23, 25, -31, -7, 24, -16, 20, 6, -25, 8, -24, 12, 15, -10, 24, -25, -2, 0, -12, 14, 10, -13, 4, 1, -17, 9, 6, -9, 9, 0, -3, -8, 11, -10, -2, 7, -1, -6, 6, 1, -12, 1, 18, -31, 23, -2, -21, 21, -6, -8, 15, -14, 4, -6, -1, 17, -22, 20, -6, -35, 37, -17, -6, 47, -41, 6, -6, -16, 12, 16, 6, 1, -36, 18, -26, 4, 59, -36, -1, 16, -64, 30, 14, 1, 16, -13, 0, -35, 17, 13, -8, 12, 14, -45, 11, 12, -24, 27, 12, -27, 10, -6, -9, 1, 14, -7, -6, 8, -4, -8, 8, 8, -24, 13, 7, -27, 28, -1, -28, 27, -19, -2, 17, -5, 6, -10, -5, 4, -25, 32, 2, -22, 32, -28, -20, 35, -20, 16, 7, -18, 1, -22, 20, 0, 2, 20, -15, -25, 24, -25, 12, 25, -23, 10, -19, -5, 8, 2, 20, -6, -13, 0, -22, 12, 15, -3, 13, -13, -25, 12, -6, 18, 13, -3, -14, -22, 3, -2, 14, 25, -10, -16, -5, -13, 2, 22, 9, -2, -11, -12, -20, 15, 20, 1, 14, -19, -17, -9, 1, 19, 5, 0, 4, -35, 17, -7, 5, 20, -16, 2, -8, -11, 11, -2, 2, 7, -19, 15, -10, 2, 12, -14, -3, 2, -9, 17, -3, 2, -7, -16, 10, 2, 9, 10, -14, -9, -6, -11, 21, 5, 4, 6, -24, -5, -4, 6, 18, 0, 8, -21, -18, 8, -8, 21, 16, -11, -9, -12, -15, 15, 3, 27, -9, -16, 5, -30, 13, 23, -11, 21, -19, -15, -3, -9, 30, -9, 14, -6, -22, -5, 15, -11, 23, -1, -14, -4, -9, 8, 4, 1, 20, -34, 9, 1, -17, 24, -6, 1, -9, 1, -4, 3, 6, 8, -16, 0, 2, -13, 11, 21, -31, 24, -21, -4, 13, -2, 7, -9, -3, 0, -18, 29, -4, -9, 16, -19, -13, 25, -5, -1, 15, -24, 4, -15, 22, 4, -11, 20, -21, -25, 39, -23, 14, 14, -23, 1, -8, 3, 12, -9, 23, -19, -18, 24, -22, 5, 30, -32, 11, 2, -21, 18, -6, 5, 1, -9, 13, -22, 4, 19, -28, 26, 3, -28, 21, -4, -25, 32, -15, 5, 0, -2, -4, -9, 15, 0, -13, 21, -14, -20, 31, -19, 2, 17, -14, -9, 12, -6, 4, -1, 4, -17, -1, 12, -2, 0, 20, -31, -8, 12, -8, 17, 14, -13, -16, -9, -7, 20, 11, 18, -13, -28, -3, -12, 13, 40, -12, 4, -20, -32, 8, 17, 14, 21, -10, -28, -18, -2, 11, 22, 17, 0, -34, -6, -3, -17, 50, 1, -13, 4, -22, -21, 17, 16, 4, 7, 0, -27, -11, 4, 10, 2, 24, -6, -28, 7, -12, -2, 33, -3, -6, 2, -37, 3, 9, 7, 24, -4, -14, -6, -24, 25, -1, 11, 16, -36, -9, 12, -25, 45, 5, -20, 11, -36, 11, 7, 0, 30, -32, -1, 7, -33, 37, 0, -9, 15, -21, -10, 12, -15, 24, -8, 3, 4, -20, 7, 3, -15, 28, -14, -7, 13, -23, 2, 11, 0, 4, 7, -9, -16, 1, 7, -7, 19, -3, -12, -14, 15, -10, 7, 30, -26, -13, 15, -30, 15, 26, -12, -1, -8, -9, -5, 13, 22, -12, -12, 7, -36, 17, 31, -24, 27, -21, -24, 15, -10, 26, 4, -12, 4, -36, 13, 14, -5, 27, -14, -22, 7, -12, 6, 23, -13, 7, -19, -2, 7, -8, 25, -5, -17, 18, -25, 3, 14, -8, 4, 0, -1, -11, 4, 12, -18, 15, 2, -23, 12, -2, -7, 12, 1, -1, -15, 11, -3, -17, 41, -24, -7, 13, -25, 3, 22, -9, 15, -12, -9, 0, -17, 32, -5, -5, 19, -49, 19, 3, -11, 45, -30, 2, -4, -28, 29, 0, 7, 12, -34, 6, -10, 1, 33, -9, -6, 4, -41, 25, 2, 4, 29, -40, 8, -17, -9, 42, -16, 16, -10, -33, 11, -7, 22, 12, -6, -6, -25, -4, 18, -3, 25, -4, -29, 5, -17, 8, 22, 1, 4, -22, 1, -13, 2, 31, -19, 9, 2, -36, 17, 5, -7, 20, -11, -2, -13, 4, 9, -18, 24, -3, -30, 33, -19, -11, 31, -21, 6, 0, -5, 3, -10, 17, -7, -19, 30, -24, 0, 26, -23, 3, 7, -17, 9, -3, 9, -1, -17, 23, -25, -3, 34, -27, 10, 15, -34, 9, 1, 1, 7, -1, 12, -31, 4, 16, -27, 32, 10, -33, 10, -1, -27, 29, 9, -9, 0, -1, -16, -6, 24, 2, -17, 23, -20, -24, 33, -11, -2, 17, -7, -21, 13, 1, -7, 10, 1, -12, -9, 13, -1, -5, 20, -16, -15, 15, -8, 5, 13, -10, -7, -9, 5, 2, 10, 7, -7, -22, 12, -13, 6, 26, -14, -6, 0, -17, 3, 16, 6, 0, -11, 3, -26, 13, 15, -6, 7, 4, -29, 6, 7, -3, 13, 1, -11, -9, 2, -1, 3, 9, -3, -8, 1, -4, 0, 5, 0, 0, -2, 0, -1, 0, 0, -2, 11, 23, 22, 24, 25, 20, 21, 15, 40, -1, -24, -42, -5, -19, -11, -8, 4, -46, -31, -14, -33, -40, -44, -48, -89, -63, -47, -33, -27, -10, -6, 22, 25, 26, 28, 37, 11, 15, 51, 44, 54, 66, 66, 71, 111, 84, 70, 63, 47, 39, 22, 47, -28, -79, -111, -90, -91, -112, -81, -87, -49, -46, -5, -24, 26, 24, 47, 29, 23, 30, 30, 13, -1, 4, -14, 17, 35, 62, 31, 53, 59, 72, 64, 27, 26, 9, 9, -61, -44, -88, -74, -81, -83, -124, -96, -37, -78, -48, -56, -68, -60, 7, 44, 39, 54, 77, 102, 110, 108, 89, 101, 100, 105, 64, 22, -1, 44, 40, -19, -29, -35, -16, -27, -40, -77, -82, -113, -104, -93, -57, -72, -56, -3, 1, 7, -1, 49, 39, 30, 31, 23, 10, 31, 11, 7, -19, -2, -2, 28, 62, 92, 75, 33, 34, -20, -47, -61, -85, -105, -93, -119, -112, -54, -70, -67, -32, -1, 4, 4, 20, 29, 62, 70, 54, 62, 78, 115, 92, 85, 78, 52, 21, 19, 27, 2, -8, 13, 0, 5, 3, 9, 18, 0, -59, -61, -45, -57, -65, -76, -89, -102, -48, -24, 17, 6, 26, 33, 35, 26, 41, 63, 20, 12, 29, 34, 8, 7, 31, 21, 31, 39, 33, -5, -8, -55, -57, -98, -94, -88, -64, -82, -74, -39, -14, 3, 16, 22, 8, 2, 17, 5, 36, 76, 74, 71, 57, 73, 62, 47, 30, 32, 19, 4, 7, -14, -18, -2, 17, -5, 13, 22, 31, 10, 8, -13, -47, -80, -85, -86, -71, -73, -60, -35, -10, 9, 19, 49, 53, 47, 60, 73, 43, 33, 20, 13, -1, -7, -7, 7, 9, -2, 5, -14, -40, -69, -61, -66, -67, -84, -58, -58, -33, 2, -7, -5, 12, 32, 18, 25, 19, 24, 65, 59, 62, 64, 63, 55, 60, 52, 31, 19, -12, -26, -4, -7, -10, -3, 6, -22, -14, 12, 19, 4, -26, -38, -40, -56, -61, -66, -59, -65, -51, -20, 29, 40, 51, 52, 62, 61, 53, 26, 20, 6, 8, 6, 9, -14, -14, -15, -2, -11, -23, -36, -38, -60, -77, -69, -60, -51, -56, -44, -27, 10, -2, 14, 10, 22, 16, 41, 60, 39, 35, 60, 62, 43, 45, 63, 52, 17, 12, 15, -1, -2, 0, -38, -48, -32, -22, -7, 3, 13, 10, -2, -1, -8, -12, -25, -48, -46, -52, -49, -36, -17, 9, 17, 26, 48, 57, 55, 69, 60, 32, 6, 4, -6, -20, -24, -9, -21, -25, -14, -18, -38, -38, -32, -51, -52, -60, -34, -6, -6, -16, -11, -2, -1, 17, 19, 3, 11, 25, 31, 41, 39, 33, 33, 41, 34, 34, 23, 21, 15, 6, -13, -24, -28, -20, -8, -12, -19, -12, -5, 9, 14, 2, -12, -25, -28, -21, -28, -23, -22, -18, -26, -5, 24, 45, 46, 47, 39, 33, 36, 42, 29, 7, -5, -10, -21, -29, -39, -39, -31, -24, -29, -39, -51, -43, -27, -22, -18, -25, -26, -20, 9, 19, 18, 4, -2, 19, 30, 38, 25, 24, 28, 33, 41, 38, 34, 32, 38, 24, 8, 4, -8, -11, -15, -25, -31, -25, -20, -22, -15, -11, -9, -12, -17, -20, -20, -15, -6, -11, -8, 0, 11, 29, 19, 17, 17, 18, 28, 31, 25, 18, 23, 18, 10, 1, -7, -18, -26, -24, -30, -41, -38, -44, -32, -31, -31, -35, -25, -12, -2, -8, -11, -13, -13, -2, 8, 15, 19, 29, 35, 37, 39, 43, 42, 40, 35, 27, 25, 18, 15, 9, 4, -4, -15, -28, -28, -26, -28, -18, -15, -25, -23, -12, -11, -14, -10, -2, -4, -1, 8, 15, 19, 22, 25, 16, 16, 17, 5, 7, 13, 18, 13, 9, 6, 6, 4, -4, -21, -31, -28, -37, -39, -34, -38, -38, -32, -17, -6, -4, -14, -19, -9, 3, -2, 3, 4, 7, 8, 13, 23, 35, 38, 43, 42, 31, 25, 23, 17, 8, 3, 4, -7, -7, -10, -13, -20, -19, -28, -33, -30, -23, -18, -13, -17, -12, 3, 14, 23, 31, 27, 23, 21, 22, 19, 12, 4, 2, 2, -2, 0, 4, 11, 11, 6, 4, -2, -5, -14, -17, -30, -38, -44, -42, -28, -21, -23, -21, -15, -15, -4, 8, 11, 4, -7, -15, -7, 5, 10, 21, 26, 28, 27, 34, 37, 36, 28, 19, 10, 11, 8, -2, -18, -17, -19, -19, -22, -24, -21, -24, -18, -17, -13, -19, -13, -1, 12, 19, 22, 21, 19, 19, 30, 34, 24, 13, 7, 2, 1, 1, 2, -1, -2, -6, 0, 0, -2, -15, -21, -17, -21, -28, -32, -31, -31, -32, -27, -24, -17, -4, 1, -3, -1, 1, 4, 7, 8, 15, 16, 15, 15, 20, 32, 36, 38, 32, 19, 12, 3, 2, -2, -4, -11, -19, -17, -15, -11, -16, -20, -27, -30, -28, -22, -13, -6, -2, 2, 12, 23, 29, 45, 44, 36, 32, 21, 16, 14, 10, 1, -9, -8, -2, -1, -7, -13, -13, -12, -9, -11, -18, -24, -26, -28, -30, -24, -21, -21, -21, -11, -11, -10, 0, -2, 0, 4, 12, 13, 14, 12, 17, 22, 28, 30, 28, 20, 16, 13, 8, 2, -2, -6, -15, -14, -18, -15, -15, -16, -18, -18, -16, -19, -18, -17, -10, 0, -1, 4, 13, 22, 37, 39, 36, 27, 27, 32, 26, 15, 6, -1, -4, -5, -7, -11, -11, -9, -15, -15, -14, -18, -21, -19, -17, -21, -19, -15, -15, -10, -15, -14, -12, -11, -6, -2, 1, -2, 1, 5, 14, 22, 33, 35, 23, 18, 16, 13, 11, 6, 1, -9, -18, -11, -6, -7, -8, -9, -11, -11, -12, -13, -17, -21, -24, -24, -15, -4, 7, 12, 17, 25, 30, 28, 31, 32, 31, 27, 22, 15, 12, 3, -2, -8, -6, -3, -9, -13, -22, -24, -20, -18, -22, -24, -18, -14, -13, -10, -11, -9, -3, -2, -3, -5, -10, -10, -5, -1, 4, 11, 15, 19, 22, 27, 23, 20, 16, 14, 5, -3, -11, -15, -16, -12, -12, -11, -5, 1, -3, -10, -13, -15, -11, -10, -10, -11, -8, -3, 2, 7, 9, 15, 25, 30, 33, 31, 25, 21, 20, 16, 13, 7, -2, -8, -5, -4, -11, -20, -21, -22, -21, -17, -20, -21, -22, -19, -19, -11, -4, -2, -2, -2, 2, 5, 2, 0, 0, -3, 1, 8, 16, 13, 14, 17, 15, 13, 8, 5, -1, -6, -10, -13, -14, -14, -13, -10, -7, -8, -8, -6, -6, -3, -1, -1, -9, -12, -7, 3, 13, 17, 14, 13, 17, 22, 23, 24, 18, 15, 18, 18, 18, 15, 8, 0, -5, -8, -11, -15, -17, -21, -26, -26, -24, -26, -24, -13, -9, -6, -3, -2, 3, 4, 6, 7, 5, 2, 4, 2, -2, -4, -3, 5, 13, 17, 10, 3, -1, -2, -4, -5, -11, -14, -13, -11, -8, -8, -8, -6, -3, 0, -1, -5, -5, 0, 4, 3, 1, 2, 0, 0, 6, 13, 20, 17, 17, 18, 21, 18, 14, 13, 11, 11, 7, 9, 3, -5, -12, -14, -18, -21, -23, -26, -26, -13, -3, -6, -13, -14, -5, 5, 8, 3, 0, 1, 3, 6, 4, -1, -1, 1, 3, 7, 5, 3, 0, 1, -1, 3, 0, -3, -11, -11, -9, -10, -9, -8, -5, -7, -7, -10, -9, -6, -1, 4, 6, 4, 2, 5, 10, 13, 9, 12, 13, 14, 15, 16, 13, 12, 10, 13, 14, 13, 8, 2, -1, -4, -6, -9, -15, -20, -21, -19, -14, -16, -22, -21, -13, -5, -3, -3, -1, 3, 5, 10, 9, 9, 6, 8, 7, 7, 7, 3, -4, -6, -4, -1, -4, -8, -10, -11, -8, -4, -6, -10, -7, -8, -11, -11, -8, -5, -4, 0, 3, 3, 8, 10, 10, 12, 12, 11, 10, 13, 12, 10, 6, 8, 9, 9, 11, 13, 11, 9, 10, 7, 2, -3, -8, -9, -14, -16, -16, -19, -18, -14, -13, -11, -11, -10, -5, -1, 3, 5, 2, 2, 9, 14, 11, 9, 10, 7, 2, 0, 2, -2, -9, -13, -15, -18, -17, -15, -13, -10, -5, -5, -7, -7, -4, -1, 0, -2, -4, -2, 1, 4, 9, 10, 10, 11, 11, 13, 14, 10, 11, 9, 9, 4, 6, 5, 4, 5, 7, 8, 10, 9, 4, -4, -8, -9, -10, -11, -12, -14, -15, -17, -15, -9, -4, -1, -6, -5, 2, 8, 8, 6, 5, 3, 4, 5, 9, 10, 10, 5, -1, -5, -10, -12, -14, -16, -18, -17, -11, -10, -11, -8, -5, -2, -2, 0, 3, 4, 5, 3, 2, 3, 5, 9, 12, 12, 11, 10, 12, 14, 12, 8, 5, 0, -1, 1, 3, 0, 1, 3, 5, 6, 5, 0, -5, -11, -10, -13, -12, -13, -15, -14, -8, -4, -3, -3, -4, 0, 4, 5, 3, 6, 4, 4, 7, 10, 9, 9, 8, 5, 5, 2, -4, -10, -15, -17, -20, -22, -22, -19, -14, -11, -10, -8, -6, 0, 3, 5, 3, 4, 8, 11, 11, 12, 13, 12, 12, 15, 15, 16, 16, 13, 11, 6, 3, -2, -5, -5, -3, -2, -1, 2, 0, -3, -4, -5, -7, -10, -12, -11, -12, -11, -8, -4, -2, 0, 1, 2, 2, 2, 4, 3, 3, 4, 5, 9, 10, 6, 2, 1, 2, 0, -3, -7, -13, -18, -19, -18, -16, -18, -20, -19, -14, -8, -4, -1, 3, 3, 5, 7, 9, 9, 10, 12, 13, 13, 13, 13, 16, 15, 13, 9, 6, 3, 2, 1, 0, -3, -5, -6, -4, -2, -2, -4, -4, -5, -5, -3, -3, -4, -6, -6, -7, -4, 0, 2, 3, 2, 2, 1, 2, 2, 1, 4, 5, 4, 1, 0, 2, 2, 0, -2, -6, -8, -6, -7, -9, -11, -15, -18, -19, -18, -18, -17, -13, -9, -2, 2, 3, 5, 10, 12, 13, 14, 14, 15, 17, 17, 16, 16, 15, 13, 11, 7, 2, -6, -10, -8, -6, -8, -8, -7, -6, -6, -3, -4, -6, -5, -3, -2, -2, 0, 1, 0, 2, 2, 3, 2, 3, 2, 3, 3, 5, 2, 0, 4, 6, 5, -1, -4, -2, -1, -2, -6, -8, -9, -10, -12, -10, -14, -17, -22, -22, -21, -19, -15, -8, -3, 1, 7, 12, 12, 15, 19, 22, 21, 18, 16, 16, 16, 13, 12, 6, 3, 3, 2, -3, -6, -7, -12, -12, -11, -8, -9, -8, -7, -3, 0, 0, 0, 0, -2, -2, 0, 1, 2, 2, 4, 6, 6, 7, 5, 4, 3, 4, 5, 3, 0, -2, -2, -4, -6, -10, -8, -8, -10, -11, -12, -12, -12, -13, -16, -16, -16, -14, -11, -8, -4, -2, 1, 6, 12, 17, 19, 20, 20, 21, 21, 19, 13, 10, 9, 5, 0, -3, -4, -4, -5, -6, -6, -4, -7, -10, -12, -12, -12, -10, -7, -4, -2, 4, 6, 8, 7, 7, 7, 7, 8, 8, 7, 5, 6, 6, 4, 1, -1, -1, 0, -3, -7, -10, -10, -8, -11, -14, -14, -12, -11, -9, -6, -8, -8, -8, -11, -13, -12, -9, -8, -5, 0, 4, 8, 11, 14, 18, 18, 20, 23, 23, 20, 14, 9, 4, 0, -3, -6, -8, -8, -8, -8, -9, -10, -11, -10, -9, -8, -8, -7, -6, -3, 0, 3, 6, 12, 16, 16, 14, 10, 8, 9, 7, 4, 1, 0, 0, -2, -1, 0, 0, -3, -7, -10, -13, -13, -12, -13, -15, -14, -13, -9, -6, -5, -5, -7, -8, -9, -7, -6, -5, -7, -5, 1, 8, 13, 17, 19, 20, 21, 22, 22, 18, 12, 9, 5, -1, -5, -9, -11, -13, -12, -12, -11, -10, -8, -7, -7, -6, -7, -6, -3, 0, 1, 3, 7, 10, 11, 12, 15, 15, 14, 9, 6, 3, 1, 0, -2, -2, -2, -3, -6, -8, -10, -11, -13, -15, -15, -15, -13, -12, -12, -7, -5, -5, -5, -4, -3, -3, -4, -4, -1, -1, 1, 4, 7, 10, 12, 14, 17, 20, 22, 19, 14, 8, 5, 2, -2, -5, -10, -14, -13, -11, -10, -10, -10, -10, -8, -6, -3, -3, -3, -1, -1, 2, 6, 10, 13, 14, 15, 15, 15, 13, 11, 8, 5, 1, -1, -3, -3, -6, -10, -12, -12, -12, -12, -13, -15, -18, -19, -15, -11, -6, -4, -3, -4, -4, -2, 1, 4, 2, -1, -2, 1, 4, 6, 8, 7, 7, 11, 14, 15, 15, 15, 13, 10, 6, 1, -3, -6, -9, -13, -15, -15, -13, -11, -9, -9, -9, -7, -3, 0, 2, 2, 4, 7, 11, 15, 16, 14, 11, 12, 13, 15, 13, 9, 4, 1, -1, -4, -6, -8, -11, -15, -17, -17, -17, -17, -15, -13, -13, -12, -10, -7, -6, -4, 1, 2, 2, 3, 4, 5, 4, 4, 3, 5, 6, 6, 8, 7, 7, 9, 11, 10, 9, 8, 5, 2, 0, -2, -6, -10, -13, -13, -14, -14, -13, -11, -9, -4, -1, -1, -1, 2, 6, 8, 10, 11, 12, 14, 14, 14, 13, 11, 10, 7, 4, 2, 3, 1, -3, -6, -10, -14, -17, -18, -18, -19, -19, -17, -15, -13, -9, -5, -1, 1, 0, 1, 3, 5, 6, 6, 6, 7, 8, 9, 8, 4, 1, 0, 2, 4, 5, 6, 5, 4, 4, 4, 3, 1, -3, -7, -9, -11, -12, -12, -12, -11, -10, -7, -4, -2, 1, 4, 5, 8, 11, 13, 14, 14, 11, 11, 11, 10, 10, 9, 6, 5, 3, 1, -2, -5, -10, -14, -16, -17, -18, -19, -20, -19, -17, -14, -10, -5, -1, 1, 3, 5, 6, 6, 6, 6, 6, 6, 6, 6, 8, 7, 6, 4, 2, 0, -1, 0, 0, 1, 2, 1, 1, 2, 1, -2, -5, -8, -9, -10, -11, -12, -12, -10, -7, -4, -1, 2, 8, 11, 13, 15, 15, 13, 12, 11, 10, 9, 8, 6, 5, 4, 4, 3, 0, -3, -6, -10, -14, -18, -21, -22, -21, -18, -16, -13, -10, -6, -3, 0, 3, 5, 5, 5, 6, 7, 8, 8, 8, 7, 8, 7, 6, 5, 4, 1, 0, -2, -4, -4, -5, -4, -4, -3, -2, -1, -2, -3, -4, -7, -8, -9, -9, -9, -8, -5, -2, 2, 4, 8, 11, 14, 15, 15, 14, 12, 10, 7, 5, 4, 4, 2, 1, 1, 2, -1, -3, -7, -10, -15, -18, -18, -18, -18, -17, -15, -11, -7, -3, 1, 3, 4, 5, 6, 7, 7, 8, 8, 9, 10, 10, 9, 6, 4, 2, 0, -3, -4, -6, -7, -7, -6, -5, -3, -2, -2, -2, -2, -3, -4, -5, -6, -6, -6, -6, -5, -4, -1, 4, 7, 9, 11, 12, 12, 11, 10, 9, 8, 7, 5, 3, 3, 2, 1, 0, -1, -4, -7, -8, -10, -13, -14, -15, -15, -15, -14, -11, -9, -6, -3, 0, 2, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 6, 5, 3, 1, -3, -6, -8, -8, -7, -7, -7, -6, -4, -2, 0, -1, -2, -3, -3, -3, -3, -4, -3, -3, -1, 1, 3, 4, 6, 7, 8, 9, 10, 10, 9, 7, 6, 6, 4, 3, 2, 1, -1, -2, -4, -6, -9, -11, -12, -12, -12, -11, -11, -10, -9, -8, -7, -5, -4, -1, 1, 3, 5, 7, 9, 10, 11, 10, 9, 8, 7, 6, 2, -1, -3, -4, -6, -7, -7, -7, -7, -6, -5, -5, -4, -3, -3, -4, -4, -4, -3, -2, 0, 0, 1, 1, 2, 4, 6, 6, 7, 7, 8, 7, 7, 7, 7, 7, 6, 5, 2, 0, -2, -4, -5, -7, -8, -8, -8, -9, -10, -10, -9, -8, -7, -7, -7, -5, -3, -2, 0, 1, 2, 4, 6, 9, 10, 11, 12, 10, 8, 6, 3, 1, -2, -4, -6, -7, -7, -7, -7, -8, -7, -7, -6, -6, -5, -4, -3, -3, -2, -1, 1, 2, 2, 3, 4, 5, 5, 5, 6, 6, 6, 5, 5, 6, 6, 6, 4, 3, 2, 1, -1, -3, -4, -6, -8, -9, -9, -8, -8, -6, -5, -5, -5, -6, -6, -6, -5, -4, -2, 0, 2, 4, 6, 7, 8, 9, 9, 9, 9, 6, 4, 1, -1, -3, -5, -6, -7, -7, -7, -6, -6, -6, -6, -6, -5, -4, -3, -3, -2, -1, 1, 3, 4, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 1, -1, -3, -4, -5, -6, -7, -7, -7, -7, -7, -6, -5, -4, -4, -3, -3, -3, -3, -2, -1, 0, 1, 3, 5, 7, 8, 8, 8, 7, 6, 4, 2, 0, -2, -3, -4, -5, -6, -7, -7, -7, -7, -6, -6, -5, -5, -5, -3, -2, 0, 1, 2, 3, 4, 5, 6, 6, 6, 5, 5, 4, 3, 3, 3, 3, 3, 3, 2, 1, 1, -1, -2, -3, -4, -5, -6, -6, -7, -6, -5, -4, -3, -3, -3, -3, -3, -2, -1, -1, 0, 1, 1, 1, 2, 3, 5, 6, 6, 6, 5, 4, 2, 1, 0, -2, -4, -5, -5, -6, -6, -6, -7, -7, -7, -6, -5, -4, -3, -2, -1, 0, 2, 3, 3, 4, 4, 5, 5, 5, 4, 4, 4, 4, 3, 3, 2, 1, 1, 0, 0, -1, -1, -2, -3, -4, -5, -5, -5, -5, -5, -4, -4, -3, -3, -2, -1, -1, -1, -1, 0, 0, 0, 1, 2, 3, 3, 4, 4, 4, 4, 4, 3, 1, 0, 0, -2, -3, -4, -5, -5, -6, -6, -6, -5, -4, -4, -4, -3, -2, -2, -1, 0, 2, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 2, 2, 1, 1, 1, 0, -1, -1, -2, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -2, -2, -2, -1, -1, -1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 0, 0, -1, -1, -2, -3, -3, -3, -4, -4, -4, -4, -3, -3, -2, -1, -1, -1, 0, 1, 1, 1, 2, 2, 2, 3, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -5, -41, -25, -37, -9, 28, 14, 6, 1, 19, 16, -83, -53, -35, -44, -29, 8, -23, -29, -6, -20, -22, -19, -40, -2, 14, 34, 78, 59, 73, 93, 73, 83, 124, 94, 87, 61, 98, 80, 29, 27, 6, 8, -9, -8, -26, -33, -35, -32, -25, -32, -28, -59, -46, -31, -19, -12, -12, 14, 14, -41, -59, -46, -33, -32, -52, -31, -29, -49, -51, -53, -85, -53, -60, -100, -85, -84, -66, -37, -26, -11, -8, 22, 41, 33, 39, 27, 29, 75, 59, 45, 52, 69, 66, 73, 90, 91, 103, 81, 46, 16, -21, -32, -13, -34, -22, -42, -51, -35, -53, -62, -45, -35, -34, -29, 25, 62, 61, 39, -8, -20, -5, -7, 2, 28, 1, -24, 8, 29, 11, -9, -54, -34, -35, -57, -41, -63, -50, -16, -18, 26, 23, -2, 38, 9, 17, 41, 39, 82, 64, 64, 103, 64, 43, 43, 51, 26, -3, 30, 1, 9, 14, -26, 20, -27, -50, -39, -47, -31, -23, -33, 25, 56, 51, 20, -19, -60, -41, -27, -10, 3, -36, -30, -22, -46, -5, -12, -7, -4, -54, 3, -25, -10, -1, -42, -75, -27, -84, -60, -88, -107, -73, -29, -67, -53, 9, -10, 17, -29, -33, 55, 12, 7, 121, 70, 42, 123, 96, 127, 74, 28, 51, 21, 60, 23, -10, 25, 103, 113, 65, 45, 15, -1, 10, 2, -26, 1, -16, 19, 27, -8, -8, -24, -20, -17, -35, -86, -87, -32, -51, -26, -60, -60, -50, -15, -31, -30, -50, -55, -19, 22, 14, 30, 49, 42, 15, -11, -57, -15, -29, -65, -37, -56, -29, 15, 70, 69, 36, 24, 19, 21, 19, 4, 60, 55, 18, -17, 0, -2, -21, 51, 49, -6, 22, 14, -24, -63, -5, 4, -53, -33, -1, -37, -34, 40, 30, 12, -6, -1, 12, 12, 23, 20, 43, 34, 11, -26, -40, 25, 56, -1, -41, -50, -37, -10, 20, -58, -65, -43, -26, 42, 57, 77, 57, 26, -4, -10, -57, -45, -23, -49, -1, -59, -41, -26, -27, 24, 52, -3, -12, 19, -44, -31, 33, 11, -14, 43, 31, 7, 58, 84, 45, 35, 18, -5, 6, -21, -6, -20, -7, 41, 53, 29, 25, 55, 68, 37, -29, -17, -41, -67, -76, -90, -112, -104, -60, -21, 25, 16, -23, -9, 30, 47, 17, 3, 19, 4, -2, 30, 24, 1, 26, 33, 34, 10, 14, 1, -5, 16, -2, -60, -32, -51, -48, -38, -34, -42, -20, 16, 17, -16, -32, -6, 4, -39, -18, 1, -20, -22, 55, 70, 34, 5, -1, 13, 2, 1, 28, 20, -31, -2, 51, 26, 24, 19, 11, -1, 2, 30, 13, 2, 70, 36, 15, 24, 5, 9, 14, 48, 43, 8, 2, -10, 18, 33, 22, -27, -19, -17, -22, 11, 19, -5, 0, -55, -60, -49, -63, -72, -45, -80, -55, -18, -8, 32, 52, 22, 0, -40, -42, -30, -68, -51, -9, -67, -52, -10, 7, 35, 12, 36, 64, 23, 13, 64, 39, 32, 73, 3, 6, -10, -6, 16, 18, 53, 51, 21, -20, -15, 13, -3, 2, -39, -30, -7, -3, 6, 10, -4, -25, -7, -10, -10, -18, -31, -23, -38, -48, -3, -26, -43, -7, 11, 31, 62, 41, -7, -34, -42, -24, 17, 12, 44, 25, 24, 18, 11, 32, 51, 46, 46, 51, 33, 24, 32, 30, 40, 8, -30, -39, -30, -44, -19, -33, -55, -41, -36, -70, -67, -64, -34, -37, -46, 1, 19, 27, 81, 23, 13, 10, -5, -18, -19, -51, -14, -48, -75, 11, 51, 43, 63, 37, 20, 19, 4, -23, 27, 47, 71, 29, 16, 15, -17, -11, 32, 40, 22, 6, 16, -7, 5, 34, 61, 12, -21, -24, -13, -38, -41, -36, -33, 2, 9, -45, -54, -36, 12, -18, -41, -25, -18, 19, 31, -11, -16, -22, -62, -65, -68, -42, -4, -48, -49, 4, 38, 65, 47, 12, -20, -20, -8, 3, 32, 69, 84, 44, 28, 31, 18, 36, 57, 74, 35, 19, 6, 24, 29, 36, 35, 6, -13, -25, -43, -45, -35, -33, -44, -23, -41, -57, -52, -41, -35, -21, -16, -22, -11, 33, 42, 14, 19, 16, 0, -6, -34, -17, -37, -25, -7, 6, 48, 47, 3, -14, -17, -19, -11, -9, -11, 42, 42, 16, 1, 6, 15, 51, 42, 33, 29, 20, -5, -3, 4, 54, 42, 8, -30, -19, -15, -15, -20, -6, -7, -24, -32, -24, -17, -1, -16, -18, -36, -55, -38, -2, 8, 16, 7, -21, -35, -56, -67, -17, -58, -67, -36, 21, 67, 48, 15, 8, 13, -9, -8, -1, 21, 107, 56, 40, 56, 32, 33, 71, 60, 36, 30, 3, 31, 15, 4, 21, 2, -2, -25, -30, -26, -13, -9, -26, -20, -34, -34, -51, -28, 6, -9, -24, -49, -67, -54, -54, -52, -41, -42, -58, -37, 16, 39, 31, 16, 19, 11, -4, -23, -5, 24, 1, 10, 24, 26, 15, 34, 70, 77, 56, 33, 43, 28, 17, 25, 12, 2, 0, -12, -15, -2, 10, -19, -28, -45, -41, -28, -17, -3, -2, -9, -3, -25, -45, -14, 23, 10, -5, -19, -32, -22, -10, -1, -15, -16, -6, 13, 48, 70, 55, 23, 23, 10, -8, -14, 6, 8, -12, -5, 13, 10, -14, 0, 33, 23, 18, 43, 21, 26, 33, 13, -14, -7, -3, -31, -29, -5, -5, -25, -27, -35, -56, -45, -21, -17, -40, -14, 2, -23, -38, -9, 8, -16, -16, -7, -13, -25, -4, -12, -21, -14, 3, 13, 44, 65, 60, 40, 15, 5, -20, -22, -3, 3, 20, 39, 39, 9, 6, 21, 48, 24, 25, 25, 11, 0, 4, -5, -31, -34, -22, -45, -40, -24, -24, -41, -38, -47, -54, -45, -16, -22, -32, -7, 16, -1, -11, 23, 31, -1, -10, -20, -19, -9, 15, -10, -28, -21, 4, 24, 45, 60, 56, 46, 30, 26, 23, 36, 48, 33, 46, 40, 34, 19, 12, 23, 43, 37, 41, 43, 22, 24, 11, -11, -2, -5, 8, -28, -33, -11, -5, -26, -30, -25, -45, -21, -8, -26, -35, -37, -39, -54, -56, -20, -23, -42, -52, -49, -63, -47, -31, -29, -16, -21, -7, 14, 26, 48, 32, 12, -10, -22, -24, -6, 0, 33, 44, 31, 25, 15, 10, 34, 48, 38, 14, 9, 16, 12, -23, -15, -15, -8, -9, -19, -22, -2, -8, -10, -32, -27, 4, 12, -5, 1, -1, 4, -5, -3, -5, 10, 37, 18, -8, -19, -3, 0, -10, -5, -31, -32, -29, -2, 18, 32, 33, 14, -12, -15, 6, 8, 36, 66, 48, 38, 37, 42, 29, 49, 50, 42, 28, 25, 33, 15, 2, 4, 2, 4, 2, -11, -1, 6, 3, 9, -14, -12, -5, -12, -33, -36, -29, -26, -38, -44, -42, -38, -38, -52, -67, -70, -50, -32, -27, -29, -38, -26, -27, 1, 21, 23, 16, -17, -34, -26, -18, -20, 2, 11, 13, 5, 10, 13, 12, 28, 33, 35, 14, 14, 14, -8, -24, -25, -8, -16, -23, -14, 12, 8, 21, 25, 13, 25, 29, 25, 6, 3, 36, 26, 34, 11, 30, 29, 34, 23, 0, 1, 7, 8, 1, -10, -9, -13, 5, 17, 30, 26, 25, 3, -11, -4, -4, 9, 13, 17, 6, 4, 17, -1, -4, 9, 16, 22, 3, -2, -4, -16, -28, -22, -13, -34, -37, -31, -9, -7, -12, -16, -26, -12, -14, -11, -23, -16, -24, -33, -24, -30, -17, -28, -34, -44, -51, -34, -24, -22, -25, -2, 14, 23, 38, 46, 43, 28, 10, -6, -11, 1, 0, 5, 18, 16, -3, 12, 27, 23, 32, 48, 42, 34, 21, 21, 10, -3, -10, -10, -20, -38, -34, -29, -22, -16, -15, -17, -9, 7, 6, 6, -6, 1, 7, 6, 3, 11, 30, 30, 15, 11, 11, 10, 17, 22, 23, 24, 9, 15, 5, -2, 4, 3, -17, -21, -4, -21, -6, 8, -9, -1, 0, 8, -7, -18, -16, -3, -14, -13, -8, -17, -10, -8, -26, -37, -28, -17, -35, -17, -10, 1, -6, 1, 25, 32, 26, 9, -18, -19, 1, -12, -20, 2, 12, 5, -4, 15, 14, 15, 15, 17, 14, 2, 6, 3, -18, -21, -9, -1, -15, -11, -15, -22, -1, 3, -7, 0, 14, 14, -4, -13, 4, 18, 12, 15, 19, 25, 28, 27, 12, 9, 9, -10, -17, -4, -5, -4, -20, -19, 11, 20, 13, 0, -19, -8, 6, -9, 6, 26, 18, 14, 17, 22, 24, 18, 21, 37, 20, 7, 11, -8, -11, -4, -3, -8, -22, -16, -18, -15, -4, -9, -21, -10, 5, -8, -7, -17, -7, -9, -20, -28, -35, -31, -23, -23, -29, -28, -28, -33, -28, -24, -6, 0, -4, 7, 29, 25, 15, -6, -19, 1, -2, -22, 4, 10, 1, 9, 10, 13, 4, 6, 21, 15, 5, 21, 11, -18, -21, -15, -3, -4, -15, -15, -19, 4, 19, 11, 2, 17, 16, 2, 14, 14, 17, 20, 22, 20, 10, 16, 27, 12, 8, 11, 5, -9, -10, -6, -1, -7, -12, -3, 3, 8, 9, -5, -3, 6, -5, -6, 23, 14, 11, 12, 21, 21, 4, 18, 30, 7, 12, 25, 3, -11, -16, -15, -10, -13, -8, -6, -21, 2, -2, -25, -18, -8, -22, -22, -17, -12, -7, -12, -15, -20, -41, -28, -24, -23, -12, -12, -15, -10, -7, 2, 1, 6, 18, 29, 23, 21, 20, 9, -3, -9, -9, -10, -15, -8, -11, -2, 6, 14, 7, 7, 11, 9, 14, 2, 3, 7, 6, 6, -21, -20, -10, -12, -15, -16, -18, -14, -11, -14, 0, 0, -5, 3, 14, 12, 9, 0, -11, 5, 5, 12, 11, -1, 5, 3, 1, 4, -1, -1, 13, 16, 8, 14, 9, -2, -7, -11, -17, -12, -5, -9, -10, -13, -4, 1, 0, 4, 5, 0, 2, 3, 5, 14, 18, 9, -3, 2, 15, 14, 6, 2, 1, -1, -5, -6, 0, 0, 0, 7, 20, 22, 23, 13, 13, 17, 20, 35, 25, 20, 20, 14, 17, 16, 3, 7, 18, 15, 13, 17, 6, -5, -6, -13, -23, -19, -19, -22, -22, -24, -17, -18, -22, -27, -31, -30, -29, -30, -33, -36, -34, -37, -47, -38, -24, -28, -27, -31, -30, -28, -26, -20, -14, -14, -9, 4, 17, 21, 15, 12, 25, 29, 33, 33, 30, 30, 31, 19, 20, 14, 4, 10, 17, 18, 21, 28, 19, 20, 20, 5, -2, -3, -7, -10, -2, 1, 4, 6, 4, 5, 3, 2, -1, -4, -7, -10, -3, -6, -16, -5, -1, -8, -7, -6, -9, -10, -11, -7, -6, -10, -11, 2, 11, 7, 1, 6, 12, 16, 18, 15, 11, 14, 16, 9, 11, 6, 5, 13, 14, 13, 11, 0, -11, -4, -4, -8, -7, -5, -6, -3, -1, 2, -1, -6, -7, -9, -9, -9, -15, -11, -14, -17, -16, -18, -17, -12, -7, -8, -7, -6, -2, -3, -12, -15, -15, -18, -13, -19, -23, -24, -21, -21, -13, -12, -7, -3, -7, -6, -4, 2, 1, 1, 3, 9, 23, 28, 23, 17, 24, 27, 22, 19, 16, 19, 10, 9, 10, 10, 19, 8, 11, 16, 15, 11, 13, 14, 7, 5, -3, -7, -12, -15, -16, -17, -10, -5, 4, -2, -2, -9, -13, -9, -8, -10, -10, -12, -5, 3, 7, 3, 9, 3, 4, -1, -2, 2, -4, -9, -4, 0, 4, 4, -6, -3, 12, 10, 15, 12, 7, 7, 1, -1, 8, 11, 9, 9, 13, 17, 17, 9, 11, 4, 0, -3, -6, -8, -9, -10, -17, -20, -24, -17, -19, -22, -20, -21, -15, -16, -19, -23, -21, -28, -26, -15, -14, -4, -1, -6, -3, -1, 4, 9, 2, 4, 7, 7, 11, 15, 6, 17, 24, 16, 15, 9, 6, 6, 3, 1, 3, 2, -2, 6, 6, 6, 3, -6, -3, -8, -7, -10, -13, -17, -18, -16, -19, -13, -9, -3, 4, 10, 7, 7, 12, 11, 13, 10, 6, 1, 2, 4, 4, 10, 10, 7, 4, 1, 4, -5, -12, -3, 1, 10, 7, 6, 4, 19, 22, 20, 23, 16, 15, 19, 17, 14, 9, 7, 4, 4, 2, 5, 3, 0, 0, -7, -7, -8, -7, -14, -15, -18, -25, -21, -21, -16, -13, -14, -17, -18, -23, -21, -23, -29, -32, -33, -30, -23, -13, -11, -10, -8, -7, -2, 1, -3, -1, 5, 13, 17, 13, 11, 13, 16, 14, 10, 11, 8, 16, 13, 4, 0, 7, 13, 14, 15, 15, 17, 17, 9, 8, 9, 9, 2, 5, 11, 14, 7, 4, 11, 10, 5, 7, 2, -1, -4, -9, -16, -15, -12, -9, -15, -23, -21, -22, -22, -20, -22, -22, -21, -22, -22, -13, -6, 4, 2, -2, 2, 7, 6, 10, 8, 9, 12, 21, 16, 11, 7, 11, 13, 11, 10, 11, 13, 9, 6, 6, 5, 4, -5, 1, 4, 5, -1, -2, 6, 3, 3, -3, -10, -14, -14, -14, -16, -8, -6, -1, -6, -7, -5, -7, -6, -9, -8, -8, -4, -5, -8, -6, 3, 12, 4, -2, 3, 1, 1, -1, -4, -4, 5, 6, 1, -4, -3, 5, 9, 8, 18, 20, 22, 15, 11, 11, 15, 12, 9, 11, 11, 11, 5, 10, 12, 5, 3, -2, -4, -9, -9, -16, -17, -14, -12, -14, -20, -15, -16, -17, -17, -19, -20, -19, -15, -17, -15, -13, -2, -3, -13, -8, 0, 4, 7, 6, 4, 11, 13, 14, 11, 5, 6, 3, -1, -2, 2, 3, -1, -2, -6, -4, -1, -3, 0, 3, 1, -2, -5, -5, -3, -6, -9, -7, -15, -13, -10, -8, -4, 1, 9, 7, 2, 8, 8, 9, 12, 14, 7, 12, 12, 12, 8, 14, 19, 11, 7, 10, 13, 10, 2, -2, -6, -1, 2, 6, 3, 1, 4, 2, 2, 5, 8, 8, 7, 7, 2, 0, -3, -6, -3, -1, -6, -12, -9, -6, -7, -9, -10, -14, -16, -12, -12, -11, -13, -16, -16, -20, -18, -14, -10, -8, -9, -13, -9, -8, -9, -7, -9, -8, -3, -4, -3, -6, 0, 2, 3, -3, 2, 5, 1, 6, 5, 5, 10, 11, 17, 15, 20, 25, 20, 15, 17, 13, 12, 11, 7, 4, -1, -2, 6, 7, 7, 9, 10, 7, 9, 7, 5, 5, 1, -6, -2, -5, -6, -3, -3, -1, -3, -5, -3, -6, -8, -7, -8, -11, -12, -16, -19, -19, -14, -14, -17, -17, -11, -12, -15, -6, -8, -12, -12, -9, -7, -6, 2, 9, 6, 8, 11, 13, 15, 14, 11, 7, 3, 3, 4, 7, 9, 10, 6, 6, 5, 7, 11, 11, 4, 1, 1, -3, -5, -1, -1, -1, -5, -2, -1, -1, 1, 1, -3, -7, -7, -9, -12, -11, -3, -3, -7, -6, -6, -5, -5, 0, -3, -4, -2, 2, -1, 0, 6, 7, 7, 4, 3, 5, -1, 0, -1, -7, -9, -8, -11, -5, 0, -1, 0, 2, 2, 5, 10, 10, 7, 7, 7, 8, 8, 9, 11, 9, 8, 9, 6, 4, 2, 0, -3, -5, -8, -8, -12, -8, -1, -4, -4, -5, -7, -9, -6, -5, -6, -8, -6, -3, -7, 0, 5, 6, 3, 1, 6, 6, 4, 3, 1, -2, -4, -6, -4, 3, 7, 3, 0, -1, -3, -2, -1, -2, -5, -8, -9, -7, -9, -8, -6, -9, -7, -9, -7, -6, -7, -6, -7, -7, -7, -7, -8, -2, 1, 2, 4, 3, 5, 6, 10, 11, 9, 10, 12, 9, 9, 11, 9, 10, 8, 7, 7, 6, 7, 5, 4, 5, 4, -1, -4, -3, -5, -1, -2, -4, -4, -4, -4, -2, -2, -3, -4, -2, -1, 0, 1, 8, 8, 4, 4, 4, 2, -2, -3, -5, -6, -9, -10, -8, -5, 2, 1, -2, -2, -2, -2, -2, -5, -5, -7, -7, -3, -4, -6, -4, -3, -5, -7, -5, -4, -7, -9, -6, -6, -9, -7, -6, -2, 3, 3, 4, 5, 3, 4, 5, 2, 0, 2, 3, 2, 5, 7, 10, 9, 7, 7, 6, 4, 1, -2, -5, -6, -10, -10, -8, 2, 8, 7, 6, 7, 5, 5, 7, 6, 3, 4, 3, 4, 1, 3, 2, 4, 2, 1, 1, -1, -3, -3, -4, -6, -9, -9, -9, -7, -6, -5, -5, -4, -5, -2, -1, -2, -3, -1, -1, -3, -2, 2, 2, 3, 4, 4, 2, 0, -1, -3, -4, -4, -5, -7, -2, 2, 2, -1, -3, -1, -4, -3, -2, -4, -4, -2, -1, -2, -4, -2, -2, -1, -2, -2, -2, -3, -2, 0, 2, 0, -2, -2, 0, 2, 3, 5, 4, 4, 4, 6, 3, 1, 0, 0, 0, 0, 5, 5, 4, 6, 4, 2, 0, -2, -3, -6, -9, -8, -10, -10, -2, 3, 4, 4, 4, 5, 4, 4, 5, 4, 4, 4, 4, 2, 3, 2, 2, 2, 1, 1, 0, -2, -3, -3, -4, -6, -8, -7, -4, -6, -3, -3, -3, -2, 1, 0, -1, -2, -2, -1, -1, 0, 1, 0, 0, 1, 0, 0, 0, -1, -2, -3, -3, -4, -5, -4, -3, -3, -3, -3, -3, -3, -2, -1, 0, -1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 2, 3, 3, 2, 2, 0, -1, -1, -2, -3, -3, -4, -5, -4, 0, 3, 3, 3, 3, 2, 3, 4, 6, 4, 4, 3, 2, 1, 2, 1, 0, 0, -1, -2, -3, -3, -2, -2, -3, -3, -3, -3, -3, -2, -2, -2, -2, -2, -2, -2, -2, -3, -2, -3, -2, -2, 0, 0, 0, 0, 0, -1, -1, -2, -2, -3, -2, -4, -4, -3, 0, -1, 0, 0, 0, 0, 0, 1, 2, 1, 1, 1, 0, 0, 0, -1, 0, -1, -1, -1, -1, -1, 0, 0, -1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, -1, -1, -2, -2, -2, -2, -2, -3, -3, -1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, -8, -33, -24, -25, -25, -26, -27, -32, -28, -36, -31, -36, -22, -34, 11, -74, -14, 94, 41, 28, 33, 30, 40, 34, 23, 41, 40, 60, 56, 59, 60, 44, 39, 54, 45, 52, 17, 44, 62, 34, 33, 19, 18, 43, 35, 22, 36, -15, -10, 32, -7, -12, -6, -8, -50, -47, -44, -4, -25, -48, -76, -58, -75, -96, -85, -118, -114, -63, -106, -103, -83, -110, -99, -84, -76, -58, -63, -61, -51, -53, -36, -32, -41, -27, -11, 11, 8, 27, 19, 30, 35, 28, 57, 53, 38, 71, 51, 68, 110, 78, 89, 109, 97, 82, 94, 115, 114, 79, 70, 79, 94, 85, 76, 84, 95, 83, 82, 55, 54, 54, 41, 41, 27, 20, 6, -11, -21, -16, -14, -33, -33, -52, -54, -59, -62, -71, -79, -88, -88, -78, -78, -72, -71, -94, -99, -93, -90, -78, -87, -105, -103, -79, -62, -71, -78, -63, -61, -66, -49, -23, -10, -11, -24, -20, -4, -22, 9, 8, 27, 43, 34, 38, 51, 83, 65, 58, 74, 75, 70, 73, 71, 65, 100, 89, 94, 65, 84, 49, 49, 61, 54, 43, 51, 58, 53, 35, 40, 36, 38, 34, 23, 14, -12, -10, -1, -1, -11, -12, -19, -33, -66, -52, -42, -37, -55, -42, -28, -32, -29, -35, -41, -28, -25, -46, -85, -64, -62, -55, -49, -68, -55, -53, -52, -47, -43, -26, -32, -41, -34, -35, -40, -26, -8, -1, -6, -11, 5, -2, 8, 3, 8, 6, 4, 20, 29, 43, 24, 33, 20, 30, 24, 39, 38, 40, 29, 37, 36, 39, 61, 58, 41, 51, 59, 51, 55, 58, 48, 32, 45, 40, 27, 30, 41, 44, 26, 19, 23, -3, 7, 0, -3, 2, 3, -6, -5, -14, -6, -10, -27, -45, -47, -41, -38, -50, -51, -46, -43, -45, -65, -65, -80, -95, -82, -74, -66, -69, -67, -33, -31, -53, -48, -51, -43, -18, -24, -24, -33, -26, -10, 0, -17, -6, 17, 31, 2, 23, 45, 46, 12, 75, 38, 63, 69, 31, 38, 80, 57, 48, 59, 81, 74, 32, 52, 72, 24, 60, 44, 55, 40, 28, 48, 33, 24, 10, -2, 21, 34, 13, 18, 7, -1, -12, -20, -18, -30, -9, -7, -30, -27, -26, -38, -20, -54, -55, -64, -53, -36, -62, -37, -71, -47, -42, -71, -45, -55, -50, -54, -56, -36, -37, -54, -36, -12, -38, -33, -26, -7, -22, -44, -10, 2, 3, 15, 8, 18, 6, 12, 8, 15, 28, 22, 50, 35, 55, 42, 36, 49, 52, 64, 48, 60, 49, 60, 62, 40, 47, 68, 52, 59, 61, 44, 53, 44, 35, 31, 31, 47, 22, 6, 4, -7, 5, -4, -21, -13, -9, -10, -27, -46, -32, -44, -46, -62, -44, -51, -67, -53, -59, -63, -74, -67, -61, -61, -65, -47, -58, -57, -45, -41, -46, -41, -38, -22, -25, -34, -16, -10, -18, 0, 1, -6, 5, 17, 15, 10, 23, 38, 28, 28, 54, 40, 19, 55, 55, 41, 46, 53, 40, 49, 51, 52, 41, 56, 39, 53, 38, 33, 35, 18, 15, 38, 30, 23, 27, 13, 11, 7, 16, -1, 0, 0, 13, -6, -10, -15, -10, -10, -24, -20, -16, -38, -36, -21, -40, -32, -42, -38, -52, -53, -41, -48, -58, -50, -47, -37, -41, -45, -29, -41, -6, -48, -24, -25, -15, -9, -10, -10, -10, -1, -17, 4, 3, 10, -4, 9, 15, 25, 24, 19, 23, 34, 28, 33, 37, 38, 26, 36, 47, 35, 46, 45, 28, 35, 32, 32, 24, 21, 26, 23, 19, 37, 20, 9, 29, -2, 26, 24, 8, 4, 14, 21, 11, -9, -8, 4, -9, -31, -11, -15, -21, -24, -29, -22, -33, -26, -29, -48, -32, -44, -28, -22, -35, -30, -38, -31, -46, -44, -36, -27, -23, -29, -24, -11, -20, -28, -13, -34, -19, -1, 7, -3, -1, 6, -3, 5, 4, 8, 17, 26, 19, 33, 27, 16, 35, 14, 36, 39, 22, 32, 31, 19, 32, 23, 29, 21, 30, 29, 23, 31, 13, 24, 17, 11, 26, 18, 12, 5, 23, 16, 9, 15, -10, 3, 18, -15, -4, -4, 6, -14, -15, -5, -34, -11, -20, -18, -8, -17, -29, -30, -29, -19, -34, -35, -20, -36, -20, -16, -21, -38, -16, -30, -24, -25, -19, -18, -15, -7, -5, -5, -10, -23, -3, -14, 0, -1, -12, -9, 7, 7, 2, 12, 5, 7, 19, 10, 21, 21, 27, 30, 22, 18, 34, 22, 11, 26, 24, 20, 21, 25, 29, 22, 27, 27, 20, 10, 20, 16, 22, 15, 16, 16, 5, 19, 10, 3, 22, -5, -5, -7, -16, -4, -11, -22, -7, -16, -11, -23, -16, -30, -24, -28, -20, -29, -24, -32, -22, -22, -30, -17, -23, -28, -22, -20, -21, -21, -17, -30, -15, -14, -20, -9, 3, 6, 5, -20, 10, 13, -2, 11, 8, -1, 7, 16, 5, 22, 23, 13, 22, 13, 22, 25, 15, 16, 11, 15, 13, 7, 12, 19, 18, 20, 12, 23, 11, 6, 10, 1, 11, 19, 5, 20, 0, 11, 11, 1, 14, 15, -3, -1, -7, 6, -6, -9, -9, 4, -3, -10, -20, -14, -9, -14, -7, -10, -5, -4, -29, -14, -12, -26, -21, -27, -18, -10, -19, -27, -18, -8, -25, -8, -13, -15, -14, -15, 5, -13, -7, -11, -4, -12, 0, 15, 5, 4, 1, 11, 6, 4, 3, 6, 21, 19, 8, 15, 13, 6, 14, 16, 18, 17, 20, 15, 11, 15, 24, 13, 11, 19, 7, 17, 14, 6, 17, 7, 7, 6, 6, 5, 11, 0, 6, 0, -6, 5, 1, -11, -6, -1, -8, -9, -15, -7, -4, -16, -17, -13, -13, -17, -14, -12, -12, -28, -13, -19, -25, -31, -24, -17, -17, -16, -7, -15, -12, -8, -15, -8, -16, -10, -4, -1, -2, 3, 5, 2, -2, 5, 3, 6, 10, 8, 11, 14, 14, 13, 15, 22, 16, 14, 18, 13, 17, 19, 16, 10, 17, 8, 17, 14, 3, 14, 7, 10, 10, 7, 6, 6, -1, 6, 1, 0, 12, -6, 6, 12, -4, -5, -4, -2, -2, -1, -2, -8, -11, -9, -11, -11, -18, -6, -5, -16, -9, -14, -10, -13, -10, -11, -15, -14, -14, -12, -17, -17, -17, -7, -11, -14, -15, -12, -6, -15, -5, -13, -9, 0, 12, -2, -2, 6, 2, -7, 4, 10, 2, 9, 8, 7, 4, 5, 11, 15, 11, 10, 18, 9, 13, 13, 13, 21, 11, 18, 19, 13, 14, 16, 6, 8, 1, 19, 11, 10, 11, 1, 3, -1, -1, 5, -11, 5, -1, -5, -3, -13, -10, -6, -7, -5, -15, -10, -11, -18, -8, -16, -20, -18, -9, -12, -17, -21, -21, -13, -21, -8, -10, -10, -5, -16, -7, 2, -6, -6, -9, -7, -2, -9, -5, 6, -7, 1, 3, -1, 2, 1, 2, 9, 8, 5, 15, 12, 1, 11, 9, 8, 10, 15, 14, 5, 13, 17, 14, 15, 10, 7, 16, 5, 5, 5, 8, 9, 10, 10, 7, 0, 4, 6, 9, -10, -4, 5, 2, -1, 0, -3, -4, -5, -10, -5, -8, -9, -10, -3, -13, -6, -9, -20, -15, -11, -18, -14, -10, -12, -20, -14, -14, -7, -12, -21, -14, -9, -8, -11, -5, -2, -7, -4, 4, -2, -3, -1, 0, -1, 8, 6, 9, 7, 10, 6, 3, 4, 7, 10, 11, 6, 9, 17, 11, 9, 7, -2, 16, 13, 12, 18, 5, 16, 9, 4, 9, 6, 8, 9, 4, 4, 3, -2, -3, 2, -6, -3, 1, -7, -6, -3, -6, -14, -8, -9, -4, -13, -9, -8, -16, -10, -12, -13, -11, -7, -8, -12, -9, -8, -7, -11, -4, -8, -7, -8, -3, -13, -10, -3, 6, -5, -5, 0, -5, -3, 6, -2, -2, 4, -2, 6, 2, -2, 5, 5, -2, 5, 15, 13, 4, 6, 6, 14, 9, 4, 8, 7, 3, 11, 12, 2, 10, 7, 10, 8, 4, 6, 2, 0, 3, 2, 4, 2, -6, -2, 2, -4, 3, -5, -6, -5, -5, -5, -4, -8, -7, -4, -4, -7, -8, -7, -13, -10, -10, -11, -9, -8, -8, -7, -11, -7, -3, -9, -6, -7, -3, -4, -5, 3, -3, -1, -2, -4, 1, 4, 0, 3, 0, 5, 2, 0, 5, 4, 1, 3, 1, 0, 1, 7, 3, 0, 4, 3, 6, 5, 0, 9, 5, 7, 6, 3, 6, 2, 3, 5, -4, 9, 0, 4, 10, 0, 5, 1, -2, 4, -3, -3, -2, 0, 2, -7, 3, -10, -1, -6, -9, -2, -4, -10, -3, -7, -6, -4, -10, -6, -6, -11, -6, 0, -6, -8, -4, -1, -9, -10, 0, -6, -7, -2, -7, 1, -5, -5, -1, 1, -6, 2, 0, -3, -1, 7, -4, 0, 7, 0, 8, 2, 3, 4, 4, 2, 5, -1, 6, 7, 5, 6, 4, 2, 4, 6, 8, 6, 3, 1, 8, 9, 2, -1, 4, 3, 4, 3, -3, 7, 4, 3, -2, 2, -4, -6, -2, -5, -2, -3, 0, -5, -6, -13, -5, -6, -11, -9, -10, -5, -4, -9, -9, -7, -7, -8, -8, -6, -5, -7, -5, -1, -3, -4, -2, -2, 2, -3, 1, 2, -3, 1, 2, 1, 0, 1, 5, 0, 2, 5, 2, 0, 4, 1, 7, 3, 2, 6, 0, 5, 7, 5, 5, 1, 3, 3, 5, 10, 3, 4, 8, 2, 7, 3, -2, 3, 0, -1, -1, 1, 0, 1, -3, -2, -5, -4, -3, -1, -7, -8, -4, -4, -10, -2, -8, -8, -8, -8, -9, -6, -8, -9, -4, -2, -7, -5, -2, -7, -6, -9, -2, 0, -4, 4, -6, -3, -4, -1, 2, 1, 2, 9, 0, 3, 0, 6, 4, 0, 5, 6, 2, 7, 7, 5, 7, 6, 8, 6, 6, 5, 5, 1, 6, 5, -1, 3, 4, -1, 4, 1, 4, 3, -5, 0, 4, 1, 4, -2, -3, -4, 0, -4, -8, -2, -5, -4, -8, -6, -5, -3, -3, -7, -9, -6, -10, -10, -6, -6, -5, -4, -7, -6, -4, -10, -3, -10, 0, -2, -2, -6, -1, 3, -3, -3, 1, 2, 1, 4, 3, 4, 3, 4, 1, 2, 6, 5, 5, 5, 7, 9, 1, 5, 4, 4, 7, 2, 9, 2, 4, 8, 2, 5, 6, 3, -2, -2, -1, -2, -1, 1, -2, -4, 1, -6, -2, -5, -3, -5, -5, -6, -4, -3, -4, -10, -4, -3, -8, -4, 0, -3, -5, -6, -6, -3, -1, -7, -3, 1, -1, -4, -2, 1, -2, 0, -1, -2, 0, 0, 5, -2, 0, 3, 3, 1, 5, 2, 4, 1, 4, 1, 2, 3, 3, 3, 4, 3, 3, 5, 1, 4, 2, 3, 1, 2, 0, 2, 1, -2, -2, -1, 0, -2, -1, -1, -3, -5, -2, 0, -5, -1, 0, -5, -2, -2, -2, -3, -3, -1, -4, -1, -2, -4, -2, -1, -2, -1, 0, -3, -1, -1, 0, 1, -1, -1, 3, -4, -2, -2, 4, -2, -1, -1, -1, 0, 0, -1, -1, -1, -1, 2, 0, -1, 2, -1, 0, -1, 2, 0, 3, 5, -2, 1, 2, 0, 5, 0, -3, 4, -3, 1, 2, 0, 4, -1, -2, 1, 0, 0, 0, -1, 1, -2, 0, 1, 1, 0, -5, 1, -2, -1, 0, -2, -3, -1, -3, 0, -2, -3, -4, 1, -2, -3, -2, -2, -1, -1, -2, -1, -4, -5, 2, -4, 0, 1, -1, 2, -2, -1, 0, 0, 1, -3, 3, 2, 0, -2, 2, 1, 2, -2, 5, 3, -2, -2, -1, 1, 0, 0, 1, 3, 2, 0, 0, -1, -2, 1, 1, 2, 1, 1, -1, 0, -1, -1, -1, -3, 1, 1, 2, -2, -1, 0, 0, -2, 0, -1, -1, 2, -2, 1, -1, 0, 0, -1, -1, -2, 0, -1, 1, -1, -1, 2, -2, 0, -1, -1, 2, -1, 0, -3, -1, 0, 0, 0, -3, -3, -2, 0, 0, -1, -1, 0, -4, 2, 0, -2, 0, 1, -3, -1, 2, 1, 0, -1, 0, 0, -1, 0, 2, -1, -1, 0, 0, -2, 1, 1, 0, 1, 0, 2, -3, -2, 2, -1, -1, 2, -2, 1, 1, 0, 0, 1, 1, 0, -4, 3, -1, 2, 0, 2, -1, -2, 0, 1, 1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -1, -1, 1, 0, -5, 0, -1, -1, -1, 1, -1, 1, -1, 1, 0, -2, 0, -2, 1, -1, 1, 0, -1, -2, 0, -1, 0, 0, 2, 0, 0, 0, 1, 0, 0, 2, 0, -1, 0, 0, 0, 2, -1, 1, 1, -1, -1, 0, 0, 1, 1, 0, 0, 0, 0, -1, 0, 0, -2, 0, 0, -1, 1, -2, -1, -1, -1, -2, -1, -2, 1, -1, 0, -2, -2, 1, -2, -1, 1, 0, 1, 1, -1, -1, 0, -1, 0, 0, 0, -2, 0, -1, 0, 0, -1, -2, -2, -2, 1, -1, 0, 0, -1, 1, 1, -2, -1, -2, -1, 1, -1, -1, -2, -2, 0, 0, 1, -1, -1, -1, -1, -2, 2, 0, 0, 1, 1, 1, -2, 0, -1, 0, -1, -1, 2, 0, -1, -1, -1, 1, -1, 2, 0, -1, 1, 1, 0, 1, 0, -1, -1, -1, -1, -3, 0, 0, -1, 1, 0, 0, -2, -2, -2, 0, -1, 0, 0, -1, 0, -1, -2, -1, -2, 0, -2, 0, 0, -1, -2, 1, -2, 0, -1, -2, 2, 0, -1, 2, -1, 1, -1, 0, 0, -1, 0, 0, 0, -1, 0, 1, 0, 0, 1, 0, -1, -1, 0, -2, -1, 0, 0, 1, 0, 0, 0, 0, -1, -1, 1, -1, -2, -1, 0, 0, -2, 0, -1, 0, 0, 0, 1, 0, 0, -1, 1, 0, -1, 0, 1, -1, 0, -1, -2, 0, -1, 0, -1, -1, -1, 0, -1, 0, 0, 0, -1, -1, 0, -2, 0, 0, 0, -2, -2, 0, -2, -1, -1, -1, -2, 0, -1, -1, -1, 0, 0, -1, -1, 0, 1, -1, -1, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0, 1, 0, 0, -1, 0, 0, -1, -1, 0, -1, -1, 0, -1, 0, -1, -1, 0, -2, -1, 0, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, -1, 1, 0, 0, 0, -1, -1, 0, -1, -1, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, 0, 0, -1, 0, -2, 0, -1, -1, -1, 0, -1, -1, 0, -1, 0, 0, 0, -2, -1, 0, -1, -1, 0, 1, -1, -1, 0, 0, 0, 0, -1, -1, -1, -1, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, -1, -1, 0, 0, -1, -1, 0, -1, 0, 0, 0, -1, 0, -1, -1, 0, -2, -1, -1, -1, 0, -1, 0, -1, -1, 0, 0, -1, 0, -1, 0, -1, -1, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, 0, -1, -1, 0, 0, 0, -1, 0, -1, 0, 1, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, -1, 0, 0, 0, -1, 0, 1, -1, -1, -1, 0, 0, -1, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, 0, -1, 0, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, 0, -1, 0, -1, 0, 0, -1, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, -1, -1, 0, -1, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, -1, 0, 0, 0, -1, -1, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, -1, -1, 0, 0, 0, -1, 0, -1, -1, 0, -1, 0, 0, -1, -1, -1, -1, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, -1, 0, -1, 0, 0, -1, -1, -1, 0, -1, -1, 0, -1, -1, 0, 0, -1, -1, -1, -1, 0, -1, -1, 0, 0, -1, 0, 0, 0, -1, -1, 0, -1, -1, -1, 0, 0, -1, -1, -1, -1, -1, 0, -1, 0, 0, -1, -1, 0, 0, -1, 0, 0, -1, -1, -1, 0, -1, 0, 0, -1, -1, 0, 0, -1, -1, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -4, 11, 6, 16, 10, -16, -48, -44, 2, 67, 42, -17, -51, 15, 71, 12, -22, -14, -44, -35, 11, 17, -18, 2, -15, 19, 12, -1, -44, -15, 50, 45, -25, -61, 17, 10, -10, 31, 18, -72, -27, 57, 26, -13, -17, -2, 6, -1, -23, -54, 17, 39, 8, 30, 28, -6, -71, -5, 33, 27, -5, 17, 10, -23, -6, 12, -26, -6, -7, -9, -14, 11, 37, 41, 8, -33, -14, 8, -31, -38, 13, 9, 15, 35, 33, 11, 17, -41, -48, -33, 29, 25, 16, -9, -9, -17, -19, -29, 43, 64, -2, -55, -42, -1, -21, -4, 29, 34, -25, -67, -29, 1, 51, 49, 25, -6, -15, -48, -76, -3, 60, 78, 33, 19, 13, -38, -35, -35, -2, 62, 19, -4, -12, -4, -4, -32, -30, 8, 68, -43, -66, -28, 55, 51, 20, -28, -29, -19, 20, -2, 8, 21, -15, -43, 24, 22, -7, -2, 35, 15, -2, -24, -12, 3, 31, 13, -15, -20, -17, -17, 26, -26, 24, -3, 7, 21, 26, -3, -17, -26, -50, -26, 33, 58, 49, -22, -67, -17, 24, 7, -57, 5, 42, -11, -3, 32, -3, 7, 13, -11, -9, 27, 17, 1, -5, -9, -18, -19, -3, -23, -5, 7, -8, 9, 13, 12, -5, 7, -37, 22, 26, 21, 24, -20, -35, 23, 24, -35, -15, 46, -38, -48, -14, -4, 0, -22, 3, 43, 38, -1, -14, -8, -5, -14, 1, 21, 23, 29, -19, -47, -42, -49, -10, 66, 77, 48, -29, -32, 1, -11, 8, 17, -17, 3, 43, 33, -22, -19, -41, 29, 22, -42, 9, 63, 28, -23, -59, -65, 7, 53, -22, -10, -27, -30, 36, 48, -4, -6, -22, -16, 10, 14, -7, 22, 50, -4, -25, -41, -55, -62, 23, 68, -16, -31, 49, 57, 21, -38, 14, 12, -43, -49, -16, 28, 7, -12, -50, -17, 49, 65, 18, 1, -8, 28, 2, -27, -13, 12, -11, -52, 4, 31, -32, -39, 15, 8, -19, 6, 25, -1, -23, 13, 34, 59, 36, -16, -5, -7, -28, -30, 1, -14, -42, 10, 43, 26, -25, -37, -61, 1, 63, 62, 1, -36, -24, 38, -7, -26, 27, 10, 4, 2, -19, -22, -27, -24, 0, 33, -8, -57, -12, 62, 77, 51, -10, -42, -27, -28, -31, -3, 5, 21, 10, 15, -27, -18, -18, -10, 3, 17, 19, 18, -16, -20, 25, -3, -19, -5, 32, 17, -3, -32, -8, 2, -11, -24, -17, -11, 3, 42, 15, -12, -2, 26, 9, -4, -30, -3, 16, 7, 13, 34, 40, 114, 11, -104, -71, 7, -14, -34, -26, 35, 45, 47, 7, -7, -16, 11, -6, -29, -32, 1, 24, 32, 10, 29, -10, -74, -80, -20, 18, 9, 18, 61, 38, -27, -44, 13, 16, -26, 20, 69, 14, -14, -46, -7, -6, -35, 0, 9, 5, 58, 71, -36, -78, -15, 43, 34, -61, -101, -27, 45, 26, -10, 23, 69, 69, 5, -72, -62, 19, 16, -37, -60, 37, 60, 10, -49, -10, -2, -1, 43, 44, 10, -50, -5, 19, 8, -43, -58, -17, 32, 28, 4, -1, -18, -10, 13, 8, 1, 1, 22, -3, -4, 9, -8, -9, 17, 3, -15, -8, 14, 11, -14, -11, -5, 13, -24, -34, -1, -16, -4, 32, 35, -32, 9, 22, 12, -27, -16, 14, 15, 0, -2, -12, -31, -24, 14, 48, 10, -14, -7, -22, 4, -8, -14, 19, 21, -21, -25, -12, 19, 24, 19, 27, -3, -15, -16, 10, 21, -14, 3, 8, 3, -11, -33, -16, 7, 5, -8, 2, -3, 12, 5, -34, -19, -6, 26, 19, 0, -4, -12, 5, 12, 20, 16, 19, 18, -13, -42, -26, -1, 0, -18, -16, 10, 27, 23, -5, -7, 9, -8, 7, 22, 10, -28, -51, -26, 13, 44, 17, 16, 25, 14, -32, -45, -36, -40, -3, 22, 41, 34, -12, -35, -31, 18, 3, 31, 28, 4, -21, 2, -14, -24, -23, 19, -6, -7, -10, -1, -13, -13, 21, 52, 28, 7, 1, -25, -36, 2, 34, 10, -37, -31, -13, 19, 11, -4, -20, 15, -5, -18, 40, -13, 15, -36, 14, 18, 17, -21, 6, -39, 21, 7, -26, 8, -33, 24, 30, 32, -11, -26, -47, -39, 62, 10, 11, 5, -17, -21, 10, 0, 18, 15, -22, 7, 13, 14, -8, -9, 30, 33, -34, -41, -32, 37, 24, -19, -15, 1, 2, 10, 10, -27, -46, -14, -9, 9, 47, 1, -22, -18, 5, 37, 29, -3, -19, -19, -18, 8, 17, 1, -11, -6, -20, 27, 37, -2, -28, -34, -3, 22, 54, 34, -31, -43, -28, -30, -33, 26, 49, 45, 43, -15, -58, -13, -2, -27, -7, 41, 11, 19, -50, -74, -28, 31, 75, 39, -45, -7, 99, 44, -83, -47, 45, -1, -30, 23, 29, -55, -30, 31, 28, -19, 2, -44, -46, -49, 30, 22, 58, 31, -50, -20, 9, -38, -53, 49, 37, -9, 13, -25, -18, 18, -27, -7, 17, 3, 24, 57, 26, -51, -52, -54, -43, 53, 85, 31, -36, -44, 7, 13, 19, -23, -33, 36, 47, -38, -11, 37, -19, -6, 18, 17, 2, 31, 54, -29, -72, -80, -1, 27, 52, 10, -29, -40, -48, -72, 24, 108, 66, -44, -76, -32, -24, 21, 69, 54, 24, -2, -8, -28, -44, -50, 34, 95, 45, -40, -72, -32, 6, 28, -1, 18, -7, 27, 1, -14, 21, -8, -51, -62, -24, 64, 56, 12, 19, -36, -22, 10, 20, -10, -1, -5, -51, 36, 72, -42, -51, 70, 45, -48, -27, 54, 19, -46, 8, 0, -46, 10, 37, 35, -21, -32, -22, -44, -82, -33, 59, 105, 48, -32, -36, -31, 18, 60, -12, -49, 10, 89, 28, 12, 8, -45, -21, -6, -16, -32, -17, -18, 3, 29, -3, 0, -20, -51, -31, 24, 52, 1, -17, -20, 1, 35, 15, 5, 35, 27, 18, -19, 8, -71, -74, -8, 88, 57, -45, -37, 17, 51, -1, -13, -4, 3, -13, -24, -7, 30, -7, -25, -1, 16, -8, -43, -70, 11, 85, 77, 12, -62, -57, 35, 53, -33, -96, 8, 82, 21, -38, 25, 39, -1, -27, -14, 18, -16, -45, -24, 42, 7, -9, 22, 32, -39, -5, -8, -49, -17, 60, 88, 21, -93, -20, 82, 31, -26, -63, -17, 52, -28, -25, 13, -2, -32, -46, 55, 56, -37, 6, -57, -33, 65, 63, 5, -25, -31, 69, 86, -32, -34, -56, -23, -47, 14, 44, -23, 19, 6, 60, -27, -69, -37, 20, -14, -5, 50, 44, 15, 13, -23, -60, -46, 23, 40, -5, -25, 6, 46, -4, -10, -27, -12, 28, 45, 10, -13, -33, -19, -39, 42, 32, -23, -25, 24, -17, 13, 25, 13, -32, 13, 48, 4, -93, -5, 40, -7, 37, -39, -37, 41, 1, -13, -33, 43, -53, 106, 8, -57, -93, 55, 40, 56, -24, -4, -19, 7, -23, -65, -18, 34, -30, 7, 66, 92, 3, -43, -37, -23, 12, -7, -17, 14, -15, -9, -18, 18, 51, -1, -57, -17, 23, 19, 15, -40, -1, 0, -8, 39, -13, -43, 72, 57, -1, -54, -17, 32, -19, 11, 0, 36, 25, -23, -86, 21, -3, 14, -17, 76, 37, 23, 2, -23, -54, -42, -80, 61, 60, 63, -12, -57, -44, 15, 35, 26, 11, -44, -22, 8, 33, -24, -17, 21, 38, -25, -39, 16, 43, -36, -28, 54, 10, -52, -18, -34, -14, 76, 60, 24, -32, -19, 16, -13, -68, -5, 30, -13, -23, -14, 61, 24, 35, 39, 4, -50, -58, -39, 0, 43, 43, 21, 24, -20, -46, -36, 38, 8, -67, -8, 61, 38, 10, -12, 5, -4, -16, -47, -5, -18, -20, 37, 41, 24, 4, 7, -19, 11, -52, 0, 17, 20, -30, -33, -16, 60, 34, -15, -46, -77, 14, 29, 26, 21, 25, 8, 7, 36, 23, -39, -16, 21, 11, -23, 11, -4, -6, -35, 13, -8, -49, -17, 44, 19, -25, -17, 9, -5, -5, -1, -31, 11, 15, 17, -8, -31, -51, 12, 54, 85, 32, 4, -58, -35, -31, 0, 10, 21, -20, -20, -29, 15, 26, -7, 8, 4, 0, 30, 2, -26, 2, 19, 15, -18, -13, -20, -19, 47, 33, -6, -51, -30, -12, 12, 30, 34, 31, 4, -45, -81, -7, -22, 1, 73, 98, 24, -67, -13, 19, -32, -86, 6, 94, 4, -47, 21, -11, -50, 22, -3, -2, 50, 20, -37, -59, 35, 28, -16, -36, -30, -11, 4, 69, 98, -65, -84, 73, 27, -90, -17, 84, 10, -51, -14, 40, -24, -11, 16, -34, -26, 38, -43, -34, 58, 85, -33, -51, 17, 7, 4, 52, 25, -35, 0, 44, -21, -47, 40, 44, -69, -65, 37, 35, -21, 4, 32, -60, -75, 21, 64, 60, -6, -11, 6, 2, -41, -34, 19, 31, 9, 7, -1, 11, 6, -11, -26, -23, 16, 35, -39, -68, 6, 56, -3, -42, 29, 28, 3, 28, 14, -37, -16, 11, -8, -18, 15, -1, -8, 43, -20, -67, -12, 34, 7, -12, -9, 5, -4, 7, -12, 27, -3, -68, 26, 96, 30, -33, -28, -25, 19, 27, -33, -48, -3, 37, -1, -35, -11, 5, 42, 36, 6, -48, -38, 26, 54, -23, -41, 52, 44, -32, -22, 28, -23, -32, 12, 41, -16, -6, -6, -17, -18, -14, -12, -5, 18, 52, 45, -10, -16, 29, 11, -36, -26, 7, 36, 12, -57, -48, 48, 70, 16, 21, -13, -46, -33, -62, -63, -21, 94, 94, 20, -110, -47, 41, 67, -16, -57, -40, 85, 71, 7, -39, 15, -29, -50, -41, 18, -40, -42, 38, 69, 21, -8, -58, -19, 23, 24, -20, -10, 11, 41, 7, -6, -30, -23, 2, 16, 57, 38, -11, -50, 36, -16, -51, -51, 81, 24, -68, -84, 39, 112, 62, -79, -104, 24, 102, 15, -38, 20, 22, -49, -91, 15, 51, 30, -1, -15, -30, -12, 17, 42, -17, -48, 0, 49, 35, 2, -19, -16, -30, 9, 17, -12, -4, -15, 5, 34, -1, -56, -64, 7, 48, 54, -16, -51, 20, 62, -17, -27, -9, -10, -29, -1, 35, 44, -20, -23, -2, -12, -4, 31, 24, -24, -14, 2, -28, -27, 49, 61, -54, -61, 6, 23, -20, 2, 41, 26, 2, 15, -5, 6, -16, -36, -16, 2, -54, -53, -18, 62, 64, 10, -3, 91, 39, -54, -103, -5, 16, -31, -28, 75, 105, -32, -114, -52, 68, 32, -52, -19, 25, 54, 61, 14, -40, 12, 1, -56, -31, 74, 40, -73, -66, 0, 49, 36, 24, -20, 0, 13, -40, -99, -11, 55, 31, -33, 39, 24, 3, -18, 7, 10, 4, -29, 17, 19, 27, -30, -41, 9, 33, -24, -25, 30, 28, -34, -57, 8, -7, -46, 5, 48, -22, -6, 57, 58, -31, -72, -2, 72, 44, -53, -42, 41, 1, -54, 30, 54, -6, -79, -14, 33, -6, -22, 14, 10, -5, -8, 13, 23, 21, -47, -74, 22, 24, -10, -7, 39, 2, 12, -7, -2, 4, 33, -20, -33, 18, 22, -88, -71, 26, 81, 14, -37, 3, -24, 6, -8, 11, 40, 18, -7, -17, 20, -8, -15, -41, -11, 27, 52, -27, -46, 33, 21, 46, -30, -13, 26, -91, -106, -47, 54, 109, 67, -87, -90, 38, 92, 31, -10, -69, -73, -27, -6, 24, -6, 20, 30, 45, 33, -13, -25, 10, 57, -16, -32, 0, -14, -55, -20, 4, 7, -4, 3, 18, -11, 34, 11, -45, -45, -125, -38, -2, 19, 72, 82, 99, 98, 35, -51, -81, -53, 3, -39, 23, -4, -58, -63, -24, 40, 84, 48, -7, -18, -2, -8, -20, -10, 3, 21, 17, -39, -66, -20, -2, 37, 30, 39, 34, -5, -41, -26, 33, 40, 18, -2, 11, 13, -20, -60, -21, 33, -25, -35, 30, 65, 22, 13, -15, 2, 16, 11, -68, -18, 74, 10, -74, -34, -39, -17, 8, 59, 39, -22, -38, -8, 9, 30, 23, 11, -3, -12, 10, -1, 59, 9, -28, -72, -27, 32, 68, -11, -3, 27, 4, -33, -39, 7, -1, -5, -7, 26, -14, -26, -40, -12, 5, 5, 1, -12, 64, 63, -41, -56, 10, 26, 40, -26, -44, -42, 25, -6, 3, -1, 10, 9, -1, 9, 1, -28, 10, 24, 26, -33, -36, 46, 20, -43, -52, -35, 22, 53, 30, -6, 18, -16, -49, -36, 45, 10, 21, 7, 9, -33, -50, 21, 73, 33, -42, -46, 42, -12, -18, 5, -50, -25, 68, 55, -31, -79, -7, 77, 25, -6, 29, 78, 24, -87, -41, -30, -41, -23, 75, 35, -32, -65, -7, -13, 3, 41, 34, -24, -33, 25, 14, -52, -28, 19, 76, 45, -45, -47, -5, 24, 9, -14, -41, -5, 49, 22, 10, -31, -35, -1, -6, 3, 10, -1, -12, -20, -51, 9, 79, 53, -36, -38, -13, -14, -15, 50, 50, -36, -33, 0, 5, 22, 23, 24, -51, -81, -27, 56, 42, -10, -16, 0, 0, -5, 16, 12, -19, 11, 10, -15, -1, -32, -17, 1, 11, 62, -16, -21, 9, 21, -29, -50, 16, 82, 17, -35, -4, 11, 3, 8, 8, -9, -13, 10, -39, -63, -19, 54, 58, -16, -25, 18, 38, -8, -50, -54, -17, 18, 47, 17, -33, -45, 0, 52, 57, -5, -34, -17, 32, 10, -28, -10, -21, -3, -9, -20, 20, 47, 22, 5, -4, -15, -37, -22, -28, 9, 37, -18, -13, 3, 15, -33, -47, 20, 73, 0, -36, 33, 60, -11, -77, -13, 42, 13, -20, 9, 47, 22, -27, 29, 6, -71, -78, -20, 21, 4, 27, 23, 19, 31, 45, -29, -54, -10, 37, -78, -46, -14, 67, 108, 57, 12, -62, -108, -15, 116, 56, -58, -110, -33, 33, 30, -39, -26, 11, 29, 22, 8, 52, 76, 31, 0, -31, -50, -10, 59, 54, -13, -84, -65, -60, 0, 35, 105, 61, -30, -117, -62, 35, 88, 57, 48, -38, -85, 41, 12, -21, -6, 7, 15, 73, -30, -72, -37, 25, 0, -5, 65, 76, -90, -78, 24, 47, 2, -14, 40, 83, 0, -32, -46, -62, -26, 50, 37, -4, -44, -40, 55, 31, -38, -13, -17, -30, -4, 7, 68, 39, 1, -23, -38, -30, 6, -35, 14, 52, -9, -62, -47, 45, 44, 11, -17, -9, 6, 16, 34, -3, -32, -21, -33, -3, 21, 26, -39, 11, 65, 33, 19, -1, -49, -85, -97, 66, 58, -93, -15, 15, 5, 81, 76, 29, -2, -52, -51, -30, 65, 38, -45, -14, 1, 28, 22, 43, 19, -59, -109, -29, 29, -14, -22, -41, 0, 54, 76, 16, 8, 23, 15, -47, -39, -8, 5, 36, -6, -3, -4, 13, 13, 21, -47, -53, -6, -9, -27, -44, 8, 86, 64, 12, -5, -32, -10, -20, -27, -23, 8, 30, 1, 16, 42, -35, -8, 4, -39, -11, -62, -29, 108, 87, -20, -104, -18, -55, 8, 47, -16, 29, 38, 4, -44, -39, -20, 38, -13, 23, 82, 30, -67, -93, 26, 79, 20, -79, -74, -23, 33, 59, 80, 39, -42, -100, 0, 19, 38, 9, -55, 9, -15, 22, 68, -17, -55, -23, 1, 87, 19, -56, -60, 32, 37, 38, -67, -33, -1, 31, 24, 15, -30, -5, -36, -29, -27, 8, 27, -9, 12, 29, 38, 33, 0, -39, -18, 6, 19, 18, 8, 1, -33, 9, -1, 2, -29, -66, 0, 41, 6, -50, -13, 9, 73, -28, -47, -21, 30, 68, 31, 32, 29, -46, -14, 13, -44, -75, -3, 62, 55, 9, -49, -1, 54, 19, -6, 7, 16, 38, 13, -26, -55, -76, -23, 16, 21, -33, -22, 16, 61, 25, -14, -35, 12, 23, -7, -17, -32, -10, -16, -1, 7, 18, -1, 19, -2, -1, 21, -14, 1, -44, -44, -23, -29, -1, 28, -28, 47, 64, 12, -4, -15, -37, -7, 24, 50, 6, -15, -26, -5, 20, 12, -25, -21, -2, -18, -23, 9, 16, 24, 36, -30, -35, -12, 32, 19, -13, 19, -6, 2, -2, -22, -11, 14, 50, 10, -21, -55, -14, 23, 6, 6, -6, -26, -25, -8, 25, 14, 24, 14, -13, 18, 11, 23, -34, -49, -45, 6, 39, 37, 3, 0, -29, 8, 26, -6, -7, -21, 2, -11, 6, 16, -1, -17, 6, 32, -4, -54, -9, 22, -14, 6, 27, -1, -2, 34, 33, 8, 1, -8, -14, -32, 23, -22, -23, -29, -12, 5, 25, 22, -4, 14, 5, 24, -39, -29, 17, -21, -80, -60, -9, 78, 99, 81, -41, -53, 22, 11, -69, -22, -2, 70, 80, 18, -56, -54, -79, -27, 56, 46, 28, -1, 12, -37, -76, 23, 64, -4, -5, 4, 0, -2, -5, 10, -4, -9, 5, 3, 3, -2, 6, -2, -1, 0, 2, 0, 1, -2, 2, -3, -2, 0, 1, -1, 0, 0, -1, -1, -1, 0, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, -1, -1, -1, -1, 0, -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, -1, -2, -3, -5, -6, -5, -5, -3, 0, -1, -3, -1, 7, 16, 20, 8, -8, -24, -35, -39, -36, -35, -42, -47, -35, -14, 0, 8, 17, 28, 45, 60, 65, 64, 66, 67, 60, 50, 39, 26, 14, 5, -14, -40, -54, -56, -56, -55, -47, -36, -20, 1, 13, 15, 16, 12, 2, -10, -20, -33, -43, -42, -38, -43, -40, -28, -17, -7, 6, 21, 34, 48, 60, 63, 64, 66, 61, 54, 51, 41, 23, 10, 1, -18, -37, -46, -54, -63, -60, -46, -30, -13, 5, 15, 16, 17, 11, -2, -11, -21, -34, -44, -45, -43, -42, -33, -21, -17, -10, 5, 23, 39, 54, 62, 61, 62, 63, 59, 53, 47, 38, 23, 10, -5, -23, -36, -42, -51, -61, -61, -48, -26, -2, 14, 16, 13, 13, 9, -1, -14, -27, -36, -42, -44, -48, -44, -31, -17, -10, -8, 1, 21, 47, 65, 67, 58, 54, 58, 61, 54, 41, 31, 23, 11, -9, -30, -41, -44, -45, -54, -61, -52, -21, 11, 25, 19, 8, 4, 7, 2, -15, -33, -39, -39, -44, -51, -48, -34, -12, -2, -4, -2, 19, 54, 74, 72, 58, 47, 51, 59, 54, 40, 26, 20, 7, -16, -37, -46, -44, -42, -51, -58, -47, -15, 19, 31, 25, 9, -1, -1, -4, -15, -30, -37, -41, -51, -55, -48, -28, -11, -4, -2, 6, 28, 58, 73, 74, 63, 50, 45, 46, 49, 42, 31, 19, -6, -30, -43, -44, -42, -51, -54, -49, -33, -3, 18, 30, 31, 17, 2, -13, -15, -15, -25, -31, -45, -62, -60, -45, -24, -16, -10, 6, 20, 40, 58, 68, 74, 69, 55, 41, 37, 44, 43, 34, 15, -17, -41, -48, -46, -51, -59, -51, -34, -16, 3, 17, 29, 33, 23, 2, -15, -18, -18, -22, -31, -50, -64, -61, -42, -30, -24, -8, 13, 35, 50, 57, 65, 70, 70, 58, 42, 40, 41, 40, 32, 6, -23, -45, -53, -55, -64, -60, -45, -24, -1, 10, 19, 27, 28, 23, 4, -9, -17, -22, -23, -36, -53, -61, -60, -47, -36, -22, -3, 19, 44, 56, 60, 65, 65, 65, 60, 52, 45, 39, 37, 23, -2, -26, -49, -63, -66, -63, -55, -42, -16, 3, 14, 25, 25, 22, 19, 11, -2, -17, -20, -29, -44, -50, -58, -64, -53, -32, -13, 0, 25, 45, 53, 65, 68, 61, 60, 63, 60, 47, 42, 33, 7, -10, -26, -56, -73, -68, -57, -53, -37, -12, -1, 14, 32, 26, 16, 17, 16, 1, -12, -19, -38, -52, -47, -55, -65, -50, -23, -9, 4, 27, 40, 48, 68, 72, 59, 58, 67, 64, 52, 42, 21, -5, -16, -31, -60, -73, -62, -54, -49, -34, -17, -4, 17, 32, 24, 13, 18, 20, 6, -11, -29, -46, -48, -46, -54, -59, -41, -17, -5, 6, 20, 35, 54, 71, 68, 55, 60, 74, 71, 53, 27, 5, -6, -16, -35, -62, -70, -57, -49, -45, -40, -25, 4, 25, 29, 15, 7, 23, 27, 10, -20, -46, -47, -41, -39, -47, -55, -34, -11, -1, 4, 11, 38, 67, 72, 62, 48, 61, 83, 76, 49, 9, -9, -7, -15, -31, -59, -70, -55, -48, -46, -43, -21, 16, 29, 22, 6, 1, 25, 32, 10, -28, -57, -47, -34, -30, -38, -49, -33, -12, -4, 3, 17, 50, 72, 68, 55, 44, 61, 86, 77, 41, -2, -16, -10, -13, -28, -56, -69, -58, -52, -47, -35, -7, 22, 25, 13, -4, -2, 25, 33, 7, -35, -58, -46, -29, -22, -32, -44, -34, -16, -5, 8, 30, 59, 72, 65, 46, 39, 62, 87, 76, 33, -8, -20, -13, -10, -28, -57, -70, -62, -51, -42, -24, 3, 23, 23, 4, -15, -4, 25, 34, 3, -38, -55, -45, -23, -17, -32, -43, -34, -15, -1, 14, 41, 64, 73, 59, 35, 35, 64, 89, 73, 26, -11, -23, -14, -11, -33, -60, -69, -59, -48, -39, -14, 11, 25, 17, -11, -24, -3, 30, 35, -3, -40, -54, -41, -18, -19, -36, -41, -28, -10, 0, 21, 51, 70, 71, 47, 24, 36, 72, 93, 65, 17, -14, -22, -13, -17, -43, -62, -63, -52, -48, -36, -5, 19, 26, 5, -26, -27, 5, 40, 31, -12, -42, -50, -34, -20, -28, -37, -33, -17, -8, -1, 29, 61, 75, 64, 31, 19, 44, 85, 93, 51, 9, -15, -18, -16, -30, -50, -57, -52, -48, -52, -32, 3, 25, 20, -10, -34, -21, 19, 42, 20, -17, -40, -43, -35, -30, -32, -32, -21, -12, -12, 3, 37, 67, 72, 50, 25, 24, 57, 92, 81, 42, 6, -12, -18, -25, -39, -53, -52, -44, -49, -51, -28, 6, 25, 13, -17, -32, -11, 29, 39, 8, -24, -38, -37, -33, -36, -39, -30, -10, -3, -9, 3, 38, 68, 71, 46, 23, 32, 68, 92, 71, 31, 5, -7, -16, -31, -50, -55, -45, -37, -49, -53, -27, 8, 23, 8, -20, -24, 3, 34, 28, -6, -28, -32, -30, -35, -46, -43, -23, 0, 0, -10, 5, 41, 67, 65, 42, 30, 47, 77, 83, 52, 23, 10, 2, -16, -43, -60, -55, -38, -36, -53, -53, -25, 8, 19, 3, -14, -8, 17, 29, 9, -17, -24, -22, -26, -43, -53, -42, -14, 4, -3, -9, 10, 44, 63, 58, 43, 43, 63, 77, 64, 38, 24, 20, 7, -23, -52, -62, -49, -38, -45, -57, -49, -19, 6, 11, 2, -1, 12, 22, 13, -7, -18, -15, -17, -32, -50, -52, -32, -11, -4, -8, -3, 21, 44, 55, 53, 52, 63, 70, 64, 49, 35, 34, 24, 0, -29, -53, -54, -50, -51, -56, -57, -37, -17, -2, 7, 9, 20, 21, 12, 1, -13, -11, -13, -24, -36, -49, -40, -30, -22, -12, -9, 10, 25, 38, 51, 57, 70, 71, 62, 57, 44, 42, 34, 15, -4, -30, -42, -53, -65, -61, -61, -49, -35, -22, -2, 10, 25, 27, 15, 11, -1, -8, -14, -22, -27, -37, -37, -37, -40, -26, -14, -2, 10, 24, 42, 54, 68, 73, 65, 65, 60, 49, 36, 27, 15, -7, -25, -43, -63, -69, -65, -61, -54, -36, -13, 3, 18, 26, 23, 20, 16, 1, -16, -21, -20, -31, -37, -38, -40, -38, -25, -15, -7, 11, 34, 48, 56, 66, 71, 72, 73, 61, 43, 34, 29, 11, -14, -31, -46, -63, -69, -72, -69, -53, -28, -7, 3, 16, 27, 30, 28, 15, -3, -14, -19, -25, -39, -42, -37, -38, -35, -30, -19, -2, 18, 39, 47, 56, 69, 75, 78, 71, 60, 49, 35, 22, -1, -20, -32, -50, -65, -76, -75, -63, -49, -27, -9, 6, 22, 28, 31, 27, 16, 6, -13, -26, -36, -43, -41, -42, -42, -36, -27, -10, 2, 18, 38, 52, 64, 70, 73, 79, 76, 70, 50, 27, 11, -5, -21, -41, -62, -69, -72, -68, -61, -50, -26, -4, 13, 21, 23, 32, 35, 27, 6, -21, -33, -37, -42, -48, -53, -45, -31, -19, -8, 3, 23, 45, 59, 65, 65, 73, 88, 88, 69, 40, 19, 10, -6, -30, -54, -69, -69, -68, -67, -59, -43, -18, 2, 10, 15, 22, 39, 46, 27, -3, -28, -34, -37, -48, -56, -60, -48, -29, -16, -1, 14, 35, 52, 58, 60, 64, 80, 96, 88, 64, 34, 16, 6, -11, -36, -62, -77, -75, -68, -58, -47, -33, -14, -1, 7, 15, 28, 43, 44, 24, -6, -30, -38, -40, -49, -63, -68, -56, -30, -5, 15, 27, 40, 51, 59, 63, 72, 84, 91, 83, 60, 32, 12, 1, -14, -45, -73, -84, -78, -62, -46, -36, -28, -17, 0, 11, 20, 31, 38, 35, 20, -6, -28, -40, -46, -58, -72, -71, -52, -26, 4, 26, 37, 45, 54, 64, 69, 74, 81, 80, 73, 59, 35, 13, -5, -28, -54, -75, -79, -74, -63, -43, -30, -21, -11, 0, 14, 23, 29, 33, 23, 14, -2, -25, -41, -58, -69, -71, -64, -43, -24, 3, 33, 47, 56, 60, 64, 73, 74, 75, 73, 62, 56, 38, 13, -12, -42, -57, -69, -77, -71, -63, -44, -25, -15, -3, 2, 13, 26, 23, 24, 19, 8, -2, -24, -44, -64, -74, -64, -60, -45, -16, 9, 34, 53, 63, 68, 66, 75, 73, 63, 66, 62, 49, 34, 11, -17, -43, -54, -66, -82, -72, -52, -43, -28, -10, 0, 4, 18, 27, 16, 13, 20, 8, -11, -26, -47, -66, -63, -59, -63, -47, -7, 20, 34, 56, 69, 65, 73, 81, 67, 54, 61, 63, 44, 25, 6, -23, -37, -44, -69, -85, -69, -48, -39, -26, -7, -4, 5, 27, 25, 9, 10, 15, 5, -17, -34, -52, -62, -54, -54, -60, -40, -5, 21, 41, 59, 67, 66, 78, 81, 64, 53, 58, 56, 39, 18, -3, -24, -34, -45, -64, -76, -67, -51, -37, -21, -8, -3, 11, 22, 20, 11, 9, 11, -4, -23, -38, -56, -57, -53, -50, -42, -31, -5, 21, 41, 63, 67, 72, 77, 69, 67, 58, 56, 49, 28, 16, -8, -28, -35, -50, -53, -62, -65, -53, -44, -20, -2, 2, 14, 10, 14, 17, 7, 5, -13, -27, -37, -60, -58, -55, -42, -22, -18, -2, 13, 36, 69, 73, 76, 71, 62, 70, 60, 53, 42, 23, 16, -13, -35, -45, -51, -40, -46, -58, -60, -52, -17, 4, 8, 11, 5, 14, 15, 4, -4, -20, -23, -37, -62, -67, -59, -27, -2, -3, -3, 3, 36, 70, 77, 75, 66, 67, 70, 57, 46, 32, 29, 19, -17, -49, -62, -46, -25, -33, -54, -68, -51, -15, 4, 8, 6, 11, 18, 8, -7, -19, -16, -12, -35, -68, -83, -56, -9, 13, 7, -7, 4, 40, 66, 73, 69, 73, 80, 69, 46, 27, 31, 42, 24, -23, -68, -69, -36, -14, -25, -57, -66, -43, -16, -3, -2, 11, 28, 23, -2, -31, -29, -4, -1, -34, -83, -89, -45, 3, 22, 6, -3, 16, 41, 56, 55, 68, 93, 93, 65, 23, 12, 38, 53, 27, -38, -80, -64, -29, -12, -31, -54, -49, -34, -22, -24, -11, 28, 47, 25, -24, -51, -27, 5, 5, -43, -90, -79, -34, 6, 11, 4, 17, 31, 39, 34, 38, 79, 114, 105, 50, 3, 12, 44, 56, 16, -49, -72, -54, -28, -29, -44, -37, -27, -28, -41, -45, -5, 46, 61, 17, -44, -53, -20, 7, -6, -53, -78, -62, -27, -7, -6, 14, 41, 45, 26, 11, 38, 93, 127, 101, 34, 1, 20, 48, 42, -1, -41, -53, -45, -40, -51, -44, -18, -9, -34, -61, -47, 7, 57, 58, 2, -46, -43, -14, -5, -27, -52, -58, -46, -31, -26, -12, 28, 59, 45, 10, 6, 50, 104, 124, 87, 30, 11, 30, 40, 19, -9, -26, -35, -44, -58, -62, -38, -4, -6, -46, -67, -37, 21, 56, 43, -4, -37, -30, -15, -25, -40, -44, -38, -38, -43, -38, -9, 40, 64, 37, 5, 14, 65, 106, 107, 75, 36, 26, 34, 24, 4, -8, -10, -24, -53, -70, -64, -30, 0, -16, -53, -61, -22, 28, 43, 29, -2, -21, -20, -26, -39, -43, -34, -26, -43, -54, -40, 0, 46, 56, 30, 12, 30, 75, 97, 90, 69, 47, 38, 29, 13, 2, 0, -1, -27, -61, -71, -55, -25, -14, -32, -50, -41, -6, 22, 25, 17, 4, -8, -19, -31, -38, -35, -28, -35, -53, -54, -29, 7, 31, 32, 23, 28, 51, 72, 78, 72, 65, 55, 42, 30, 19, 15, 11, -8, -36, -58, -58, -42, -35, -35, -43, -40, -18, 0, 12, 14, 11, 9, -4, -15, -25, -31, -28, -36, -49, -53, -45, -18, 1, 12, 19, 23, 43, 58, 64, 68, 64, 64, 57, 46, 40, 28, 22, 9, -17, -35, -48, -47, -44, -47, -45, -44, -31, -12, -2, 7, 10, 9, 7, -2, -8, -19, -28, -32, -44, -51, -48, -37, -21, -9, 5, 16, 26, 43, 55, 60, 64, 63, 61, 58, 55, 48, 34, 21, 6, -13, -27, -39, -49, -53, -50, -46, -41, -32, -16, -3, 5, 11, 9, 6, 5, -4, -17, -32, -40, -42, -44, -42, -40, -32, -12, 5, 17, 24, 35, 50, 58, 64, 64, 60, 65, 61, 50, 34, 18, 10, -2, -18, -38, -58, -56, -49, -45, -41, -38, -22, -4, 8, 14, 8, 11, 10, -5, -20, -38, -41, -36, -37, -40, -48, -37, -12, 4, 14, 19, 27, 46, 59, 66, 63, 62, 70, 64, 50, 34, 22, 17, 8, -11, -38, -59, -57, -50, -49, -47, -43, -28, -6, 10, 16, 10, 14, 8, 1, -5, -5, -4, -5, 5, 2, 2, 1, -1, 0, 1, 0, 2, 0, 0, -2, -1, -1, 2, 1, 1, 0, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, -1, -1, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 1, 0, 0, 0, 1, 0, 1, 0, -3, -10, -11, -8, -13, -25, -21, -10, 0, 2, 18, 41, 44, 42, 66, 62, 28, 10, 17, 17, -16, -10, 25, 28, 29, 34, 47, 34, -7, 7, 25, -12, -43, -44, -40, -61, -85, -78, -55, -42, -33, -10, 17, 31, 43, 59, 51, 25, 25, 40, 27, -1, 2, 25, 30, 15, 12, 27, 26, 13, 16, 9, -24, -43, -37, -49, -83, -92, -62, -40, -42, -36, 1, 33, 34, 45, 61, 46, 27, 32, 33, 10, -6, 15, 38, 26, 4, 15, 35, 19, 7, 17, 3, -26, -41, -50, -67, -91, -82, -48, -40, -46, -24, 18, 33, 32, 54, 62, 46, 30, 22, 20, 7, 4, 28, 33, 15, 10, 22, 25, 9, 13, 18, -2, -29, -54, -65, -74, -86, -68, -49, -46, -32, -8, 17, 29, 45, 65, 60, 43, 23, 13, 17, 12, 18, 28, 22, 19, 16, 13, 14, 16, 24, 13, -13, -40, -66, -72, -75, -74, -64, -55, -36, -20, -9, 15, 43, 63, 65, 51, 37, 17, 9, 19, 23, 21, 19, 24, 21, 3, 4, 24, 31, 18, -2, -20, -49, -77, -74, -65, -71, -69, -47, -27, -27, -10, 38, 66, 59, 52, 51, 34, 4, 11, 36, 26, 12, 22, 26, 2, -11, 25, 45, 18, 0, -1, -23, -72, -83, -55, -65, -83, -61, -34, -37, -36, 23, 71, 55, 43, 60, 55, 11, 1, 40, 37, 8, 16, 31, 6, -22, 14, 55, 27, -3, 8, 2, -52, -83, -57, -56, -89, -79, -43, -43, -55, -4, 66, 61, 35, 56, 68, 31, 4, 32, 46, 13, 7, 31, 16, -24, -4, 50, 42, 2, 7, 16, -25, -67, -60, -54, -86, -95, -55, -44, -63, -32, 40, 62, 40, 47, 67, 48, 22, 32, 42, 18, 4, 25, 25, -15, -16, 29, 44, 21, 11, 15, -5, -39, -49, -59, -85, -96, -72, -52, -62, -50, 7, 45, 49, 50, 56, 56, 43, 42, 39, 19, 9, 16, 21, 1, -16, 9, 32, 31, 24, 14, 5, -14, -34, -52, -81, -94, -85, -71, -62, -55, -21, 21, 41, 53, 55, 55, 57, 51, 44, 26, 13, 15, 11, 3, -3, 0, 19, 27, 29, 26, 11, 0, -16, -41, -70, -90, -88, -85, -80, -57, -34, -3, 26, 42, 57, 57, 60, 64, 50, 33, 20, 17, 9, -6, -1, 6, 10, 23, 26, 28, 22, 10, 1, -27, -60, -78, -87, -90, -94, -74, -42, -20, 10, 34, 44, 57, 65, 71, 58, 35, 30, 23, 8, -5, -7, 4, 7, 19, 33, 23, 19, 24, 17, -13, -53, -65, -75, -96, -98, -83, -61, -40, -7, 32, 38, 38, 66, 83, 65, 36, 36, 37, 8, -7, 1, 0, -5, 11, 39, 34, 10, 21, 36, 4, -45, -59, -59, -89, -106, -84, -67, -62, -32, 21, 41, 30, 47, 85, 80, 41, 34, 45, 20, -8, 0, 9, -7, -6, 31, 45, 21, 12, 32, 25, -27, -55, -52, -76, -104, -95, -70, -64, -57, -7, 33, 34, 38, 67, 84, 57, 35, 46, 29, -1, -4, 7, 7, -8, 12, 41, 31, 21, 24, 25, -5, -43, -45, -65, -98, -98, -82, -62, -58, -35, 13, 27, 38, 59, 70, 67, 45, 49, 39, 2, -3, 2, 9, 9, 6, 30, 30, 24, 31, 20, 3, -26, -37, -48, -91, -100, -88, -75, -53, -41, -9, 12, 23, 55, 65, 61, 54, 51, 51, 14, -6, 1, 1, 15, 18, 26, 29, 16, 30, 28, 4, -14, -29, -36, -71, -100, -93, -87, -64, -38, -16, 2, 6, 33, 61, 59, 56, 54, 55, 32, 1, -3, -4, 5, 25, 36, 36, 17, 14, 25, 14, -4, -19, -30, -53, -84, -94, -95, -82, -49, -16, 4, 2, 10, 37, 56, 61, 58, 54, 42, 19, 3, -9, -8, 14, 41, 53, 32, 10, 7, 10, 10, -7, -25, -43, -65, -81, -97, -99, -72, -29, 9, 11, 3, 10, 33, 61, 65, 55, 46, 30, 19, 0, -17, -5, 29, 62, 57, 24, -1, -6, 10, 8, -16, -35, -54, -64, -80, -105, -99, -57, -2, 26, 13, -2, 6, 42, 67, 60, 49, 36, 31, 22, -10, -24, 1, 49, 77, 53, 9, -14, -4, 10, -4, -26, -47, -56, -58, -89, -115, -93, -34, 23, 33, 6, -6, 16, 50, 62, 53, 39, 34, 40, 16, -24, -26, 15, 71, 82, 38, -5, -13, -1, 3, -13, -39, -53, -48, -61, -103, -119, -80, -6, 42, 27, -1, 2, 26, 51, 56, 43, 33, 43, 42, 4, -34, -23, 37, 87, 70, 20, -6, -10, -3, -5, -27, -49, -48, -44, -72, -115, -118, -56, 22, 43, 17, 3, 12, 33, 51, 45, 34, 38, 51, 38, -11, -42, -9, 59, 86, 53, 13, -5, -5, -3, -19, -42, -50, -43, -45, -85, -127, -105, -28, 34, 37, 15, 8, 23, 41, 42, 34, 33, 45, 55, 26, -27, -38, 12, 69, 77, 40, 9, 1, 0, -13, -33, -48, -49, -39, -55, -102, -124, -83, -8, 37, 31, 14, 19, 35, 39, 34, 30, 35, 51, 50, 9, -31, -25, 27, 72, 65, 30, 12, 9, -2, -23, -42, -52, -46, -43, -71, -109, -112, -63, 7, 36, 25, 20, 33, 42, 35, 29, 29, 40, 52, 35, -2, -28, -12, 40, 69, 51, 26, 18, 13, -8, -33, -48, -50, -46, -57, -84, -107, -98, -43, 14, 29, 24, 30, 44, 43, 30, 26, 34, 44, 40, 19, -8, -20, 4, 46, 59, 42, 29, 25, 10, -18, -40, -46, -47, -57, -73, -91, -100, -78, -30, 13, 25, 30, 44, 48, 39, 29, 31, 41, 35, 23, 9, -9, -5, 16, 43, 52, 40, 37, 25, 0, -23, -41, -43, -54, -74, -82, -93, -86, -60, -26, 12, 26, 41, 53, 44, 40, 33, 36, 38, 19, 12, 2, -3, 9, 18, 40, 48, 42, 41, 16, -6, -23, -41, -45, -68, -84, -86, -90, -71, -52, -22, 15, 32, 52, 54, 45, 45, 36, 36, 25, 6, 6, 0, 5, 15, 21, 41, 46, 46, 37, 10, -7, -24, -42, -57, -81, -88, -88, -83, -62, -43, -14, 16, 41, 59, 55, 48, 48, 40, 27, 10, 2, 2, 0, 8, 22, 30, 36, 45, 50, 32, 5, -9, -23, -48, -75, -86, -86, -88, -81, -54, -26, -11, 16, 52, 65, 55, 50, 53, 39, 9, -2, 4, 2, -4, 11, 36, 34, 27, 47, 51, 26, 0, -9, -23, -63, -91, -85, -81, -89, -79, -38, -13, -11, 23, 62, 67, 55, 52, 56, 29, -8, -7, 7, 0, -5, 19, 44, 30, 28, 49, 46, 21, -2, -10, -32, -79, -96, -83, -81, -87, -67, -27, -11, 0, 36, 65, 67, 58, 54, 48, 14, -15, -7, 3, 1, 6, 26, 35, 30, 38, 46, 37, 18, -2, -18, -48, -85, -96, -89, -81, -70, -52, -30, -8, 20, 48, 63, 66, 59, 50, 33, 6, -14, -15, -2, 13, 20, 21, 25, 36, 45, 42, 31, 12, -10, -31, -56, -84, -103, -96, -70, -50, -43, -31, 0, 35, 58, 68, 65, 51, 37, 26, 8, -19, -25, 2, 27, 27, 17, 20, 36, 45, 45, 29, 0, -27, -41, -55, -87, -111, -93, -57, -37, -33, -23, 5, 41, 70, 77, 59, 36, 26, 24, 4, -24, -22, 7, 31, 33, 19, 14, 29, 49, 50, 22, -16, -39, -48, -63, -92, -104, -86, -51, -25, -19, -16, 10, 53, 82, 74, 47, 26, 19, 16, -1, -18, -16, 7, 35, 37, 18, 10, 31, 55, 41, 4, -25, -45, -57, -73, -90, -95, -82, -42, -9, -8, -11, 20, 71, 84, 57, 39, 27, 13, 2, -6, -9, -12, 8, 45, 41, 8, 5, 42, 56, 20, -10, -24, -50, -73, -83, -83, -87, -76, -25, 10, -5, -9, 39, 84, 71, 44, 38, 26, 2, -9, -2, -4, -11, 17, 52, 36, 0, 11, 50, 43, 3, -19, -31, -57, -84, -84, -77, -82, -59, -9, 14, 1, 7, 55, 81, 61, 38, 29, 20, -2, -10, -1, -4, 0, 26, 42, 30, 8, 20, 41, 28, -4, -31, -46, -64, -84, -82, -79, -66, -37, -7, 15, 18, 30, 58, 68, 57, 33, 17, 9, 0, -3, -7, 0, 15, 23, 31, 29, 23, 24, 22, 14, -12, -43, -63, -72, -73, -83, -75, -47, -26, -2, 20, 37, 48, 50, 57, 52, 30, 6, -1, 11, 0, -9, 7, 16, 24, 28, 32, 33, 15, 7, 2, -21, -55, -79, -66, -67, -81, -63, -38, -12, 9, 29, 53, 48, 42, 51, 47, 22, -6, 5, 18, -4, -7, 6, 22, 28, 26, 39, 28, 2, -2, -8, -35, -73, -76, -56, -67, -77, -55, -20, 4, 16, 40, 54, 42, 41, 51, 37, 7, 0, 17, 13, -12, -9, 20, 31, 25, 29, 33, 15, -5, -8, -22, -57, -74, -62, -57, -74, -71, -33, 0, 11, 26, 44, 45, 41, 47, 45, 22, 3, 12, 19, 0, -15, 4, 30, 32, 27, 26, 17, 3, -4, -14, -44, -69, -66, -56, -63, -74, -52, -11, 12, 21, 29, 35, 41, 49, 51, 31, 9, 11, 19, 11, -8, -7, 20, 36, 34, 22, 10, 6, 5, -4, -33, -64, -66, -58, -58, -67, -63, -29, 4, 20, 21, 21, 35, 52, 57, 39, 12, 10, 18, 16, 3, -7, 8, 31, 39, 25, 5, 3, 10, 5, -22, -58, -67, -58, -56, -60, -64, -45, -11, 15, 19, 12, 24, 50, 62, 46, 17, 9, 18, 20, 12, 0, 2, 21, 37, 31, 7, 0, 11, 14, -12, -51, -66, -58, -53, -54, -59, -54, -29, 3, 16, 9, 17, 44, 62, 51, 22, 8, 17, 24, 21, 9, 1, 11, 30, 31, 14, 3, 11, 16, -4, -43, -65, -58, -49, -50, -53, -55, -43, -16, 5, 10, 16, 38, 59, 54, 26, 7, 18, 29, 24, 18, 8, 5, 16, 27, 23, 11, 14, 18, -1, -36, -63, -56, -43, -48, -47, -49, -52, -36, -12, 8, 17, 35, 55, 50, 28, 9, 17, 33, 25, 24, 20, 5, 4, 15, 27, 23, 20, 22, 0, -32, -58, -55, -40, -47, -44, -39, -52, -54, -34, -2, 19, 35, 53, 46, 27, 12, 18, 34, 26, 26, 33, 13, -6, 0, 22, 34, 32, 28, 3, -31, -53, -51, -39, -47, -45, -30, -45, -66, -56, -19, 15, 38, 52, 43, 22, 13, 22, 35, 26, 26, 41, 25, -7, -13, 10, 35, 46, 39, 10, -29, -50, -46, -37, -47, -46, -27, -35, -65, -72, -42, 2, 38, 55, 43, 19, 11, 24, 36, 27, 26, 43, 37, 2, -19, -6, 25, 53, 56, 20, -24, -46, -43, -36, -46, -48, -29, -28, -56, -77, -64, -22, 31, 61, 45, 16, 10, 23, 35, 30, 26, 41, 42, 16, -14, -21, 7, 51, 70, 36, -15, -38, -40, -35, -42, -49, -35, -29, -44, -71, -81, -49, 14, 60, 50, 18, 10, 21, 34, 34, 26, 37, 43, 30, 0, -27, -13, 37, 74, 54, 2, -29, -35, -32, -37, -49, -42, -32, -36, -57, -85, -73, -12, 46, 57, 27, 9, 17, 32, 38, 28, 30, 41, 39, 18, -20, -27, 15, 62, 68, 26, -17, -30, -28, -29, -45, -51, -40, -34, -45, -77, -86, -42, 18, 54, 43, 14, 12, 29, 42, 34, 25, 33, 41, 30, -2, -24, -5, 36, 65, 50, 3, -24, -24, -19, -33, -54, -52, -42, -45, -61, -75, -58, -15, 32, 48, 25, 10, 24, 45, 45, 27, 26, 32, 28, 13, -4, -6, 14, 44, 55, 24, -11, -18, -12, -20, -46, -57, -53, -54, -57, -63, -57, -33, 4, 35, 32, 16, 22, 40, 49, 36, 26, 28, 23, 17, 8, 1, 10, 27, 43, 33, 5, -6, -8, -14, -33, -53, -57, -61, -62, -61, -59, -38, -10, 15, 26, 20, 26, 40, 44, 41, 30, 27, 25, 18, 12, 3, 9, 26, 33, 28, 13, 5, 5, -8, -25, -45, -57, -60, -64, -66, -65, -49, -17, 6, 13, 16, 26, 43, 47, 39, 32, 27, 27, 25, 13, 3, 6, 22, 35, 26, 13, 10, 12, 5, -17, -40, -54, -58, -58, -68, -74, -61, -31, -1, 9, 10, 23, 40, 50, 45, 31, 24, 27, 31, 20, 3, 2, 17, 32, 31, 16, 12, 15, 12, -4, -31, -51, -55, -54, -62, -76, -73, -47, -17, 2, 8, 19, 37, 51, 50, 34, 24, 26, 31, 25, 9, 4, 13, 26, 34, 25, 9, 13, 20, -2, -33, -44, -43, -58, -78, -77, -59, -44, -33, -10, 17, 6, 12, -9, 32, 13, 4, -4, 6, -9, 27, 8, 2, -1, -3, -2, 3, -4, -3, 2, 0, -2, 1, -2, 1, -4, 2, 1, 0, -2, -1, -3, 2, 0, -1, -2, -2, -2, -1, -2, -2, -1, -2, -2, -2, -2, -1, -2, -1, 0, -1, -2, -2, -2, -1, 0, -2, -2, -2, -2, -1, -1, -2, -1, -2, -2, -2, -3, -1, -1, 0, 0, -1, -3, -2, 1, 3, 0, 0, -2, -8, -21, -17, -2, 12, 20, 19, 6, -13, -28, -73, -67, -64, -58, -39, -11, 19, 38, 60, 96, 80, 38, 12, 6, -20, -65, -83, -65, -61, -56, -17, 22, 35, 49, 74, 94, 55, 16, 20, -5, -52, -89, -81, -53, -65, -36, 21, 37, 48, 51, 85, 82, 25, 23, 9, -36, -80, -105, -58, -57, -54, 7, 36, 54, 44, 58, 97, 48, 26, 16, -21, -61, -115, -83, -45, -57, -12, 23, 57, 54, 36, 86, 77, 37, 21, -16, -40, -103, -110, -54, -46, -24, 6, 43, 68, 36, 62, 86, 60, 30, -12, -34, -80, -119, -76, -44, -24, -5, 24, 64, 51, 50, 76, 72, 48, 0, -34, -68, -106, -94, -56, -26, -7, 11, 45, 59, 58, 66, 71, 60, 23, -27, -68, -93, -93, -72, -37, -8, 10, 25, 50, 70, 68, 62, 62, 45, -10, -70, -88, -83, -79, -57, -15, 15, 13, 31, 73, 80, 59, 53, 61, 15, -67, -89, -73, -75, -75, -33, 21, 11, 10, 66, 92, 65, 42, 63, 42, -56, -92, -66, -66, -84, -57, 16, 19, -5, 50, 98, 76, 39, 56, 60, -35, -95, -64, -53, -84, -79, 0, 28, -8, 29, 96, 89, 42, 46, 69, -10, -90, -69, -41, -74, -95, -25, 28, -1, 13, 81, 101, 53, 37, 69, 11, -77, -75, -38, -53, -103, -55, 22, 8, 6, 61, 104, 75, 29, 59, 31, -61, -76, -43, -36, -91, -88, 6, 17, 1, 46, 96, 94, 34, 40, 48, -40, -80, -47, -27, -69, -107, -27, 26, 4, 29, 87, 105, 51, 24, 46, -10, -76, -58, -21, -49, -107, -62, 17, 16, 17, 70, 110, 67, 22, 38, 10, -60, -71, -24, -28, -97, -85, -6, 25, 18, 50, 106, 84, 28, 31, 16, -38, -71, -38, -17, -78, -94, -30, 15, 30, 41, 86, 92, 44, 31, 15, -25, -54, -53, -26, -57, -88, -51, -2, 33, 45, 68, 88, 59, 35, 17, -15, -42, -55, -41, -48, -73, -60, -19, 24, 50, 61, 74, 67, 46, 21, -8, -32, -48, -54, -53, -57, -57, -34, 9, 50, 63, 59, 65, 58, 29, -1, -24, -38, -62, -67, -48, -47, -40, -8, 43, 68, 48, 58, 66, 38, 6, -19, -26, -62, -85, -45, -35, -39, -21, 28, 72, 41, 47, 74, 45, 15, -14, -17, -53, -102, -50, -24, -36, -26, 10, 69, 42, 32, 81, 52, 21, -4, -15, -39, -109, -64, -12, -35, -26, -1, 54, 47, 21, 79, 65, 20, 7, -12, -33, -100, -82, -8, -27, -32, -2, 36, 47, 21, 66, 77, 25, 12, -2, -36, -88, -87, -18, -16, -36, -8, 27, 36, 30, 56, 77, 39, 12, 6, -33, -84, -79, -30, -11, -29, -20, 19, 27, 31, 58, 66, 50, 21, 5, -25, -81, -75, -32, -17, -17, -27, 2, 24, 28, 61, 61, 48, 35, 4, -22, -71, -77, -31, -19, -12, -23, -18, 16, 29, 59, 65, 45, 41, 10, -23, -59, -76, -37, -14, -11, -18, -29, -2, 29, 57, 68, 51, 37, 16, -21, -55, -67, -44, -12, -5, -21, -29, -19, 19, 59, 68, 61, 36, 14, -12, -55, -61, -44, -16, 3, -21, -29, -25, 0, 55, 72, 69, 43, 8, -6, -49, -63, -39, -18, 5, -15, -31, -26, -18, 39, 78, 75, 53, 8, -8, -40, -67, -37, -15, 2, -8, -30, -26, -29, 16, 79, 84, 59, 14, -11, -33, -66, -42, -9, -2, -6, -23, -26, -33, -7, 66, 94, 67, 22, -9, -32, -62, -48, -8, 0, -9, -16, -20, -35, -24, 46, 96, 78, 31, -2, -29, -59, -51, -13, 1, -10, -13, -9, -31, -35, 23, 86, 88, 42, 5, -22, -57, -53, -18, -3, -10, -13, 0, -19, -44, 2, 69, 90, 57, 12, -13, -50, -57, -21, -9, -13, -13, 1, -3, -41, -17, 51, 82, 69, 23, -9, -37, -57, -25, -12, -22, -15, 0, 10, -25, -32, 32, 69, 71, 37, -4, -25, -48, -30, -12, -32, -23, -3, 14, -2, -33, 11, 56, 63, 49, 3, -18, -32, -31, -13, -37, -38, -9, 11, 17, -16, -6, 41, 53, 51, 11, -17, -15, -23, -14, -35, -54, -22, 4, 26, 10, -10, 26, 43, 46, 19, -19, -6, -5, -10, -30, -65, -42, -9, 24, 35, 3, 12, 32, 37, 24, -20, -8, 14, 2, -23, -68, -62, -26, 10, 50, 28, 11, 22, 27, 24, -19, -19, 24, 21, -8, -63, -78, -45, -11, 47, 53, 23, 21, 19, 22, -17, -34, 21, 40, 15, -48, -89, -65, -34, 30, 68, 44, 27, 16, 16, -11, -47, 3, 49, 39, -22, -89, -82, -55, 3, 68, 61, 44, 21, 11, -6, -53, -21, 45, 56, 11, -74, -96, -72, -26, 52, 73, 60, 39, 10, -3, -48, -44, 27, 61, 42, -43, -101, -88, -52, 27, 73, 70, 59, 21, -1, -40, -60, 2, 52, 60, -4, -90, -100, -74, -2, 62, 72, 76, 42, 5, -30, -66, -22, 34, 63, 33, -62, -104, -92, -31, 44, 68, 84, 66, 21, -21, -64, -41, 13, 54, 55, -26, -94, -104, -57, 20, 56, 82, 84, 43, -6, -57, -54, -10, 36, 60, 7, -70, -107, -78, -6, 40, 73, 92, 66, 12, -45, -57, -27, 16, 52, 29, -41, -96, -90, -32, 20, 60, 91, 83, 34, -27, -52, -37, -3, 34, 36, -15, -77, -91, -52, -1, 43, 83, 93, 53, -5, -42, -40, -17, 14, 32, 1, -54, -81, -65, -21, 23, 71, 96, 67, 16, -25, -37, -24, -5, 21, 6, -36, -64, -69, -37, 3, 54, 93, 73, 35, -6, -28, -25, -19, 8, 4, -27, -46, -65, -46, -14, 34, 86, 73, 49, 15, -17, -19, -28, -4, -3, -28, -32, -56, -48, -24, 15, 74, 67, 55, 36, -2, -10, -28, -14, -9, -36, -25, -42, -50, -29, 1, 60, 59, 50, 55, 16, -3, -22, -20, -14, -46, -29, -28, -48, -33, -5, 47, 50, 40, 64, 40, 4, -14, -17, -19, -53, -40, -18, -40, -41, -6, 39, 39, 28, 61, 62, 17, -10, -7, -21, -59, -53, -20, -28, -47, -11, 38, 29, 15, 52, 77, 36, -6, 1, -12, -63, -66, -25, -20, -46, -19, 37, 28, 0, 38, 83, 54, 5, 5, -2, -57, -81, -34, -15, -44, -22, 29, 31, -4, 16, 85, 68, 17, 15, 1, -44, -87, -54, -8, -42, -27, 25, 24, 2, 0, 69, 88, 24, 25, 11, -42, -76, -75, -14, -25, -40, 23, 18, -3, 3, 42, 96, 45, 22, 29, -39, -70, -75, -40, -8, -39, 7, 24, -17, 8, 33, 79, 76, 22, 35, -21, -75, -64, -60, -15, -17, -14, 21, -21, -4, 40, 59, 88, 45, 24, -3, -71, -61, -59, -38, 1, -14, 0, -17, -18, 41, 54, 82, 74, 22, -3, -53, -61, -53, -54, -2, 3, -19, -25, -22, 30, 57, 73, 92, 38, -15, -40, -51, -50, -58, -17, 17, -23, -44, -22, 19, 55, 72, 97, 60, -22, -40, -35, -45, -55, -32, 14, -17, -60, -26, 11, 46, 75, 97, 78, -17, -46, -23, -38, -45, -37, -1, -14, -66, -31, 3, 34, 80, 98, 85, -4, -47, -19, -33, -33, -30, -20, -25, -63, -34, -4, 18, 79, 104, 84, 9, -38, -18, -29, -27, -14, -30, -46, -63, -32, -5, 3, 68, 111, 84, 18, -23, -12, -25, -28, -2, -25, -67, -75, -29, 1, -6, 46, 112, 91, 22, -11, 0, -18, -33, -1, -9, -76, -96, -34, 9, -8, 22, 101, 102, 27, -2, 14, -7, -36, -9, 4, -68, -114, -48, 13, -3, 5, 80, 109, 40, 4, 26, 6, -33, -18, 6, -52, -120, -67, 7, 4, -1, 55, 103, 58, 14, 31, 17, -21, -24, -4, -39, -110, -84, -10, 6, 2, 34, 87, 71, 29, 36, 25, -7, -23, -16, -33, -96, -90, -29, -1, 6, 22, 68, 75, 45, 45, 31, 4, -15, -24, -37, -84, -87, -43, -15, 3, 18, 53, 68, 57, 58, 38, 11, -7, -22, -45, -81, -79, -48, -29, -10, 17, 45, 57, 61, 71, 50, 17, 0, -15, -49, -85, -74, -45, -40, -25, 10, 42, 49, 55, 82, 65, 22, 7, -9, -43, -89, -80, -34, -47, -40, -1, 35, 52, 43, 85, 84, 25, 17, -4, -38, -85, -92, -28, -44, -55, -9, 21, 53, 42, 75, 100, 35, 22, 6, -38, -74, -99, -38, -34, -65, -18, 12, 42, 51, 63, 102, 52, 25, 21, -36, -70, -90, -56, -30, -64, -30, 7, 27, 55, 63, 90, 69, 33, 26, -26, -69, -79, -66, -43, -54, -37, -1, 17, 49, 69, 79, 72, 50, 30, -15, -61, -75, -68, -58, -52, -33, -12, 9, 42, 69, 78, 64, 60, 42, -9, -49, -71, -69, -68, -61, -25, -17, -1, 38, 64, 77, 59, 62, 58, -3, -37, -62, -72, -72, -73, -24, -12, -11, 35, 55, 73, 59, 58, 69, 8, -29, -48, -75, -76, -82, -31, -4, -14, 28, 49, 63, 61, 54, 73, 22, -21, -36, -71, -82, -88, -42, 0, -9, 21, 43, 53, 57, 56, 73, 33, -12, -25, -62, -89, -95, -49, -2, -2, 18, 37, 43, 49, 60, 75, 38, -2, -16, -49, -89, -105, -54, -7, 1, 19, 31, 37, 38, 59, 81, 39, 4, -7, -35, -83, -115, -62, -10, 0, 20, 27, 32, 30, 53, 87, 43, 4, 0, -24, -70, -118, -75, -12, -2, 19, 24, 27, 27, 45, 89, 52, 4, 1, -14, -55, -113, -87, -18, -3, 13, 20, 24, 28, 41, 85, 60, 7, -3, -9, -40, -100, -91, -28, -4, 7, 10, 21, 30, 43, 82, 62, 13, -8, -11, -26, -85, -87, -36, -10, 2, -4, 14, 35, 47, 81, 62, 18, -9, -21, -20, -65, -78, -38, -19, -4, -16, 0, 39, 54, 85, 65, 20, -7, -31, -24, -47, -62, -33, -26, -15, -25, -19, 35, 63, 90, 73, 22, -3, -39, -39, -35, -43, -20, -26, -30, -34, -36, 24, 71, 94, 85, 29, -3, -40, -58, -34, -24, -4, -16, -46, -47, -47, 6, 73, 100, 97, 42, -4, -39, -73, -45, -8, 12, 0, -51, -64, -56, -13, 66, 104, 106, 64, 2, -40, -82, -63, -3, 27, 18, -43, -82, -68, -28, 51, 104, 112, 86, 19, -42, -86, -81, -10, 40, 34, -26, -90, -86, -41, 31, 98, 116, 104, 46, -38, -92, -95, -25, 46, 48, -6, -84, -105, -55, 13, 84, 117, 114, 76, -20, -95, -105, -45, 41, 54, 8, -65, -112, -70, -1, 65, 109, 115, 100, 14, -85, -106, -62, 21, 50, 13, -44, -104, -84, -14, 45, 98, 112, 111, 53, -62, -105, -75, -3, 44, 12, -31, -85, -93, -27, 27, 82, 110, 110, 81, -27, -95, -81, -27, 31, 11, -31, -66, -90, -39, 12, 61, 106, 107, 94, 12, -73, -79, -48, 11, 13, -32, -57, -78, -46, -1, 38, 97, 109, 96, 43, -41, -69, -62, -13, 13, -30, -58, -68, -46, -11, 17, 81, 112, 97, 59, -7, -51, -67, -37, 6, -23, -62, -67, -42, -14, 2, 60, 110, 99, 65, 20, -24, -63, -56, -7, -15, -63, -75, -40, -12, -8, 39, 102, 103, 67, 35, 6, -48, -68, -25, -11, -56, -85, -46, -7, -10, 22, 86, 107, 72, 41, 29, -25, -70, -42, -14, -42, -91, -62, -5, -6, 9, 67, 105, 84, 40, 40, 3, -64, -56, -23, -30, -83, -85, -12, 3, 1, 50, 97, 96, 44, 36, 28, -45, -69, -33, -22, -67, -101, -34, 13, 2, 31, 88, 104, 56, 28, 37, -16, -71, -51, -18, -49, -103, -62, 9, 14, 18, 70, 109, 68, 26, 36, 6, -58, -68, -23, -28, -97, -84, -7, 23, 19, 50, 106, 84, 28, 31, -21, -26, -18, -30, -24, -77, -76, -48, -46, 31, 0, -1, 0, 0, 2, 0, 1, -2, 1, 0, -6, -7, -5, -3, 0, -3, -4, -2, 2, 0, -8, -11, -14, -10, -8, -4, 6, 13, 14, 9, 2, -6, -10, -9, -6, 9, 17, 15, 8, 0, 1, -4, -12, -19, -14, -8, -4, 3, 6, -2, -4, -6, -7, -10, -8, -12, -11, 3, 23, 27, 11, 4, -3, -5, 0, -9, -3, 6, 11, 19, 4, -8, -17, -20, -21, -3, 5, 8, 2, 3, 5, 2, -3, -3, -12, 4, 1, 3, -7, 0, 5, 6, 0, -7, -8, -5, -7, -5, -3, 4, 9, 5, -5, -5, -5, -17, -7, 3, 17, 15, 7, -2, -5, -3, 3, -8, -5, -3, 3, 8, 12, 5, -10, -27, -20, 1, 5, -4, -9, -17, 4, 10, 9, -2, -12, -16, -12, -2, 8, 16, 13, 11, 16, 19, 10, -2, -16, -21, -11, 14, 15, 21, 11, 6, -10, -8, -11, -24, -35, -31, -13, 9, 24, 17, -2, -11, -20, -11, -19, -7, 3, 8, 22, 21, 21, 2, -7, -10, 12, 24, 18, -3, -19, -6, 0, -5, -18, -17, 6, 12, 7, -16, -20, -22, -27, -19, -14, 12, 14, 3, 0, 2, 8, -3, -5, -3, 21, 29, 17, 6, -8, 3, 3, 10, 10, 3, 12, 4, -9, -18, -20, -20, -9, 6, 3, -9, -7, -14, -9, -8, -9, -23, -19, 7, 17, 20, 9, 8, 5, 9, 18, 9, 8, -10, -10, -4, 9, 25, -6, -19, -19, -5, -4, -7, -7, -17, -15, -7, -4, 0, 2, -2, -17, -4, 14, 23, 15, 2, -7, -5, 9, 11, 1, 0, -3, 0, 0, 15, 14, -4, -15, -20, -26, -22, -13, 0, 6, 12, 5, -10, 2, 8, -2, -18, -8, 6, 20, 28, 23, 0, -16, -7, 9, 7, 10, -12, -21, -19, 7, 12, 4, -17, -28, -24, -3, 14, 4, -19, -18, -9, 11, 22, 16, -13, -23, -15, 18, 32, 32, 17, -4, 1, 14, 11, 1, -20, -19, -3, 9, 13, -4, -13, -16, -18, -23, -12, -17, -16, -20, -15, -14, -4, 8, 12, 0, 8, 5, 12, 17, 26, 25, 14, 10, 11, 11, 18, 15, 4, -9, -13, -8, -9, -14, -20, -28, -32, -12, -9, -16, -17, -24, -18, -12, 5, 10, 4, 6, 8, 18, 35, 31, 17, 1, 12, 21, 33, 18, 6, -10, -11, -4, -9, -13, -19, -24, -24, -24, -18, -20, -18, -20, -13, -15, -10, -9, -5, 8, 10, 13, 23, 26, 29, 14, 13, 13, 13, 16, 25, 19, 17, 4, -15, -18, -15, -14, -17, -34, -23, -16, -12, -16, -26, -33, -23, -15, -4, 4, 10, 16, 19, 22, 29, 28, 7, 1, 2, 18, 26, 30, 21, 9, 3, -4, -10, -16, -29, -31, -27, -4, -9, -11, -28, -23, -17, -15, -13, -11, 4, 11, 9, 13, 16, 25, 18, 8, 10, 18, 17, 8, 18, 17, 11, -5, -19, -17, -12, -19, -38, -27, -8, 0, -3, -14, -19, -20, -14, -10, -13, -3, 6, 12, 26, 38, 34, 14, 2, -2, 11, 19, 14, 8, 5, 16, 9, -7, -19, -24, -29, -36, -26, -13, -12, -22, -28, -20, 5, -3, -10, -19, 7, 20, 18, 17, 24, 25, 14, 18, 19, 29, 21, 11, 10, 9, 13, -13, -29, -27, -20, -24, -30, -22, -12, -7, -15, -22, -21, -13, -14, -20, -8, 12, 26, 25, 21, 33, 27, 25, 16, 13, 16, 16, -2, 2, 11, 9, -2, -17, -18, -16, -25, -25, -26, -27, -30, -35, -30, -12, -6, -6, -6, -5, 19, 19, 11, 15, 17, 24, 23, 34, 28, 23, 13, 2, 9, 18, 16, -14, -18, -12, -7, -9, -31, -37, -33, -24, -14, -24, -20, -16, -21, -15, -7, 5, 9, 15, 20, 28, 38, 29, 21, 15, 22, 17, 4, 12, 6, 12, -4, -9, -15, -16, -19, -40, -38, -34, -23, -18, -17, -8, -10, -3, -7, 1, 3, 4, 11, 13, 36, 41, 36, 24, 9, 17, 20, 21, 14, -5, -9, -11, -8, -19, -14, -24, -30, -23, -18, -25, -30, -24, -17, -20, -9, -3, 6, 8, 22, 23, 20, 27, 18, 10, 10, 14, 18, 14, 23, 17, 6, 5, -4, -8, -26, -19, -24, -25, -24, -21, -27, -28, -15, -19, -16, -9, 0, 7, 9, 17, 14, 15, 24, 30, 29, 29, 32, 16, 10, 8, 0, -3, -10, -7, -17, -22, -25, -30, -36, -32, -25, -26, -22, -12, -16, -11, -3, 5, 7, 13, 21, 21, 26, 32, 28, 26, 28, 31, 17, 15, 15, 5, -4, -14, -18, -28, -25, -24, -28, -32, -33, -32, -29, -18, -17, -20, -10, -4, 6, 6, 18, 22, 22, 37, 38, 31, 27, 26, 23, 22, 23, 12, 4, -5, -2, -11, -19, -25, -35, -35, -36, -36, -43, -32, -24, -20, -12, -7, -3, -7, 3, 13, 23, 29, 35, 37, 35, 42, 33, 26, 22, 17, 12, 6, 4, -9, -23, -28, -34, -34, -33, -31, -40, -36, -27, -25, -22, -30, -20, -11, 2, 12, 22, 22, 26, 28, 35, 47, 44, 27, 29, 29, 29, 19, 2, 1, -9, -15, -21, -34, -35, -34, -40, -44, -42, -34, -31, -26, -21, -9, -12, -3, 10, 17, 29, 26, 27, 34, 48, 50, 34, 33, 25, 21, 16, 8, 3, -8, -11, -25, -30, -37, -37, -42, -51, -34, -28, -21, -26, -25, -19, -13, 4, 9, 17, 29, 41, 33, 33, 44, 45, 32, 31, 28, 22, 16, 5, -10, -13, -16, -23, -38, -39, -39, -45, -54, -40, -32, -24, -22, -17, -14, 0, 6, 9, 18, 41, 43, 34, 32, 40, 40, 31, 30, 27, 22, 19, 14, -2, -16, -21, -34, -48, -45, -41, -41, -41, -45, -38, -25, -21, -17, -20, -7, 11, 17, 19, 36, 40, 42, 44, 47, 46, 39, 33, 26, 15, 11, 8, -5, -19, -24, -29, -40, -44, -48, -44, -37, -37, -43, -43, -26, -19, -14, -2, 13, 23, 31, 36, 36, 43, 41, 47, 46, 44, 40, 24, 15, 14, 3, -12, -21, -23, -30, -36, -47, -51, -50, -47, -44, -46, -31, -19, -16, -11, 2, 16, 20, 25, 29, 40, 53, 51, 49, 45, 41, 35, 25, 18, 7, 5, -12, -18, -23, -34, -39, -56, -58, -54, -49, -50, -45, -35, -26, -12, -5, 6, 17, 29, 41, 42, 47, 50, 46, 49, 50, 50, 39, 30, 16, 2, -8, -15, -21, -30, -41, -49, -50, -46, -57, -63, -57, -41, -29, -24, -12, -3, 5, 12, 22, 33, 41, 50, 51, 53, 57, 55, 46, 36, 29, 16, 2, -4, -11, -21, -33, -40, -49, -47, -53, -60, -58, -51, -42, -34, -23, -13, -2, 5, 17, 27, 39, 49, 48, 51, 56, 54, 58, 44, 37, 28, 18, 4, -3, -15, -29, -39, -49, -49, -51, -62, -65, -64, -47, -42, -36, -26, -14, -5, 10, 24, 32, 45, 50, 49, 62, 65, 63, 47, 42, 41, 36, 23, 7, -7, -22, -31, -41, -53, -58, -62, -59, -62, -56, -54, -50, -44, -32, -16, 0, 11, 25, 35, 50, 54, 55, 56, 66, 65, 62, 54, 45, 36, 23, 14, -4, -22, -44, -55, -52, -62, -61, -66, -70, -68, -60, -54, -45, -29, -15, 4, 21, 34, 36, 44, 54, 62, 70, 73, 68, 67, 59, 50, 37, 21, -5, -12, -25, -39, -48, -53, -63, -76, -73, -71, -71, -67, -57, -45, -29, -12, 2, 13, 30, 42, 51, 61, 76, 71, 63, 66, 71, 60, 50, 40, 23, -2, -9, -20, -41, -54, -59, -72, -79, -71, -64, -73, -68, -60, -51, -36, -13, 2, 13, 27, 47, 54, 71, 78, 71, 60, 72, 74, 65, 54, 39, 28, 7, -6, -23, -50, -59, -64, -69, -75, -70, -78, -74, -73, -64, -52, -37, -13, 6, 18, 40, 51, 58, 64, 78, 79, 75, 68, 64, 68, 57, 45, 21, 4, -16, -34, -50, -65, -75, -83, -80, -71, -69, -68, -73, -63, -57, -36, -16, 6, 26, 45, 60, 70, 71, 79, 79, 81, 78, 80, 64, 55, 36, 16, -4, -23, -38, -54, -63, -69, -81, -85, -87, -76, -72, -66, -61, -52, -30, -12, 12, 24, 44, 55, 69, 78, 85, 84, 74, 70, 71, 71, 62, 41, 17, -11, -25, -42, -55, -66, -75, -87, -87, -81, -74, -76, -76, -63, -48, -32, -13, 7, 30, 51, 64, 76, 80, 82, 83, 81, 80, 82, 70, 61, 42, 19, 0, -28, -49, -61, -72, -78, -87, -90, -89, -88, -87, -82, -69, -54, -33, -13, 15, 36, 58, 68, 79, 90, 96, 90, 84, 86, 89, 79, 62, 38, 22, -3, -29, -55, -69, -81, -89, -94, -94, -94, -94, -89, -74, -62, -52, -35, -18, 14, 39, 54, 65, 76, 87, 98, 95, 94, 90, 82, 75, 69, 47, 26, -6, -33, -57, -72, -82, -88, -97, -90, -91, -88, -83, -80, -75, -59, -33, -9, 20, 42, 58, 68, 82, 90, 94, 93, 94, 88, 85, 77, 65, 43, 16, -10, -37, -60, -71, -84, -89, -95, -97, -102, -95, -84, -80, -72, -57, -26, -4, 19, 42, 62, 80, 89, 94, 97, 100, 99, 90, 83, 71, 65, 39, 14, -9, -43, -65, -83, -90, -95, -98, -96, -100, -96, -88, -76, -66, -51, -24, -12, 21, 45, 70, 85, 93, 95, 97, 101, 105, 92, 84, 69, 58, 35, 16, -14, -44, -68, -86, -88, -96, -101, -101, -102, -97, -90, -74, -69, -50, -19, 9, 35, 56, 76, 84, 92, 98, 96, 99, 97, 93, 84, 77, 59, 24, 2, -30, -52, -76, -87, -93, -98, -100, -102, -100, -96, -89, -81, -73, -46, -18, 12, 36, 62, 82, 88, 96, 104, 107, 105, 102, 92, 84, 77, 53, 26, -6, -35, -57, -75, -81, -92, -103, -114, -111, -108, -98, -88, -83, -67, -35, -7, 20, 39, 60, 70, 89, 106, 116, 107, 103, 99, 86, 90, 82, 53, 18, -13, -31, -52, -73, -92, -102, -106, -104, -97, -106, -99, -101, -92, -72, -42, -5, 16, 38, 66, 86, 101, 99, 101, 95, 112, 107, 99, 95, 81, 53, 16, -3, -29, -60, -81, -102, -98, -102, -102, -112, -114, -101, -104, -88, -69, -34, -8, 14, 41, 67, 92, 94, 99, 103, 104, 115, 109, 103, 90, 78, 52, 22, 0, -39, -65, -92, -95, -91, -103, -104, -118, -110, -102, -93, -84, -71, -36, -15, 19, 52, 81, 94, 89, 98, 103, 115, 117, 102, 92, 83, 80, 49, 23, -11, -43, -67, -90, -93, -102, -105, -110, -118, -104, -100, -89, -83, -64, -36, -7, 28, 50, 74, 88, 95, 104, 103, 115, 107, 106, 97, 87, 74, 50, 20, -17, -47, -75, -89, -93, -101, -102, -115, -117, -106, -97, -88, -90, -73, -38, 2, 36, 60, 75, 84, 96, 104, 115, 115, 102, 98, 96, 96, 84, 52, 10, -12, -32, -53, -71, -87, -101, -109, -112, -109, -106, -105, -102, -92, -74, -48, -19, 7, 33, 56, 76, 91, 101, 108, 111, 111, 108, 103, 96, 85, 63, 33, 1, -27, -51, -73, -90, -102, -109, -112, -110, -107, -103, -100, -93, -76, -50, -19, 10, 36, 58, 76, 91, 101, 108, 111, 111, 108, 103, 96, 85, 63, 33, 1, -27, -51, -73, -90, -102, -109, -112, -110, -107, -103, -100, -93, -76, -50, -19, 10, 36, 58, 76, -1, -2, -15, 21, -17, 23, -30, 1, 34, -34, 6, 5, -15, 19, 1, -25, 6, 20, -2, -28, 15, 10, -15, 0, -7, 10, 7, -5, -9, -6, 19, -3, -21, 3, 20, -4, -20, 1, 16, -3, -8, -2, 5, 1, -8, -6, 3, 9, 2, -13, -4, 15, -7, -9, 0, 3, 6, -7, -7, 5, 8, -8, -4, 0, 1, 1, -6, -4, 7, 2, -2, -7, 0, 4, -3, -4, 0, 2, 0, -2, -4, 1, 4, -2, -4, -3, 1, 3, -5, -4, 4, 3, -6, -5, 4, -1, -2, -3, 0, 3, -3, -1, -4, 3, 3, -5, -3, 1, 1, -2, -3, 1, 2, -2, -4, 0, 0, 0, -1, -3, 1, 1, -3, -2, 1, 0, -2, -2, 0, 0, -2, -1, 0, -1, 1, -2, -2, 1, 0, -2, 0, -1, 0, -1, -1, -1, 0, 0, -1, -3, 1, 1, -2, -2, 0, 1, -1, -2, -1, 0, 0, 0, -2, -1, 1, 0, -3, 0, 2, -1, -2, 0, 0, 0, -2, 0, -1, 0, -1, -1, 1, 0, -1, 0, -1, 1, 0, -13, 5, 7, -11, 24, -50, 41, 4, -29, 14, -11, 8, 11, -15, -12, 15, 18, -21, -14, 22, -2, -11, -3, -3, 18, -3, -5, -14, 9, 22, -24, -16, 23, 12, -23, -8, 9, 10, -4, -8, -3, 11, -4, -14, 0, 8, 8, -5, -14, 8, 10, -12, -4, -2, 10, 0, -11, -3, 11, 0, -7, -2, -1, 7, -6, -8, 3, 6, 0, -3, -8, 7, 2, -7, -2, 2, 1, -2, -4, -1, 3, 3, -4, -5, 1, 3, -3, -6, 2, 5, -1, -7, -1, 3, -1, -4, -3, 5, 0, -3, -2, -1, 4, -1, -5, -1, 3, -1, -4, -1, 3, 1, -4, -2, 1, 0, -2, -3, 0, 2, -1, -4, 1, 1, -1, -2, -2, 1, -1, -3, 0, 0, 0, -1, -2, 0, 0, -2, -1, 0, -1, 0, -2, -1, 0, -1, 0, -1, -2, 2, -1, -2, -1, 0, 1, -2, 0, -1, -1, 0, -1, -2, 0, 1, -1, -3, 0, 1, -1, -3, 0, 1, -2, -1, 0, 0, -1, -1, 0, -1, -1, -1, -1, 0, 0, -1, -1, 0, 0, -2, 0, 0, 0, 0, -2, 1, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, -1, 0, -1, 1, 0, 0, 0, 1, -1, -1, 0, 0, 0, 1, -2, 4, -3, 3, -40, 71, -73, 67, -27, -68, 127, -80, 3, 5, 1, 17, -14, 1, -30, 53, -3, -42, 15, 19, -9, -17, -1, 13, 16, -17, 4, -32, 43, 15, -68, 18, 54, -38, -7, -1, 11, 7, -3, -18, 5, 25, -27, -9, 9, 19, -6, -12, -8, 20, -1, -15, -1, 1, 17, -10, -16, 12, 12, -13, 0, -6, 10, 2, -16, -1, 14, -4, 4, -11, -2, 12, -6, -8, 4, 4, -2, -4, 1, -2, 4, 3, -7, -5, 8, 0, -10, 1, 4, 2, -4, -6, 4, 1, -1, -7, 1, 8, -9, 2, -5, 3, 3, -4, -3, 0, 3, -3, -5, 4, 3, -3, -4, 0, 2, 0, -3, -4, 5, 0, -5, -1, 2, 0, -3, 0, -1, 2, -2, -4, 3, 0, -1, -2, -1, 2, -2, -2, 1, -1, 0, -1, -3, 1, 1, -2, 1, -3, 1, 1, -3, -1, 1, 0, -1, -2, 1, -1, -1, 1, -2, 1, -1, -1, -1, -1, 0, 1, -3, 0, 0, 1, -4, 0, 1, -2, 0, -2, 0, 0, 0, -2, 1, -1, 0, -2, 0, 2, -2, -1, 0, -1, 2, -2, -1, 1, -2, 0, -1, 1, -1, -1, -1, 1, -2, 1, -1, -1, 2, -3, 0, 0, -1, 1, -1, 0, 1, 0, -2, 0, -1, 1, -2, 0, 0, -1, 1, 0, -2, 0, 1, -2, 1, 0, 0, -1, 0, 1, -1, -1, -1, 1, 1, -1, 0, 0, 0, -1, 1, 0, -1, 1, 0, 0, 1, 0, -1, 1, 0, 3, -40, 58, -39, 12, 42, -117, 108, 1, -66, 22, 17, 0, -9, 10, -39, 42, 4, -23, -12, 28, 3, -34, 9, 17, 3, -9, 10, -29, 13, 53, -79, 3, 64, -26, -24, 16, -9, 14, 2, -8, -15, 31, -9, -30, 11, 29, -15, -7, 0, 3, 6, -4, -9, -6, 22, 1, -24, 9, 11, -8, 0, -2, 2, 8, -12, -6, 10, 2, 2, -9, -4, 11, -2, -10, 3, 2, 3, -5, -1, 1, -1, 6, -4, -8, 9, 2, -8, -3, 6, 3, -4, -3, -1, 6, -2, -8, 0, 9, -4, -3, -2, 2, 4, -4, -1, -1, 4, -2, -6, 4, 2, -1, -4, 0, 1, 2, -3, -5, 3, 3, -3, -4, 3, 0, -1, 0, -2, 2, 0, -3, 0, 3, 0, -3, -1, 2, 0, -3, 1, 0, -1, 2, -2, -2, 2, -1, 0, -1, -1, 1, -1, -2, 0, 0, 1, -3, 1, 0, -1, 1, -2, -1, 2, -2, -1, 0, -1, 2, -3, -1, 1, 1, -2, -2, 2, 1, -2, -1, 0, 0, 1, -3, 1, 0, 0, 0, -2, 3, 0, -2, 0, 0, 1, 0, -1, 1, -2, 0, 0, 0, -1, 1, 0, 0, 0, -1, 1, -1, 1, 0, -1, 1, -2, 0, 1, 1, 0, 1, -2, 1, 0, 1, 0, 0, 3, -1, 0, 1, 0, 0, 3, -29, 35, -12, -16, 56, -88, 39, 62, -79, 5, 29, 1, -13, 12, -29, 26, 17, -28, -3, 12, 5, -11, -19, 28, 1, -5, 9, -21, -7, 60, -56, -20, 57, -10, -27, 21, -21, 16, 12, -12, -21, 24, 6, -29, 4, 19, 2, -7, -5, -3, 7, 6, -11, -9, 11, 13, -18, -4, 13, 1, -3, -6, -1, 10, -8, -6, 5, 3, 5, -3, -11, 4, 9, -11, 0, 4, 3, -4, -1, 0, 0, 7, 0, -14, 7, 5, -7, -4, 4, 5, -1, -4, -4, 4, 1, -4, -4, 7, -1, -1, -3, 0, 5, -1, -4, -1, 2, 0, -3, 1, 1, 2, -2, -4, 1, 2, 0, -5, 2, 3, -2, -2, 1, 1, -2, 2, -3, 0, 0, -1, -1, 0, 1, 0, -3, 0, 0, -1, 1, -1, -2, 1, -1, 0, -2, 2, 1, -2, -1, 1, 0, -1, -1, 0, 1, -1, 0, -2, 1, 1, -1, 0, -1, -1, 0, 0, -1, -1, 0, -1, -1, 2, -2, -1, 1, 0, 0, -1, -1, 1, 0, -1, 1, -1, 0, 1, -3, 1, 1, -1, -1, 0, 1, 0, 0, 0, -1, 0, 0, -1, 0, 1, 0, 0, 2, -2, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, -1, -1, -7, -9, 35, -52, 59, -33, -32, 64, -15, -41, 19, 22, -20, 9, -11, -3, 33, -27, 2, 7, -9, 19, -37, 24, 7, -11, 11, -1, -30, 37, 8, -57, 36, 19, -33, 14, 0, -17, 26, 1, -20, -5, 26, -18, -13, 14, 7, -6, 4, -9, -4, 11, 3, -14, -7, 20, 0, -18, 10, 1, 4, -5, -7, 6, 0, -3, -2, -2, 8, 5, -11, -6, 10, -1, -10, 6, -2, -1, 1, -3, 0, 3, 5, -9, -5, 9, -3, -4, 1, 1, 3, -1, -4, -1, 2, -2, -5, 5, -3, 0, 1, -5, 4, 2, -3, -3, 0, 0, -2, 1, 0, -2, 3, -2, -5, 2, 2, -2, -4, 3, 0, -2, 1, -2, -2, 5, -2, -6, 1, 2, -1, -1, 0, 1, -1, -2, -1, -1, 2, 0, -4, 0, 1, 0, -3, 0, 2, 0, -3, 0, 0, 1, -1, -1, 1, 0, -1, -2, 1, 0, 0, -1, 0, -2, 1, 0, -1, 1, -1, 0, -2, 1, 1, -2, -1, 2, -2, 1, -3, 1, 1, -1, 0, 0, -1, 1, 0, -2, 2, -1, -1, 0, 0, 1, 0, 1, 0, -2, 1, 0, 0, -1, 1, 0, 0, 0, 0, -3, -20, 45, -56, 40, -5, -34, 27, 24, -42, -1, 29, -14, -4, 2, -7, 24, -20, -1, 18, -25, 25, -29, 9, 21, -26, 14, 4, -20, 7, 27, -42, 5, 31, -24, -2, 19, -30, 21, 8, -11, -17, 20, 1, -22, 11, 7, -7, 6, -5, -7, 3, 11, -6, -18, 11, 16, -20, 1, 5, 2, -3, -3, 0, -3, 4, -1, -7, 2, 10, -9, -8, 7, 2, -9, 5, -1, -5, 2, 1, -3, -2, 9, -5, -8, 4, 1, -5, 0, 1, 2, -1, 0, -5, 4, -1, -5, 4, -3, 1, 1, -5, 3, 0, 0, -3, 0, -1, -2, 1, 2, -5, 2, 1, -5, -2, 3, -1, -5, 2, 1, -4, 2, -1, -4, 2, 3, -7, -1, 2, 0, -2, 1, 0, -2, -1, 0, -3, 1, 2, -3, -2, 3, 0, -3, -1, 1, 0, -1, -2, -1, 1, 0, 0, -1, 0, 0, -2, 0, 0, 1, -2, 2, -3, 1, 0, 0, -2, 1, 0, -1, 0, 0, -1, -1, 2, -3, 0, 0, -1, 0, 0, -1, 1, 0, -4, -13, 32, -41, 31, -10, -10, 4, 22, -25, -8, 21, -3, -14, 5, 1, 12, -23, 8, 18, -31, 25, -26, 10, 17, -23, 8, 5, -9, 0, 16, -25, 2, 23, -22, -2, 22, -30, 15, 7, -6, -13, 12, 1, -17, 9, 5, -6, 4, -3, -7, 5, 7, -6, -13, 7, 10, -11, 0, 0, 4, -3, -3, 2, -7, 4, 2, -5, 0, 6, -3, -8, 4, 2, -8, 7, 0, -8, -1, 6, 0, -8, 6, 0, -5, 1, 0, -5, 3, 2, -3, -2, 4, -5, -1, -1, -2, 3, -4, 1, -1, -3, 3, -1, -2, -2, 1, -2, -2, 1, 1, -4, 1, 2, -5, -3, 5, -3, -4, 4, -1, -4, 2, -1, -4, 3, 1, -5, -2, 2, 0, -2, 2, -1, -4, 3, -1, -3, 0, 1, -2, -2, 1, -1, -1, -1, 0, 0, -1, -1, -1, 0, -1, 1, -1, -1, 0, -2, 1, 0, -1, -1, 0, -1, -1, -1, 2, -2, -1, 1, -1, -2, 1, -1, -1, 1, -2, 1, -7, -3, 15, -23, 20, -16, 9, -12, 16, -12, -8, 11, 5, -18, 6, 8, 0, -18, 16, 4, -19, 16, -17, 10, 5, -8, -2, 9, -5, -4, 10, -17, 5, 13, -18, 2, 12, -17, 10, 0, -2, -8, 7, -4, -7, 6, 1, -3, 1, 3, -9, -2, 10, -7, -8, 4, 6, -6, 1, 0, 0, -2, 1, -1, -8, 6, 1, -5, 2, 4, -2, -4, 1, 1, -7, 5, -1, -4, -2, 4, 0, -4, 4, -3, -4, 1, 0, -3, 0, 2, -1, -2, 2, -2, -1, -3, 0, 3, -4, 3, -3, 0, 2, 0, -3, -1, 1, -3, -1, 2, 0, -1, 0, 0, -3, 0, 1, -4, -1, 2, 0, -2, 0, 1, -3, 1, 1, -3, -2, 2, -1, -1, 2, -1, -2, 1, 0, -1, -1, -1, -3, -8, -16, -20, -7, 14, 20, 19, 18, 16, 11, 3, -9, -21, -36, -43, -39, -24, 6, 38, 57, 55, 26, 0, -7, -10, -13, -12, -11, -29, -56, -59, -37, 0, 43, 74, 87, 75, 37, -2, -31, -51, -59, -45, -15, -16, -34, -20, -10, -5, 29, 61, 72, 51, 18, -2, -21, -39, -35, -24, 1, 0, -31, -29, -23, -44, -13, 48, 82, 79, 46, 16, -4, -44, -58, -26, 3, 6, -38, -52, -24, -42, -35, 47, 95, 88, 55, 19, 12, -22, -72, -38, 4, 3, -31, -67, -29, -24, -60, 23, 112, 111, 72, 22, 7, -20, -90, -73, -1, 19, -4, -57, -36, 3, -54, -32, 98, 125, 71, 14, 14, 0, -82, -106, 0, 42, 10, -48, -32, -2, -54, -63, 72, 125, 82, 24, 14, -8, -57, -104, -22, 52, 34, -34, -46, -16, -35, -83, 32, 127, 99, 26, 19, 4, -55, -110, -48, 45, 36, -12, -26, -22, -41, -64, -7, 107, 113, 56, 6, 4, -41, -92, -74, 35, 57, 12, -41, -21, -39, -67, -40, 86, 114, 71, 10, 22, -31, -83, -83, 16, 46, 34, -28, -18, -42, -58, -60, 55, 108, 97, 3, 21, -8, -77, -102, 10, 45, 42, -26, -2, -27, -68, -73, 45, 83, 92, 29, 25, -8, -56, -104, -13, 35, 52, -6, -7, -22, -46, -91, 10, 80, 95, 35, 26, 8, -38, -106, -34, 34, 42, 5, 1, -23, -39, -73, -28, 61, 89, 60, 20, 2, -7, -73, -86, 24, 52, 26, -12, -11, -19, -58, -86, 46, 91, 62, 17, 22, -15, -39, -106, 8, 55, 45, -13, -6, -30, -21, -102, 4, 82, 87, 7, 28, -3, -9, -115, -32, 50, 63, -23, 8, -19, -18, -94, -28, 61, 96, 14, 39, -4, 1, -85, -60, 23, 79, -3, 2, -20, -10, -82, -65, 25, 108, 28, 31, 19, 9, -65, -74, -5, 78, 16, -3, -9, -14, -65, -76, -3, 93, 60, 29, 22, 13, -43, -90, -30, 61, 49, -9, -1, 4, -52, -98, -16, 68, 72, 21, 38, 15, -31, -94, -34, 32, 67, 5, 9, 0, -28, -111, -33, 40, 85, 24, 37, 23, -6, -104, -44, 13, 69, 9, 14, 8, -11, -110, -53, 20, 80, 32, 48, 30, 5, -87, -66, -7, 63, 33, 12, 2, 5, -86, -94, -2, 79, 46, 26, 44, 22, -59, -88, -19, 54, 48, 13, 14, 4, -51, -112, -37, 67, 71, 21, 38, 29, -29, -104, -50, 44, 63, 11, 10, 14, -24, -103, -67, 49, 88, 20, 27, 43, -10, -90, -79, 24, 69, 21, 7, 18, -8, -82, -103, 17, 94, 38, 10, 54, 12, -70, -97, 1, 68, 37, -4, 27, -6, -56, -104, -21, 82, 67, -3, 46, 23, -37, -108, -31, 57, 58, -13, 29, 11, -32, -106, -50, 53, 92, -6, 38, 38, -15, -105, -54, 34, 79, -12, 20, 22, -11, -98, -70, 22, 99, 4, 16, 48, 14, -99, -75, 15, 82, 2, 0, 44, 8, -93, -80, 0, 84, 29, -3, 57, 32, -79, -94, 1, 66, 27, -19, 49, 29, -73, -109, -7, 54, 52, -17, 62, 53, -46, -113, -4, 43, 51, -30, 46, 37, -42, -128, -23, 26, 69, -18, 51, 59, -2, -122, -30, 24, 66, -27, 31, 51, 1, -128, -48, 13, 71, -11, 33, 66, 22, -110, -57, 8, 68, -9, 12, 53, 28, -104, -87, -4, 67, 8, 8, 72, 53, -80, -91, -4, 59, 10, -13, 63, 44, -81, -109, -19, 46, 33, -6, 76, 57, -43, -104, -24, 36, 42, -26, 55, 51, -34, -126, -39, 19, 58, -21, 68, 71, -8, -114, -32, 2, 62, -24, 52, 54, -4, -120, -53, -22, 71, -8, 49, 62, 31, -102, -52, -25, 70, -5, 24, 55, 35, -109, -69, -40, 59, 16, 25, 65, 55, -80, -70, -37, 47, 23, 7, 48, 51, -73, -97, -48, 30, 46, 6, 57, 74, -37, -98, -34, 21, 48, -10, 44, 58, -34, -123, -46, -2, 61, 2, 50, 69, 10, -110, -40, -5, 59, -9, 31, 53, 19, -126, -59, -20, 62, 8, 32, 64, 49, -105, -59, -16, 58, 2, 17, 50, 45, -102, -83, -31, 46, 24, 15, 53, 69, -65, -86, -24, 42, 25, -4, 45, 64, -58, -112, -37, 30, 41, -6, 51, 75, -24, -105, -32, 26, 41, -19, 39, 62, -14, -117, -51, 7, 54, -13, 35, 78, 19, -105, -47, 9, 58, -19, 21, 69, 18, -113, -66, -10, 52, -10, 14, 75, 42, -83, -60, -5, 52, 0, -3, 69, 43, -83, -83, -21, 35, 17, -13, 72, 57, -54, -82, -10, 29, 28, -29, 65, 52, -45, -98, -21, 1, 40, -30, 64, 63, -7, -94, -9, 1, 51, -36, 51, 54, -8, -115, -23, -22, 47, -30, 48, 65, 24, -90, -13, -15, 46, -26, 30, 55, 21, -100, -37, -26, 31, -10, 24, 65, 41, -71, -35, -10, 25, -2, 4, 58, 32, -69, -61, -16, 2, 8, 1, 67, 42, -33, -56, -1, -1, 20, -13, 59, 33, -28, -82, -10, -20, 22, -15, 64, 40, -1, -70, 0, -17, 29, -22, 53, 33, 1, -84, -15, -29, 22, -19, 53, 43, 22, -64, -7, -19, 25, -18, 37, 38, 16, -73, -30, -33, 11, -14, 32, 50, 31, -45, -17, -15, 16, -4, 16, 43, 23, -49, -43, -30, -2, -1, 8, 52, 36, -25, -32, -13, -1, 11, -1, 42, 30, -25, -49, -25, -18, 10, -7, 44, 40, -2, -34, -11, -15, 21, -6, 29, 33, -5, -54, -29, -30, 13, -6, 29, 46, 15, -32, -10, -18, 16, -1, 13, 36, 9, -45, -30, -32, 0, 1, 12, 43, 28, -23, -16, -16, 6, 9, 2, 33, 22, -33, -34, -27, -11, 2, 1, 35, 36, -14, -16, -11, -5, 8, 3, 24, 32, -19, -30, -29, -17, -4, 1, 20, 43, -5, -14, -13, -4, 0, 7, 11, 39, -9, -23, -28, -17, -16, 1, 9, 44, 3, -7, -15, -4, -4, 7, 5, 38, 3, -20, -30, -19, -19, -8, 0, 40, 17, -6, -7, -3, -2, -1, 4, 32, 16, -20, -21, -26, -17, -18, -3, 28, 32, -7, -1, -9, 4, -9, 3, 22, 34, -19, -14, -27, -13, -27, -10, 16, 44, -8, 5, -6, 3, -12, 1, 13, 40, -12, -11, -25, -17, -27, -15, 5, 45, 4, 2, 0, 0, -9, -5, 6, 38, 2, -17, -14, -20, -24, -23, 0, 38, 19, -4, 11, -4, -7, -10, 4, 27, 20, -20, -9, -23, -22, -30, -6, 26, 35, -8, 12, 2, -4, -15, 2, 20, 32, -16, -7, -15, -22, -37, -14, 18, 39, -3, 5, 8, -5, -18, -2, 18, 34, -4, -14, -4, -21, -35, -25, 15, 36, 8, -4, 21, -5, -17, -14, 23, 26, 9, -22, 4, -25, -32, -40, 14, 27, 24, -12, 30, 1, -8, -26, 24, 21, 19, -28, 9, -20, -28, -51, 7, 23, 30, -15, 27, 9, -7, -32, 16, 25, 23, -21, 4, -8, -27, -50, -10, 25, 29, -9, 13, 24, -7, -28, -3, 34, 20, -12, -9, 10, -31, -43, -29, 30, 23, 2, -3, 38, -9, -19, -19, 39, 18, -1, -20, 25, -29, -36, -42, 26, 17, 12, -14, 43, -3, -15, -29, 35, 19, 6, -28, 27, -18, -36, -48, 16, 17, 15, -15, 39, 12, -13, -29, 24, 24, 9, -25, 19, -1, -39, -50, 1, 18, 11, -11, 25, 26, -14, -26, 12, 32, 10, -17, 6, 17, -33, -48, -14, 20, 6, -7, 11, 36, -9, -26, -1, 34, 11, -9, -4, 25, -25, -49, -26, 19, 4, -4, 5, 41, 3, -21, -8, 31, 12, -7, -11, 23, -13, -47, -37, 13, 6, -3, 1, 40, 14, -17, -14, 26, 16, -2, -12, 20, -3, -40, -44, 2, 6, -2, -4, 35, 24, -9, -19, 19, 17, 2, -13, 16, 5, -29, -48, -7, 4, 3, -7, 28, 28, 2, -21, 13, 14, 9, -14, 11, 9, -15, -49, -17, -3, 6, -11, 20, 30, 14, -23, 7, 12, 14, -11, 6, 10, -4, -46, -24, -10, 6, -8, 11, 29, 24, -15, 0, 11, 14, -4, -2, 11, 3, -37, -36, -13, -3, -2, 2, 28, 27, -2, -10, 14, 9, 7, -8, 13, 3, -21, -42, -14, -14, 4, -6, 24, 24, 13, -16, 12, 3, 14, -8, 12, 4, -7, -44, -18, -20, 5, -6, 18, 22, 23, -13, 6, 2, 13, -4, 5, 5, 1, -36, -26, -20, -1, -1, 10, 23, 25, -3, -4, 5, 9, 5, -2, 8, 1, -24, -36, -18, -10, 4, 1, 24, 23, 11, -9, 8, 4, 12, -7, 9, 1, -12, -40, -19, -16, 4, -4, 21, 21, 16, -9, 6, 2, 13, -4, 6, 6, -4, -33, -24, -18, -2, -2, 10, 21, 18, 0, -3, 3, 8, 6, -1, 8, 0, -18, -31, -19, -10, 1, 0, 19, 20, 13, -5, 4, 5, 12, -4, 5, 2, -7, -34, -24, -17, 1, -4, 13, 20, 21, -3, 2, 5, 14, 0, 2, 4, 0, -26, -28, -20, -6, -4, 4, 18, 23, 6, -3, 5, 9, 7, -1, 6, 3, -14, -33, -22, -14, -1, -1, 16, 22, 17, -4, 4, 4, 10, -2, 4, 3, -4, -30, -25, -19, -2, -2, 11, 20, 23, 0, 0, 2, 10, 3, 1, 4, 1, -23, -30, -22, -8, -1, 4, 19, 23, 10, -3, 4, 6, 8, -2, 5, 2, -13, -33, -23, -15, 0, -1, 16, 21, 16, -3, 3, 4, 11, 0, 5, 6, -3, -27, -25, -19, -4, -2, 9, 19, 19, 2, -3, 2, 8, 6, -1, 8, 0, 0, 2, 33, 42, 58, 71, 79, 85, 88, 91, 94, 79, 95, 82, 106, 86, 105, 47, 16, -6, 13, 44, 31, -15, -38, -36, 20, 70, 41, 48, 58, 24, -57, -127, -119, -102, -126, -128, -111, -78, -82, -88, -87, -60, -66, -98, -104, -99, -97, -99, -104, -101, -88, -87, -91, -61, -27, -34, -54, -55, -45, -24, -10, -5, -4, 5, 34, 63, 101, 94, 78, 52, 51, 52, 74, 81, 77, 59, 46, 17, 7, 39, 53, 47, 42, 66, 83, 73, 52, 28, 22, 11, 8, 11, 0, -15, -23, -15, -14, -6, 16, 46, 62, 71, 76, 90, 102, 103, 103, 101, 100, 90, 75, 63, 67, 49, 37, 28, 12, 5, 6, 15, 15, 8, -7, -12, -4, -10, -28, -24, -17, -25, -50, -64, -81, -103, -116, -116, -113, -95, -72, -54, -41, -47, -65, -65, -50, -33, -24, -7, 11, 8, -4, -13, -28, -51, -75, -90, -91, -90, -90, -87, -88, -83, -84, -82, -81, -81, -76, -65, -71, -85, -84, -79, -83, -81, -77, -72, -70, -65, -66, -66, -65, -66, -68, -61, -56, -51, -36, -13, -3, -5, -8, -12, -12, 3, 16, 21, 31, 50, 69, 77, 82, 90, 102, 110, 114, 116, 117, 118, 119, 116, 112, 109, 105, 98, 99, 103, 102, 91, 73, 64, 63, 61, 57, 51, 40, 24, 35, 57, 75, 84, 79, 65, 37, 4, -26, -45, -57, -54, -46, -45, -54, -67, -67, -48, -16, 15, 35, 44, 45, 44, 45, 46, 38, 23, 2, -15, -34, -52, -60, -70, -77, -80, -79, -74, -77, -84, -86, -80, -72, -68, -72, -80, -87, -92, -96, -101, -104, -104, -101, -93, -90, -89, -86, -85, -84, -83, -82, -81, -79, -77, -76, -73, -71, -66, -62, -55, -39, -31, -27, -25, -31, -37, -46, -51, -53, -54, -48, -45, -38, -20, 3, 24, 35, 39, 32, 16, 5, 3, 0, -6, -13, -13, -11, -2, 14, 28, 40, 50, 53, 50, 55, 64, 74, 90, 105, 108, 112, 106, 104, 109, 112, 123, 127, 127, 127, 127, 127, 127, 118, 113, 107, 110, 114, 111, 104, 101, 101, 102, 103, 99, 99, 89, 73, 53, 35, 20, 0, -22, -43, -63, -77, -82, -76, -65, -48, -36, -29, -24, -25, -29, -37, -40, -49, -59, -67, -73, -76, -78, -79, -75, -73, -74, -75, -68, -52, -44, -30, -19, -9, -6, -9, -13, -24, -33, -35, -31, -30, -35, -40, -44, -45, -51, -53, -54, -50, -50, -47, -42, -50, -55, -54, -56, -56, -54, -54, -49, -48, -41, -32, -28, -18, -13, -5, 6, 18, 33, 49, 60, 71, 78, 88, 95, 97, 93, 88, 91, 93, 97, 98, 97, 94, 91, 85, 81, 72, 70, 66, 61, 60, 64, 66, 74, 83, 92, 102, 108, 109, 107, 102, 97, 95, 91, 87, 80, 74, 67, 62, 61, 58, 61, 61, 57, 53, 43, 35, 27, 25, 24, 20, 20, 22, 27, 34, 36, 32, 21, 8, -3, -10, -16, -18, -16, -16, -19, -15, -11, -11, -12, -20, -34, -45, -59, -72, -80, -89, -94, -95, -102, -111, -114, -111, -111, -108, -106, -104, -101, -98, -93, -90, -86, -86, -83, -82, -81, -79, -76, -73, -70, -72, -78, -81, -79, -79, -72, -60, -43, -31, -25, -27, -34, -37, -40, -42, -41, -39, -36, -34, -25, -12, -4, 5, 12, 16, 17, 15, 13, 6, -4, -7, -8, -6, -1, 4, 7, 9, 12, 16, 19, 19, 22, 28, 29, 28, 29, 30, 34, 40, 49, 57, 71, 78, 85, 92, 96, 95, 89, 85, 86, 93, 99, 104, 102, 100, 94, 85, 77, 73, 69, 66, 63, 60, 60, 59, 57, 52, 47, 41, 31, 18, 6, -3, -7, -11, -12, -14, -18, -22, -23, -22, -24, -30, -37, -41, -44, -50, -56, -64, -67, -65, -62, -58, -58, -58, -59, -61, -62, -66, -72, -78, -79, -77, -73, -68, -64, -61, -56, -53, -54, -52, -52, -57, -63, -69, -70, -68, -65, -62, -59, -57, -56, -58, -60, -61, -63, -64, -62, -61, -60, -58, -54, -49, -45, -42, -39, -36, -32, -28, -22, -13, -7, -3, 2, 13, 28, 41, 52, 64, 71, 73, 73, 70, 64, 61, 60, 64, 66, 65, 66, 64, 61, 60, 62, 65, 64, 66, 67, 67, 68, 66, 64, 66, 68, 73, 76, 74, 72, 66, 58, 52, 46, 42, 38, 38, 41, 47, 52, 52, 48, 45, 42, 40, 38, 34, 29, 27, 26, 28, 29, 28, 29, 30, 31, 28, 24, 21, 19, 17, 14, 10, 6, 3, -4, -9, -15, -19, -26, -33, -40, -49, -55, -60, -65, -70, -73, -72, -72, -71, -70, -71, -75, -78, -81, -83, -86, -86, -85, -84, -82, -80, -77, -72, -69, -66, -63, -61, -61, -61, -61, -61, -60, -58, -53, -48, -42, -36, -30, -28, -30, -32, -33, -32, -31, -28, -22, -18, -10, -5, 0, 3, 6, 11, 16, 19, 22, 24, 26, 27, 29, 34, 40, 46, 48, 48, 48, 45, 40, 36, 33, 31, 33, 35, 40, 48, 55, 62, 68, 73, 76, 78, 78, 77, 79, 82, 85, 87, 87, 87, 86, 86, 86, 83, 78, 71, 63, 55, 48, 44, 39, 36, 36, 36, 35, 32, 28, 24, 18, 13, 9, 6, 4, 1, -2, -5, -11, -17, -20, -21, -20, -21, -24, -28, -32, -34, -33, -33, -35, -37, -40, -43, -47, -52, -58, -63, -69, -74, -77, -80, -81, -82, -81, -80, -77, -74, -69, -62, -54, -48, -48, -51, -54, -57, -57, -57, -56, -55, -55, -56, -57, -56, -55, -54, -54, -54, -54, -52, -49, -45, -41, -38, -34, -31, -29, -27, -24, -20, -17, -11, -7, -3, 0, 5, 10, 16, 22, 27, 31, 34, 38, 42, 44, 45, 48, 50, 52, 57, 61, 64, 64, 65, 65, 63, 60, 57, 55, 55, 58, 61, 63, 65, 67, 69, 71, 74, 77, 79, 79, 77, 74, 71, 68, 66, 63, 60, 57, 55, 51, 46, 40, 36, 30, 25, 20, 17, 16, 17, 16, 14, 12, 10, 7, 3, -1, -5, -11, -15, -17, -18, -18, -19, -21, -25, -29, -32, -33, -33, -36, -39, -43, -46, -50, -53, -56, -58, -59, -60, -61, -62, -63, -65, -66, -67, -68, -70, -72, -72, -70, -67, -63, -61, -60, -60, -58, -56, -54, -53, -52, -52, -52, -51, -50, -49, -47, -45, -43, -40, -37, -35, -34, -32, -29, -25, -21, -18, -14, -9, -4, 0, 4, 7, 11, 15, 18, 21, 25, 28, 33, 37, 41, 44, 46, 47, 47, 46, 46, 45, 43, 42, 42, 43, 46, 48, 49, 50, 52, 55, 59, 62, 65, 66, 67, 68, 69, 69, 70, 72, 74, 74, 73, 72, 71, 69, 65, 61, 57, 53, 50, 46, 43, 38, 35, 32, 28, 23, 19, 17, 17, 15, 13, 11, 9, 5, 1, -3, -6, -9, -12, -14, -17, -19, -23, -27, -31, -35, -38, -40, -43, -46, -48, -52, -55, -57, -61, -64, -66, -67, -68, -69, -70, -70, -70, -69, -69, -70, -71, -70, -66, -62, -59, -55, -52, -50, -46, -43, -41, -38, -36, -35, -35, -34, -33, -33, -33, -33, -31, -30, -28, -26, -25, -24, -21, -20, -20, -19, -19, -18, -17, -16, -15, -13, -11, -8, -3, 2, 9, 15, 21, 27, 33, 38, 41, 45, 48, 51, 53, 55, 56, 56, 56, 56, 56, 56, 56, 55, 57, 58, 60, 61, 62, 62, 64, 66, 68, 69, 71, 72, 73, 74, 72, 70, 67, 63, 60, 57, 54, 50, 46, 41, 36, 31, 27, 23, 19, 16, 14, 12, 11, 9, 8, 5, 2, -1, -4, -8, -10, -15, -18, -19, -20, -22, -22, -23, -23, -24, -26, -29, -31, -33, -35, -36, -37, -38, -41, -44, -46, -48, -50, -52, -54, -56, -59, -61, -63, -63, -64, -65, -64, -63, -62, -61, -60, -59, -58, -57, -58, -57, -57, -55, -53, -50, -49, -47, -46, -43, -40, -37, -33, -31, -28, -26, -23, -20, -16, -14, -12, -9, -5, -2, 1, 5, 9, 13, 17, 21, 24, 26, 29, 32, 35, 37, 37, 38, 39, 41, 43, 44, 45, 46, 48, 50, 51, 53, 52, 52, 50, 48, 47, 46, 46, 46, 46, 47, 48, 49, 51, 54, 56, 58, 60, 61, 62, 62, 62, 61, 59, 57, 55, 54, 53, 52, 51, 49, 46, 41, 36, 31, 27, 22, 18, 14, 11, 9, 6, 3, 0, -2, -5, -8, -11, -16, -20, -25, -28, -31, -34, -37, -39, -41, -41, -42, -42, -42, -43, -45, -46, -47, -49, -50, -52, -54, -56, -57, -58, -60, -61, -63, -64, -64, -64, -63, -63, -61, -59, -58, -57, -55, -54, -53, -52, -52, -51, -50, -49, -47, -46, -45, -44, -42, -40, -38, -35, -32, -30, -28, -25, -22, -19, -17, -15, -12, -9, -5, -1, 3, 7, 11, 15, 19, 23, 25, 27, 30, 34, 36, 37, 38, 39, 40, 42, 44, 45, 46, 47, 49, 50, 52, 53, 52, 51, 49, 47, 47, 46, 46, 46, 47, 47, 48, 50, 52, 55, 57, 59, 61, 62, 62, 62, 61, 60, 58, 56, 54, 54, 53, 51, 50, 47, 44, 39, 34, 29, 25, 20, 16, 13, 10, 7, 4, 2, -1, -3, -6, -9, -14, -18, -22, -26, -30, -33, -35, -38, -40, -41, -41, -42, -42, -43, -44, -46, -47, -48, -49, -51, -53, -55, -56, -57, -59, -60, -62, -63, -64, -64, -63, -63, -62, -60, -59, -57, -56, -55, -53, -52, -52, -51, -51, -50, -48, -46, -45, -44, -43, -41, -39, -36, -34, -31, -29, -26, -24, -21, -16, -1, -2, -1, -3, 1, -2, -2, -4, 2, 6, 2, -2, -2, 0, 7, 8, 4, -2, -2, 6, 5, 6, 0, -2, 5, 12, 10, 0, -5, -3, 5, 10, 9, -7, -8, -7, 5, 8, 3, -9, -13, -5, 3, 5, -5, -9, -4, 0, 6, 0, -4, -11, -7, 3, 4, 0, -5, 0, -1, 5, 1, 4, -6, -5, -3, 12, 9, -2, -10, 4, 11, 8, -4, -5, -9, -6, 1, 19, 13, -2, -22, 4, 9, 6, -26, -4, 3, 12, -9, 0, 2, 0, -15, 4, 8, -8, -20, 0, 15, 8, -13, -2, -4, -4, -2, 12, 3, -14, -18, 1, 21, 13, -9, -25, -8, 17, 15, 5, -14, -17, 5, 19, 13, -15, -17, -3, 10, 20, 10, -27, -19, 5, 11, 12, 3, -13, -17, -1, 6, -3, -2, 1, -1, -11, -17, 7, 7, -7, -7, -13, 9, 0, -5, 9, -5, -9, 6, 5, -2, -16, -5, 15, 17, -10, -20, 1, 11, 14, -1, 1, 10, -11, -8, -1, 18, 13, -2, -12, 1, -16, -2, 34, 27, -28, -42, -3, 42, 26, -14, -39, -19, 7, 26, 25, -16, -55, -26, 32, 57, 4, -69, -48, 6, 75, 29, -51, -67, -32, 51, 56, 7, -57, -75, 14, 63, 43, -29, -82, -27, 31, 56, 28, -43, -81, -31, 59, 85, 1, -100, -59, 8, 102, 41, -42, -92, -52, 72, 79, 29, -103, -85, -1, 117, 49, -54, -113, 7, 24, 94, -28, -39, -84, 39, 28, 61, -44, -28, -67, 61, 23, 35, -40, -23, -37, 6, 38, 69, -42, -61, -53, 58, 86, 2, -93, -24, 19, 72, 17, -19, -87, 45, 10, 64, -13, -45, -57, 38, 48, 36, -51, -35, -37, 46, 26, 37, -73, -28, -12, 44, 22, 27, -84, -22, 6, 70, 17, -24, -82, -7, 26, 79, 9, -63, -78, 6, 90, 68, -55, -118, -3, 92, 62, -10, -73, -50, 14, 110, 15, -5, -118, 5, 69, 53, 22, -81, -45, 29, 47, 80, -69, -28, -52, 58, 66, -1, -25, -59, -22, 107, 2, 43, -108, -13, 20, 59, 56, -58, -66, -7, 34, 114, -42, -63, -50, 42, 69, 44, -63, -37, -50, 114, 27, 18, -49, -81, 20, 74, 51, -14, -102, -4, 40, 70, 38, -64, -73, 11, 60, 76, -41, -30, -78, 42, 46, 68, -63, -48, -56, 89, 43, 28, -100, -53, 41, 60, 11, -6, -76, -16, 44, 52, 9, -67, -48, 10, 69, 30, -1, -84, -4, 36, 72, -23, -22, -27, -33, 55, 74, -11, -86, -1, 27, 36, 31, -7, -101, 49, 5, 66, -7, -46, -39, 9, 64, 44, -63, -33, -22, 55, 23, 43, -79, -24, 5, 29, 54, -14, -59, -53, 63, 32, 20, -34, -32, -36, 93, -2, 20, -35, -38, 18, 51, 61, -94, 15, -14, 17, 69, 5, -87, 16, 28, 34, 1, 34, -57, -53, 118, -22, 34, -10, -71, 23, 70, 25, -29, -7, -19, -3, 117, -33, -12, -21, -19, 43, 84, -38, -57, 33, 0, 32, 41, -7, -103, 85, 2, 2, 58, -14, -103, 103, 7, -17, 34, -32, -59, 71, 51, -78, 76, -65, -30, 63, 48, -66, 9, -11, -28, 52, 50, -72, -37, 73, -61, 75, 7, -51, -44, 73, -3, -11, 40, -78, 7, 63, -15, -16, 30, -53, 12, 38, 12, -42, 39, -63, 47, 23, 0, -23, -11, 8, -25, 60, -37, -15, -3, -9, 12, 27, -14, -40, 22, 12, 14, 15, -31, -14, 15, 23, -12, 14, -31, 19, 13, 32, -39, 27, -51, 43, 8, 0, 5, -26, 16, 4, 19, -24, 17, -18, 6, -2, 49, -67, 39, -1, -30, 46, -13, -16, -9, 21, -17, 27, 2, -34, 19, -3, 24, 8, -38, 13, -10, 22, 15, -34, 2, 4, -10, 18, 14, -15, -15, 26, -12, 28, -21, 0, -6, 0, 7, 0, -15, 6, -2, -18, 9, 8, -18, -15, 59, -94, 81, -40, -24, 14, -18, 25, -15, 4, -21, -9, 24, -20, 3, 3, -52, 56, -29, 4, 5, -51, 45, -50, 73, -75, 13, 17, -48, 38, -10, -16, 5, 4, -22, 3, 17, -27, -23, 42, -30, -5, 41, -53, 10, 23, -28, 1, 29, -47, 9, 13, -3, -18, 9, -13, -11, 18, 12, -53, 28, 1, -41, 41, 7, -61, 32, 0, -34, 16, 9, -74, 45, -23, -33, 22, 39, -104, 49, 23, -96, 83, 5, -46, 36, -4, -45, 54, -25, -26, 21, 2, -39, 51, -25, -25, 43, -22, -25, 30, -2, -32, 39, 14, -69, 42, 22, -78, 60, 23, -83, 33, 44, -74, 19, 69, -113, 43, 53, -88, 51, 17, -74, 42, 1, -38, 4, 39, -67, 12, 35, -39, -23, 73, -82, -5, 67, -71, -5, 42, -36, -48, 78, -64, -4, 40, -48, -7, 50, -80, 17, 31, -56, 9, 6, -18, -36, 43, -37, -29, 47, -47, -18, 33, -29, -27, 40, -30, -37, 51, -46, -25, 61, -66, 7, 28, -48, 30, -15, -8, -6, 17, -14, -9, 26, -23, 4, 9, -15, 12, -9, 16, -22, 7, 22, -51, 59, -29, -23, 54, -49, 6, 20, -19, -11, 17, -3, -30, 32, -27, -5, 16, -28, 4, 4, -27, 32, -46, 27, -18, -8, 11, -25, 18, -6, -17, 10, 1, -18, 24, -33, 10, 8, -12, -10, 21, -19, 0, 8, -18, 14, 11, -44, 39, -22, -4, -6, 11, -15, -13, 17, -17, -6, 13, -22, -1, 7, -5, -8, 0, 4, -24, 29, -23, 0, 20, -25, -8, 30, -34, 31, -29, 11, -9, 21, -15, -1, 10, -9, -11, 32, -23, -2, -14, 27, -19, 10, -4, -23, 14, 13, -45, 48, -44, 11, -4, -7, -3, 4, -2, -34, -8, 37, -41, 20, -24, -4, -10, 2, 4, 12, -28, -30, 9, 32, -16, 6, -46, -23, 60, 0, -22, -3, -23, -15, 48, 12, -34, -17, -18, 10, 46, -1, -56, -8, 12, 9, 18, 13, -72, -3, 26, 9, 28, -14, -89, 15, 67, -18, 1, -19, -52, 45, 26, -8, -5, -25, -25, 36, 38, -13, -36, -18, -6, 55, 23, -51, -14, 4, 6, 25, 24, -41, -44, 38, 19, 10, 10, -59, -14, 42, 1, 6, -8, -43, -1, 43, 10, -30, -10, -36, 18, 35, -20, -14, -11, -19, 9, 20, -5, -22, -9, -6, 13, 26, -30, -23, 4, 1, 20, 9, -20, -22, 3, -1, 17, 28, -26, -25, 16, -2, -4, 12, -10, -16, 24, -2, -18, 17, -27, -1, 36, -6, -7, -4, -26, 6, 29, -3, -17, -6, -4, 18, 18, -26, -10, -4, 6, 30, -1, -6, -24, 0, 24, 12, 2, -16, -25, 13, 32, -3, -4, -3, -24, 15, 16, -7, 8, -20, -13, 36, 9, -24, -11, -10, 10, 20, -1, -13, -10, -9, 20, 17, -12, -9, -15, 9, 20, -11, -14, -6, 5, 10, 6, 5, -7, -11, 7, 19, 1, 3, -11, -10, 24, 14, -16, 2, -9, 11, 14, 7, -1, -11, -4, 15, 24, 3, -24, -4, 4, 15, 13, -3, -15, 0, 15, 8, 2, 0, -19, 16, 12, -1, 7, -13, -2, 18, 3, -3, 5, -9, -10, 12, 9, -2, 8, -9, 4, 9, 6, 1, -8, 10, 4, -2, 11, -14, 3, 5, 1, 9, 4, -15, 0, 10, 1, 5, -4, -10, 3, 7, -1, 8, -13, 1, 4, 10, 6, -9, -3, 1, 6, 14, -3, -4, 4, -10, 10, 13, -1, -4, 5, -3, 10, 13, -13, 4, 7, 1, 8, -1, 1, 4, 5, 4, 11, -5, -2, 1, 8, 6, 1, 3, -1, -5, 11, 3, -3, 4, -5, -1, 17, -4, -2, 6, -10, 10, 10, -4, 2, 3, -10, 10, 5, -2, -2, -1, 4, 3, -1, -2, -4, 1, 6, -4, 6, -4, -10, 8, 2, -4, 6, -4, -4, 12, -2, 2, 6, -9, 3, 2, 0, 7, -5, -3, 3, 2, 4, -4, -2, 7, 3, 5, 9, -3, 1, 12, -3, 7, 6, -9, 4, 9, -4, 12, 1, -7, 9, 2, 1, 10, -3, 1, 0, 0, 8, 0, -1, 5, -2, 8, 1, -3, 10, 2, 0, 11, -4, -1, 6, -3, 2, 3, -5, 4, 0, -5, 5, -3, 1, 3, 0, 4, -3, -3, 4, -2, -2, 5, -2, -1, 6, -5, 2, 3, -4, 4, -2, -3, 11, -8, 0, 5, -1, 1, 0, -3, 4, 2, 2, 6, -2, 4, 5, -3, 4, 7, -4, 11, -1, 0, 3, 0, 3, 7, -2, 5, 1, 0, 6, 3, 2, 4, -1, 2, 6, 0, 3, 5, -4, 6, 0, 2, 7, -4, -1, 2, -2, 7, 1, -1, 1, -2, 2, 4, -5, 0, 4, -1, 2, -1, -2, 1, -2, 3, 2, -3, 3, -1, -4, 5, -2, -2, 3, 0, -1, 2, -5, 2, 1, -4, 0, 1, -3, 5, -2, 2, 2, -3, 1, 3, -2, 3, 1, -2, 4, 1, 2, 5, -2, 3, 1, 2, 5, 0, -1, 4, 0, 1, 4, 2, 4, 4, -2, 0, 2, 3, 5, 0, 0, 0, 1, 5, -2, -3, 4, 0, 1, 2, -2, -4, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -13, -14, -16, -18, -21, -25, -29, -34, -36, -38, -39, -40, -42, -44, -47, -50, -53, -56, -58, -59, -58, -55, -50, -44, -38, -31, -24, -18, -13, -9, -6, -3, 0, 3, 6, 9, 13, 17, 21, 27, 33, 42, 53, 63, 74, 83, 91, 98, 104, 108, 111, 113, 115, 118, 119, 121, 123, 125, 126, 127, 127, 127, 127, 126, 126, 126, 126, 127, 127, 127, 127, 127, 127, 127, 126, 125, 123, 121, 118, 114, 111, 107, 104, 101, 100, 99, 98, 98, 98, 98, 98, 99, 98, 98, 97, 95, 92, 88, 81, 73, 63, 54, 46, 39, 33, 29, 27, 25, 24, 22, 20, 18, 14, 10, 5, 0, -5, -8, -8, -7, -3, 2, 8, 14, 19, 23, 26, 28, 29, 30, 31, 32, 32, 31, 30, 28, 24, 20, 14, 9, 4, -1, -4, -7, -9, -10, -12, -13, -15, -17, -19, -22, -24, -25, -25, -23, -21, -19, -17, -15, -15, -14, -15, -15, -16, -17, -17, -17, -16, -16, -16, -17, -19, -22, -25, -30, -35, -39, -44, -47, -50, -53, -56, -58, -61, -63, -64, -65, -65, -63, -60, -55, -49, -43, -38, -34, -32, -31, -31, -32, -33, -35, -36, -37, -37, -36, -35, -34, -34, -34, -36, -39, -43, -49, -55, -61, -67, -72, -77, -81, -85, -88, -90, -92, -94, -94, -95, -94, -94, -94, -94, -95, -96, -98, -100, -102, -104, -105, -107, -108, -108, -109, -110, -110, -110, -109, -109, -109, -108, -108, -109, -109, -109, -109, -108, -108, -107, -106, -106, -105, -105, -105, -105, -105, -105, -104, -103, -101, -98, -93, -88, -82, -76, -70, -64, -58, -52, -47, -42, -38, -34, -31, -29, -27, -25, -22, -18, -13, -7, -1, 6, 13, 20, 26, 32, 37, 41, 45, 48, 51, 55, 58, 63, 68, 73, 77, 82, 85, 89, 91, 94, 96, 97, 98, 99, 99, 99, 100, 100, 100, 101, 101, 101, 101, 101, 101, 99, 97, 95, 93, 90, 87, 84, 81, 77, 73, 67, 60, 51, 40, 29, 17, 6, -5, -14, -23, -31, -38, -45, -52, -58, -65, -70, -75, -80, -84, -87, -90, -92, -94, -95, -96, -97, -98, -100, -101, -102, -102, -103, -103, -104, -104, -103, -102, -100, -97, -93, -89, -86, -82, -79, -77, -75, -72, -70, -67, -63, -59, -53, -47, -40, -33, -26, -20, -14, -9, -6, -3, 0, 3, 6, 9, 13, 17, 21, 26, 31, 37, 44, 51, 58, 64, 70, 75, 79, 83, 86, 88, 90, 92, 93, 95, 96, 97, 98, 100, 100, 101, 102, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 102, 102, 102, 101, 100, 98, 96, 94, 92, 90, 89, 88, 88, 87, 87, 87, 87, 87, 86, 85, 84, 82, 79, 76, 72, 67, 61, 55, 49, 43, 39, 35, 32, 30, 29, 27, 25, 24, 21, 18, 15, 12, 8, 5, 3, 3, 4, 6, 9, 12, 15, 18, 21, 23, 25, 27, 28, 30, 31, 31, 31, 30, 28, 25, 22, 18, 14, 10, 7, 5, 3, 1, 0, -2, -4, -6, -9, -11, -14, -16, -17, -17, -16, -14, -12, -11, -9, -9, -9, -10, -11, -12, -13, -14, -15, -15, -16, -16, -17, -19, -22, -26, -30, -34, -38, -42, -45, -48, -50, -52, -53, -54, -55, -56, -56, -55, -53, -50, -46, -42, -38, -35, -32, -31, -30, -31, -31, -33, -34, -35, -36, -36, -36, -35, -35, -35, -36, -38, -41, -45, -49, -54, -59, -64, -68, -73, -76, -80, -83, -86, -88, -89, -90, -91, -91, -91, -92, -92, -93, -95, -96, -98, -100, -101, -102, -103, -104, -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, -104, -104, -103, -102, -102, -101, -100, -100, -100, -99, -99, -99, -98, -96, -94, -91, -86, -82, -76, -71, -65, -59, -53, -48, -42, -37, -32, -28, -25, -22, -19, -16, -13, -8, -3, 3, 9, 16, 22, 28, 35, 40, 45, 49, 53, 56, 60, 63, 67, 71, 76, 80, 85, 88, 92, 94, 97, 99, 100, 102, 103, 103, 104, 104, 104, 104, 105, 105, 105, 105, 105, 104, 103, 101, 99, 97, 94, 91, 87, 84, 80, 76, 71, 65, 57, 48, 39, 28, 18, 8, -2, -11, -19, -27, -34, -41, -47, -54, -60, -65, -70, -75, -79, -82, -85, -87, -89, -91, -92, -94, -95, -96, -97, -98, -99, -100, -100, -100, -100, -100, -98, -96, -94, -90, -87, -84, -81, -78, -76, -73, -71, -68, -65, -61, -57, -52, -46, -40, -33, -27, -21, -15, -11, -7, -4, 0, 3, 7, 11, 15, 20, 24, 29, 35, 41, 48, 54, 61, 67, 72, 77, 81, 85, 88, 90, 92, 94, 95, 97, 98, 99, 101, 102, 103, 104, 104, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 104, 104, 103, 101, 99, 98, 96, 95, 93, 93, 92, 92, 91, 91, 90, 90, 88, 87, 86, 84, 81, 78, 74, 69, 64, 59, 54, 49, 45, 42, 39, 37, 35, 33, 31, 29, 27, 24, 21, 18, 15, 13, 11, 11, 12, 13, 15, 17, 20, 22, 24, 25, 27, 28, 29, 30, 31, 31, 31, 30, 28, 26, 23, 20, 17, 14, 11, 9, 8, 6, 5, 3, 1, -1, -4, -6, -8, -10, -11, -11, -11, -10, -9, -8, -8, -8, -9, -10, -11, -13, -14, -15, -16, -17, -17, -18, -20, -22, -25, -28, -31, -35, -38, -41, -44, -46, -47, -49, -50, -51, -52, -52, -52, -51, -49, -47, -44, -40, -38, -35, -33, -33, -32, -33, -33, -34, -35, -36, -37, -38, -38, -38, -38, -39, -40, -42, -45, -49, -53, -57, -61, -65, -69, -73, -76, -79, -82, -85, -87, -88, -89, -90, -91, -91, -92, -93, -94, -95, -97, -98, -99, -100, -101, -102, -103, -103, -104, -104, -104, -104, -104, -104, -104, -104, -104, -103, -103, -103, -102, -102, -101, -100, -99, -99, -98, -97, -97, -96, -96, -95, -94, -92, -89, -86, -82, -77, -72, -67, -61, -56, -50, -45, -39, -34, -29, -25, -21, -18, -14, -11, -5, 4, 8, 14, 19, 25, 31, 37, 42, 47, 52, 57, 61, 65, 69, 72, 76, 79, 83, 86, 89, 92, 95, 97, 99, 101, 102, 104, 104, 105, 106, 106, 106, 106, 106, 106, 105, 104, 104, 103, 101, 99, 97, 95, 92, 89, 85, 81, 77, 73, 68, 62, 57, 50, 43, 35, 28, 19, 12, 4, -4, -11, -18, -25, -32, -38, -44, -50, -55, -61, -65, -69, -73, -77, -80, -82, -85, -87, -89, -91, -92, -93, -95, -95, -96, -97, -97, -97, -96, -96, -95, -93, -92, -90, -88, -86, -84, -82, -79, -77, -74, -71, -68, -64, -60, -55, -51, -46, -41, -36, -31, -26, -21, -16, -11, -7, -2, 3, 8, 14, 19, 25, 30, 36, 42, 47, 53, 58, 63, 68, 72, 76, 79, 82, 85, 87, 89, 91, 93, 95, 96, 98, 99, 101, 102, 103, 103, 104, 105, 105, 105, 106, 106, 106, 106, 106, 106, 106, 105, 105, 105, 104, 103, 103, 102, 101, 100, 99, 99, 98, 97, 96, 95, 93, 92, 91, 89, 87, 85, 82, 79, 76, 73, 70, 67, 63, 60, 58, 55, 53, 50, 48, 46, 44, 41, 39, 37, 34, 32, 31, 29, 28, 28, 27, 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 29, 29, 28, 27, 26, 25, 23, 22, 20, 19, 17, 16, 15, 13, 12, 10, 8, 6, 4, 2, 1, -1, -2, -4, -5, -6, -7, -9, -10, -12, -13, -15, -17, -19, -21, -22, -24, -26, -27, -29, -31, -32, -34, -36, -38, -40, -42, -43, -45, -46, -47, -47, -48, -48, -49, -49, -48, -48, -47, -46, -45, -44, -44, -43, -43, -43, -44, -44, -45, -46, -47, -48, -49, -50, -51, -52, -53, -55, -57, -59, -61, -64, -67, -70, -72, -75, -78, -80, -82, -84, -86, -88, -90, -91, -92, -94, -95, -96, -97, -98, -98, -99, -100, -101, -101, -101, -102, -102, -102, -102, -102, -102, -102, -102, -102, -102, -101, -101, -100, -100, -99, -98, -97, -96, -95, -94, -93, -92, -91, -89, -88, -87, -85, -83, -81, -78, -75, -71, -67, -63, -58, -54, -49, -44, -39, -33, -28, -23, -18, -13, -8, -3, 2, 7, 13, 18, 23, 29, 35, 40, 45, 51, 55, 60, 64, 68, 71, 75, 78, 82, 85, 88, 91, 93, 96, 98, 100, 101, 103, 104, 105, 105, 106, 106, 106, 106, 105, 105, 104, 104, 103, 101, 100, 98, 95, 93, 90, 86, 83, 79, 75, 70, 65, 60, 54, 47, 40, 33, 25, 18, 10, 2, -5, -12, -19, -26, -32, -38, -44, -50, -55, -60, -65, -69, -73, -76, -79, -82, -84, -87, -89, -90, -92, -93, -94, -95, -96, -96, -96, -96, -96, -95, -94, -93, -91, -90, -88, -86, -84, -81, -79, -76, -74, -70, -67, -63, -59, -54, -49, -44, -39, -34, -29, -24, -19, -14, -10, -5, -2, -1, 3, -2, 1, -3, 4, -2, 0, 0, 8, 0, 10, -9, -7, -128, -72, 13, -44, -13, -18, 4, -4, 12, 3, 31, 4, 66, 74, 38, 38, 36, 30, 25, 22, 18, 13, 7, 5, 2, 1, -5, -7, -9, -9, -11, -14, -12, -14, -12, -16, -13, -16, -13, -14, -16, -11, -14, -10, -13, -11, -13, -8, -8, -6, -6, -5, 0, -6, -3, -3, 3, -4, 6, -13, 17, -5, -5, 15, -1, -23, 6, 23, 28, 35, 13, 41, -3, 24, 25, -4, 6, 30, 4, 18, 10, -32, -64, -120, -64, -91, -76, -33, -45, -58, 2, 1, -19, -14, 18, 48, 50, 59, 51, 53, 47, 46, 41, 37, 35, 26, 28, 19, 21, 10, 13, 9, 3, 5, -4, 2, -5, -3, -8, -5, -8, -8, -10, -9, -10, -10, -12, -7, -17, -8, -11, -14, -5, -15, -5, -4, -10, -13, 11, -22, 3, -3, -4, -5, -11, 13, 2, -16, -9, -5, -12, 27, 15, 17, 21, 20, 20, 8, 14, 13, 0, 10, 35, 10, -1, -12, -52, -89, -78, -58, -85, -74, -51, -25, -25, -28, -30, -14, 12, 29, 44, 44, 51, 46, 50, 49, 43, 38, 36, 32, 29, 23, 19, 17, 14, 10, 6, 6, 2, 4, -8, 3, -7, -3, -6, -7, -11, -4, -12, -7, -6, -20, 1, -15, -14, -8, -7, -10, -10, -10, 2, -14, -12, 7, -10, -8, -5, -6, 1, 6, -2, -12, -19, -3, 3, 2, 19, 19, 14, 19, 24, 13, 5, 12, 12, 13, 21, 29, 5, -18, -43, -48, -64, -82, -82, -71, -44, -37, -37, -40, -33, -23, 5, 20, 33, 38, 45, 48, 51, 46, 44, 41, 38, 36, 27, 26, 24, 19, 13, 16, 5, 11, 4, -1, 3, -4, -3, 1, -9, -7, -2, -9, -6, -13, -4, -6, -17, -8, -6, -15, -10, -5, -10, -8, -10, -5, -7, -5, -2, -14, -10, 3, 5, -4, -3, -10, -17, -10, 3, 4, 5, 18, 18, 18, 16, 16, 10, 5, 11, 23, 26, 22, 7, -9, -16, -37, -62, -80, -76, -65, -46, -43, -43, -51, -41, -24, -4, 11, 24, 32, 41, 47, 43, 49, 45, 41, 40, 33, 31, 31, 20, 23, 18, 11, 16, 9, 5, 3, 2, 5, -2, -7, 2, -4, -10, -3, -5, -8, -10, -7, -8, -14, -10, -8, -11, -9, -6, -14, -10, -2, -3, -12, -10, -7, -9, 0, 6, -1, -11, -12, -11, -10, -7, 4, 7, 12, 17, 20, 18, 13, 6, 8, 19, 22, 24, 17, 14, 5, -8, -29, -54, -77, -71, -55, -50, -44, -54, -57, -39, -32, -15, 3, 15, 31, 34, 39, 47, 45, 44, 44, 37, 37, 33, 28, 27, 18, 20, 21, 10, 7, 10, 7, 1, 2, 2, 0, -5, 0, -2, -7, -3, -5, -8, -8, -5, -13, -13, -5, -6, -14, -11, -8, -8, -5, -5, -9, -17, -10, -2, 0, -2, -1, -9, -12, -14, -12, -6, -1, 3, 11, 19, 19, 14, 7, 9, 13, 17, 23, 22, 19, 21, 12, 2, -21, -55, -65, -59, -52, -47, -56, -56, -50, -53, -38, -22, -7, 10, 18, 29, 36, 40, 45, 43, 38, 41, 40, 32, 27, 26, 26, 19, 17, 17, 12, 9, 9, 6, 2, 4, 4, -1, -2, 2, -3, -3, 0, -2, -8, -9, -7, -7, -7, -6, -8, -12, -6, -4, -7, -12, -13, -10, -5, -2, -2, -3, -8, -12, -15, -16, -14, -13, -7, 2, 8, 11, 8, 4, 5, 8, 13, 20, 22, 23, 24, 23, 19, 6, -13, -23, -29, -32, -37, -42, -46, -53, -57, -53, -49, -39, -25, -12, -1, 10, 21, 28, 32, 35, 36, 34, 34, 32, 28, 25, 24, 21, 18, 19, 16, 10, 7, 8, 9, 8, 6, 5, 2, 3, 6, 7, 5, 2, -2, -4, -3, -1, -3, -4, -3, -1, -3, -8, -13, -14, -11, -4, -1, -2, -4, -6, -11, -16, -19, -21, -21, -17, -9, -3, 0, 0, -3, -5, -2, 4, 11, 18, 23, 25, 26, 24, 17, 10, 5, -1, -7, -12, -20, -29, -37, -44, -51, -55, -54, -47, -39, -28, -16, -4, 9, 18, 23, 27, 31, 31, 30, 30, 28, 23, 20, 22, 23, 20, 14, 10, 9, 9, 10, 9, 6, 4, 4, 6, 9, 10, 7, 2, 0, 1, -1, -2, -2, -1, 1, 2, -2, -10, -14, -11, -8, -5, -2, -1, -3, -6, -9, -14, -20, -23, -23, -18, -11, -5, -3, -4, -6, -8, -4, 2, 7, 14, 21, 25, 25, 23, 19, 13, 8, 4, -1, -9, -15, -23, -31, -39, -48, -53, -51, -48, -44, -34, -20, -8, 3, 12, 20, 24, 27, 30, 31, 29, 24, 22, 22, 23, 22, 18, 13, 10, 10, 11, 11, 9, 5, 3, 5, 10, 11, 9, 7, 5, 4, 2, 0, -3, -1, 3, 5, 2, -3, -8, -11, -10, -7, -5, -3, -2, -2, -4, -7, -14, -20, -24, -24, -19, -12, -6, -6, -8, -8, -8, -7, -2, 5, 12, 19, 23, 24, 22, 20, 16, 12, 7, 1, -5, -10, -17, -27, -36, -42, -47, -52, -51, -45, -36, -26, -12, 0, 9, 15, 21, 27, 30, 29, 26, 23, 22, 23, 23, 21, 17, 12, 9, 10, 12, 10, 6, 3, 4, 7, 10, 11, 9, 8, 9, 7, 2, -1, 0, 2, 6, 6, 3, -2, -7, -9, -8, -6, -4, -3, -1, -1, -2, -6, -13, -21, -26, -24, -18, -13, -10, -9, -10, -11, -11, -10, -5, 3, 10, 17, 21, 22, 22, 21, 19, 14, 8, 5, 1, -7, -14, -21, -29, -38, -45, -49, -50, -48, -40, -28, -16, -6, 3, 11, 19, 26, 27, 26, 24, 22, 22, 24, 24, 20, 14, 11, 11, 12, 11, 8, 4, 3, 6, 8, 9, 9, 10, 11, 10, 6, 2, 0, 2, 5, 8, 7, 3, -2, -5, -6, -7, -6, -4, -3, -1, 1, 1, -5, -13, -21, -24, -23, -18, -14, -12, -11, -12, -13, -14, -13, -8, 0, 8, 14, 17, 21, 22, 21, 18, 15, 12, 8, 2, -3, -9, -16, -24, -32, -40, -47, -51, -49, -41, -30, -21, -12, -1, 9, 17, 23, 25, 24, 21, 21, 24, 24, 22, 17, 12, 11, 13, 12, 8, 4, 3, 4, 6, 7, 7, 9, 11, 12, 10, 6, 3, 3, 6, 9, 10, 8, 5, 1, -2, -3, -3, -2, -1, 1, 3, 3, 1, -5, -12, -18, -20, -20, -18, -16, -16, -16, -17, -19, -20, -17, -11, -5, 1, 8, 13, 17, 18, 18, 17, 16, 14, 11, 7, 2, -3, -8, -14, -22, -34, -43, -46, -42, -35, -28, -20, -11, -2, 7, 15, 19, 19, 19, 19, 20, 20, 17, 14, 11, 10, 9, 7, 1, -4, -6, -4, 0, 2, 4, 6, 7, 8, 9, 8, 7, 7, 10, 13, 15, 15, 13, 9, 6, 3, 2, 4, 7, 9, 11, 11, 7, 1, -5, -10, -13, -14, -14, -14, -16, -19, -23, -26, -28, -27, -23, -18, -13, -7, -1, 6, 11, 14, 15, 14, 14, 15, 15, 12, 7, 2, -1, -4, -11, -22, -34, -41, -40, -34, -26, -19, -12, -4, 4, 10, 14, 17, 17, 18, 19, 18, 15, 12, 10, 9, 8, 6, 0, -6, -11, -10, -6, -1, 3, 5, 6, 6, 6, 7, 7, 8, 10, 13, 16, 18, 17, 13, 9, 5, 3, 4, 7, 11, 13, 14, 11, 5, -2, -7, -11, -12, -12, -13, -14, -17, -22, -26, -28, -29, -27, -22, -17, -11, -5, 1, 7, 12, 14, 14, 13, 14, 15, 14, 11, 5, 0, -2, -6, -15, -27, -37, -42, -38, -31, -24, -17, -9, -1, 6, 12, 15, 17, 18, 19, 19, 17, 13, 11, 9, 9, 8, 4, -2, -8, -11, -9, -4, 1, 4, 5, 6, 6, 6, 7, 7, 9, 11, 14, 17, 18, 16, 12, 8, 4, 3, 5, 9, 12, 14, 13, 9, 2, -4, -9, -12, -13, -12, -13, -15, -19, -23, -27, -29, -28, -25, -20, -15, -9, -3, 3, 9, 13, 15, 14, 13, 15, 15, 13, 9, 3, -1, -3, -9, -19, -31, -40, -41, -36, -28, -21, -14, -6, 2, 9, 13, 16, 17, 18, 19, 18, 16, 12, 10, 9, 9, 7, 2, -4, -10, -11, -8, -2, 2, 5, 5, 6, 6, 7, 7, 8, 9, 12, 16, 18, 17, 14, 10, 6, 4, 4, 6, 10, 13, 14, 12, 7, 0, -6, -10, -12, -13, -13, -14, -16, -21, -25, -28, -29, -28, -24, -18, -13, -7, -1, 6, 11, 14, 15, 13, 14, 15, 15, 12, 7, 2, -1, -5, -12, -23, -35, -41, -40, -34, -26, -19, -12, -3, 4, 10, 14, 17, 18, 18, 19, 18, 14, 11, 9, 9, 8, 6, 0, -7, -11, -10, -6, 0, 2, -1, -2, -9, -24, 4, -3, 3, -3, 10, 7, 4, 13, -4, 1, 3, 3, 0, 2, 8, -9, -9, 2, 1, -1, 7, 17, 21, 37, 25, 13, 14, -2, 15, 20, 5, 0, -3, -7, -27, -14, -18, -19, -29, -20, -4, -18, -32, -30, -30, -29, -32, -22, -26, -19, -19, -1, -6, 4, 7, 5, 2, 0, -8, -16, -12, -13, -17, -17, 19, 20, 24, 16, 8, -4, 8, 0, 13, 28, 33, 16, 11, 5, -3, -1, 4, 12, 12, 40, 20, 11, 4, 5, 8, -1, 2, 5, 5, 22, 13, 21, 8, 9, 18, 20, 13, 20, 26, 11, 24, 17, 10, 27, 30, 22, 28, 30, 41, 47, 57, 36, 36, 20, -16, 4, 6, -19, -21, -41, -39, -33, -38, -41, -46, -42, -36, -18, -37, -65, -75, -77, -78, -62, -63, -62, -68, -63, -63, -44, -50, -30, -41, -43, -26, -34, -35, -36, -45, -49, -27, 1, -6, -4, -7, -20, -16, -20, -21, -13, 2, -6, -1, -12, 0, -1, 15, 19, 20, 26, 37, 40, 46, 37, 50, 35, 34, 41, 43, 51, 54, 55, 50, 56, 47, 59, 51, 51, 75, 67, 66, 71, 59, 60, 72, 75, 72, 80, 79, 82, 98, 99, 87, 93, 62, 49, 58, 41, 42, 28, 5, -6, -6, -18, -24, -23, -30, -25, -20, -38, -60, -75, -77, -80, -75, -71, -75, -70, -73, -69, -76, -60, -66, -71, -66, -57, -62, -61, -61, -87, -90, -69, -63, -46, -31, -35, -47, -42, -53, -63, -53, -45, -33, -36, -39, -37, -43, -39, -34, -30, -19, -9, 2, -9, -1, -3, 1, -3, 5, 7, 15, 24, 22, 23, 20, 32, 43, 33, 48, 63, 67, 70, 68, 52, 59, 73, 73, 77, 85, 73, 81, 103, 98, 116, 115, 87, 80, 76, 72, 69, 60, 37, 27, 29, 12, 19, 4, -12, 1, 3, -3, -31, -42, -57, -67, -67, -61, -61, -61, -48, -58, -51, -41, -46, -48, -40, -35, -33, -26, -36, -67, -68, -65, -59, -47, -28, -34, -37, -36, -52, -61, -61, -47, -34, -39, -39, -42, -42, -48, -36, -38, -37, -20, -19, -16, -16, -18, -20, -22, -26, -22, -16, -15, 1, -4, -6, 10, 12, 13, 22, 32, 41, 54, 52, 44, 54, 66, 61, 78, 81, 71, 87, 89, 99, 119, 107, 91, 77, 76, 69, 76, 68, 47, 49, 35, 33, 37, 22, 14, 24, 37, 26, 13, -10, -26, -41, -43, -34, -40, -34, -33, -43, -39, -25, -27, -27, -18, -25, -15, -1, -10, -29, -42, -39, -39, -19, -7, -10, -10, -11, -20, -35, -44, -33, -30, -28, -36, -34, -47, -41, -36, -46, -42, -34, -27, -29, -25, -34, -30, -32, -40, -36, -36, -31, -16, -25, -25, -15, -21, -14, -9, -11, 1, 17, 15, 9, 25, 20, 25, 46, 39, 46, 50, 51, 68, 85, 87, 72, 65, 52, 50, 59, 44, 42, 29, 23, 22, 23, 11, -5, 8, 14, 19, 8, -6, -23, -38, -43, -42, -48, -41, -34, -42, -38, -19, -23, -16, -15, -19, -10, 8, 8, -9, -18, -27, -30, -10, -4, 7, 6, 15, 8, -8, -17, -15, -8, -11, -3, -15, -17, -14, -16, -27, -30, -26, -22, -19, -21, -22, -19, -30, -27, -26, -36, -22, -9, -13, -10, -10, -8, -9, -6, -12, -1, 16, 6, 11, 16, 6, 19, 24, 27, 38, 38, 38, 48, 71, 72, 78, 66, 51, 54, 52, 49, 42, 32, 21, 25, 26, 13, 1, -1, 10, 15, 8, 1, -22, -38, -47, -56, -58, -46, -43, -46, -33, -25, -17, -11, -9, -19, -9, 16, 18, 12, 1, -17, -18, -9, 3, 9, 17, 24, 26, 9, -4, -1, -6, 2, 9, 0, -2, 2, -3, -13, -16, -15, -8, -8, -8, -1, -6, -17, -11, -22, -24, -16, -12, -9, -9, -9, -9, -6, -8, -16, 2, 6, 2, 13, 9, 7, 10, 17, 19, 30, 31, 22, 37, 49, 61, 70, 56, 43, 37, 36, 31, 32, 15, 4, 11, 9, 4, -14, -16, -7, -5, -1, -8, -28, -46, -56, -75, -74, -67, -70, -67, -62, -55, -47, -36, -32, -42, -28, -9, 1, 4, -4, -17, -30, -18, -12, -2, 4, 15, 21, 7, 1, -7, -6, -1, 7, 0, 0, 3, -3, -8, -15, -18, -6, -9, -6, 5, -2, -2, 0, -7, -12, -7, -3, 2, 7, 3, 4, 14, 2, 1, 12, 11, 17, 20, 19, 16, 19, 20, 24, 39, 36, 37, 42, 55, 71, 84, 76, 63, 56, 47, 49, 46, 29, 18, 14, 18, 11, -5, -11, -8, -3, 4, 4, -16, -27, -44, -60, -64, -59, -62, -62, -55, -55, -47, -28, -32, -35, -29, -15, -3, 4, 3, -15, -25, -24, -13, -11, -3, 10, 14, 12, 4, -5, -9, -1, 2, -1, 1, 1, -1, -7, -17, -16, -12, -17, -8, 0, -1, -1, -2, -8, -13, -9, -9, 0, 9, 1, 14, 16, 6, 7, 10, 12, 18, 26, 20, 22, 22, 16, 25, 32, 36, 34, 36, 43, 60, 75, 72, 67, 52, 44, 50, 45, 38, 17, 14, 17, 11, -2, -9, -14, -10, 0, -4, -12, -24, -41, -59, -67, -63, -70, -69, -62, -70, -55, -40, -38, -42, -38, -29, -16, -3, -3, -9, -29, -31, -25, -26, -20, -7, 0, 2, -1, -14, -18, -14, -14, -12, -10, -10, -4, -13, -21, -19, -22, -24, -16, -10, -6, -2, -2, -10, -12, -15, -17, -4, -4, -5, 7, 9, 3, 4, 7, 5, 18, 23, 22, 28, 25, 22, 27, 34, 39, 43, 38, 41, 62, 71, 79, 78, 62, 55, 55, 57, 49, 31, 23, 30, 21, 15, 7, -5, 1, 8, 9, 8, -3, -16, -39, -46, -50, -60, -55, -58, -62, -53, -36, -33, -34, -34, -29, -18, -6, 5, -2, -17, -23, -22, -24, -17, -8, 1, 9, 10, -4, -7, -8, -9, -6, -9, -6, 0, -11, -14, -14, -21, -24, -21, -16, -10, 1, -3, -3, -5, -14, -11, -7, -7, -5, 6, 9, 4, 8, 1, 3, 11, 16, 20, 26, 24, 20, 25, 29, 36, 41, 32, 40, 51, 64, 77, 78, 67, 55, 54, 57, 53, 33, 27, 25, 22, 20, 9, -3, -3, 3, 7, 6, 4, -16, -32, -42, -55, -60, -61, -64, -70, -62, -49, -39, -41, -40, -37, -33, -18, -5, -8, -16, -24, -29, -31, -28, -24, -15, -1, 1, -7, -11, -14, -13, -14, -18, -11, -8, -14, -16, -16, -25, -31, -29, -31, -20, -12, -13, -6, -11, -19, -19, -14, -17, -12, -1, 2, 6, 7, 2, 4, 8, 11, 18, 24, 21, 22, 19, 21, 33, 33, 32, 32, 40, 55, 71, 76, 72, 58, 55, 62, 56, 42, 34, 28, 29, 26, 17, 4, 2, 6, 4, 13, 12, -4, -18, -30, -45, -50, -51, -59, -63, -61, -47, -37, -33, -32, -34, -32, -19, -4, -3, -5, -13, -21, -23, -22, -24, -13, 1, 5, 5, -3, -6, -1, -7, -9, -2, 1, -2, -2, -4, -13, -16, -22, -22, -15, -10, -4, 2, -1, -11, -8, -7, -12, -6, 1, 6, 12, 11, 8, 9, 9, 9, 20, 23, 26, 25, 20, 24, 32, 34, 35, 33, 35, 49, 63, 74, 74, 58, 55, 60, 54, 45, 33, 27, 25, 26, 19, 6, 4, 1, 1, 9, 12, -1, -10, -26, -43, -50, -54, -61, -70, -69, -61, -50, -43, -40, -44, -44, -34, -18, -12, -9, -15, -24, -25, -28, -31, -22, -12, -2, 1, -8, -8, -5, -12, -14, -8, -8, -8, -5, -9, -11, -18, -27, -26, -22, -19, -12, -1, -4, -9, -8, -11, -14, -12, -8, 0, 7, 5, 5, 6, 0, 3, 8, 13, 20, 18, 13, 15, 22, 27, 29, 25, 26, 36, 51, 70, 71, 59, 56, 57, 55, 47, 37, 25, 24, 27, 17, 9, 3, -2, -2, 8, 9, 6, -2, -16, -34, -44, -47, -54, -63, -66, -63, -55, -44, -39, -42, -44, -35, -23, -11, -4, -10, -16, -17, -23, -25, -22, -13, 1, 6, 1, 1, 4, -2, -4, 1, -1, 4, 3, 2, 2, -3, -12, -15, -14, -15, -7, 3, 5, 3, 2, 1, -2, -4, -4, 3, 9, 10, 13, 11, 9, 8, 9, 15, 22, 22, 20, 19, 21, 27, 30, 28, 28, 28, 42, 61, 69, 65, 60, 60, 58, 55, 47, 35, 30, 30, 24, 18, 10, 0, -1, 2, 6, 7, 3, -8, -24, -36, -43, -50, -59, -65, -66, -62, -52, -43, -43, -44, -41, -35, -21, -12, -12, -13, -17, -23, -26, -30, -24, -12, -4, -5, -3, -2, -5, -6, -6, -5, -3, -2, -1, 2, 2, -5, -3, 2, 8, 17, 26, 32, 42, 50, 56, 68, 73, 64, 63, 65, 48, 56, 71, 48, 49, 50, 26, 30, 30, 16, 25, 21, -2, 0, -13, -15, -2, -19, -17, -16, -50, -49, -49, -81, -85, -88, -108, -112, -116, -127, -126, -113, -113, -106, -79, -65, -48, -17, 5, 20, 41, 58, 63, 69, 59, 28, 17, 0, -32, -41, -52, -69, -63, -61, -59, -41, -26, -19, 6, 28, 33, 52, 67, 70, 81, 87, 84, 90, 93, 84, 72, 69, 60, 45, 56, 57, 40, 46, 39, 25, 29, 25, 16, 21, 12, -1, -3, -11, -8, -5, -16, -12, -21, -41, -38, -48, -68, -70, -77, -91, -93, -98, -106, -103, -93, -92, -82, -60, -47, -30, -4, 13, 27, 44, 56, 60, 62, 47, 23, 13, -8, -32, -40, -54, -64, -59, -59, -53, -36, -26, -14, 12, 27, 36, 56, 66, 72, 84, 86, 86, 93, 92, 82, 73, 70, 57, 49, 59, 52, 43, 47, 37, 29, 30, 24, 18, 18, 7, -2, -6, -11, -7, -10, -16, -14, -29, -42, -42, -57, -71, -73, -83, -93, -96, -102, -107, -101, -93, -90, -75, -55, -41, -22, 3, 19, 33, 50, 59, 61, 60, 41, 21, 10, -14, -33, -43, -57, -63, -60, -61, -51, -36, -27, -9, 15, 26, 40, 59, 66, 74, 85, 85, 88, 94, 90, 80, 75, 69, 56, 54, 60, 50, 47, 46, 36, 31, 30, 23, 19, 15, 4, -3, -7, -10, -9, -14, -17, -19, -35, -44, -47, -63, -73, -77, -88, -96, -98, -104, -107, -99, -92, -86, -69, -50, -35, -14, 9, 24, 38, 54, 60, 61, 56, 36, 19, 4, -20, -35, -46, -60, -62, -61, -60, -48, -35, -25, -3, 17, 27, 45, 60, 66, 77, 85, 86, 91, 94, 88, 80, 75, 67, 56, 58, 59, 50, 49, 45, 36, 33, 30, 23, 19, 13, 2, -5, -8, -10, -11, -16, -18, -25, -40, -45, -53, -68, -76, -81, -91, -97, -100, -106, -106, -97, -90, -81, -63, -44, -28, -6, 15, 28, 44, 57, 61, 61, 52, 31, 16, -1, -24, -37, -50, -61, -62, -62, -59, -46, -35, -22, 1, 18, 30, 48, 61, 68, 79, 85, 87, 92, 93, 86, 80, 75, 66, 58, 60, 58, 51, 50, 44, 37, 33, 29, 23, 17, 10, 0, -6, -9, -10, -14, -18, -21, -31, -43, -48, -59, -72, -78, -85, -94, -99, -102, -107, -104, -95, -88, -76, -56, -39, -22, 2, 20, 33, 49, 59, 61, 60, 47, 27, 12, -7, -27, -40, -53, -62, -62, -63, -57, -44, -34, -18, 5, 19, 33, 51, 61, 70, 81, 85, 88, 94, 92, 85, 80, 74, 65, 60, 62, 57, 52, 50, 43, 37, 33, 28, 22, 15, 8, -2, -7, -10, -12, -16, -20, -24, -36, -46, -52, -64, -75, -81, -89, -97, -100, -104, -107, -102, -93, -85, -70, -50, -33, -14, 8, 25, 38, 53, 61, 61, 58, 42, 24, 8, -12, -30, -43, -56, -62, -63, -63, -54, -43, -32, -13, 7, 20, 37, 53, 62, 72, 82, 85, 89, 94, 90, 84, 80, 73, 64, 62, 62, 56, 53, 49, 43, 37, 33, 27, 20, 14, 5, -3, -8, -11, -13, -18, -22, -28, -40, -49, -57, -69, -78, -84, -92, -99, -102, -105, -106, -99, -90, -81, -64, -44, -27, -7, 14, 29, 43, 56, 61, 61, 54, 37, 20, 4, -17, -33, -46, -58, -62, -64, -62, -52, -42, -29, -9, 9, 23, 40, 55, 64, 74, 83, 86, 91, 93, 89, 84, 80, 72, 65, 64, 62, 56, 53, 49, 42, 37, 33, 26, 19, 12, 3, -5, -8, -12, -16, -20, -24, -33, -44, -52, -61, -73, -80, -87, -95, -100, -103, -106, -104, -96, -88, -76, -57, -38, -21, 0, 20, 33, 47, 59, 62, 60, 51, 33, 17, -1, -21, -36, -49, -59, -63, -64, -61, -51, -40, -25, -5, 11, 26, 43, 56, 65, 76, 83, 87, 92, 93, 88, 84, 79, 71, 65, 65, 61, 56, 53, 48, 42, 37, 32, 25, 17, 10, 1, -6, -10, -13, -18, -22, -27, -37, -48, -55, -65, -76, -83, -90, -97, -101, -104, -106, -102, -94, -84, -71, -51, -33, -15, 7, 24, 38, 51, 60, 62, 59, 46, 29, 13, -6, -25, -39, -52, -60, -63, -64, -59, -49, -38, -21, -1, 14, 29, 46, 57, 67, 78, 84, 88, 92, 92, 87, 83, 78, 70, 66, 65, 61, 57, 53, 48, 42, 37, 31, 23, 15, 7, -1, -7, -11, -15, -20, -24, -31, -41, -51, -59, -69, -79, -85, -93, -99, -102, -105, -106, -100, -91, -80, -65, -45, -27, -8, 13, 29, 42, 55, 61, 61, 56, 42, 25, 8, -11, -28, -42, -54, -61, -64, -64, -57, -47, -35, -17, 1, 16, 33, 48, 59, 69, 79, 84, 89, 93, 91, 87, 83, 77, 70, 67, 65, 60, 57, 53, 47, 41, 36, 29, 21, 14, 5, -3, -8, -12, -17, -22, -27, -35, -45, -54, -63, -73, -81, -88, -95, -100, -103, -105, -104, -97, -88, -76, -58, -39, -21, -1, 18, 33, 46, 58, 62, 61, 53, 38, 21, 4, -15, -31, -45, -56, -62, -65, -64, -56, -46, -32, -13, 4, 19, 36, 50, 61, 71, 80, 85, 90, 92, 90, 86, 82, 76, 70, 68, 65, 60, 57, 52, 46, 41, 35, 27, 19, 12, 3, -5, -9, -14, -19, -24, -29, -38, -48, -57, -66, -76, -84, -91, -97, -101, -104, -105, -102, -94, -84, -71, -52, -33, -15, 5, 23, 37, 50, 60, 62, 60, 50, 34, 17, -1, -19, -35, -48, -58, -63, -65, -62, -54, -43, -28, -10, 7, 22, 39, 52, 62, 73, 81, 86, 91, 92, 89, 86, 82, 75, 70, 68, 64, 60, 57, 52, 46, 40, 34, 26, 17, 9, 1, -6, -11, -15, -21, -26, -32, -42, -52, -60, -70, -79, -86, -93, -99, -102, -104, -105, -100, -91, -80, -65, -46, -27, -9, 11, 28, 42, 54, 61, 62, 58, 46, 30, 13, -6, -23, -38, -51, -60, -64, -65, -61, -52, -41, -25, -6, 9, 26, 42, 54, 64, 75, 82, 87, 91, 91, 89, 85, 81, 74, 71, 68, 64, 60, 56, 51, 45, 39, 32, 24, 16, 7, -1, -7, -12, -17, -23, -28, -36, -45, -55, -64, -73, -82, -88, -95, -100, -103, -105, -104, -97, -88, -76, -59, -40, -22, -2, 17, 32, 45, 57, 62, 62, 56, 42, 26, 9, -10, -27, -41, -53, -61, -65, -65, -60, -50, -38, -21, -3, 12, 29, 44, 55, 66, 76, 82, 88, 91, 91, 88, 85, 80, 74, 71, 68, 63, 60, 56, 50, 44, 38, 30, 22, 14, 5, -3, -9, -14, -19, -25, -31, -39, -49, -58, -67, -77, -84, -91, -97, -101, -103, -105, -102, -95, -84, -71, -53, -34, -16, 4, 22, 37, 49, 59, 63, 61, 53, 38, 22, 4, -14, -30, -44, -56, -62, -66, -65, -58, -48, -35, -17, -1, 15, 32, 46, 57, 68, 77, 83, 88, 91, 90, 88, 84, 79, 74, 71, 67, 63, 60, 55, 49, 43, 37, 28, 20, 12, 3, -5, -10, -15, -21, -27, -33, -43, -52, -61, -70, -79, -86, -93, -98, -102, -104, -104, -100, -92, -81, -66, -47, -28, -10, 10, 27, 40, 53, 61, 63, 59, 49, 34, 18, -1, -18, -34, -47, -58, -63, -66, -64, -56, -46, -31, -14, 2, 18, 35, 48, 59, 70, 78, 84, 89, 91, 90, 87, 83, 78, 74, 71, 67, 63, 59, 54, 49, 42, 35, 27, 18, 9, 1, -6, -12, -17, -23, -29, -36, -46, -55, -64, -73, -82, -89, -95, -100, -102, -104, -103, -97, -88, -76, -60, -41, -23, -4, 15, 31, 44, 55, 62, 62, 57, 46, 30, 13, -5, -22, -37, -50, -59, -64, -66, -62, -55, -43, -28, -11, 5, 22, 37, 50, 61, 71, 79, 85, 89, 91, 89, 87, 82, 77, 73, 70, 66, 63, 59, 53, 47, 41, 33, 24, 16, 7, -1, -8, -14, -19, -25, -32, -40, -49, -58, -67, -76, -84, -91, -96, -101, -103, -104, -102, -95, -85, -72, -55, -37, -18, 1, 19, 34, 47, 57, 62, 62, 56, 43, 28, 10, -8, -25, -39, -52, -60, -65, -66, -62, -53, -42, -25, -9, 8, 24, 39, 51, 62, 72, 80, 86, 90, 90, 89, 86, 82, 77, 73, 70, 66, 62, 58, 53, 47, 40, 33, 24, 15, 6, -2, -8, -14, -19, -25, -32, -40, -49, -58, -67, -72, -103, -18, -76, 0, 0, 0, 0, 1, 2, 3, 5, 6, 0, -7, -8, -15, -9, 10, 8, 17, 33, 14, 5, 38, 44, 31, 63, 70, 51, 73, 82, 68, 85, 100, 96, 97, 103, 115, 114, 112, 127, 122, 110, 116, 113, 109, 120, 120, 118, 113, 91, 93, 109, 97, 98, 115, 110, 109, 120, 112, 94, 75, 63, 69, 72, 64, 64, 59, 45, 39, 36, 35, 42, 42, 24, 5, 2, 3, 4, 7, 9, 11, 14, 17, 19, 14, -3, -20, -26, -30, -26, -24, -31, -32, -34, -40, -39, -33, -34, -45, -56, -60, -66, -64, -55, -60, -62, -56, -59, -58, -50, -56, -70, -73, -76, -86, -77, -70, -80, -76, -71, -77, -71, -66, -76, -85, -82, -90, -95, -80, -82, -92, -85, -86, -94, -85, -79, -86, -92, -90, -94, -101, -92, -85, -90, -84, -77, -78, -74, -73, -85, -86, -85, -95, -85, -77, -90, -88, -83, -94, -93, -83, -81, -81, -86, -89, -89, -94, -88, -77, -77, -71, -59, -58, -59, -63, -72, -74, -77, -73, -61, -67, -72, -67, -73, -80, -74, -68, -60, -56, -65, -70, -67, -72, -66, -52, -49, -40, -27, -27, -32, -39, -47, -50, -42, -30, -31, -34, -32, -38, -46, -46, -43, -35, -20, -16, -24, -30, -30, -31, -24, -13, -6, 4, 13, 11, 3, -5, -9, -2, 12, 15, 15, 16, 9, 3, -2, -5, -1, 12, 24, 30, 29, 20, 17, 22, 25, 30, 41, 47, 49, 46, 37, 32, 41, 52, 54, 60, 61, 52, 48, 45, 36, 35, 43, 51, 60, 67, 69, 60, 57, 63, 63, 64, 73, 75, 72, 69, 63, 67, 78, 78, 82, 89, 80, 73, 76, 67, 60, 64, 67, 73, 79, 83, 88, 82, 75, 80, 81, 77, 83, 83, 76, 74, 77, 83, 85, 86, 94, 89, 80, 82, 78, 69, 68, 68, 69, 78, 80, 81, 90, 83, 73, 79, 77, 70, 73, 70, 62, 65, 73, 75, 76, 84, 82, 70, 71, 69, 59, 57, 54, 48, 53, 63, 64, 68, 76, 66, 57, 58, 51, 42, 40, 33, 28, 37, 46, 49, 55, 56, 42, 37, 37, 27, 22, 20, 10, 4, 8, 15, 24, 30, 31, 24, 14, 8, -3, -14, -21, -26, -26, -15, -4, -1, -4, -13, -21, -26, -34, -39, -42, -50, -57, -63, -66, -60, -47, -43, -48, -51, -57, -66, -75, -82, -88, -91, -88, -78, -74, -81, -86, -85, -92, -101, -100, -102, -109, -109, -110, -112, -113, -115, -109, -106, -113, -113, -107, -110, -110, -106, -108, -112, -109, -110, -114, -111, -98, -95, -98, -93, -93, -98, -94, -89, -81, -69, -65, -71, -73, -73, -77, -73, -62, -56, -48, -40, -41, -45, -47, -47, -37, -20, -11, -4, 5, 4, 3, 6, 9, 16, 30, 39, 47, 51, 44, 40, 45, 47, 50, 59, 64, 66, 68, 65, 65, 75, 80, 78, 87, 95, 91, 93, 98, 96, 98, 104, 100, 96, 99, 104, 101, 100, 106, 107, 105, 108, 109, 109, 110, 111, 110, 101, 87, 82, 84, 81, 82, 88, 89, 90, 91, 85, 71, 57, 49, 48, 51, 52, 55, 59, 58, 58, 60, 61, 61, 57, 42, 24, 14, 7, 5, 9, 11, 15, 20, 21, 19, 11, -3, -18, -27, -33, -31, -25, -24, -21, -16, -16, -14, -11, -17, -29, -40, -49, -59, -61, -55, -54, -52, -45, -42, -41, -41, -48, -59, -65, -72, -81, -79, -72, -73, -69, -62, -61, -59, -60, -69, -76, -79, -87, -92, -84, -81, -82, -76, -72, -71, -67, -66, -72, -79, -81, -87, -94, -92, -87, -86, -82, -76, -75, -75, -78, -85, -87, -91, -96, -91, -82, -83, -80, -74, -74, -71, -64, -64, -68, -73, -77, -81, -87, -88, -82, -79, -76, -70, -69, -72, -76, -80, -84, -87, -82, -71, -67, -64, -58, -57, -55, -49, -43, -39, -40, -47, -54, -58, -64, -66, -61, -58, -54, -49, -50, -55, -59, -63, -65, -58, -45, -38, -32, -25, -24, -23, -18, -13, -5, 3, 4, -2, -11, -17, -23, -26, -23, -20, -18, -15, -18, -24, -28, -28, -21, -7, 3, 11, 18, 20, 19, 22, 24, 30, 40, 47, 51, 49, 40, 32, 28, 24, 23, 25, 25, 23, 20, 15, 15, 23, 34, 43, 51, 59, 59, 58, 59, 58, 60, 67, 73, 78, 84, 85, 78, 71, 68, 63, 60, 60, 57, 53, 50, 50, 56, 65, 70, 76, 84, 84, 81, 81, 79, 76, 79, 84, 87, 91, 96, 98, 94, 88, 85, 81, 76, 73, 70, 66, 66, 70, 76, 80, 84, 91, 92, 87, 86, 83, 78, 76, 78, 81, 85, 88, 91, 96, 93, 86, 83, 78, 71, 68, 64, 61, 64, 71, 74, 78, 84, 86, 80, 76, 72, 64, 59, 56, 55, 59, 66, 69, 74, 79, 76, 69, 64, 57, 48, 43, 39, 39, 45, 52, 56, 62, 63, 55, 47, 41, 31, 21, 15, 8, 5, 9, 16, 24, 31, 35, 33, 26, 19, 10, 0, -6, -9, -7, -7, -13, -17, -22, -26, -31, -34, -37, -40, -42, -44, -46, -48, -50, -51, -54, -56, -58, -61, -64, -67, -70, -74, -78, -82, -86, -90, -93, -97, -99, -102, -104, -106, -108, -109, -110, -111, -112, -113, -113, -114, -114, -115, -115, -115, -115, -115, -114, -113, -111, -109, -107, -104, -100, -97, -93, -90, -87, -84, -82, -80, -78, -76, -74, -73, -71, -69, -67, -65, -61, -58, -53, -48, -42, -35, -28, -21, -13, -6, 1, 8, 15, 21, 26, 31, 35, 38, 41, 44, 46, 48, 50, 52, 55, 58, 61, 64, 68, 72, 76, 80, 83, 87, 90, 92, 94, 96, 98, 99, 100, 101, 102, 102, 103, 103, 103, 103, 104, 103, 103, 103, 102, 101, 99, 97, 94, 92, 88, 85, 81, 78, 74, 71, 67, 64, 61, 58, 55, 53, 51, 49, 47, 46, 44, 42, 40, 37, 34, 30, 26, 22, 17, 12, 8, 3, -1, -5, -9, -13, -16, -20, -23, -26, -29, -31, -33, -35, -37, -38, -40, -42, -44, -46, -48, -51, -54, -56, -59, -61, -64, -65, -67, -69, -70, -72, -74, -75, -77, -78, -80, -81, -82, -83, -84, -85, -86, -86, -87, -88, -89, -90, -90, -91, -92, -92, -92, -92, -92, -92, -91, -91, -92, -92, -92, -93, -93, -94, -94, -94, -95, -95, -95, -95, -95, -95, -95, -95, -95, -94, -93, -92, -91, -90, -89, -87, -86, -85, -85, -85, -84, -84, -85, -85, -85, -85, -85, -85, -85, -85, -85, -84, -83, -82, -81, -79, -77, -75, -73, -70, -68, -65, -63, -62, -60, -59, -59, -59, -59, -59, -59, -59, -60, -59, -59, -59, -58, -57, -55, -53, -50, -47, -44, -40, -36, -32, -29, -25, -22, -20, -18, -17, -16, -15, -15, -16, -16, -16, -16, -16, -16, -15, -13, -11, -9, -6, -2, 2, 6, 10, 15, 19, 22, 26, 29, 31, 33, 35, 36, 36, 36, 36, 35, 35, 35, 35, 35, 36, 38, 40, 42, 45, 48, 52, 55, 58, 61, 64, 67, 70, 72, 73, 74, 75, 76, 76, 76, 75, 75, 74, 74, 74, 74, 74, 75, 77, 78, 80, 82, 83, 85, 87, 89, 90, 91, 92, 93, 94, 94, 94, 94, 94, 93, 93, 92, 91, 91, 90, 90, 90, 90, 91, 91, 92, 92, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 92, 92, 91, 90, 89, 88, 87, 87, 86, 86, 85, 85, 85, 84, 84, 83, 83, 82, 81, 80, 79, 78, 77, 77, 76, 75, 74, 72, 71, 70, 68, 67, 65, 64, 63, 61, 60, 58, 57, 55, 53, 50, 48, 45, 43, 40, 38, 36, 34, 32, 30, 29, 27, 25, 23, 21, 19, 17, 14, 12, 9, 6, 3, 0, -4, -8, -12, -17, -21, -25, -29, -33, -36, -39, -42, -45, -47, -49, -51, -53, -55, -58, -60, -63, -65, -68, -71, -74, -77, -81, -84, -87, -91, -94, -97, -99, -102, -104, -105, -107, -108, -109, -110, -111, -111, -112, -112, -113, -113, -113, -113, -113, -113, -112, -111, -109, -107, -105, -102, -99, -96, -93, -90, -87, -84, -82, -79, -77, -75, -73, -70, -69, -66, -64, -60, -58, -53, -49, -44, -39, -32, -27, -19, -14, -8, -3, 3, 11, 22, 10, 8, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 5, 6, 6, 6, 6, 6, 6, 7, 5, 7, 5, 6, 4, 6, 4, 4, 4, 4, 3, 3, 2, 3, 1, 3, -2, 2, 0, 0, 0, 0, -2, -1, -2, -3, -3, 0, -5, -1, -2, -2, -2, -1, 0, -3, -1, -1, 0, 1, -1, 0, -1, 0, 0, 1, 0, 0, 1, -1, 1, -1, 1, -2, -1, -3, 0, -2, -1, -2, -2, -2, -3, -2, -3, -4, -5, -6, -5, -9, -8, -9, -9, -9, -11, -10, -13, -14, -14, -15, -16, -15, -17, -19, -19, -21, -18, -21, -20, -22, -20, -24, -21, -22, -19, -20, -21, -17, -19, -16, -17, -15, -17, -13, -11, -10, -7, -5, -3, 2, 6, 4, 8, 9, 18, 14, 31, 25, 24, 25, 24, 21, 13, 15, 15, 11, 9, 1, 4, -20, -18, -38, -44, -57, -57, -55, -55, -52, -55, -46, -47, -40, -32, -26, -19, -16, -2, 3, 13, 19, 28, 30, 37, 40, 44, 39, 38, 35, 34, 37, 41, 48, 51, 53, 58, 61, 70, 74, 76, 76, 80, 81, 86, 83, 83, 78, 78, 73, 69, 65, 55, 47, 40, 36, 29, 23, 16, 14, 8, -2, -4, -11, -11, -19, -22, -26, -25, -34, -39, -40, -41, -45, -49, -51, -57, -56, -58, -59, -66, -70, -70, -72, -65, -64, -59, -53, -49, -45, -34, -29, -21, -15, -10, -6, -6, -3, -4, 2, 3, 3, 3, -1, -3, -11, -11, -13, -16, -22, -24, -27, -32, -34, -37, -35, -31, -30, -26, -25, -22, -21, -15, -13, -15, -10, -12, -12, -7, 2, 15, 22, 27, 24, 28, 22, 22, 21, 22, 17, 13, 14, 9, 5, 2, -8, -12, -16, -14, -17, -17, -17, -17, -14, -8, -3, -3, 0, 5, 3, 5, 6, 3, -2, -6, -9, -11, -13, -18, -19, -29, -42, -61, -72, -79, -81, -83, -82, -79, -76, -65, -54, -42, -33, -24, -14, 0, 18, 33, 48, 62, 75, 87, 93, 99, 100, 102, 102, 104, 102, 100, 100, 96, 93, 95, 96, 105, 109, 112, 111, 110, 106, 106, 104, 102, 97, 93, 85, 80, 71, 60, 48, 36, 26, 12, 0, -5, -13, -21, -28, -31, -36, -42, -49, -53, -56, -59, -61, -63, -64, -64, -63, -67, -70, -77, -75, -77, -78, -79, -80, -81, -80, -75, -69, -64, -57, -50, -43, -35, -26, -16, -6, 6, 13, 17, 22, 26, 25, 27, 27, 26, 23, 19, 11, 5, -5, -12, -19, -24, -31, -37, -42, -45, -50, -49, -48, -47, -43, -41, -38, -38, -37, -35, -35, -37, -42, -40, -33, -27, -20, -12, -11, -13, -10, -9, -10, -10, -10, -13, -11, -9, -8, -11, -13, -16, -18, -17, -15, -15, -14, -12, -8, -3, 3, 8, 16, 22, 25, 31, 34, 36, 36, 34, 31, 25, 23, 24, 26, 23, 13, -1, -16, -29, -38, -45, -51, -56, -57, -54, -48, -39, -34, -29, -20, -10, 0, 13, 27, 39, 54, 68, 79, 87, 92, 94, 96, 94, 92, 89, 87, 82, 76, 72, 71, 74, 76, 81, 83, 83, 84, 84, 85, 85, 82, 81, 82, 80, 75, 71, 66, 57, 46, 34, 24, 15, 5, -2, -8, -13, -19, -26, -31, -37, -41, -44, -48, -53, -54, -53, -54, -54, -57, -61, -64, -67, -70, -72, -75, -77, -79, -79, -76, -73, -70, -63, -58, -53, -47, -38, -29, -21, -13, -6, 0, 4, 7, 7, 8, 8, 6, 5, -1, -8, -15, -22, -30, -36, -41, -47, -51, -54, -56, -58, -59, -56, -50, -45, -42, -37, -31, -26, -23, -23, -23, -24, -21, -14, -6, 2, 8, 12, 15, 18, 21, 20, 20, 20, 20, 21, 23, 22, 18, 13, 10, 8, 6, 5, 4, 3, 2, 2, 4, 7, 10, 13, 18, 22, 24, 26, 28, 27, 21, 14, 8, 5, 4, 2, -3, -12, -24, -37, -50, -59, -67, -76, -80, -79, -75, -69, -61, -55, -47, -38, -27, -15, -2, 11, 27, 43, 58, 71, 82, 90, 94, 96, 98, 98, 98, 95, 89, 84, 81, 79, 81, 85, 88, 89, 91, 92, 92, 90, 89, 89, 88, 85, 82, 79, 75, 67, 58, 48, 37, 25, 14, 4, -4, -10, -17, -24, -31, -37, -42, -47, -51, -56, -59, -59, -59, -59, -61, -63, -65, -67, -70, -72, -74, -76, -78, -78, -78, -75, -70, -66, -61, -56, -50, -41, -33, -23, -14, -6, 2, 10, 16, 19, 21, 23, 24, 24, 22, 19, 13, 7, 0, -6, -14, -20, -25, -27, -32, -37, -39, -39, -38, -36, -33, -30, -27, -22, -19, -19, -20, -23, -24, -22, -18, -13, -8, -4, 0, 2, 5, 6, 5, 3, 2, 4, 6, 6, 5, 1, -2, -6, -8, -9, -10, -11, -13, -12, -12, -11, -9, -4, 0, 4, 8, 13, 18, 20, 19, 14, 10, 6, 4, 4, 4, 0, -8, -17, -28, -38, -49, -60, -68, -72, -72, -70, -65, -59, -54, -46, -37, -27, -17, -5, 8, 22, 37, 51, 66, 77, 84, 88, 91, 93, 94, 94, 91, 85, 79, 75, 74, 76, 77, 80, 83, 85, 85, 85, 86, 86, 85, 85, 85, 83, 81, 77, 70, 64, 55, 44, 32, 22, 13, 6, -1, -9, -16, -22, -27, -32, -38, -43, -46, -47, -47, -47, -48, -49, -49, -50, -52, -54, -56, -59, -62, -64, -66, -65, -64, -61, -59, -56, -53, -48, -41, -33, -25, -17, -10, -2, 4, 9, 13, 15, 16, 17, 17, 15, 11, 7, 1, -7, -15, -22, -27, -33, -38, -43, -47, -49, -50, -50, -49, -46, -42, -37, -31, -28, -28, -29, -30, -29, -26, -22, -17, -13, -8, -3, 2, 6, 7, 6, 5, 6, 8, 10, 12, 11, 8, 5, 3, 1, -1, -2, -3, -4, -6, -7, -6, -3, 0, 1, 5, 10, 16, 20, 21, 19, 15, 10, 8, 6, 6, 4, 0, -5, -12, -22, -33, -45, -57, -65, -70, -72, -70, -68, -64, -58, -51, -44, -36, -24, -13, -2, 11, 27, 43, 58, 70, 78, 83, 88, 92, 96, 97, 93, 89, 85, 81, 80, 81, 83, 86, 88, 90, 91, 91, 91, 91, 91, 91, 91, 89, 86, 83, 79, 72, 63, 52, 41, 30, 21, 13, 4, -5, -11, -17, -23, -31, -38, -44, -47, -49, -50, -52, -54, -55, -57, -57, -58, -60, -63, -66, -69, -72, -74, -73, -72, -70, -69, -67, -64, -59, -53, -45, -37, -30, -22, -14, -7, -2, 3, 8, 10, 12, 12, 13, 12, 8, 3, -4, -10, -16, -21, -27, -33, -37, -41, -44, -46, -48, -48, -45, -48, -43, -37, -33, -31, -32, -33, -32, -29, -26, -22, -18, -12, -5, 1, 6, 9, 9, 9, 9, 11, 14, 16, 16, 14, 12, 8, 5, 3, 2, 1, -1, -3, -4, -4, -2, -1, 2, 5, 11, 18, 24, 27, 27, 24, 20, 17, 15, 13, 11, 9, 5, -1, -10, -22, -35, -49, -61, -70, -75, -77, -76, -73, -69, -63, -56, -47, -36, -25, -13, 0, 16, 34, 52, 67, 79, 88, 95, 101, 106, 109, 108, 105, 100, 95, 92, 90, 91, 93, 96, 99, 100, 101, 101, 101, 101, 101, 101, 100, 97, 95, 91, 85, 78, 67, 55, 43, 31, 21, 11, 1, -7, -14, -21, -29, -37, -45, -51, -54, -56, -58, -60, -62, -64, -65, -66, -67, -69, -72, -76, -80, -82, -84, -83, -82, -80, -79, -77, -73, -67, -60, -51, -42, -34, -25, -16, -8, -2, 4, 9, 12, 13, 14, 14, 13, 9, 3, -5, -12, -18, -25, -31, -37, -42, -47, -50, -53, -54, -53, -48, -41, -36, -32, -31, -31, -32, -31, -28, -25, -22, -17, -12, -5, 1, 1, -2, -1, -9, -9, -6, 5, 6, -1, -10, 8, 24, 11, -2, -14, -9, -15, -13, 5, 14, 12, -6, -1, -12, 1, -9, 12, 12, 10, 5, -19, -11, -13, -2, 8, 5, 1, -2, -3, 9, -6, 6, 5, 6, -3, -17, -7, 3, 2, -1, 0, 7, -7, 5, 4, 6, -18, -24, 6, 20, -1, -4, -1, 10, 3, -10, 8, 7, -11, -17, -15, 5, 18, 4, 1, 8, -16, -4, 0, 11, 9, -10, -15, 0, -22, -12, 19, 34, 16, -9, -16, -7, -12, -10, 13, 23, -1, -10, -2, -3, -11, 13, 7, -6, -9, 3, 11, -10, -18, 12, 22, 7, -27, -29, -4, 20, 20, 10, 8, -16, -26, -6, 22, 21, 7, 15, 8, -50, -50, -7, 35, 22, -13, 32, 41, -33, -46, -10, 23, -7, -25, 23, 21, -38, -36, 14, 44, 2, 2, 34, -14, -51, -29, 11, 19, 7, 22, 13, -23, -21, -8, -9, 1, 14, 26, 26, -8, -34, -33, 4, 1, -6, -2, 16, -7, -23, 12, 27, 5, 6, 6, 0, -8, 0, -1, -17, -13, -12, 3, 9, 4, 11, 23, 36, 0, -43, -16, 4, -21, -26, 27, 16, -25, 3, 65, 4, -34, 24, -10, -38, -14, 13, 4, -15, 36, 44, -42, -51, 20, -5, -6, 68, 20, -18, -39, -11, 9, 17, 6, -33, -20, -13, 48, 30, 22, -4, -9, -53, -20, 32, 32, -16, 17, -11, -36, -8, -5, 39, 28, 33, 21, -64, -48, 3, -22, 15, 62, -26, 0, 3, 5, 73, -14, -48, -20, -59, 4, 70, 60, -7, -2, -88, -22, -17, 39, 17, 33, -3, 15, 28, -47, -80, -37, 5, 7, 104, 16, -99, -92, -36, 109, 78, 26, -15, -92, -21, 62, 48, -51, -81, -25, 55, 63, 35, 21, -115, -54, 101, 73, -41, -110, -66, 50, 107, 45, -8, -109, -38, 12, 102, 3, 17, -45, -2, -36, 39, 46, -12, -28, -27, -17, 17, -18, 82, -5, -3, -25, -5, -14, 15, 9, -3, -17, -6, 2, 7, -36, -13, 6, 21, -23, -20, 16, -18, 3, -2, 26, 0, 13, -23, -2, -19, -28, -18, 15, 12, 22, -4, 23, -17, -22, -9, -18, -4, 11, 13, 0, 34, -16, -20, 26, 23, 15, -4, -25, 7, 8, -9, 8, 44, 1, -40, 17, -32, 9, -30, -52, 52, 3, 2, -21, 83, 58, -14, -46, -61, -12, -67, -20, 64, 72, 57, -10, 5, 1, -77, 31, -47, -39, 12, 22, 57, 28, 0, 9, -76, 15, -74, 33, -12, 39, 114, -35, -36, -38, -23, 27, -21, 14, 56, 47, 6, -72, -61, -4, 18, -4, 19, 13, 45, 71, 48, -1, -125, -52, -56, -20, -18, -12, 51, 78, 68, -46, 32, -40, -29, -28, -81, -25, 75, 42, 58, -38, 1, -29, -34, 31, -36, -14, 10, 64, 37, 2, -31, -72, -17, -33, 30, -52, -54, 25, 43, 70, 81, -9, -73, 4, -65, 15, -28, 25, 0, 28, 19, 51, -26, 6, 0, -37, -15, -22, -20, -16, -5, 50, 56, 67, 25, 16, -35, -29, -14, -39, 19, -24, -52, -13, -32, -10, 39, 33, 59, 6, 37, 55, 11, -9, -35, -15, -57, -56, -36, -34, 19, 19, 6, 20, 17, -11, 5, 26, 19, 16, 7, -20, -26, -55, -62, -36, -18, 19, 37, 47, 25, -6, -14, 1, -4, -13, 12, 23, 34, 38, 41, 33, 31, -10, -56, -52, -49, -31, -40, -21, -12, 0, 5, 12, 22, 22, 21, 31, 12, 2, -8, -4, -18, -7, 3, 1, -1, 11, 12, 18, 17, 9, -2, -12, -13, -11, -1, 8, 3, 3, 2, 5, -5, -16, -15, -13, -8, -12, -9, -2, -1, 2, 7, 10, 7, 11, 14, 7, -1, -4, 5, -3, -2, 0, -6, -10, -1, -5, 3, 9, 0, -8, -9, -6, -6, 0, 6, 3, 6, 7, 10, 0, -8, -3, -5, -1, -8, -7, -4, -3, -3, 0, -1, -6, 2, 7, 7, 5, 4, 10, 5, 8, -1, -11, -15, -11, -15, -10, -1, -8, -12, -5, 1, 3, 6, 8, 11, 18, 22, 26, 10, -10, -1, -15, -3, -21, -16, -14, -12, -7, -8, -18, -20, -11, 9, 20, 27, 26, 11, 1, 21, 6, 3, -9, -15, -9, -20, 3, 5, 21, 14, 6, 11, -21, -22, -6, -21, -23, -18, 11, 6, 5, 21, 9, 23, 16, -3, -30, -7, -27, -4, 5, 18, 22, 16, 2, 7, -1, -2, -10, -14, -10, -17, -10, -15, -16, 3, 12, 30, 18, -1, -6, -15, -3, 5, 11, -18, -2, 8, 21, 11, -13, -4, -30, -7, 0, 12, 25, -3, 17, 14, -20, -6, -27, -41, -11, -12, 23, -8, 13, 24, 18, 27, -11, -8, -12, -2, 17, 23, 13, -20, -21, -2, -21, -34, -46, -23, 28, 48, 9, -10, 8, 29, 27, 5, -29, -12, 13, -5, -2, -35, 1, 3, 24, 13, 17, -18, -30, -21, 14, -1, 6, -8, 48, 45, -7, -34, -49, -32, -6, -26, 20, 29, 76, 30, -21, -66, -36, -15, 40, -5, 29, 3, 10, -39, -25, -2, 24, 19, 19, -4, -8, 3, -22, -23, -18, 13, 17, -3, -25, 23, 66, 26, -18, -27, -34, -30, -30, 36, 25, 28, -22, -17, -7, -22, 21, 18, 42, 8, -25, -28, -31, -10, 15, 18, 0, -1, -5, 16, -12, 13, 13, 12, -8, -37, -9, 13, -5, 8, -3, 13, -8, 4, 24, -16, -43, -18, 26, 26, -11, -9, 19, 9, -15, 9, 15, -12, -31, -27, 8, 29, 5, 7, 17, -33, -14, 14, 23, -1, -18, -18, -4, -35, -17, 47, 71, -16, -20, -11, -16, -25, 6, 37, 14, -18, 1, -8, -14, 10, 14, 2, -20, 0, 20, -10, -25, 14, 32, 7, -39, -38, -3, 34, 25, 13, 3, -24, -34, 5, 38, 18, 7, 29, -30, -74, -41, 36, 40, -12, 26, 55, -17, -59, -26, 28, -2, -31, 24, 25, -44, -39, 21, 44, -1, 10, 33, -34, -50, -12, 18, 13, 20, 17, -6, -31, -10, -6, -1, 7, 12, 14, 6, -16, -24, 6, 9, -16, -16, 6, 2, -10, 13, 12, -10, 0, 11, 11, 10, -3, -22, -22, -12, -7, 19, 17, -2, -12, 6, 16, 7, -11, -1, -20, -22, -8, 26, 16, -3, 12, 1, -33, 2, 30, -23, -5, 28, -17, -19, 21, 9, -28, -14, 25, -1, 4, 24, 0, -26, -9, 7, 2, -2, 20, -10, -11, 5, -3, -4, 8, -9, 14, 18, 25, -22, -15, -22, -3, -12, 27, 30, 15, -11, -26, -4, 15, -7, -14, 23, -23, -4, 34, -2, -38, 14, -11, -24, 16, 34, 11, -13, 3, -3, -19, -34, 0, -3, 24, 43, 1, -12, -38, -25, -11, 23, 35, 12, -28, -25, -16, 7, 22, 1, -10, 8, 8, -3, 6, -24, -20, -13, 9, 31, 12, -16, 7, -29, 5, 8, -28, 3, 4, 12, 26, -9, -15, -5, -20, 9, 21, 0, 1, -9, 0, 8, -3, -7, -9, -3, 22, 8, 3, -11, -9, -11, 3, 15, 9, -10, 1, -3, -3, -2, -5, 9, 0, 12, 7, -15, -7, 0, -8, 5, 9, -5, 7, -7, 10, 4, -11, -2, -8, -4, 9, 9, 0, -2, -11, -3, -4, 3, 4, 3, -2, 3, 3, -8, -9, -2, 0, 3, 5, -1, -10, -7, 2, 8, 3, 0, -5, -5, 2, 4, -2, -5, -3, 2, 3, 0, 2, -5, -3, 3, 2, -2, -4, -2, 1, 2, 1, 0, 0, 0, 0, -1, -7, -9, -5, 0, 2, 2, 5, 6, 0, -11, -13, -5, 3, 1, 0, 0, 1, -3, -9, -6, -1, 5, 3, -3, -5, -3, -1, -4, -3, -1, 2, -2, -9, -7, -2, -5, -18, -31, -36, -36, -41, -38, -29, -21, -27, -31, -26, -4, 37, 65, 67, 44, 22, 10, 2, -4, 8, 32, 44, 38, 24, 17, 9, 4, 3, 12, 26, 32, 32, 23, 16, 7, 1, -7, -13, -8, 1, -5, -39, -72, -79, -64, -49, -40, -24, -1, 12, 0, -25, -44, -43, -30, -14, 1, 13, 13, 4, 4, 16, 34, 46, 55, 65, 73, 67, 53, 54, 58, 62, 60, 51, 38, 33, 20, -7, -27, -40, -46, -55, -58, -41, -9, 7, 8, 2, -26, -49, -71, -92, -101, -93, -80, -70, -71, -73, -65, -67, -69, -61, -42, -15, 15, 18, -5, -33, -54, -54, -40, -18, 2, 21, 21, 3, -28, -52, -33, 9, 35, 33, 30, 34, 45, 46, 43, 54, 63, 65, 61, 56, 43, 45, 59, 77, 96, 104, 112, 115, 100, 78, 53, 22, -3, -6, 5, 24, 37, 38, 35, 25, 3, -19, -38, -51, -46, -33, -34, -42, -47, -48, -38, -27, -30, -40, -48, -45, -30, -24, -38, -44, -43, -47, -34, -13, 7, 27, 30, 9, -18, -38, -22, 19, 47, 70, 83, 68, 28, -13, -41, -41, -19, -1, 10, 8, 4, 4, -7, -12, 6, 32, 42, 31, 0, -39, -71, -99, -115, -111, -85, -56, -46, -61, -74, -66, -45, -22, 4, 21, 27, 25, 1, -30, -51, -37, 4, 37, 40, 26, 17, 12, 12, 5, 1, 2, 12, 29, 43, 44, 45, 54, 45, 28, 10, 13, 26, 32, 43, 59, 67, 62, 60, 66, 72, 61, 34, 11, 0, 1, -6, -18, -12, 19, 47, 51, 32, 9, -8, -22, -26, -27, -30, -29, -12, 7, 18, 13, -1, -11, -11, 5, 16, 14, 11, 5, -19, -47, -54, -29, 13, 37, 42, 33, 9, -17, -31, -21, 14, 61, 81, 68, 39, 4, -26, -46, -38, -17, -1, 1, -4, -14, -25, -23, -4, 24, 43, 49, 37, 4, -48, -97, -123, -116, -89, -66, -65, -73, -67, -64, -66, -69, -46, 3, 36, 27, -3, -25, -39, -38, -39, -36, -24, -9, 5, 13, 13, 4, -1, -13, -15, 0, 22, 47, 65, 76, 67, 35, 3, -4, 6, 27, 47, 58, 68, 72, 73, 72, 66, 59, 62, 61, 49, 28, -5, -30, -27, 9, 40, 51, 46, 40, 28, 1, -30, -56, -57, -41, -13, 5, 12, 7, -11, -38, -54, -40, -16, 12, 23, 13, -16, -49, -62, -55, -29, 4, 38, 45, 28, -5, -36, -36, -5, 39, 68, 77, 73, 55, 8, -35, -46, -29, -15, -15, -16, -12, -9, -23, -30, -18, 16, 48, 51, 24, -18, -45, -72, -96, -111, -101, -80, -67, -71, -79, -77, -70, -46, -22, -7, -4, -5, -4, -2, -15, -37, -43, -42, -27, -5, 9, 27, 38, 27, 4, -14, -15, 6, 30, 61, 93, 90, 52, 16, 2, 1, 5, 11, 34, 64, 79, 71, 48, 35, 43, 61, 59, 46, 27, 1, -22, -33, -25, -9, 15, 37, 56, 54, 28, -10, -44, -58, -49, -27, -8, 20, 29, 0, -42, -66, -60, -34, -7, 16, 30, 15, -20, -50, -64, -49, -11, 21, 34, 34, 17, -7, -31, -29, 3, 43, 69, 78, 73, 45, 10, -20, -32, -33, -26, -12, -6, -18, -41, -44, -27, -6, 10, 17, 19, 18, -4, -49, -87, -108, -100, -84, -87, -93, -83, -67, -54, -45, -45, -35, -23, -13, 6, 17, 14, 1, -22, -40, -35, -18, 2, 28, 57, 63, 33, -7, -21, -4, 23, 57, 89, 102, 94, 68, 37, 8, -4, 4, 37, 71, 88, 79, 54, 46, 55, 62, 55, 53, 54, 46, 20, -14, -40, -41, -16, 15, 44, 60, 59, 30, -21, -61, -70, -54, -26, 10, 29, 19, -16, -49, -63, -58, -33, 4, 29, 26, -1, -33, -49, -50, -34, -9, 16, 34, 34, 9, -20, -25, -9, 13, 29, 54, 87, 91, 56, 11, -12, -11, -12, -20, -22, -17, -11, -12, -22, -25, -15, 3, 19, 19, 9, -11, -38, -62, -76, -92, -107, -109, -95, -68, -53, -49, -49, -58, -63, -48, -25, -5, 12, 12, -7, -36, -56, -56, -32, 8, 50, 64, 36, 6, -10, -15, -11, 9, 47, 94, 118, 100, 58, 14, -3, 3, 19, 44, 72, 83, 78, 75, 66, 53, 45, 52, 66, 70, 52, 22, -8, -36, -36, -14, 21, 63, 84, 63, 14, -29, -55, -54, -42, -12, 28, 40, 14, -24, -52, -58, -42, -22, 6, 19, 16, -5, -34, -49, -43, -24, -12, 2, 14, 22, 10, -10, -20, -16, 3, 28, 60, 72, 61, 42, 25, 1, -26, -44, -46, -31, -25, -26, -32, -30, -24, -12, -12, -15, 0, 6, -3, -23, -47, -79, -112, -128, -115, -84, -61, -45, -42, -51, -64, -68, -61, -33, 9, 29, 12, -28, -54, -64, -56, -30, 9, 36, 41, 34, 10, -18, -38, -29, 13, 70, 105, 106, 79, 48, 31, 12, -1, 12, 51, 78, 89, 87, 75, 66, 49, 44, 56, 73, 79, 66, 23, -23, -42, -39, -9, 31, 65, 75, 52, 7, -32, -54, -57, -30, 3, 24, 19, 2, -18, -39, -50, -39, -10, 8, 10, -2, -12, -18, -21, -29, -33, -16, 11, 28, 17, 1, -4, 3, -3, -6, 13, 42, 64, 67, 56, 29, 2, -21, -36, -42, -40, -25, -15, -10, -7, -10, -27, -38, -24, 2, 19, 14, -6, -44, -86, -115, -121, -109, -81, -45, -27, -36, -58, -76, -81, -53, -13, 11, 8, -11, -24, -40, -58, -62, -30, 11, 42, 44, 17, -15, -36, -38, -22, 15, 53, 84, 88, 73, 52, 19, -6, -9, 13, 44, 71, 88, 93, 79, 54, 42, 46, 67, 82, 79, 54, 20, -10, -28, -27, 0, 46, 70, 61, 29, 2, -18, -38, -45, -23, 7, 16, 10, -8, -22, -26, -30, -32, -23, -13, -2, 6, -6, -15, -16, -18, -20, -9, 0, 2, 11, 19, 17, -2, -21, -12, 14, 33, 50, 65, 61, 43, 19, -17, -44, -50, -42, -21, 1, 11, 1, -31, -56, -45, -22, -1, 17, 18, -4, -44, -95, -126, -123, -95, -56, -36, -41, -51, -59, -68, -60, -38, -15, 5, 14, 7, -17, -47, -61, -37, 1, 27, 33, 24, 7, -13, -30, -43, -26, 13, 47, 70, 74, 68, 48, 12, -19, -14, 14, 46, 74, 81, 75, 64, 52, 48, 56, 67, 82, 78, 44, 9, -12, -20, -8, 18, 41, 57, 46, 23, 0, -23, -33, -21, -10, -10, -2, 3, 5, -2, -19, -33, -32, -24, -16, -11, -14, -6, 7, -2, -20, -25, -16, -6, 6, 17, 27, 22, 2, -10, -11, 0, 24, 51, 68, 79, 65, 25, -19, -49, -48, -30, -9, 8, 10, -12, -40, -57, -57, -34, -1, 25, 24, -7, -56, -95, -111, -102, -84, -69, -57, -44, -42, -59, -74, -71, -47, -17, 0, 3, -6, -21, -37, -38, -27, -6, 15, 23, 22, 12, -4, -23, -32, -26, 1, 36, 63, 82, 78, 46, 12, -1, 2, 20, 41, 64, 81, 79, 66, 59, 61, 67, 75, 76, 66, 49, 27, 5, -7, 2, 24, 41, 44, 38, 28, 13, -5, -19, -21, -17, -11, -2, 4, 4, -2, -14, -28, -32, -27, -21, -16, -13, -1, 6, -4, -21, -25, -17, -7, 6, 0, 0, -4, -4, -5, -8, -4, 3, 8, 6, 1, 1, 2, 3, 3, -2, -7, -11, -10, -5, -2, 4, 6, 0, -2, -5, -4, -4, -9, -9, -7, -11, -11, -10, -7, 4, 0, -4, -4, -1, 4, 0, -4, -3, -5, -6, -5, -4, 4, -1, 2, 11, 5, -13, -20, -30, -49, -50, -34, -22, -33, -27, -20, -17, 0, 34, 70, 73, 42, 3, -26, -37, -25, -1, 25, 48, 71, 75, 44, 22, 45, 69, 57, 44, 52, 58, 24, -23, -41, -50, -58, -67, -82, -66, -29, -29, -41, -34, -19, -4, -4, -1, 20, 50, 56, 35, 12, 4, -8, -15, 4, 28, 44, 46, 34, 17, 2, 0, 11, 28, 42, 22, -28, -51, -45, -34, -39, -37, -19, -17, -30, -32, -18, -4, 9, 19, 38, 35, 3, -24, -35, -40, -23, -11, -25, -47, -52, -51, -58, -61, -52, -47, -37, -17, -5, -5, -16, -31, -24, -11, -1, -3, -23, -40, -48, -40, -12, 15, 25, 17, -5, -2, 14, 21, 15, -12, -26, -18, -2, 28, 48, 55, 52, 42, 35, 35, 42, 38, 36, 40, 53, 55, 52, 44, 36, 49, 57, 56, 57, 55, 50, 39, 27, 31, 30, 15, 11, 12, 6, 4, 14, 28, 23, 1, -6, -17, -35, -44, -41, -33, -22, -9, -6, -12, -15, -13, -27, -29, -7, 14, -5, -55, -71, -49, -33, -37, -46, -33, -18, -43, -89, -96, -65, -23, 2, 8, 20, 24, -11, -50, -51, -12, 15, 4, 1, 20, 47, 53, 43, 52, 77, 98, 114, 110, 100, 88, 53, 10, -29, -55, -71, -83, -77, -58, -55, -57, -52, -48, -47, -46, -12, 34, 59, 52, 25, -10, -33, -21, 18, 49, 54, 46, 18, 13, 30, 41, 48, 54, 53, 44, 24, 1, -13, -25, -43, -38, -28, -35, -55, -71, -64, -40, -13, 10, 24, 38, 41, 21, -1, -11, 1, 15, 7, -6, -13, -39, -57, -64, -51, -20, -12, -24, -37, -30, -4, 17, 21, 12, -7, -16, -15, -7, 6, 1, -20, -34, -30, -1, 32, 44, 36, 22, 25, 21, 6, 1, -2, -13, -5, 19, 28, 24, 12, 11, 16, 19, 38, 54, 49, 38, 28, 28, 39, 52, 49, 32, 25, 33, 45, 49, 39, 40, 46, 20, -9, -6, 6, 1, -22, -29, 10, 48, 33, -17, -51, -55, -44, -49, -50, -36, -33, -57, -84, -71, -21, 11, 13, 4, -1, -8, -32, -45, -32, -10, 2, -13, -37, -39, -42, -57, -65, -63, -36, -11, 10, 33, 22, -12, -34, -28, -12, 2, 8, 6, -2, -4, 0, 10, 22, 36, 57, 82, 104, 122, 127, 109, 70, 17, -28, -45, -36, -20, -33, -68, -102, -114, -103, -76, -45, -20, -7, -11, -10, -2, 6, 0, -14, -5, 30, 48, 29, 3, -8, 10, 39, 67, 86, 83, 59, 32, 17, 32, 46, 40, 11, -29, -48, -57, -68, -69, -57, -43, -26, -13, -2, 1, 1, 3, 4, 8, 21, 20, 11, 3, -2, -6, -26, -39, -33, -34, -36, -28, -23, -27, -28, -17, -1, 0, -6, -10, -9, -7, -12, -26, -44, -54, -38, -16, 0, 18, 27, 17, -3, -18, -3, 19, 11, -9, -7, 10, 14, 5, 5, 18, 29, 29, 12, 16, 38, 43, 14, 2, 24, 55, 59, 33, 17, 24, 44, 65, 75, 77, 55, 15, -16, -20, 6, 31, 27, 17, 18, 19, 17, 7, 0, -5, -20, -22, -25, -49, -69, -73, -58, -45, -29, -4, 9, -1, -23, -51, -52, -24, -2, 11, 12, -16, -51, -75, -77, -67, -59, -59, -54, -35, -15, -9, -9, -9, -7, -8, -12, -1, 15, 22, 10, -14, -34, -28, -14, 11, 64, 113, 127, 117, 97, 87, 84, 68, 50, 37, 36, 24, -15, -58, -78, -84, -71, -40, -14, -12, -34, -48, -41, -14, 20, 37, 35, 16, -6, 1, 14, 15, 20, 23, 24, 38, 58, 69, 57, 40, 54, 73, 75, 65, 40, -3, -49, -68, -56, -42, -42, -53, -59, -44, -23, -9, -3, -11, -18, -13, -11, -5, 3, 13, 4, -25, -39, -22, -14, -16, -27, -38, -37, -42, -55, -51, -21, 8, 10, -8, -12, -4, -10, -39, -55, -38, -13, -4, -11, -15, -3, 15, 12, 2, 11, 28, 34, 15, -5, 3, 11, 6, 12, 25, 25, 13, 10, 15, 27, 48, 55, 38, 23, 17, 23, 32, 23, 32, 57, 75, 75, 52, 22, 10, 5, 12, 28, 33, 23, 2, -14, -4, 19, 30, 25, 15, 1, -27, -64, -78, -67, -49, -45, -48, -42, -31, -25, -40, -50, -39, -18, -4, 13, 19, 12, -10, -43, -59, -53, -47, -54, -61, -51, -20, -2, -12, -23, -25, -18, 5, 33, 51, 45, 16, -16, -46, -53, -38, -6, 33, 57, 74, 81, 75, 77, 89, 105, 114, 110, 83, 39, -6, -25, -28, -39, -48, -52, -55, -59, -67, -67, -57, -42, -23, -3, 10, 3, -19, -33, -30, -8, 20, 23, 2, -18, -17, 12, 40, 58, 65, 65, 66, 71, 64, 54, 38, 1, -41, -62, -47, -26, -31, -49, -55, -42, -21, -17, -19, -10, -2, -3, -10, -13, 2, 13, -10, -38, -27, 3, 8, -18, -46, -61, -65, -53, -36, -18, -5, -6, -14, -22, -18, -12, -19, -29, -28, -21, -10, -15, -24, -18, -4, 16, 23, 17, 14, 10, 9, 13, 15, 28, 35, 19, 4, 2, -2, 9, 34, 62, 66, 43, 13, -2, 15, 42, 50, 48, 51, 56, 56, 45, 44, 45, 48, 40, 33, 31, 27, 10, -10, -4, 16, 41, 52, 48, 31, -1, -36, -56, -50, -27, -14, -25, -43, -60, -67, -47, -31, -38, -47, -40, -17, 13, 32, 28, -10, -50, -68, -62, -40, -21, -20, -33, -58, -72, -63, -45, -28, -11, 18, 48, 42, 15, -14, -43, -54, -40, -15, 4, 2, -5, 0, 20, 55, 91, 113, 120, 109, 89, 77, 63, 43, 26, 20, 12, -13, -47, -69, -68, -53, -49, -49, -36, -28, -27, -27, -28, -12, 5, 1, -9, -2, 14, 10, -25, -39, -6, 21, 35, 41, 53, 73, 82, 74, 64, 54, 39, 9, -23, -37, -30, -22, -30, -52, -62, -54, -32, -9, 2, 5, -3, -17, -25, -17, -1, 13, 8, -7, -12, -7, -7, -21, -40, -51, -51, -38, -21, -16, -22, -29, -33, -23, -10, -2, -9, -24, -33, -33, -29, -21, -8, 3, 2, -10, -18, -11, 8, 26, 32, 27, 21, 14, 7, 1, 3, 12, 22, 35, 45, 43, 29, 13, 10, 20, 37, 54, 59, 45, 28, 28, 37, 48, 55, 60, 60, 43, 17, 0, -3, 9, 24, 31, 31, 28, 28, 26, 14, -5, -22, -31, -30, -21, -7, -8, -34, -63, -82, -80, -63, -45, -28, -14, -5, 3, 2, -11, -27, -39, -33, -11, 2, -8, -39, -73, -95, -91, -54, -8, 19, 16, 4, 5, 14, 14, 2, -8, -14, -19, -33, -45, -38, -19, 2, 21, 54, 93, 106, 90, 74, 80, 97, 98, 76, 52, 34, 10, -18, -37, -36, -27, -35, -52, -62, -56, -44, -39, -37, -29, -17, -8, -2, 3, 4, -4, -16, -27, -32, -19, 1, 19, 41, 60, 70, 71, 67, 64, 61, 53, 38, 14, -8, -21, -29, -34, -38, -39, -29, -15, 0, 5, -5, -19, -25, -16, 5, 19, 17, 6, -3, -7, 0, -1, 1, -2, -5, 0, 0, 2, 0, -3, -2, 0, 1, 0, -2, -2, -2, 0, 3, 3, -2, -5, -1, -1, -1, -4, 3, 9, 1, -1, -2, -11, -7, 1, 9, 11, 8, -4, -11, -12, -9, -4, 18, 15, 14, 1, -22, -29, -14, 3, 30, 29, 14, -2, -35, -43, -11, 13, 36, 42, 15, -16, -49, -44, -10, 28, 47, 38, 11, -25, -66, -39, 4, 36, 58, 33, -3, -44, -65, -29, 19, 52, 54, 23, -13, -59, -65, -15, 32, 69, 49, 8, -30, -74, -51, 3, 43, 71, 40, -5, -48, -77, -31, 16, 57, 67, 24, -15, -67, -72, -12, 36, 66, 59, 5, -31, -80, -51, 3, 49, 75, 37, -2, -59, -81, -28, 20, 67, 66, 22, -23, -76, -65, -10, 41, 78, 48, 4, -36, -85, -47, 6, 59, 80, 31, -8, -69, -82, -22, 29, 73, 63, 17, -31, -81, -63, -1, 47, 79, 47, 3, -56, -90, -40, 19, 75, 73, 28, -25, -86, -74, -10, 48, 85, 56, 6, -51, -93, -48, 11, 67, 86, 33, -11, -78, -87, -29, 36, 89, 66, 13, -38, -91, -60, 2, 50, 83, 48, 0, -56, -90, -41, 16, 71, 78, 30, -17, -80, -75, -20, 31, 82, 62, 15, -32, -85, -66, -7, 48, 84, 50, 4, -53, -87, -44, 8, 62, 78, 35, -8, -65, -83, -30, 23, 70, 71, 24, -20, -76, -75, -12, 32, 73, 62, 15, -30, -85, -62, -2, 41, 76, 51, 9, -39, -86, -52, 1, 45, 79, 46, 8, -49, -89, -46, 3, 54, 80, 43, 7, -55, -83, -50, 0, 53, 76, 54, 11, -52, -83, -55, 0, 40, 67, 58, 22, -32, -79, -67, -11, 28, 63, 52, 37, -9, -70, -63, -28, 10, 42, 49, 53, 8, -46, -64, -41, 1, 22, 38, 51, 39, -16, -63, -46, -23, 5, 33, 38, 48, 14, -42, -57, -29, -5, 22, 37, 40, 28, -23, -53, -39, -10, 14, 30, 40, 31, -1, -48, -40, -18, 11, 19, 31, 26, 14, -20, -50, -25, -5, 11, 31, 30, 14, 0, -35, -39, -4, -1, 19, 27, 17, 9, -10, -39, -21, -8, 9, 24, 26, 13, -5, -19, -30, -12, -1, 17, 25, 16, 3, -19, -26, -13, -6, 17, 22, 20, 5, -16, -32, -19, -1, 23, 27, 23, 4, -30, -33, -23, -1, 35, 35, 24, -2, -41, -45, -21, 9, 45, 41, 22, -12, -50, -46, -18, 28, 55, 45, 10, -27, -78, -42, 0, 53, 66, 32, -1, -61, -74, -28, 27, 64, 64, 24, -28, -80, -66, -15, 53, 84, 48, 5, -59, -94, -41, 17, 75, 80, 26, -21, -91, -79, -12, 48, 87, 55, 10, -58, -96, -46, 9, 80, 81, 30, -23, -84, -80, -15, 49, 90, 49, 9, -57, -95, -45, 17, 76, 79, 26, -20, -91, -75, -18, 52, 90, 52, 6, -59, -92, -41, 15, 68, 80, 31, -21, -87, -76, -13, 45, 87, 49, 11, -60, -94, -35, 14, 80, 68, 22, -23, -89, -66, -7, 47, 93, 44, -8, -61, -95, -31, 24, 86, 75, 10, -35, -96, -66, -1, 61, 100, 44, -12, -77, -105, -33, 32, 97, 92, 16, -44, -111, -90, -5, 65, 121, 65, -3, -80, -123, -59, 17, 98, 111, 46, -25, -112, -109, -33, 42, 112, 90, 30, -55, -115, -84, -17, 66, 105, 71, 13, -73, -113, -61, 0, 77, 96, 56, 4, -80, -108, -50, 8, 78, 93, 47, 3, -88, -98, -40, 7, 65, 76, 53, 18, -71, -90, -44, 0, 39, 57, 43, 34, -19, -69, -54, -19, 18, 32, 31, 34, 7, -40, -36, -21, -1, 12, 12, 25, 27, -9, -32, -14, -14, 2, 0, 1, 20, 19, -2, -13, -11, -18, -12, -2, 18, 24, 12, -2, -14, -19, -19, -12, 18, 24, 22, -2, -15, -32, -20, 3, 22, 26, 17, -13, -31, -27, -13, 17, 33, 32, 5, -29, -47, -29, 2, 33, 42, 32, -6, -53, -52, -24, 22, 51, 41, 27, -32, -74, -45, 0, 45, 59, 33, -1, -62, -66, -31, 26, 73, 49, 17, -42, -80, -42, -8, 63, 72, 28, -10, -75, -72, -23, 32, 88, 47, 13, -56, -93, -38, 10, 76, 69, 26, -20, -96, -66, -10, 48, 90, 47, 0, -69, -103, -29, 25, 87, 73, 18, -35, -104, -68, -2, 61, 93, 47, -5, -83, -98, -31, 30, 92, 68, 17, -39, -97, -63, -5, 64, 88, 35, -9, -74, -86, -22, 31, 85, 54, 13, -44, -93, -46, 9, 65, 75, 23, -17, -75, -78, -15, 39, 84, 54, 3, -52, -96, -46, 12, 71, 90, 29, -18, -89, -87, -26, 36, 86, 72, 26, -37, -106, -77, -12, 45, 99, 68, 22, -46, -108, -73, -10, 43, 87, 69, 19, -27, -92, -79, -12, 27, 63, 57, 26, 4, -53, -75, -35, 12, 33, 37, 31, 26, -9, -53, -39, -16, 6, 20, 23, 22, 13, -8, -22, -23, -18, -3, 9, 25, 19, 4, -8, -20, -17, -10, 6, 16, 17, 13, -8, -34, -21, -6, 17, 33, 23, 6, -32, -51, -23, 11, 36, 46, 31, -11, -46, -65, -31, 15, 59, 55, 28, -20, -73, -64, -26, 42, 78, 51, 14, -53, -85, -48, -4, 70, 80, 38, -16, -80, -76, -32, 39, 90, 58, 19, -59, -99, -50, 14, 71, 75, 36, -21, -94, -70, -23, 51, 88, 53, 9, -68, -97, -40, 16, 83, 73, 29, -33, -100, -61, -13, 58, 87, 41, 0, -74, -81, -35, 24, 87, 55, 20, -41, -88, -58, 0, 69, 73, 34, -5, -86, -75, -20, 38, 79, 49, 13, -48, -90, -39, 2, 71, 68, 31, -16, -84, -67, -15, 38, 79, 42, 12, -50, -85, -37, 2, 62, 71, 34, -5, -83, -75, -24, 27, 82, 51, 27, -30, -88, -54, -15, 44, 73, 50, 16, -49, -81, -47, -6, 38, 58, 50, 27, -31, -69, -52, -13, 15, 36, 45, 33, -5, -41, -44, -23, 2, 14, 27, 33, 10, -25, -20, -18, -6, 1, -1, 17, 22, 3, -13, -10, -17, -13, -6, 13, 24, 15, 1, -11, -19, -19, -16, 12, 24, 24, 3, -12, -29, -26, -1, 18, 27, 19, -4, -31, -28, -19, 11, 30, 35, 12, -21, -46, -35, -6, 28, 42, 36, 5, -46, -57, -31, 10, 50, 43, 33, -16, -71, -55, -9, 35, 62, 38, 10, -51, -71, -40, 11, 69, 58, 24, -26, -81, -50, -18, 48, 79, 37, 1, -62, -81, -32, 16, 84, 59, 20, -37, -96, -50, -2, 63, 78, 33, -4, -85, -80, -20, 33, 88, 59, 10, -50, -107, -47, 14, 75, 85, 27, -19, -95, -83, -15, 47, 94, 60, 8, -66, -105, -46, 15, 83, 81, 26, -23, -91, -76, -18, 48, 92, 47, 1, -59, -94, -36, 18, 78, 66, 19, -27, -91, -60, -3, 53, 80, 35, -8, -62, -86, -28, 27, 79, 66, 13, -38, -94, -62, 1, 56, 95, 42, -6, -75, -96, -39, 22, 80, 80, 36, -20, -97, -92, -24, 30, 93, 79, 32, -27, -102, -87, -22, 31, 81, 79, 29, -14, -81, -91, -25, 19, 56, 63, 31, 11, -39, -77, -47, 3, 31, 37, 33, 27, 3, -48, -46, -20, 0, 18, 22, 23, 16, -3, -20, -19, -15, -4, 2, 8, 5, 0, 0, 0, 0, 2, 2, 5, 9, 12, 14, 12, 7, 6, 4, 0, -1, -1, 1, -2, -2, -11, -17, -32, -41, -49, -55, -58, -61, -61, -65, -61, -57, -47, -37, -27, -22, -15, -5, 6, 12, 16, 21, 27, 28, 32, 33, 35, 41, 44, 45, 47, 50, 54, 57, 56, 53, 53, 54, 50, 50, 52, 54, 56, 52, 53, 54, 50, 49, 46, 43, 38, 33, 27, 19, 8, 2, -11, -20, -27, -29, -30, -32, -35, -42, -52, -57, -57, -59, -48, -40, -27, -13, 4, 13, 20, 18, 14, 11, 7, 3, -1, -3, -10, -11, -20, -28, -46, -60, -72, -82, -92, -97, -97, -97, -94, -90, -81, -71, -61, -55, -55, -53, -47, -38, -29, -23, -11, -6, -3, 1, 2, 5, 6, 3, 3, 5, 15, 24, 28, 30, 30, 35, 37, 36, 39, 39, 44, 47, 48, 56, 62, 73, 84, 91, 96, 95, 91, 85, 76, 72, 63, 55, 47, 44, 43, 41, 38, 31, 19, 7, 0, -9, -7, -4, 8, 22, 40, 54, 67, 71, 70, 64, 56, 45, 32, 24, 15, 12, 3, -3, -21, -42, -66, -84, -102, -117, -124, -128, -127, -124, -118, -107, -96, -86, -86, -88, -86, -80, -70, -63, -50, -40, -33, -25, -23, -20, -18, -18, -21, -25, -22, -14, -8, -3, -3, -1, 1, 0, 1, -3, -1, 2, 4, 13, 24, 35, 49, 59, 67, 70, 69, 68, 59, 54, 46, 40, 31, 29, 27, 25, 23, 20, 12, -1, -9, -19, -22, -21, -11, 3, 23, 41, 60, 71, 76, 73, 71, 65, 56, 50, 44, 42, 35, 33, 24, 9, -13, -31, -48, -65, -76, -83, -83, -82, -77, -69, -59, -46, -40, -40, -41, -38, -30, -24, -13, -2, 8, 17, 22, 24, 25, 23, 20, 13, 9, 11, 15, 19, 16, 12, 9, 4, 1, -6, -10, -11, -14, -12, -5, 3, 15, 26, 35, 40, 41, 41, 35, 28, 19, 12, 3, -2, -6, -7, -10, -13, -19, -31, -39, -50, -56, -58, -52, -41, -22, -3, 18, 34, 46, 48, 47, 45, 38, 32, 26, 24, 20, 19, 15, 5, -14, -32, -49, -65, -79, -88, -91, -91, -88, -82, -75, -63, -52, -47, -46, -46, -38, -31, -21, -8, 4, 17, 26, 31, 36, 39, 42, 40, 35, 36, 39, 47, 48, 45, 43, 38, 36, 30, 24, 22, 19, 18, 23, 29, 40, 50, 61, 68, 72, 74, 71, 66, 57, 50, 40, 32, 24, 21, 16, 12, 7, -3, -14, -26, -38, -45, -46, -43, -31, -16, 3, 18, 33, 39, 39, 36, 31, 22, 13, 8, 3, -1, -4, -9, -24, -42, -60, -77, -94, -107, -115, -119, -120, -116, -112, -103, -91, -81, -78, -80, -75, -69, -61, -51, -39, -25, -13, -5, 2, 8, 14, 17, 16, 15, 16, 24, 31, 32, 32, 29, 29, 27, 22, 21, 20, 19, 22, 26, 35, 46, 59, 70, 77, 83, 85, 84, 79, 74, 66, 59, 50, 46, 41, 38, 35, 29, 21, 11, 0, -9, -14, -16, -11, 0, 16, 30, 48, 58, 62, 61, 58, 51, 40, 31, 25, 19, 15, 13, 4, -11, -28, -44, -61, -76, -87, -95, -100, -100, -99, -95, -86, -75, -68, -69, -68, -67, -62, -56, -49, -38, -27, -19, -13, -9, -3, 2, 1, -1, -3, 0, 7, 10, 10, 6, 5, 4, 0, -4, -5, -7, -7, -7, -2, 5, 16, 27, 36, 44, 49, 52, 50, 46, 40, 35, 26, 22, 18, 15, 15, 13, 9, 4, -5, -14, -19, -23, -21, -14, 0, 15, 33, 49, 60, 63, 63, 61, 53, 44, 38, 32, 27, 27, 23, 14, 0, -14, -29, -44, -58, -67, -74, -76, -76, -73, -67, -55, -45, -41, -41, -41, -39, -35, -30, -23, -12, -3, 4, 9, 14, 20, 21, 20, 17, 15, 19, 24, 26, 24, 21, 20, 18, 12, 9, 6, 3, 0, 1, 4, 11, 21, 30, 38, 43, 47, 48, 45, 38, 32, 23, 15, 9, 5, 3, 1, -2, -5, -13, -22, -30, -37, -41, -40, -30, -18, -3, 15, 30, 38, 41, 41, 37, 27, 19, 12, 6, 3, 2, -2, -13, -25, -39, -53, -67, -78, -88, -92, -92, -91, -86, -77, -63, -54, -50, -48, -47, -43, -38, -32, -23, -11, -1, 6, 11, 19, 25, 27, 26, 24, 26, 31, 36, 38, 36, 37, 37, 34, 32, 29, 27, 24, 22, 23, 27, 35, 45, 53, 61, 67, 70, 71, 66, 60, 51, 42, 34, 28, 24, 21, 18, 16, 11, 2, -8, -16, -24, -28, -25, -17, -5, 10, 26, 39, 45, 47, 45, 37, 27, 18, 9, 3, 0, -2, -10, -22, -36, -51, -67, -81, -93, -102, -107, -108, -107, -102, -90, -78, -71, -67, -66, -63, -59, -56, -49, -39, -28, -19, -13, -6, 1, 7, 8, 6, 5, 8, 14, 19, 19, 19, 20, 20, 19, 16, 15, 13, 12, 11, 13, 20, 30, 39, 49, 57, 63, 68, 68, 65, 58, 51, 43, 37, 32, 29, 27, 26, 24, 19, 11, 2, -5, -12, -14, -9, 0, 13, 30, 46, 56, 62, 65, 61, 53, 44, 35, 26, 22, 20, 15, 6, -6, -20, -36, -51, -66, -78, -87, -91, -92, -92, -85, -74, -65, -58, -56, -55, -52, -50, -46, -40, -30, -20, -14, -8, -2, 5, 7, 6, 3, 2, 5, 10, 11, 10, 9, 9, 8, 5, 2, 0, -2, -5, -5, -3, 5, 14, 23, 32, 39, 46, 50, 49, 45, 38, 31, 24, 17, 14, 11, 10, 9, 7, 2, -5, -12, -20, -25, -25, -19, -8, 7, 24, 40, 50, 58, 60, 56, 49, 41, 31, 24, 22, 20, 15, 6, -5, -19, -34, -48, -61, -72, -79, -83, -85, -81, -72, -62, -52, -47, -44, -41, -39, -35, -31, -24, -13, -5, 1, 7, 14, 20, 22, 21, 19, 18, 22, 25, 25, 24, 23, 23, 20, 17, 15, 12, 10, 7, 5, 9, 16, 24, 33, 40, 47, 53, 56, 54, 48, 41, 33, 25, 20, 15, 11, 9, 8, 5, -2, -10, -19, -27, -32, -31, -25, -15, 0, 17, 30, 40, 46, 46, 42, 35, 25, 15, 10, 9, 5, -2, -11, -23, -37, -52, -65, -79, -89, -95, -99, -100, -95, -85, -74, -65, -60, -55, -52, -48, -44, -40, -29, -18, -10, -4, 4, 12, 18, 20, 19, 17, 20, 24, 27, 27, 26, 26, 25, 23, 21, 19, 17, 15, 12, 13, 17, 25, 34, 41, 49, 57, 62, 65, 63, 57, 51, 42, 35, 30, 25, 22, 21, 19, 15, 8, 0, -9, -17, -21, -20, -14, -3, 13, 26, 38, 48, 53, 52, 47, 39, 28, 19, 15, 13, 8, 0, -10, -22, -37, -51, -65, -79, -88, -95, -100, -99, -94, -84, -74, -67, -61, -58, -55, -51, -49, -43, -33, -23, -17, -10, -2, 6, 10, 11, 9, 9, 12, 15, 17, 16, 16, 16, 14, 12, 11, 9, 8, 5, 3, 4, 10, 18, 26, 34, 42, 50, 57, 59, 57, 52, 45, 38, 32, 27, 23, 21, 20, 19, 14, 8, 1, -9, 2, 5, 7, 8, -1, 6, 15, 1, 20, 28, 1, 37, 41, 31, 29, 27, 61, 40, -12, 38, 52, -16, -20, -1, -23, -48, -56, -63, -61, -77, -100, -88, -76, -103, -113, -98, -103, -118, -120, -108, -107, -104, -110, -118, -104, -109, -128, -107, -83, -106, -86, -94, -100, -77, -113, -88, -43, -77, -46, -44, -69, -34, -54, -39, 4, -30, 11, 18, -25, 20, 16, 10, 52, 35, 52, 74, 33, 55, 74, 59, 70, 81, 85, 91, 81, 72, 89, 94, 82, 80, 99, 100, 85, 86, 91, 100, 91, 81, 91, 102, 83, 74, 92, 95, 63, 62, 75, 71, 63, 39, 54, 74, 15, 1, 31, 6, -5, -13, -20, -8, -44, -59, -38, -69, -73, -67, -86, -90, -68, -73, -77, -49, -82, -70, -43, -76, -27, 0, -29, 22, 25, -5, 44, 45, 29, 66, 71, 49, 84, 92, 73, 92, 74, 72, 91, 37, 48, 99, 47, 31, 44, 36, 33, -5, -11, 26, 6, -33, -22, -6, -32, -55, -44, -45, -52, -63, -73, -55, -51, -77, -79, -61, -73, -91, -83, -70, -77, -74, -82, -85, -68, -88, -98, -57, -67, -77, -58, -75, -66, -64, -78, -33, -37, -50, -19, -47, -38, -23, -41, 3, 6, -7, 30, 0, -4, 24, 15, 31, 45, 44, 66, 44, 34, 58, 54, 59, 67, 71, 87, 78, 60, 73, 84, 78, 76, 86, 95, 89, 76, 85, 94, 89, 73, 82, 99, 85, 66, 75, 93, 75, 50, 56, 69, 59, 31, 31, 61, 29, -15, 15, 5, -15, -14, -36, -25, -29, -69, -55, -53, -82, -78, -76, -95, -88, -69, -80, -65, -63, -86, -58, -67, -59, -12, -28, -9, 29, -8, 13, 44, 22, 44, 68, 53, 62, 91, 74, 81, 89, 64, 84, 78, 35, 78, 86, 44, 43, 47, 45, 22, -5, 17, 21, -16, -24, -14, -14, -34, -50, -40, -36, -63, -71, -58, -60, -69, -78, -78, -67, -81, -98, -78, -71, -89, -85, -84, -86, -82, -99, -82, -60, -76, -75, -74, -76, -71, -86, -68, -37, -51, -34, -41, -57, -37, -51, -31, -7, -17, -3, 1, 7, 22, 31, 46, 57, 41, 43, 56, 63, 62, 68, 85, 86, 80, 84, 92, 96, 93, 93, 104, 105, 96, 99, 108, 106, 102, 98, 102, 111, 99, 87, 106, 110, 85, 80, 88, 89, 79, 68, 70, 81, 48, 25, 39, 32, 18, 9, 12, 0, -29, -31, -38, -60, -52, -63, -79, -71, -66, -62, -59, -62, -74, -72, -73, -81, -43, -21, -28, 8, 10, -10, 16, 28, 27, 42, 50, 47, 66, 76, 68, 81, 73, 67, 72, 39, 40, 67, 41, 23, 25, 22, 12, -16, -22, -5, -27, -51, -44, -45, -57, -68, -73, -71, -74, -91, -89, -84, -90, -97, -98, -98, -102, -105, -108, -103, -97, -105, -109, -101, -107, -113, -106, -92, -87, -90, -92, -92, -92, -100, -92, -57, -56, -54, -40, -59, -58, -54, -61, -23, -9, -12, 16, 0, -14, 4, 5, 17, 32, 41, 57, 55, 43, 54, 66, 67, 68, 84, 89, 87, 87, 91, 98, 100, 96, 104, 109, 105, 103, 108, 111, 109, 105, 105, 113, 111, 99, 102, 115, 104, 88, 90, 97, 93, 80, 75, 86, 75, 37, 40, 43, 33, 20, 20, -14, -26, -36, -53, -52, -65, -75, -75, -69, -69, -69, -74, -77, -76, -74, -59, -34, -26, -9, 9, 5, 13, 32, 39, 42, 53, 58, 61, 73, 77, 77, 73, 61, 57, 46, 29, 37, 37, 17, 6, 2, -10, -27, -38, -41, -46, -58, -68, -69, -75, -85, -89, -92, -97, -101, -103, -106, -107, -108, -112, -111, -112, -115, -115, -115, -113, -111, -116, -115, -112, -116, -117, -110, -101, -98, -101, -101, -98, -101, -101, -86, -69, -65, -59, -57, -62, -58, -54, -39, -19, -12, 1, 7, -1, 5, 16, 24, 36, 46, 58, 64, 61, 64, 74, 79, 81, 90, 96, 97, 100, 100, 104, 108, 107, 111, 114, 113, 115, 115, 115, 118, 117, 116, 118, 119, 116, 115, 116, 117, 111, 104, 105, 107, 99, 93, 95, 91, 71, 57, 53, 47, 38, 29, 23, 14, -11, -28, -38, -49, -58, -67, -73, -80, -84, -84, -83, -82, -80, -78, -74, -67, -56, -42, -29, -16, -4, 7, 18, 29, 40, 49, 57, 64, 70, 74, 78, 79, 77, 72, 67, 60, 53, 48, 42, 33, 23, 14, 4, -6, -16, -24, -32, -40, -48, -55, -61, -68, -74, -78, -83, -87, -91, -94, -96, -99, -101, -103, -104, -106, -107, -107, -107, -107, -107, -108, -107, -107, -107, -105, -101, -98, -96, -94, -93, -91, -87, -82, -74, -67, -62, -57, -54, -49, -43, -35, -25, -16, -7, -1, 4, 10, 17, 25, 33, 41, 49, 55, 59, 63, 69, 74, 78, 83, 88, 91, 93, 96, 98, 100, 102, 104, 106, 107, 107, 108, 108, 109, 109, 108, 108, 108, 107, 105, 104, 102, 99, 94, 91, 87, 83, 78, 73, 66, 56, 46, 37, 28, 19, 9, 0, -11, -23, -35, -45, -55, -64, -71, -78, -83, -85, -84, -83, -81, -79, -75, -70, -61, -49, -36, -23, -10, 2, 12, 24, 35, 45, 53, 61, 67, 72, 76, 79, 78, 75, 70, 65, 58, 52, 46, 39, 29, 20, 11, 1, -9, -18, -26, -34, -42, -50, -56, -63, -69, -74, -79, -83, -88, -91, -94, -96, -98, -101, -102, -104, -105, -106, -106, -106, -106, -106, -106, -106, -106, -105, -102, -98, -96, -94, -92, -90, -88, -84, -77, -70, -64, -59, -55, -51, -45, -38, -29, -20, -11, -4, 2, 7, 13, 21, 29, 37, 44, 51, 56, 60, 65, 70, 75, 80, 84, 88, 91, 93, 96, 98, 100, 102, 104, 105, 106, 107, 107, 108, 108, 107, 107, 107, 106, 104, 103, 101, 99, 95, 91, 87, 83, 78, 73, 67, 59, 49, 39, 30, 21, 12, 3, -8, -19, -31, -41, -51, -60, -68, -75, -81, -84, -85, -84, -82, -80, -77, -73, -65, -55, -42, -29, -16, -4, 7, 18, 29, 40, 49, 57, 64, 70, 74, 78, 79, 77, 73, 68, 62, 56, 50, 44, 36, 26, 17, 7, -3, -12, -20, -28, -36, -44, -51, -58, -64, -70, -75, -79, -84, -88, -91, -93, -96, -98, -100, -102, -103, -105, -105, -105, -105, -105, -105, -105, -105, -104, -102, -99, -96, -94, -92, -90, -88, -85, -79, -72, -66, -61, -56, -52, -47, -41, -33, -24, -15, -8, -1, 4, 10, 17, 24, 32, 40, 47, 53, 57, 62, 67, 72, 77, 81, 85, 89, 91, 94, 96, 98, 100, 102, 104, 105, 105, 106, 106, 107, 106, 106, 106, 105, 104, 102, 101, 99, 95, 91, 87, 83, 79, 74, 68, 61, 52, 42, 33, 24, 15, 5, -5, -15, -27, -38, -48, -57, -66, -72, -79, -83, -85, -85, -83, -81, -79, -75, -69, -60, -48, -35, -23, -10, 2, 13, 24, 35, 45, 54, 61, 67, 72, 77, 78, 79, 76, 72, 66, 60, 54, 49, 41, 32, 23, 12, 3, -4, -17, -15, 1, -1, 0, 0, 1, 3, 5, 9, 13, 18, 24, 32, 38, 32, 18, -9, -48, -73, -41, 2, -3, -24, -34, -44, -72, -111, -124, -62, 40, 40, -51, -35, 45, 46, -22, -79, 35, 78, -47, -98, -88, -69, -57, -44, -31, -17, -9, -3, 6, 41, 85, 43, -91, -128, -65, -25, -21, -19, -12, 2, 16, 29, 39, 49, 48, 10, -69, -47, 50, 8, -52, -44, 5, 21, -40, -42, 33, 79, 66, 38, 24, 25, 26, 18, 21, 70, 117, 98, 28, -1, 20, 22, 0, 1, 9, -10, -49, -33, 39, 68, 39, -5, -17, -58, -76, 78, 104, 17, 6, -23, -43, -13, 58, 85, 43, 21, 35, 46, 31, 22, 35, 14, -48, -74, -38, 6, 10, -8, -17, -24, -37, -60, -69, -41, 15, 27, -21, -26, 18, 28, -1, -41, 5, 51, -9, -51, -48, -38, -31, -24, -16, -8, -2, 1, 6, 23, 52, 41, -39, -83, -50, -19, -13, -12, -8, 1, 10, 20, 27, 34, 35, 15, -40, -46, 27, 16, -35, -38, -6, 19, -18, -35, 17, 61, 55, 33, 21, 22, 25, 21, 18, 52, 98, 92, 31, -5, 9, 17, -1, -2, 7, -7, -47, -43, 24, 62, 39, -3, -20, -48, -88, 46, 113, 25, 4, -20, -45, -25, 42, 82, 47, 19, 28, 42, 32, 18, 30, 19, -39, -77, -51, -4, 10, -6, -18, -25, -37, -57, -70, -50, 4, 26, -15, -33, 9, 27, 6, -38, -12, 50, 6, -47, -50, -40, -32, -25, -17, -10, -3, 0, 4, 17, 45, 47, -23, -82, -60, -24, -14, -13, -10, -2, 7, 16, 24, 30, 33, 18, -32, -56, 13, 23, -31, -41, -15, 19, -6, -35, 4, 52, 55, 35, 21, 22, 25, 22, 15, 41, 89, 94, 38, -5, 4, 16, 2, -2, 7, -4, -41, -48, 12, 58, 43, 2, -20, -38, -89, 14, 118, 38, 3, -15, -43, -32, 28, 78, 53, 19, 24, 40, 34, 18, 26, 23, -28, -75, -61, -14, 10, -2, -16, -24, -34, -53, -68, -55, -7, 25, -8, -36, 1, 27, 12, -31, -26, 45, 22, -39, -50, -41, -32, -25, -17, -10, -4, 0, 3, 13, 38, 51, -5, -77, -69, -31, -15, -14, -11, -4, 5, 13, 21, 27, 31, 20, -24, -61, -3, 28, -23, -43, -23, 15, 5, -32, -6, 43, 53, 36, 22, 21, 26, 24, 14, 32, 79, 95, 46, -3, 0, 15, 5, -1, 7, -1, -36, -52, 2, 53, 46, 7, -18, -30, -84, -15, 114, 55, 4, -10, -40, -37, 15, 72, 59, 22, 20, 36, 36, 19, 23, 26, -18, -70, -68, -25, 7, 2, -13, -22, -32, -49, -65, -59, -16, 22, -1, -36, -8, 25, 17, -22, -35, 34, 36, -29, -48, -42, -32, -25, -18, -10, -4, 0, 3, 10, 32, 52, 11, -67, -76, -38, -16, -13, -11, -6, 3, 11, 19, 25, 30, 22, -15, -62, -19, 30, -14, -43, -30, 9, 13, -25, -15, 33, 51, 37, 23, 21, 26, 26, 15, 24, 68, 94, 54, 0, -3, 13, 8, 1, 8, 2, -30, -53, -8, 47, 49, 13, -16, -25, -75, -41, 102, 73, 6, -5, -36, -40, 2, 65, 64, 25, 18, 33, 37, 21, 21, 27, -8, -63, -73, -36, 2, 5, -10, -21, -30, -45, -62, -61, -25, 17, 5, -35, -17, 21, 21, -13, -39, 20, 46, -16, -46, -42, -32, -25, -17, -10, -4, 0, 3, 8, 27, 50, 25, -54, -81, -46, -19, -13, -12, -7, 1, 9, 17, 23, 28, 23, -8, -59, -35, 27, -5, -42, -35, 2, 20, -16, -20, 24, 47, 38, 24, 21, 27, 28, 17, 18, 58, 91, 62, 5, -6, 10, 10, 3, 9, 5, -24, -52, -17, 40, 50, 18, -13, -22, -64, -60, 83, 90, 12, -3, -31, -41, -8, 55, 67, 30, 17, 30, 37, 24, 19, 27, 1, -54, -75, -46, -4, 7, -7, -18, -28, -41, -58, -61, -32, 11, 10, -31, -24, 17, 23, -4, -39, 5, 52, -2, -42, -42, -32, -25, -17, -10, -4, 0, 3, 6, 22, 47, 35, -38, -82, -55, -23, -13, -12, -8, -1, 7, 15, 21, 26, 23, -1, -53, -48, 20, 5, -39, -39, -6, 22, -5, -22, 14, 43, 38, 25, 21, 27, 29, 19, 15, 47, 86, 68, 12, -7, 7, 11, 4, 10, 7, -18, -50, -25, 33, 51, 24, -10, -20, -52, -72, 58, 103, 21, -1, -26, -41, -17, 44, 67, 35, 16, 27, 36, 26, 18, 25, 8, -45, -76, -55, -13, 7, -3, -16, -26, -38, -55, -61, -38, 4, 13, -26, -30, 11, 25, 4, -36, -10, 51, 14, -37, -42, -33, -24, -17, -10, -4, 1, 3, 6, 18, 42, 42, -22, -80, -63, -28, -14, -12, -9, -3, 5, 12, 19, 24, 23, 3, -46, -58, 9, 14, -34, -41, -14, 21, 6, -21, 4, 36, 38, 26, 21, 26, 30, 22, 13, 37, 78, 73, 20, -7, 4, 11, 6, 10, 10, -11, -45, -33, 22, 49, 29, -4, -18, -40, -75, 23, 108, 40, 1, -18, -39, -26, 28, 65, 42, 17, 22, 34, 29, 18, 23, 15, -30, -71, -65, -27, 3, 2, -11, -22, -34, -49, -58, -45, -7, 13, -16, -35, -1, 24, 13, -23, -26, 37, 36, -20, -39, -34, -24, -17, -10, -4, 1, 3, 5, 12, 33, 46, 6, -64, -75, -40, -17, -12, -10, -5, 2, 9, 15, 20, 22, 10, -30, -65, -18, 20, -19, -42, -27, 11, 21, -8, -8, 22, 34, 27, 22, 26, 31, 27, 14, 22, 60, 75, 34, -4, -2, 8, 8, 11, 14, -2, -36, -42, 6, 44, 36, 4, -15, -26, -66, -24, 95, 71, 8, -10, -33, -32, 7, 56, 51, 21, 17, 29, 32, 20, 19, 20, -12, -59, -72, -45, -8, 5, -5, -17, -28, -42, -54, -50, -21, 9, -5, -36, -16, 19, 21, -7, -34, 12, 51, 4, -33, -34, -25, -17, -10, -4, 1, 4, 5, 9, 23, 44, 29, -39, -79, -55, -24, -13, -10, -7, -1, 6, 12, 16, 20, 14, -15, -62, -46, 16, -2, -39, -36, -2, 29, 9, -12, 8, 28, 27, 23, 25, 31, 31, 17, 13, 43, 72, 46, 2, -5, 5, 8, 11, 16, 5, -26, -44, -8, 36, 40, 12, -12, -19, -52, -53, 67, 94, 20, -5, -27, -35, -7, 45, 55, 27, 15, 25, 32, 23, 17, 21, 0, -47, -73, -57, -19, 4, 0, -13, -24, -37, -50, -51, -29, 3, 1, -32, -26, 12, 23, 3, -32, -6, 52, 22, -26, -34, -25, -17, -10, -4, 1, 5, 6, 8, 18, 39, 38, -21, -76, -64, -30, -14, -10, -8, -2, 4, 10, 15, 18, 14, -9, -56, -57, 7, 7, -35, -39, -10, 27, 18, -10, 2, 23, 26, 23, 24, 31, 32, 20, 11, 35, 67, 51, 7, -6, 3, 8, 11, 17, 8, -20, -44, -15, 31, 41, 16, -9, -17, -43, -61, 44, 102, 31, -2, -23, -35, -15, 36, 56, 32, 0, -27, 1, -1, -1, 3, -4, -2, 1, -1, -2, 2, 3, -6, 1, 2, -6, 2, 2, -4, -1, 2, -5, 1, 4, -4, 0, -1, 0, -1, -2, 2, 2, -6, 0, 4, -3, -3, 4, -2, -3, -2, 0, 1, 1, -2, -2, 3, -8, 27, -42, 11, 21, -35, 34, -25, 12, 9, -24, 14, 13, -38, 53, -42, -3, 46, -73, 55, -16, -9, 28, -49, 38, -12, -21, 49, -51, 20, 32, -73, 64, -28, -7, 32, -50, 42, -11, -30, 49, -21, -31, 46, -25, -7, 20, -22, 18, -16, -10, 21, -23, 5, 28, -35, 8, 0, 8, -26, 19, 6, -11, -20, 64, -46, -18, 51, -73, 119, -117, 46, 36, -80, 67, -46, 22, 0, -24, 56, -59, 14, 26, -40, 24, -9, 20, -20, -15, 43, -26, -11, 9, 14, -3, -31, 6, 54, -62, 3, 67, -78, 20, 21, -25, 31, -41, 18, 27, -53, 32, 15, -48, 37, -11, 4, -12, -3, 31, -24, -21, 42, -10, -45, 55, -32, 34, -43, -14, 86, -78, 8, 39, -35, -2, 13, 2, 5, -11, -4, 7, 5, -31, 37, -4, -28, 28, -9, -11, 10, -1, 4, -18, 17, -9, -13, 24, -18, 20, -18, -30, 59, -25, -29, 48, -15, -29, 23, 4, -3, -18, 14, 6, -8, -19, 19, 8, -13, 0, 13, -18, 4, 1, 0, 0, 10, -14, -12, 39, -46, 23, 9, -22, 23, -20, -22, 63, -42, -28, 77, -66, 12, 38, -56, 31, 27, -77, 66, -11, -39, 59, -33, -41, 92, -54, -50, 96, -36, -46, 46, -17, 31, -43, -28, 98, -57, -50, 84, -22, -44, 39, -8, 17, -28, -13, 63, -67, 16, 10, 3, -15, -4, 36, -34, -1, 26, -27, -2, 13, 7, -22, 0, 27, -11, -19, 6, 26, -42, 14, 18, -7, -14, -10, 37, -14, -24, 25, -4, -5, -10, 3, 35, -39, -7, 31, -8, -23, 15, 4, -1, -25, 28, 7, -35, 34, -16, -1, 9, -35, 45, -22, -17, 48, -52, 24, 22, -65, 48, 7, -45, 47, -19, -33, 71, -70, 46, -7, -52, 68, -25, -35, 48, -13, -17, 14, 2, -12, 8, -10, 1, 22, -32, 4, 34, -26, -18, 29, -7, -19, 15, -7, 15, -8, -29, 50, -22, -35, 53, -19, -37, 47, -9, -40, 41, 1, -27, 7, 3, 0, 0, -7, 13, -7, -21, 26, 14, -44, 11, 40, -51, 10, 26, -28, 16, -13, -3, 31, -42, 11, 34, -52, 11, 34, -43, 10, 29, -19, -21, 27, -10, -5, 10, -14, 11, 3, -35, 43, 3, -52, 37, 22, -66, 49, -12, -19, 50, -58, 16, 42, -70, 50, -2, -42, 60, -69, 43, 11, -57, 54, -8, -31, 23, -8, -7, 24, -32, 11, 21, -51, 60, -44, -6, 68, -87, 33, 45, -79, 50, -7, -13, 21, -40, 31, 12, -41, 18, 24, -39, 15, 7, -17, 25, -20, -12, 43, -47, 17, 6, -16, 10, 4, -11, -1, 14, -10, -7, 6, 9, -23, 9, 3, 13, -30, 16, 16, -33, 17, 4, -17, 23, -29, 3, 54, -86, 50, 11, -41, 30, -23, 15, 18, -60, 56, 7, -65, 49, -4, -12, 1, -6, 19, -4, -33, 35, -10, -12, 13, -2, -2, -2, 2, -10, 16, -8, -11, 19, -6, -19, 24, -14, 9, 3, -24, 24, -6, -13, 19, -11, -6, 6, -9, 16, -8, -10, 14, -10, -1, -5, 16, -8, -25, 37, -11, -27, 37, -14, -13, 19, -17, 14, -5, -15, 26, -27, 10, 11, -23, 22, -5, -19, 25, -7, -28, 44, -35, 0, 25, -31, 31, -10, -26, 46, -41, 2, 33, -40, 24, 8, -43, 44, -12, -25, 37, -25, -6, 29, -27, 5, 24, -40, 24, -1, -25, 23, -1, -6, -2, -1, 14, -24, 8, 13, -11, 0, -13, 16, 15, -56, 43, 12, -35, 14, -9, 18, -10, -19, 28, -3, -27, 23, -2, -14, 27, -35, 10, 35, -68, 44, 7, -43, 46, -21, -25, 56, -35, -21, 51, -33, -8, 28, -27, 19, -2, -26, 36, -26, 3, 13, -12, 6, -10, 8, -14, 15, -12, 0, 13, -9, -16, 32, -27, 3, 23, -49, 49, -17, -31, 63, -64, 25, 36, -76, 61, -11, -47, 75, -54, -9, 69, -81, 32, 29, -63, 46, -7, -26, 39, -31, 6, 18, -26, 13, -5, 5, -5, -2, 5, -12, 17, -17, -2, 22, -25, 1, 20, -19, 3, 6, -6, 3, -9, 10, -6, -3, 7, -7, -3, 12, -5, -5, -11, 24, -7, -23, 24, 0, -14, 0, 12, -10, -2, 5, 0, 1, -10, 10, -2, -17, 26, -11, -16, 28, -22, 6, 4, -17, 30, -27, -7, 46, -54, 15, 29, -42, 25, -4, -15, 26, -29, 11, 15, -28, 19, -7, 1, 8, -20, 14, 1, -15, 11, -2, -2, 0, -10, 15, -5, -12, 15, -1, -15, 12, 4, -15, 9, -1, -9, 9, -5, -6, 13, -12, 1, 6, -6, -3, 6, -4, 0, -6, 11, -9, -2, 13, -12, -2, -1, 8, -11, 4, 2, -6, 4, -4, 4, 0, -13, 15, 0, -21, 23, -5, -15, 15, -2, -9, 6, -2, -4, 2, 3, -1, -7, 7, -2, -9, 6, 2, -9, 4, 5, -12, 10, -9, 4, 5, -16, 12, -2, -13, 20, -13, -4, 17, -23, 14, 2, -20, 22, -13, -3, 15, -22, 12, 4, -18, 17, -7, -7, 13, -14, 6, 4, -10, 9, -5, -6, 7, 0, -7, 8, -4, -1, 0, -6, 4, 7, -14, 2, 13, -16, 3, 10, -15, 7, -1, -10, 14, -10, -2, 11, -9, -4, 7, -6, 3, -3, -5, 9, -6, -3, 5, 1, -7, 3, -2, 0, -2, 0, 4, -3, -2, 4, -6, 4, -2, -2, 0, 1, 0, -7, 7, -2, -7, 9, -7, -4, 11, -15, 11, -2, -9, 9, -4, -3, 2, 3, -7, 5, 0, -5, 6, -7, 1, 7, -10, -2, 13, -9, -4, 8, -4, -2, -1, 1, 1, -7, 4, 5, -8, 0, 6, -6, 0, 3, -4, 0, 1, -2, 2, -4, -4, 8, -7, -1, 6, -9, 8, -3, -6, 12, -12, 1, 10, -11, 1, 5, -6, 3, -2, -3, 7, -10, 2, 7, -12, 5, 2, -5, 3, -5, 0, 6, -10, 3, 4, -8, 2, 2, -3, 3, -8, 8, 2, -14, 10, 3, -12, 8, 2, -11, 8, -2, -6, 9, -7, -4, 10, -9, -1, 7, -7, 1, 3, -8, 8, -2, -8, 10, -3, -5, 5, -6, 3, 1, -8, 10, -5, -5, 7, -4, -2, 2, -3, 1, -1, -3, 4, -3, 0, 0, 0, 0, -4, 3, -2, -3, 3, -5, 3, 0, -7, 5, 1, -8, 5, 1, -6, 6, -5, 0, 3, -7, 3, 2, -6, 3, 2, -6, 3, 1, -3, -2, 5, -4, -1, 3, -4, 0, 0, -3, 5, -5, -3, 7, -5, -3, 6, -4, 0, -1, -3, 3, -2, -1, 2, -1, -2, 1, -2, 1, -1, -7, 8, -1, 5, -7, 13, -22, 8, -7, 8, -110, -28, 24, 54, 36, 2, 60, -45, 57, 42, -43, 20, 41, -66, 24, -11, 18, -18, -38, -63, -36, 30, -11, 33, 25, 30, 18, 11, -18, -5, 5, -46, 40, 1, -13, -18, -20, -31, 20, 10, 29, -7, -18, 40, -29, -17, 42, -19, 6, -4, 6, -8, 10, -26, -5, 3, 1, -17, 6, 0, 19, -1, 8, 0, -6, -10, -1, -12, -1, 1, -3, 8, -7, 4, 11, 4, 14, -13, 16, -19, -4, -13, -13, -14, 6, 4, -1, 4, 11, -1, 11, -1, 1, -4, -1, -15, 6, -9, 1, -1, 0, 3, 1, -8, 3, -1, -1, 2, -2, 2, -2, 1, -5, -7, 3, -3, 6, -3, 4, -1, 0, -4, 2, -7, 3, -6, -1, -1, 4, 0, 3, -2, 2, -5, 5, -8, -3, -3, 2, -5, 7, -1, 4, -2, 4, -10, 6, -6, -1, -4, 5, -13, 7, -6, 5, -8, 17, -20, 14, -6, 9, -40, 71, -127, 9, -73, 127, 76, -28, 74, -32, 8, -62, -49, -38, 40, -68, 22, -12, 68, 10, 39, -10, 0, 35, -23, 0, -59, -15, -7, -3, -23, 1, -20, 37, 27, 2, 30, -2, 17, 2, -5, -7, -27, -29, 16, -3, -11, 1, -16, -5, -8, -10, 7, 32, 9, 5, -4, 16, 5, -8, -17, -16, 5, -13, 8, 11, 15, -10, -9, 0, -1, 2, 7, -3, -23, 9, 2, 3, 1, -13, -1, -6, 11, -6, 8, 1, 12, -12, 9, -14, 8, -1, 0, -3, -13, 4, -7, -4, 8, 5, -5, -7, 4, -2, -3, 2, 3, -6, 8, -3, 1, -3, -2, 2, -6, 2, -4, -3, -4, 3, 1, 0, 0, 1, -1, -1, 2, -2, 0, -4, -2, 1, 2, 0, -3, 1, -3, 0, -1, -3, -6, 2, -2, 3, -4, 10, -8, 9, -5, 12, -19, 46, 37, -128, 60, -90, 102, -65, 40, -57, 39, -6, 23, -8, 19, 24, 15, -17, -47, -27, -36, -16, 21, 3, 23, 14, 50, -8, 19, 25, 7, -9, -28, -63, -37, 0, -42, 54, -17, 68, -3, 30, -12, -4, 11, -15, 9, -25, -15, -2, -27, -25, 38, -8, -13, 33, 24, 12, -38, 39, -12, -3, -17, -44, 38, 2, 27, 3, -5, -4, -13, -30, -56, -4, 11, 1, 9, 17, 46, 25, -14, 6, -3, -7, -21, 2, 16, -5, -22, 2, -2, 6, -12, -25, -15, 10, 9, 8, 11, 43, 8, -5, -22, -16, 14, -31, 16, 7, -7, -26, -20, -2, 9, 11, 26, 7, 6, -20, -13, 0, 4, 17, -17, -18, 10, 2, -10, 27, -8, 24, -23, -14, 1, 0, 13, -19, 14, 10, -16, 16, -4, -20, 20, -33, 2, 2, 24, 21, -3, -26, -24, -18, -18, 10, 10, 24, 18, 2, 9, -24, 16, -14, -8, 9, -5, -14, 8, -5, 30, -11, 11, -13, -15, -12, 7, 4, -13, -13, 13, -13, 12, 23, 9, 0, 14, -10, -9, -35, -2, -21, 12, -1, 17, 19, 11, -4, 0, -18, -24, 11, -10, 1, 11, 12, -13, -16, 10, -23, 21, 9, -9, 3, 12, -6, 3, -5, 12, 0, -2, 0, -19, -9, 5, -11, -7, 10, 1, -3, 9, 18, -6, 0, -1, 1, -13, 2, 1, -3, -8, 17, -4, -9, 18, -15, 8, -1, -11, -5, -14, 11, -5, -7, 12, 16, -7, 7, -3, -11, -5, -6, 1, 4, -3, -3, 15, 5, 0, 3, 6, -16, 4, -14, -6, -9, -4, 2, 11, 11, 7, -2, 4, -12, -7, -14, -6, -7, 9, 4, 7, -2, 6, 5, 6, -4, -3, -4, 7, -7, -11, -9, 0, -3, 7, -2, -2, 3, 13, -4, -6, -15, 9, -7, -1, 4, 6, 5, 8, -6, -8, 0, -11, -4, 6, -8, 4, 3, 5, 13, -4, -9, -3, 4, -3, -3, 4, -1, -12, 6, -14, 2, 3, 15, 2, 6, -7, -8, 3, 1, -2, 3, -3, -12, -6, -14, 7, -2, 13, 6, 10, 6, 0, -2, -10, -12, -8, -6, -7, -6, 6, 4, -2, 5, 2, 0, -1, 3, -11, 4, 0, 20, -8, -2, 0, -1, -3, 7, -3, -4, -2, -6, -10, -10, -8, 1, 2, 5, 8, 2, 5, 8, 3, 4, 3, -2, -15, 0, -1, -7, -2, -5, -10, 10, -1, 5, 3, 5, -1, -2, -8, -5, -9, 1, -8, 6, 5, 4, 1, 1, 2, 3, -2, 4, -7, 1, -7, -9, -2, 0, 2, 3, 6, -8, 8, 3, 0, -2, -9, -3, -2, 0, 3, -1, -2, -3, 7, -3, 10, -8, 1, -12, 3, -7, 2, -3, 7, 4, 4, 0, 0, -6, -1, -5, -3, -4, -7, 0, 5, 7, 0, 2, -3, 10, -1, 3, -7, -5, -4, -9, -3, -7, 5, -4, 9, 2, 1, 4, 5, 0, -5, 1, -8, 4, -9, 5, -5, 0, 3, -2, -1, 1, 1, -7, 7, 0, 3, -5, 0, -3, -1, -1, -5, -1, 1, -1, 1, -1, 0, 2, 0, 2, -7, -7, 4, -1, 0, 3, 4, -1, -3, -4, -6, 3, -2, 4, -1, 5, -2, -1, -5, -2, -4, 1, 3, 2, 2, 0, -3, 1, 1, -3, -3, -1, 1, -3, -2, -1, -2, -3, -1, 0, 4, 3, 5, 2, 1, -4, -9, -3, -7, 1, -2, 7, -2, 3, 3, 3, 1, 0, -1, -6, -7, -6, -4, -1, 1, 0, 5, 2, -2, 2, -3, -1, 3, -1, 1, -4, -4, -5, 0, -7, 2, -4, 3, 4, 1, 2, -1, -1, -2, -2, 0, -1, 1, -1, -1, -3, 1, 1, 3, -3, -1, 1, 1, -2, -3, -8, -5, 0, -1, 5, 2, 3, 1, -2, -1, -1, -3, 1, 1, -2, -3, -3, -1, 0, -1, 1, 2, 2, 5, 0, -1, -2, -1, -2, 0, -4, 0, -5, -1, -1, 0, 1, 5, 4, -2, -1, -2, 0, -6, -1, 0, 1, -1, -2, 1, 0, 0, 3, 1, -2, 1, -2, -4, -1, 0, -1, -1, -4, -2, -4, 2, -1, 1, 0, 3, 2, 0, 4, -1, 4, -6, 2, -4, -3, -5, -4, -3, 0, 2, 0, 1, 4, 2, 2, -2, -2, -5, -6, -5, -3, -2, 1, -1, 0, 0, 2, 2, 2, 0, 4, -2, 3, 2, -1, -2, -3, -3, -3, -5, -5, -5, -1, -1, 0, 2, 2, 4, 1, 2, 1, 2, -1, -1, -3, -4, -5, -3, -2, -2, -1, 1, 4, 2, 2, 2, 1, -1, -2, -6, -2, -3, 2, -1, 1, -2, 0, 2, 1, 2, -2, 1, 0, -2, -2, -3, 0, -2, -1, -1, 0, -2, -2, 1, 0, 2, -1, 1, -1, 0, -1, -1, 0, -1, 0, -2, 2, 0, 2, 2, 5, 3, 6, 8, 12, 13, -6, -110, -7, 51, -99, -128, 10, -28, -39, 25, -33, -27, 41, 34, -5, 17, 23, 25, 24, 23, 20, 24, 25, 24, 21, 20, 23, 23, 16, 20, 9, 20, 18, 10, 14, 5, 14, 11, 7, 5, 3, 10, 2, 7, -4, 0, 3, 0, -3, -5, -6, -1, -12, -4, -17, -10, 9, -42, -40, 65, 40, -58, 29, 72, 39, 50, 31, -1, 30, 25, -7, -4, -33, -47, -29, -49, -74, -69, -71, -79, -61, -51, -57, -53, -34, -20, -22, -16, -10, -6, -2, 1, 3, 4, 8, 8, 12, 10, 9, 14, 13, 12, 12, 13, 12, 12, 14, 12, 12, 12, 12, 13, 12, 9, 11, 11, 11, 7, 8, 7, 8, 9, 2, 5, 8, -6, 2, 17, -17, -20, 18, 5, -15, 15, 27, 21, 37, 44, 41, 46, 38, 26, 32, 26, -4, -15, -6, -20, -44, -50, -54, -60, -59, -58, -58, -54, -46, -38, -32, -26, -19, -14, -9, -5, -1, 2, 5, 7, 8, 10, 11, 12, 13, 13, 14, 14, 14, 13, 13, 14, 15, 14, 11, 13, 14, 13, 12, 10, 12, 12, 10, 10, 8, 6, 11, 9, -1, 5, 11, -1, -6, 1, -1, -4, 0, -1, 0, 14, 25, 24, 28, 37, 38, 38, 38, 31, 22, 14, 4, -5, -15, -26, -38, -47, -52, -54, -56, -57, -55, -51, -45, -39, -34, -28, -22, -17, -13, -8, -3, -1, 2, 5, 7, 8, 10, 11, 12, 13, 13, 13, 13, 14, 14, 13, 13, 14, 13, 12, 13, 13, 12, 11, 12, 11, 9, 11, 9, 6, 7, 8, 5, 3, 2, 0, 0, 0, -2, -3, 0, 3, 6, 11, 18, 23, 27, 31, 34, 35, 32, 27, 21, 14, 5, -5, -15, -26, -35, -43, -48, -52, -53, -53, -52, -49, -44, -40, -35, -29, -24, -19, -14, -10, -6, -3, 1, 3, 5, 7, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 13, 12, 11, 13, 11, 10, 10, 9, 9, 8, 7, 7, 5, 4, 3, 2, 0, -1, -1, 0, 2, 4, 8, 12, 17, 22, 25, 28, 30, 30, 28, 24, 19, 12, 3, -5, -14, -23, -31, -37, -43, -46, -46, -48, -47, -43, -41, -38, -33, -29, -25, -21, -16, -12, -8, -5, -2, 0, 3, 5, 7, 9, 10, 11, 12, 12, 13, 14, 13, 13, 13, 13, 13, 12, 12, 12, 11, 11, 11, 10, 9, 9, 8, 7, 7, 6, 5, 4, 4, 3, 3, 3, 3, 5, 6, 8, 10, 12, 14, 17, 18, 19, 20, 19, 17, 14, 10, 5, 0, -6, -11, -17, -22, -26, -29, -32, -34, -34, -35, -34, -32, -31, -28, -26, -23, -20, -17, -14, -11, -8, -5, -3, 0, 2, 4, 6, 7, 8, 9, 10, 11, 11, 12, 12, 12, 12, 11, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 5, 5, 5, 4, 4, 5, 5, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 13, 13, 12, 10, 8, 5, 2, -2, -6, -10, -14, -18, -21, -24, -26, -28, -29, -29, -30, -29, -28, -27, -25, -23, -20, -18, -15, -12, -10, -7, -4, -2, 0, 2, 4, 6, 7, 9, 10, 10, 11, 11, 12, 12, 12, 12, 11, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 5, 5, 6, 6, 7, 7, 8, 9, 10, 11, 12, 13, 13, 13, 12, 11, 10, 8, 5, 2, -1, -5, -9, -13, -16, -19, -22, -24, -26, -27, -28, -28, -28, -27, -26, -24, -22, -20, -18, -15, -13, -10, -7, -5, -2, 0, 2, 4, 5, 7, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 6, 5, 5, 5, 5, 6, 6, 6, 7, 8, 9, 10, 11, 11, 12, 12, 12, 11, 10, 9, 7, 5, 2, -1, -5, -8, -12, -15, -18, -21, -23, -25, -26, -27, -27, -27, -26, -25, -24, -22, -20, -18, -16, -13, -11, -8, -6, -3, -1, 1, 3, 4, 6, 7, 8, 9, 10, 10, 10, 11, 11, 11, 10, 10, 10, 10, 9, 9, 8, 8, 7, 7, 6, 6, 6, 5, 5, 5, 5, 6, 6, 6, 7, 8, 9, 9, 10, 11, 11, 11, 11, 11, 10, 9, 7, 4, 2, -1, -4, -7, -11, -14, -17, -19, -21, -23, -24, -25, -26, -26, -25, -24, -23, -22, -20, -18, -16, -13, -11, -9, -6, -4, -2, 0, 2, 4, 5, 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 10, 10, 10, 9, 9, 8, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 8, 9, 9, 10, 11, 11, 11, 11, 10, 10, 8, 7, 5, 2, -1, -3, -7, -10, -13, -15, -18, -20, -22, -23, -24, -25, -25, -24, -24, -23, -21, -20, -18, -16, -14, -11, -9, -7, -5, -2, 0, 1, 3, 5, 6, 7, 8, 9, 9, 10, 10, 10, 10, 10, 10, 10, 9, 9, 8, 8, 8, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10, 9, 9, 8, 7, 6, 4, 2, 0, -2, -5, -7, -10, -12, -15, -17, -18, -20, -21, -21, -22, -22, -21, -21, -20, -18, -17, -15, -13, -12, -10, -8, -6, -4, -2, 0, 1, 3, 4, 5, 6, 7, 8, 8, 8, 9, 9, 9, 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 7, 6, 5, 4, 3, 1, -1, -3, -5, -7, -9, -10, -12, -14, -15, -16, -17, -18, -18, -18, -18, -17, -17, -16, -15, -13, -12, -11, -9, -7, -6, -4, -3, -1, 0, 1, 3, 4, 5, 5, 6, 7, 7, 7, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 5, 4, 3, 2, 0, -1, -3, -5, -7, -9, -10, -12, -13, -15, -16, -17, -17, -18, -18, -18, -17, -17, -16, -15, -14, -12, -11, -9, -8, -6, -5, -3, -2, -1, 1, 2, 3, 4, 5, 5, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 5, 4, 3, 2, 0, -1, -3, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 6, 7, 8, 9, 10, 10, 11, 12, 12, 13, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 29, 29, 29, 28, 28, 28, 29, 30, 31, 31, 31, 31, 28, 19, -8, -41, -53, -57, -59, -60, -62, -62, -63, -64, -65, -65, -66, -67, -69, -69, -69, -72, -74, -73, -74, -76, -78, -79, -81, -82, -82, -83, -81, -83, -85, -81, -81, -88, -90, -80, -64, -47, -32, -23, -18, -15, -13, -12, -12, -12, -13, -13, -13, -13, -13, -12, -12, -11, -9, -7, -6, -4, -2, -1, 0, 1, 2, 4, 5, 7, 10, 12, 14, 16, 18, 19, 18, 19, 21, 19, 20, 22, 22, 22, 25, 27, 28, 29, 29, 29, 29, 29, 30, 31, 31, 31, 33, 34, 34, 35, 34, 33, 31, 30, 29, 26, 25, 26, 25, 22, 22, 21, 20, 20, 19, 19, 19, 18, 18, 18, 17, 17, 17, 17, 16, 16, 16, 15, 13, 13, 14, 14, 15, 13, 12, 13, 13, 11, 12, 14, 14, 16, 17, 15, 16, 19, 19, 19, 19, 21, 19, 17, 18, 19, 18, 15, 15, 17, 18, 18, 13, 11, 14, 15, 14, 11, 6, 5, 10, 13, 17, 18, 11, 2, -2, -2, -3, 2, 14, 24, 30, 37, 47, 52, 52, 56, 63, 65, 65, 63, 65, 72, 75, 73, 71, 73, 77, 82, 82, 77, 77, 82, 90, 99, 104, 99, 89, 84, 86, 94, 106, 119, 127, 126, 117, 104, 87, 64, 42, 24, 10, -2, -15, -22, -25, -27, -30, -35, -37, -36, -34, -33, -36, -40, -42, -44, -43, -44, -48, -53, -57, -59, -57, -53, -52, -53, -57, -62, -68, -73, -75, -75, -71, -63, -56, -48, -40, -34, -29, -26, -23, -22, -21, -19, -19, -20, -21, -22, -22, -22, -22, -22, -21, -21, -21, -20, -19, -19, -18, -18, -17, -17, -16, -14, -14, -13, -11, -9, -9, -9, -9, -9, -8, -8, -8, -8, -8, -7, -6, -7, -6, -4, -3, -2, -2, -3, -4, -3, -3, -2, -1, 0, 0, -1, -1, 0, -1, -1, -1, -3, -5, -5, -8, -10, -10, -9, -9, -10, -11, -11, -11, -11, -11, -10, -9, -10, -10, -10, -11, -12, -12, -13, -12, -11, -12, -14, -14, -11, -10, -12, -11, -11, -12, -12, -11, -11, -13, -12, -9, -6, -6, -7, -7, -6, -5, -4, -4, -5, -8, -12, -11, -8, -4, -3, -5, -6, -7, -9, -12, -13, -8, -3, -2, -4, -8, -11, -14, -15, -17, -19, -19, -15, -8, -1, 2, 4, 8, 12, 17, 23, 26, 25, 24, 25, 30, 36, 40, 39, 36, 33, 32, 33, 37, 43, 49, 53, 53, 49, 45, 43, 43, 46, 52, 60, 67, 76, 82, 82, 78, 69, 58, 47, 37, 26, 14, 2, -9, -16, -21, -24, -28, -32, -35, -37, -38, -37, -36, -36, -36, -39, -43, -46, -49, -51, -49, -47, -46, -45, -45, -48, -52, -58, -62, -65, -66, -65, -62, -58, -54, -50, -45, -39, -34, -30, -28, -25, -23, -21, -20, -20, -20, -20, -19, -18, -19, -20, -18, -17, -18, -17, -17, -18, -17, -16, -15, -15, -13, -12, -10, -10, -10, -9, -8, -7, -6, -4, -4, -5, -6, -5, -4, -4, -3, -2, -2, -1, -1, -1, 0, 2, 3, 2, 2, 3, 2, 1, 2, 4, 5, 5, 4, 4, 4, 3, 2, 2, 1, 0, 0, -1, -4, -5, -4, -2, -2, -3, -3, -3, -2, -1, -2, -3, -2, -3, -4, -4, -3, -4, -6, -7, -4, 0, 0, -2, -4, -4, -3, -2, -2, -3, -4, -4, -3, -2, -1, 3, 6, 8, 6, 3, 0, 0, 2, 4, 5, 4, 3, 2, 2, 2, 1, 0, -1, 2, 7, 11, 9, 6, 2, -1, -3, -3, -5, -7, -8, -6, -3, 2, 8, 13, 17, 18, 18, 19, 23, 28, 34, 40, 42, 42, 40, 39, 39, 40, 42, 46, 50, 55, 59, 59, 55, 51, 48, 48, 51, 57, 63, 70, 76, 82, 86, 88, 89, 86, 80, 71, 61, 51, 43, 34, 25, 18, 10, 2, -5, -9, -12, -13, -12, -12, -13, -14, -17, -22, -26, -29, -28, -27, -25, -24, -24, -25, -27, -31, -35, -40, -43, -46, -47, -49, -49, -46, -43, -40, -36, -32, -28, -24, -21, -18, -16, -14, -13, -13, -12, -11, -11, -12, -11, -10, -9, -11, -11, -11, -12, -12, -12, -10, -10, -10, -10, -9, -8, -7, -6, -5, -4, -4, -4, -4, -4, -3, -2, -2, -1, -2, -3, -2, -1, 0, 0, 1, 2, 3, 2, 1, 1, 2, 3, 3, 4, 5, 4, 4, 5, 6, 7, 6, 4, 3, 3, 3, 2, -1, -3, -3, -1, -1, -2, -3, -3, -2, -1, 1, 0, -1, -1, -2, -5, -6, -5, -4, -4, -4, -4, -6, -6, -4, -1, 0, -2, -6, -9, -10, -8, -5, -4, -3, -3, -1, 1, 1, -1, -3, -4, -2, 0, 2, 2, 0, -3, -6, -7, -6, -4, -3, -2, -1, -1, -1, 0, 1, 0, -3, -9, -14, -18, -18, -15, -12, -9, -8, -7, -5, -3, -2, 0, 5, 11, 17, 22, 25, 24, 23, 21, 20, 22, 27, 32, 37, 40, 41, 40, 39, 37, 35, 34, 34, 35, 39, 45, 52, 59, 66, 71, 73, 75, 74, 71, 65, 60, 55, 48, 39, 28, 17, 7, -1, -7, -11, -13, -13, -14, -17, -21, -24, -28, -31, -32, -32, -32, -32, -31, -29, -29, -30, -33, -36, -40, -44, -47, -50, -52, -54, -55, -54, -52, -49, -47, -43, -39, -35, -31, -28, -26, -24, -22, -21, -19, -18, -17, -17, -16, -15, -16, -18, -17, -16, -16, -17, -18, -18, -17, -16, -16, -14, -13, -13, -12, -12, -12, -11, -10, -10, -9, -7, -8, -9, -10, -10, -8, -6, -5, -6, -6, -5, -3, -3, -4, -4, -4, -3, -2, -2, -1, -1, -1, 0, 2, 3, 3, 3, 2, 1, 0, -1, -1, -1, -2, -3, -5, -5, -4, -2, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 3, 2, 0, -1, 1, 2, 1, -1, -1, 2, 2, 0, 1, 2, 2, -1, -4, -10, -21, -30, -36, -41, -44, -40, -30, -18, -10, -8, -11, -13, -8, 3, 18, 32, 41, 44, 45, 48, 49, 43, 32, 23, 14, 7, 8, 16, 27, 35, 37, 30, 18, 9, 5, 3, 2, 1, 1, -1, -6, -11, -12, -6, -2, -5, -11, -18, -28, -39, -47, -55, -69, -86, -99, -102, -92, -70, -46, -28, -15, -3, 7, 17, 26, 28, 24, 23, 30, 42, 53, 57, 50, 36, 21, 5, -5, -4, 6, 20, 31, 35, 34, 29, 26, 27, 37, 56, 76, 85, 80, 71, 63, 55, 47, 34, 13, -13, -32, -39, -40, -46, -65, -93, -117, -128, -128, -126, -120, -110, -96, -78, -58, -36, -14, 3, 10, 20, 41, 60, 68, 63, 54, 45, 39, 36, 32, 28, 29, 35, 41, 47, 46, 41, 39, 43, 53, 68, 80, 78, 64, 46, 28, 13, 3, -9, -35, -64, -80, -82, -74, -66, -71, -91, -111, -121, -118, -105, -86, -68, -57, -49, -37, -22, -7, 5, 14, 26, 42, 55, 56, 46, 35, 25, 14, 6, 2, 1, 3, 11, 22, 32, 40, 43, 42, 46, 60, 77, 88, 90, 78, 54, 30, 14, 2, -15, -37, -62, -82, -90, -89, -86, -90, -99, -107, -109, -101, -81, -54, -29, -14, -5, 7, 24, 40, 49, 56, 68, 83, 92, 92, 87, 74, 54, 32, 12, -5, -19, -25, -24, -18, -7, 1, -1, -6, -4, 13, 41, 69, 84, 80, 63, 44, 32, 29, 25, 11, -10, -25, -31, -35, -40, -48, -65, -87, -104, -109, -102, -87, -69, -58, -54, -42, -21, 0, 13, 29, 51, 71, 84, 89, 86, 75, 54, 33, 14, -3, -19, -29, -27, -22, -18, -11, -8, -16, -26, -19, 2, 24, 40, 48, 42, 27, 21, 29, 34, 24, 7, -5, -14, -23, -28, -32, -45, -67, -82, -85, -78, -63, -46, -34, -29, -24, -13, 0, 12, 25, 44, 65, 79, 85, 86, 78, 60, 41, 27, 12, -5, -15, -15, -14, -13, -8, -7, -17, -27, -23, -3, 23, 44, 51, 43, 25, 12, 11, 14, 8, -3, -10, -15, -22, -28, -30, -36, -55, -73, -78, -74, -71, -63, -51, -43, -39, -34, -25, -18, -9, 8, 28, 46, 56, 61, 62, 58, 47, 36, 28, 20, 12, 11, 16, 19, 20, 21, 15, 0, -6, 10, 37, 57, 63, 55, 36, 15, 2, -3, -9, -19, -27, -34, -43, -49, -49, -52, -66, -82, -86, -81, -77, -71, -61, -51, -47, -43, -35, -22, -12, 2, 24, 47, 58, 63, 67, 66, 58, 51, 45, 34, 18, 9, 7, 7, 7, 8, 1, -14, -24, -12, 18, 47, 64, 68, 63, 53, 42, 37, 38, 36, 29, 21, 16, 11, 5, -2, -17, -36, -49, -52, -56, -62, -63, -61, -61, -63, -60, -56, -49, -37, -19, 2, 17, 25, 30, 34, 37, 37, 37, 34, 25, 15, 11, 13, 14, 14, 8, -7, -21, -16, 9, 37, 53, 60, 61, 53, 40, 33, 34, 32, 22, 14, 12, 10, 6, -2, -15, -32, -48, -57, -60, -63, -67, -66, -63, -63, -65, -64, -58, -49, -34, -13, 6, 16, 21, 28, 34, 38, 41, 43, 36, 25, 19, 21, 26, 27, 20, 4, -11, -11, 7, 31, 53, 66, 70, 66, 57, 49, 47, 44, 33, 21, 17, 16, 10, 1, -9, -26, -46, -60, -67, -76, -84, -84, -80, -78, -79, -78, -73, -65, -52, -32, -11, 4, 10, 17, 25, 32, 36, 40, 37, 24, 13, 15, 23, 23, 11, -5, -19, -25, -16, 9, 38, 59, 70, 72, 67, 63, 63, 60, 50, 39, 32, 28, 22, 14, 3, -14, -34, -53, -65, -76, -87, -94, -93, -91, -94, -96, -93, -86, -76, -56, -30, -9, 4, 16, 29, 40, 51, 63, 65, 52, 39, 39, 45, 42, 29, 11, -7, -22, -24, -8, 19, 42, 54, 60, 63, 61, 58, 57, 53, 43, 36, 36, 34, 28, 21, 11, -5, -24, -39, -52, -65, -75, -77, -75, -75, -78, -80, -78, -73, -61, -43, -23, -9, 1, 10, 23, 39, 52, 56, 47, 36, 35, 41, 42, 33, 17, -2, -24, -35, -26, -3, 18, 32, 42, 50, 52, 53, 52, 47, 38, 31, 30, 31, 29, 26, 22, 14, -1, -18, -33, -46, -58, -65, -65, -65, -71, -79, -81, -79, -75, -62, -42, -27, -21, -14, 1, 19, 34, 40, 36, 29, 27, 31, 38, 39, 29, 9, -12, -27, -28, -14, 8, 25, 37, 50, 62, 67, 66, 62, 53, 42, 36, 37, 36, 32, 30, 25, 12, -7, -24, -39, -54, -65, -67, -67, -72, -78, -81, -82, -81, -70, -51, -35, -29, -23, -7, 15, 30, 37, 40, 35, 25, 25, 36, 41, 33, 15, -6, -26, -36, -27, -9, 7, 20, 35, 50, 58, 59, 58, 52, 43, 37, 37, 37, 36, 34, 31, 24, 8, -11, -29, -44, -57, -67, -70, -73, -79, -86, -92, -93, -87, -72, -59, -53, -46, -29, -9, 7, 20, 28, 26, 19, 17, 27, 38, 38, 26, 7, -12, -25, -26, -15, 1, 14, 28, 47, 61, 67, 68, 68, 63, 54, 51, 53, 51, 49, 49, 47, 34, 14, -5, -22, -39, -56, -65, -67, -73, -86, -96, -97, -92, -86, -77, -69, -61, -49, -28, -6, 10, 22, 27, 25, 24, 33, 49, 56, 48, 32, 13, -5, -15, -12, -2, 7, 18, 35, 50, 59, 63, 65, 61, 53, 48, 46, 44, 43, 46, 49, 43, 27, 10, -6, -25, -45, -53, -53, -60, -75, -87, -90, -90, -88, -81, -75, -72, -65, -48, -25, -6, 5, 10, 13, 18, 31, 49, 60, 58, 44, 28, 12, -1, -7, -7, -1, 8, 23, 41, 54, 61, 65, 66, 63, 56, 48, 43, 41, 42, 44, 43, 37, 25, 8, -12, -32, -44, -49, -53, -64, -80, -91, -95, -93, -89, -85, -82, -78, -68, -50, -27, -6, 0, -1, 0, 0, 0, 1, 2, 3, 6, 9, 13, 17, 19, 13, -4, -15, -10, 4, 19, 26, 15, -9, -16, 6, -2, -18, 38, 64, 21, -48, 30, 82, -23, -63, -50, -26, -7, 12, 26, 47, 83, 100, 3, -108, -87, -30, -6, 5, 18, 33, 46, 47, 21, -52, -46, 48, 3, -54, -32, 22, 25, -7, 12, 9, -18, -33, -24, 2, 44, 88, 92, 10, -28, -1, 1, 20, 42, 1, -17, 53, 72, 12, -16, -74, -31, 127, 52, 1, -35, -46, 13, 39, -13, -13, 13, 12, 11, 8, -57, -80, -44, -5, 14, 18, 6, -13, -26, -11, -8, -24, 3, 30, 14, -28, -12, 41, -2, -37, -35, -23, -12, -1, 6, 17, 34, 53, 19, -55, -67, -32, -13, -5, 2, 12, 19, 24, 14, -24, -47, 12, 11, -36, -35, -1, 18, -3, 0, 5, -13, -25, -22, -5, 19, 53, 69, 21, -28, -10, -5, 6, 28, 8, -25, 23, 57, 17, -17, -49, -63, 84, 70, 3, -23, -50, -6, 36, -2, -20, 8, 14, 9, 13, -37, -82, -58, -19, 8, 17, 10, -9, -26, -19, -7, -24, -9, 25, 22, -17, -28, 33, 16, -32, -37, -27, -15, -4, 4, 13, 27, 48, 35, -35, -72, -43, -17, -7, -1, 9, 16, 23, 17, -12, -51, -7, 21, -27, -40, -12, 19, 6, -3, 5, -9, -22, -23, -8, 11, 42, 68, 38, -23, -16, -6, 3, 25, 19, -24, 8, 54, 31, -13, -33, -76, 46, 95, 13, -13, -48, -20, 32, 13, -22, 2, 15, 10, 15, -17, -77, -67, -31, 3, 17, 15, -3, -21, -23, -7, -20, -18, 18, 27, -4, -34, 17, 33, -21, -36, -29, -16, -6, 4, 11, 23, 42, 47, -12, -69, -54, -22, -8, -2, 7, 15, 22, 20, -2, -46, -27, 23, -13, -41, -22, 15, 16, -2, 4, -5, -18, -21, -10, 5, 32, 64, 53, -12, -21, -6, 0, 21, 27, -16, -6, 48, 42, -6, -22, -71, 2, 106, 31, -6, -41, -32, 22, 25, -18, -4, 15, 12, 14, -1, -64, -74, -42, -5, 16, 19, 4, -16, -25, -10, -14, -23, 9, 29, 9, -31, -2, 42, -5, -33, -30, -18, -8, 3, 9, 19, 36, 51, 10, -58, -63, -29, -11, -2, 4, 13, 20, 21, 6, -35, -44, 16, 1, -38, -30, 7, 23, 3, 2, -2, -16, -20, -12, 2, 23, 56, 62, 3, -24, -7, -2, 17, 30, -5, -17, 37, 49, 4, -17, -57, -37, 99, 55, 0, -31, -41, 9, 33, -10, -11, 13, 14, 12, 9, -47, -78, -53, -15, 12, 20, 9, -10, -24, -14, -11, -25, -2, 27, 18, -21, -20, 39, 13, -29, -31, -20, -9, 1, 8, 17, 30, 49, 29, -41, -70, -39, -15, -4, 2, 11, 17, 21, 11, -22, -52, 0, 14, -31, -36, -4, 25, 11, 1, -1, -13, -19, -13, 0, 15, 45, 65, 20, -24, -10, -4, 12, 30, 8, -22, 24, 52, 17, -14, -39, -61, 71, 81, 8, -21, -44, -5, 34, 2, -16, 9, 16, 11, 14, -29, -76, -62, -27, 6, 20, 15, -4, -21, -19, -9, -23, -12, 22, 25, -8, -30, 26, 30, -20, -31, -23, -11, -1, 8, 14, 25, 44, 42, -19, -69, -50, -20, -6, 1, 9, 15, 20, 15, -11, -51, -19, 20, -20, -39, -15, 23, 20, 2, 0, -11, -17, -14, -2, 9, 35, 63, 37, -19, -14, -5, 8, 28, 18, -22, 9, 50, 28, -11, -26, -68, 32, 100, 22, -13, -43, -18, 30, 15, -17, 4, 16, 12, 15, -12, -69, -69, -39, -2, 18, 19, 2, -17, -22, -10, -19, -20, 15, 27, 4, -31, 7, 41, -7, -30, -25, -13, -3, 6, 12, 22, 38, 48, 3, -61, -60, -27, -9, 0, 7, 13, 19, 17, -2, -44, -37, 18, -7, -39, -24, 15, 28, 7, 0, -9, -16, -14, -3, 6, 25, 57, 49, -9, -18, -7, 3, 25, 26, -15, -4, 45, 38, -5, -18, -61, -8, 103, 42, -6, -37, -30, 21, 25, -13, -3, 16, 13, 14, 2, -56, -73, -49, -12, 15, 21, 8, -11, -23, -13, -15, -24, 4, 28, 14, -25, -12, 42, 9, -26, -26, -15, -5, 5, 11, 19, 32, 48, 22, -46, -67, -36, -12, -2, 4, 12, 17, 18, 4, -33, -50, 6, 6, -35, -31, 4, 31, 14, 0, -8, -15, -14, -4, 4, 17, 48, 57, 4, -21, -8, -1, 21, 30, -5, -15, 36, 44, 5, -14, -46, -40, 88, 67, 2, -29, -37, 9, 31, -6, -9, 14, 15, 13, 11, -40, -74, -58, -24, 9, 22, 13, -6, -21, -17, -13, -25, -6, 25, 21, -13, -25, 33, 26, -19, -27, -18, -6, 3, 10, 16, 27, 45, 36, -26, -69, -46, -17, -4, 2, 10, 15, 18, 9, -22, -55, -11, 15, -26, -36, -8, 30, 23, 2, -6, -14, -14, -6, 4, 11, 37, 59, 19, -20, -10, -4, 16, 31, 7, -20, 23, 47, 15, -13, -32, -58, 58, 88, 13, -21, -40, -5, 32, 4, -13, 10, 17, 12, 14, -23, -70, -65, -35, 1, 20, 17, 0, -18, -20, -12, -23, -16, 19, 25, -1, -30, 16, 39, -8, -26, -20, -8, 1, 9, 14, 23, 39, 44, -5, -63, -57, -24, -7, 1, 8, 13, 17, 12, -12, -52, -30, 17, -15, -38, -18, 23, 32, 7, -6, -13, -14, -7, 3, 8, 27, 55, 33, -16, -13, -6, 10, 30, 17, -20, 10, 46, 25, -9, -21, -60, 19, 100, 31, -13, -39, -17, 27, 15, -13, 4, 17, 13, 15, -8, -61, -69, -46, -10, 17, 21, 6, -13, -22, -13, -20, -22, 10, 27, 9, -27, -4, 44, 6, -24, -22, -11, -1, 8, 13, 20, 33, 46, 14, -50, -65, -33, -11, 0, 5, 12, 15, 14, -4, -43, -46, 10, -2, -36, -27, 13, 36, 15, -4, -13, -14, -8, 3, 7, 18, 49, 43, -7, -16, -7, 5, 27, 24, -14, -3, 42, 33, -3, -16, -51, -17, 97, 51, -3, -38, -5, -13, 1, -7, 5, -22, -32, -35, -32, -43, -35, -55, -42, -66, -48, -80, -57, -17, -128, -59, -76, 0, -26, 1, -33, 21, 3, 16, 15, 26, 43, 28, 66, 6, 97, 40, 103, 67, 101, 102, 98, 94, 21, 98, 90, 57, 78, 89, 81, 61, -6, 54, 4, 62, 19, 27, 34, 12, 16, 14, -17, 19, -5, -2, -13, -38, -24, -3, -33, -14, -11, -16, 0, -13, 7, -26, -13, -16, 6, -57, -23, -28, -13, -9, -34, -32, -20, -87, -62, -28, -38, -75, -37, -27, -41, -71, -48, -30, -44, -83, -67, -52, -48, -45, -46, -45, -63, -47, -40, -32, -45, -24, -32, -43, -21, -17, 0, 21, 26, 43, 51, 62, 47, 41, 55, 57, 68, 34, 53, 63, 62, 71, 60, 61, 56, 53, 56, 54, 38, 50, 58, 50, 40, 28, 54, 39, 41, 38, 22, 32, 20, -3, 19, -1, -7, -6, -16, -16, -14, -27, -29, -46, -66, -61, -51, -54, -61, -41, -50, -47, -52, -55, -45, -44, -28, -58, -56, -31, -37, -36, -32, -18, -16, -34, -29, -9, -21, -20, -30, -22, -17, -19, -8, -12, -14, -6, -14, -6, -11, -2, 4, -6, 9, 8, 17, 23, 13, 31, 13, 24, 30, 28, 29, 30, 43, 34, 37, 52, 42, 44, 50, 67, 59, 49, 54, 48, 43, 51, 45, 42, 62, 47, 39, 37, 36, 24, 28, 13, 3, 9, -11, -3, -9, -14, -18, -34, -27, -29, -39, -42, -38, -46, -37, -46, -43, -41, -35, -38, -31, -38, -34, -39, -39, -34, -48, -44, -47, -49, -54, -52, -44, -53, -37, -47, -38, -31, -38, -27, -19, -19, -15, -16, 0, 0, 2, 7, 13, 29, 22, 32, 32, 39, 47, 41, 40, 55, 48, 41, 44, 57, 43, 36, 47, 43, 42, 37, 32, 32, 27, 33, 36, 30, 23, 25, 25, 22, 18, 22, 20, 16, 8, 6, 12, 7, 0, 1, 3, -5, -14, -9, -7, -8, -19, -15, -16, -23, -21, -21, -32, -31, -29, -26, -27, -29, -33, -26, -29, -30, -39, -28, -41, -43, -35, -34, -32, -29, -28, -28, -25, -27, -24, -27, -27, -27, -22, -23, -17, -9, -10, -14, -10, -8, -4, -2, -1, -3, 5, 4, 10, 11, 7, 13, 11, 14, 27, 22, 22, 22, 27, 36, 34, 36, 37, 45, 44, 47, 48, 51, 49, 52, 51, 52, 48, 50, 47, 48, 42, 40, 29, 33, 24, 22, 12, 5, 0, -3, -5, -9, -21, -21, -25, -19, -28, -28, -30, -33, -39, -42, -42, -46, -46, -45, -42, -43, -47, -47, -36, -32, -30, -34, -31, -22, -29, -29, -30, -26, -28, -30, -21, -26, -27, -21, -19, -16, -11, -12, -8, -2, 1, -4, 1, 0, 1, 9, 8, 7, 12, 10, 13, 20, 17, 18, 21, 26, 29, 30, 30, 29, 34, 33, 34, 33, 30, 32, 33, 28, 33, 29, 35, 32, 31, 30, 31, 30, 25, 27, 24, 21, 21, 20, 16, 17, 12, 6, 4, -3, 1, -6, -7, -11, -13, -11, -10, -8, -13, -12, -9, -17, -14, -19, -24, -22, -24, -30, -32, -30, -33, -37, -39, -40, -42, -39, -41, -39, -40, -41, -35, -35, -35, -37, -36, -33, -30, -25, -25, -19, -16, -16, -10, -6, -7, -4, -2, 1, 3, 6, 10, 9, 15, 17, 18, 17, 13, 19, 18, 17, 19, 20, 24, 24, 27, 27, 29, 30, 26, 28, 28, 27, 28, 26, 25, 24, 25, 20, 19, 17, 18, 15, 12, 13, 10, 6, 8, 6, 3, 4, 3, 0, -3, 0, -1, -2, -5, -4, -5, -4, -5, -6, -8, -9, -9, -12, -11, -16, -16, -15, -15, -13, -17, -16, -17, -17, -21, -20, -25, -24, -24, -24, -26, -30, -30, -27, -30, -26, -26, -27, -27, -25, -24, -19, -20, -17, -13, -12, -8, -8, -8, -6, -5, -2, -1, 0, 3, 8, 10, 12, 16, 18, 24, 25, 25, 28, 30, 28, 32, 33, 31, 32, 31, 35, 33, 31, 31, 27, 28, 26, 23, 23, 20, 22, 18, 16, 13, 11, 9, 5, 4, -2, -2, -3, -8, -9, -11, -12, -13, -15, -15, -15, -15, -15, -14, -12, -12, -13, -13, -8, -11, -10, -12, -10, -12, -12, -8, -8, -9, -9, -9, -8, -9, -10, -11, -11, -10, -13, -14, -13, -16, -16, -17, -17, -18, -19, -18, -17, -16, -16, -15, -15, -13, -12, -10, -12, -10, -9, -8, -6, -6, -3, 0, 0, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 14, 14, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 14, 13, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -1, -2, -3, -4, -5, -5, -6, -7, -7, -8, -9, -9, -10, -11, -11, -12, -12, -13, -13, -13, -13, -14, -14, -14, -15, -15, -15, -15, -15, -15, -16, -16, -16, -15, -15, -15, -14, -13, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -2, -1, 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 16, 16, 15, 15, 14, 14, 13, 12, 11, 10, 9, 7, 6, 5, 3, 1, 0, -2, -4, -5, -7, -9, -10, -11, -13, -14, -15, -15, -16, -17, -17, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -18, -17, -17, -16, -16, -15, -14, -14, -13, -12, -11, -10, -9, -8, -7, -6, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 11, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 14, 14, 13, 12, 12, 11, 10, 9, 8, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, -1, 0, 0, -1, 2, 1, 0, 1, 4, 2, 2, 2, 5, 2, 5, 5, 8, 4, 13, 15, 19, -62, -65, 56, -18, -128, -39, 15, -57, -10, 19, -22, -11, 36, 30, 5, 19, 25, 17, 21, 21, 16, 21, 18, 17, 17, 15, 14, 13, 12, 10, 6, 8, 6, 6, -1, 1, -4, 7, -10, -36, 35, 64, -25, -18, 83, 50, 22, 39, 21, 19, -4, -20, 28, 0, -88, -55, -5, -55, -83, -64, -58, -77, -61, -22, -39, -57, -15, 2, -14, -9, -1, 1, 1, 2, 9, 5, 6, 11, 9, 9, 10, 11, 12, 12, 10, 9, 9, 13, 7, 3, 14, 4, -3, 2, 2, 17, 40, 12, 14, 55, 58, 44, 39, 38, 37, 6, 4, 31, -6, -50, -25, -15, -49, -52, -41, -60, -68, -32, -25, -47, -36, -9, -5, -7, -3, 3, 4, 6, 8, 11, 9, 10, 14, 14, 11, 13, 15, 14, 13, 14, 12, 11, 12, 12, 8, 8, 3, 4, 5, -1, 8, 32, 21, 14, 43, 50, 39, 47, 39, 20, 23, 16, 5, -9, -23, -26, -34, -48, -37, -48, -71, -56, -34, -43, -49, -36, -20, -14, -13, -9, -4, -1, 1, 3, 6, 6, 6, 9, 10, 8, 10, 11, 11, 11, 11, 10, 10, 10, 10, 6, 6, 4, 3, 6, -3, 2, 25, 23, 16, 34, 38, 43, 51, 31, 19, 38, 22, -10, -7, 0, -25, -45, -34, -32, -54, -62, -47, -39, -45, -47, -36, -24, -19, -16, -11, -6, -3, 0, 2, 4, 6, 7, 8, 10, 11, 9, 11, 12, 11, 11, 12, 11, 10, 10, 8, 7, 6, 3, 5, 4, 0, 13, 28, 23, 19, 36, 50, 42, 30, 31, 39, 24, -6, -2, 7, -21, -40, -27, -34, -51, -51, -44, -42, -45, -45, -37, -27, -22, -18, -13, -9, -6, -2, 1, 2, 5, 7, 7, 9, 11, 10, 10, 12, 12, 11, 12, 11, 10, 10, 9, 7, 7, 4, 5, 7, 1, 7, 27, 24, 15, 34, 47, 37, 32, 36, 36, 26, 4, -1, 4, -13, -30, -27, -34, -47, -46, -42, -43, -45, -44, -38, -31, -25, -21, -17, -12, -8, -5, -1, 1, 3, 5, 6, 8, 9, 10, 10, 10, 11, 11, 11, 11, 11, 10, 9, 7, 7, 6, 3, 6, 5, 6, 17, 23, 19, 29, 40, 35, 33, 36, 34, 26, 14, 3, 0, -6, -18, -26, -32, -39, -40, -38, -39, -41, -40, -36, -31, -27, -23, -19, -15, -12, -8, -4, -2, 0, 3, 4, 5, 7, 8, 9, 9, 9, 10, 10, 10, 10, 10, 9, 8, 8, 8, 7, 8, 10, 11, 14, 19, 22, 25, 28, 29, 29, 29, 27, 21, 14, 7, -1, -5, -11, -19, -26, -29, -31, -32, -33, -34, -33, -32, -29, -26, -24, -21, -18, -15, -12, -9, -6, -4, -2, 0, 2, 3, 5, 6, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 11, 12, 14, 16, 18, 20, 22, 23, 24, 24, 23, 20, 17, 12, 7, 2, -3, -8, -13, -17, -21, -23, -25, -26, -27, -27, -27, -26, -25, -23, -21, -19, -17, -14, -12, -9, -7, -5, -3, -1, 1, 2, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 13, 15, 16, 18, 19, 21, 22, 22, 22, 21, 19, 17, 13, 9, 4, 0, -5, -10, -14, -18, -21, -23, -25, -26, -26, -26, -26, -25, -23, -22, -20, -18, -15, -13, -11, -9, -6, -4, -2, 0, 1, 3, 4, 5, 6, 7, 7, 8, 8, 8, 9, 9, 10, 11, 12, 13, 14, 15, 17, 18, 20, 21, 21, 21, 21, 19, 17, 14, 11, 7, 2, -3, -7, -11, -15, -19, -21, -23, -25, -25, -26, -25, -25, -24, -22, -21, -19, -17, -15, -12, -10, -8, -6, -4, -2, 0, 1, 3, 4, 5, 6, 6, 7, 8, 8, 9, 9, 10, 11, 11, 12, 13, 15, 16, 17, 19, 20, 20, 21, 20, 19, 18, 15, 12, 8, 4, 0, -4, -9, -13, -16, -19, -21, -23, -24, -25, -25, -25, -24, -23, -21, -20, -18, -16, -14, -12, -9, -7, -5, -3, -2, 0, 1, 3, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 20, 20, 19, 18, 16, 13, 10, 6, 2, -2, -6, -10, -13, -16, -19, -21, -23, -24, -24, -24, -24, -23, -22, -20, -19, -17, -15, -13, -11, -8, -6, -5, -3, -1, 0, 2, 3, 4, 5, 6, 7, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 19, 18, 16, 14, 11, 8, 4, 0, -3, -7, -11, -14, -17, -19, -21, -22, -23, -23, -23, -23, -22, -21, -19, -18, -16, -14, -12, -10, -8, -6, -4, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19, 18, 17, 15, 12, 9, 6, 3, -1, -5, -9, -12, -15, -17, -19, -21, -22, -23, -23, -23, -22, -21, -20, -18, -17, -15, -13, -11, -9, -7, -6, -4, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 17, 18, 18, 18, 17, 16, 14, 12, 10, 7, 4, 0, -3, -6, -9, -12, -15, -17, -18, -20, -20, -21, -21, -21, -20, -19, -18, -17, -15, -14, -12, -10, -9, -7, -5, -4, -2, -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 15, 14, 12, 11, 8, 6, 3, 0, -3, -6, -9, -12, 1, -1, 2, -1, 4, 2, 8, 5, 10, -5, 0, 5, 17, -11, 0, 19, -17, 26, 65, 15, 29, 3, 35, 67, 50, 88, 59, 117, 28, -6, -16, 29, 63, 62, -40, 59, 22, -95, -49, -55, 19, 36, -15, 26, -117, 60, 8, -101, -115, 23, 60, -32, -106, -84, -88, -127, -99, -117, -110, -56, -42, -53, -79, -44, 43, 10, -11, 72, 22, 61, 10, -92, -106, -111, -35, -68, -128, -67, -36, -118, -97, -96, -4, 75, 70, 113, 36, 73, 115, 37, 6, 79, 97, 89, -8, -38, -8, -72, -8, -29, -35, 73, 98, 66, 12, 40, 113, 106, 87, 126, 112, 127, 87, -3, -21, -23, 40, 14, -68, -20, 21, -57, -67, -67, -4, 69, 53, 90, 17, 36, 78, -7, -54, -2, 32, 21, -71, -109, -89, -124, -103, -114, -113, -37, -4, -30, -88, -83, 15, 13, -35, 42, 28, 33, 14, -90, -92, -104, -37, -34, -115, -73, -9, -75, -89, -85, -29, 67, 51, 97, 55, 47, 115, 46, -9, 42, 90, 96, 26, -36, 11, -43, -25, -6, -37, 59, 104, 88, 31, 22, 96, 116, 69, 110, 119, 119, 109, 11, -15, -26, 18, 37, -45, -32, 34, -13, -62, -62, -30, 61, 47, 75, 46, 14, 72, 14, -58, -35, 16, 30, -38, -109, -78, -109, -116, -102, -123, -57, -2, -11, -58, -95, -18, 22, -41, -3, 36, 20, 31, -69, -94, -100, -72, -21, -91, -92, -9, -33, -82, -81, -57, 48, 52, 70, 81, 35, 97, 69, -10, 8, 66, 94, 55, -27, 4, -5, -40, -1, -33, 30, 102, 101, 61, 19, 70, 121, 72, 77, 123, 112, 121, 36, -13, -21, -10, 38, -18, -43, 27, 25, -40, -59, -45, 40, 54, 52, 68, 15, 56, 35, -48, -58, -12, 25, -10, -98, -84, -83, -122, -101, -123, -81, -8, -3, -28, -85, -47, 20, -28, -39, 23, 18, 31, -38, -99, -92, -97, -35, -66, -102, -26, -3, -60, -77, -69, 18, 59, 47, 87, 46, 73, 86, 3, -13, 34, 80, 70, -8, -12, 19, -32, -12, -21, 3, 91, 105, 87, 34, 51, 114, 89, 53, 106, 115, 119, 65, -10, -13, -25, 20, 4, -45, 9, 44, -8, -49, -51, 14, 61, 39, 68, 34, 39, 51, -30, -67, -41, 7, 5, -76, -96, -65, -111, -110, -115, -103, -20, -1, -9, -58, -65, 8, -9, -55, -6, 17, 24, -11, -94, -89, -102, -64, -50, -101, -51, 6, -30, -66, -71, -12, 59, 40, 72, 67, 58, 91, 24, -21, 6, 56, 74, 14, -22, 23, -8, -24, -14, -13, 71, 106, 101, 62, 42, 101, 105, 49, 76, 114, 114, 87, 3, -12, -23, -6, 13, -37, -11, 45, 24, -29, -49, -8, 57, 40, 53, 54, 32, 56, -6, -65, -61, -21, 6, -52, -101, -65, -85, -115, -109, -116, -42, 0, -1, -27, -65, -12, 7, -51, -37, 7, 17, 6, -76, -95, -94, -91, -52, -90, -76, -2, -4, -46, -66, -35, 46, 46, 49, 78, 57, 85, 50, -17, -13, 26, 64, 34, -22, 9, 18, -22, -14, -18, 42, 103, 105, 88, 50, 83, 114, 63, 49, 96, 110, 99, 26, -14, -15, -23, 6, -24, -29, 33, 45, 0, -38, -23, 44, 50, 37, 60, 38, 52, 21, -54, -70, -48, -7, -31, -95, -78, -63, -104, -108, -117, -69, -4, -1, -5, -47, -30, 13, -33, -58, -14, 8, 11, -50, -99, -87, -101, -70, -77, -92, -22, 10, -22, -52, -46, 23, 55, 36, 70, 66, 74, 69, -2, -23, 1, 43, 43, -11, -8, 29, -4, -17, -16, 18, 91, 105, 102, 71, 72, 112, 83, 40, 70, 101, 102, 50, -10, -10, -24, -10, -13, -36, 14, 52, 27, -18, -28, 26, 58, 33, 51, 49, 46, 40, -34, -70, -66, -31, -22, -81, -92, -56, -83, -105, -112, -91, -17, 0, 2, -22, -37, 7, -12, -61, -39, -5, 7, -27, -93, -90, -96, -90, -72, -95, -48, 9, -1, -33, -46, 0, 55, 37, 50, 72, 68, 77, 20, -25, -15, 17, 40, 3, -20, 22, 19, -12, -14, 2, 70, 105, 106, 92, 72, 104, 100, 48, 46, 83, 98, 70, 3, -12, -16, -23, -11, -34, -8, 46, 47, 11, -21, 8, 57, 41, 36, 53, 45, 48, -6, -64, -72, -57, -28, -61, -98, -65, -60, -94, -105, -103, -41, 1, 0, -1, -29, -6, 5, -48, -60, -26, -3, -12, -74, -97, -86, -100, -80, -89, -74, -6, 13, -10, -35, -18, 41, 48, 33, 64, 68, 75, 46, -15, -25, -7, 24, 16, -20, 4, 33, 5, -11, -5, 43, 98, 105, 105, 85, 93, 110, 67, 35, 59, 87, 81, 25, -13, -9, -23, -18, -27, -25, 30, 55, 37, -1, -3, 46, 53, 29, 44, 47, 48, 20, -48, -72, -72, -47, -48, -93, -82, -51, -73, -96, -102, -66, -6, 0, 5, -10, -16, 10, -26, -66, -49, -20, -10, -51, -98, -86, -93, -93, -85, -88, -32, 14, 8, -16, -23, 22, 54, 32, 45, 67, 70, 61, 4, -27, -21, 2, 17, -13, -13, 29, 26, -1, -5, 23, 83, 104, 106, 100, 90, 110, 87, 40, 38, 68, 80, 45, -6, -9, -14, -24, -23, -32, 8, 52, 53, 25, 1, 31, 60, 35, 30, 45, 45, 36, -24, -68, -76, -67, -49, -80, -94, -57, -54, -81, -95, -82, -23, 2, 1, 4, -12, 4, -5, -57, -65, -40, -20, -36, -87, -94, -83, -97, -87, -90, -57, 2, 18, 2, -12, 8, 10, -20, 30, 25, 21, 14, 4, 15, -48, -33, 11, -70, 54, -5, -21, -8, -3, 73, -52, 65, -55, 80, -28, -67, -3, -13, 21, -49, -2, 11, 36, 59, -60, 34, -28, 21, -25, -45, 54, 5, 0, -19, -12, 20, 54, -51, -23, 22, 36, -59, -20, 8, 28, -9, -54, 127, -44, 69, -128, 5, 69, -8, -98, 45, 69, 20, -97, 23, -7, 121, -81, -2, -21, 51, -67, -14, -24, 127, -60, 45, -116, 127, -29, -93, -23, 107, -5, -21, -62, 37, 41, 29, -74, -63, 103, 24, -59, -44, 62, 43, -28, -46, 7, 72, 19, -70, -47, 42, 53, -68, -13, 37, 59, -38, -60, 39, 66, 27, -128, 36, 77, 15, -74, -15, 75, 38, -49, -11, -39, 16, -8, -30, 35, 41, -1, -2, 17, -68, 99, -97, 60, -49, 32, -44, -29, 82, -26, 39, -35, 10, 38, -20, -21, -92, 83, -24, 13, 31, -33, 22, 45, -31, -24, 9, -24, -32, 42, -17, 34, 7, -27, 6, 61, -9, -34, -5, -8, -17, -6, -34, 17, 43, -9, 35, -34, 16, 27, -24, -17, -17, 5, -17, 42, -31, 22, 17, -26, -22, 32, 41, -27, -25, -10, -5, 16, -2, 13, -1, 48, -33, -27, 6, 16, 13, -37, -11, 18, 25, -42, -11, 46, -7, -15, 9, 15, 4, -3, -36, -24, 31, -8, 14, 12, 27, -19, -17, -14, -7, 42, -5, -15, 5, 1, -15, 14, 43, -19, 1, -25, -35, 16, 16, 29, -12, 8, -14, 1, 21, -8, -12, -22, -4, 24, 26, -16, -22, 37, 3, -41, 7, 4, 3, 30, 4, -27, 11, -6, -26, 33, 23, -23, -14, -20, -7, -4, 36, 0, 18, 10, -27, 1, 1, 16, -1, -4, -44, -5, 17, 9, 13, -4, -3, 31, 24, -14, -26, 9, -27, -28, 19, 22, 32, -11, -15, 5, 15, -23, -21, 16, 14, 18, -11, -26, 13, 10, -12, -12, 11, 14, -6, -13, -3, 6, -6, 3, 12, 32, 14, -22, -45, -10, 37, 11, -50, -11, 50, 22, -13, -4, -4, 15, -16, -33, 7, 34, -9, -14, -1, 21, 15, -14, -12, -6, 7, 8, 2, 0, -5, 6, 15, 4, -9, 13, 3, -51, -18, 27, 10, 5, -11, 6, -1, 5, 22, 2, -14, -39, -12, 19, 17, 4, 11, 5, -25, 2, 23, 8, 2, -3, -39, -22, 4, 18, 6, 14, 25, 20, -17, -20, 17, 7, -43, -38, -18, 17, 24, -6, 30, 44, 6, -36, -20, 7, 24, 1, -69, -25, 47, 15, -4, 35, 19, -18, -22, -12, 20, 39, -36, -49, 9, 28, -16, 9, 34, 36, -22, -69, -16, 39, 7, -28, -3, 33, -18, -7, 18, 53, 24, -37, -61, -10, 38, 2, -24, -11, 12, 17, 0, 28, 50, -5, -59, -57, 22, 14, -15, -5, 22, 9, -20, 19, 33, 31, -33, -62, -13, -2, 45, -9, -4, -3, 19, 8, -8, 40, 8, -16, -44, -19, 16, 3, 23, -32, 22, 5, -9, 5, 26, 21, -27, -18, -45, 3, 15, 0, 7, 7, 7, 13, 18, -10, 3, -5, -30, -30, -3, 9, 31, 17, -10, 19, 28, -33, -20, 31, 14, -67, -27, 13, 20, 29, 1, -2, 24, -3, -26, -12, 32, -7, -31, -17, 5, 22, 11, -6, 6, 7, 2, 7, 5, -12, -22, -17, -24, 22, 47, 1, 2, 10, 5, -29, -5, 13, 1, -30, -28, -5, 23, 25, 6, 5, 1, 7, 0, 5, 3, -33, -37, -6, 19, 20, 26, -1, -15, 21, 9, -14, -13, 0, -11, -24, -9, 9, 23, 1, 1, 32, 11, -25, -18, 5, -5, -6, -9, -10, 2, 18, 4, 12, 6, -2, -8, 2, 2, -7, 2, -22, -5, 17, 25, 15, -5, -1, -24, -8, -10, -5, 12, 7, -4, -10, 4, 8, 22, 11, -1, -12, -31, -17, 6, 12, 11, 5, -3, -1, 22, 0, -4, 3, -18, -17, -3, 16, 9, 2, -5, 0, 4, -9, 18, 17, -22, -19, -8, -6, 21, 11, -6, -16, 33, 13, -15, -3, -15, 1, -3, -10, -7, 8, 17, -11, 9, 19, 0, 5, 0, -18, -13, 2, -20, 10, 29, -11, -13, 5, 11, 16, 4, -25, -21, 13, -5, 1, 3, -1, 6, 13, -7, -1, 17, -6, -6, -9, -6, -3, -1, 1, 18, 11, -22, 2, 18, -2, -15, 1, 5, -12, -10, -7, 9, 26, 10, -11, 5, 0, -7, -3, -11, -9, -3, 2, -10, 19, 28, -3, -3, -4, 9, -14, -5, -7, 8, -3, -27, 5, 37, 11, -2, 3, -27, -15, 12, -2, 14, 2, -8, -16, 22, 11, -1, 10, -17, -8, -5, -23, 2, 29, 8, -21, 8, 12, 6, 8, -17, 3, -2, -12, -27, 16, 25, -5, -7, 2, 19, 1, -15, 7, 2, -5, -34, 2, 18, 17, -10, 2, 18, -1, -12, -10, 5, 1, -16, -9, 12, 21, 4, -10, 2, 12, 1, -19, -11, 20, 5, -14, -21, 5, 17, -5, 3, 17, 4, -25, -5, 5, 4, 0, -5, 2, 2, -1, 1, 13, 0, -11, -8, 3, 2, -1, -3, -3, 11, 8, -6, 2, 7, 4, -5, -23, -2, 14, -1, -15, -2, 15, 10, 1, -4, 16, 1, -24, -12, 8, 8, -20, -2, 14, 13, 10, 2, 2, -9, -6, -9, -3, 5, 7, -3, -9, 0, 2, 8, 3, -1, 2, -4, 0, -1, -1, -1, -2, -8, -14, -19, -28, -51, -53, -49, -48, -49, -44, -37, -30, -23, -14, -8, -11, -5, 3, 11, 2, 0, 8, 19, 10, 1, 6, 18, 15, 4, 4, 17, 19, 13, 9, 20, 27, 26, 26, 33, 42, 45, 53, 59, 68, 69, 83, 89, 92, 85, 88, 91, 80, 56, 37, 29, 9, -25, -54, -65, -74, -94, -113, -112, -103, -101, -103, -93, -79, -66, -62, -50, -41, -33, -27, -17, -11, -12, -8, 0, 7, -1, -2, 5, 15, 8, -1, 3, 15, 13, 2, 2, 12, 17, 12, 8, 15, 23, 24, 25, 29, 38, 42, 50, 56, 65, 68, 78, 87, 91, 87, 87, 91, 84, 64, 43, 33, 16, -14, -44, -60, -70, -87, -107, -111, -105, -101, -103, -96, -84, -70, -64, -55, -45, -36, -30, -22, -14, -14, -11, -4, 4, 0, -3, 1, 11, 8, -1, 0, 10, 12, 3, 0, 9, 15, 11, 7, 14, 22, 23, 24, 28, 37, 42, 49, 55, 64, 67, 78, 87, 91, 88, 88, 93, 86, 67, 47, 36, 20, -10, -40, -56, -67, -84, -104, -109, -105, -101, -103, -96, -85, -71, -65, -56, -46, -38, -31, -23, -16, -15, -12, -6, 2, -1, -5, 0, 9, 6, -1, -1, 8, 11, 3, 0, 8, 14, 11, 7, 13, 21, 23, 23, 27, 37, 41, 48, 54, 63, 67, 77, 86, 91, 89, 89, 93, 87, 70, 51, 39, 23, -6, -36, -53, -64, -81, -101, -107, -103, -100, -102, -96, -85, -72, -66, -57, -47, -39, -32, -25, -17, -16, -13, -7, 0, -3, -5, -1, 7, 6, -2, -2, 7, 9, 2, -1, 7, 13, 10, 7, 12, 20, 22, 23, 27, 36, 41, 48, 54, 63, 68, 77, 87, 91, 91, 91, 95, 89, 73, 54, 43, 27, -1, -31, -49, -61, -78, -98, -105, -102, -99, -101, -96, -85, -73, -66, -58, -48, -40, -33, -26, -19, -17, -14, -9, -2, -4, -6, -3, 5, 4, -3, -3, 5, 8, 1, -1, 6, 12, 10, 7, 11, 20, 22, 23, 27, 35, 41, 47, 54, 62, 68, 76, 86, 91, 91, 92, 96, 91, 76, 58, 46, 30, 3, -27, -45, -57, -75, -94, -103, -100, -98, -100, -96, -85, -74, -67, -59, -49, -41, -34, -28, -20, -19, -15, -10, -3, -5, -7, -4, 3, 3, -4, -4, 4, 7, 1, -2, 5, 11, 9, 6, 11, 19, 21, 22, 26, 35, 40, 46, 53, 61, 67, 76, 86, 91, 92, 93, 97, 93, 78, 61, 49, 33, 7, -22, -41, -54, -72, -91, -100, -99, -97, -100, -96, -86, -74, -67, -60, -51, -42, -35, -29, -22, -20, -17, -11, -5, -6, -8, -5, 2, 1, -5, -5, 2, 5, 0, -3, 3, 10, 8, 5, 10, 18, 21, 21, 25, 34, 39, 45, 52, 61, 67, 75, 85, 91, 92, 94, 97, 94, 81, 64, 52, 37, 11, -18, -37, -51, -69, -88, -98, -98, -96, -99, -95, -86, -75, -68, -61, -52, -44, -36, -30, -23, -21, -17, -13, -6, -7, -9, -6, 0, 0, -5, -5, 1, 4, -1, -3, 2, 8, 8, 5, 10, 17, 20, 21, 25, 33, 39, 45, 51, 60, 66, 75, 85, 91, 93, 94, 98, 95, 83, 67, 55, 40, 15, -14, -33, -48, -66, -85, -96, -96, -95, -98, -95, -86, -75, -69, -62, -53, -45, -38, -32, -25, -22, -19, -14, -8, -9, -10, -8, -2, -1, -6, -7, -1, 2, -2, -4, 1, 7, 6, 5, 8, 16, 19, 20, 24, 32, 38, 44, 50, 59, 66, 74, 84, 91, 93, 95, 99, 97, 85, 70, 58, 43, 18, -10, -30, -45, -63, -82, -93, -95, -94, -97, -95, -87, -76, -70, -63, -54, -46, -39, -33, -26, -23, -20, -16, -10, -10, -12, -9, -3, -3, -7, -8, -2, 1, -2, -5, 0, 6, 6, 4, 8, 15, 18, 20, 23, 31, 37, 43, 50, 58, 65, 74, 83, 91, 93, 96, 100, 98, 87, 72, 61, 46, 22, -6, -27, -42, -60, -79, -91, -94, -93, -97, -95, -87, -77, -70, -64, -55, -47, -40, -34, -28, -25, -22, -17, -12, -11, -13, -11, -5, -4, -8, -9, -3, 0, -4, -6, -1, 5, 5, 3, 7, 14, 18, 19, 23, 30, 36, 42, 49, 57, 65, 73, 83, 90, 94, 96, 100, 99, 89, 75, 63, 49, 25, -2, -23, -38, -56, -76, -88, -92, -92, -95, -94, -87, -77, -71, -65, -57, -48, -41, -36, -29, -26, -23, -19, -13, -12, -14, -12, -7, -6, -9, -10, -5, -1, -4, -7, -2, 2, 5, 4, 6, 12, 18, 20, 24, 30, 38, 45, 52, 61, 70, 79, 89, 99, 106, 109, 113, 115, 109, 96, 81, 66, 44, 16, -12, -32, -52, -74, -92, -101, -104, -107, -108, -103, -94, -85, -78, -70, -60, -52, -45, -38, -33, -29, -25, -19, -16, -17, -16, -12, -9, -10, -12, -9, -5, -5, -7, -5, 0, 3, 3, 5, 11, 17, 20, 23, 29, 37, 44, 51, 59, 69, 78, 88, 98, 105, 110, 114, 116, 110, 98, 84, 69, 48, 20, -7, -29, -49, -71, -89, -99, -102, -105, -107, -103, -94, -86, -79, -71, -62, -54, -47, -40, -34, -30, -26, -21, -18, -18, -17, -14, -10, -12, -14, -11, -5, -10, 43, -94, 44, -13, 27, -98, 1, 9, 77, 63, 4, 8, -128, 63, -73, 78, -116, 127, -14, 111, -87, -67, -43, -45, 38, 53, 99, -37, 14, -51, -58, -23, -32, 34, 27, 75, 9, 51, -104, -71, -33, 27, 67, 0, -1, 25, 0, -35, 1, -70, 28, -4, 109, 3, 5, -42, -7, 42, -15, 37, -62, 67, -14, 48, -85, -46, -94, 37, 35, 23, 15, -79, 35, -50, 91, -64, 40, -69, 46, 20, 43, -21, -51, 8, -1, 95, -47, 69, -104, 98, -44, 74, -61, -14, -19, 7, 52, -40, 8, -89, 58, -53, 106, -106, 42, -82, 61, -1, -8, -10, -59, 53, -18, 85, -83, 63, -73, 89, -32, 50, -62, 10, 13, 20, 62, -81, 41, -84, 88, -32, 41, -78, 27, -30, 51, -6, -42, 6, -49, 74, -41, 41, -89, 27, -33, 57, 0, -16, -8, -4, 45, 8, 20, -63, 36, -29, 75, -23, -17, -23, -14, 45, -7, 17, -56, 20, -12, 45, -16, -13, -31, 6, 31, -7, 17, -81, 40, -35, 73, -34, 0, -31, 10, 35, -4, 19, -60, 44, -30, 83, -66, 41, -87, 59, -6, 23, -4, -59, 34, -33, 77, -70, 49, -89, 88, -45, 63, -62, 4, -20, 18, 46, -49, 45, -101, 91, -56, 78, -79, 35, -51, 67, -12, -2, -14, -49, 66, -35, 72, -87, 51, -74, 83, -38, 29, -36, -10, 23, 3, 30, -59, 27, -59, 91, -44, 41, -63, 12, 2, 23, 8, -36, 14, -35, 66, -38, 32, -59, 25, -11, 40, -6, -25, -2, -24, 55, -25, 29, -58, 30, -17, 41, -18, -17, -3, -13, 50, -25, 26, -63, 35, -23, 50, -22, -5, -18, 0, 33, -19, 22, -67, 57, -39, 63, -45, 6, -27, 13, 23, -6, 15, -55, 44, -42, 70, -59, 36, -60, 56, -13, 15, -9, -50, 49, -38, 72, -63, 37, -65, 67, -48, 55, -51, 10, 2, -5, 45, -61, 46, -83, 91, -58, 72, -69, 23, -27, 35, -8, -3, -2, -33, 66, -61, 79, -100, 67, -60, 66, -26, 13, -21, -13, 23, -11, 29, -49, 40, -53, 80, -67, 52, -63, 28, 6, -1, 23, -45, 25, -30, 42, -25, 22, -42, 33, -26, 39, -26, -9, 10, -28, 61, -50, 33, -43, 18, 2, 6, 4, -18, 4, -8, 24, -21, 22, -49, 50, -40, 52, -35, -10, 17, -34, 64, -53, 38, -47, 37, -28, 40, -47, 33, -32, 28, 3, -20, 30, -69, 79, -75, 88, -72, 39, -34, 22, -7, 9, -18, 1, 19, -27, 58, -89, 81, -90, 89, -58, 42, -27, -5, 16, -21, 29, -34, 28, -37, 59, -65, 72, -90, 69, -45, 31, 6, -36, 40, -53, 56, -47, 39, -42, 40, -38, 50, -52, 34, -31, 7, 32, -47, 62, -79, 66, -51, 41, -27, 12, -10, 12, -5, 3, -5, -18, 33, -44, 70, -75, 60, -52, 27, 4, -19, 22, -29, 27, -15, 18, -31, 26, -36, 50, -41, 35, -31, 3, 19, -37, 55, -62, 51, -38, 25, -11, 1, -13, 12, -7, 13, 4, -33, 38, -56, 72, -64, 52, -43, 20, 6, -20, 25, -40, 34, -25, 38, -41, 43, -68, 68, -59, 53, -28, -7, 27, -45, 63, -70, 56, -60, 59, -41, 48, -56, 39, -43, 35, -3, -19, 40, -70, 85, -81, 76, -75, 48, -36, 41, -20, 12, -23, 0, 16, -23, 51, -76, 78, -82, 80, -57, 29, -23, 3, 14, -2, 9, -29, 17, -31, 55, -51, 53, -66, 49, -27, 17, 3, -35, 36, -33, 44, -27, 11, -30, 24, -18, 37, -29, 4, -3, -15, 45, -47, 42, -57, 46, -19, 18, -11, -20, 10, -3, 24, -18, 14, -46, 52, -50, 64, -57, 25, -14, 1, 33, -42, 30, -52, 50, -28, 47, -54, 32, -49, 53, -25, 14, -4, -34, 57, -54, 69, -78, 46, -45, 52, -21, 21, -37, 7, 1, 3, 29, -57, 56, -74, 90, -66, 47, -51, 16, 6, 10, 10, -29, 9, -32, 58, -47, 59, -84, 65, -49, 52, -24, -18, 14, -30, 61, -39, 31, -57, 39, -38, 67, -56, 37, -46, 26, 10, -15, 18, -49, 45, -27, 42, -37, 11, -24, 30, -15, 21, -34, 15, -5, 11, 5, -24, 11, -16, 30, -16, 6, -20, 7, 3, 11, -9, -5, -6, 4, 16, -15, 9, -29, 22, -6, 14, -6, -16, 9, -12, 28, -22, 15, -27, 22, -11, 21, -23, 5, -10, 8, 17, -22, 19, -42, 41, -31, 39, -37, 20, -20, 19, -3, -7, 2, -17, 27, -20, 30, -43, 30, -34, 38, -24, 13, -13, -1, 16, -16, 19, -36, 28, -21, 30, -22, 7, -17, 11, 2, 1, 1, -19, 22, -21, 32, -34, 18, -21, 17, 6, -8, 5, -25, 21, -13, 24, -24, 12, -22, 24, -11, 10, -14, -7, 15, -11, 28, -36, 21, -30, 30, -10, 10, -13, -5, 6, -2, 14, -22, 15, -25, 33, -22, 23, -31, 11, -6, 8, 11, -21, 14, -28, 32, -23, 25, -31, 19, -15, 19, -7, -7, 1, -13, 26, -19, 24, -37, 25, -24, 30, -18, 6, -9, -2, 17, -16, 17, -34, 27, -19, 28, -21, 6, -15, 10, 4, 0, 2, -20, 22, -19, -21, 0, -3, -3, 2, 1, -1, 2, -2, -1, 4, 3, -3, -15, -21, -20, -23, -42, -45, -31, -27, -17, -8, 9, 29, 41, 44, 33, 20, 13, 6, 12, 16, 25, 43, 44, 33, 33, 35, 15, -5, -3, 8, 16, 8, -10, -6, 8, 4, -4, 1, -18, -38, -43, -51, -54, -55, -71, -85, -68, -58, -61, -50, -33, -27, -15, -5, 22, 67, 100, 109, 114, 110, 91, 69, 50, 37, 35, 46, 48, 37, 36, 14, -24, -38, -42, -38, -38, -59, -91, -86, -57, -44, -32, -15, -26, -44, -30, -30, -30, -16, -31, -50, -34, -43, -59, -49, -44, -52, -62, -69, -50, -4, 47, 83, 105, 120, 111, 88, 72, 55, 57, 76, 69, 59, 55, 41, 10, -18, -32, -28, -19, -36, -68, -76, -72, -71, -46, -35, -47, -43, -43, -61, -48, -28, -25, -22, -19, -23, -15, -7, 3, 4, -8, -28, -37, -5, 42, 72, 107, 127, 122, 117, 90, 48, 37, 48, 51, 54, 56, 43, 24, -8, -37, -33, -11, -28, -55, -61, -75, -75, -51, -58, -55, -33, -33, -41, -35, -30, -21, -16, -17, -24, -26, -20, -18, -17, -12, -36, -72, -65, -45, -6, 53, 88, 106, 119, 107, 71, 52, 50, 59, 75, 87, 85, 76, 43, -1, -7, 9, -1, -13, -34, -69, -80, -74, -80, -73, -65, -67, -65, -56, -44, -33, -23, -18, -24, -25, -16, -20, -9, -1, -21, -38, -55, -64, -40, 3, 39, 82, 113, 114, 95, 71, 54, 56, 68, 76, 87, 94, 57, 10, -9, -17, -17, -15, -35, -60, -75, -89, -92, -85, -76, -71, -74, -70, -53, -41, -20, -9, -9, 4, 4, 10, 33, 38, 25, 15, -17, -43, -33, -15, 3, 40, 77, 94, 91, 69, 37, 31, 33, 37, 68, 96, 82, 53, 25, 8, 22, 28, 9, -9, -27, -46, -56, -65, -62, -61, -60, -51, -51, -39, -25, -23, -11, -3, -15, -10, 5, 12, 20, 18, -11, -41, -52, -47, -34, -2, 33, 65, 82, 70, 51, 45, 28, 21, 49, 74, 86, 74, 33, 5, 10, 14, 7, -10, -28, -45, -67, -68, -73, -76, -66, -66, -65, -46, -39, -31, -9, -3, -6, 1, 8, 22, 41, 49, 33, 8, -16, -34, -30, -17, 7, 49, 73, 64, 63, 50, 19, 5, 13, 32, 62, 65, 37, 8, -5, 4, -1, -8, -15, -36, -50, -57, -71, -65, -53, -58, -49, -37, -40, -28, -10, -3, 0, 2, -2, 5, 30, 41, 36, 22, -7, -33, -39, -46, -30, 15, 44, 56, 72, 65, 44, 21, 2, 15, 42, 59, 49, 18, 2, -3, -4, 0, -10, -25, -34, -52, -65, -59, -56, -50, -37, -33, -33, -25, -12, -2, 10, 12, 3, 6, 27, 42, 52, 43, 16, -3, -24, -48, -41, -11, 16, 48, 67, 78, 75, 49, 21, 13, 36, 64, 63, 47, 25, -1, -2, 2, -12, -18, -28, -53, -65, -71, -76, -70, -55, -53, -49, -41, -35, -24, -1, 5, 1, 4, 8, 28, 51, 43, 26, 18, -14, -42, -51, -49, -23, 5, 31, 55, 67, 58, 26, -2, 11, 35, 49, 55, 35, 8, 3, -2, -5, -6, -13, -30, -38, -49, -61, -56, -45, -43, -36, -31, -37, -25, -7, 1, 6, 1, -10, 11, 33, 29, 27, 17, -6, -34, -58, -67, -57, -34, -4, 21, 50, 63, 37, 11, 8, 17, 45, 63, 55, 39, 26, 12, 11, 10, -1, -11, -19, -35, -51, -52, -52, -45, -35, -36, -41, -31, -24, -9, 9, -3, -12, 2, 19, 33, 40, 37, 25, -3, -30, -51, -59, -42, -24, -3, 38, 58, 51, 32, 8, 2, 25, 45, 50, 49, 35, 18, 16, 19, 10, 9, 4, -13, -27, -36, -45, -36, -24, -32, -29, -31, -33, -10, 6, 1, -4, -6, 4, 19, 30, 37, 30, 12, -13, -48, -59, -57, -56, -35, 2, 31, 48, 41, 12, -2, 7, 25, 41, 52, 44, 29, 25, 22, 18, 20, 15, 1, -6, -26, -38, -28, -26, -21, -17, -31, -33, -19, -4, 0, -8, -16, -15, -11, 9, 19, 22, 24, -2, -34, -49, -61, -70, -57, -32, 4, 38, 46, 26, 5, -1, 7, 29, 45, 44, 38, 32, 23, 27, 30, 23, 24, 14, -8, -16, -24, -24, -12, -10, -19, -27, -26, -9, -2, -4, -6, -16, -14, -2, 8, 23, 34, 17, -6, -26, -47, -61, -62, -50, -18, 26, 50, 48, 31, 12, 6, 24, 40, 44, 51, 40, 29, 34, 28, 27, 32, 20, 7, -5, -23, -26, -19, -9, -12, -25, -25, -17, -8, 1, -4, -13, -12, -16, -9, 13, 26, 23, 8, -13, -37, -55, -71, -78, -59, -18, 16, 35, 34, 8, -3, 4, 13, 31, 40, 34, 34, 29, 23, 30, 31, 27, 21, 7, -6, -21, -21, -10, -10, -19, -24, -28, -17, -6, -8, -9, -9, -19, -21, -5, 12, 23, 22, 5, -16, -34, -55, -80, -78, -56, -22, 18, 33, 24, 14, 3, 7, 25, 31, 37, 41, 33, 29, 29, 32, 33, 30, 24, 7, -16, -22, -18, -15, -14, -24, -31, -22, -13, -12, -8, -6, -18, -27, -22, -6, -5, -1, -1, -1, 1, 2, 7, 13, 19, 10, -12, -31, -13, 17, 29, -4, -29, 24, 53, 18, 92, 15, -15, 23, 13, -35, -52, 127, 9, 3, -9, 31, -63, -64, -5, -50, 14, 33, -29, -42, 0, 43, 39, -15, -59, -45, 3, 33, 12, -35, -10, 51, 18, 49, 55, -28, 16, 4, 3, -64, 54, 53, -12, 0, 5, -4, -72, -7, -31, -14, 26, -2, -37, -14, 17, 35, 4, -33, -45, -12, 15, 21, -16, -23, 22, 28, 12, 55, -7, -2, 7, 7, -34, -10, 65, -4, 1, -5, 14, -46, -28, -9, -29, 13, 13, -23, -23, 4, 27, 18, -17, -39, -25, 5, 20, 0, -26, 1, 34, 7, 41, 24, -20, 11, 1, -6, -45, 53, 22, -6, -4, 9, -17, -52, -4, -30, -6, 20, -9, -29, -8, 18, 27, -2, -33, -36, -6, 16, 13, -20, -16, 27, 19, 18, 49, -17, 3, 2, 6, -42, 9, 55, -9, 1, -3, 9, -54, -19, -16, -24, 16, 7, -27, -19, 8, 28, 12, -22, -40, -20, 8, 19, -7, -25, 9, 31, 7, 48, 9, -14, 9, 2, -17, -35, 62, 9, -2, -6, 13, -30, -44, -4, -31, 2, 18, -15, -27, -3, 22, 24, -8, -36, -32, -2, 17, 8, -23, -9, 31, 13, 28, 40, -21, 8, 1, 3, -47, 29, 43, -9, 0, 1, 1, -57, -11, -22, -17, 19, 2, -28, -14, 12, 29, 7, -27, -39, -14, 11, 17, -13, -22, 17, 27, 10, 51, -4, -7, 7, 5, -27, -19, 64, -1, 1, -6, 14, -41, -34, -8, -30, 8, 15, -20, -24, 2, 25, 20, -14, -38, -27, 2, 18, 2, -25, -1, 33, 9, 37, 29, -21, 11, 0, -3, -46, 46, 29, -7, -2, 7, -9, -54, -6, -27, -10, 20, -4, -28, -9, 16, 28, 1, -30, -37, -8, 14, 14, -18, -17, 25, 22, 16, 50, -13, 1, 4, 5, -37, 0, 59, -7, 2, -4, 12, -49, -24, -13, -26, 13, 11, -23, -19, 6, 27, 15, -19, -39, -21, 6, 18, -4, -24, 7, 32, 8, 45, 15, -16, 10, 2, -12, -39, 58, 16, -3, -5, 11, -22, -48, -4, -30, -2, 19, -10, -26, -4, 20, 25, -5, -34, -33, -4, 16, 10, -21, -11, 30, 16, 25, 43, -19, 7, 1, 4, -44, 20, 49, -8, 1, -1, 6, -54, -15, -19, -20, 17, 6, -26, -15, 10, 29, 9, -23, -39, -16, 9, 17, -10, -22, 15, 29, 10, 50, 2, -10, 8, 3, -22, -26, 63, 5, 0, -6, 14, -34, -39, -6, -30, 4, 17, -15, -24, 0, 24, 22, -11, -36, -28, 1, 17, 5, -23, -3, 32, 12, 34, 33, -21, 10, 0, 0, -46, 39, 36, -7, -1, 4, -3, -54, -9, -24, -14, 19, 0, -26, -10, 14, 28, 4, -27, -37, -11, 12, 15, -15, -18, 22, 24, 14, 50, -9, -2, 5, 5, -32, -8, 61, -3, 2, -5, 14, -44, -29, -10, -27, 10, 13, -20, -20, 4, 26, 17, -16, -37, -23, 4, 18, -1, -23, 5, 32, 9, 42, 20, -18, 11, 1, -7, -41, 53, 22, -4, -3, 9, -14, -50, -6, -27, -7, 19, -6, -26, -5, 18, 26, -2, -31, -34, -6, 14, 11, -19, -12, 28, 19, 22, 45, -17, 4, 2, 5, -40, 11, 54, -6, 2, -3, 10, -51, -20, -16, -23, 14, 9, -23, -15, 8, 28, 12, -20, -38, -18, 7, 17, -7, -22, 13, 30, 10, 47, 7, -12, 9, 2, -17, -31, 61, 10, 0, -5, 13, -26, -43, -6, -29, 0, 18, -11, -23, -1, 22, 23, -8, -34, -30, -1, 15, 7, -22, -5, 31, 14, 30, 37, -20, 9, 0, 2, -44, 30, 42, -7, 1, 2, 2, -53, -12, -21, -17, 17, 4, -25, -11, 12, 28, 6, -25, -37, -13, 10, 15, -13, -18, 20, 26, 13, 49, -5, -5, 6, 4, -27, -16, 62, 1, 2, -5, 14, -38, -34, -9, -28, 6, 15, -16, -20, 3, 25, 19, -13, -36, -25, 2, 16, 1, -23, 3, 32, 11, 38, 25, -19, 11, 0, -4, -43, 46, 29, -4, -2, 7, -8, -51, -8, -25, -10, 18, -2, -25, -7, 16, 27, 0, -28, -35, -8, 12, 12, -17, -13, 26, 21, 19, 46, -14, 2, 3, 4, -36, 2, 57, -4, 3, -4, 12, -46, -25, -13, -25, 11, 12, -20, -16, 7, 27, 14, -18, -37, -20, 5, 16, -5, -21, 10, 31, 10, 45, 12, -14, 10, 1, -12, -36, 57, 16, -1, -4, 11, -20, -46, -6, -28, -4, 18, -8, -23, -3, 20, 24, -5, -32, -31, -4, 13, 8, -20, -6, 29, 17, 27, 39, -19, 7, 0, 3, -42, 21, 47, -6, 2, 0, 7, -51, -17, -18, -20, 15, 7, -23, -12, 10, 28, 8, -22, -37, -15, 8, 15, -10, -19, 18, 27, 13, 47, 0, -8, 8, 3, -24, -20, 52, -36, -2, 0, -2, 3, 5, -4, -28, 22, -43, 36, -13, -127, -43, 2, -18, 126, 78, -127, -48, 68, -74, -67, 33, 62, 83, 42, -32, -46, -70, -26, 115, 21, -66, 72, 52, -27, 44, 50, 50, 61, 28, -12, 3, -59, 49, 3, -19, 39, 94, 16, 31, 6, 29, 3, -100, -1, -4, -60, 19, 7, -29, -28, -38, -3, -47, -20, -21, -1, 5, -55, -12, -55, -39, 26, 47, -22, -9, -41, -21, -19, -37, 0, 45, -56, 24, 75, -50, -9, 31, 28, 26, 13, -3, -15, -27, 1, 1, -31, -10, 38, -1, 7, 43, 19, 21, 41, 33, 9, -17, -3, -42, -76, -30, -8, -9, -1, 21, 22, 38, 32, 22, 0, -18, -32, -58, -12, 5, -48, -13, 64, 29, -2, 2, 19, 43, 25, -19, -39, -69, -92, -15, 23, 30, 30, 51, 37, 35, 37, 30, -27, -63, 5, -30, -56, -16, 26, 52, 20, 14, 59, 27, -9, 22, -4, -20, -37, -17, -34, -34, -1, 35, 26, 31, 5, -16, 4, 33, 22, 8, 5, -28, -41, -20, -10, -6, -2, -16, 12, 31, -23, 7, -2, -39, -28, -13, 8, 5, 16, -4, -6, -18, -24, -27, -50, -6, 5, 12, 0, -2, -14, -23, 5, -28, -10, 2, 28, 15, 2, 22, 27, 41, 31, 2, 12, 31, 5, 12, -6, 15, 40, 34, 18, 26, 26, 12, 34, 23, 34, 30, 22, 10, -26, -22, 1, 0, -1, 12, -4, -21, -5, -5, -20, -31, -25, -24, -42, -44, -41, -41, -37, -29, -28, -29, -40, -17, -21, -38, -42, -38, -40, -36, -13, -14, -8, -15, -7, -6, 5, 12, -1, -17, -1, 9, 2, 16, 30, 27, 37, 36, 38, 36, 36, 19, 45, 45, 33, 26, 33, 28, 36, 31, 17, 12, 22, 11, 11, 17, 5, -13, 6, 10, 2, -6, 2, 9, 15, -6, -8, -23, -44, -3, -11, -35, -25, -35, -23, -21, 0, -11, -21, -17, 11, -6, -11, -17, -33, -16, -16, -4, -7, -7, -9, -4, 1, 1, -3, 6, 7, 4, -17, -11, -6, -4, 1, 3, 6, 4, 5, -4, 17, 7, 3, 9, -20, 0, -7, -3, -5, 4, 9, 16, 2, 3, 8, 15, 15, 1, -3, 8, -1, 5, 14, 7, 4, 8, -8, 2, -3, 5, 11, 5, 3, -4, 10, 17, 13, -11, -5, 1, -3, 0, -6, -12, 2, -3, 13, -5, -25, -15, -7, 4, 1, -8, -4, -12, -16, 3, 9, -6, 3, -21, -4, 4, -14, 1, -1, -2, 3, -8, -5, 0, 7, -2, -3, -1, 3, -9, 5, -4, -17, -1, 9, 3, 7, 1, -4, -3, 5, 2, -7, -9, 12, -6, -14, -16, 2, -1, 16, 2, 2, 7, -6, -26, 3, -2, -4, -2, 10, 3, -7, 3, 8, 9, 5, 4, 1, -5, -5, 11, 8, 7, 11, 12, -1, -5, -16, 13, 7, 2, 11, 4, -4, 9, -8, -8, 14, 11, -8, 0, -1, -5, -2, -1, -10, -5, -9, -9, -16, -12, -8, -16, 5, -10, -4, -11, -3, 1, 0, -3, -5, -13, -9, -2, -8, 5, -9, -7, -2, 2, -11, -7, 13, 8, -3, 2, 7, -2, -1, 5, 0, 11, 6, 13, 15, 1, -4, 9, 5, 3, 8, -3, -4, 16, 4, 11, 9, 0, 8, 1, -6, -5, -18, 3, 7, -18, -4, 0, -3, -3, -6, -4, -5, -5, -10, -2, -9, -5, -2, -4, -11, -2, 1, -5, -2, 11, -6, -9, 1, 4, -6, -1, -5, 1, 2, 9, 5, 0, 4, 4, -2, 7, 0, -10, 5, 2, -3, 0, -6, 7, -4, -3, 6, -1, -6, -1, -1, 2, -2, -6, -3, 0, 8, -6, 4, -1, -5, -3, 3, 1, -5, -6, -2, -3, 5, 6, 0, 7, -3, 3, -1, 0, -2, 9, 1, 1, -3, 4, 5, -5, 2, -2, 2, -11, -2, -4, 11, 4, 5, 0, -5, -12, -6, -5, -5, 3, -2, -2, 2, 2, 1, 0, -1, -8, -5, -5, -3, 2, -1, 3, -1, 3, 0, -1, 0, -1, 1, 1, -4, -4, 2, -2, 1, -6, 1, 2, 4, 2, 2, -5, -1, 6, -3, -1, -4, 11, 3, -9, -2, -6, -3, 2, 4, 2, 1, 2, 4, 3, -6, -4, -3, -2, 0, 2, -2, 5, 2, -1, 3, -9, -3, -3, -4, -4, -1, 0, -2, 7, 3, 1, 1, -2, -4, -2, -3, -2, -4, 2, 4, -1, 2, 3, 0, 3, -1, 0, -2, -2, -3, 1, -1, -4, 5, -1, 5, 0, -3, -2, -1, -4, 3, -1, -3, -2, -2, -1, 0, 0, 1, -1, 0, -2, -2, 0, -3, -1, 0, 0, 1, 1, -2, -1, 1, -3, 1, 2, 0, -1, 0, -1, 1, 5, -2, 1, -3, -3, -1, -3, 0, 1, 3, 2, -1, -1, -2, -2, -1, 1, 0, -1, -2, -2, -2, -3, -3, -3, -2, -2, -2, -2, -2, -2, -2, -1, 0, 1, 1, -2, -2, 0, 0, 2, -3, -16, -22, -20, -28, -35, -31, -17, 19, 33, 36, 33, 34, 40, 36, 25, 18, 20, 18, 14, 17, 12, 14, 10, -24, -36, -27, -38, -55, -69, -66, -47, -33, -13, 3, 5, 10, 22, 25, 15, 28, 43, 41, 51, 56, 58, 58, 31, -18, -52, -64, -71, -92, -105, -98, -77, -50, -17, 23, 59, 85, 99, 94, 76, 55, 14, -9, -5, -7, -18, -17, -35, -53, -53, -33, -23, -33, -36, -15, 17, 32, 24, 12, 19, 37, 54, 49, 38, 21, -14, -44, -30, -22, -15, 5, 8, -1, -26, -42, -46, -49, -51, -37, -17, 1, -4, -19, -4, 45, 84, 91, 79, 57, 3, -30, -29, -35, -25, -8, -6, -26, -61, -75, -73, -77, -72, -54, -19, 9, 6, -10, 3, 47, 85, 92, 103, 92, 45, 21, 6, 4, 16, 27, 27, -1, -48, -69, -78, -80, -84, -72, -33, -10, -24, -41, -20, 40, 82, 99, 123, 102, 69, 49, 30, 27, 34, 42, 41, -2, -58, -96, -108, -103, -106, -83, -37, -10, -18, -38, -18, 40, 65, 92, 110, 84, 44, 1, -26, -23, -7, 21, 32, 7, -39, -78, -84, -79, -82, -61, -19, 5, -14, -52, -25, 25, 59, 102, 127, 116, 86, 40, 13, 4, 9, 27, 29, 4, -47, -88, -94, -87, -83, -56, -18, 15, -13, -49, -30, -2, 29, 69, 87, 80, 50, 9, -15, -27, -10, 18, 44, 36, -9, -45, -53, -53, -46, -33, 6, 31, -8, -36, -28, -11, 21, 54, 76, 76, 44, 4, -33, -53, -45, -18, 13, 10, -35, -62, -70, -61, -44, -19, 38, 63, 30, 9, 4, 9, 35, 60, 81, 75, 51, 14, -25, -44, -37, -9, 29, 24, -11, -41, -59, -51, -54, -33, 23, 35, 6, -13, -28, -18, 8, 43, 73, 76, 63, 33, -1, -21, -22, 10, 43, 35, 5, -32, -47, -51, -68, -44, 6, 14, 0, -21, -34, -25, 0, 37, 65, 73, 64, 35, 5, -22, -25, 11, 40, 39, 13, -20, -28, -42, -64, -32, 6, 15, -1, -25, -39, -39, -16, 19, 44, 58, 53, 27, -2, -39, -38, -2, 30, 40, 13, -16, -19, -45, -60, -29, 6, 17, 1, -21, -40, -44, -24, 9, 38, 58, 51, 38, 8, -31, -29, 0, 34, 44, 9, -11, -23, -58, -69, -42, -6, 9, 0, -16, -33, -36, -12, 19, 55, 72, 68, 58, 18, -22, -25, -6, 29, 31, 2, -5, -23, -57, -69, -45, -8, 12, 10, 0, -22, -24, -7, 20, 52, 61, 65, 59, 21, -15, -28, -11, 26, 20, 2, -2, -22, -56, -71, -49, -14, 3, 8, -5, -26, -28, -19, 14, 42, 54, 71, 67, 38, 8, -11, 16, 47, 37, 26, 18, -10, -51, -74, -59, -35, -19, -12, -24, -37, -44, -34, 0, 24, 44, 67, 64, 43, 3, -18, 11, 35, 28, 22, 18, -4, -47, -68, -55, -34, -11, -7, -15, -27, -43, -32, -1, 18, 42, 58, 60, 43, -8, -29, -6, 11, 7, 4, 4, -17, -59, -75, -66, -41, -13, -3, 1, -11, -29, -19, 1, 19, 42, 53, 64, 45, -8, -28, -9, 7, 4, 4, 9, -13, -51, -71, -69, -43, -19, -7, 3, -11, -25, -17, -2, 23, 43, 60, 78, 55, 1, -19, -5, 8, 3, 7, 13, -8, -41, -66, -67, -40, -19, 3, 16, 1, -7, -5, 10, 34, 46, 67, 87, 62, 11, -13, -1, 8, 4, 15, 20, 1, -33, -64, -65, -48, -30, -2, 6, -5, -14, -18, 1, 21, 32, 62, 86, 66, 20, -3, 6, 7, 5, 16, 20, 7, -29, -62, -65, -59, -39, -13, -5, -8, -22, -27, -6, 7, 17, 49, 74, 58, 14, -5, -2, -4, -3, 7, 14, 6, -32, -59, -66, -63, -40, -16, -2, -2, -19, -20, -1, 6, 18, 49, 77, 62, 21, 3, -1, -5, -2, 5, 18, 10, -26, -50, -65, -64, -43, -24, -5, -6, -24, -23, -8, -2, 10, 45, 75, 60, 25, 6, -4, -4, -5, 3, 20, 8, -20, -43, -60, -58, -45, -24, 1, -1, -15, -12, -1, 3, 16, 53, 83, 70, 42, 19, 9, 7, 3, 16, 29, 17, -7, -35, -55, -56, -49, -24, 2, -1, -11, -7, 3, 4, 16, 55, 83, 75, 50, 25, 15, 6, 0, 13, 21, 13, -9, -40, -58, -66, -62, -35, -11, -11, -18, -13, -3, -7, 9, 49, 75, 74, 51, 28, 19, 5, 1, 13, 20, 16, -3, -28, -48, -62, -61, -37, -16, -13, -20, -15, -12, -19, -5, 21, 50, 61, 47, 28, 15, -1, -6, 0, 9, 14, 1, -19, -37, -55, -56, -38, -16, -11, -13, -9, -9, -16, -8, 18, 48, 59, 44, 28, 9, 15, -3, 2, -5, 3, 3, 4, 1, 7, -2, 7, -4, 2, -124, -37, 33, -48, 7, -27, 8, -14, 77, 26, -9, 26, 7, 20, 10, 13, 8, 9, 7, 4, 5, 2, 3, 2, 1, -1, 0, -3, -2, -5, 1, -10, 11, 70, -6, 21, 5, 27, -2, 41, -15, -61, -66, -128, 0, -48, -21, -46, -6, -55, 23, 53, -6, 11, 2, 14, 11, 10, 11, 8, 9, 9, 8, 5, 8, 5, 6, 5, 6, 2, 7, -4, 6, 5, -23, 62, 29, 24, 8, 33, 4, 32, 36, -30, -16, -124, -58, -39, -18, -51, -3, -43, -40, 53, 19, 12, 4, 9, 12, 13, 10, 11, 9, 8, 11, 6, 5, 8, 6, 3, 9, 1, 7, 2, -5, 22, -33, 20, 37, 35, 7, 29, 14, 8, 52, -5, 17, -64, -84, -70, -15, -55, -23, -12, -72, 1, 28, 16, 8, 6, 7, 12, 10, 8, 11, 6, 8, 10, 5, 4, 10, 1, 8, 4, 2, 10, -15, 26, -16, -9, 14, 42, 17, 19, 29, -3, 42, 14, 28, -8, -45, -92, -37, -41, -54, 0, -53, -48, 2, 18, 10, 8, 4, 8, 12, 8, 10, 10, 6, 9, 10, 2, 10, 5, 3, 9, -2, 18, -16, 17, 3, -9, -12, 26, 28, 13, 35, 3, 27, 19, 31, 17, 4, -60, -67, -33, -66, -22, -22, -58, -38, 2, 11, 9, 7, 4, 9, 10, 8, 10, 9, 5, 12, 5, 5, 9, 2, 11, -5, 21, -8, 4, 10, 5, -17, -1, 28, 11, 34, 13, 20, 17, 28, 24, 27, -6, -61, -41, -57, -51, -17, -36, -56, -32, -1, 7, 8, 5, 6, 8, 10, 8, 12, 6, 9, 9, 5, 9, 1, 15, -7, 15, 5, -2, 4, 14, -3, -18, 15, 8, 28, 21, 20, 16, 23, 23, 29, 30, -20, -38, -45, -63, -38, -23, -43, -53, -29, -5, 5, 5, 5, 5, 9, 7, 11, 8, 8, 10, 5, 12, -2, 16, -1, 4, 11, 4, -3, 8, 15, -16, 0, 1, 16, 23, 23, 17, 20, 21, 21, 39, 19, -14, -28, -52, -58, -33, -28, -47, -50, -30, -6, 2, 5, 4, 6, 6, 9, 10, 7, 12, 3, 15, 0, 10, 8, 1, 6, 11, 2, -4, 20, -1, -6, -5, 4, 15, 24, 20, 18, 23, 15, 30, 38, 13, -6, -27, -56, -52, -30, -34, -48, -50, -28, -8, 2, 3, 5, 5, 6, 11, 5, 13, 3, 12, 6, 5, 10, 5, 2, 7, 13, -8, 10, 11, 0, -6, -4, 3, 17, 23, 16, 24, 18, 17, 36, 32, 13, -1, -30, -57, -45, -31, -36, -51, -49, -28, -7, -1, 3, 6, 2, 11, 5, 12, 6, 9, 10, 5, 8, 8, 5, -1, 16, 1, -1, 11, 9, -1, -5, -5, 4, 20, 17, 20, 24, 14, 23, 37, 29, 16, 2, -33, -53, -42, -30, -39, -52, -49, -27, -9, -3, 5, 0, 8, 5, 10, 8, 6, 10, 6, 7, 6, 11, -3, 8, 11, 0, 2, 11, 8, -1, -5, -7, 9, 18, 16, 24, 20, 14, 27, 35, 27, 21, 1, -33, -50, -38, -32, -42, -53, -48, -25, -14, -1, -2, 4, 3, 6, 9, 5, 9, 7, 7, 4, 12, 4, 1, 10, 6, 2, 6, 10, 4, 0, -6, -2, 11, 14, 18, 22, 17, 20, 32, 34, 28, 20, 0, -26, -36, -34, -37, -45, -54, -44, -30, -13, -8, -3, 1, 2, 6, 4, 7, 8, 8, 2, 8, 10, 1, 4, 6, 5, 5, 9, 6, 1, -3, -5, 3, 10, 14, 18, 18, 17, 26, 35, 35, 29, 17, -1, -17, -24, -32, -41, -50, -51, -44, -28, -18, -12, -5, -2, 2, 3, 3, 6, 9, 4, 3, 9, 6, 2, 2, 4, 5, 9, 10, 4, -2, -5, -1, 5, 10, 14, 16, 15, 19, 30, 38, 37, 29, 15, 1, -5, -14, -31, -43, -50, -52, -42, -29, -22, -16, -9, -3, 0, 0, 2, 6, 6, 2, 4, 7, 6, 2, 1, 2, 6, 11, 10, 2, -5, -4, 0, 5, 10, 14, 15, 14, 21, 32, 39, 38, 29, 14, 4, 0, -3, -19, -32, -40, -43, -41, -36, -31, -25, -19, -12, -9, -8, -6, -1, 2, 2, 0, -3, -4, -1, 3, 6, 6, 2, -3, -6, -2, 2, 2, 1, 2, 7, 16, 25, 32, 35, 35, 36, 36, 33, 24, 11, -3, -18, -32, -40, -42, -40, -36, -30, -25, -18, -12, -9, -8, -5, -1, 2, 2, 0, -3, -4, -1, 3, 7, 6, 2, -4, -5, -2, 2, 2, 1, 2, 8, 17, 25, 32, 35, 36, 36, 36, 32, 23, 10, -4, -20, -33, -41, -42, -40, -35, -30, -24, -18, -12, -9, -8, -5, -1, 3, 2, -1, -4, -4, -1, 4, 7, 6, 1, -4, -5, -2, -1, 3, 1, 3, 5, 3, -3, -1, -1, 1, -15, 1, 1, -5, -7, 7, -2, -4, 3, -2, -5, -1, -3, -3, -1, 6, 3, 2, 3, -26, -117, 35, -8, -19, 24, 58, -7, -6, 25, -9, 7, 4, 10, 2, 7, 6, 6, 0, 6, -2, -1, -3, -3, 8, 71, 0, 17, 27, 20, -102, -115, 39, -32, -18, -5, 58, -15, -12, 13, -10, -4, 1, 2, 1, 0, 6, 2, 1, 2, 0, -4, 0, -5, 2, 67, 9, 14, 28, 29, -72, -126, 27, -25, -19, -14, 58, -6, -11, 13, -5, -3, 3, 3, 4, 1, 8, 3, 3, 3, 3, -2, 2, -3, -3, 62, 17, 14, 27, 35, -45, -128, 11, -19, -20, -22, 53, 1, -12, 11, -3, -4, 2, 3, 4, 1, 7, 3, 3, 3, 3, -2, 2, -2, -9, 57, 22, 14, 25, 37, -23, -125, -8, -15, -20, -30, 46, 9, -12, 10, -2, -3, 0, 3, 3, 1, 6, 4, 2, 3, 2, -2, 1, 0, -16, 50, 26, 13, 22, 37, -2, -117, -27, -13, -18, -36, 36, 16, -13, 9, -2, -2, -2, 3, 2, 2, 4, 5, 1, 4, 2, -1, 0, 4, -20, 43, 29, 15, 20, 36, 14, -102, -43, -15, -16, -40, 26, 22, -12, 8, -2, -2, -3, 3, 1, 3, 2, 6, 1, 5, 1, 0, -1, 7, -23, 35, 31, 18, 18, 33, 27, -83, -57, -20, -14, -42, 14, 26, -9, 7, -2, 0, -5, 3, 1, 4, 1, 7, 0, 5, 1, 1, -2, 10, -24, 26, 31, 20, 17, 30, 36, -62, -65, -27, -12, -43, 2, 28, -7, 6, -2, 0, -5, 3, 0, 4, 0, 7, 0, 5, 1, 2, -4, 11, -23, 17, 32, 22, 16, 27, 42, -44, -67, -36, -9, -42, -8, 28, -3, 5, -1, 1, -5, 2, 0, 4, 1, 7, 1, 5, 1, 3, -5, 13, -22, 10, 31, 23, 17, 22, 45, -25, -66, -45, -8, -40, -18, 27, 0, 5, -1, 1, -5, 1, 0, 4, 0, 6, 2, 4, 2, 3, -6, 14, -19, 2, 29, 25, 19, 19, 47, -10, -60, -54, -10, -37, -27, 24, 4, 4, 0, 1, -5, 0, 0, 3, 1, 5, 2, 4, 2, 4, -7, 15, -16, -4, 27, 25, 21, 15, 48, 4, -51, -61, -12, -33, -34, 19, 7, 4, 1, 0, -4, -1, 0, 3, 2, 5, 3, 3, 3, 5, -8, 15, -11, -10, 24, 25, 23, 12, 45, 15, -39, -66, -18, -28, -40, 12, 10, 4, 2, 1, -3, -2, 0, 2, 2, 4, 3, 3, 3, 5, -8, 13, -6, -14, 19, 25, 25, 10, 43, 24, -25, -67, -25, -24, -45, 4, 11, 5, 3, 0, -2, -3, -1, 1, 2, 3, 3, 3, 2, 6, -9, 11, -2, -17, 15, 24, 27, 9, 39, 31, -13, -66, -33, -19, -48, -3, 11, 5, 3, 1, -2, -3, -1, 1, 2, 4, 3, 3, 2, 8, -9, 9, 3, -18, 10, 22, 29, 9, 35, 35, 0, -61, -41, -17, -49, -11, 10, 6, 3, 2, -2, -3, -2, 1, 1, 4, 3, 5, 1, 9, -9, 7, 6, -18, 5, 20, 29, 10, 32, 38, 11, -47, -45, -18, -47, -20, 5, 6, 4, 2, -1, -3, -2, 0, 1, 5, 1, 6, 1, 7, -7, 6, 6, -16, 1, 16, 27, 11, 29, 40, 20, -30, -43, -23, -46, -28, -2, 4, 4, 2, -1, -3, -2, -1, 0, 6, -1, 7, 2, 5, -6, 5, 6, -15, -3, 13, 25, 12, 26, 41, 26, -14, -36, -26, -44, -35, -11, 1, 4, 2, 0, -4, -3, -3, -1, 7, -2, 7, 4, 4, -6, 4, 7, -13, -6, 10, 23, 12, 24, 42, 31, 0, -24, -28, -42, -40, -19, -4, 4, 2, 1, -4, -3, -4, -3, 8, -3, 6, 6, 3, -6, 4, 7, -11, -8, 7, 20, 12, 21, 41, 34, -2, -31, -34, -29, -21, -12, -3, -4, -10, -7, -5, -6, -4, 5, 8, -3, -1, 7, -1, -11, -7, 0, 1, 6, 16, 28, 33, 33, 30, 13, -1, -26, -35, -30, -24, -14, -5, -4, -11, -7, -5, -6, -6, 3, 8, -2, -2, 7, 1, -11, -9, -1, 0, 4, 14, 26, 32, 33, 32, 17, 3, -22, -34, -31, -25, -16, -6, -3, -10, -8, -5, -6, -7, 2, 9, 0, -3, 6, 3, -9, -10, -2, 0, 3, 12, 24, 32, -1, 0, -3, -1, -8, -5, -16, -5, -14, -4, -13, -5, -1, -7, 16, -17, 28, -16, 47, 1, 70, 35, 97, 71, 98, 66, 32, -5, -71, -69, -122, -69, -105, -33, -67, -6, -35, 2, -12, -2, 4, -12, 16, -19, 29, -16, 44, 2, 66, 37, 92, 76, 95, 74, 33, 5, -69, -63, -122, -69, -106, -36, -66, -11, -33, -3, -9, -7, 7, -16, 18, -22, 29, -17, 42, 3, 61, 40, 86, 81, 91, 82, 34, 15, -67, -57, -122, -69, -105, -40, -64, -17, -29, -9, -6, -12, 10, -20, 20, -23, 28, -17, 39, 4, 56, 42, 80, 85, 88, 89, 35, 24, -63, -53, -119, -70, -104, -45, -62, -22, -26, -14, -2, -16, 12, -23, 20, -25, 27, -16, 35, 7, 51, 45, 74, 89, 85, 96, 38, 32, -58, -49, -116, -72, -102, -50, -60, -27, -24, -19, 0, -20, 14, -24, 20, -24, 24, -14, 31, 10, 45, 48, 69, 92, 82, 102, 40, 39, -53, -45, -112, -74, -100, -55, -57, -33, -21, -24, 3, -24, 15, -26, 19, -24, 22, -12, 27, 12, 40, 50, 63, 95, 80, 106, 43, 45, -47, -42, -107, -76, -97, -60, -55, -38, -18, -28, 4, -26, 15, -27, 18, -23, 19, -10, 23, 15, 35, 53, 59, 97, 78, 110, 47, 50, -39, -39, -102, -79, -94, -65, -52, -43, -16, -32, 5, -28, 14, -27, 16, -21, 15, -7, 18, 18, 30, 55, 54, 98, 76, 113, 51, 55, -32, -37, -96, -81, -91, -70, -50, -48, -15, -35, 6, -30, 13, -26, 13, -19, 11, -5, 13, 20, 25, 56, 50, 99, 75, 115, 56, 59, -24, -35, -90, -83, -88, -75, -48, -52, -14, -38, 5, -30, 11, -25, 10, -17, 7, -2, 9, 22, 21, 57, 47, 99, 75, 116, 61, 62, -15, -33, -82, -86, -84, -80, -47, -56, -14, -39, 4, -30, 9, -24, 6, -15, 3, 1, 5, 24, 17, 57, 44, 98, 75, 116, 66, 65, -6, -31, -75, -88, -81, -83, -46, -59, -14, -41, 3, -30, 6, -22, 3, -12, -1, 3, 1, 26, 13, 57, 41, 96, 75, 115, 72, 68, 2, -29, -69, -89, -78, -87, -45, -62, -15, -42, 0, -29, 3, -20, -1, -10, -5, 5, -2, 26, 11, 56, 40, 94, 76, 114, 77, 69, 12, -28, -61, -91, -75, -89, -45, -64, -16, -42, -2, -28, 0, -18, -5, -8, -9, 7, -6, 27, 8, 55, 38, 91, 77, 112, 82, 71, 20, -25, -55, -91, -73, -91, -46, -65, -18, -42, -5, -26, -4, -15, -10, -5, -13, 9, -9, 27, 7, 53, 37, 88, 78, 110, 87, 72, 29, -23, -48, -90, -71, -93, -47, -66, -21, -41, -9, -24, -8, -13, -13, -3, -16, 9, -11, 27, 5, 51, 37, 84, 79, 108, 93, 74, 37, -20, -42, -90, -70, -94, -49, -66, -24, -40, -12, -23, -12, -12, -16, -2, -18, 10, -12, 25, 5, 48, 37, 80, 81, 105, 98, 75, 45, -16, -36, -88, -68, -94, -51, -66, -28, -39, -16, -21, -15, -10, -19, -1, -21, 10, -13, 24, 4, 45, 37, 76, 82, 102, 102, 76, 52, -13, -30, -85, -67, -94, -54, -66, -31, -38, -20, -19, -19, -9, -22, 0, -22, 9, -14, 22, 4, 41, 37, 71, 83, 99, 105, 77, 59, -8, -25, -82, -67, -93, -56, -65, -35, -37, -23, -18, -22, -7, -25, 0, -24, 8, -14, 20, 5, 37, 38, 67, 84, 96, 108, 79, 65, -3, -20, -79, -66, -92, -59, -65, -39, -36, -27, -17, -25, -7, -27, -1, -24, 6, -14, 17, 6, 34, 39, 63, 84, 93, 111, 80, 71, 1, -15, -75, -66, -90, -62, -64, -43, -35, -31, -16, -28, -6, -28, -1, -25, 5, -14, 14, 6, 30, 39, 58, 85, 90, 113, 82, 76, 7, -11, -70, -66, -88, -66, -62, -46, -34, -34, -15, -30, -7, -30, -2, -25, 2, -13, 11, 7, 26, 40, 53, 84, 87, 115, 84, 81, 13, -7, -65, -66, -85, -68, -61, -50, -33, -37, -15, -32, -7, -30, -4, -25, 0, -12, 7, 9, 19, 37, 52, 80, 97, 118, 113, 98, 54, 7, -41, -72, -87, -87, -75, -65, -47, -42, -29, -30, -22, -24, -19, -19, -14, -9, -2, 8, 17, 36, 50, 77, 95, 117, 115, 101, 60, 13, -35, -69, -85, -88, -75, -66, -49, -44, -31, -31, -23, -25, -20, -20, -15, -9, -2, -1, 0, 0, 0, 0, -1, -1, -1, 3, 9, 14, 14, 10, -3, -17, -13, 1, 1, 23, 33, -14, -55, -59, -80, -75, -35, -7, 51, 40, -29, -35, -53, -128, -31, 111, 72, 46, 55, -19, -73, -23, 14, 64, 104, 87, 105, 68, -54, -76, -1, -18, 12, 92, 23, -79, -93, -105, -119, -64, -20, 39, 70, 2, -45, -52, -107, -82, 73, 106, 56, 53, 12, -57, -37, 14, 52, 105, 101, 94, 85, -5, -75, -25, -1, -8, 59, 52, -45, -89, -94, -117, -90, -42, 1, 53, 29, -29, -45, -79, -104, 3, 99, 78, 63, 42, -25, -49, -7, 30, 83, 112, 103, 99, 40, -54, -58, -11, -7, 36, 68, -4, -80, -98, -114, -106, -57, -15, 33, 42, -10, -46, -66, -97, -45, 68, 90, 67, 53, 4, -40, -20, 18, 60, 103, 107, 100, 69, -15, -62, -31, -9, 15, 60, 31, -50, -90, -108, -115, -79, -33, 11, 42, 15, -33, -58, -87, -75, 21, 87, 79, 63, 27, -26, -33, 1, 40, 88, 111, 105, 85, 20, -50, -49, -17, 5, 46, 49, -17, -77, -102, -115, -95, -49, -7, 31, 28, -15, -50, -76, -84, -21, 64, 84, 71, 45, -4, -32, -13, 22, 66, 103, 108, 95, 50, -23, -56, -32, -5, 30, 55, 14, -53, -92, -111, -107, -68, -24, 16, 34, 4, -37, -66, -85, -53, 32, 81, 77, 58, 17, -25, -24, 6, 46, 89, 108, 101, 71, 6, -49, -45, -16, 15, 49, 36, -26, -77, -103, -110, -85, -41, 0, 30, 20, -21, -55, -79, -72, -5, 65, 81, 67, 36, -10, -28, -8, 27, 71, 102, 104, 85, 34, -31, -51, -29, 1, 37, 48, 2, -57, -93, -109, -97, -58, -16, 20, 28, -4, -42, -70, -79, -36, 39, 78, 74, 51, 9, -24, -18, 11, 51, 91, 105, 94, 57, -6, -48, -41, -12, 22, 48, 26, -33, -79, -103, -104, -74, -32, 6, 28, 12, -27, -60, -78, -59, 8, 66, 78, 62, 27, -13, -24, -3, 33, 74, 100, 99, 74, 20, -35, -48, -25, 8, 40, 40, -7, -61, -94, -106, -88, -49, -9, 21, 21, -11, -47, -72, -71, -22, 45, 76, 71, 43, 2, -22, -13, 16, 56, 91, 101, 85, 43, -15, -47, -36, -6, 28, 45, 16, -38, -80, -102, -97, -65, -24, 11, 25, 4, -33, -63, -75, -46, 18, 66, 75, 56, 19, -15, -20, 2, 38, 77, 98, 93, 62, 8, -38, -44, -20, 14, 41, 32, -15, -64, -94, -101, -79, -40, -2, 22, 15, -17, -52, -72, -61, -9, 49, 74, 66, 36, -2, -21, -9, 22, 61, 91, 96, 76, 31, -22, -45, -32, 0, 32, 40, 7, -43, -82, -99, -89, -56, -17, 14, 21, -2, -38, -65, -69, -33, 26, 66, 71, 50, 13, -16, -16, 7, 43, 79, 95, 85, 50, -2, -40, -40, -14, 20, 40, 24, -22, -66, -93, -95, -70, -32, 3, 21, 9, -23, -55, -70, -51, 1, 52, 71, 60, 28, -6, -19, -4, 27, 64, 90, 91, 66, 19, -27, -43, -26, 6, 34, 35, -1, -48, -83, -96, -81, -47, -10, 16, 17, -9, -43, -66, -62, -22, 33, 66, 67, 43, 7, -16, -13, 12, 48, 80, 91, 77, 39, -10, -40, -36, -8, 24, 38, 17, -28, -69, -92, -89, -62, -25, 7, 19, 4, -29, -58, -67, -42, 10, 55, 70, 55, 22, -9, -17, 0, 33, 68, 90, 86, 57, 10, -31, -41, -21, 12, 36, 30, -8, -53, -85, -94, -75, -41, -5, 17, 13, -15, -48, -67, -57, -13, 39, 68, 64, 37, 3, -16, -9, 18, 54, 84, 91, 72, 30, -17, -41, -33, -2, 28, 37, 10, -35, -74, -94, -86, -56, -19, 10, 17, -2, -36, -63, -66, -34, 19, 60, 70, 51, 17, -11, -15, 5, 39, 74, 92, 83, 49, 1, -36, -40, -16, 18, 37, 24, -17, -61, -90, -93, -70, -34, 1, 18, 8, -22, -55, -69, -50, -2, 47, 70, 61, 31, -3, -17, -5, 26, 62, 88, 90, 65, 19, -25, -42, -27, 5, 33, 33, 1, -45, -81, -95, -81, -48, -11, 14, 15, -10, -43, -66, -61, -22, 31, 65, 68, 43, 9, -14, -11, 12, 49, 80, 92, 76, 38, -10, -39, -36, -8, 24, 38, 16, -27, -70, -92, -89, -61, -25, 7, 17, 3, -31, -59, -68, -39, 8, 55, 55, 19, 0, -9, -10, -14, -13, -21, -30, -32, -44, -49, -57, -65, -72, -83, -98, -104, -117, -123, -128, -127, -128, -128, -128, -128, -127, -128, -120, -117, -109, -100, -90, -83, -72, -66, -55, -50, -33, -42, -18, -29, -18, 15, -6, 11, 7, 19, 3, 38, 5, 48, 44, 64, 57, 97, 82, 111, 104, 110, 107, 120, 116, 125, 126, 126, 126, 126, 127, 117, 125, 123, 100, 127, 101, 124, 102, 121, 109, 126, 96, 125, 116, 127, 90, 119, 87, 127, 90, 118, 95, 123, 93, 106, 90, 100, 104, 74, 84, 73, 97, 72, 71, 57, 66, 80, 36, 59, 38, 55, 35, 57, -6, 64, 10, 25, 19, 19, -22, 65, -26, 14, 2, -17, -12, 22, -40, -3, -31, -24, -38, -1, -56, -6, -48, -36, -54, -19, -56, -33, -49, -69, -49, -52, -53, -60, -61, -84, -76, -85, -96, -95, -95, -114, -93, -117, -104, -93, -101, -98, -100, -101, -96, -78, -95, -71, -70, -72, -52, -63, -70, -43, -77, -41, -48, -65, -53, -53, -59, -42, -56, -37, -64, -54, -52, -50, -54, -56, -54, -55, -62, -51, -47, -44, -67, -60, -63, -56, -64, -53, -48, -61, -53, -58, -38, -48, -32, -38, -34, -28, -26, -23, -25, -22, -6, -7, -12, -1, 5, 6, 6, -7, 22, -4, 27, 15, 18, 24, 37, 30, 47, 24, 53, 29, 63, 29, 46, 46, 51, 52, 53, 36, 54, 65, 55, 33, 64, 36, 69, 54, 26, 62, 66, 36, 68, 30, 47, 54, 58, 20, 55, 31, 40, 50, 35, 19, 56, 33, 25, 46, 18, 22, 42, 21, 25, 32, 19, 19, 26, 18, 23, 29, 24, 7, 27, 6, 33, 8, 17, -2, 14, 3, 23, 14, 7, 5, -9, -13, -10, -23, -12, -16, -27, -8, -18, -15, -3, -18, -24, -5, -23, -9, 0, -11, 4, -1, 4, 2, 5, -2, 3, -1, -7, 4, -11, 1, -12, -4, -7, -10, -11, -11, -16, -23, -15, -20, -22, -23, -20, -30, -23, -31, -25, -32, -35, -41, -34, -44, -39, -34, -49, -33, -30, -36, -29, -33, -14, -24, -32, -18, -15, -7, -9, -11, 5, -14, 27, -11, 16, -10, 13, -9, 23, -10, 19, 10, 18, 11, 29, 1, 47, 27, -4, 45, 3, 43, 40, 14, 13, 57, 16, 34, 27, 22, 30, 32, 14, 24, 27, 20, 20, 17, 4, 20, 20, 8, 8, 0, 10, -3, 17, -8, -1, -4, 1, 0, 6, -7, -3, -3, -13, -5, -6, -18, -5, -28, -12, -13, -5, -11, -5, -28, -7, -15, -10, -6, -28, -16, -12, -17, -8, -10, -19, -10, -24, -30, -32, -26, -31, -36, -32, -33, -27, -25, -26, -26, -25, -25, -23, -16, -22, -10, -11, -7, -7, 4, -10, 10, -9, 11, -8, 4, -6, 4, -8, 3, -4, 2, -3, -5, -3, -11, -8, -6, -12, -11, -7, -24, -4, -17, -9, -18, -28, -16, -29, -23, -38, -24, -34, -22, -38, -18, -27, -10, -22, -19, -21, -2, -23, 10, -19, 0, 4, 16, 7, 0, 3, 17, 14, 26, 8, 25, 27, 30, 25, 38, 31, 49, 37, 42, 45, 48, 55, 63, 46, 54, 54, 56, 59, 56, 47, 50, 53, 47, 50, 44, 42, 35, 40, 31, 37, 35, 27, 20, 23, 19, 26, 24, 18, 11, 14, 18, 24, 18, 12, 10, 3, 12, 2, 9, 4, 0, 0, 3, -4, 11, 1, 1, -1, -5, -7, 1, -6, -1, 2, -4, 1, -1, -7, -9, -11, -21, -19, -20, -28, -27, -22, -29, -24, -26, -32, -22, -25, -31, -24, -19, -22, -11, -19, -15, -4, -5, -4, 0, -6, -6, 2, -9, -5, -5, -9, -10, -7, -18, -8, -14, -14, -19, -29, -25, -16, -25, -30, -30, -30, -21, -29, -38, -37, -36, -41, -44, -53, -48, -43, -44, -55, -46, -40, -33, -36, -40, -40, -28, -25, -24, -23, -17, -15, 1, -3, -1, 5, 2, 9, 1, 4, 12, 13, 14, 15, 9, 21, 26, 32, 31, 28, 28, 41, 38, 49, 45, 46, 53, 56, 57, 57, 57, 58, 55, 48, 56, 56, 56, 45, 39, 41, 41, 44, 42, 25, 28, 27, 24, 28, 21, 14, 17, 8, 15, 22, 13, 15, 16, 3, 11, 10, 4, 6, 4, -8, 0, -2, -2, -3, -2, 1, 3, -3, -3, -6, -8, -5, 4, 3, 2, -4, -2, -1, 5, 3, -2, -2, -2, 3, 7, -2, -26, -37, -34, -30, -13, -14, -21, -24, -27, -24, -13, -7, -15, 6, 3, -30, -50, -48, -47, -41, -26, -8, 28, 43, 38, 57, 63, 56, 75, 118, 127, 117, 99, 86, 85, 66, 46, 59, 80, 69, 43, 27, -6, -47, -74, -80, -71, -57, -40, -44, -56, -78, -88, -78, -59, -52, -51, -56, -57, -47, -36, -36, -39, -39, -32, -17, 6, 24, 33, 10, -14, -14, -2, -11, -20, -15, -24, -28, -28, -25, -28, -54, -73, -65, -43, -18, 6, 27, 21, 23, 17, 22, 18, 16, 31, 50, 45, 25, 22, 8, -20, -17, 8, 29, 10, -22, -41, -45, -51, -53, -31, -18, -23, -7, 37, 54, 38, 36, 60, 100, 119, 120, 122, 125, 110, 88, 94, 99, 90, 85, 82, 54, 26, -5, -49, -83, -85, -67, -36, -14, -30, -55, -76, -86, -65, -41, -45, -60, -53, -43, -35, -34, -41, -43, -45, -35, 10, 40, 32, 3, -3, -14, -30, -38, -33, -23, -29, -26, -18, -10, -17, -37, -46, -58, -61, -45, -17, -4, -2, 19, 31, 27, 13, 22, 38, 49, 59, 69, 60, 23, -13, -11, 13, 24, 19, 24, 8, -30, -58, -58, -66, -85, -90, -61, -19, -1, -11, -5, 25, 42, 61, 92, 109, 106, 110, 104, 93, 93, 89, 82, 86, 81, 71, 51, 13, -40, -74, -87, -73, -35, -24, -50, -71, -73, -53, -50, -58, -68, -60, -61, -54, -30, -25, -40, -52, -25, 13, 32, 45, 49, 44, 28, 22, 29, 32, 20, 3, 7, 6, 0, -1, -4, -30, -63, -69, -62, -57, -49, -25, 2, 17, 24, 27, 30, 10, 4, 38, 77, 66, 32, 13, 7, 0, 9, 31, 43, 23, -11, -25, -23, -46, -83, -87, -63, -42, -19, -6, -3, 6, 27, 49, 81, 108, 121, 123, 124, 115, 110, 98, 80, 78, 77, 77, 69, 54, 8, -56, -99, -92, -53, -46, -64, -75, -73, -70, -75, -62, -67, -86, -88, -54, -28, -33, -46, -50, -40, -24, -3, 29, 51, 48, 34, 44, 44, 30, 18, 13, -3, -15, -7, -1, -10, -36, -56, -65, -79, -100, -91, -64, -52, -40, -5, 20, 9, -14, -9, 21, 49, 59, 58, 49, 25, -1, 11, 39, 39, 22, 19, 20, 8, -19, -49, -72, -69, -58, -43, -27, -24, -13, -5, 12, 38, 74, 97, 110, 124, 126, 126, 114, 105, 100, 87, 91, 108, 115, 73, 5, -41, -49, -49, -53, -45, -49, -69, -77, -60, -51, -71, -94, -96, -68, -49, -46, -44, -45, -60, -60, -27, 0, 11, 26, 37, 37, 37, 40, 42, 34, 8, -1, 14, 15, -5, -12, -18, -44, -75, -85, -88, -98, -99, -76, -36, -12, -19, -24, -11, -9, 1, 36, 71, 58, 29, 13, 17, 33, 33, 30, 35, 44, 44, 27, -3, -39, -51, -61, -55, -41, -31, -25, -29, -21, -1, 23, 46, 76, 102, 109, 110, 116, 118, 92, 61, 76, 112, 120, 93, 57, 14, -28, -54, -50, -46, -60, -83, -82, -64, -62, -82, -89, -93, -101, -88, -59, -52, -64, -75, -76, -63, -50, -30, -1, 9, 8, 11, 32, 44, 36, 29, 32, 27, 20, 22, 28, 24, 0, -21, -30, -45, -78, -97, -83, -66, -50, -32, -17, -16, -23, -20, 4, 38, 51, 47, 37, 28, 29, 27, 27, 31, 42, 54, 55, 43, 20, -5, -29, -40, -37, -30, -27, -23, -15, -12, -11, 8, 43, 67, 78, 100, 122, 126, 107, 84, 81, 92, 106, 115, 110, 79, 31, -3, -13, -26, -47, -56, -56, -58, -58, -56, -59, -72, -86, -84, -66, -57, -56, -56, -60, -74, -74, -51, -32, -24, -14, 3, 14, 15, 19, 28, 33, 19, 11, 22, 29, 18, 8, 9, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -3, -2, -1, 0, 2, -4, -13, -21, -23, -19, -8, 7, 17, 23, 26, 33, 38, 32, 17, -5, -17, -24, -20, -6, -3, -16, -29, -26, -17, -5, -1, 2, 7, 11, 17, 15, 9, 9, 3, 10, 15, 9, -14, -33, -27, -18, -6, -7, -10, -6, 0, 12, 15, 29, 38, 36, 32, 11, 0, -30, -45, -50, -39, -23, -27, -24, -15, 6, 25, 37, 51, 46, 40, 0, -19, -22, -34, -30, -40, -45, -51, -34, -1, 25, 48, 40, 43, 51, 64, 58, 5, -22, -49, -63, -69, -68, -58, -54, -16, 13, 44, 66, 61, 68, 72, 86, 47, -17, -56, -82, -88, -93, -72, -58, -40, 4, 45, 94, 98, 84, 65, 68, 71, 15, -46, -88, -90, -88, -85, -62, -56, -34, -4, 41, 80, 82, 74, 54, 70, 66, 25, -29, -70, -74, -90, -87, -79, -73, -46, -10, 54, 90, 103, 88, 76, 90, 69, 25, -38, -76, -96, -119, -111, -103, -81, -57, -12, 50, 90, 113, 98, 100, 112, 103, 60, -11, -54, -95, -121, -124, -119, -95, -71, -10, 53, 103, 116, 93, 91, 89, 80, 31, -28, -67, -108, -122, -128, -110, -87, -53, 8, 60, 107, 107, 89, 83, 83, 76, 27, -14, -52, -84, -99, -103, -82, -72, -40, 4, 53, 92, 92, 88, 85, 97, 87, 42, 3, -45, -74, -106, -111, -105, -101, -70, -30, 27, 65, 77, 83, 87, 106, 90, 58, 16, -30, -67, -101, -100, -101, -93, -68, -27, 29, 60, 77, 79, 93, 111, 96, 71, 24, -21, -73, -109, -118, -127, -118, -98, -50, 6, 43, 65, 70, 99, 115, 108, 82, 40, -1, -53, -80, -94, -105, -101, -82, -31, 18, 56, 66, 72, 95, 103, 97, 64, 29, -15, -63, -85, -102, -105, -104, -81, -35, 13, 53, 58, 69, 86, 97, 94, 67, 39, -12, -54, -80, -97, -102, -103, -77, -38, 9, 40, 45, 60, 77, 95, 88, 70, 41, -8, -46, -74, -87, -99, -100, -78, -42, 10, 37, 50, 66, 89, 110, 103, 91, 57, 9, -33, -68, -86, -105, -105, -89, -51, -2, 23, 40, 53, 80, 99, 98, 89, 53, 8, -37, -68, -90, -107, -106, -94, -51, -5, 25, 43, 58, 86, 95, 98, 86, 52, 9, -36, -64, -92, -105, -108, -95, -53, -11, 22, 37, 57, 81, 90, 96, 82, 52, 6, -34, -64, -92, -104, -113, -97, -59, -18, 15, 31, 58, 79, 92, 98, 87, 57, 9, -29, -63, -87, -100, -109, -91, -58, -13, 16, 36, 62, 78, 93, 96, 88, 56, 12, -25, -62, -83, -101, -106, -89, -57, -15, 6, 30, 52, 71, 87, 94, 89, 55, 18, -21, -55, -76, -96, -100, -88, -53, -16, 6, 31, 53, 76, 93, 105, 98, 64, 26, -18, -52, -78, -99, -105, -95, -59, -26, 0, 24, 45, 66, 81, 97, 88, 62, 28, -12, -40, -67, -84, -95, -83, -50, -21, 4, 24, 47, 64, 81, 96, 85, 63, 26, -11, -41, -69, -88, -102, -91, -64, -36, -12, 10, 34, 51, 74, 87, 81, 62, 26, -7, -40, -63, -83, -95, -83, -58, -31, -10, 14, 34, 51, 75, 85, 82, 61, 30, -3, -34, -57, -81, -92, -83, -60, -36, -15, 11, 27, 47, 69, 80, 79, 59, 30, -5, -33, -57, -82, -93, -84, -61, -38, -15, 10, 25, 48, 68, 80, 77, 58, 29, -4, -30, -56, -80, -89, -78, -54, -34, -8, 10, 0, 0, 1, 0, -2, -2, -5, -8, -3, 3, -4, -10, 2, 8, 3, 4, 5, -3, -9, 10, 26, 26, 12, -4, -40, -64, -50, 1, 55, 69, 28, -23, -65, -83, -52, 13, 67, 67, 39, 16, -15, -48, -38, 10, 53, 44, 5, -5, -14, -43, -35, 16, 54, 37, -1, -26, -53, -82, -37, 35, 67, 44, 2, -10, -20, -39, -19, 27, 55, 42, 3, -26, -67, -107, -62, 43, 110, 102, 43, -18, -63, -91, -35, 73, 120, 77, -6, -72, -113, -109, -36, 53, 78, 50, 0, -46, -72, -71, -20, 67, 112, 100, 44, -24, -88, -123, -84, 5, 71, 97, 66, 7, -53, -100, -80, -1, 83, 127, 108, 38, -57, -121, -119, -57, 24, 84, 97, 62, -4, -77, -97, -46, 32, 101, 108, 56, -20, -103, -119, -69, 18, 105, 126, 90, 6, -92, -126, -90, -3, 85, 108, 75, 0, -86, -117, -85, -6, 76, 115, 101, 30, -68, -118, -105, -33, 57, 105, 102, 41, -46, -104, -112, -59, 25, 95, 121, 81, -5, -88, -126, -94, -12, 63, 101, 76, 7, -67, -107, -73, 11, 94, 127, 102, 21, -74, -124, -95, -21, 57, 101, 82, 21, -48, -89, -59, 6, 67, 95, 60, -11, -82, -115, -81, -13, 52, 84, 52, -9, -68, -96, -56, 9, 66, 93, 63, 10, -52, -86, -54, 1, 60, 96, 70, 19, -44, -80, -51, 0, 55, 94, 69, 20, -42, -88, -76, -40, 24, 79, 72, 34, -28, -75, -63, -23, 35, 71, 48, 4, -57, -95, -67, -10, 62, 103, 75, 18, -61, -110, -86, -22, 61, 110, 90, 37, -45, -100, -87, -39, 34, 81, 70, 33, -39, -88, -76, -24, 54, 94, 76, 32, -46, -100, -92, -42, 35, 73, 62, 26, -46, -97, -93, -44, 36, 81, 75, 35, -38, -87, -81, -26, 58, 99, 85, 37, -44, -101, -103, -46, 47, 98, 97, 56, -27, -90, -99, -49, 37, 88, 95, 62, -12, -74, -93, -51, 27, 69, 71, 35, -30, -78, -87, -38, 41, 84, 90, 57, -11, -71, -96, -56, 21, 69, 86, 60, -4, -67, -97, -61, 12, 65, 88, 65, 3, -61, -94, -60, 14, 71, 96, 68, 3, -66, -104, -70, 3, 59, 84, 59, -1, -67, -107, -76, -3, 59, 89, 64, 3, -67, -111, -82, -9, 57, 92, 76, 26, -43, -93, -71, -9, 50, 80, 64, 16, -51, -100, -79, -17, 49, 88, 77, 30, -41, -95, -79, -17, 49, 87, 77, 34, -36, -92, -78, -19, 44, 82, 73, 33, -37, -95, -84, -23, 47, 89, 83, 43, -30, -92, -83, -28, 39, 79, 74, 40, -28, -87, -82, -31, 34, 71, 67, 35, -31, -88, -85, -36, 28, 68, 69, 44, -20, -79, -83, -43, 19, 59, 64, 41, -25, -89, -100, -61, 9, 60, 76, 57, -10, -75, -90, -51, 22, 74, 88, 66, 1, -61, -78, -42, 25, 71, 84, 63, -1, -67, -90, -59, 8, 59, 81, 68, 8, -56, -85, -62, 1, 50, 74, 63, 7, -53, -84, -60, 5, 55, 80, 70, 17, -43, -76, -55, 4, 49, 73, 65, 17, -41, -77, -62, -9, 38, 68, 64, 17, -43, -84, -73, -22, 23, 56, 57, 18, -36, -77, -68, -23, 20, 51, 52, 16, -36, -77, -70, -26, 18, 54, 59, 28, -22, -64, -59, -20, 21, 56, 63, 36, -12, -55, -52, -16, 25, 58, 63, 35, -14, -59, -57, -22, 18, 51, 57, 31, -16, -58, -58, -27, 10, 43, 51, 30, -16, -59, -60, -28, 12, 48, 57, 35, -13, -59, -64, -35, 7, 47, 63, 47, 1, -46, -55, -32, 7, 47, 0, 0, -1, -1, -4, 1, -1, -3, -13, -8, -14, -3, -2, -2, 1, 8, 5, 7, -21, -13, -2, -6, -8, -22, -6, 5, 11, 34, 41, 33, 13, 28, 33, 48, 35, 21, -3, -26, -18, -10, 3, 7, 22, 21, 63, 40, 41, 43, 4, -8, -43, -63, -77, -77, -59, -18, 3, 2, -21, -46, -74, -90, -108, -101, -94, -89, -84, -85, -77, -59, -50, -33, -7, 18, 37, 47, 64, 101, 127, 125, 127, 126, 126, 126, 122, 100, 87, 62, 37, 28, 27, 25, 27, 34, 25, -4, -45, -85, -123, -128, -126, -128, -127, -123, -92, -73, -55, -45, -37, -33, -32, -33, -43, -53, -55, -43, -20, 3, 20, 34, 42, 49, 55, 63, 74, 84, 93, 101, 107, 112, 117, 109, 92, 63, 33, 8, -13, -25, -29, -30, -27, -27, -32, -46, -63, -82, -98, -109, -116, -121, -118, -104, -80, -49, -12, 21, 45, 58, 64, 66, 66, 61, 51, 44, 37, 32, 32, 33, 33, 28, 23, 15, 8, 3, 2, 9, 16, 20, 24, 23, 14, -1, -20, -37, -48, -53, -52, -47, -38, -26, -13, -5, -1, -4, -10, -22, -34, -43, -48, -46, -34, -16, 5, 25, 45, 65, 78, 84, 83, 71, 55, 39, 24, 9, -3, -12, -23, -34, -45, -57, -65, -71, -71, -63, -49, -34, -21, -11, -2, 2, 8, 11, 12, 14, 14, 20, 28, 38, 50, 58, 63, 61, 56, 46, 33, 17, -1, -19, -34, -45, -48, -44, -32, -19, -5, 5, 7, 4, -2, -7, -11, -15, -18, -21, -23, -26, -28, -30, -31, -29, -26, -20, -12, -1, 11, 21, 32, 42, 51, 55, 55, 52, 46, 41, 37, 32, 30, 28, 27, 24, 19, 12, -1, -21, -45, -67, -89, -103, -107, -101, -90, -70, -51, -33, -18, -2, 11, 23, 33, 39, 44, 49, 52, 57, 59, 59, 56, 52, 48, 41, 35, 28, 20, 15, 11, 4, 0, -5, -11, -18, -25, -34, -42, -47, -48, -46, -40, -33, -27, -24, -21, -24, -32, -42, -51, -56, -58, -56, -47, -35, -18, 2, 24, 48, 70, 88, 99, 104, 102, 97, 89, 79, 69, 59, 49, 37, 27, 14, 0, -14, -29, -44, -58, -71, -81, -87, -88, -88, -85, -81, -77, -72, -63, -51, -37, -21, -5, 12, 29, 43, 53, 59, 61, 57, 48, 36, 24, 13, 8, 8, 15, 25, 38, 48, 54, 54, 50, 43, 33, 22, 11, 3, -6, -15, -25, -35, -46, -54, -61, -65, -68, -69, -69, -68, -64, -59, -52, -43, -32, -20, -7, 6, 19, 31, 42, 51, 58, 62, 64, 62, 58, 52, 44, 35, 26, 17, 9, 1, -5, -10, -15, -18, -19, -20, -19, -18, -16, -15, -14, -14, -15, -16, -17, -18, -19, -19, -19, -19, -18, -16, -14, -11, -9, -6, -3, 0, 3, 6, 10, 14, 18, 22, 27, 32, 35, 37, 37, 35, 30, 23, 14, 4, -6, -15, -24, -31, -36, -39, -40, -39, -37, -32, -26, -19, -10, -1, 8, 17, 24, 29, 32, 33, 32, 29, 25, 20, 15, 11, 7, 3, -1, -5, -9, -14, -19, -24, -28, -31, -32, -31, -27, -23, -16, -10, -3, 2, 7, 10, 12, 13, 13, 13, 12, 10, 8, 7, 5, 5, 5, 5, 6, 8, 10, 13, 17, 20, 23, 25, 26, 25, 21, 16, 9, 1, -7, -16, -24, -31, -37, -42, -47, -49, -51, -52, -51, -48, -43, -37, -30, -20, -7, 6, 19, -1, -4, -4, 0, -1, -4, -3, 4, 4, -2, -3, 2, 1, -4, 0, 5, 0, -4, 2, -10, -26, -29, -34, -49, -61, -44, -21, -8, -3, -3, 1, 20, 32, 38, 32, 12, -4, 1, 14, 28, 51, 68, 78, 80, 72, 38, 1, -6, 16, 23, 2, -14, -15, -20, -33, -62, -65, -37, -18, -27, -29, -26, -45, -38, 8, 52, 55, 31, 26, 16, 17, 45, 80, 87, 77, 62, 54, 24, -23, -50, -43, -28, -47, -72, -86, -86, -87, -61, -35, -38, -57, -69, -55, -27, 1, 4, 22, 45, 54, 31, 0, -7, -5, -3, 0, -9, -21, -20, -15, -27, -31, -10, 5, 9, 3, -21, -67, -83, -46, -3, 8, 18, 22, 4, -3, 5, 35, 52, 67, 72, 83, 89, 71, 37, 19, 25, 8, -11, -37, -58, -80, -85, -68, -33, -24, -57, -60, -34, -16, -14, 17, 73, 96, 77, 48, 17, -7, -9, 4, -1, -3, 6, 3, -12, -10, 19, 33, 33, 41, 35, -29, -70, -64, -38, -18, 3, 17, -5, -26, -35, -5, 31, 63, 73, 86, 94, 80, 64, 50, 46, 37, 28, -2, -32, -65, -91, -84, -63, -59, -82, -97, -80, -66, -65, -43, 8, 49, 60, 61, 42, 27, 23, 23, 14, 15, 18, 10, -12, -17, -9, -13, 8, 35, 42, 2, -41, -76, -87, -67, -46, -31, -32, -45, -72, -53, -5, 32, 46, 72, 92, 96, 92, 77, 75, 73, 61, 44, 12, -32, -68, -72, -54, -58, -75, -85, -67, -57, -61, -60, -46, -11, 24, 35, 22, 15, 6, -1, -13, 8, 23, 8, -1, -1, -6, -8, 35, 71, 86, 79, 50, -11, -46, -38, -31, -29, -21, -30, -64, -68, -43, -12, 10, 28, 62, 89, 88, 84, 85, 90, 89, 95, 83, 28, -32, -53, -36, -44, -62, -64, -55, -59, -54, -52, -48, -23, 19, 48, 37, 39, 42, 31, 12, 19, 20, 5, 4, 1, -23, -40, -14, 14, 42, 68, 64, 14, -33, -53, -52, -32, -18, -24, -43, -67, -62, -36, -18, -1, 25, 54, 57, 58, 56, 54, 50, 66, 80, 44, -21, -50, -40, -52, -69, -77, -60, -56, -54, -53, -62, -49, -9, 28, 41, 58, 58, 47, 43, 49, 41, 34, 37, 18, -19, -44, -47, -36, 1, 35, 38, 19, -20, -62, -71, -59, -36, -34, -47, -63, -63, -50, -38, -17, 7, 37, 56, 74, 80, 73, 61, 87, 116, 99, 47, -7, -26, -22, -20, -32, -57, -72, -76, -76, -71, -47, -9, 13, 24, 29, 29, 25, 27, 52, 68, 62, 9, -38, -67, -66, -39, -11, -4, -24, -37, -47, -51, -49, -44, -55, -39, -6, -17, -52, -54, -19, 1, 15, 24, 31, 41, 55, 71, 79, 89, 111, 115, 88, 54, 22, -2, -8, -5, -7, -27, -49, -57, -69, -72, -64, -30, -3, 17, 31, 37, 29, 14, 39, 67, 73, 47, 10, -40, -72, -58, -23, -12, -19, -19, -39, -49, -42, -46, -62, -44, -8, -11, -36, -51, -39, -15, 0, 13, 21, 25, 40, 55, 63, 73, 95, 115, 115, 85, 53, 20, 2, -1, -2, -10, -32, -48, -64, -73, -77, -62, -33, -9, 16, 33, 31, 18, 17, 44, 67, 70, 49, 6, -45, -69, -53, -24, -13, -19, -24, -40, -47, -45, -50, -62, -43, -10, -13, -37, -51, -39, -15, 0, -3, -1, 1, -1, -6, -6, -4, -1, -2, -6, -8, -7, -4, -5, -10, -14, -16, -16, -16, -17, -18, -18, -17, -15, -15, -16, -15, -13, -10, -9, -9, -11, -13, -14, -11, -9, -8, -9, -7, -3, -2, -5, -8, -6, 1, 5, 4, 1, 0, 1, 4, 4, 4, 5, 7, 9, 9, 8, 8, 9, 10, 9, 5, 2, 3, 5, 7, 7, 9, 11, 11, 12, 14, 14, 12, 8, 7, 8, 5, 1, 3, 8, 9, 9, 10, 14, 16, 15, 14, 12, 11, 9, 7, 3, -2, -3, 3, 5, 0, -5, -1, -1, -6, -10, -16, -23, -28, -29, -32, -39, -36, -23, -16, -19, -19, -10, -7, -12, -11, -5, -6, -11, -13, -11, -9, -8, -2, 6, 8, 8, 9, 6, 2, 4, 8, 9, 4, 4, 12, 18, 17, 14, 17, 20, 20, 16, 9, 7, 7, 5, 3, 4, 1, -2, 0, 3, 2, -1, 1, 3, 3, 1, 2, 2, 0, 3, 6, 9, 8, 0, -5, -3, 7, 12, 8, -2, -2, 9, 10, 2, -3, 2, 5, 1, -3, -5, -6, -2, -3, -11, -20, -26, -28, -30, -32, -37, -43, -45, -43, -40, -42, -41, -31, -22, -20, -18, -16, -16, -19, -15, -8, -3, -3, 3, 17, 26, 22, 16, 18, 23, 27, 26, 23, 17, 15, 21, 25, 24, 25, 31, 36, 32, 29, 23, 17, 15, 11, 5, 1, 4, 6, 8, 6, 7, 8, 10, 14, 18, 22, 20, 17, 14, 15, 13, 10, 15, 15, 12, 9, 10, 15, 14, 9, 3, 6, 10, 5, -3, -9, -16, -16, -10, -11, -20, -24, -18, -20, -32, -42, -48, -55, -70, -84, -95, -100, -92, -75, -65, -68, -67, -56, -55, -51, -41, -33, -37, -42, -38, -33, -31, -26, -6, 19, 30, 25, 25, 28, 30, 27, 19, 16, 18, 31, 44, 46, 48, 56, 71, 77, 74, 66, 54, 47, 37, 19, 3, 2, 3, 3, 4, 13, 20, 21, 25, 24, 25, 19, 18, 19, 19, 14, 6, 17, 14, 1, 3, 12, 27, 29, 25, 13, 14, 24, 22, 6, -7, -7, 0, 11, 12, 1, 0, 10, 8, -13, -32, -46, -52, -57, -70, -88, -106, -101, -81, -74, -82, -75, -49, -37, -42, -44, -42, -46, -51, -47, -40, -32, -27, -6, 3, 16, 32, 29, 25, 24, 30, 54, 69, 74, 78, 90, 108, 118, 124, 117, 107, 102, 93, 76, 61, 50, 41, 35, 31, 26, 13, 4, 0, -1, 0, -6, -12, -10, -8, -4, 0, -3, -20, -31, -27, -18, -16, -22, -29, -28, -9, 0, -3, -1, 2, 11, 20, 24, 18, 22, 34, 32, 16, -1, -18, -34, -46, -55, -67, -91, -102, -91, -72, -73, -81, -68, -55, -55, -65, -74, -79, -87, -87, -83, -81, -77, -60, -25, 4, 4, -3, 0, 13, 29, 29, 24, 23, 29, 51, 67, 72, 77, 88, 105, 114, 122, 116, 106, 100, 93, 77, 63, 51, 42, 36, 31, 27, 15, 5, 0, -1, 0, -4, -10, -9, -7, -3, 2, -1, -16, -28, -26, -16, -13, -18, -25, -25, -8, 2, 1, 2, 5, 13, 21, 26, 20, 23, 35, 35, 20, 3, -14, -32, -45, -54, -67, -91, -102, -90, -72, -75, -82, -68, -56, -56, -66, -75, -81, -88, -88, -83, -82, -77, -59, -22, 4, 1, -1, -2, -3, -3, -1, -1, -6, -8, -9, -12, -5, 6, 15, 21, 22, 21, 9, -8, -16, -23, -32, -22, 4, 27, 32, 17, -2, -21, -34, -37, -30, -24, -3, 24, 47, 58, 50, 23, -12, -41, -52, -47, -33, -2, 28, 48, 45, 28, 0, -36, -58, -53, -34, -4, 26, 52, 75, 73, 45, -5, -66, -101, -90, -61, -14, 23, 59, 87, 89, 63, 10, -46, -79, -80, -55, -23, -3, 27, 58, 62, 41, -6, -66, -92, -77, -29, 19, 41, 65, 74, 69, 42, -9, -73, -109, -107, -67, -17, 23, 70, 104, 111, 83, 21, -56, -104, -109, -62, -21, 4, 34, 68, 89, 75, 19, -46, -89, -85, -38, -1, 23, 45, 64, 74, 62, 8, -53, -98, -93, -47, -9, 16, 36, 62, 86, 78, 13, -67, -121, -109, -56, -9, 25, 58, 89, 109, 81, 8, -70, -119, -106, -56, -7, 32, 63, 90, 108, 74, -3, -89, -128, -118, -70, -22, 23, 62, 101, 126, 98, 26, -64, -117, -110, -72, -32, 6, 44, 93, 124, 100, 28, -63, -116, -110, -71, -26, 16, 54, 101, 121, 92, 13, -86, -128, -120, -79, -28, 15, 60, 111, 127, 95, 11, -83, -127, -116, -80, -29, 15, 67, 117, 127, 100, 17, -75, -118, -108, -75, -31, 7, 60, 109, 123, 87, 3, -83, -118, -106, -67, -23, 13, 62, 106, 119, 85, 3, -77, -106, -95, -61, -27, 2, 52, 103, 124, 97, 19, -61, -95, -92, -63, -34, -4, 45, 94, 116, 87, 8, -63, -91, -85, -58, -36, -9, 36, 81, 104, 76, 2, -60, -87, -77, -52, -32, -2, 48, 97, 119, 86, 7, -59, -90, -85, -65, -50, -22, 26, 78, 107, 79, 11, -49, -78, -73, -58, -46, -18, 31, 85, 112, 75, 1, -59, -84, -73, -55, -40, -12, 30, 80, 106, 74, 10, -46, -70, -62, -49, -39, -13, 31, 86, 110, 74, 8, -49, -70, -59, -46, -33, -6, 38, 92, 111, 76, 13, -42, -62, -56, -51, -44, -23, 19, 75, 97, 67, 8, -44, -63, -58, -56, -48, -26, 19, 75, 94, 64, 8, -40, -55, -50, -49, -42, -25, 18, 69, 85, 57, 4, -41, -54, -51, -50, -45, -28, 18, 71, 88, 60, 8, -35, -46, -47, -48, -46, -30, 16, 66, 84, 59, 9, -30, -41, -43, -42, -40, -22, 25, 73, 88, 60, 8, -30, -42, -46, -45, -42, -21, 28, 74, 83, 52, -1, -36, -46, -45, -40, -37, -17, 26, 66, 73, 41, -10, -42, -54, -53, -48, -43, -19, 27, 68, 76, 44, -4, -34, -44, -41, -37, -33, -10, 34, 71, 75, 40, -7, -36, -47, -43, -39, -35, -9, 35, 72, 75, 39, -7, -38, -49, -45, -43, -38, -11, 33, 68, 70, 36, -4, -31, -39, -36, -35, -31, -5, 36, 69, 69, 35, -4, -31, -38, -35, -37, -33, -8, 31, 64, 63, 31, -7, -34, -42, -40, -43, -38, -12, 28, 61, 59, 27, -10, -34, -40, -38, -41, -35, -9, 31, 63, 60, 29, -6, -31, -37, -38, -42, -35, -10, 29, 60, 56, 27, -8, -30, -33, -34, -38, -32, -10, 28, 56, 51, 23, -9, -29, -32, -34, -38, -33, -10, 29, 55, 50, 23, -9, -28, -30, -33, -37, -32, -8, 32, 56, 52, 23, 23, 0, -2, 0, -2, -6, -6, -6, -5, -2, -1, 5, 15, 20, 11, 12, 12, 6, 0, -8, -19, -12, -4, -19, -19, -4, 4, -7, -3, 5, 8, 11, 14, 9, 9, 8, -4, -11, -6, -8, -16, -14, -7, -1, -3, 1, 10, 13, 24, 28, 12, 10, 14, 11, -14, -29, -19, -12, -21, -25, -16, 2, 0, -11, -7, 7, 10, 0, 0, 5, 11, 6, 10, 21, 13, 7, 14, 4, -4, -9, -5, -11, -16, -7, -3, 3, 15, -2, 2, 17, 6, -19, -16, 3, 3, -14, -10, 7, 7, 4, 8, 11, 4, -5, -12, -9, -6, -14, -13, -17, -13, -8, 5, 9, 3, 10, 12, 24, 28, 26, 35, 20, -3, 24, 23, -19, -31, -23, -23, -38, -34, -18, -10, -8, -6, -4, -1, 5, -4, -8, 2, 15, 12, 26, 56, 37, 10, 25, 25, -4, -21, -24, -23, -26, -30, -27, -8, 10, -5, 3, 30, 6, -26, -7, 13, -2, -19, -2, 11, 3, 14, 21, 8, 12, 5, -19, -26, -12, 9, 1, -8, -8, 20, 27, 17, 16, 15, 0, 23, 39, 11, -4, -13, -21, -21, -32, -36, -27, -20, -24, -10, -4, 5, 14, 4, -11, -10, 7, -8, -7, 7, 7, 2, 15, 29, 55, 26, 4, 22, 37, 32, 14, 10, 18, 7, -1, -28, -49, -24, -14, -41, -53, -37, -28, -27, -15, 1, 2, 14, 14, 13, 3, 0, 1, 18, 9, 7, 11, 23, 23, 25, 16, -7, 1, 13, 26, 26, 9, 13, 28, 28, 1, -29, -29, -26, -27, -43, -43, -31, -12, -26, -15, 6, 16, 6, 22, 11, -4, 0, 3, 0, -4, -20, -9, 15, 23, 19, 7, 25, 19, 42, 63, 40, 13, 22, 24, 1, -41, -60, -55, -63, -69, -61, -31, -7, 10, 8, 0, 7, 4, 4, 20, 5, -4, 9, 27, 31, 27, 23, 13, 19, 12, 2, 4, 15, 20, 35, 19, 16, 26, 3, -30, -48, -31, -40, -60, -59, -47, -13, -3, 12, 22, 11, 7, 9, 8, 3, -10, -34, -5, 6, 24, 38, 19, 13, 21, 40, 15, 2, 27, 26, 16, 44, 47, -7, -43, -41, -29, -44, -80, -81, -58, -26, -17, 3, 16, 30, 19, 10, 25, 16, 6, -12, -3, 13, 30, 38, 20, 17, 22, 25, 18, 13, 16, -3, 1, 32, 44, -11, -48, -51, -34, -38, -49, -64, -70, -23, -10, -14, -1, 20, 18, 20, 21, 11, 3, -8, -3, 13, 14, 22, 18, 32, 37, 30, 25, 16, 27, 27, 18, 37, 52, 12, -26, -56, -57, -46, -71, -92, -86, -50, -21, -10, 8, 15, 15, 18, 28, 17, 1, 1, 2, 13, 13, 23, 23, 21, 29, 31, 29, 15, 20, 33, 32, 29, 46, 21, -31, -49, -53, -51, -66, -82, -76, -54, -32, -10, 12, 19, 29, 18, 3, 0, 16, 20, 29, 31, 20, 25, 31, 43, 41, 34, 44, 27, 29, 65, 54, -15, -70, -79, -63, -86, -114, -114, -79, -26, -2, 6, 18, 19, 10, 19, 26, 15, 5, 0, 16, 23, 29, 30, 21, 25, 28, 37, 37, 38, 44, 32, 29, 66, 65, -7, -67, -74, -59, -82, -114, -117, -85, -31, -2, 11, 20, 18, 9, 20, 30, 15, 5, 0, 0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 7, 7, 7, 7, 7, 6, 4, 3, 2, 0, -1, -2, -3, -5, -6, -8, -9, -9, -11, -12, -14, -15, -17, -17, -17, -18, -19, -19, -19, -18, -17, -16, -15, -13, -11, -8, -7, -6, -5, -3, -1, 0, 0, 1, 3, 5, 8, 10, 12, 14, 17, 19, 21, 23, 26, 27, 28, 28, 28, 26, 25, 24, 23, 23, 21, 19, 18, 16, 15, 14, 13, 12, 11, 11, 11, 10, 8, 6, 5, 5, 4, 2, 0, -2, -4, -5, -7, -10, -11, -12, -13, -14, -15, -15, -15, -15, -15, -16, -17, -18, -18, -19, -21, -23, -25, -27, -28, -29, -29, -30, -30, -29, -27, -25, -23, -22, -20, -18, -16, -14, -13, -12, -11, -11, -10, -9, -8, -6, -5, -4, -3, -1, 1, 3, 4, 6, 7, 8, 8, 9, 10, 11, 12, 13, 13, 13, 13, 15, 18, 21, 23, 24, 25, 25, 28, 31, 33, 34, 34, 32, 31, 31, 31, 30, 27, 22, 16, 12, 10, 9, 7, 3, -5, -13, -19, -22, -22, -23, -25, -28, -31, -33, -33, -32, -32, -31, -32, -33, -32, -29, -25, -21, -19, -19, -19, -19, -18, -15, -9, -3, 2, 6, 9, 12, 16, 21, 27, 32, 37, 39, 40, 40, 39, 39, 40, 41, 40, 38, 35, 34, 34, 33, 29, 22, 16, 11, 10, 11, 12, 12, 10, 8, 7, 5, 3, 2, 0, -6, -12, -19, -23, -23, -22, -23, -26, -30, -33, -33, -33, -34, -35, -37, -40, -45, -50, -53, -52, -48, -42, -37, -32, -27, -22, -20, -18, -16, -16, -18, -21, -26, -30, -33, -34, -35, -36, -38, -40, -41, -41, -38, -36, -36, -38, -41, -40, -38, -34, -30, -27, -25, -22, -20, -16, -15, -16, -17, -18, -16, -13, -10, -7, -4, -2, 1, 6, 11, 16, 21, 24, 25, 26, 24, 22, 19, 18, 19, 22, 24, 26, 30, 33, 38, 44, 50, 56, 61, 63, 68, 72, 74, 73, 68, 64, 57, 50, 47, 46, 44, 37, 21, 3, -11, -20, -23, -25, -30, -33, -36, -36, -34, -31, -27, -22, -21, -22, -21, -18, -21, -24, -27, -31, -33, -32, -27, -21, -14, -13, -17, -17, -10, 0, 10, 15, 16, 14, 8, 6, 10, 16, 25, 34, 39, 43, 47, 53, 62, 72, 82, 89, 92, 90, 84, 79, 77, 77, 76, 67, 54, 42, 33, 26, 18, 5, -11, -27, -41, -53, -65, -73, -77, -79, -81, -86, -93, -102, -110, -116, -118, -120, -124, -127, -128, -128, -126, -122, -116, -107, -96, -85, -78, -72, -64, -54, -45, -39, -40, -46, -49, -49, -47, -45, -44, -45, -45, -44, -42, -38, -33, -29, -26, -23, -20, -18, -14, -11, -8, -5, -2, 2, 7, 11, 10, 8, 7, 9, 16, 22, 26, 28, 31, 34, 39, 44, 49, 53, 57, 60, 62, 63, 63, 65, 66, 63, 57, 51, 46, 46, 50, 53, 54, 55, 54, 55, 57, 63, 69, 73, 75, 73, 69, 66, 64, 65, 63, 55, 43, 30, 18, 11, 3, -6, -15, -23, -29, -32, -32, -28, -22, -16, -13, -16, -16, -11, -2, 9, 15, 1, 0, 0, 0, -1, 0, -3, 0, -1, 0, -18, 21, -22, 23, -41, 20, 84, -39, 50, -61, 26, -126, -19, -37, 15, 2, 70, -33, 127, -55, 117, -73, 15, -45, -50, 8, -11, 23, 33, 1, 26, -67, 26, -25, 14, -45, 57, -124, 12, -4, -23, 107, -54, 127, -49, 43, 27, -59, -30, 15, -128, 5, -128, 86, -39, 82, 12, 62, 9, 51, -59, 53, -95, 67, -92, 68, -28, 94, 21, 47, -11, -1, -41, 0, -25, -9, 18, -68, 15, -27, 49, -27, 103, -4, 3, -36, 58, -98, 56, -116, -31, -123, 25, -58, 89, -21, 110, -25, 73, -28, 39, -21, 35, -40, 37, -20, 50, 55, 51, 6, 1, -47, -11, -32, -23, 38, -67, 3, -54, 34, -55, 79, 1, 32, -61, 89, -86, 53, -67, -10, -128, -6, -68, 51, -4, 82, 15, 83, -16, 63, -24, 55, -29, 8, 0, 6, 11, 54, 14, 16, -39, -9, -12, -47, 37, -40, -22, -60, 21, -76, 51, -17, 74, -63, 98, -36, 44, -33, 24, -113, -37, -89, 20, -30, 67, 18, 87, 0, 67, -6, 38, 1, -2, -18, -5, -20, 32, 17, 21, -8, -30, 15, -47, 11, -17, 11, -97, 43, -87, 27, -36, 91, -41, 66, 3, 44, -28, 55, -74, -37, -92, -21, -37, 33, -1, 75, 22, 36, 14, 26, 8, 8, -12, -7, -21, -1, 27, 11, 21, -30, 21, -37, -3, -13, 23, -27, -32, -10, -23, -44, 56, -1, 43, -12, 76, -29, 48, -9, -25, -71, -70, -48, -20, 2, 9, 56, 8, 56, -10, 52, -12, 31, -29, 27, -60, 62, -42, 83, -45, 30, -24, 4, -26, 33, -23, 5, -18, -25, -53, -7, -6, -6, 19, 16, 31, 3, 58, -14, 0, -64, -33, -58, -8, -43, 42, -18, 57, -9, 54, 1, 47, -3, 36, -18, 3, 4, 6, 2, -17, 8, -14, -27, 35, 2, -3, 1, -8, -43, -34, -1, -22, 12, 2, 37, -6, 53, 14, 16, -43, -22, -75, -2, -67, 23, -24, 39, -3, 39, 6, 44, 9, 37, 5, 1, 3, 5, 12, -18, 0, 0, -31, 5, 23, 1, -3, 10, -20, -48, -6, -30, 7, -18, 35, -4, 32, 21, 39, -26, -1, -75, -9, -65, -3, -28, 20, -5, 32, 5, 36, 20, 30, 30, 3, 10, -1, 16, -10, -7, -1, -17, -23, 18, 14, -3, 8, 9, -45, -14, -35, -1, -27, 18, -2, 29, 1, 61, -14, 20, -56, -19, -51, -22, -38, 9, -14, 22, 5, 24, 27, 23, 41, 13, 20, -7, 23, -2, -8, -2, -9, -26, -6, 14, 11, -11, 37, -33, -12, -38, -6, -33, 7, -14, 30, -12, 55, 4, 33, -32, -14, -45, -22, -43, -7, -15, 18, 18, 33, 17, 41, 22, 15, 14, 8, -24, -16, -18, -16, -7, 6, 16, -2, 8, -14, -6, -23, 0, -22, 1, -23, 21, 4, 24, -1, 9, -9, -11, -14, -13, -16, -14, -15, -12, -16, -5, 8, 28, 25, 28, 34, 27, 15, 16, 2, -20, -22, -20, -15, -8, 10, 11, 7, -3, -5, -16, -10, -13, -5, -16, -5, 4, 17, 13, 6, 1, -9, -1, -2, -3, -4, -4, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -5, -6, -6, -6, -6, -6, -5, -3, -3, -5, -5, -5, -7, -8, -5, 4, 5, 13, 12, -12, -5, 10, 5, 4, 0, 3, 26, 33, 10, -15, -69, -89, -25, 25, 58, 70, 22, -41, -62, -31, 18, 17, -17, -12, -9, 20, 99, 96, 0, -88, -123, -69, 61, 116, 54, -11, -45, -28, 40, 38, -42, -59, -53, -31, 63, 78, -9, -65, -83, -59, 48, 110, 50, -11, -51, -54, 41, 96, 9, -87, -119, -77, 42, 118, 67, -18, -57, -46, 24, 89, 81, 22, -43, -77, -65, -41, -23, -3, 4, 8, -13, -54, -52, -21, 30, 89, 86, 8, -49, -76, -56, 30, 55, 52, 47, -7, -45, -49, -48, -10, 68, 74, 43, 22, -27, -25, 12, 20, -5, -43, -69, -46, 21, 53, 51, 38, -8, -32, 6, 20, -1, -19, -56, -67, -26, 27, 76, 95, 23, -64, -60, -15, 33, 39, -8, -37, -24, -7, 7, 4, -25, -23, -10, -14, -7, -5, -12, 2, 28, 31, 37, 21, -18, -16, -4, -22, -37, -46, -56, -8, 58, 64, 53, 31, -9, -9, -2, -57, -85, -52, -13, 59, 92, 21, -42, -47, -33, 27, 75, 27, -22, -38, -44, 18, 77, 32, -21, -46, -50, 34, 89, 22, -37, -60, -56, 31, 95, 36, -27, -57, -82, -15, 53, 15, -13, -25, -44, 14, 66, 14, -32, -53, -62, 25, 96, 50, 3, -32, -56, 25, 98, 51, -9, -56, -78, 7, 92, 71, 28, -31, -92, -42, 28, 20, 24, 8, -34, 22, 70, 18, -17, -53, -88, -20, 39, 7, -2, -8, -28, 35, 80, 19, -23, -55, -93, -22, 63, 54, 47, 19, -52, -35, 2, -36, -32, -18, -49, -9, 41, 15, 26, 34, -22, -6, 31, 1, 8, 9, -43, -15, 30, -3, -1, -7, -73, -48, 6, -14, 5, 13, -47, -30, 12, -13, 6, 18, -37, -13, 39, 27, 45, 38, -37, -32, 12, 3, 32, 46, -10, 6, 48, 16, 15, 15, -32, -2, 47, 24, 26, 18, -51, -51, -15, -29, -1, 19, -28, -15, 21, 2, 18, 22, -34, -24, 13, -3, 15, 14, -45, -34, 7, 10, 38, 31, -34, -30, 4, 5, 43, 61, 13, 4, 6, -22, 4, 24, -13, -13, -10, -34, 0, 23, -16, -16, -13, -42, -18, -4, -36, -17, 5, -10, 14, 22, -21, -22, -16, -37, -6, 20, -2, 17, 36, 19, 43, 43, -9, -15, -12, -29, 6, 31, 6, 10, 7, -23, -2, 9, -23, -15, -10, -26, 3, 20, -5, 1, 0, -22, 5, 22, -6, -8, -16, -37, -5, 20, 2, 11, 6, -19, 11, 33, 12, 20, 16, -7, 20, 35, 11, 11, -3, -28, 2, 19, -1, 3, -6, -29, -5, 2, -25, -17, -12, -16, 22, 34, 3, -4, -21, -36, 4, 26, 8, -1, -30, -54, -23, -3, -11, 0, -12, -27, 7, 24, 13, 19, -1, -21, 10, 27, 14, 17, 0, -14, 18, 33, 19, 14, -17, -41, -10, 9, 2, 7, -14, -30, 4, 20, 9, 9, -15, -35, -3, 16, 9, 0, -1, -2, -3, 4, 7, 4, -2, -3, 0, 3, -1, -1, 4, 5, -2, -13, -9, 1, 4, 2, 1, 2, 2, -2, -8, -4, 0, 4, 4, -3, -4, -3, 1, 2, -1, 3, 14, 1, -7, -12, -4, -2, 1, 1, 9, 5, -6, -5, -2, -1, -1, 1, 14, 6, -6, -7, 3, 8, -2, -4, 13, 12, -10, -17, -10, -5, -4, 2, 3, 7, -6, -6, -1, -1, -4, 1, 11, 6, -6, -9, 10, 11, 3, 1, 14, 15, -12, -20, -12, -9, -15, -1, 7, 2, -16, -7, 6, 0, -2, 10, 26, 17, -6, -11, 24, 21, 1, 0, 18, 15, -17, -31, -28, -23, -14, 0, -4, 0, -16, -8, 8, -4, -3, 7, 15, 5, -3, -3, 26, 25, 12, 8, 28, 17, -15, -28, -18, -17, -18, -7, -3, -7, -20, 0, 7, 1, -9, 6, 9, -4, -9, 2, 15, 24, 34, 31, 10, -4, -15, -29, -17, -21, -41, -40, -5, 19, -20, 3, 11, 33, 28, 21, 18, 15, 16, 3, -1, 18, 17, 15, 1, -15, -10, -5, -14, -42, -48, -43, -26, 4, -29, -14, -9, 32, 20, 12, 15, 21, 39, 24, 8, 26, 33, 6, -3, 0, 1, -7, -16, -41, -44, -51, -34, -3, -6, -6, -19, 26, 10, 15, 35, 46, 32, 20, 16, 23, 38, 15, -4, -10, 17, -6, -41, -48, -53, -70, -52, -9, -9, -22, -15, 19, 24, 22, 30, 49, 34, 10, 1, 15, 33, 15, 1, 17, 46, 12, -38, -59, -50, -57, -46, -13, -16, -30, -24, 26, 37, 33, 30, 45, 40, 2, -11, 17, 41, 24, -4, 16, 48, 15, -38, -67, -64, -65, -46, -18, -18, -35, -32, 35, 39, 37, 21, 45, 42, -2, -19, 14, 37, 22, 7, 24, 40, 13, -42, -68, -63, -63, -38, -6, -12, -34, -25, 39, 43, 39, 17, 47, 45, 3, -19, 21, 45, 25, 2, 21, 31, 0, -45, -71, -78, -83, -48, 2, 7, -27, -32, 34, 45, 49, 23, 44, 36, 5, -5, 38, 60, 27, -13, 21, 42, -13, -69, -81, -86, -79, -38, -9, -11, -41, -36, 38, 56, 45, 10, 43, 43, 10, -6, 36, 57, 41, 10, 36, 46, -16, -67, -66, -71, -80, -44, -8, -5, -29, -27, 30, 43, 46, 20, 52, 39, -9, -21, 40, 68, 42, -1, 20, 32, -14, -70, -86, -94, -90, -45, -2, 0, -31, -17, 36, 47, 46, 18, 44, 29, -2, -11, 46, 74, 51, 14, 36, 46, -15, -78, -87, -91, -89, -46, -12, -11, -28, -5, 41, 46, 40, 17, 51, 33, -6, -13, 49, 75, 52, 15, 30, 34, -21, -79, -88, -93, -88, -42, -9, -4, -25, -3, 36, 40, 34, 16, 44, 23, -8, -10, 52, 83, 55, 17, 38, 31, -31, -82, -91, -93, -82, -39, -16, -10, -25, 5, 33, 42, 32, 20, 54, 25, -9, -3, 59, 85, 63, 24, 37, 24, -39, -86, -92, -97, -80, -34, -17, -15, -24, 10, 35, 45, 32, 16, 45, 12, -23, -2, 62, 78, 53, 21, 37, 26, -39, -91, -95, -96, -77, -29, -16, -16, -25, 10, -1, 0, 3, 21, -26, 18, -30, 32, -19, -15, -27, 2, 0, 103, -84, -53, -52, 79, 51, 36, -69, -31, 48, 71, 33, -74, -64, 10, 51, 49, -68, -91, -16, 30, 33, -31, -58, -42, 14, 24, -25, 23, -71, 79, -22, 123, -74, 28, 28, 115, 99, -7, 9, -15, 72, 1, 16, -47, -5, -71, -18, -75, -26, -71, -28, -56, -24, -57, -19, -33, -5, 7, -3, 14, -8, 82, 100, 23, -32, -15, 80, 98, 68, -30, -21, 24, 71, 28, -41, -96, -22, 32, 37, -57, -110, -67, 28, 35, -22, -112, -79, 13, 70, 27, -55, -63, 31, 95, 86, -4, -40, 29, 110, 110, 28, -50, -12, 66, 80, 14, -87, -81, -7, 36, -5, -95, -118, -42, 26, 8, -69, -121, -48, 37, 60, -6, -68, -29, 67, 104, 61, -24, -17, 70, 123, 92, -5, -43, 23, 82, 67, -28, -96, -54, 18, 30, -39, -115, -96, -7, 25, -13, -99, -101, -13, 52, 42, -35, -62, 9, 88, 93, 28, -32, 15, 97, 118, 58, -29, -24, 51, 82, 39, -61, -88, -26, 28, 9, -70, -117, -63, 7, 14, -46, -109, -71, 15, 55, 16, -51, -42, 43, 94, 75, 2, -21, 48, 107, 101, 23, -36, 4, 65, 70, 1, -81, -69, -3, 26, -19, -94, -106, -32, 14, -3, -74, -103, -37, 34, 46, -10, -56, -12, 66, 91, 49, -15, 1, 74, 111, 76, -4, -28, 31, 72, 50, -33, -85, -43, 11, 15, -46, -106, -80, -11, 13, -26, -92, -84, -8, 44, 29, -30, -48, 19, 80, 81, 26, -18, 27, 91, 103, 49, -22, -10, 48, 68, 22, -60, -75, -22, 17, -5, -71, -105, -54, 3, 3, -49, -98, -58, 14, 44, 11, -44, -27, 45, 85, 65, 5, -8, 53, 100, 87, 21, -26, 11, 60, 56, -6, -74, -58, -4, 13, -25, -90, -91, -29, 7, -12, -72, -90, -29, 32, 37, -10, -46, -2, 66, 83, 47, -8, 10, 74, 101, 68, -3, -19, 31, 62, 38, -36, -77, -40, 6, 4, -49, -100, -72, -12, 3, -31, -86, -73, -4, 37, 25, -28, -36, 25, 75, 74, 25, -9, 34, 88, 94, 43, -16, -4, 47, 58, 15, -57, -69, -22, 6, -12, -73, -96, -50, -4, -7, -53, -89, -49, 13, 36, 5, -37, -17, 47, 77, 59, 9, 2, 58, 92, 79, 19, -17, 16, 54, 45, -13, -69, -52, -8, 3, -33, -85, -82, -29, -2, -20, -68, -79, -23, 24, 29, -11, -34, 7, 61, 73, 41, 0, 22, 73, 90, 58, 1, -9, 32, 52, 26, -36, -69, -35, -3, -7, -53, -90, -63, -16, -7, -36, -78, -60, -4, 29, 16, -22, -23, 29, 68, 64, 26, 2, 42, 80, 81, 38, -8, 5, 42, 44, 4, -53, -57, -21, -2, -22, -69, -83, -43, -10, -15, -51, -77, -38, 11, 27, 3, -27, -5, 46, 68, 52, 13, 15, 58, 83, 68, 19, -8, 21, 46, 32, -16, -60, -44, -12, -6, -36, -76, -74, -34, -10, -20, -57, -73, -33, 12, 27, 3, -1, -6, -11, -3, 4, 0, -7, -8, 1, 21, 14, 28, 33, 25, -1, 7, 4, -13, -21, -44, -29, -17, -31, -32, 2, 0, -20, 4, 3, 4, 0, -2, -5, -4, -14, 3, 14, 9, 28, 34, 54, 43, 54, 39, 19, 17, -1, 5, -23, -31, -25, -35, -46, -60, -29, -29, -13, -37, -22, -16, -20, -27, -21, -6, -16, 8, -5, 15, 26, 69, 65, 74, 85, 81, 76, 51, 22, -10, -10, -19, -3, -39, -73, -55, -36, -18, -45, -49, -45, -52, -47, -74, -73, -56, -31, -15, -16, -5, 18, 65, 86, 108, 94, 97, 90, 79, 54, 30, 19, 10, 25, -16, -34, -37, -9, -16, -35, -44, -60, -60, -50, -62, -70, -66, -44, -34, -34, -29, -10, 23, 61, 85, 79, 75, 70, 61, 41, 31, 7, 8, 3, -22, -42, -28, 0, -13, -29, -39, -52, -56, -55, -58, -60, -57, -41, -35, -37, -19, 5, 35, 71, 87, 85, 97, 112, 97, 71, 56, 52, 53, 43, 18, -7, -3, 10, 0, -17, -39, -55, -58, -64, -80, -106, -121, -112, -110, -113, -105, -82, -51, -8, 16, 20, 45, 66, 66, 49, 46, 59, 75, 78, 63, 62, 74, 80, 80, 69, 51, 27, 11, 0, -14, -40, -53, -48, -55, -68, -71, -56, -34, -1, 14, 24, 49, 62, 59, 42, 34, 43, 47, 43, 26, 30, 33, 38, 26, 4, -17, -41, -66, -81, -92, -112, -120, -115, -116, -128, -125, -103, -71, -36, -11, 9, 33, 56, 59, 54, 61, 67, 77, 77, 77, 79, 74, 75, 73, 55, 30, 10, -21, -38, -46, -61, -70, -67, -70, -81, -77, -64, -45, -23, -4, 10, 30, 44, 44, 39, 42, 48, 51, 50, 51, 58, 58, 65, 65, 47, 29, 12, -14, -31, -41, -53, -63, -60, -62, -64, -58, -44, -26, -11, 1, 10, 20, 22, 17, 9, 5, 6, 6, 2, 4, 10, 10, 17, 19, 9, 7, -1, -14, -18, -13, -14, -9, 1, 7, 12, 17, 23, 31, 35, 36, 35, 38, 31, 21, 16, 3, 0, -8, -11, -11, -13, -19, -20, -23, -34, -39, -51, -69, -78, -81, -83, -83, -78, -70, -60, -47, -34, -19, 2, 20, 39, 57, 60, 66, 67, 63, 61, 53, 50, 51, 47, 37, 32, 23, 13, 6, -3, -17, -23, -28, -34, -37, -35, -27, -15, -2, 4, 12, 23, 30, 44, 47, 43, 41, 35, 29, 22, 15, 13, 14, 7, -1, -5, -11, -19, -20, -25, -37, -43, -41, -43, -47, -47, -40, -29, -17, -7, 5, 13, 23, 38, 44, 37, 34, 31, 23, 17, 6, 1, -2, -10, -20, -25, -35, -45, -50, -54, -64, -68, -65, -66, -65, -59, -47, -30, -19, -7, 5, 14, 28, 48, 62, 66, 72, 75, 78, 76, 67, 60, 56, 46, 32, 20, 9, -2, -10, -21, -35, -43, -44, -49, -56, -57, -51, -38, -25, -13, -2, 9, 25, 42, 56, 59, 64, 65, 67, 65, 57, 52, 49, 41, 28, 18, 8, -2, -10, 0, 8, 13, 21, 20, 20, 17, 10, 8, -2, -6, -17, -21, -29, -23, -25, -14, -7, -2, 7, 10, 20, 21, 22, 23, 19, 14, 9, -2, -6, -18, -20, -28, -25, -23, -18, -10, -3, 5, 9, 22, 17, 28, 22, 21, 17, 11, 2, -8, -18, -23, -27, -26, -24, -19, -13, -6, 3, 9, 17, 20, 28, 24, 25, 21, 13, 6, -5, -14, -21, -29, -29, -30, -23, -19, -7, -1, 10, 18, 25, 29, 27, 28, 20, 17, 5, -7, -13, -26, -29, -30, -30, -27, -20, -12, 0, 11, 19, 25, 27, 30, 26, 28, 19, 11, -2, -12, -24, -30, -35, -34, -30, -24, -14, -2, 9, 18, 23, 28, 26, 33, 31, 29, 24, 12, 5, -12, -23, -30, -37, -36, -36, -26, -19, -5, 5, 19, 22, 32, 32, 36, 35, 26, 21, 3, -6, -22, -34, -41, -44, -38, -31, -18, -6, 6, 15, 23, 32, 33, 39, 34, 31, 23, 10, -2, -21, -32, -44, -47, -45, -37, -23, -12, 6, 13, 28, 30, 38, 40, 40, 38, 23, 17, -6, -15, -35, -42, -50, -49, -41, -31, -14, 0, 14, 26, 35, 42, 45, 45, 40, 27, 18, -4, -14, -33, -42, -54, -52, -47, -36, -21, -5, 13, 24, 39, 43, 52, 47, 42, 36, 20, 7, -15, -32, -45, -55, -56, -54, -43, -27, -8, 12, 26, 38, 45, 50, 51, 48, 40, 27, 9, -11, -30, -46, -58, -62, -58, -49, -31, -11, 9, 24, 41, 45, 54, 53, 54, 45, 30, 14, -10, -27, -48, -58, -67, -64, -56, -35, -15, 6, 24, 37, 45, 54, 56, 56, 49, 39, 18, 0, -26, -45, -60, -74, -70, -63, -41, -23, 4, 21, 39, 48, 53, 61, 58, 59, 43, 29, 3, -20, -46, -64, -77, -77, -69, -50, -27, 0, 20, 36, 49, 56, 64, 64, 63, 51, 34, 6, -17, -46, -65, -79, -83, -76, -58, -33, -6, 17, 38, 49, 60, 67, 68, 66, 53, 37, 13, -13, -38, -65, -79, -90, -82, -68, -41, -15, 14, 36, 52, 63, 70, 73, 69, 62, 44, 19, -8, -38, -63, -83, -93, -90, -77, -49, -20, 12, 34, 54, 65, 72, 75, 76, 65, 51, 26, -1, -33, -62, -86, -98, -96, -86, -58, -29, 6, 32, 54, 66, 73, 79, 76, 73, 58, 36, 4, -27, -60, -85, -101, -104, -92, -70, -36, -1, 31, 53, 70, 75, 81, 80, 78, 65, 41, 15, -24, -56, -84, -105, -109, -101, -79, -46, -7, 25, 56, 65, 77, 82, 85, 83, 69, 51, 19, -14, -50, -83, -103, -115, -107, -88, -55, -17, 21, 50, 67, 81, 86, 89, 85, 79, 55, 28, -8, -46, -77, -103, -116, -117, -97, -67, -25, 1, 39, 66, 81, 92, 96, 97, 90, 73, 45, 11, -27, -64, -97, -120, -128, -117, -89, -49, -5, 35, 65, 81, 93, 98, 99, 91, 75, 46, 12, -27, 28, -9, -42, -57, -50, -18, 33, 77, 77, 17, -64, -96, -55, 22, 73, 68, 17, -43, -77, -67, -15, 59, 102, 79, 12, -48, -71, -57, -28, -3, 11, 10, -3, -17, -4, 44, 88, 79, 10, -69, -103, -74, -6, 54, 75, 53, -4, -63, -80, -38, 32, 73, 59, 7, -43, -67, -57, -18, 33, 71, 71, 24, -31, -47, -17, 20, 23, -14, -58, -73, -47, 10, 73, 110, 93, 20, -62, -97, -68, -6, 43, 54, 28, -13, -51, -65, -35, 26, 74, 69, 12, -50, -68, -37, 9, 37, 37, 16, -12, -26, -7, 36, 65, 45, -19, -87, -112, -75, -7, 58, 97, 92, 41, -30, -75, -62, -3, 49, 52, 7, -44, -63, -45, -6, 37, 60, 42, -5, -42, -41, -3, 38, 41, 8, -33, -51, -38, 3, 54, 90, 79, 12, -76, -127, -106, -29, 47, 78, 63, 23, -19, -36, -16, 24, 50, 35, -15, -59, -64, -27, 17, 40, 35, 11, -20, -39, -26, 19, 63, 67, 14, -61, -97, -72, -5, 64, 101, 87, 26, -49, -96, -86, -32, 24, 40, 17, -11, -17, -3, 24, 51, 55, 29, -20, -66, -69, -23, 35, 55, 25, -26, -59, -55, -14, 44, 86, 80, 23, -56, -105, -87, -19, 48, 79, 67, 27, -18, -46, -43, -14, 17, 16, -20, -54, -47, 3, 59, 83, 66, 18, -35, -64, -54, -8, 44, 59, 18, -48, -87, -72, -16, 49, 88, 84, 37, -31, -81, -79, -26, 33, 52, 29, -5, -19, -6, 20, 34, 27, -5, -51, -84, -71, -9, 62, 95, 71, 12, -40, -58, -37, 8, 52, 63, 22, -53, -103, -88, -23, 47, 80, 64, 24, -14, -33, -28, -3, 21, 18, -15, -45, -39, 5, 57, 78, 54, -1, -60, -97, -89, -29, 50, 92, 67, 0, -53, -57, -13, 38, 64, 52, 10, -44, -82, -76, -26, 28, 49, 32, 1, -14, -1, 24, 40, 38, 9, -43, -87, -79, -13, 69, 110, 80, 4, -65, -90, -69, -21, 32, 58, 39, -9, -48, -45, 0, 52, 69, 46, 5, -34, -57, -50, -14, 23, 28, -8, -48, -48, 4, 71, 99, 69, 3, -63, -99, -88, -30, 46, 92, 78, 16, -45, -66, -44, -6, 25, 34, 16, -24, -55, -43, 10, 67, 80, 37, -22, -48, -29, 7, 30, 27, -5, -51, -84, -73, -11, 71, 116, 95, 27, -43, -84, -84, -43, 18, 63, 60, 10, -44, -53, -9, 41, 49, 14, -31, -57, -50, -15, 29, 61, 57, 14, -37, -51, -14, 38, 63, 47, -1, -61, -106, -105, -47, 44, 115, 113, 42, -36, -64, -42, -2, 23, 20, -3, -28, -39, -21, 24, 64, 59, 7, -48, -67, -47, -7, 36, 59, 47, 2, -55, -77, -31, 55, 111, 89, 7, -75, -113, -96, -42, 21, 62, 64, 28, -13, -18, 17, 45, 28, -2, -7, -6, -7, -7, -8, -8, -8, -8, -7, -6, -5, -4, -3, -3, -2, -2, -1, 0, 1, 2, 4, 5, 6, 8, 9, 10, 11, 12, 13, 13, 14, 15, 16, 17, 17, 17, 17, 17, 16, 16, 15, 15, 14, 14, 13, 12, 10, 10, 9, 8, 7, 6, 5, 5, 4, 3, 2, 1, 0, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -13, -14, -14, -14, -14, -14, -15, -15, -15, -15, -16, -16, -14, -14, -12, -10, -13, -10, -13, -7, -3, -5, -1, -1, -5, -5, 8, 13, 10, 10, 15, 16, 17, 30, 34, 19, 17, 22, 29, 27, 22, 16, 1, -3, 8, 18, 11, 6, 8, 8, 1, 6, 18, 5, -8, -4, 4, 5, 3, 5, -3, -6, 12, 30, 23, 9, 5, 6, 9, 15, 27, 20, 2, 0, 10, 17, 8, -1, -4, -8, -8, -3, -7, -19, -28, -24, -22, -31, -42, -47, -50, -50, -42, -35, -35, -43, -41, -31, -27, -23, -17, -9, -7, 3, 26, 37, 38, 37, 41, 39, 39, 49, 55, 50, 46, 53, 58, 51, 44, 36, 24, 9, 5, 2, -12, -25, -28, -26, -33, -42, -44, -55, -66, -69, -62, -60, -65, -57, -42, -33, -26, -15, -5, -6, 0, 15, 29, 34, 41, 55, 61, 62, 68, 71, 62, 49, 49, 49, 39, 29, 24, 14, -2, -10, -16, -34, -56, -67, -70, -77, -83, -85, -88, -93, -92, -79, -74, -78, -74, -61, -49, -41, -23, -9, -2, 11, 35, 54, 56, 58, 64, 69, 73, 81, 91, 86, 77, 78, 77, 67, 50, 39, 24, 6, -4, -10, -22, -41, -49, -52, -62, -73, -81, -87, -98, -97, -83, -74, -70, -63, -46, -33, -23, -6, 9, 18, 26, 48, 69, 77, 85, 97, 106, 107, 111, 114, 104, 89, 83, 84, 75, 60, 50, 34, 13, -5, -16, -34, -59, -74, -80, -86, -95, -97, -96, -104, -104, -95, -86, -86, -82, -66, -49, -32, -11, 12, 26, 36, 55, 73, 81, 84, 94, 104, 107, 114, 120, 116, 102, 92, 88, 73, 54, 37, 21, 0, -16, -23, -37, -58, -76, -85, -94, -108, -114, -116, -120, -119, -106, -89, -84, -78, -64, -49, -37, -21, 1, 13, 25, 46, 71, 88, 95, 105, 113, 112, 113, 116, 112, 97, 91, 91, 83, 68, 51, 35, 11, -10, -23, -38, -60, -80, -86, -93, -102, -107, -110, -116, -121, -114, -102, -98, -93, -77, -55, -38, -18, 1, 13, 25, 46, 71, 88, 95, 105, 113, 112, 113, 116, 112, 97, 91, 91, 83, 68, 51, 35, 11, -10, -23, -38, -60, -80, -86, -93, -102, -107, -110, -116, -121, -114, -102, -98, -93, -77, -55, -38, -18, 1, -3, -7, -8, -3, 1, 0, 3, -5, -9, -14, -15, -4, 0, 7, 12, 12, 11, 18, 16, 14, 14, 11, 20, 14, 19, 7, 12, 8, 13, 8, 7, 9, 0, 9, -7, -4, -5, -8, -7, -9, -7, -2, -7, -4, 1, 1, 0, -2, 3, 2, 1, 2, 1, -2, -3, -7, -2, -2, -2, -5, -4, -4, -4, 3, 6, 8, 3, 0, -3, -2, 3, 4, 3, 2, 2, -2, 1, 0, 2, 3, 9, 8, 2, -3, -4, -2, 1, 4, 0, -2, 3, 1, 7, 1, -4, 0, 2, 3, 1, 1, 2, -5, 3, -3, -4, -3, -8, 2, -7, 1, -3, -2, -5, -8, -7, -8, -7, -5, -7, -4, -8, -10, -7, -8, -7, -5, 0, -2, 0, -2, -3, -3, -2, 0, 1, 0, 1, 0, -3, -3, -5, -5, -9, -9, -13, -16, -21, -26, -25, -25, -16, -16, -12, -13, -15, -9, 3, 25, 44, 66, 68, 66, 49, 17, 13, 18, 41, 51, 40, 35, 25, 23, -2, -16, -28, -8, -4, -12, -18, -34, -29, -31, -28, -18, -4, 2, 16, 13, 20, 9, 4, 2, -3, -4, -9, -9, -9, -8, -9, -10, -13, -14, -15, -13, -4, 7, 13, 19, 18, 16, 9, 7, 4, 6, 8, 7, 7, 3, -3, -15, -19, -24, -21, -16, -9, 0, 3, 7, 4, 4, -3, -2, 6, 13, 20, 14, 16, 14, 11, 7, 0, -4, -3, -3, -7, -12, -12, -9, -5, -5, -7, -9, -4, -2, -2, -2, -4, -9, -10, -13, -13, -14, -15, -13, -9, -8, -9, -9, -7, -4, 2, 2, 6, 9, 8, 11, 9, 11, 9, 8, 6, 0, -7, -13, -21, -29, -36, -45, -53, -63, -72, -73, -61, -41, 0, 52, 98, 109, 81, 64, 54, 78, 77, 45, 39, 44, 25, 19, 6, -8, 25, 30, 44, 62, 46, -20, -85, -89, -88, -47, -29, -30, 2, 11, 8, 12, 24, 33, 29, 25, 22, 1, -15, -34, -37, -36, -41, -36, -28, -15, 2, 9, 11, 14, 12, 8, 12, 17, 18, 19, 23, 20, 20, 20, 8, -5, -14, -15, -15, -13, -13, -18, -19, -24, -29, -32, -31, -23, -12, -2, 12, 20, 23, 24, 25, 20, 22, 18, 16, 14, 9, 7, 2, 1, -9, -10, -19, -15, -12, -13, -8, -5, -4, -4, -7, -10, -12, -12, -16, -14, -8, -9, -13, -14, -18, -15, -10, -5, -3, 3, 4, 6, 11, 13, 13, 16, 16, 16, 12, 6, -3, -10, -16, -21, -28, -37, -48, -61, -77, -88, -87, -68, -34, 28, 92, 127, 99, 64, 50, 72, 92, 55, 43, 51, 41, 32, 4, -8, -7, -17, -23, -31, -33, -35, -32, -28, -23, -18, -12, -8, -4, -2, 0, 1, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 4, 6, 7, 7, 7, 8, 9, 9, 8, 8, 9, 11, 14, 18, 22, 27, 32, 33, 30, 21, 6, -12, -30, -45, -54, -56, -51, -41, -29, -17, -9, -3, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 2, 3, 4, 5, 8, 9, 10, 9, 8, 7, 7, 8, 10, 15, 20, 25, 30, 35, 39, 39, 32, 19, 0, -22, -42, -56, -62, -61, -53, -40, -27, -15, -7, -3, -1, 0, 0, 0, 0, 2, 3, 4, 5, 5, 5, 4, 2, 0, -1, 0, 2, 5, 8, 9, 10, 10, 9, 9, 8, 9, 10, 14, 19, 24, 28, 32, 34, 38, 36, 29, 17, -5, -28, -49, -61, -65, -61, -52, -39, -25, -14, -7, -3, -2, -1, -2, -1, 0, 2, 4, 6, 7, 7, 5, 3, 0, -1, -1, 0, 3, 7, 11, 13, 14, 13, 12, 10, 8, 8, 9, 12, 17, 22, 26, 29, 31, 33, 31, 26, 18, 3, -16, -35, -50, -59, -61, -56, -46, -35, -23, -14, -6, -2, 0, 1, 2, 3, 4, 4, 5, 5, 5, 4, 2, 1, -1, -1, 0, 2, 5, 9, 12, 13, 13, 12, 11, 9, 7, 7, 8, 11, 15, 20, 24, 29, 33, 35, 34, 30, 21, 4, -16, -37, -55, -66, -68, -63, -50, -35, -21, -9, -1, 4, 5, 5, 4, 4, 3, 3, 3, 3, 2, 2, 1, 0, -1, -1, 1, 6, 10, 13, 15, 15, 13, 11, 8, 5, 4, 4, 7, 11, 17, 22, 27, 32, 36, 39, 39, 36, 24, 6, -20, -48, -70, -81, -79, -67, -48, -29, -12, -1, 5, 7, 7, 4, 2, 1, 1, 2, 2, 3, 2, 2, -1, -2, -3, -3, -1, 3, 8, 13, 16, 17, 16, 12, 8, 3, -1, -3, -2, 2, 11, 21, 29, 36, 38, 39, 42, 48, 57, 52, 23, -27, -76, -107, -113, -98, -71, -42, -18, -1, 8, 12, 13, 10, 7, 3, 1, 1, 2, 3, 2, 1, 0, -2, -3, -3, -1, 2, 8, 13, 17, 18, 17, 12, 7, 1, -3, -4, -3, 20, 30, 38, 41, 39, 38, 46, 65, 75, 45, -23, -89, -126, -127, -101, -64, -31, -7, 5, 11, 13, 14, 13, 9, 4, 1, 0, 1, 2, 1, -1, -3, -4, -4, -2, 2, 6, 10, 14, 18, 18, 15, 9, 1, -6, -10, -13, -10, -4, 7, 20, 0, 14, 19, 23, 26, 28, 28, 26, 23, 18, 11, 3, -4, -10, -16, -21, -23, -24, -22, -20, -16, -12, -8, -3, 3, 8, 13, 19, 23, 26, 27, 26, 23, 17, 10, 4, -3, -9, -15, -20, -24, -25, -25, -22, -17, -11, -3, 3, 9, 14, 18, 20, 22, 23, 23, 21, 17, 13, 6, 1, -6, -11, -15, -18, -20, -19, -19, -17, -16, -13, -11, -8, -5, -1, 2, 5, 7, 9, 9, 8, 6, 3, 0, -3, -7, -10, -14, -17, -19, -19, -18, -16, -12, -7, -2, 3, 8, 13, 16, 18, 19, 17, 14, 8, -1, -11, -21, -31, -38, -41, -40, -34, -25, -12, 2, 17, 32, 45, 56, 62, 65, 63, 58, 49, 38, 25, 10, -6, -18, -28, -37, -44, -51, -59, -64, -64, -56, -40, -17, 7, 29, 46, 56, 58, 59, 56, 51, 45, 33, 19, 4, -13, -26, -39, -49, -56, -59, -55, -46, -34, -19, -4, 10, 21, 30, 40, 46, 51, 52, 49, 43, 31, 18, 5, -8, -16, -21, -23, -26, -29, -35, -39, -42, -40, -34, -22, -11, 2, 11, 18, 21, 24, 23, 22, 19, 14, 7, -3, -13, -21, -30, -39, -46, -50, -52, -49, -42, -31, -17, -3, 12, 26, 39, 49, 57, 60, 58, 51, 39, 22, 1, -23, -47, -68, -82, -89, -88, -77, -60, -37, -11, 16, 43, 65, 83, 94, 100, 101, 96, 87, 71, 51, 29, 4, -18, -38, -58, -75, -91, -104, -109, -105, -87, -61, -27, 8, 39, 67, 87, 97, 97, 88, 71, 54, 36, 16, -2, -23, -42, -57, -70, -75, -75, -71, -60, -43, -23, -1, 18, 31, 47, 57, 66, 71, 68, 61, 49, 32, 17, 1, -11, -22, -33, -41, -47, -54, -59, -63, -62, -57, -46, -30, -12, 1, 17, 30, 41, 49, 50, 47, 40, 29, 17, 3, -14, -30, -46, -60, -70, -76, -77, -73, -63, -48, -28, -4, 20, 44, 65, 81, 91, 93, 88, 77, 60, 37, 11, -19, -49, -76, -97, -109, -110, -100, -81, -56, -25, 7, 38, 67, 91, 109, 121, 127, 126, 116, 96, 68, 38, 8, -18, -43, -68, -90, -110, -124, -127, -116, -91, -59, -22, 14, 47, 77, 98, 107, 105, 93, 74, 54, 33, 13, -6, -26, -45, -60, -71, -78, -79, -74, -61, -42, -21, 1, 18, 33, 49, 60, 68, 73, 70, 62, 48, 32, 15, 0, -13, -24, -34, -42, -48, -55, -61, -65, -65, -60, -48, -32, -15, 2, 19, 32, 43, 50, 51, 47, 40, 28, 16, 1, -14, 2, -2, 2, -5, -3, -1, 0, -4, -4, -6, -4, -6, -4, -4, -7, -6, -7, -6, -1, 0, 3, 13, 14, 16, 12, 13, 2, 1, 0, -1, -1, -1, -2, -2, -2, -3, -3, -4, -8, -4, -4, -5, -5, -5, -7, -9, -12, -8, -14, -11, -14, -18, -8, 1, 31, 71, 68, 24, -5, -11, -7, -5, -5, -5, -3, -2, -5, -5, -9, -8, -7, -7, -9, -12, -11, -17, -14, -16, -15, -20, -26, -30, -27, -15, 16, 51, 87, 101, 70, 8, -18, -11, -14, -7, -7, -1, -2, -5, -7, -12, -14, -10, -10, -13, -14, -13, -16, -16, -17, -18, -35, -31, -30, -34, -9, 16, 56, 84, 89, 60, 30, 5, -7, -5, -8, -3, -4, -4, -6, -12, -14, -13, -10, -12, -12, -9, -10, -8, -12, -13, -15, -19, -23, -26, -33, -29, -28, -9, 12, 43, 71, 88, 72, 48, 29, -2, -16, -19, -12, -12, -12, -7, -11, -10, -10, -10, -11, -13, -15, -18, -19, -17, -16, -15, -13, -12, -13, -9, -13, -17, -21, -18, 2, 34, 59, 87, 92, 98, 38, -30, -24, -27, -18, -16, -11, -11, -13, -15, -12, -14, -15, -18, -17, -20, -18, -15, -10, -7, -3, -1, 2, -8, -11, -22, -22, -20, 7, 31, 61, 97, 106, 43, -23, -28, -25, -20, -12, -7, -5, -7, -10, -13, -13, -13, -11, -14, -15, -15, -12, -8, -7, -4, -2, -4, -10, -15, -19, -26, -10, 12, 42, 72, 101, 90, 20, -25, -27, -22, -18, -10, -6, -9, -11, -16, -17, -16, -14, -10, -8, -9, -9, -9, -9, -9, -8, -5, -3, -6, -10, -17, -24, -21, 4, 30, 61, 84, 96, 79, -16, -38, -27, -26, -17, -12, -8, -12, -13, -14, -14, -11, -8, -4, -4, -7, -9, -8, -10, -12, -8, -5, -4, -7, -10, -18, -24, -11, 14, 42, 70, 79, 93, 36, -32, -26, -28, -19, -15, -9, -9, -13, -16, -14, -12, -8, -5, -3, -7, -9, -9, -9, -11, -8, -5, -1, -6, -9, -15, -24, -23, 6, 28, 63, 86, 127, 37, -45, -27, -28, -26, -19, -4, -5, -8, -11, -12, -14, -12, -8, -4, -8, -8, -10, -8, -13, -8, -8, -3, -8, -8, -16, -23, -17, 7, 34, 69, 83, 113, 37, -50, -28, -25, -22, -16, 0, -3, -8, -12, -12, -14, -14, -10, -5, -7, -6, -9, -9, -13, -9, -10, -7, -9, -9, -15, -20, -14, 8, 33, 64, 81, 90, 57, -29, -28, 0, -4, 10, 10, 11, -15, 4, -1, 3, -11, 11, 2, -12, 3, 18, -10, -62, 89, -16, -95, 118, -128, 122, -128, 112, -100, 109, -121, 120, -104, 58, 10, -88, 127, -102, 6, 98, -126, 35, 89, -111, -7, 112, -53, -94, 92, 64, -106, -53, 109, 52, -100, -75, 86, 95, -45, -119, -12, 111, 74, -58, -118, -27, 97, 100, -4, -107, -95, 17, 109, 92, -4, -99, -109, -26, 78, 115, 66, -27, -104, -109, -41, 55, 112, 98, 32, -53, -109, -105, -44, 41, 102, 109, 67, -4, -74, -112, -102, -47, 27, 88, 112, 93, 45, -19, -78, -110, -105, -65, -4, 59, 101, 110, 87, 43, -13, -67, -103, -111, -89, -44, 13, 65, 100, 109, 93, 59, 14, -36, -78, -104, -108, -90, -53, -6, 43, 83, 104, 106, 88, 57, 17, -27, -66, -95, -108, -102, -80, -44, -2, 41, 77, 99, 106, 98, 77, 46, 10, -29, -64, -91, -105, -105, -91, -64, -29, 10, 48, 78, 98, 105, 100, 84, 59, 30, -3, -36, -65, -88, -101, -105, -99, -83, -60, -32, -1, 30, 58, 80, 96, 103, 102, 94, 80, 62, 40, 16, -10, -35, -58, -78, -92, -101, -104, -100, -91, -77, -58, -36, -13, 12, 36, 57, 75, 89, 98, 102, 102, 97, 88, 76, 61, 44, 25, 5, -15, -35, -54, -70, -84, -94, -101, -104, -103, -98, -89, -77, -63, -46, -27, -8, 12, 31, 49, 65, 79, 90, 97, 102, 104, 102, 97, 90, 81, 70, 57, 42, 27, 10, -7, -24, -40, -56, -70, -81, -91, -99, -103, -105, -105, -101, -95, -87, -76, -63, -49, -34, -18, -1, 16, 32, 48, 62, 74, 85, 93, 100, 104, 105, 105, 102, 97, 90, 82, 72, 61, 48, 35, 21, 6, -9, -24, -38, -52, -65, -76, -86, -94, -101, -105, -108, -108, -106, -102, -96, -87, -78, -66, -54, -40, -26, -11, 4, 19, 34, 48, 61, 73, 83, 92, 99, 104, 107, 108, 108, 105, 101, 96, 89, 80, 70, 60, 48, 36, 22, 9, -5, -19, -33, -46, -58, -69, -80, -89, -96, -102, -107, -109, -110, -110, -107, -102, -97, -89, -80, -70, -59, -47, -33, -20, -6, 7, 19, 30, 41, 50, 58, 65, 71, 75, 78, 79, 80, 79, 77, 74, 70, 65, 60, 54, 48, 42, 36, 29, 22, 16, 10, 4, -2, -7, -12, -16, -19, -22, -24, -26, -27, -27, -27, -26, -25, -23, -22, -19, -17, -14, -12, -10, -1, -1, -4, -9, -9, -7, -6, -7, -3, 4, 8, 10, 11, 13, 10, 4, -3, -10, -15, -13, -9, -10, -11, -5, 4, 12, 14, 12, 13, 14, 9, 1, -8, -15, -21, -23, -22, -13, -3, 7, 17, 24, 27, 19, 11, 16, 15, -5, -24, -29, -23, -27, -32, -21, 5, 18, 20, 21, 24, 24, 15, 11, 8, -6, -30, -31, -19, -17, -24, -14, 2, 17, 15, 12, 17, 16, 19, 8, -5, -2, -1, -17, -17, -3, 6, 5, -4, 0, 1, -12, -9, 9, 11, -4, -14, -8, 9, -2, -21, -14, 4, 9, 9, 11, 18, 21, 10, 8, 16, 10, 26, 35, 6, -14, -28, -25, -24, -55, -65, -33, -17, 1, -6, -6, 8, 23, 33, 49, 37, 19, 16, 11, 24, 42, 17, -37, -36, 3, 7, -23, -36, -9, 9, -12, -20, -8, -2, -4, -23, -17, -6, 0, 10, 24, 24, 40, 46, 33, 39, 26, 5, 6, 9, -12, -26, -33, -42, -61, -52, -43, -37, -21, -4, 7, 13, 28, 36, 31, 24, 1, -1, 20, 24, 23, 21, 26, 27, 8, -32, -44, -3, 28, -1, -36, -30, -6, 13, -12, -34, -18, -6, 9, 21, 25, 16, 10, 38, 62, 46, 17, -11, -7, 10, -8, -44, -53, -33, -35, -38, -29, -27, -16, 0, 1, 9, 37, 50, 36, 2, -20, -12, 15, 21, 24, 32, 29, 20, 23, 12, -8, -3, 4, -10, -5, 2, -19, -63, -70, -21, 20, 41, 23, 33, 57, 61, 42, 21, 15, 10, -45, -82, -60, -29, -44, -77, -50, -7, 4, -4, 10, 32, 56, 42, 1, -10, -18, 2, 22, 28, 33, 42, 47, 43, 47, 11, -23, 0, 10, -40, -81, -70, -28, -29, -68, -29, 19, 6, 7, 21, 40, 41, 32, 22, 28, 47, 69, 66, 35, 21, 15, -3, -20, -34, -24, -6, -19, -59, -47, -42, -35, -28, 15, 45, 51, 66, 78, 83, 37, 1, 13, 7, -51, -81, -92, -83, -87, -74, -58, -73, -51, 12, 35, 26, 35, 47, 69, 70, 63, 65, 49, 47, 68, 73, 52, 33, 15, -12, -30, -50, -51, -46, -45, -60, -50, -50, -50, -54, -24, 38, 78, 90, 106, 99, 40, -6, -11, -46, -110, -127, -107, -76, -67, -53, -41, -41, -23, 14, 33, 27, 34, 49, 70, 71, 66, 65, 51, 51, 69, 72, 52, 32, 10, -12, 0, -5, -2, -5, 2, -29, 22, 0, -27, 67, -59, 45, -13, -37, 28, 65, -4, 6, 60, 5, 58, 44, 60, 27, 43, 96, 71, 81, 48, 96, 70, 23, 90, 66, 80, 88, 40, 20, 61, 64, 12, 36, 24, 4, 7, 5, -27, -38, -26, -33, -49, -50, -70, -69, -93, -92, -94, -104, -104, -101, -110, -107, -111, -111, -126, -87, -119, -100, -94, -112, -93, -93, -80, -81, -76, -58, -56, -70, -30, -21, -42, -13, -3, 2, 8, 20, 28, 41, 45, 59, 62, 69, 84, 85, 90, 103, 109, 111, 118, 121, 121, 123, 121, 122, 121, 122, 121, 122, 121, 121, 120, 121, 120, 121, 120, 121, 120, 120, 119, 120, 119, 120, 118, 105, 106, 110, 83, 89, 92, 75, 67, 61, 57, 47, 40, 33, 24, 17, 10, 3, -2, -10, -20, -31, -31, -37, -49, -50, -63, -66, -69, -74, -79, -91, -89, -92, -95, -102, -106, -104, -107, -113, -113, -110, -113, -116, -114, -115, -114, -115, -114, -113, -114, -113, -114, -113, -112, -113, -109, -105, -111, -106, -107, -103, -100, -103, -99, -97, -98, -99, -92, -92, -93, -92, -92, -90, -88, -90, -88, -86, -89, -85, -85, -87, -85, -85, -82, -83, -82, -80, -78, -79, -76, -74, -73, -73, -69, -68, -66, -64, -65, -62, -58, -56, -56, -52, -50, -47, -43, -42, -39, -35, -33, -31, -27, -23, -21, -16, -16, -8, -7, -3, 1, 0, 10, 15, 15, 19, 26, 29, 30, 38, 41, 42, 47, 54, 54, 57, 63, 68, 69, 72, 77, 78, 80, 85, 84, 86, 87, 86, 87, 86, 85, 86, 85, 84, 85, 84, 83, 84, 83, 82, 82, 83, 82, 81, 82, 81, 80, 81, 80, 79, 80, 79, 79, 78, 79, 78, 78, 77, 74, 70, 66, 64, 61, 55, 52, 49, 45, 40, 35, 32, 29, 24, 19, 15, 12, 8, 4, 0, -4, -8, -11, -15, -17, -20, -25, -26, -29, -32, -34, -37, -39, -41, -43, -45, -46, -48, -49, -50, -50, -52, -52, -53, -52, -53, -54, -53, -53, -52, -52, -51, -50, -50, -49, -48, -48, -46, -45, -44, -42, -41, -40, -39, -37, -35, -34, -32, -30, -28, -27, -24, -23, -22, -20, -19, -17, -15, -14, -13, -12, -10, -9, -8, -8, -6, -6, -5, -4, -4, -3, -3, -2, -2, -1, -2, -1, -2, -1, -1, 0, -1, -1, 1, 0, 0, -3, -1, 1, -4, -4, -3, -2, -5, -3, 0, -1, -1, -3, -1, 0, 2, 0, -2, -5, 5, 4, 1, 7, 2, 2, 1, 8, 1, 6, 2, -4, 2, 1, -4, 6, -8, -3, -7, -2, -6, -1, -9, 1, -2, -4, 1, 2, 1, -2, 8, 2, 0, 14, 9, 10, 5, 3, 5, 6, 4, 3, -8, -2, -4, -10, -1, -5, -3, -4, -6, -13, -5, -4, -4, -3, 2, -13, -6, 3, 6, 6, 7, 1, 1, 6, 6, 16, 13, 9, 10, 9, 2, 7, 10, 4, -4, -3, -17, -7, -6, -6, -10, -17, -17, -10, -11, -9, -5, -6, -8, 2, 1, 8, 19, 15, 18, 24, 19, 16, 17, 19, 11, 7, 1, -5, -8, -9, -15, -8, -9, -14, -20, -19, -9, -18, -10, -13, -23, -13, -12, -7, 0, -1, 5, 16, 12, 28, 30, 32, 34, 34, 19, 24, 23, 16, 11, 5, -7, -19, -17, -16, -21, -26, -23, -32, -31, -30, -25, -26, -24, -19, -13, -9, -1, 0, 4, 6, 13, 15, 19, 17, 13, 8, 8, 8, 7, 0, -4, -8, -10, -7, -5, -6, -6, -9, -12, -8, -10, -9, -9, -11, -13, -12, -9, -4, -1, 4, 9, 19, 27, 31, 26, 16, 14, 16, 16, 12, 1, -8, -14, -11, -9, -6, -11, -11, -12, -14, -10, -11, -13, -15, -19, -23, -19, -14, -8, -5, -1, 8, 34, 62, 59, 12, 14, 32, 22, 6, 20, 6, -9, -54, -16, -1, -19, 7, -15, -13, -12, -14, -15, -14, -22, -24, -30, -30, -20, -12, -6, 3, 26, 66, 88, 39, 0, 47, 36, -2, 26, -23, 21, 13, -6, -60, -42, 6, -22, 4, -18, -16, -4, -16, -19, -24, -39, -31, -25, -32, -26, -11, 12, 55, 104, 75, 10, 35, 62, 9, 26, -16, -8, 19, 3, -9, -61, -46, 2, -26, -7, -16, -10, 2, -7, -22, -23, -38, -40, -37, -44, -33, -8, 37, 101, 124, 36, -5, 89, 20, 38, 5, -26, 3, 1, 5, -28, -65, -21, 1, -22, -12, -26, 1, -7, -10, -24, -26, -33, -37, -48, -50, -36, 5, 63, 122, 109, 7, 35, 84, 5, 59, -36, -4, -11, -1, -5, -40, -55, -4, -15, -21, -16, -22, 5, -10, -17, -20, -27, -23, -44, -54, -62, -23, 29, 114, 127, 51, 7, -2, -4, -2, 4, 11, 14, 10, 2, -7, -9, -9, -15, -16, -7, 3, 2, -10, -21, -17, 6, 10, -8, -28, -11, 45, 66, 64, 47, 36, 49, 49, 27, 9, -12, -18, -25, -30, -11, 0, -5, 0, -1, -18, -36, -33, -18, -10, -13, -31, -26, -25, -17, 4, 28, 70, 89, 48, 9, -32, -58, -56, -70, -57, -17, -38, -48, -35, -32, -7, 35, 38, 53, 62, 44, 33, 27, -6, -35, -52, -65, -54, -40, -43, -30, -25, 2, 63, 54, 34, 17, 34, 70, 60, 8, -15, -3, 0, 39, 55, 35, 39, 60, 75, 36, 20, -7, -25, -66, -110, -89, -89, -71, -36, -12, 9, 31, 41, 54, 46, 45, 59, 41, 22, 3, -69, -110, -126, -116, -64, -15, 9, 29, 33, 30, 56, 42, 12, 23, 6, -27, -36, -21, -22, -32, -21, -30, -29, -5, 9, 16, 22, -9, -12, 31, 24, -17, -41, -23, 32, 32, 26, 34, 64, 66, 109, 104, 51, 5, 12, 16, -36, -58, -59, -66, -63, -82, -64, -23, -9, 11, 16, 20, 19, 13, 12, 33, 37, 41, 46, 28, 7, -58, -93, -79, -64, -33, -1, 22, -4, 2, 19, 4, -7, -3, -3, 5, 1, -10, -3, 12, -6, -38, -29, -17, -5, 11, 2, -33, -20, 44, 42, 20, -30, -24, 9, 44, 38, 20, 36, 71, 61, 86, 72, 25, -8, 10, 17, -35, -54, -63, -67, -70, -78, -58, -16, -7, 19, 22, 20, 21, 29, 21, 16, 35, 36, 16, -8, -27, -61, -58, -67, -43, 3, 35, 38, -2, -2, 10, -9, -29, -14, -5, -1, -5, 2, 12, -6, -32, -23, -22, -16, -5, 3, -9, -29, 27, 56, 39, 11, -27, -28, 23, 34, 28, 18, 20, 62, 82, 71, 74, 24, -4, 16, 18, -39, -54, -65, -61, -52, -64, -49, -11, -4, 12, 17, 16, 25, 24, 6, 23, 36, 18, 18, -1, -42, -50, -90, -43, 3, 35, 38, -2, -2, 10, -9, -29, -14, -5, -1, -5, 2, 12, -6, -32, -23, -22, -16, -5, 3, -9, -29, 27, 56, 39, 11, -27, -28, 23, 34, 28, 18, 20, 62, 82, 71, 74, 24, -4, 16, 18, -39, -54, -65, -61, -52, -64, -49, -11, -4, 12, 17, 16, 25, 24, 6, 23, 36, 18, 18, -1, -42, -50, -90, -43, 0, 1, 6, -11, 19, -25, 24, -15, 11, -6, 1, 9, -6, -3, 11, -18, 28, -23, 8, 6, -2, -1, 0, -5, 18, -23, 24, -28, 27, -12, -1, -2, 6, 4, -14, 19, -29, 42, -40, 22, -6, -3, 14, -16, 4, 8, -9, 13, -22, 17, 5, -24, 37, -34, 20, -4, -11, 19, -20, 21, -16, 1, 17, -17, 5, -9, 25, -31, 31, -40, 32, -11, -7, 4, -4, 13, -23, 29, -40, 51, -49, 20, 3, -20, 38, -47, 34, -21, 14, -9, 4, -13, 20, -29, 37, -57, 59, -48, 23, -5, -7, 5, -6, -5, 13, -17, 9, -4, -12, 22, -19, -8, 10, -5, -7, 8, -18, 19, -13, 5, -12, 6, -10, 18, -40, 66, -91, 82, -56, 17, 19, -51, 56, -45, 30, -19, 5, -6, 7, -9, -4, -2, -5, 13, -19, 1, 20, -28, 13, -6, 0, -17, 33, -48, 38, -16, -20, 53, -75, 75, -61, 30, -12, -9, 2, 5, -9, -7, 15, -17, 9, 4, -46, 70, -85, 86, -67, 29, 18, -60, 76, -70, 29, -8, -1, 1, 14, -58, 93, -118, 127, -125, 85, -36, -2, 17, -39, 46, -61, 70, -99, 122, -120, 56, 15, -85, 116, -101, 30, 43, -108, 127, -122, 72, -38, -3, 20, -31, 29, -37, 42, -50, 63, -72, 40, -7, -46, 66, -82, 53, -25, 1, 1, -1, -3, 3, -24, 24, -34, 27, -24, 36, -49, 37, -38, 35, -42, 13, -4, -14, 14, -29, 42, -58, 58, -60, 41, -39, 27, -35, 27, -32, 25, -37, 43, -50, 32, -20, -4, 4, -14, 16, -43, 66, -93, 79, -58, 27, -11, -21, 34, -40, 24, -7, -25, 31, -29, 19, -18, -2, 1, -6, 4, -31, 47, -63, 62, -64, 32, 2, -29, 23, -21, 19, -41, 59, -76, 62, -52, 26, -11, -1, -10, 6, -10, -7, 17, -42, 34, -12, -34, 73, -106, 92, -61, 26, -24, 8, -7, -2, 3, -24, 31, -44, 27, -9, -22, 38, -43, 15, -4, -3, -2, -12, 5, 1, -7, 7, -25, 17, -17, 4, -15, 27, -40, 34, -18, 6, -13, 12, -3, -9, -6, 8, -18, 18, -36, 54, -55, 30, -25, 26, -41, 38, -49, 48, -38, 8, 16, -40, 47, -52, 34, -12, -4, 2, -13, 0, 1, 6, -11, 19, -25, 24, -15, 11, -6, 1, 9, -6, -3, 11, -18, 28, -23, 8, 6, -2, -1, 0, -5, 18, -23, 24, -28, 27, -12, -1, -2, 6, 4, -14, 19, -29, 42, -40, 22, -6, -3, 14, -16, 4, 8, -9, 13, -22, 17, 5, -24, 37, -34, 20, -4, -11, 19, -20, 21, -16, 1, 17, -17, 5, -9, 25, -31, 31, -40, 32, -11, -7, 4, -4, 13, -23, 29, -40, 51, -49, 20, 3, -20, 38, -47, 34, -21, 14, -9, 4, -13, 20, -29, 37, -57, 59, -48, 23, -5, -7, 5, -6, -5, 13, -17, 9, -4, -12, 22, -19, -8, 10, -5, -7, 8, -18, 19, -13, 5, -12, 6, -10, 18, -40, 66, -91, 82, -56, 17, 19, -51, 56, -45, 30, -19, 5, -6, 7, -9, -4, -2, -5, 13, -19, 1, 20, -28, 13, -6, 0, -17, 33, -48, 38, -16, -20, 53, -75, 75, -61, 30, -12, -9, 2, 5, -9, -7, 15, -17, 9, 4, -46, 70, -85, 86, -67, 29, 18, -60, 76, -70, 29, -8, -1, 1, 14, -58, 93, -118, 127, -125, 85, -36, -2, 17, -39, 46, -61, 70, -99, 122, -120, 56, 15, -85, 116, -101, 30, 43, -108, 127, -122, 72, -38, -3, 20, -31, 29, -37, 42, -50, 63, -72, 40, -7, -46, 66, -82, 53, -25, 1, 1, -1, -3, 3, -24, 24, -34, 27, -24, 36, -49, 37, -38, 35, -42, 13, -4, -14, 14, -29, 42, -58, 58, -60, 41, -39, 27, -35, 27, -32, 25, -37, 43, -50, 32, -20, -4, 4, -14, 16, -43, 66, -93, 79, -58, 27, -11, -21, 34, -40, 24, -7, -25, 31, -29, 19, -18, -2, 1, -6, 4, -31, 47, -63, 62, -64, 32, 2, -29, 23, -21, 19, -41, 59, -76, 62, -52, 26, -11, -1, -10, 6, -10, -7, 17, -42, 34, -12, -34, 73, -106, 92, -61, 26, -24, 8, -7, -2, 3, -24, 31, -44, 27, -9, -22, 38, -43, 15, -4, -3, -2, -12, 5, 1, -7, 7, -25, 17, -17, 4, -15, 27, -40, 34, -18, 6, -13, 12, -3, -9, -6, 8, -18, 18, -36, 54, -55, 30, -25, 26, -41, 38, -49, 48, -38, 8, 16, -40, 47, -52, 34, -12, -4, 2, -13, -1, -2, -1, -4, -3, -25, -41, 8, 16, 27, 2, 16, 1, 13, 21, -8, -6, -29, 17, 8, 8, 20, -13, 5, 4, 25, 17, 30, 22, 14, 15, 19, 7, 51, -16, -15, -32, -13, 12, -8, -17, -49, -27, -29, -29, -52, -66, -55, -32, -20, -41, -21, -36, -11, -16, 22, 3, 19, 0, -6, -10, 0, -38, -17, -35, -19, -27, 0, -35, -27, -9, -17, -14, -2, 20, 50, 63, 57, 49, 70, 70, 97, 81, 68, 52, 78, 93, 98, 102, 56, 34, 20, 53, 60, 45, 24, -18, 21, -10, 0, -38, -79, -38, -37, -13, -27, -41, -50, -51, 14, 10, 16, -21, -13, -22, -20, -48, -53, -55, -66, -76, -65, -91, -105, -92, -87, -101, -79, -56, -34, -7, -4, 7, 20, 15, 26, 29, 32, -8, 36, 47, 50, 66, 29, 18, -33, -11, -4, -10, -24, -42, -31, -22, 2, -23, -75, -34, -36, 5, 1, 1, -17, -47, 20, 43, 68, 28, 30, 9, 29, 7, -9, -5, -32, -46, -36, -15, -40, -35, -15, -26, -21, 2, 21, 49, 62, 83, 87, 106, 77, 97, 94, 67, 60, 85, 79, 110, 80, 61, 1, 8, 16, 50, 36, 2, -22, 4, -2, 21, -35, -33, -19, 4, 24, 19, 10, -58, -23, 18, 45, 34, 8, -12, -6, -5, -48, -51, -75, -72, -77, -37, -65, -80, -57, -66, -68, -38, -38, 2, 10, 38, 31, 58, 22, 39, 37, 27, -9, 23, 9, 35, 18, 15, -31, -50, -44, -5, 6, -10, -63, -41, -56, -15, -41, -71, -45, -37, 7, -6, 5, -56, -71, -6, 21, 41, 8, -13, -14, -40, -30, -41, -40, -56, -31, -31, -9, -15, -5, 10, 42, 27, 73, 82, 73, 73, 79, 70, 38, 28, 31, 23, 45, 42, 44, 30, -40, 8, 28, 52, 30, -18, -29, -40, -14, -45, -50, -55, -68, -39, -6, -29, -45, -59, -32, 4, 31, 23, 16, 20, 11, -1, 1, -28, -45, -53, -56, -67, -60, -55, -40, -31, -25, -16, 11, 20, 36, 67, 70, 75, 77, 81, 65, 46, 38, 34, 39, 51, 44, 57, 7, -4, 13, 37, 46, 19, -8, -29, -1, -9, -21, -32, -43, -55, -58, -40, -8, 15, 29, 38, 44, 59, 63, 51, 20, -20, -47, -61, -58, -48, -42, -43, -35, -15, 15, 41, 55, 61, 62, 70, 67, 45, 11, -31, -62, -80, -78, -71, -62, -54, -39, -15, 18, 50, 68, 79, 83, 92, 88, 57, 16, -31, -71, -94, -95, -90, -83, -71, -55, -28, 7, 49, 77, 93, 100, 109, 107, 78, 36, -20, -71, -99, -104, -100, -92, -83, -69, -43, -5, 42, 79, 100, 108, 114, 112, 90, 51, -9, -65, -100, -110, -105, -95, -87, -76, -52, -11, 35, 75, 100, 107, 111, 106, 90, 52, -4, -60, -97, -109, -99, -87, -80, -65, -35, 5, 43, 75, 91, 95, 93, 87, 71, 31, -19, -64, -93, -99, -88, -76, -66, -44, -9, 28, 59, 79, 84, 80, 71, 59, 35, -5, -45, -76, -96, -95, -77, -59, -39, -9, 28, 61, 86, 98, 93, 74, 52, 28, -6, -43, -72, -94, -108, -99, -77, -52, -20, 19, 56, 84, 106, 115, 106, 79, 45, 3, -40, -74, -93, -108, -112, -100, -79, -46, -1, 45, 78, 100, 113, 118, 108, 81, 39, -19, -67, -93, -103, -108, -104, -94, -74, -32, 19, 61, 88, 102, 108, 109, 100, 73, 21, -44, -87, -102, -104, -97, -90, -78, -49, 0, 46, 78, 90, 92, 89, 87, 77, 43, -15, -72, -101, -104, -93, -79, -69, -47, -3, 47, 84, 96, 89, 74, 65, 58, 37, -7, -61, -99, -110, -101, -82, -62, -38, 2, 49, 92, 112, 106, 82, 59, 41, 18, -19, -61, -95, -111, -110, -98, -74, -39, 6, 54, 99, 122, 123, 104, 79, 50, 12, -32, -72, -100, -111, -110, -106, -90, -54, -4, 49, 99, 123, 126, 113, 95, 69, 24, -27, -72, -102, -114, -109, -104, -94, -64, -16, 36, 87, 116, 121, 111, 97, 76, 36, -15, -61, -94, -110, -108, -98, -86, -60, -19, 29, 77, 104, 109, 99, 86, 67, 35, -7, -47, -82, -98, -101, -92, -77, -48, -14, 25, 67, 92, 95, 83, 66, 45, 18, -9, -37, -62, -77, -81, -78, -54, -16, 0, 0, 0, 12, -10, 16, -14, -18, 17, -31, -2, 3, -19, -8, 17, 28, 37, 31, -1, -25, -16, -47, -13, -43, -22, 6, 34, 41, 49, 41, 27, 6, -33, -62, -54, -59, -32, -13, 29, 53, 73, 60, 54, 16, -19, -58, -77, -89, -42, -46, 17, 55, 78, 86, 81, 33, -3, -35, -84, -110, -75, -70, 0, 39, 78, 92, 105, 70, 13, -15, -82, -107, -103, -84, -41, 20, 81, 85, 127, 86, 39, -4, -63, -103, -99, -107, -69, 2, 68, 82, 127, 84, 58, 28, -44, -88, -104, -108, -83, -13, 29, 69, 116, 87, 77, 40, -16, -65, -89, -104, -89, -40, -1, 47, 96, 90, 85, 52, 9, -38, -62, -96, -95, -62, -22, 21, 73, 78, 86, 65, 35, -15, -41, -80, -92, -69, -48, 1, 43, 65, 80, 73, 49, 8, -23, -59, -75, -74, -60, -22, 17, 49, 69, 65, 60, 25, -1, -36, -59, -70, -61, -40, -9, 30, 52, 57, 63, 37, 17, -12, -41, -61, -57, -50, -30, 9, 30, 49, 60, 47, 28, 6, -20, -49, -51, -53, -42, -11, 13, 34, 53, 50, 34, 18, -3, -35, -39, -52, -49, -23, 0, 18, 41, 47, 36, 31, 10, -21, -28, -43, -49, -31, -13, 2, 28, 39, 35, 38, 19, -7, -18, -33, -42, -36, -26, -12, 19, 30, 34, 36, 22, 6, -5, -25, -38, -36, -29, -17, 8, 19, 26, 35, 28, 12, 3, -17, -30, -29, -29, -22, -3, 9, 19, 33, 26, 14, 8, -9, -18, -22, -28, -25, -9, 3, 15, 22, 20, 18, 12, 1, -11, -22, -24, -21, -13, -3, 8, 11, 20, 21, 12, 5, -6, -19, -16, -17, -17, -7, 3, 8, 20, 17, 7, 7, -2, -11, -13, -16, -17, -5, 2, 5, 12, 13, 8, 6, 3, -9, -11, -9, -14, -5, 1, -3, 6, 11, 6, 7, 2, -6, -4, -4, -10, -6, -3, -4, 5, 8, 2, 5, 4, -2, 0, -3, -9, -4, -3, -3, 2, 3, 0, 6, 4, 0, -1, -2, -2, 0, 0, 0, 12, -10, 16, -14, -18, 17, -31, -2, 3, -19, -8, 17, 28, 37, 31, -1, -25, -16, -47, -13, -43, -22, 6, 34, 41, 49, 41, 27, 6, -33, -62, -54, -59, -32, -13, 29, 53, 73, 60, 54, 16, -19, -58, -77, -89, -42, -46, 17, 55, 78, 86, 81, 33, -3, -35, -84, -110, -75, -70, 0, 39, 78, 92, 105, 70, 13, -15, -82, -107, -103, -84, -41, 20, 81, 85, 127, 86, 39, -4, -63, -103, -99, -107, -69, 2, 68, 82, 127, 84, 58, 28, -44, -88, -104, -108, -83, -13, 29, 69, 116, 87, 77, 40, -16, -65, -89, -104, -89, -40, -1, 47, 96, 90, 85, 52, 9, -38, -62, -96, -95, -62, -22, 21, 73, 78, 86, 65, 35, -15, -41, -80, -92, -69, -48, 1, 43, 65, 80, 73, 49, 8, -23, -59, -75, -74, -60, -22, 17, 49, 69, 65, 60, 25, -1, -36, -59, -70, -61, -40, -9, 30, 52, 57, 63, 37, 17, -12, -41, -61, -57, -50, -30, 9, 30, 49, 60, 47, 28, 6, -20, -49, -51, -53, -42, -11, 13, 34, 53, 50, 34, 18, -3, -35, -39, -52, -49, -23, 0, 18, 41, 47, 36, 31, 10, -21, -28, -43, -49, -31, -13, 2, 28, 39, 35, 38, 19, -7, -18, -33, -42, -36, -26, -12, 19, 30, 34, 36, 22, 6, -5, -25, -38, -36, -29, -17, 8, 19, 26, 35, 28, 12, 3, -17, -30, -29, -29, -22, -3, 9, 19, 33, 26, 14, 8, -9, -18, -22, -28, -25, -9, 3, 15, 22, 20, 18, 12, 1, -11, -22, -24, -21, -13, -3, 8, 11, 20, 21, 12, 5, -6, -19, -16, -17, -17, -7, 3, 8, 20, 17, 7, 7, -2, -11, -13, -16, -17, -5, 2, 5, 12, 13, 8, 6, 3, -9, -11, -9, -14, -5, 1, -3, 6, 11, 6, 7, 2, -6, -4, -4, -10, -6, -3, -4, 5, 8, 2, 5, 4, -2, 0, -3, -9, -4, -3, -3, 2, 3, 0, 6, 4, 0, -1, -2, -2, 0, -1, -1, -3, -7, -14, -23, -32, -45, -55, -66, -74, -83, -88, -80, -77, -71, -64, -54, -46, -37, -31, -25, -19, -12, -6, -1, 4, 8, 12, 17, 21, 23, 25, 25, 27, 29, 32, 35, 36, 34, 32, 31, 32, 35, 37, 37, 35, 31, 29, 29, 31, 33, 34, 32, 29, 26, 25, 27, 30, 32, 31, 29, 27, 27, 29, 31, 34, 35, 35, 35, 36, 38, 41, 43, 45, 47, 49, 52, 55, 57, 59, 61, 63, 66, 69, 70, 70, 68, 66, 63, 61, 58, 54, 47, 36, 24, 11, 1, -9, -20, -33, -48, -64, -78, -89, -97, -103, -110, -116, -123, -128, -128, -126, -121, -116, -112, -107, -102, -95, -88, -78, -69, -61, -54, -47, -41, -34, -27, -21, -16, -12, -7, -2, 2, 5, 6, 8, 10, 13, 16, 19, 19, 19, 17, 18, 19, 22, 24, 24, 22, 19, 18, 19, 21, 23, 24, 22, 19, 17, 18, 20, 22, 24, 24, 22, 21, 22, 24, 27, 29, 30, 30, 31, 32, 35, 37, 40, 42, 45, 47, 50, 53, 56, 58, 60, 62, 66, 68, 70, 69, 68, 65, 63, 61, 59, 54, 46, 36, 24, 13, -1, -14, -28, -43, -57, -68, -78, -86, -94, -102, -109, -114, -117, -117, -115, -112, -109, -106, -101, -96, -89, -81, -73, -67, -59, -53, -46, -40, -34, -28, -23, -18, -13, -9, -5, -2, 0, 2, 5, 7, 10, 12, 14, 15, 15, 15, 16, 18, 19, 20, 20, 19, 18, 18, 19, 21, 22, 22, 21, 20, 19, 21, 23, 24, 25, 25, 25, 25, 26, 29, 31, 33, 34, 35, 36, 38, 40, 43, 46, 48, 51, 53, 56, 59, 62, 65, 68, 71, 74, 77, 78, 79, 78, 77, 76, 74, 71, 66, 58, 49, 39, 28, 17, 6, -6, -20, -35, -50, -64, -75, -85, -94, -102, -110, -117, -122, -124, -123, -121, -118, -114, -110, -106, -99, -92, -84, -76, -69, -61, -55, -48, -41, -34, -29, -23, -18, -13, -9, -5, -2, 0, -1, -1, 0, 2, 0, 3, 2, 2, 4, 5, 4, 4, 4, 4, 5, 3, 4, 3, 1, 2, 0, 0, -1, -3, -4, -2, -3, -5, -3, -4, -5, -5, -4, -3, -3, -6, -5, -4, -2, -5, -5, -2, -3, -3, -3, 1, 4, 4, 8, 8, 8, 13, 12, 13, 14, 12, 9, 8, 6, 6, 3, -2, -2, -5, -5, -4, -5, -11, -16, -12, -7, -3, -5, -10, -11, -6, -2, -2, -1, -4, -6, -6, -7, -8, -5, -2, 2, 5, 6, 8, 8, 9, 13, 16, 16, 14, 11, 7, 5, 4, 2, 0, -2, -3, -3, 0, -3, -13, -28, -11, 7, -1, -15, -1, -5, -18, -10, 6, 11, -11, -1, -10, -14, -13, -13, -4, 4, 6, 14, 13, 10, 10, 15, 17, 24, 24, 13, 12, 10, 1, 0, 2, -4, 0, -6, 2, 7, -22, -68, 2, 35, -40, 14, -24, -3, -10, -9, -20, -3, 28, 2, -9, -12, -28, -19, -4, -1, 15, 17, 17, 16, 12, 16, 22, 25, 28, 6, 17, 9, -1, -2, -3, 2, 12, -6, 6, -5, -35, -89, 32, 28, -39, 20, -36, 9, -20, -9, -34, 3, 34, 8, -16, -11, -37, -15, -3, 0, 26, 18, 13, 15, 13, 25, 27, 29, 20, 3, 21, 2, -2, 0, -8, 11, 16, -1, 8, -21, -76, -81, 87, -25, 4, -4, -23, 6, -26, -20, -35, 23, 28, 0, -18, -16, -43, 2, -9, 17, 25, 15, 9, 18, 17, 37, 28, 35, 3, 14, 12, -5, -1, -1, -5, 27, 0, 16, -11, -49, -128, 36, 40, -36, 35, -41, 21, -27, -14, -45, 4, 24, 20, -23, -6, -41, -9, -1, 6, 23, 19, 5, 15, 14, 33, 35, 40, 16, 5, 16, -3, -5, 4, -12, 24, 10, 18, 1, -38, -128, -21, 72, -50, 42, -38, 19, -16, -16, -43, -10, 21, 24, -22, -11, -30, -15, 6, 4, 22, 18, 6, 11, 13, 27, 39, 42, 22, 4, -3, -2, -2, -5, -3, -5, -3, -2, -6, -5, -5, -6, -5, -3, -5, -3, -5, -4, -6, -3, -1, -2, -1, 0, -2, 1, 2, 1, 4, 4, 5, 5, 5, 8, 10, 11, 9, 10, 11, 8, 5, 10, 7, 5, 5, 0, -3, 1, 0, -5, -2, -8, -9, -7, -7, -5, -9, -11, -9, -8, -8, -7, -9, -7, -6, -7, -5, -6, -5, -3, -3, -3, -4, -4, -2, 0, 1, 2, 5, 9, 12, 16, 19, 22, 22, 24, 22, 22, 19, 13, 11, 7, 7, 4, -2, -7, -9, -9, -8, -10, -14, -14, -15, -15, -13, -14, -17, -18, -14, -12, -12, -8, -9, -7, -6, -6, -6, -8, -9, -9, -11, -13, -11, -6, -1, 3, 9, 20, 27, 33, 37, 46, 46, 42, 37, 28, 21, 14, 11, 10, 14, 20, -2, -40, -47, -22, -5, -4, -1, 4, -15, -53, -56, -7, -33, -14, -2, -19, -7, -8, -15, -6, -9, -8, -3, -9, -15, -18, -26, -19, -6, -5, -6, 0, 12, 22, 29, 30, 28, 32, 29, 21, 15, 13, 5, 5, 3, 19, 30, 3, -68, -26, 2, -17, 17, -12, 15, -1, -12, -48, -43, -19, -1, 3, 6, -8, -4, -10, -10, -4, 0, -6, -1, -7, -9, -17, -12, -6, -9, -14, -5, 14, 33, 33, 41, 32, 41, 35, 20, 10, 8, 4, 10, -2, 36, 40, 3, -110, -8, -7, -6, 16, -18, 27, -2, -4, -56, -57, -33, 16, -2, 12, -11, -5, -17, -9, -5, 10, -6, 0, -12, -11, -20, -10, -8, -12, -17, -3, 17, 38, 34, 45, 36, 51, 37, 18, 4, -3, 3, 8, 8, 54, 48, -34, -128, 28, -33, 28, -13, 1, 21, 3, -20, -59, -65, -10, 17, -1, 7, -17, -10, -19, -8, 5, 11, -4, -2, -16, -17, -20, -9, -11, -18, -11, 3, 31, 36, 41, 41, 44, 53, 30, 10, 1, -13, 12, -5, 42, 63, 43, -127, -55, 19, -27, 28, -1, 0, 3, 5, 8, 12, 14, 15, 15, 14, 12, 8, 5, 1, -3, -9, -14, -17, -19, -18, -16, -12, -8, -5, -4, -2, -1, -1, -2, -3, -4, -3, -2, -1, -1, 0, 0, 0, 2, 8, 12, 16, 19, 23, 26, 34, 40, 39, 28, 11, -8, -26, -36, -40, -39, -35, -27, -19, -10, -5, -6, -10, -12, -15, -14, -12, -9, -5, -3, -1, 1, 6, 8, 7, 7, 7, 8, 13, 20, 28, 35, 43, 48, 55, 57, 51, 32, 3, -29, -56, -68, -67, -60, -46, -31, -17, -7, -4, -7, -11, -15, -16, -15, -10, -5, -1, 1, 3, 5, 7, 9, 11, 12, 12, 10, 13, 19, 26, 36, 43, 51, 58, 65, 61, 40, 6, -30, -60, -75, -73, -64, -49, -32, -16, -5, -1, -4, -11, -18, -23, -23, -19, -12, -5, 2, 8, 12, 13, 11, 9, 8, 8, 10, 15, 21, 27, 32, 37, 42, 49, 55, 63, 55, 32, -3, -39, -66, -79, -73, -56, -39, -24, -12, -7, -7, -12, -19, -24, -24, -21, -14, -6, 3, 8, 11, 12, 11, 10, 10, 10, 11, 14, 17, 21, 27, 33, 41, 49, 56, 63, 66, 49, 15, -27, -61, -82, -85, -73, -52, -33, -18, -9, -5, -7, -12, -18, -21, -20, -15, -9, -1, 4, 8, 12, 15, 15, 14, 11, 8, 7, 10, 15, 22, 32, 45, 59, 72, 86, 95, 75, 22, -40, -93, -119, -120, -97, -64, -32, -9, 5, 9, 5, -3, -14, -21, -23, -20, -13, -5, 4, 12, 17, 18, 15, 10, 7, 4, 3, 6, 9, 15, 21, 30, 40, 56, 77, 99, 99, 54, -19, -86, -123, -127, -103, -66, -27, 1, 16, 18, 11, -1, -12, -21, -23, -21, -16, -8, 1, 9, 16, 19, 16, 11, 8, 5, 5, 7, 9, 14, 19, 27, 35, 49, 68, 90, 101, 73, 6, -66, -114, -128, -113, -78, -39, -6, 13, 19, 11, -1, 0, 10, 30, 35, 40, 39, 37, 28, 18, 6, -9, -20, -30, -35, -33, -30, -28, -23, -24, -23, -19, -20, -15, -11, -8, -3, 0, 1, 0, -2, -4, -1, 0, 10, 15, 21, 27, 25, 25, 22, 13, 10, -5, -9, -15, -19, -17, -17, -12, -7, 0, 4, 10, 8, 5, -5, -13, -23, -31, -30, -24, -13, 11, 36, 62, 81, 83, 78, 54, 35, 19, -11, -29, -49, -57, -47, -35, -20, -19, -26, -27, -33, -30, -26, -22, -11, -8, 3, 11, 6, 0, -16, -23, -23, -11, 9, 23, 35, 45, 51, 46, 49, 26, 12, -13, -26, -37, -45, -31, -35, -17, -4, 8, 23, 24, 23, 9, -10, -22, -37, -40, -38, -33, -12, 22, 67, 100, 119, 111, 79, 50, 10, -12, -32, -52, -69, -62, -38, -14, -9, -21, -42, -60, -50, -39, -19, -4, -1, 3, 15, 19, 2, -16, -43, -57, -48, -21, 19, 38, 63, 66, 69, 74, 59, 39, 4, -33, -52, -67, -58, -39, -25, 2, 10, 32, 35, 36, 18, -7, -25, -37, -31, -28, -23, -10, 11, 53, 101, 121, 123, 92, 48, 11, -24, -42, -60, -66, -67, -48, -20, 2, -16, -41, -67, -87, -62, -44, -10, 8, 19, 30, 34, 35, 4, -36, -66, -78, -75, -27, 22, 49, 83, 91, 97, 90, 69, 39, -18, -61, -104, -98, -75, -32, 19, 47, 68, 70, 56, 16, -33, -77, -89, -76, -47, 7, 35, 64, 100, 123, 125, 107, 60, 5, -39, -76, -94, -101, -93, -69, -36, -3, 17, 10, -15, -56, -80, -86, -69, -40, -7, 25, 49, 66, 72, 54, 19, -19, -55, -77, -67, -40, 4, 45, 76, 96, 100, 92, 67, 32, -11, -56, -88, -91, -73, -33, 9, 41, 61, 65, 52, 17, -28, -67, -80, -68, -36, 6, 47, 82, 114, 126, 114, 74, 18, -32, -73, -93, -101, -93, -70, -36, -3, 17, 10, -15, 0, -1, -2, -2, 0, 2, 3, 6, 7, 6, 6, 3, 2, -1, -4, -8, -12, -14, -13, -13, -11, -5, -1, 5, 10, 14, 17, 19, 18, 15, 12, 7, 3, 1, -2, -4, -4, -7, -11, -13, -16, -16, -12, -9, -6, -3, -1, -1, -1, -4, -8, -11, -15, -16, -15, -10, -2, 7, 18, 25, 28, 28, 24, 16, 10, 4, -2, -5, -5, -4, -4, -1, 0, 0, 1, 1, 0, -1, -3, -6, -11, -11, -14, -16, -17, -19, -19, -16, -10, -2, 8, 19, 27, 33, 35, 32, 26, 21, 14, 7, 0, -6, -11, -18, -25, -31, -32, -27, -19, -9, 1, 10, 15, 14, 10, 0, -13, -28, -38, -42, -40, -26, -4, 17, 40, 58, 66, 62, 51, 35, 17, 3, -8, -16, -18, -18, -15, -13, -15, -17, -17, -15, -13, -11, -12, -3, -2, 1, -3, -15, -28, -36, -42, -40, -28, -11, 14, 45, 63, 70, 69, 56, 44, 36, 21, 3, -12, -18, -26, -37, -47, -58, -55, -41, -20, 4, 22, 34, 43, 37, 22, -7, -43, -71, -88, -86, -64, -31, 7, 56, 99, 115, 106, 85, 48, 17, 1, -14, -28, -33, -20, -11, -12, -18, -37, -44, -41, -29, -23, -7, 15, 31, 40, 33, 8, -27, -56, -73, -74, -63, -33, 4, 50, 93, 101, 91, 79, 56, 43, 24, 5, -17, -32, -31, -43, -56, -63, -72, -57, -32, 3, 26, 46, 62, 63, 45, 9, -39, -85, -112, -106, -84, -49, 6, 60, 104, 127, 115, 83, 46, 16, -1, -16, -21, -26, -16, -2, -8, -25, -47, -67, -62, -49, -26, 2, 34, 60, 74, 65, 33, -21, -71, -98, -92, -77, -36, 21, 69, 106, 112, 88, 58, 29, 9, -8, -18, -24, -17, -4, -10, -26, -47, -67, -62, -49, -26, 2, 34, 60, 74, 65, 33, 17, 16, -38, 9, 40, -58, 27, 43, -80, 52, -2, -54, 64, -27, -17, 32, 4, -49, 53, -22, -47, 90, -73, 17, 42, -45, 8, 23, -41, -1, 58, -74, 40, 25, -66, 56, -19, -45, 58, -9, -39, 45, 3, -48, 55, -41, -27, 78, -66, 13, 40, -38, 0, 29, -51, 12, 57, -79, 38, 31, -64, 40, -4, -47, 63, -16, -40, 55, -16, -32, 45, -31, -29, 76, -64, 0, 58, -49, 4, 31, -52, 31, 5, -35, 45, -21, 4, -5, 3, -17, -7, 55, -72, 43, 35, -88, 80, -57, 3, 45, -62, 53, -14, -2, -17, 46, -77, 42, 23, -61, 75, -54, 39, -40, 31, -42, 25, 11, -48, 93, -97, 62, -27, -13, 7, 0, 30, -59, 82, -74, 28, 10, -53, 65, -47, 46, -41, 40, -48, 7, 45, -95, 127, -99, 43, -9, -25, 40, -58, 84, -84, 78, -66, 11, 50, -96, 111, -85, 51, -26, -14, 36, -60, 91, -84, 58, -26, -22, 56, -87, 98, -71, 47, -25, -11, 44, -84, 103, -92, 69, -32, -3, 25, -59, 87, -90, 70, -45, 17, 16, -57, 81, -73, 50, -33, 14, 0, -35, 75, -84, 69, -42, 8, 11, -46, 74, -69, 57, -47, 36, -26, -20, 69, -89, 83, -58, 37, -24, -7, 41, -58, 54, -53, 53, -42, 14, 28, -54, 52, -55, 46, -41, 22, 30, -57, 58, -64, 56, -54, 26, 31, -55, 63, -73, 66, -68, 49, -3, -38, 61, -71, 75, -87, 69, -15, -27, 37, -55, 74, -84, 73, -34, -5, 26, -59, 74, -85, 84, -33, -12, 30, -57, 65, -85, 86, -40, 9, 15, -50, 69, -94, 93, -53, 15, 11, -38, 58, -86, 96, -64, 11, 21, -30, 17, -3, -3, 0, 0, -3, -4, -4, -3, -4, -4, -5, -6, -6, -8, -5, -6, -3, 0, 2, 4, 7, 8, 12, 12, 14, 13, 13, 12, 8, 7, 2, 2, -4, -6, -10, -11, -12, -12, -14, -10, -9, -3, -3, 2, 3, 3, 2, 1, 1, -3, -3, -4, -3, -3, -3, -4, 0, -3, -3, -3, 0, -3, 0, -3, 0, 1, 0, 0, 0, 0, 0, -3, 1, -3, 1, -3, 2, 1, 0, 0, -3, -4, -5, -9, -10, -15, -16, -17, -17, -14, -10, -3, 4, 9, 14, 19, 24, 25, 26, 28, 30, 34, 42, 31, 9, -31, -39, -23, -15, -17, -23, -30, -23, -12, -10, 4, 9, 19, 13, 14, 6, 0, -9, -11, -12, -9, -8, 0, 0, 2, 1, 1, -3, -3, -5, -3, -5, -3, -4, 0, -3, -4, -4, -3, -5, -3, -5, -3, 0, 3, 2, 7, 7, 7, 3, 0, -14, -17, -26, -26, -28, -21, -17, -11, -10, 2, 6, 19, 18, 32, 32, 60, 69, 98, 60, 7, -58, -8, -8, -14, -39, -30, -14, -47, -21, -45, -3, 7, 20, 14, 31, 12, 10, -15, -5, -23, -14, -15, -4, -8, 2, 1, 7, -3, 2, -8, -4, -6, -6, -3, 0, -6, -6, -8, -10, -11, -12, -9, -9, -4, -3, 0, 8, 10, 12, 15, 13, 4, -10, -15, -30, -32, -30, -23, -22, -19, -14, -4, 3, 10, 14, 26, 40, 70, 102, 127, 62, -17, -39, 9, -25, -9, -87, -12, -16, 0, -30, -27, -19, -9, 6, 18, 21, 19, 6, 0, -9, -17, -14, -16, -8, -6, 0, 4, 4, -5, -4, -11, -3, -6, 2, 2, 0, -6, 0, -2, -4, -8, -14, -21, -25, -28, -32, -36, -40, -44, -48, -51, -55, -59, -63, -67, -71, -74, -78, -82, -86, -90, -94, -98, -101, -84, -60, -38, -15, 8, 28, 27, 23, 19, 16, 11, 21, 46, 68, 93, 109, 106, 102, 98, 95, 91, 87, 83, 79, 75, 71, 67, 64, 60, 56, 52, 49, 45, 41, 37, 33, 30, 26, 22, 18, 15, 11, 7, 3, -1, -5, -9, -13, -17, -20, -24, -28, -32, -35, -39, -43, -47, -51, -54, -58, -62, -66, -69, -73, -77, -81, -85, -89, -93, -97, -100, -105, -95, -70, -48, -23, -7, -10, -14, -17, -22, -18, 4, 26, 50, 72, 96, 107, 103, 100, 96, 92, 88, 84, 80, 76, 72, 68, 64, 61, 57, 53, 49, 46, 42, 38, 34, 30, 26, 23, 19, 15, 11, 8, 4, 0, -4, -8, -11, -15, -19, -23, -27, -30, -35, -38, -43, -46, -51, -54, -58, -61, -66, -56, -31, -9, 16, 33, 30, 26, 22, 18, 15, 11, 7, 3, -1, -5, -9, -13, -16, -20, -24, -28, -32, -36, -40, -43, -48, -51, -55, -59, -63, -50, -26, -4, 20, 42, 64, 67, 62, 59, 55, 51, 47, 43, 39, 35, 31, 27, 23, 20, 16, 12, 8, 4, 0, -4, -7, -11, -15, -19, -22, -27, -17, 8, 30, 55, 72, 69, 65, 61, 57, 54, 50, 46, 42, 38, 34, 30, 26, 22, 18, 15, 11, 7, 3, 0, -4, -8, -12, -15, -19, -23, -27, -31, -35, -38, -42, -46, -50, -54, -57, -61, -65, -69, -73, -77, -81, -85, -89, -92, -96, -100, -100, -79, -64, -47, -31, -15, 0, 0, -4, -3, -6, -8, 6, 10, -8, -13, 22, 55, 15, -58, -102, -88, -25, 51, 77, 79, 82, 19, -45, -107, -128, -88, 19, 81, 86, 71, 35, -16, -50, -73, -55, -27, -14, 7, 77, 89, 31, -22, -27, -61, -86, -34, 40, 55, 67, 80, 57, -1, -48, -60, -41, -46, -31, 28, 62, 47, 43, 33, -5, -34, -45, -52, -33, 26, 66, 70, 41, 17, -34, -79, -93, -41, -6, 22, 53, 93, 62, 17, -20, -66, -118, -88, -4, 45, 60, 69, 67, 2, -72, -109, -95, -78, -7, 67, 101, 78, 69, 19, -56, -110, -89, -64, -19, 45, 100, 86, 36, -11, -65, -107, -108, -41, 24, 69, 93, 111, 56, -15, -70, -81, -88, -38, 30, 88, 90, 83, 43, -24, -81, -82, -57, -24, 38, 100, 115, 70, 26, -25, -75, -108, -66, -20, 29, 71, 105, 67, 7, -46, -67, -83, -60, 0, 58, 82, 81, 57, -9, -72, -99, -78, -60, -8, 54, 95, 69, 44, 0, -51, -92, -69, -26, 18, 53, 81, 63, 6, -44, -74, -88, -79, -19, 40, 75, 75, 72, 18, -42, -80, -74, -69, -25, 32, 76, 66, 39, 5, -41, -82, -76, -34, 3, 42, 79, 88, 38, -12, -49, -74, -92, -48, 8, 51, 70, 83, 50, -7, -58, -68, -65, -43, 13, 70, 82, 62, 34, -17, -72, -94, -65, -28, 17, 69, 101, 71, 25, -21, -60, -88, -66, -13, 37, 62, 82, 68, 11, -47, -73, -79, -66, -15, 49, 82, 76, 57, 11, -51, -88, -78, -48, -9, 49, 0, 0, 0, 0, 0, 0, -3, -5, -5, -7, -6, -2, 5, 16, 24, 21, 17, 12, 3, -10, -31, -44, -47, -42, -28, -2, 26, 29, 36, 35, 1, -26, -39, -52, -53, -38, -10, -32, -41, -7, 2, 22, 65, 89, 74, 15, -16, -24, 12, 62, 39, 6, -12, -3, 47, 48, 21, 109, 127, 119, 53, -9, 19, 9, -50, -55, -43, -71, -46, -5, -2, -20, -12, -9, 12, -27, -66, -50, -8, -19, -58, -22, -8, -19, -34, -42, 10, 32, -4, 4, 46, 96, 34, -51, -10, -8, -93, -70, -58, -46, -16, -32, -30, 6, 7, -41, -29, 3, 25, 73, 67, 45, 37, 30, 83, 0, -31, -4, -50, -28, -41, -75, -110, -53, -13, -3, 22, 14, 14, 13, 7, 9, 38, 47, 39, 17, -8, 90, 75, -5, -29, -46, -54, -102, -66, -35, -27, -29, -21, 32, 5, 1, 1, -2, 16, 16, 19, 30, 50, 89, 41, 6, 40, -10, -15, -41, -46, -43, -77, -100, -100, -48, -37, -26, -4, -9, 0, 13, 36, 70, 75, 59, 34, 12, -13, -27, 37, 71, 48, 53, 37, 7, 8, 34, 48, 40, 31, 25, 2, -20, -15, -5, 12, -11, -49, -20, 15, -13, -42, -29, 16, -6, -58, -28, 17, 12, -20, -11, 16, -3, -37, -14, 3, -32, -10, 40, 54, 53, 27, -3, -5, -34, -47, -49, -90, -68, -36, -32, -31, -16, 26, 3, 0, -2, -2, 15, 16, 19, 30, 51, 88, 40, 6, 39, -10, 3, -2, 11, -7, 23, 19, 74, 39, 32, -13, -21, -7, -39, -44, -128, -58, -21, 52, -86, -74, -94, 75, 61, 72, -38, 13, 59, 116, 71, -9, -33, -12, 68, -2, -35, -128, -42, -43, 39, -78, -57, -81, 56, 59, 63, -13, 7, 69, 98, 87, -13, -9, -24, 70, -11, -23, -128, -42, -48, 28, -68, -61, -69, 34, 64, 46, 8, -5, 79, 82, 100, -17, 5, -29, 69, -13, -21, -122, -49, -43, 11, -55, -72, -54, 13, 73, 30, 23, -16, 87, 72, 107, -17, 10, -26, 64, -6, -26, -109, -61, -31, -6, -40, -86, -41, -4, 80, 17, 31, -22, 88, 70, 106, -10, 6, -16, 53, 7, -37, -93, -76, -17, -21, -28, -99, -33, -15, 83, 12, 31, -21, 83, 76, 98, 2, -4, -1, 41, 24, -49, -77, -89, -6, -31, -20, -106, -32, -19, 79, 14, 23, -15, 71, 87, 87, 17, -16, 13, 30, 39, -57, -67, -97, -1, -34, -19, -106, -38, -16, 69, 23, 11, -5, 56, 100, 75, 32, -28, 25, 22, 50, -59, -62, -98, -2, -30, -24, -100, -52, -9, 55, 36, -4, 5, 41, 112, 67, 43, -34, 30, 21, 55, -53, -65, -93, -11, -18, -34, -88, -69, 0, 41, 48, -17, 12, 29, 118, 65, 49, -34, 28, 27, 53, -42, -72, -83, -23, -6, -44, -77, -85, 5, -69, 1, -12, -29, -28, -13, 1, 9, -4, -27, -18, -5, 11, 65, 87, 54, 59, 66, 30, 12, 8, -6, -7, 4, -7, -39, -59, -63, -48, -23, -13, -6, 22, 61, 68, 15, -59, -87, -41, 3, 5, -10, -17, -17, -20, -23, -20, -28, -17, -3, -10, -29, 23, 11, 25, 52, 56, 62, 80, 54, 22, -15, -31, -38, -5, 11, -9, -7, -36, -44, -6, 52, 127, 26, -68, -125, -105, 22, 15, -27, -27, 13, 25, 69, 28, -42, -77, -57, -70, 15, 44, 14, 26, 57, 69, 43, 33, 41, 33, 32, 25, -50, -98, -100, -38, 24, 7, -35, -38, -2, 76, 64, 15, -79, -93, -50, -12, 27, 45, 32, -4, 23, 6, -36, -47, -33, -52, -15, 37, 78, 49, 40, 17, 14, 14, 70, 81, 60, -3, -4, -12, -42, -50, -28, -20, 5, 9, 27, 46, -13, -69, -99, -88, -47, 5, -4, -10, 17, 39, -12, -8, -21, -16, 22, 9, -9, 1, 15, 15, 33, 29, 17, 11, 38, 72, 29, -8, -36, -27, -42, 17, -40, 25, 25, 8, -3, 14, 15, 2, 43, 33, -2, -19, -24, -8, 2, -69, -114, -94, -77, -87, 22, 27, 19, 24, 57, 121, 94, 40, -27, -29, 4, 28, -12, 5, -21, -28, -18, 0, -9, 1, 36, 22, 7, 6, 12, 7, 8, 55, 6, -2, -7, -13, -12, -12, -8, -5, -5, -1, -4, -4, -3, -1, 5, 11, 15, 18, 16, 11, 5, -5, -12, -16, -17, -14, -10, -7, -3, -2, -3, -3, -5, -3, 2, 9, 18, 22, 23, 18, 11, -2, -14, -20, -22, -18, -12, -8, -5, -3, -5, -6, -6, -5, 1, 11, 22, 30, 31, 24, 15, -1, -12, -20, -23, -19, -13, -8, -3, -3, -2, -6, -8, -9, -5, 6, 21, 32, 35, 29, 19, 1, -15, -27, -29, -25, -15, -9, -4, -1, -2, -7, -14, -15, -10, 4, 24, 42, 48, 43, 26, 4, -20, -36, -38, -30, -17, -7, -3, 0, -1, -4, -16, -24, -19, -3, 26, 49, 61, 60, 40, 9, -23, -45, -52, -39, -22, -5, -2, 1, 3, -2, -18, -32, -30, -10, 22, 55, 77, 78, 52, 15, -22, -51, -66, -52, -29, -5, 0, 2, 9, 6, -15, -37, -42, -22, 10, 55, 89, 99, 71, 22, -20, -58, -79, -68, -35, -8, 6, 1, 12, 13, -9, -37, -50, -35, 0, 46, 93, 116, 90, 33, -15, -60, -89, -84, -44, -9, 10, 3, 13, 19, -3, -35, -53, -43, -12, 34, 91, 127, 109, 46, -9, -57, -95, -96, -57, -13, 11, 7, 10, 25, 2, -2, -35, 0, 2, 7, 12, -7, -79, -68, 2, -6, -5, 19, 40, 33, 55, 56, 17, 32, 32, 2, -20, 5, 51, 27, -21, -13, -11, -17, -20, -6, -63, -125, -116, -86, -59, -34, 11, 23, 20, 39, 66, 50, 47, 54, 46, 11, -4, 44, 67, 30, 11, 16, 6, -2, 7, -4, -77, -114, -107, -70, -50, -20, 29, 26, 12, 48, 69, 44, 47, 49, 28, -8, 9, 53, 49, 15, 9, 8, -3, -11, 7, -33, -107, -123, -101, -62, -49, -5, 25, 6, 13, 55, 49, 32, 40, 39, 7, -17, 18, 49, 32, 7, 8, 1, -12, -3, 7, -62, -113, -109, -74, -50, -31, 23, 32, 13, 40, 69, 48, 46, 54, 42, 2, 1, 42, 52, 25, 10, 11, 0, -11, 10, -10, -90, -115, -101, -64, -52, -15, 29, 16, 10, 51, 59, 41, 46, 49, 25, -9, 15, 48, 42, 15, 10, 7, -9, -7, 16, -43, -107, -113, -89, -60, -47, 4, 27, 4, 19, 58, 47, 38, 46, 43, 6, -9, 28, 47, 29, 10, 11, 2, -14, 5, 5, -73, -111, -106, -73, -56, -29, 24, 22, 6, 40, 61, 43, 43, 52, 37, -3, 6, 41, 47, 23, 12, 11, 0, -14, 1, 3, 5, 5, 6, 8, 6, 4, 0, -4, -5, -6, -9, -9, -11, -11, -12, -13, -13, -13, -12, -11, -9, -5, -2, -1, 1, 4, 6, 9, 11, 12, 12, 11, 8, 5, 2, -2, -2, -2, -2, 0, -1, -1, -2, -5, -5, -5, -1, 4, 10, 17, 20, 22, 19, 15, 7, -1, -9, -15, -19, -21, -21, -18, -16, -13, -11, -12, -15, -19, -23, -24, -20, -13, -3, 9, 20, 34, 44, 50, 46, 35, 21, 7, -4, -14, -20, -19, -13, -8, 2, 0, -5, -15, -28, -32, -29, -14, 0, 11, 27, 42, 58, 59, 45, 22, 4, -15, -26, -37, -43, -42, -37, -17, 1, 18, 23, 8, -5, -29, -47, -47, -43, -25, -5, 20, 52, 80, 92, 76, 43, 9, -20, -35, -38, -46, -41, -29, -12, 19, 35, 22, 4, -34, -53, -58, -40, -26, -16, 14, 47, 88, 108, 90, 50, 16, -9, -36, -51, -64, -64, -52, -33, -1, 32, 40, 24, 3, -29, -62, -58, -65, -52, -18, 23, 68, 114, 127, 95, 41, 1, -36, -54, -56, -68, -55, -35, -17, 19, 42, 29, 13, -16, -46, -60, -54, -56, -47, -11, 29, 72, 116, 127, 94, 41, -3, 0, 16, 39, 54, 46, 18, 7, -15, -36, -9, -6, -16, -5, -15, -30, -23, -35, -20, 22, 3, -19, -20, -13, -9, 19, 23, 10, 12, 35, 66, 54, 4, -43, -58, -15, -10, 16, 55, 18, -39, -38, -30, 2, 9, 27, 51, -32, -60, -72, -4, 32, 71, 19, -8, 56, -2, -42, 10, 21, -6, 31, -9, -70, 8, -6, -19, -93, -20, -5, -31, 10, 5, 56, 24, -45, 11, 66, 48, 61, 89, 49, -57, -6, -20, -69, -104, -83, -50, 32, 10, -16, -87, -78, 30, 127, 63, -17, -91, -2, -12, 45, 83, 30, 56, 54, 42, 7, 79, -26, -52, -64, -97, 12, -3, -107, -99, -39, 34, 86, 19, -25, 25, 90, -8, -38, 65, 36, 10, 30, 36, 19, -6, 38, -47, -101, -52, -45, 30, -9, -106, 18, -10, -37, 16, 100, -94, -111, -25, -35, -12, -8, -9, 51, 24, -5, -70, -52, -52, -19, -11, 48, 93, 61, 17, 113, 125, 73, -16, -30, -57, -78, -116, -55, -38, -10, -5, -4, 38, 31, -3, -46, -46, -50, -20, -10, 52, 84, 48, 14, 115, 119, 64, -16, -1, 4, 0, -9, -11, -1, 6, 2, -2, 4, -6, -10, -2, 11, 14, 3, -10, -15, -1, 17, 4, 6, 4, -12, -18, 6, 10, 4, 6, -8, -36, 2, 3, 3, 5, 15, -20, -17, 9, 8, 11, 17, -8, -26, 18, 2, 5, 5, 13, -24, -8, -2, 2, 5, 7, -21, -18, 13, 5, -5, 17, 7, -14, -13, -12, 0, 14, 3, -12, -26, 13, 3, 10, 18, 12, -15, -14, -1, 3, 19, 0, -10, -29, 11, 4, 17, 15, 12, -24, -20, 6, 9, 22, -3, -13, -15, 9, 1, 7, 6, 18, -19, -26, -18, 2, 22, 0, -25, -20, 15, 8, -4, 8, 31, -12, -20, -15, 9, 33, 9, -29, -2, 27, 7, -11, 8, 20, -20, -41, -10, 15, 35, 15, -21, 11, 49, 6, -6, 4, 3, -48, -76, -35, 14, 37, 22, -24, 29, 68, 20, 3, 7, -5, -68, -90, -59, 19, 36, 28, -13, 59, 93, 30, 2, 18, -25, -88, -105, -81, 13, 26, 30, -4, 88, 109, 33, 0, 22, -30, -88, -112, -76, 17, 31, 18, 5, 94, 114, 30, -4, 0, 4, -30, -1, 0, -2, -2, -2, -1, 4, 11, 18, 30, 7, -64, -60, -30, -7, 0, 2, 22, 67, 117, 23, -128, -74, -30, -5, -2, 1, 19, 62, 116, 38, -123, -82, -31, -8, -1, -1, 16, 57, 114, 52, -117, -88, -33, -10, -2, -3, 14, 52, 112, 64, -108, -96, -35, -13, -2, -4, 12, 49, 108, 77, -99, -102, -37, -15, -2, -5, 10, 43, 104, 86, -87, -109, -40, -18, -2, -6, 8, 40, 100, 95, -73, -115, -42, -21, -2, -8, 7, 35, 95, 102, -59, -120, -45, -24, -2, -8, 5, 32, 90, 109, -44, -124, -49, -26, -3, -9, 3, 28, 85, 114, -29, -126, -53, -28, -4, -9, 2, 25, 81, 116, -13, -127, -58, -29, -6, -9, 0, 22, 75, 119, 3, -126, -63, -31, -7, -9, -2, 19, 70, 120, 18, -124, -69, -32, -9, -9, -3, 16, 65, 119, 34, -63, -107, -58, -23, -11, -7, 7, 46, 107, 89, -52, -109, -62, -25, -12, -8, 5, 42, 104, 97, -41, -87, -70, -36, -18, -11, 0, 30, 85, 100, -2, -87, -5, 11, -23, -10, -3, -20, -3, -17, -24, -33, -26, -1, -13, -12, -6, -9, 6, 25, 19, -7, -1, 22, -6, -20, 13, 6, -12, 26, 48, 0, -7, 34, 23, 4, 32, 23, -41, -11, 49, -3, -30, 35, 45, -14, -2, 62, 18, -44, -2, 26, -4, -28, -6, 16, 2, -9, -9, 2, 18, 24, 9, -25, -57, -36, 30, 38, -21, -63, -37, 9, 37, 40, 0, -56, -56, 3, 39, 20, -23, -52, -58, -46, 8, 67, 56, -18, -61, -18, 36, 70, 95, 73, -35, -128, -127, -73, -17, 32, 48, 29, 28, 60, 106, 113, 91, 36, -26, -67, -90, -91, -71, -44, -25, -13, 9, 36, 51, 69, 70, 32, -40, -92, -99, -70, -25, 12, 29, 21, 3, -9, 10, 21, 12, -11, -22, -27, -44, -23, 10, 30, 25, 24, 39, 18, 3, 8, 19, -1, -19, -8, 6, 5, 13, 50, 43, 37, 36, 40, 37, 4, 12, -10, -33, -31, -25, -1, 1, 7, 14, 10, -4, -11, -10, -6, -19, -42, -28, -54, -51, -18, -5, 3, 2, -10, -10, 10, 28, 27, 16, 5, -5, -24, -26, -7, -14, -25, -16, 53, 33, -49, -30, 53, 50, -24, -34, 40, 82, -118, -23, 120, -56, -70, -72, 106, -10, -48, 3, 87, 28, -126, -16, 81, 4, -84, -51, 38, 62, -32, 36, 84, -12, -41, 72, -42, -60, -64, 4, 77, -24, -79, -9, 122, 6, -94, 52, 43, 35, 13, -62, -7, -89, 24, -30, 16, 29, 56, -59, 83, 42, 31, 36, -76, -2, -128, -2, 45, 27, -104, -31, 66, 21, 19, 36, 121, 11, -76, -26, -93, 34, 24, -34, -65, -53, 53, 17, 73, 46, 75, -9, -64, -21, -103, 41, 51, -41, -83, -43, 108, 6, -11, 28, 127, 2, -84, -38, -72, 39, 17, -23, -15, -67, 37, 6, 29, 64, 79, 17, -39, -39, -120, 55, 23, -17, -62, -51, 81, 23, 20, 24, 99, -38, -99, 4, 17, -66, -41, -33, 63, 62, 16, 53, 91, 56, -65, -36, -99, -38, 14, -47, -29, -38, 35, 83, 9, 48, 83, 62, -45, -31, -103, -49, 14, 2, 6, -33, 33, -4, -1, 34, -93, 60, -49, 68, -21, 41, -38, -38, 27, -87, 127, -34, 38, -3, -34, -2, -85, 79, -24, 4, 75, -23, 11, -70, 1, -6, -6, 63, -48, 76, -71, 2, -7, -15, 46, -32, 48, -25, -5, 10, -31, 18, -23, 5, 6, 17, 11, 3, 24, -46, -21, -1, -5, 31, 1, 36, -23, -11, -4, -29, 14, -5, 29, 9, -2, -2, -20, -2, -15, 13, 7, 4, 15, -11, 4, -13, -1, 1, -13, 15, -6, 9, 9, -2, -4, -11, -2, -11, 7, 12, 9, 5, -6, -6, -16, -2, 3, 6, 13, 1, 7, -14, -3, -11, -1, 8, 0, 18, -3, -3, -6, -13, 0, 4, 2, 9, 2, 2, -6, -4, -1, -8, 2, 4, 2, 7, -4, 2, 1, -7, -3, -2, 0, 2, 8, -2, 2, -1, -7, -3, -1, 3, 4, 3, 3, -3, -4, -4, 0, 2, 1, 5, -1, -2, 1, -4, -1, 1, 0, 2, -5, -8, -3, -3, -9, -2, -2, 5, 10, 16, 11, 5, -3, -5, -1, -4, -6, -7, -15, -18, -27, -31, -21, -11, 22, 56, 90, 66, -17, -25, -25, 0, -12, -15, -25, -32, -39, -37, -26, 6, 33, 65, 69, 44, -1, -13, -12, 1, 0, -9, -14, -22, -40, -44, -42, -23, 8, 39, 60, 84, 57, -16, -25, -19, 2, -8, -11, -18, -32, -51, -45, -32, -6, 28, 54, 85, 96, -5, -29, -23, -7, -10, -17, -16, -28, -53, -44, -40, -7, 22, 52, 82, 112, 17, -37, -25, -20, -11, -18, -10, -23, -33, -51, -40, -23, 10, 45, 65, 96, 64, -21, -35, -34, -19, -20, -13, -5, -14, -35, -41, -39, -17, 9, 45, 58, 82, 98, -2, -57, -47, -23, -12, -11, -2, -18, -28, -39, -36, -24, -1, 26, 57, 84, 121, 23, -65, -50, -40, -12, -11, -4, -14, -20, -34, -32, -27, -5, 19, 56, 80, 127, 15, -66, -50, -2, -5, -5, 2, 10, 8, -7, -16, -9, 6, 17, 8, -19, -20, 14, 38, 34, 20, -5, 1, 50, 37, -50, -54, -66, -32, 32, -3, -13, -18, -17, 46, 89, -17, -62, 45, 127, 57, -57, -67, -109, -11, 88, -31, -90, -88, -27, 63, 97, -27, -105, -44, 65, 110, 60, -12, -30, -27, 17, 49, -2, -39, -6, 30, -16, -36, -43, 32, 67, -54, -58, -38, -21, 47, 95, 76, -33, -78, -62, 10, 107, 24, -106, -107, 12, 52, 27, 78, 8, -75, 25, 6, -26, 59, 32, -17, -7, -19, 11, 32, -51, -52, 41, -9, -13, 94, 2, -65, 5, -46, -86, 34, 62, 85, 29, -93, -89, -29, 44, 35, -31, -33, -19, 56, 127, 7, -9, -62, -52, 23, 46, 44, -56, -16, -55, -46, 22, 83, -13, -42, -7, 13, 81, 49, 3, -9, -30, -47, -30, 3, 23, 6, -7, -20, -44, 10, 96, -13, 0, 16, 31, 47, 61, 75, 87, 98, 107, 115, 121, 125, 127, 127, 125, 121, 116, 108, 99, 88, 75, 62, 47, 32, 16, 0, -16, -31, -47, -61, -75, -87, -98, -108, -116, -122, -126, -128, -128, -126, -123, -117, -109, -100, -89, -77, -64, -49, -34, -18, -2, 14, 29, 45, 59, 73, 86, 97, 106, 114, 121, 125, 127, 127, 126, 122, 116, 109, 100, 89, 77, 63, 49, 34, 18, 2, -14, -30, -45, -60, -73, -86, -97, -107, -115, -121, -126, -128, -128, -127, -123, -118, -110, -101, -91, -79, -65, -51, -36, -20, -4, 12, 28, 43, 58, 72, 84, 96, 106, 114, 120, 124, 127, 127, 126, 122, 117, 109, 100, 90, 78, 64, 50, 35, 19, 3, -13, -29, -44, -59, -73, -85, -97, -107, -115, -121, -125, -128, -128, -127, -123, -118, -110, -101, -91, -79, -65, -51, -36, -20, -4, 12, 2, 5, 5, 0, -16, -9, -2, -19, 4, 18, 6, 10, -16, -21, 22, -2, 3, -7, 21, 43, -57, -37, 46, -39, -31, 78, 23, -23, -10, -10, -7, -52, 44, 50, -44, 9, -9, -46, 47, 12, -75, 40, 45, 32, -10, -25, -15, -45, 24, 44, -40, -10, 18, -48, -29, 63, 44, -30, -1, 83, -45, -94, 96, 0, -103, 21, 29, -42, 21, 80, -25, -15, 26, 39, -79, -18, 73, -111, -45, 61, 29, 55, -22, -77, 40, 9, -72, 78, 35, -1, -1, -69, 12, -50, -42, 123, 45, -7, -39, -86, 3, 51, 30, 28, -4, -33, -41, -66, 54, -8, -30, 127, -7, -30, -32, -39, 48, -65, 20, 121, -33, -14, -53, -32, 46, -24, 36, 98, -49, -39, -61, 1, 49, -54, 65, 59, -83, -11, -49, 32, 39, -72, 113, 59, -83, -11, -49, 32, 39, -72, 113, 59, -2, -4, -4, -7, -8, -8, -7, -4, -3, -2, 1, 4, 6, 6, 6, 4, 2, 0, -2, -3, -4, -7, -7, -5, -3, 0, 4, 9, 11, 11, 9, 7, 4, 1, -3, -7, -9, -12, -13, -16, -19, -19, -13, -2, 9, 17, 19, 20, 18, 13, 8, 3, 0, -2, -3, -8, -14, -21, -25, -21, -9, 4, 15, 23, 28, 25, 20, 9, -7, -21, -14, 3, 3, -18, -38, -49, -32, -7, 8, 14, 26, 37, 42, 37, 26, 7, -18, -27, -5, 8, -7, -24, -34, -40, -32, -19, 1, 17, 42, 56, 58, 40, -19, -81, 1, 67, 0, -60, -49, -27, -24, 0, -18, -24, -8, 37, 67, 70, 59, 34, -42, -81, 7, 51, -12, -54, -37, -14, -25, -14, -16, -24, 4, 55, 75, 102, 52, -102, -104, 90, 30, -48, -76, 1, -14, 0, -2, -2, -3, -5, -7, -8, -8, -7, -6, -4, -2, 0, 1, 3, 4, 6, 6, 6, 6, 5, 4, 3, 1, 0, 0, -3, -4, -7, -10, -11, -11, -8, -6, 1, 5, 6, 8, 11, 11, 8, 5, 5, 2, 1, 0, 0, -2, 1, -4, -16, -36, -27, -5, 6, -3, -6, 0, -6, 2, 27, 24, 19, 16, 9, 3, 0, -4, 2, 1, 9, 19, -14, -79, -32, 22, -4, -22, -14, 25, 8, -11, 13, 28, 16, 19, 16, 1, -2, -4, -3, -6, 28, 38, -59, -111, 25, 16, -16, -40, 16, 24, -20, 4, 24, 29, 17, 27, 13, 1, -10, -6, -10, -8, 43, 61, -68, -128, 28, 12, -15, -39, 12, 21, -28, 12, 37, 25, 12, 27, 11, 0, -16, -2, -12, -11, 52, 67, -68, 35, 54, 47, 4, -60, -92, -68, -27, 0, -2, -18, -20, -6, 2, -8, -15, -11, -3, 3, -7, -11, -6, -2, 7, 15, 18, 19, 22, 27, 40, 40, 29, 20, 24, 28, 34, 30, 25, 32, 20, 14, 9, 16, 19, 17, 6, -1, 3, -6, -14, -23, -18, -7, 1, -18, -18, -24, -25, -24, -35, -35, -35, -21, -12, -14, -21, -17, -29, -24, -31, -34, -9, -11, -9, -3, -7, -7, 6, -17, -22, 7, 16, 14, -4, -11, 10, 33, 24, 21, 27, 3, -19, -25, -18, 17, 50, 48, 49, 61, 31, -48, -103, -73, 9, 56, 70, 82, 109, 127, 71, -46, -127, -96, -30, -4, 9, 47, 103, 117, 60, -39, -110, -119, -94, -64, -40, -4, 35, -8, -14, -9, -5, -4, -3, 6, 18, 19, 6, -14, -20, -12, -3, -3, -6, 2, 21, 28, 13, -16, -26, -14, -6, -6, -7, 1, 27, 36, 18, -15, -27, -15, -3, -2, -10, -6, 25, 41, 22, -17, -34, -18, -4, -3, -16, -12, 29, 56, 31, -24, -44, -20, -4, -1, -19, -22, 31, 73, 47, -27, -62, -25, -2, 4, -21, -36, 26, 91, 61, -27, -79, -33, 0, 10, -18, -49, 14, 106, 82, -24, -94, -40, 8, 14, -12, -59, 1, 112, 105, -19, -106, -51, 12, 16, -4, -63, -13, 110, 127, -12, -114, -51, 0, -1, -4, -8, -11, -8, -2, 0, 7, 14, 21, 46, 92, 120, 76, -36, -121, -119, -73, -31, -7, 3, 2, -4, -6, 2, 22, 60, 106, 116, 43, -72, -128, -105, -57, -21, -3, 3, -1, -6, -5, 7, 33, 76, 117, 102, 5, -100, -127, -89, -43, -13, 0, 2, -3, -7, -2, 14, 46, 92, 122, 79, -34, -118, -118, -72, -31, -8, 1, 0, -5, -7, 2, 23, 61, 107, 118, 46, -69, -126, -104, -56, -21, -4, 1, 0, -4, -5, 0, 16, 48, 87, 103, 60, -25, -87, -94, -58, -20, -4, -11, 12, 24, 31, -36, 29, -9, 2, -38, -5, -5, -10, -33, -10, -24, -20, -39, -36, -18, -38, -58, -5, -22, -15, -15, 90, -42, -3, -8, 25, 6, 28, 25, 17, 25, -16, 28, 80, 22, 12, -6, 35, 22, 8, -7, 28, 29, -19, 7, 8, -1, -29, -23, 10, -23, -13, -26, -17, -20, -33, -41, -19, -28, -64, -13, -21, -13, -29, 54, 25, -20, -36, 42, -4, 13, 52, -8, 47, -14, 9, 42, 88, -12, 20, -5, 43, 22, -11, 127, 127, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, -128, 1, 4, 7, 10, 12, 16, 19, 22, 25, 28, 31, 35, 38, 42, 45, 49, 51, 56, 58, 63, 65, 70, 73, 78, 80, 85, 87, 93, 95, 100, 102, 108, 109, 117, 114, 127, 85, -63, -60, -64, -60, -62, -59, -61, -59, -61, -58, -60, -58, -59, -58, -58, -57, -57, -55, -55, -54, -54, -52, -51, -50, -49, -47, -46, -44, -43, -41, -40, -37, -36, -34, -32, -30, -28, -25, -24, -21, -19, -16, -14, -11, -9, -6, 1, 1, 4, 7, 10, 12, 16, 19, 22, 25, 28, 31, 35, 38, 42, 45, 49, 51, 56, 58, 63, 65, 70, 73, 78, 80, 85, 87, 93, 95, 100, 102, 108, 109, 117, 114, 127, 85, -63, -60, -64, -60, -62, -59, -61, -59, -61, -58, -60, -58, -59, -58, -58, -57, -57, -55, -55, -54, -54, -52, -51, -50, -49, -47, -46, -44, -43, -41, -40, -37, -36, -34, -32, -30, -28, -25, -24, -21, -19, -16, -14, -11, -9, -6, 1, -3, -19, -24, -14, -8, -19, -12, -10, -5, -12, -50, -19, 23, 35, 4, -20, -7, -26, 9, 40, 69, 16, -88, -69, -38, -32, -27, 41, 65, 55, 18, -40, -38, -20, 66, 127, 121, 57, -23, -55, -48, 13, 53, 31, -20, -38, -13, 10, 8, 0, 12, 17, 13, 2, -1, -3, -3, 6, 13, 7, -17, -24, -12, 4, 3, -10, -20, -32, -22, -18, -12, -3, 6, 16, 22, 29, 30, 27, 20, 11, 0, -7, -12, -11, -5, 0, -3, -14, -20, -16, -9, -9, -17, -25, -29, -31, -33, -35, -33, -29, -25, -22, -20, -17, -14, -13, -12, -11, -9, -10, -13, -15, -11, -5, 3, 9, 10, 9, 9, 12, 18, 30, 50, 80, 119, 127, 102, 82, 77, 60, 37, 5, -34, -70, -84, -83, -74, -60, -46, -29, -12, -2, 6, -23, 28, -20, 50, 50, -14, 14, -28, -2, 28, 52, -25, -13, -52, 43, -41, -9, -26, 36, -25, -20, -17, 3, -11, 38, 30, -61, 12, -6, 5, 45, 41, -4, 4, -20, -12, 45, 33, -11, -29, -44, 27, -17, -36, -1, 17, -11, -31, -12, 4, -10, 37, 20, -39, -23, 0, -104, -55, -11, 24, 33, 30, 7, -15, -31, -30, -25, -23, -20, -9, 10, 31, 59, 91, 111, 115, 92, 51, 7, -33, -64, -81, -81, -71, -51, -22, 16, 52, 74, 82, 81, 68, 38, 0, -40, -81, -112, -124, -102, -57, -11, 0, 7, -23, -58, -85, -100, -104, -100, -92, -81, -69, -57, -45, -33, -22, -11, -1, 8, 18, 27, 37, 49, 62, 79, 99, 118, 124, 111, 84, 53, 26, 5, -8, -14, -15, -12, -6, 2, 12, 21, 28, 26, 9, -22, -58, -20, 7, 10, 21, -14, 9, 22, 57, 62, 127, 56, 28, 26, -28, 10, -81, -31, -81, -35, -19, -55, -27, -4, -4, 23, 49, 88, 85, 22, 1, 0, -3, 18, -22, -12, -39, -14, -47, -67, -53, -53, -33, -20, 8, -22, 25, 30, 6, -19, -62, -19, 10, 83, 57, -67, -88, -52, 63, 127, 42, -63, -121, -70, 82, 111, 46, -43, -114, -35, 45, 73, 39, -19, -54, -41, 9, 49, 24, -16, -14, -9, -6, 10, 8, -22, 25, 30, 6, -19, -62, -19, 10, 83, 57, -67, -88, -52, 63, 127, 42, -63, -121, -70, 82, 111, 46, -43, -114, -35, 45, 73, 39, -19, -54, -41, 9, 49, 24, -16, -14, -9, -6, 10, 8, -22, 25, 30, 6, -19, -62, -19, 10, 83, 57, -67, -88, -52, 63, 127, 42, -63, -121, -70, 82, 111, 46, -43, -114, -35, 45, 73, 39, -19, -54, -41, 9, 49, 24, -16, -14, -9, -6, 10, -18, -15, 80, 127, 20, 18, 72, 60, -36, 22, 33, -73, -105, -27, 29, 25, 8, 43, 23, -22, -35, -14, -8, -34, -25, -5, -18, -46, -13, -28, -3, -19, -10, -28, -10, 17, -18, 96, 127, 123, 127, 126, 126, 95, 61, 22, -17, -56, -95, -118, -123, -128, -128, -128, -128, -128, -128, -128, -128, -124, -93, -55, -17, 25, 62, 100, 107, 119, 119, 127, 41, -4, -4, -10, -27, -62, -102, -128, -117, -85, -76, -49, -25, -7, 15, 24, 14, 0, -9, -12, -3, 33, 81, 105, 111, 101, 80, 62, 45, 30, 16, 8, 1, -4, 126, 86, -44, -68, -88, -63, 4, 84, 127, 14, -29, -51, -127, -47, 58, 87, 82, 24, -17, -112, -113, 18, 46, 72, 102, 19, -72, -118, -51, 9, 27, 126, 19, -53, -114, -108, 15, 122, 111, 21, -71, -70, 5, 59, 83, 23, -72, -84, -49, 12, 37, 38, -28, -65, -26, 7, -2, 11, 5, 23, 68, 19, 27, -54, 15, -24, -31, 46, 71, 81, -24, -33, -87, -41, -71, -61, -70, -36, -44, -3, 12, -25, -20, 20, 68, 85, 127, 15, 50, -5, 27, 51, 82, 106, 127, 118, 101, 92, 74, 52, 39, 37, 14, -41, -105, -108, -94, -119, -124, -93, -57, -40, -37, -45, -51, -41, -5, 51, 127, 127, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 }; const EAS_U32 eas_sampleLengths[] = { 16820, 16708, 16592, 11754, 10954, 10295, 9922, 7489, 5779, 5462, 4452, 3779, 3115, 3093, 3057, 3024, 2818, 2776, 2171, 2168, 2052, 1902, 1835, 1614, 1603, 1528, 1517, 1480, 1455, 1424, 1387, 1302, 1262, 1254, 1230, 1227, 1185, 1181, 1178, 1168, 1132, 1120, 1034, 1033, 1018, 994, 964, 926, 907, 886, 881, 866, 830, 817, 816, 813, 749, 748, 739, 720, 652, 610, 610, 583, 564, 561, 556, 549, 542, 535, 530, 530, 516, 508, 492, 478, 461, 448, 437, 431, 423, 418, 403, 402, 400, 394, 387, 387, 367, 357, 347, 347, 341, 336, 334, 329, 325, 312, 294, 284, 277, 265, 255, 233, 230, 213, 207, 205, 194, 193, 184, 181, 181, 167, 164, 158, 152, 152, 145, 139, 128, 103, 100, 88, 87, 84, 84, 72, 71, 55, 46, 45, 43, 40, 40, 40, 37, 35, 32, 32, 30, 29, 27, 23, 22, 21, 21, 21, 21, 20 }; const EAS_U32 eas_sampleOffsets[] = { 0x00000000, 0x000041b4, 0x000082f8, 0x0000c3c8, 0x0000f1b2, 0x00011c7c, 0x000144b3, 0x00016b75, 0x000188b6, 0x00019f49, 0x0001b49f, 0x0001c603, 0x0001d4c6, 0x0001e0f1, 0x0001ed06, 0x0001f8f7, 0x000204c7, 0x00020fc9, 0x00021aa1, 0x0002231c, 0x00022b94, 0x00023398, 0x00023b06, 0x00024231, 0x0002487f, 0x00024ec2, 0x000254ba, 0x00025aa7, 0x0002606f, 0x0002661e, 0x00026bae, 0x00027119, 0x0002762f, 0x00027b1d, 0x00028003, 0x000284d1, 0x0002899c, 0x00028e3d, 0x000292da, 0x00029774, 0x00029c04, 0x0002a070, 0x0002a4d0, 0x0002a8da, 0x0002ace3, 0x0002b0dd, 0x0002b4bf, 0x0002b883, 0x0002bc21, 0x0002bfac, 0x0002c322, 0x0002c693, 0x0002c9f5, 0x0002cd33, 0x0002d064, 0x0002d394, 0x0002d6c1, 0x0002d9ae, 0x0002dc9a, 0x0002df7d, 0x0002e24d, 0x0002e4d9, 0x0002e73b, 0x0002e99d, 0x0002ebe4, 0x0002ee18, 0x0002f049, 0x0002f275, 0x0002f49a, 0x0002f6b8, 0x0002f8cf, 0x0002fae1, 0x0002fcf3, 0x0002fef7, 0x000300f3, 0x000302df, 0x000304bd, 0x0003068a, 0x0003084a, 0x000309ff, 0x00030bae, 0x00030d55, 0x00030ef7, 0x0003108a, 0x0003121c, 0x000313ac, 0x00031536, 0x000316b9, 0x0003183c, 0x000319ab, 0x00031b10, 0x00031c6b, 0x00031dc6, 0x00031f1b, 0x0003206b, 0x000321b9, 0x00032302, 0x00032447, 0x0003257f, 0x000326a5, 0x000327c1, 0x000328d6, 0x000329df, 0x00032ade, 0x00032bc7, 0x00032cad, 0x00032d82, 0x00032e51, 0x00032f1e, 0x00032fe0, 0x000330a1, 0x00033159, 0x0003320e, 0x000332c3, 0x0003336a, 0x0003340e, 0x000334ac, 0x00033544, 0x000335dc, 0x0003366d, 0x000336f8, 0x00033778, 0x000337df, 0x00033843, 0x0003389b, 0x000338f2, 0x00033946, 0x0003399a, 0x000339e2, 0x00033a29, 0x00033a60, 0x00033a8e, 0x00033abb, 0x00033ae6, 0x00033b0e, 0x00033b36, 0x00033b5e, 0x00033b83, 0x00033ba6, 0x00033bc6, 0x00033be6, 0x00033c04, 0x00033c21, 0x00033c3c, 0x00033c53, 0x00033c69, 0x00033c7e, 0x00033c93, 0x00033ca8, 0x00033cbd }; /*---------------------------------------------------------------------------- * S_EAS *---------------------------------------------------------------------------- */ const S_EAS easSoundLib = { 0x01534145, 0x00105622, eas_banks, eas_programs, eas_regions, eas_articulations, eas_sampleLengths, eas_sampleOffsets, eas_samples, 0, 1, 1, 377, 185, 150, 0 }; /* end S_EAS */ /*---------------------------------------------------------------------------- * Statistics * * Number of banks: 1 * Number of programs: 1 * Number of regions: 377 * Number of articulations: 185 * Number of samples: 150 * Size of sample pool: 212050 *---------------------------------------------------------------------------- */ /* end wt_200k_G.c */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_vm_protos.h0000644000000000000000000000013213532747316027145 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.797999979 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_vm_protos.h0000644000175000001440000011265013532747316027743 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_vm_protos.h * * Contents and purpose: * Declarations, interfaces, and prototypes for voice manager. * * Copyright Sonic Network Inc. 2004 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 736 $ * $Date: 2007-06-22 13:51:24 -0700 (Fri, 22 Jun 2007) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_VM_PROTOS_H #define _EAS_VM_PROTOS_H // includes #include "eas_data.h" #include "eas_sndlib.h" /*---------------------------------------------------------------------------- * VMInitialize() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * *---------------------------------------------------------------------------- */ EAS_RESULT VMInitialize (S_EAS_DATA *pEASData); /*---------------------------------------------------------------------------- * VMInitMIDI() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * *---------------------------------------------------------------------------- */ EAS_RESULT VMInitMIDI (S_EAS_DATA *pEASData, S_SYNTH **ppSynth); /*---------------------------------------------------------------------------- * VMInitializeAllChannels() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * *---------------------------------------------------------------------------- */ void VMInitializeAllChannels (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); /*---------------------------------------------------------------------------- * VMResetControllers() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * *---------------------------------------------------------------------------- */ void VMResetControllers (S_SYNTH *pSynth); /*---------------------------------------------------------------------------- * VMInitMIPTable() *---------------------------------------------------------------------------- * Purpose: * Initialize the SP-MIDI MIP table * * Inputs: * pEASData - pointer to synthesizer instance data * mute - EAS_FALSE to unmute channels, EAS_TRUE to mute * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ void VMInitMIPTable (S_SYNTH *pSynth); /*---------------------------------------------------------------------------- * VMSetMIPEntry() *---------------------------------------------------------------------------- * Purpose: * Sets the priority and MIP level for a MIDI channel * * Inputs: * pEASData - pointer to synthesizer instance data * channel - MIDI channel number * priority - priority (0-15 with 0 = highest priority) * mip - maximum instantaneous polyphony * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ void VMSetMIPEntry (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 priority, EAS_U8 mip); /*---------------------------------------------------------------------------- * VMUpdateMIPTable() *---------------------------------------------------------------------------- * Purpose: * This routine is called when the polyphony count in the synthesizer changes * * Inputs: * pEASData - pointer to synthesizer instance data * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ void VMUpdateMIPTable (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); /*---------------------------------------------------------------------------- * VMInitializeAllVoices() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * *---------------------------------------------------------------------------- */ void VMInitializeAllVoices (S_VOICE_MGR *pVoiceMgr, EAS_INT vSynthNum); /*---------------------------------------------------------------------------- * VMStartNote() *---------------------------------------------------------------------------- * Purpose: * Update the synth's state to play the requested note on the requested * channel if possible. * * Inputs: * nChannel - the MIDI channel * nKeyNumber - the MIDI key number for this note * nNoteVelocity - the key velocity for this note * psEASData - pointer to overall EAS data structure * * Outputs: * *---------------------------------------------------------------------------- */ void VMStartNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity); /*---------------------------------------------------------------------------- * VMCheckKeyGroup() *---------------------------------------------------------------------------- * Purpose: * If the note that we've been asked to start is in the same key group as * any currently playing notes, then we must shut down the currently playing * note in the same key group and then start the newly requested note. * * Inputs: * nChannel - synth channel that wants to start a new note * nKeyNumber - new note's midi note number * nRegionIndex - calling routine finds this index and gives to us * nNoteVelocity - new note's velocity * psEASData - pointer to overall EAS data structure * * Outputs: * pbVoiceStealingRequired - flag: this routine sets true if we needed to * steal a voice * * Side Effects: * gsSynthObject.m_sVoice[free voice num].m_nKeyNumber may be assigned * gsSynthObject.m_sVoice[free voice num].m_nVelocity may be assigned *---------------------------------------------------------------------------- */ void VMCheckKeyGroup (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U16 keyGroup, EAS_U8 channel); /*---------------------------------------------------------------------------- * VMCheckPolyphonyLimiting() *---------------------------------------------------------------------------- * Purpose: * We only play at most 2 of the same note on a MIDI channel. * E.g., if we are asked to start note 36, and there are already two voices * that are playing note 36, then we must steal the voice playing * the oldest note 36 and use that stolen voice to play the new note 36. * * Inputs: * nChannel - synth channel that wants to start a new note * nKeyNumber - new note's midi note number * nNoteVelocity - new note's velocity * psEASData - pointer to overall EAS data structure * * Outputs: * pbVoiceStealingRequired - flag: this routine sets true if we needed to * steal a voice * * * Side Effects: * psSynthObject->m_sVoice[free voice num].m_nKeyNumber may be assigned * psSynthObject->m_sVoice[free voice num].m_nVelocity may be assigned *---------------------------------------------------------------------------- */ EAS_BOOL VMCheckPolyphonyLimiting (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity, EAS_U16 regionIndex, EAS_I32 lowVoice, EAS_I32 highVoice); /*---------------------------------------------------------------------------- * VMStopNote() *---------------------------------------------------------------------------- * Purpose: * Update the synth's state to end the requested note on the requested * channel. * * Inputs: * nChannel - the MIDI channel * nKeyNumber - the key number of the note to stop * nNoteVelocity - the note-off velocity * psEASData - pointer to overall EAS data structure * * Outputs: * Side Effects: * gsSynthObject.m_sVoice[free voice num].m_nSynthChannel may be assigned * gsSynthObject.m_sVoice[free voice num].m_nKeyNumber is assigned * gsSynthObject.m_sVoice[free voice num].m_nVelocity is assigned *---------------------------------------------------------------------------- */ void VMStopNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 key, EAS_U8 velocity); /*---------------------------------------------------------------------------- * VMFindAvailableVoice() *---------------------------------------------------------------------------- * Purpose: * Find an available voice and return the voice number if available. * * Inputs: * pnVoiceNumber - really an output, see below * psEASData - pointer to overall EAS data structure * * Outputs: * pnVoiceNumber - returns the voice number of available voice if found * success - if there is an available voice * failure - otherwise *---------------------------------------------------------------------------- */ EAS_RESULT VMFindAvailableVoice (S_VOICE_MGR *pVoiceMgr, EAS_INT *pVoiceNumber, EAS_I32 lowVoice, EAS_I32 highVoice); /*---------------------------------------------------------------------------- * VMStealVoice() *---------------------------------------------------------------------------- * Purpose: * Steal a voice and return the voice number * * Stealing algorithm: steal the best choice with minimal work, taking into * account SP-Midi channel priorities and polyphony allocation. * * In one pass through all the voices, figure out which voice to steal * taking into account a number of different factors: * Priority of the voice's MIDI channel * Number of voices over the polyphony allocation for voice's MIDI channel * Amplitude of the voice * Note age * Key velocity (for voices that haven't been started yet) * If any matching notes are found * * Inputs: * nChannel - the channel that this voice wants to be started on * nKeyNumber - the key number for this new voice * psEASData - pointer to overall EAS data structure * * Outputs: * pnVoiceNumber - voice stolen * EAS_RESULT EAS_SUCCESS - always successful *---------------------------------------------------------------------------- */ EAS_RESULT VMStealVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_INT *pVoiceNumber, EAS_U8 channel, EAS_U8 note, EAS_I32 lowVoice, EAS_I32 highVoice); /*---------------------------------------------------------------------------- * VMAddSamples() *---------------------------------------------------------------------------- * Purpose: * Synthesize the requested number of samples. * * Inputs: * nNumSamplesToAdd - number of samples to write to buffer * psEASData - pointer to overall EAS data structure * * Outputs: * number of samples actually written to buffer * * Side Effects: * - samples are added to the presently free buffer * *---------------------------------------------------------------------------- */ EAS_I32 VMAddSamples (S_VOICE_MGR *pVoiceMgr, EAS_I32 *pMixBuffer, EAS_I32 numSamplesToAdd); /*---------------------------------------------------------------------------- * VMProgramChange() *---------------------------------------------------------------------------- * Purpose: * Change the instrument (program) for the given channel. * * Depending on the program number, and the bank selected for this channel, the * program may be in ROM, RAM (from SMAF or CMX related RAM wavetable), or * Alternate wavetable (from mobile DLS or other DLS file) * * This function figures out what wavetable should be used, and sets it up as the * wavetable to use for this channel. Also the channel may switch from a melodic * channel to a rhythm channel, or vice versa. * * Inputs: * * Outputs: * Side Effects: * gsSynthObject.m_sChannel[nChannel].m_nProgramNumber is likely changed * gsSynthObject.m_sChannel[nChannel].m_psEAS may be changed * gsSynthObject.m_sChannel[nChannel].m_bRhythmChannel may be changed * *---------------------------------------------------------------------------- */ void VMProgramChange (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 program); /*---------------------------------------------------------------------------- * VMChannelPressure() *---------------------------------------------------------------------------- * Purpose: * Change the channel pressure for the given channel * * Inputs: * nChannel - the MIDI channel * nVelocity - the channel pressure value * psEASData - pointer to overall EAS data structure * * Outputs: * Side Effects: * gsSynthObject.m_sChannel[nChannel].m_nChannelPressure is updated *---------------------------------------------------------------------------- */ void VMChannelPressure (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 value); /*---------------------------------------------------------------------------- * VMPitchBend() *---------------------------------------------------------------------------- * Purpose: * Change the pitch wheel value for the given channel. * This routine constructs the proper 14-bit argument when the calling routine * passes the pitch LSB and MSB. * * Note: some midi disassemblers display a bipolar pitch bend value. * We can display the bipolar value using * if m_nPitchBend >= 0x2000 * bipolar pitch bend = postive (m_nPitchBend - 0x2000) * else * bipolar pitch bend = negative (0x2000 - m_nPitchBend) * * Inputs: * nChannel - the MIDI channel * nPitchLSB - the LSB byte from the pitch bend message * nPitchMSB - the MSB byte from the message * psEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * gsSynthObject.m_sChannel[nChannel].m_nPitchBend is changed * *---------------------------------------------------------------------------- */ void VMPitchBend (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 pitchLSB, EAS_U8 pitchMSB); /*---------------------------------------------------------------------------- * VMControlChange() *---------------------------------------------------------------------------- * Purpose: * Change the controller (or mode) for the given channel. * * Inputs: * nChannel - the MIDI channel * nControllerNumber - the controller number * nControlValue - the controller number for this control change * nControlValue - the value for this control change * psEASData - pointer to overall EAS data structure * * Outputs: * Side Effects: * gsSynthObject.m_sChannel[nChannel] controller is changed * *---------------------------------------------------------------------------- */ void VMControlChange (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 controller, EAS_U8 value); /*---------------------------------------------------------------------------- * VMUpdateRPNStateMachine() *---------------------------------------------------------------------------- * Purpose: * Call this function when we want to parse a stream of RPN messages. * NOTE: The synth has only one set of global RPN data instead of RPN data * per channel. * So actually, we don't really need to look at the nChannel parameter, * but we pass it to facilitate future upgrades. Furthermore, we only * support RPN0 (pitch bend sensitivity), RPN1 (fine tuning) and * RPN2 (coarse tuning). Any other RPNs are rejected. * * Inputs: * nChannel - the MIDI channel * nControllerNumber - the RPN controller number * nControlValue - the value for this control change * psEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * gsSynthObject.m_RPN0 (or m_RPN1 or m_RPN2) may be updated if the * proper RPN message sequence is parsed. *---------------------------------------------------------------------------- */ EAS_RESULT VMUpdateRPNStateMachine (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 controller, EAS_U8 value); /*---------------------------------------------------------------------------- * VMUpdateStaticChannelParameters() *---------------------------------------------------------------------------- * Purpose: * Update all of the static channel parameters for channels that have had * a controller change values * Or if the synth has signalled that all channels must forcibly * be updated * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * none * * Side Effects: * - psSynthObject->m_sChannel[].m_nStaticGain and m_nStaticPitch * are updated for channels whose controller values have changed * or if the synth has signalled that all channels must forcibly * be updated *---------------------------------------------------------------------------- */ void VMUpdateStaticChannelParameters (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); /*---------------------------------------------------------------------------- * VMReleaseAllDeferredNoteOffs() *---------------------------------------------------------------------------- * Purpose: * Call this functin when the sustain flag is presently set but * we are now transitioning from damper pedal on to * damper pedal off. This means all notes in this channel * that received a note off while the damper pedal was on, and * had their note-off requests deferred, should now proceed to * the release state. * * Inputs: * nChannel - this channel has its sustain pedal transitioning from on to off * psEASData - pointer to overall EAS data structure * * Outputs: * Side Effects: * any voice with deferred note offs on this channel are updated such that * * *---------------------------------------------------------------------------- */ void VMReleaseAllDeferredNoteOffs (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); /*---------------------------------------------------------------------------- * VMCatchNotesForSustainPedal() *---------------------------------------------------------------------------- * Purpose: * Call this function when the sustain flag is presently clear and * the damper pedal is off and we are transitioning from damper pedal OFF to * damper pedal ON. Currently sounding notes should be left * unchanged. However, we should try to "catch" notes if possible. * If any notes have levels >= sustain level, catch them, * otherwise, let them continue to release. * * Inputs: * nChannel - this channel has its sustain pedal transitioning from on to off * psEASData - pointer to overall EAS data structure * * Outputs: * Side Effects: * any voice with deferred note offs on this channel are updated such that * psVoice->m_sEG1.m_eState = eEnvelopeStateSustainPedal *---------------------------------------------------------------------------- */ void VMCatchNotesForSustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); /*---------------------------------------------------------------------------- * VMUpdateAllNotesAge() *---------------------------------------------------------------------------- * Purpose: * Increment the note age for all voices older than the age of the voice * that is stopping, effectively making the voices "younger". * * Inputs: * nAge - age of voice that is going away * psEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * m_nAge for some voices is incremented *---------------------------------------------------------------------------- */ void VMUpdateAllNotesAge (S_VOICE_MGR *pVoiceMgr, EAS_U16 nAge); /*---------------------------------------------------------------------------- * VMFindRegionIndex() *---------------------------------------------------------------------------- * Purpose: * Find the region index for the given instrument using the midi key number * and the RPN2 (coarse tuning) value. By using RPN2 as part of the * region selection process, we reduce the amount a given sample has * to be transposed by selecting the closest recorded root instead. * * Inputs: * nChannel - current channel for this note * nKeyNumber - current midi note number * psEASData - pointer to overall EAS data structure * * Outputs: * pnRegionIndex - valid only if we returned success * success if we found the region index number, otherwise * failure * * Side Effects: *---------------------------------------------------------------------------- */ EAS_RESULT VMFindRegionIndex (S_VOICE_MGR *pVoiceMgr, EAS_U8 channel, EAS_U8 note, EAS_U16 *pRegionIndex); /*---------------------------------------------------------------------------- * VMIncRefCount() *---------------------------------------------------------------------------- * Increment reference count for virtual synth *---------------------------------------------------------------------------- */ void VMIncRefCount (S_SYNTH *pSynth); /*---------------------------------------------------------------------------- * VMReset() *---------------------------------------------------------------------------- * Purpose: * We call this routine to start the process of reseting the synth. * This routine sets a flag for the entire synth indicating that we want * to reset. * We also force all voices to mute quickly. * However, we do not actually perform any synthesis in this routine. That * is, we do not ramp the voices down from this routine, but instead, we * let the "regular" synth processing steps take care of adding the ramp * down samples to the output buffer. After we are sure that all voices * have completed ramping down, we continue the process of resetting the * synth (from another routine). * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * - set a flag (in gsSynthObject.m_nFlags) indicating synth reset requested. * - force all voices to update their envelope states to mute * *---------------------------------------------------------------------------- */ void VMReset (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_BOOL force); /*---------------------------------------------------------------------------- * VMMuteAllVoices() *---------------------------------------------------------------------------- * Purpose: * We call this in an emergency reset situation. * This forces all voices to mute quickly. * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * - forces all voices to update their envelope states to mute * *---------------------------------------------------------------------------- */ void VMMuteVoice (S_VOICE_MGR *pVoiceMgr, EAS_I32 voiceNum); void VMMuteAllVoices (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); /*---------------------------------------------------------------------------- * VMReleaseAllVoices() *---------------------------------------------------------------------------- * Purpose: * We call this after we've encountered the end of the Midi file. * This ensures all voice are either in release (because we received their * note off already) or forces them to mute quickly. * We use this as a safety to prevent bad midi files from playing forever. * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * - forces all voices to update their envelope states to release or mute * *---------------------------------------------------------------------------- */ void VMReleaseAllVoices (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); /*---------------------------------------------------------------------------- * VMAllNotesOff() *---------------------------------------------------------------------------- * Purpose: * Quickly mute all notes on the given channel. * * Inputs: * nChannel - quickly turn off all notes on this channel * psEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * - forces all voices on this channel to update their envelope states to mute * *---------------------------------------------------------------------------- */ void VMAllNotesOff (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); /*---------------------------------------------------------------------------- * VMDeferredStopNote() *---------------------------------------------------------------------------- * Purpose: * Stop the notes that had deferred note-off requests. * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * None. * * Side Effects: * voices that have had deferred note-off requests are now put into release * gsSynthObject.m_sVoice[i].m_nFlags has the VOICE_FLAG_DEFER_MIDI_NOTE_OFF * cleared *---------------------------------------------------------------------------- */ void VMDeferredStopNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth); /*---------------------------------------------------------------------------- * VMSetSynthPolyphony() *---------------------------------------------------------------------------- * Purpose: * Set the synth to a new polyphony value. Value must be >= 1 and * <= MAX_SYNTH_VOICES. This function will pin the polyphony at those limits * * Inputs: * pVoiceMgr pointer to synthesizer data * synth synthesizer number (0 = onboard, 1 = DSP) * polyphonyCount desired polyphony count * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT VMSetSynthPolyphony (S_VOICE_MGR *pVoiceMgr, EAS_I32 synth, EAS_I32 polyphonyCount); /*---------------------------------------------------------------------------- * VMGetSynthPolyphony() *---------------------------------------------------------------------------- * Purpose: * Set the synth to a new polyphony value. Value must be >= 1 and * <= MAX_SYNTH_VOICES. This function will pin the polyphony at those limits * * Inputs: * pVoiceMgr pointer to synthesizer data * synth synthesizer number (0 = onboard, 1 = DSP) * polyphonyCount desired polyphony count * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT VMGetSynthPolyphony (S_VOICE_MGR *pVoiceMgr, EAS_I32 synth, EAS_I32 *pPolyphonyCount); /*---------------------------------------------------------------------------- * VMSetPolyphony() *---------------------------------------------------------------------------- * Purpose: * Set the virtual synth polyphony. 0 = no limit (i.e. can use * all available voices). * * Inputs: * pVoiceMgr pointer to synthesizer data * polyphonyCount desired polyphony count * pSynth pointer to virtual synth * * Outputs: * Returns error code * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT VMSetPolyphony (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 polyphonyCount); /*---------------------------------------------------------------------------- * VMGetPolyphony() *---------------------------------------------------------------------------- * Purpose: * Returns the current polyphony setting * * Inputs: * pVoiceMgr pointer to synthesizer data * pSynth pointer to virtual synth * pPolyphonyCount pointer to variable to receive data * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT VMGetPolyphony (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 *pPolyphonyCount); /*---------------------------------------------------------------------------- * VMSetPriority() *---------------------------------------------------------------------------- * Purpose: * Set the virtual synth priority * * Inputs: * pVoiceMgr pointer to synthesizer data * priority new priority * pSynth pointer to virtual synth * * Outputs: * Returns error code * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT VMSetPriority (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 priority); /*---------------------------------------------------------------------------- * VMGetPriority() *---------------------------------------------------------------------------- * Purpose: * Get the virtual synth priority * * Inputs: * pVoiceMgr pointer to synthesizer data * pPriority pointer to variable to hold priority * pSynth pointer to virtual synth * * Outputs: * Returns error code * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT VMGetPriority (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 *pPriority); /*---------------------------------------------------------------------------- * VMSetVolume() *---------------------------------------------------------------------------- * Purpose: * Set the master volume for this sequence * * Inputs: * nSynthVolume - the desired master volume * psEASData - pointer to overall EAS data structure * * Outputs: * * * Side Effects: * overrides any previously set master volume from sysex * *---------------------------------------------------------------------------- */ void VMSetVolume (S_SYNTH *pSynth, EAS_U16 masterVolume); /*---------------------------------------------------------------------------- * VMSetPitchBendRange() *---------------------------------------------------------------------------- * Set the pitch bend range for the given channel. *---------------------------------------------------------------------------- */ void VMSetPitchBendRange (S_SYNTH *pSynth, EAS_INT channel, EAS_I16 pitchBendRange); /*---------------------------------------------------------------------------- * VMSetEASLib() *---------------------------------------------------------------------------- * Purpose: * Sets the pointer to the sound library * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * *---------------------------------------------------------------------------- */ EAS_RESULT VMSetGlobalEASLib (S_VOICE_MGR *pVoiceMgr, EAS_SNDLIB_HANDLE pEAS); EAS_RESULT VMSetEASLib (S_SYNTH *pSynth, EAS_SNDLIB_HANDLE pEAS); #ifdef DLS_SYNTHESIZER /*---------------------------------------------------------------------------- * VMSetDLSLib() *---------------------------------------------------------------------------- * Purpose: * Sets the pointer to the sound library * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * *---------------------------------------------------------------------------- */ EAS_RESULT VMSetGlobalDLSLib (EAS_DATA_HANDLE pEASData, EAS_DLSLIB_HANDLE pDLS); EAS_RESULT VMSetDLSLib (S_SYNTH *pSynth, EAS_DLSLIB_HANDLE pDLS); #endif /*---------------------------------------------------------------------------- * VMSetTranposition() *---------------------------------------------------------------------------- * Purpose: * Sets the global key transposition used by the synthesizer. * Transposes all melodic instruments up or down by the specified * amount. Range is limited to +/-12 semitones. * * Inputs: * psEASData - pointer to overall EAS data structure * transposition - transpose amount (+/-12) * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ void VMSetTranposition (S_SYNTH *pSynth, EAS_I32 transposition); /*---------------------------------------------------------------------------- * VMGetTranposition() *---------------------------------------------------------------------------- * Purpose: * Gets the global key transposition used by the synthesizer. * Transposes all melodic instruments up or down by the specified * amount. Range is limited to +/-12 semitones. * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ void VMGetTranposition (S_SYNTH *pSynth, EAS_I32 *pTransposition); /*---------------------------------------------------------------------------- * VMGetNoteCount() *---------------------------------------------------------------------------- * Returns the total note count *---------------------------------------------------------------------------- */ EAS_I32 VMGetNoteCount (S_SYNTH *pSynth); /*---------------------------------------------------------------------------- * VMRender() *---------------------------------------------------------------------------- * Purpose: * This routine renders a frame of audio * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * pVoicesRendered - number of voices rendered this frame * * Side Effects: * sets psMidiObject->m_nMaxWorkloadPerFrame * *---------------------------------------------------------------------------- */ EAS_RESULT VMRender (S_VOICE_MGR *pVoiceMgr, EAS_I32 numSamples, EAS_I32 *pMixBuffer, EAS_I32 *pVoicesRendered); /*---------------------------------------------------------------------------- * VMInitWorkload() *---------------------------------------------------------------------------- * Purpose: * Clears the workload counter * * Inputs: * pVoiceMgr - pointer to instance data * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ void VMInitWorkload (S_VOICE_MGR *pVoiceMgr); /*---------------------------------------------------------------------------- * VMSetWorkload() *---------------------------------------------------------------------------- * Purpose: * Sets the max workload for a single frame. * * Inputs: * pVoiceMgr - pointer to instance data * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ void VMSetWorkload (S_VOICE_MGR *pVoiceMgr, EAS_I32 maxWorkLoad); /*---------------------------------------------------------------------------- * VMCheckWorkload() *---------------------------------------------------------------------------- * Purpose: * Checks to see if work load has been exceeded on this frame. * * Inputs: * pVoiceMgr - pointer to instance data * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_BOOL VMCheckWorkload (S_VOICE_MGR *pVoiceMgr); /*---------------------------------------------------------------------------- * VMActiveVoices() *---------------------------------------------------------------------------- * Purpose: * Returns the number of active voices in the synthesizer. * * Inputs: * pEASData - pointer to instance data * * Outputs: * Returns the number of active voices * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_I32 VMActiveVoices (S_SYNTH *pSynth); /*---------------------------------------------------------------------------- * VMMIDIShutdown() *---------------------------------------------------------------------------- * Purpose: * Clean up any Synth related system issues. * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * None * * Side Effects: * *---------------------------------------------------------------------------- */ void VMMIDIShutdown (S_EAS_DATA *pEASData, S_SYNTH *pSynth); /*---------------------------------------------------------------------------- * VMShutdown() *---------------------------------------------------------------------------- * Purpose: * Clean up any Synth related system issues. * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * None * * Side Effects: * *---------------------------------------------------------------------------- */ void VMShutdown (S_EAS_DATA *pEASData); #ifdef EXTERNAL_AUDIO /*---------------------------------------------------------------------------- * EAS_RegExtAudioCallback() *---------------------------------------------------------------------------- * Register a callback for external audio processing *---------------------------------------------------------------------------- */ void VMRegExtAudioCallback (S_SYNTH *pSynth, EAS_VOID_PTR pInstData, EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, EAS_EXT_EVENT_FUNC cbEventFunc); /*---------------------------------------------------------------------------- * VMGetMIDIControllers() *---------------------------------------------------------------------------- * Returns the MIDI controller values on the specified channel *---------------------------------------------------------------------------- */ void VMGetMIDIControllers (S_SYNTH *pSynth, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl); #endif #ifdef _SPLIT_ARCHITECTURE /*---------------------------------------------------------------------------- * VMStartFrame() *---------------------------------------------------------------------------- * Purpose: * Starts an audio frame * * Inputs: * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_BOOL VMStartFrame (S_EAS_DATA *pEASData); /*---------------------------------------------------------------------------- * VMEndFrame() *---------------------------------------------------------------------------- * Purpose: * Stops an audio frame * * Inputs: * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_BOOL VMEndFrame (S_EAS_DATA *pEASData); #endif #endif /* #ifdef _EAS_VM_PROTOS_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_rtttldata.c0000644000000000000000000000013213532747316027113 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.797999979 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_rtttldata.c0000644000175000001440000000253113532747316027705 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_rtttldata.c * * Contents and purpose: * RTTTL File Parser data module for static memory models * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 547 $ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ *---------------------------------------------------------------------------- */ #include "eas_types.h" #include "eas_rtttldata.h" /*---------------------------------------------------------------------------- * * eas_RTTTLData * * Static memory allocation for RTTTL parser *---------------------------------------------------------------------------- */ S_RTTTL_DATA eas_RTTTLData; drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_wavefile.h0000644000000000000000000000013213532747316026717 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.797999979 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_wavefile.h0000644000175000001440000000353013532747316027511 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_wavefile.h * * Contents and purpose: * Static data block for wave file parser. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 439 $ * $Date: 2006-10-26 11:53:18 -0700 (Thu, 26 Oct 2006) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_WAVEFILE_H #define _EAS_WAVEFILE_H #include "eas_data.h" #include "eas_pcm.h" /*---------------------------------------------------------------------------- * * S_WAVE_STATE * * This structure contains the WAVE file parser state information *---------------------------------------------------------------------------- */ typedef struct s_wave_state_tag { EAS_FILE_HANDLE fileHandle; EAS_PCM_HANDLE streamHandle; S_METADATA_CB metadata; EAS_U32 time; EAS_I32 fileOffset; EAS_I32 audioOffset; EAS_I32 mediaLength; EAS_U32 audioSize; EAS_U32 flags; EAS_I16 fileType; #ifdef MMAPI_SUPPORT EAS_VOID_PTR fmtChunk; #endif EAS_I32 infoChunkPos; EAS_I32 infoChunkSize; } S_WAVE_STATE; #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_xmf.h0000644000000000000000000000013213532747316025707 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.797999979 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_xmf.h0000644000175000001440000000336113532747316026503 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_xmf.h * * Contents and purpose: * XMF Type 0 and 1 File Parser * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_XMF_H #define _EAS_XMF_H #ifndef MAX_XMF_STREAMS #define MAX_XMF_STREAMS 16 #endif /* offsets in to the XMF file */ #define XMF_OFS_HEADER_SIZE 4 #define XMF_OFS_FILE_TYPE 8 #define XMF_OFS_NUM_TRACKS 10 /* size of chunk info (chunk ID + chunk size) */ #define XMF_CHUNK_INFO_SIZE 8 /* 'MTrk' track chunk ID */ #define XMF_CHUNK_TYPE_TRACK 0x4d54726bL /* some useful meta-events */ #define XMF_META_END_OF_TRACK 0x2f #define XMF_META_TEMPO 0x51 /* default timebase (120BPM) */ #define XMF_DEFAULT_TIMEBASE 500000L /* value for pXMFStream->ticks to signify end of track */ #define XMF_END_OF_TRACK 0xffffffff #endif /* end _EAS_XMF_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_synthcfg.h0000644000000000000000000000013213532747316026742 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.801999983 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_synthcfg.h0000644000175000001440000000351513532747316027537 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_synthcfg.h * * Contents and purpose: * Defines for various synth configurations * * Copyright Sonic Network Inc. 2004, 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 664 $ * $Date: 2007-04-25 13:11:22 -0700 (Wed, 25 Apr 2007) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_SYNTHCFG_H #define _EAS_SYNTHCFG_H #if defined(EAS_WT_SYNTH) #define _WT_SYNTH /* FM on MCU */ #elif defined(EAS_FM_SYNTH) #define _FM_SYNTH /* wavetable drums and FM melodic on MCU */ #elif defined(EAS_HYBRID_SYNTH) #define _WT_SYNTH #define _FM_SYNTH #define _SECONDARY_SYNTH #define _HYBRID_SYNTH /* wavetable drums on MCU, wavetable melodic on DSP */ #elif defined(EAS_SPLIT_WT_SYNTH) #define _WT_SYNTH #define _SPLIT_ARCHITECTURE /* wavetable drums on MCU, FM melodic on DSP */ #elif defined(EAS_SPLIT_HYBRID_SYNTH) #define _WT_SYNTH #define _FM_SYNTH #define _SECONDARY_SYNTH #define _SPLIT_ARCHITECTURE #define _HYBRID_SYNTH /* FM synth on DSP */ #elif defined(EAS_SPLIT_FM_SYNTH) #define _FM_SYNTH #define _SPLIT_ARCHITECTURE #else #error "Unrecognized architecture option" #endif #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_mixbuf.c0000644000000000000000000000013213532747316026402 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.801999983 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_mixbuf.c0000644000175000001440000000224413532747316027175 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_mixbuf.c * * Contents and purpose: * Contains a data allocation for synthesizer * * Copyright Sonic Network Inc. 2004 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ // includes #include "eas_data.h" #include "eas_mixer.h" // globals EAS_I32 eas_MixBuffer[BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS]; drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_wtsynth.h0000644000000000000000000000013213532747316026635 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.801999983 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_wtsynth.h0000644000175000001440000000417113532747316027431 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_wtsynth.h * * Contents and purpose: * This file defines the interface for synthesizer engine * * Copyright Sonic Network Inc. 2004 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_WTSYNTH_H #define _EAS_WTSYNTH_H #include "eas_sndlib.h" #include "eas_wtengine.h" /* adjust the filter cutoff frequency to the sample rate */ #if defined (_SAMPLE_RATE_8000) #define FILTER_CUTOFF_FREQ_ADJUST 0 #elif defined (_SAMPLE_RATE_16000) #define FILTER_CUTOFF_FREQ_ADJUST 1200 #elif defined (_SAMPLE_RATE_20000) #define FILTER_CUTOFF_FREQ_ADJUST 1586 #elif defined (_SAMPLE_RATE_22050) #define FILTER_CUTOFF_FREQ_ADJUST 1756 #elif defined (_SAMPLE_RATE_24000) #define FILTER_CUTOFF_FREQ_ADJUST 1902 #elif defined (_SAMPLE_RATE_32000) #define FILTER_CUTOFF_FREQ_ADJUST 2400 #elif defined (_SAMPLE_RATE_44100) #define FILTER_CUTOFF_FREQ_ADJUST 2956 #elif defined (_SAMPLE_RATE_48000) #define FILTER_CUTOFF_FREQ_ADJUST 3102 #else #error "_SAMPLE_RATE_XXXXX must be defined to valid rate" #endif /* function prototypes */ void WT_UpdateLFO (S_LFO_CONTROL *pLFO, EAS_I16 phaseInc); #if defined(_FILTER_ENABLED) || defined(DLS_SYNTHESIZER) void WT_SetFilterCoeffs (S_WT_INT_FRAME *pIntFrame, EAS_I32 cutoff, EAS_I32 resonance); #endif #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_data.c0000644000000000000000000000013213532747316026021 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.801999983 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_data.c0000644000175000001440000000220013532747316026604 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_data.c * * Contents and purpose: * Contains a data allocation for synthesizer * * Copyright Sonic Network Inc. 2004 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 547 $ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ *---------------------------------------------------------------------------- */ // includes #include "eas_data.h" // globals S_EAS_DATA eas_Data; S_VOICE_MGR eas_Synth; S_SYNTH eas_MIDI; drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_rtttl.c0000644000000000000000000000013213532747316026261 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.801999983 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_rtttl.c0000644000175000001440000010262513532747316027060 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_rtttl.c * * Contents and purpose: * RTTTL parser * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 795 $ * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ *---------------------------------------------------------------------------- */ #include "eas_data.h" #include "eas_miditypes.h" #include "eas_parser.h" #include "eas_report.h" #include "eas_host.h" #include "eas_midi.h" #include "eas_config.h" #include "eas_vm_protos.h" #include "eas_rtttldata.h" #include "eas_ctype.h" /* increase gain for mono ringtones */ #define RTTTL_GAIN_OFFSET 8 /* maximum title length including colon separator */ #define RTTTL_MAX_TITLE_LEN 32 #define RTTTL_INFINITE_LOOP 15 /* length of 32nd note in 1/256ths of a msec for 63 BPM tempo */ #define DEFAULT_TICK_CONV 30476 #define TICK_CONVERT 1920000 /* default channel and program for RTTTL playback */ #define RTTTL_CHANNEL 0 #define RTTTL_PROGRAM 80 #define RTTTL_VELOCITY 127 /* note used for rest */ #define RTTTL_REST 1 /* multiplier for fixed point triplet conversion */ #define TRIPLET_MULTIPLIER 683 #define TRIPLET_SHIFT 10 /* local prototypes */ static EAS_RESULT RTTTL_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); static EAS_RESULT RTTTL_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT RTTTL_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); static EAS_RESULT RTTTL_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); static EAS_RESULT RTTTL_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); static EAS_RESULT RTTTL_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT RTTTL_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT RTTTL_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT RTTTL_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT RTTTL_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); static EAS_RESULT RTTTL_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); static EAS_RESULT RTTTL_GetStyle (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData); static EAS_RESULT RTTTL_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pDuration); static EAS_RESULT RTTTL_GetOctave (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_U8 *pOctave); static EAS_RESULT RTTTL_GetTempo (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData); static EAS_RESULT RTTTL_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I32 *pValue); static EAS_RESULT RTTTL_ParseHeader (S_EAS_DATA *pEASData, S_RTTTL_DATA* pData, EAS_BOOL metaData); static EAS_RESULT RTTTL_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pValue); static EAS_RESULT RTTTL_PeekNextChar (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pValue); /* inline functions */ EAS_INLINE void RTTTL_PutBackChar (S_RTTTL_DATA *pData, EAS_I8 value) { pData->dataByte = value; } /* lookup table for note values */ static const EAS_U8 noteTable[] = { 21, 23, 12, 14, 16, 17, 19, 23 }; /*---------------------------------------------------------------------------- * * EAS_RTTTL_Parser * * This structure contains the functional interface for the iMelody parser *---------------------------------------------------------------------------- */ const S_FILE_PARSER_INTERFACE EAS_RTTTL_Parser = { RTTTL_CheckFileType, RTTTL_Prepare, RTTTL_Time, RTTTL_Event, RTTTL_State, RTTTL_Close, RTTTL_Reset, RTTTL_Pause, RTTTL_Resume, NULL, RTTTL_SetData, RTTTL_GetData, NULL }; /*---------------------------------------------------------------------------- * RTTTL_CheckFileType() *---------------------------------------------------------------------------- * Purpose: * Check the file type to see if we can parse it * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT RTTTL_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) { S_RTTTL_DATA data; S_RTTTL_DATA *pData; /* see if we can parse the header */ data.fileHandle = fileHandle; data.fileOffset = offset; *ppHandle= NULL; if (RTTTL_ParseHeader (pEASData, &data, EAS_FALSE) == EAS_SUCCESS) { /* check for static memory allocation */ if (pEASData->staticMemoryModel) pData = EAS_CMEnumData(EAS_CM_RTTTL_DATA); else pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_RTTTL_DATA)); if (!pData) return EAS_ERROR_MALLOC_FAILED; EAS_HWMemSet(pData, 0, sizeof(S_RTTTL_DATA)); /* return a pointer to the instance data */ pData->fileHandle = fileHandle; pData->fileOffset = offset; pData->state = EAS_STATE_OPEN; *ppHandle = pData; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RTTTL_Prepare() *---------------------------------------------------------------------------- * Purpose: * Prepare to parse the file. Allocates instance data (or uses static allocation for * static memory model). * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT RTTTL_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_RTTTL_DATA* pData; EAS_RESULT result; /* check for valid state */ pData = (S_RTTTL_DATA*) pInstData; if (pData->state != EAS_STATE_OPEN) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; /* instantiate a synthesizer */ if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } return result; } pData->state = EAS_STATE_ERROR; if ((result = RTTTL_ParseHeader (pEASData, pData, (EAS_BOOL) (pData->metadata.callback != NULL))) != EAS_SUCCESS) { /* if using dynamic memory, free it */ if (!pEASData->staticMemoryModel) EAS_HWFree(pEASData->hwInstData, pData); return result; } pData->state = EAS_STATE_READY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RTTTL_Time() *---------------------------------------------------------------------------- * Purpose: * Returns the time of the next event in msecs * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * pTime - pointer to variable to hold time of next event (in msecs) * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ static EAS_RESULT RTTTL_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) { S_RTTTL_DATA *pData; pData = (S_RTTTL_DATA*) pInstData; /* return time in milliseconds */ /*lint -e{704} use shift instead of division */ *pTime = pData->time >> 8; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RTTTL_Event() *---------------------------------------------------------------------------- * Purpose: * Parse the next event in the file * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT RTTTL_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) { S_RTTTL_DATA* pData; EAS_RESULT result; EAS_I32 ticks; EAS_I32 temp; EAS_I8 c; EAS_U8 note; EAS_U8 octave; pData = (S_RTTTL_DATA*) pInstData; if (pData->state >= EAS_STATE_OPEN) return EAS_SUCCESS; /* initialize MIDI channel when the track starts playing */ if (pData->time == 0) { /* set program to square lead */ VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, RTTTL_CHANNEL, RTTTL_PROGRAM); /* set channel volume to max */ VMControlChange(pEASData->pVoiceMgr, pData->pSynth, RTTTL_CHANNEL, 7, 127); } /* check for end of note */ if (pData->note) { /* stop the note */ VMStopNote(pEASData->pVoiceMgr, pData->pSynth, RTTTL_CHANNEL, pData->note, 0); pData->note = 0; /* check for rest between notes */ if (pData->restTicks) { pData->time += pData->restTicks; pData->restTicks = 0; return EAS_SUCCESS; } } /* parse the next event */ octave = pData->octave; note = 0; ticks = pData->duration * pData->tick; for (;;) { /* get next character */ if ((result = RTTTL_GetNextChar(pEASData->hwInstData, pData, &c)) != EAS_SUCCESS) { if (result != EAS_EOF) return result; /* end of file, if no notes to process, check for looping */ if (!note) { /* if no loop set state to stopping */ if (pData->repeatCount == 0) { pData->state = EAS_STATE_STOPPING; VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth); return EAS_SUCCESS; } /* decrement loop count */ if (pData->repeatCount != RTTTL_INFINITE_LOOP) pData->repeatCount--; /* if locating, ignore infinite loops */ else if (parserMode != eParserModePlay) { pData->state = EAS_STATE_STOPPING; VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth); return EAS_SUCCESS; } /* loop back to start of notes */ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->repeatOffset)) != EAS_SUCCESS) return result; continue; } /* still have a note to process */ else c = ','; } /* bpm */ if (c == 'b') { /* peek at next character */ if ((result = RTTTL_PeekNextChar(pEASData->hwInstData, pData, &c)) != EAS_SUCCESS) return result; /* if a number, must be octave or tempo */ if (IsDigit(c)) { if ((result = RTTTL_GetNumber(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) return result; /* check for octave first */ if ((temp >= 4) && (temp <= 7)) { octave = (EAS_U8) temp; } /* check for tempo */ else if ((temp >= 25) && (temp <= 900)) { pData->tick = TICK_CONVERT / (EAS_U32) temp; } /* don't know what it was */ else return EAS_ERROR_FILE_FORMAT; } /* must be a note */ else { note = noteTable[1]; } } /* octave */ else if (c == 'o') { if ((result = RTTTL_GetOctave(pEASData->hwInstData, pData, &pData->octave)) != EAS_SUCCESS) return result; } /* style */ else if (c == 's') { if ((result = RTTTL_GetStyle(pEASData->hwInstData, pData)) != EAS_SUCCESS) return result; } /* duration or octave */ else if (IsDigit(c)) { RTTTL_PutBackChar(pData, c); /* duration comes before note */ if (!note) { if ((result = RTTTL_GetDuration(pEASData->hwInstData, pData, &c)) != EAS_SUCCESS) return result; ticks = c * pData->tick; } /* octave comes after note */ else { if ((result = RTTTL_GetOctave(pEASData->hwInstData, pData, &octave)) != EAS_SUCCESS) return result; } } /* note or rest */ else if ((c >= 'a') && (c <= 'h')) { note = noteTable[c - 'a']; } else if (c == 'p') { note = RTTTL_REST; } /* dotted note */ else if (c == '.') { /*lint -e{704} shift for performance */ ticks += ticks >> 1; } /* accidental */ else if (c == '#') { if (note) note++; } /* end of event */ else if ((c == ',') && note) { /* handle note events */ if (note != RTTTL_REST) { /* save note and start it */ pData->note = note + octave; if (parserMode == eParserModePlay) VMStartNote(pEASData->pVoiceMgr, pData->pSynth, RTTTL_CHANNEL, pData->note, RTTTL_VELOCITY); /* determine note length */ switch (pData->style) { /* natural */ case 'n': /*lint -e{704} shift for performance */ pData->restTicks = ticks >> 4; break; /* continuous */ case 'c': pData->restTicks = 0; break; /* staccato */ case 's': /*lint -e{704} shift for performance */ pData->restTicks = ticks >> 1; break; default: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "RTTTL_Event: Unexpected style type %c\n", pData->style); */ } break; } /* next event is at end of this note */ pData->time += ticks - pData->restTicks; } /* rest */ else pData->time += ticks; /* event found, return to caller */ break; } } pData->state = EAS_STATE_PLAY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RTTTL_State() *---------------------------------------------------------------------------- * Purpose: * Returns the current state of the stream * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * pState - pointer to variable to store state * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ static EAS_RESULT RTTTL_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) { S_RTTTL_DATA* pData; /* establish pointer to instance data */ pData = (S_RTTTL_DATA*) pInstData; /* if stopping, check to see if synth voices are active */ if (pData->state == EAS_STATE_STOPPING) { if (VMActiveVoices(pData->pSynth) == 0) pData->state = EAS_STATE_STOPPED; } if (pData->state == EAS_STATE_PAUSING) { if (VMActiveVoices(pData->pSynth) == 0) pData->state = EAS_STATE_PAUSED; } /* return current state */ *pState = pData->state; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RTTTL_Close() *---------------------------------------------------------------------------- * Purpose: * Close the file and clean up * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT RTTTL_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_RTTTL_DATA* pData; EAS_RESULT result; pData = (S_RTTTL_DATA*) pInstData; /* close the file */ if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS) return result; /* free the synth */ if (pData->pSynth != NULL) VMMIDIShutdown(pEASData, pData->pSynth); /* if using dynamic memory, free it */ if (!pEASData->staticMemoryModel) EAS_HWFree(pEASData->hwInstData, pData); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RTTTL_Reset() *---------------------------------------------------------------------------- * Purpose: * Reset the sequencer. Used for locating backwards in the file. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT RTTTL_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_RTTTL_DATA* pData; EAS_RESULT result; pData = (S_RTTTL_DATA*) pInstData; /* reset the synth */ VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE); /* reset time to zero */ pData->time = 0; pData->note = 0; /* reset file position and re-parse header */ pData->state = EAS_STATE_ERROR; if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) return result; if ((result = RTTTL_ParseHeader (pEASData, pData, EAS_TRUE)) != EAS_SUCCESS) return result; pData->state = EAS_STATE_READY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RTTTL_Pause() *---------------------------------------------------------------------------- * Purpose: * Pauses the sequencer. Mutes all voices and sets state to pause. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT RTTTL_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_RTTTL_DATA *pData; /* can't pause a stopped stream */ pData = (S_RTTTL_DATA*) pInstData; if (pData->state == EAS_STATE_STOPPED) return EAS_ERROR_ALREADY_STOPPED; /* mute the synthesizer */ VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth); pData->state = EAS_STATE_PAUSING; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RTTTL_Resume() *---------------------------------------------------------------------------- * Purpose: * Resume playing after a pause, sets state back to playing. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ static EAS_RESULT RTTTL_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_RTTTL_DATA *pData; /* can't resume a stopped stream */ pData = (S_RTTTL_DATA*) pInstData; if (pData->state == EAS_STATE_STOPPED) return EAS_ERROR_ALREADY_STOPPED; /* nothing to do but resume playback */ pData->state = EAS_STATE_PLAY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RTTTL_SetData() *---------------------------------------------------------------------------- * Purpose: * Return file type * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ static EAS_RESULT RTTTL_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) { S_RTTTL_DATA *pData; pData = (S_RTTTL_DATA *) pInstData; switch (param) { /* set metadata callback */ case PARSER_DATA_METADATA_CB: EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB)); break; default: return EAS_ERROR_INVALID_PARAMETER; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RTTTL_GetData() *---------------------------------------------------------------------------- * Purpose: * Return file type * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ static EAS_RESULT RTTTL_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) { S_RTTTL_DATA *pData; pData = (S_RTTTL_DATA *) pInstData; switch (param) { /* return file type as RTTTL */ case PARSER_DATA_FILE_TYPE: *pValue = EAS_FILE_RTTTL; break; #if 0 /* set transposition */ case PARSER_DATA_TRANSPOSITION: *pValue = pData->transposition; break; #endif case PARSER_DATA_SYNTH_HANDLE: *pValue = (EAS_I32) pData->pSynth; break; case PARSER_DATA_GAIN_OFFSET: *pValue = RTTTL_GAIN_OFFSET; break; default: return EAS_ERROR_INVALID_PARAMETER; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RTTTL_GetStyle() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT RTTTL_GetStyle (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData) { EAS_RESULT result; EAS_I8 style; /* get style */ if ((result = RTTTL_GetNextChar(hwInstData, pData, &style)) != EAS_SUCCESS) return result; if ((style != 's') && (style != 'n') && (style != 'c')) return EAS_ERROR_FILE_FORMAT; pData->style = style; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RTTTL_GetDuration() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT RTTTL_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pDuration) { EAS_RESULT result; EAS_I32 duration; EAS_I8 temp; /* get the duration */ if ((result = RTTTL_GetNumber(hwInstData, pData, &duration)) != EAS_SUCCESS) return result; if ((duration != 1) && (duration != 2) && (duration != 4) && (duration != 8) && (duration != 16) && (duration != 32)) return EAS_ERROR_FILE_FORMAT; temp = 64; while (duration) { /*lint -e{704} shift for performance */ duration = duration >> 1; /*lint -e{702} use shift for performance */ temp = temp >> 1; } *pDuration = temp; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RTTTL_GetOctave() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT RTTTL_GetOctave (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_U8 *pOctave) { EAS_RESULT result; EAS_I32 octave; /* get the tempo */ if ((result = RTTTL_GetNumber(hwInstData, pData, &octave)) != EAS_SUCCESS) return result; if ((octave < 4) || (octave > 7)) return EAS_ERROR_FILE_FORMAT; *pOctave = (EAS_U8) (octave * 12); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RTTTL_GetTempo() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT RTTTL_GetTempo (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData) { EAS_RESULT result; EAS_I32 tempo; /* get the tempo */ if ((result = RTTTL_GetNumber(hwInstData, pData, &tempo)) != EAS_SUCCESS) return result; if ((tempo < 25) || (tempo > 900)) return EAS_ERROR_FILE_FORMAT; pData->tick = TICK_CONVERT / (EAS_U32) tempo; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RTTTL_GetNumber() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT RTTTL_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I32 *pValue) { EAS_RESULT result; EAS_INT temp; EAS_I8 c; *pValue = -1; temp = 0; for (;;) { if ((result = RTTTL_PeekNextChar(hwInstData, pData, &c)) != EAS_SUCCESS) { if ((result == EAS_EOF) && (*pValue != -1)) return EAS_SUCCESS; return result; } if (IsDigit(c)) { pData->dataByte = 0; temp = temp * 10 + c - '0'; *pValue = temp; } else return EAS_SUCCESS; } } /*---------------------------------------------------------------------------- * RTTTL_ParseHeader() *---------------------------------------------------------------------------- * Purpose: * Prepare to parse the file. Allocates instance data (or uses static allocation for * static memory model). * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT RTTTL_ParseHeader (S_EAS_DATA *pEASData, S_RTTTL_DATA* pData, EAS_BOOL metaData) { EAS_RESULT result; EAS_I32 i; EAS_I8 temp; EAS_I8 control; /* initialize some defaults */ pData->time = 0; pData->tick = DEFAULT_TICK_CONV; pData->note = 0; pData->duration = 4; pData ->restTicks = 0; pData->octave = 60; pData->repeatOffset = -1; pData->repeatCount = 0; pData->style = 'n'; pData->dataByte = 0; metaData = metaData && (pData->metadata.buffer != NULL) && (pData->metadata.callback != NULL); /* seek to start of data */ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) return result; /* zero the metadata buffer */ if (metaData) EAS_HWMemSet(pData->metadata.buffer, 0, pData->metadata.bufferSize); /* read the title */ for (i = 0; i < RTTTL_MAX_TITLE_LEN; i++) { if ((result = EAS_HWGetByte(pEASData->hwInstData, pData->fileHandle, &temp)) != EAS_SUCCESS) return result; if (temp == ':') break; /* pass along metadata */ if (metaData) { if (i < (pData->metadata.bufferSize- 1)) pData->metadata.buffer[i] = (char) temp; } } /* check for error in title */ if (i == RTTTL_MAX_TITLE_LEN) return EAS_ERROR_FILE_FORMAT; /* pass along metadata */ if (metaData) (*pData->metadata.callback)(EAS_METADATA_TITLE, pData->metadata.buffer, pData->metadata.pUserData); /* control fields */ for (;;) { /* get control type */ if ((result = RTTTL_GetNextChar(pEASData->hwInstData, pData, &control)) != EAS_SUCCESS) return result; /* next char should be equal sign */ if ((result = RTTTL_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) return result; if (temp != '=') return EAS_ERROR_FILE_FORMAT; /* get the control value */ switch (control) { /* bpm */ case 'b': if ((result = RTTTL_GetTempo(pEASData->hwInstData, pData)) != EAS_SUCCESS) return result; break; /* duration */ case 'd': if ((result = RTTTL_GetDuration(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) return result; pData->duration = temp; break; /* loop */ case 'l': if ((result = RTTTL_GetNumber(pEASData->hwInstData, pData, &i)) != EAS_SUCCESS) return result; if ((i < 0) || (i > 15)) return EAS_ERROR_FILE_FORMAT; pData->repeatCount = (EAS_U8) i; break; /* octave */ case 'o': if ((result = RTTTL_GetOctave(pEASData->hwInstData, pData, &pData->octave)) != EAS_SUCCESS) return result; break; /* get style */ case 's': if ((result = RTTTL_GetStyle(pEASData->hwInstData, pData)) != EAS_SUCCESS) return result; break; /* unrecognized control */ default: return EAS_ERROR_FILE_FORMAT; } /* next character should be comma or colon */ if ((result = RTTTL_GetNextChar(pEASData->hwInstData, pData, &temp)) != EAS_SUCCESS) return result; /* check for end of control field */ if (temp == ':') break; /* must be a comma */ if (temp != ',') return EAS_ERROR_FILE_FORMAT; } /* should be at the start of the music block */ if ((result = EAS_HWFilePos(pEASData->hwInstData, pData->fileHandle, &pData->repeatOffset)) != EAS_SUCCESS) return result; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * RTTTL_GetNextChar() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT RTTTL_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pValue) { EAS_RESULT result; EAS_I8 temp; *pValue = 0; for(;;) { /* check for character that has been put back */ if (pData->dataByte) { temp = pData->dataByte; pData->dataByte = 0; } else { if ((result = EAS_HWGetByte(hwInstData, pData->fileHandle, &temp)) != EAS_SUCCESS) return result; } /* ignore white space */ if (!IsSpace(temp)) { *pValue = ToLower(temp); return EAS_SUCCESS; } } } /*---------------------------------------------------------------------------- * RTTTL_PeekNextChar() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT RTTTL_PeekNextChar (EAS_HW_DATA_HANDLE hwInstData, S_RTTTL_DATA *pData, EAS_I8 *pValue) { EAS_RESULT result; EAS_I8 temp; *pValue = 0; for(;;) { /* read a character from the file, if necessary */ if (!pData->dataByte) { if ((result = EAS_HWGetByte(hwInstData, pData->fileHandle, &pData->dataByte)) != EAS_SUCCESS) return result; } temp = pData->dataByte; /* ignore white space */ if (!IsSpace(temp)) { *pValue = ToLower(temp); return EAS_SUCCESS; } pData->dataByte = 0; } } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_rtttldata.h0000644000000000000000000000013113532747316027117 xustar0030 mtime=1567346382.709999865 29 atime=1567346382.85400005 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_rtttldata.h0000644000175000001440000000515213532747316027714 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_rtttldata.h * * Contents and purpose: * SMF File Parser * * This file contains data declarations for the RTTTL parser. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ #ifndef EAS_RTTTLDATA_H #define EAS_RTTTLDATA_H #include "eas_data.h" /* maximum line size as specified in iMelody V1.2 spec */ #define MAX_LINE_SIZE 75 /*---------------------------------------------------------------------------- * * S_RTTTL_DATA * * This structure contains the state data for the iMelody parser *---------------------------------------------------------------------------- */ typedef struct { EAS_FILE_HANDLE fileHandle; /* file handle */ S_SYNTH *pSynth; /* synthesizer handle */ S_METADATA_CB metadata; /* metadata callback */ EAS_I32 fileOffset; /* offset to start of data */ EAS_I32 time; /* current time in 256ths of a msec */ EAS_I32 tick; /* length of 32nd note in 256th of a msec */ EAS_I32 restTicks; /* ticks to rest after current note */ EAS_I32 repeatOffset; /* file offset to start of repeat section */ EAS_U8 repeatCount; /* repeat counter */ EAS_I8 dataByte; /* storage for characters that are "put back" */ EAS_U8 state; /* current state EAS_STATE_XXXX */ EAS_I8 style; /* from STYLE */ EAS_U8 note; /* MIDI note number */ EAS_U8 octave; /* decault octave prefix */ EAS_I8 duration; /* default note duration */ } S_RTTTL_DATA; #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_midictrl.h0000644000000000000000000000013113532747316026723 xustar0030 mtime=1567346382.701999855 29 atime=1567346382.85400005 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_midictrl.h0000644000175000001440000000460713532747316027524 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_midictrl.h * * Contents and purpose: * MIDI controller definitions * * This header only contains declarations that are specific * to this implementation. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_MIDICTRL_H #define _EAS_MIDICTRL_H /* define controller types */ /* Note that these controller types are specified in base 10 (decimal) and not in hexadecimal. The above midi messages are specified in hexadecimal. */ #define MIDI_CONTROLLER_BANK_SELECT 0 #define MIDI_CONTROLLER_BANK_SELECT_MSB 0 #define MIDI_CONTROLLER_MOD_WHEEL 1 #define MIDI_CONTROLLER_ENTER_DATA_MSB 6 #define MIDI_CONTROLLER_VOLUME 7 #define MIDI_CONTROLLER_PAN 10 #define MIDI_CONTROLLER_EXPRESSION 11 #define MIDI_CONTROLLER_BANK_SELECT_LSB 32 #define MIDI_CONTROLLER_ENTER_DATA_LSB 38 /* 0x26 */ #define MIDI_CONTROLLER_SUSTAIN_PEDAL 64 #define MIDI_CONTROLLER_SELECT_NRPN_LSB 98 #define MIDI_CONTROLLER_SELECT_NRPN_MSB 99 #define MIDI_CONTROLLER_SELECT_RPN_LSB 100 /* 0x64 */ #define MIDI_CONTROLLER_SELECT_RPN_MSB 101 /* 0x65 */ #define MIDI_CONTROLLER_ALL_SOUND_OFF 120 #define MIDI_CONTROLLER_RESET_CONTROLLERS 121 #define MIDI_CONTROLLER_ALL_NOTES_OFF 123 #define MIDI_CONTROLLER_OMNI_OFF 124 #define MIDI_CONTROLLER_OMNI_ON 125 #define MIDI_CONTROLLER_MONO_ON_POLY_OFF 126 #define MIDI_CONTROLLER_POLY_ON_MONO_OFF 127 #endif /* #ifndef _EAS_MIDICTRL_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_pcm.h0000644000000000000000000000013113532747316025673 xustar0030 mtime=1567346382.709999865 29 atime=1567346382.85400005 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_pcm.h0000644000175000001440000002544713532747316026501 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_pcm.h * * Contents and purpose: * External function prototypes for eas_pcm.c module * * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 847 $ * $Date: 2007-08-27 21:30:08 -0700 (Mon, 27 Aug 2007) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_PCM_H #define _EAS_PCM_H /* default gain setting - roughly unity gain */ #define PCM_DEFAULT_GAIN_SETTING 0x6000 typedef struct s_pcm_state_tag *EAS_PCM_HANDLE; typedef void (*EAS_PCM_CALLBACK) (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR cbInstData, EAS_PCM_HANDLE pcmHandle, EAS_STATE state); /* parameters for EAS_PEOpenStream */ typedef struct s_pcm_open_params_tag { EAS_FILE_HANDLE fileHandle; EAS_I32 decoder; EAS_U32 sampleRate; EAS_I32 size; EAS_U32 loopStart; EAS_U32 loopSamples; EAS_I32 blockSize; EAS_U32 flags; EAS_U32 envData; EAS_I16 volume; EAS_PCM_CALLBACK pCallbackFunc; EAS_VOID_PTR cbInstData; } S_PCM_OPEN_PARAMS; /*---------------------------------------------------------------------------- * EAS_PEInit() *---------------------------------------------------------------------------- * Purpose: * Initializes the PCM engine * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PEInit (EAS_DATA_HANDLE pEASData); /*---------------------------------------------------------------------------- * EAS_PEShutdown() *---------------------------------------------------------------------------- * Purpose: * Shuts down the PCM engine * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PEShutdown (EAS_DATA_HANDLE pEASData); /*---------------------------------------------------------------------------- * EAS_PEOpenStream() *---------------------------------------------------------------------------- * Purpose: * Starts up a PCM playback * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PEOpenStream (EAS_DATA_HANDLE pEASData, S_PCM_OPEN_PARAMS *pParams, EAS_PCM_HANDLE *pHandle); /*---------------------------------------------------------------------------- * EAS_PEContinueStream() *---------------------------------------------------------------------------- * Purpose: * Continues a PCM stream * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PEContinueStream (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle, EAS_I32 size); /*---------------------------------------------------------------------------- * EAS_PEGetFileHandle() *---------------------------------------------------------------------------- * Purpose: * Returns the file handle of a stream * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PEGetFileHandle (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle, EAS_FILE_HANDLE *pFileHandle); /*---------------------------------------------------------------------------- * EAS_PERender() *---------------------------------------------------------------------------- * Purpose: * Render a buffer of PCM audio * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PERender (EAS_DATA_HANDLE pEASData, EAS_I32 numSamples); /*---------------------------------------------------------------------------- * EAS_PEUpdateParams() *---------------------------------------------------------------------------- * Purpose: * Update the pitch and volume parameters using MIDI controls * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PEUpdateParams (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch, EAS_I16 gainLeft, EAS_I16 gainRight); /*---------------------------------------------------------------------------- * EAS_PELocate() *---------------------------------------------------------------------------- * Purpose: * This function seeks to the requested place in the file. Accuracy * is dependent on the sample rate and block size. * * Inputs: * pEASData - pointer to overall EAS data structure * pState - stream handle * time - media time in milliseconds *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PELocate (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I32 time); /*---------------------------------------------------------------------------- * EAS_PEUpdateVolume() *---------------------------------------------------------------------------- * Purpose: * Update the volume parameters for a PCM stream * * Inputs: * pEASData - pointer to EAS library instance data * handle - pointer to S_PCM_STATE for this stream * gainLeft - linear gain multipler in 1.15 fraction format * gainRight - linear gain multipler in 1.15 fraction format * initial - initial settings, set current gain * * Outputs: * * * Side Effects: * * Notes * In mono mode, leftGain controls the output gain and rightGain is ignored *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_RESULT EAS_PEUpdateVolume (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I16 volume); /*---------------------------------------------------------------------------- * EAS_PEUpdatePitch() *---------------------------------------------------------------------------- * Purpose: * Update the pitch parameter for a PCM stream * * Inputs: * pEASData - pointer to EAS library instance data * pState - pointer to S_PCM_STATE for this stream * pitch - new pitch value in pitch cents *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_RESULT EAS_PEUpdatePitch (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE pState, EAS_I16 pitch); /*---------------------------------------------------------------------------- * EAS_PEState() *---------------------------------------------------------------------------- * Purpose: * Returns the current state of the stream * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * pState - pointer to variable to store state * * Outputs: * * * Side Effects: * * Notes: * This interface is also exposed in the internal library for use by the other modules. *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PEState (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle, EAS_STATE *pState); /*---------------------------------------------------------------------------- * EAS_PEClose() *---------------------------------------------------------------------------- * Purpose: * Close the file and clean up * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PEClose (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); /*---------------------------------------------------------------------------- * EAS_PEReset() *---------------------------------------------------------------------------- * Purpose: * Reset the sequencer. Used for locating backwards in the file. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PEReset (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); /*---------------------------------------------------------------------------- * EAS_PEPause() *---------------------------------------------------------------------------- * Purpose: * Mute and pause rendering a PCM stream. Sets the gain target to zero and stops the playback * at the end of the next audio frame. * * Inputs: * pEASData - pointer to EAS library instance data * handle - pointer to S_PCM_STATE for this stream * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PEPause (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); /*---------------------------------------------------------------------------- * EAS_PEResume() *---------------------------------------------------------------------------- * Purpose: * Resume rendering a PCM stream. Sets the gain target back to its * previous setting and restarts playback at the end of the next audio * frame. * * Inputs: * pEASData - pointer to EAS library instance data * handle - pointer to S_PCM_STATE for this stream * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PEResume (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); /*---------------------------------------------------------------------------- * EAS_PERelease() *---------------------------------------------------------------------------- * Purpose: * Put the PCM stream envelope into release. * * Inputs: * pEASData - pointer to EAS library instance data * handle - pointer to S_PCM_STATE for this stream * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PERelease (EAS_DATA_HANDLE pEASData, EAS_PCM_HANDLE handle); #endif /* end _EAS_PCM_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_imelody.c0000644000000000000000000000013113532747316026551 xustar0030 mtime=1567346382.701999855 29 atime=1567346382.85400005 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_imelody.c0000644000175000001440000014272213532747316027353 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_imelody.c * * Contents and purpose: * iMelody parser * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 797 $ * $Date: 2007-08-01 00:15:56 -0700 (Wed, 01 Aug 2007) $ *---------------------------------------------------------------------------- */ /* lint doesn't like the way some string.h files look */ #ifdef _lint #include "lint_stdlib.h" #else #include #endif #include "eas_data.h" #include "eas_miditypes.h" #include "eas_parser.h" #include "eas_report.h" #include "eas_host.h" #include "eas_midi.h" #include "eas_config.h" #include "eas_vm_protos.h" #include "eas_imelodydata.h" #include "eas_ctype.h" // #define _DEBUG_IMELODY /* increase gain for mono ringtones */ #define IMELODY_GAIN_OFFSET 8 /* length of 32nd note in 1/256ths of a msec for 120 BPM tempo */ #define DEFAULT_TICK_CONV 16000 #define TICK_CONVERT 1920000 /* default channel and program for iMelody playback */ #define IMELODY_CHANNEL 0 #define IMELODY_PROGRAM 80 #define IMELODY_VEL_MUL 4 #define IMELODY_VEL_OFS 67 /* multiplier for fixed point triplet conversion */ #define TRIPLET_MULTIPLIER 683 #define TRIPLET_SHIFT 10 static const char* const tokens[] = { "BEGIN:IMELODY", "VERSION:", "FORMAT:CLASS", "NAME:", "COMPOSER:", "BEAT:", "STYLE:", "VOLUME:", "MELODY:", "END:IMELODY" }; /* ledon or ledoff */ static const char ledStr[] = "edo"; /* vibeon or vibeoff */ static const char vibeStr[] = "ibeo"; /* backon or backoff */ static const char backStr[] = "cko"; typedef enum { TOKEN_BEGIN, TOKEN_VERSION, TOKEN_FORMAT, TOKEN_NAME, TOKEN_COMPOSER, TOKEN_BEAT, TOKEN_STYLE, TOKEN_VOLUME, TOKEN_MELODY, TOKEN_END, TOKEN_INVALID } ENUM_IMELODY_TOKENS; /* lookup table for note values */ static const EAS_I8 noteTable[] = { 9, 11, 0, 2, 4, 5, 7 }; /* inline functions */ #ifdef _DEBUG_IMELODY static void PutBackChar (S_IMELODY_DATA *pData) { if (pData->index) pData->index--; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "PutBackChar '%c'\n", pData->buffer[pData->index]); */ } } #else EAS_INLINE void PutBackChar (S_IMELODY_DATA *pData) { if (pData->index) pData->index--; } #endif /* local prototypes */ static EAS_RESULT IMY_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); static EAS_RESULT IMY_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT IMY_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); static EAS_RESULT IMY_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); static EAS_RESULT IMY_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); static EAS_RESULT IMY_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT IMY_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT IMY_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT IMY_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT IMY_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); static EAS_RESULT IMY_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); static EAS_BOOL IMY_PlayNote (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData, EAS_I8 note, EAS_INT parserMode); static EAS_BOOL IMY_PlayRest (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData); static EAS_BOOL IMY_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_I32 *pDuration); static EAS_BOOL IMY_GetLEDState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData); static EAS_BOOL IMY_GetVibeState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData); static EAS_BOOL IMY_GetBackState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData); static EAS_BOOL IMY_GetVolume (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader); static EAS_BOOL IMY_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_INT *temp, EAS_BOOL inHeader); static EAS_RESULT IMY_ParseHeader (S_EAS_DATA *pEASData, S_IMELODY_DATA* pData); static EAS_I8 IMY_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader); static EAS_RESULT IMY_ReadLine (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I8 *buffer, EAS_I32 *pStartLine); static EAS_INT IMY_ParseLine (EAS_I8 *buffer, EAS_U8 *pIndex); /*---------------------------------------------------------------------------- * * EAS_iMelody_Parser * * This structure contains the functional interface for the iMelody parser *---------------------------------------------------------------------------- */ const S_FILE_PARSER_INTERFACE EAS_iMelody_Parser = { IMY_CheckFileType, IMY_Prepare, IMY_Time, IMY_Event, IMY_State, IMY_Close, IMY_Reset, IMY_Pause, IMY_Resume, NULL, IMY_SetData, IMY_GetData, NULL }; /*---------------------------------------------------------------------------- * IMY_CheckFileType() *---------------------------------------------------------------------------- * Purpose: * Check the file type to see if we can parse it * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT IMY_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) { S_IMELODY_DATA* pData; EAS_I8 buffer[MAX_LINE_SIZE+1]; EAS_U8 index; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_CheckFileType\n"); */ } #endif /* read the first line of the file */ *ppHandle = NULL; if (IMY_ReadLine(pEASData->hwInstData, fileHandle, buffer, NULL) != EAS_SUCCESS) return EAS_SUCCESS; /* check for header string */ if (IMY_ParseLine(buffer, &index) == TOKEN_BEGIN) { /* check for static memory allocation */ if (pEASData->staticMemoryModel) pData = EAS_CMEnumData(EAS_CM_IMELODY_DATA); else pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_IMELODY_DATA)); if (!pData) return EAS_ERROR_MALLOC_FAILED; EAS_HWMemSet(pData, 0, sizeof(S_IMELODY_DATA)); /* initialize */ pData->fileHandle = fileHandle; pData->fileOffset = offset; pData->state = EAS_STATE_ERROR; pData->state = EAS_STATE_OPEN; /* return a pointer to the instance data */ *ppHandle = pData; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * IMY_Prepare() *---------------------------------------------------------------------------- * Purpose: * Prepare to parse the file. Allocates instance data (or uses static allocation for * static memory model). * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT IMY_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_IMELODY_DATA* pData; EAS_RESULT result; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_Prepare\n"); */ } #endif /* check for valid state */ pData = (S_IMELODY_DATA*) pInstData; if (pData->state != EAS_STATE_OPEN) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; /* instantiate a synthesizer */ if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } return result; } /* parse the header */ if ((result = IMY_ParseHeader(pEASData, pData)) != EAS_SUCCESS) return result; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Prepare: state set to EAS_STATE_READY\n"); */ } #endif pData ->state = EAS_STATE_READY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * IMY_Time() *---------------------------------------------------------------------------- * Purpose: * Returns the time of the next event in msecs * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * pTime - pointer to variable to hold time of next event (in msecs) * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) common decoder interface - pEASData not used */ static EAS_RESULT IMY_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) { S_IMELODY_DATA *pData; pData = (S_IMELODY_DATA*) pInstData; /* return time in milliseconds */ /*lint -e{704} use shift instead of division */ *pTime = pData->time >> 8; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * IMY_Event() *---------------------------------------------------------------------------- * Purpose: * Parse the next event in the file * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT IMY_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) { S_IMELODY_DATA* pData; EAS_RESULT result; EAS_I8 c; EAS_BOOL eof; EAS_INT temp; pData = (S_IMELODY_DATA*) pInstData; if (pData->state >= EAS_STATE_OPEN) return EAS_SUCCESS; if (pData->state == EAS_STATE_READY) { pData->state = EAS_STATE_PLAY; } /* initialize MIDI channel when the track starts playing */ if (pData->time == 0) { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: Reset\n"); */ } #endif /* set program to square lead */ VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, IMELODY_PROGRAM); /* set channel volume to max */ VMControlChange(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, 7, 127); } /* check for end of note */ if (pData->note) { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Stopping note %d\n", pData->note); */ } #endif /* stop the note */ VMStopNote(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, pData->note, 0); pData->note = 0; /* check for rest between notes */ if (pData->restTicks) { pData->time += pData->restTicks; pData->restTicks = 0; return EAS_SUCCESS; } } /* parse the next event */ eof = EAS_FALSE; while (!eof) { /* get next character */ c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); switch (c) { /* start repeat */ case '(': #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter repeat section\n", c); */ } #endif if (pData->repeatOffset < 0) { pData->repeatOffset = pData->startLine + (EAS_I32) pData->index; /* save current time and check it later to make sure the loop isn't zero length */ pData->repeatTime = pData->time; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat offset = %d\n", pData->repeatOffset); */ } #endif } else { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring nested repeat section\n"); */ } break; /* end repeat */ case ')': #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "End repeat section, repeat offset = %d\n", pData->repeatOffset); */ } #endif /* ignore zero-length loops */ if (pData->repeatTime == pData->time) { pData->repeatCount = -1; pData->repeatOffset = -1; } else if (pData->repeatCount >= 0) { /* decrement repeat count (repeatCount == 0 means infinite loop) */ if (pData->repeatCount > 0) { if (--pData->repeatCount == 0) { pData->repeatCount = -1; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat loop complete\n"); */ } #endif } } //2 TEMPORARY FIX: If locating, don't do infinite loops. //3 We need a different mode for metadata parsing where we don't loop at all if ((parserMode == eParserModePlay) || (pData->repeatCount != 0)) { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Rewinding file for repeat\n"); */ } #endif /* rewind to start of loop */ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->repeatOffset)) != EAS_SUCCESS) return result; IMY_ReadLine(pEASData->hwInstData, pData->fileHandle, pData->buffer, &pData->startLine); pData->index = 0; /* if last loop, prevent future loops */ if (pData->repeatCount == -1) pData->repeatOffset = -1; } } break; /* repeat count */ case '@': if (!IMY_GetNumber(pEASData->hwInstData, pData, &temp, EAS_FALSE)) eof = EAS_TRUE; else if (pData->repeatOffset > 0) { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Repeat count = %dt", pData->repeatCount); */ } #endif if (pData->repeatCount < 0) pData->repeatCount = (EAS_I16) temp; } break; /* volume */ case 'V': if (!IMY_GetVolume(pEASData->hwInstData, pData, EAS_FALSE)) eof = EAS_TRUE; break; /* flat */ case '&': pData->noteModifier = -1; break; /* sharp */ case '#': pData->noteModifier = +1; break; /* octave */ case '*': c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); if (IsDigit(c)) pData->octave = (EAS_U8) ((c - '0' + 1) * 12); else if (!c) eof = EAS_TRUE; break; /* ledon or ledoff */ case 'l': if (!IMY_GetLEDState(pEASData, pData)) eof = EAS_TRUE; break; /* vibeon or vibeoff */ case 'v': if (!IMY_GetVibeState(pEASData, pData)) eof = EAS_TRUE; break; /* either a B note or backon or backoff */ case 'b': if (IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE) == 'a') { if (!IMY_GetBackState(pEASData, pData)) eof = EAS_TRUE; } else { PutBackChar(pData); if (IMY_PlayNote(pEASData, pData, c, parserMode)) return EAS_SUCCESS; eof = EAS_TRUE; } break; /* rest */ case 'r': case 'R': if (IMY_PlayRest(pEASData, pData)) return EAS_SUCCESS; eof = EAS_TRUE; break; /* EOF */ case 0: #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: end of iMelody file detected\n"); */ } #endif eof = EAS_TRUE; break; /* must be a note */ default: c = ToLower(c); if ((c >= 'a') && (c <= 'g')) { if (IMY_PlayNote(pEASData, pData, c, parserMode)) return EAS_SUCCESS; eof = EAS_TRUE; } else { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unexpected character '%c' [0x%02x]\n", c, c); */ } break; } } /* handle EOF */ #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Event: state set to EAS_STATE_STOPPING\n"); */ } #endif pData->state = EAS_STATE_STOPPING; VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * IMY_State() *---------------------------------------------------------------------------- * Purpose: * Returns the current state of the stream * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * pState - pointer to variable to store state * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) common decoder interface - pEASData not used */ static EAS_RESULT IMY_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) { S_IMELODY_DATA* pData; /* establish pointer to instance data */ pData = (S_IMELODY_DATA*) pInstData; /* if stopping, check to see if synth voices are active */ if (pData->state == EAS_STATE_STOPPING) { if (VMActiveVoices(pData->pSynth) == 0) { pData->state = EAS_STATE_STOPPED; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_State: state set to EAS_STATE_STOPPED\n"); */ } #endif } } if (pData->state == EAS_STATE_PAUSING) { if (VMActiveVoices(pData->pSynth) == 0) { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_State: state set to EAS_STATE_PAUSED\n"); */ } #endif pData->state = EAS_STATE_PAUSED; } } /* return current state */ *pState = pData->state; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * IMY_Close() *---------------------------------------------------------------------------- * Purpose: * Close the file and clean up * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT IMY_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_IMELODY_DATA* pData; EAS_RESULT result; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Close: close file\n"); */ } #endif pData = (S_IMELODY_DATA*) pInstData; /* close the file */ if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS) return result; /* free the synth */ if (pData->pSynth != NULL) VMMIDIShutdown(pEASData, pData->pSynth); /* if using dynamic memory, free it */ if (!pEASData->staticMemoryModel) EAS_HWFree(pEASData->hwInstData, pData); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * IMY_Reset() *---------------------------------------------------------------------------- * Purpose: * Reset the sequencer. Used for locating backwards in the file. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT IMY_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_IMELODY_DATA* pData; EAS_RESULT result; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Reset: reset file\n"); */ } #endif pData = (S_IMELODY_DATA*) pInstData; /* reset the synth */ VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE); /* reset time to zero */ pData->time = 0; pData->note = 0; /* reset file position and re-parse header */ pData->state = EAS_STATE_ERROR; if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) return result; if ((result = IMY_ParseHeader (pEASData, pData)) != EAS_SUCCESS) return result; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Reset: state set to EAS_STATE_ERROR\n"); */ } #endif pData->state = EAS_STATE_READY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * IMY_Pause() *---------------------------------------------------------------------------- * Purpose: * Pauses the sequencer. Mutes all voices and sets state to pause. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT IMY_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_IMELODY_DATA *pData; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Pause: pause file\n"); */ } #endif /* can't pause a stopped stream */ pData = (S_IMELODY_DATA*) pInstData; if (pData->state == EAS_STATE_STOPPED) return EAS_ERROR_ALREADY_STOPPED; /* mute the synthesizer */ VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth); pData->state = EAS_STATE_PAUSING; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * IMY_Resume() *---------------------------------------------------------------------------- * Purpose: * Resume playing after a pause, sets state back to playing. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) common decoder interface - pEASData not used */ static EAS_RESULT IMY_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_IMELODY_DATA *pData; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_Resume: resume file\n"); */ } #endif /* can't resume a stopped stream */ pData = (S_IMELODY_DATA*) pInstData; if (pData->state == EAS_STATE_STOPPED) return EAS_ERROR_ALREADY_STOPPED; /* nothing to do but resume playback */ pData->state = EAS_STATE_PLAY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * IMY_SetData() *---------------------------------------------------------------------------- * Purpose: * Adjust tempo relative to song tempo * * Inputs: * pEASData - pointer to overall EAS data structure * pInstData - pointer to iMelody instance data * rate - rate (28-bit fractional amount) * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) common decoder interface - pEASData not used */ static EAS_RESULT IMY_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) { S_IMELODY_DATA *pData; pData = (S_IMELODY_DATA*) pInstData; switch (param) { /* set metadata callback */ case PARSER_DATA_METADATA_CB: EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB)); break; default: return EAS_ERROR_INVALID_PARAMETER; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * IMY_GetData() *---------------------------------------------------------------------------- * Purpose: * Return the file type * * Inputs: * pEASData - pointer to overall EAS data structure * pInstData - pointer to iMelody instance data * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) common decoder interface - pEASData not used */ static EAS_RESULT IMY_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) { S_IMELODY_DATA *pData; pData = (S_IMELODY_DATA*) pInstData; switch (param) { /* return file type as iMelody */ case PARSER_DATA_FILE_TYPE: *pValue = EAS_FILE_IMELODY; break; case PARSER_DATA_SYNTH_HANDLE: *pValue = (EAS_I32) pData->pSynth; break; case PARSER_DATA_GAIN_OFFSET: *pValue = IMELODY_GAIN_OFFSET; break; default: return EAS_ERROR_INVALID_PARAMETER; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * IMY_PlayNote() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_BOOL IMY_PlayNote (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData, EAS_I8 note, EAS_INT parserMode) { EAS_I32 duration; EAS_U8 velocity; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayNote: start note %d\n", note); */ } #endif /* get the duration */ if (!IMY_GetDuration(pEASData->hwInstData, pData, &duration)) return EAS_FALSE; /* save note value */ pData->note = (EAS_U8) (pData->octave + noteTable[note - 'a'] + pData->noteModifier); velocity = (EAS_U8) (pData->volume ? pData->volume * IMELODY_VEL_MUL + IMELODY_VEL_OFS : 0); /* start note only if in play mode */ if (parserMode == eParserModePlay) VMStartNote(pEASData->pVoiceMgr, pData->pSynth, IMELODY_CHANNEL, pData->note, velocity); #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayNote: Start note %d, duration %d\n", pData->note, duration); */ } #endif /* determine note length */ switch (pData->style) { case 0: /*lint -e{704} shift for performance */ pData->restTicks = duration >> 4; break; case 1: pData->restTicks = 0; break; case 2: /*lint -e{704} shift for performance */ pData->restTicks = duration >> 1; break; default: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "IMY_PlayNote: Note style out of range: %d\n", pData->style); */ } /*lint -e{704} shift for performance */ pData->restTicks = duration >> 4; break; } /* next event is at end of this note */ pData->time += duration - pData->restTicks; /* reset the flat/sharp modifier */ pData->noteModifier = 0; return EAS_TRUE; } /*---------------------------------------------------------------------------- * IMY_PlayRest() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_BOOL IMY_PlayRest (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData) { EAS_I32 duration; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_PlayRest]n"); */ } #endif /* get the duration */ if (!IMY_GetDuration(pEASData->hwInstData, pData, &duration)) return EAS_FALSE; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_PlayRest: note duration %d\n", duration); */ } #endif /* next event is at end of this note */ pData->time += duration; return EAS_TRUE; } /*---------------------------------------------------------------------------- * IMY_GetDuration() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_BOOL IMY_GetDuration (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_I32 *pDuration) { EAS_I32 duration; EAS_I8 c; /* get the duration */ *pDuration = 0; c = IMY_GetNextChar(hwInstData, pData, EAS_FALSE); if (!c) return EAS_FALSE; if ((c < '0') || (c > '5')) { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetDuration: error in duration '%c'\n", c); */ } #endif return EAS_FALSE; } /* calculate total length of note */ duration = pData->tick * (1 << ('5' - c)); /* check for duration modifier */ c = IMY_GetNextChar(hwInstData, pData, EAS_FALSE); if (c) { if (c == '.') /*lint -e{704} shift for performance */ duration += duration >> 1; else if (c == ':') /*lint -e{704} shift for performance */ duration += (duration >> 1) + (duration >> 2); else if (c == ';') /*lint -e{704} shift for performance */ duration = (duration * TRIPLET_MULTIPLIER) >> TRIPLET_SHIFT; else PutBackChar(pData); } *pDuration = duration; return EAS_TRUE; } /*---------------------------------------------------------------------------- * IMY_GetLEDState() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_BOOL IMY_GetLEDState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData) { EAS_I8 c; EAS_INT i; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetLEDState\n"); */ } #endif for (i = 0; i < 5; i++) { c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); if (!c) return EAS_FALSE; switch (i) { case 3: if (c == 'n') { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetLEDState: LED on\n"); */ } #endif EAS_HWLED(pEASData->hwInstData, EAS_TRUE); return EAS_TRUE; } else if (c != 'f') return EAS_FALSE; break; case 4: if (c == 'f') { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetLEDState: LED off\n"); */ } #endif EAS_HWLED(pEASData->hwInstData, EAS_FALSE); return EAS_TRUE; } return EAS_FALSE; default: if (c != ledStr[i]) return EAS_FALSE; break; } } return EAS_FALSE; } /*---------------------------------------------------------------------------- * IMY_GetVibeState() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_BOOL IMY_GetVibeState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData) { EAS_I8 c; EAS_INT i; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetVibeState\n"); */ } #endif for (i = 0; i < 6; i++) { c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); if (!c) return EAS_FALSE; switch (i) { case 4: if (c == 'n') { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVibeState: vibrate on\n"); */ } #endif EAS_HWVibrate(pEASData->hwInstData, EAS_TRUE); return EAS_TRUE; } else if (c != 'f') return EAS_FALSE; break; case 5: if (c == 'f') { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVibeState: vibrate off\n"); */ } #endif EAS_HWVibrate(pEASData->hwInstData, EAS_FALSE); return EAS_TRUE; } return EAS_FALSE; default: if (c != vibeStr[i]) return EAS_FALSE; break; } } return EAS_FALSE; } /*---------------------------------------------------------------------------- * IMY_GetBackState() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_BOOL IMY_GetBackState (S_EAS_DATA *pEASData, S_IMELODY_DATA *pData) { EAS_I8 c; EAS_INT i; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetBackState\n"); */ } #endif for (i = 0; i < 5; i++) { c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_FALSE); if (!c) return EAS_FALSE; switch (i) { case 3: if (c == 'n') { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetBackState: backlight on\n"); */ } #endif EAS_HWBackLight(pEASData->hwInstData, EAS_TRUE); return EAS_TRUE; } else if (c != 'f') return EAS_FALSE; break; case 4: if (c == 'f') { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetBackState: backlight off\n"); */ } #endif EAS_HWBackLight(pEASData->hwInstData, EAS_FALSE); return EAS_TRUE; } return EAS_FALSE; default: if (c != backStr[i]) return EAS_FALSE; break; } } return EAS_FALSE; } /*---------------------------------------------------------------------------- * IMY_GetVolume() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_BOOL IMY_GetVolume (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader) { EAS_INT temp; EAS_I8 c; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetVolume\n"); */ } #endif c = IMY_GetNextChar(hwInstData, pData, inHeader); if (c == '+') { if (pData->volume < 15) pData->volume++; return EAS_TRUE; } else if (c == '-') { if (pData->volume > 0) pData->volume--; return EAS_TRUE; } else if (IsDigit(c)) temp = c - '0'; else return EAS_FALSE; c = IMY_GetNextChar(hwInstData, pData, inHeader); if (IsDigit(c)) temp = temp * 10 + c - '0'; else if (c) PutBackChar(pData); if ((temp >= 0) && (temp <= 15)) { if (inHeader && (temp == 0)) { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring V0 encountered in header\n"); */ } else pData->volume = (EAS_U8) temp; } return EAS_TRUE; } /*---------------------------------------------------------------------------- * IMY_GetNumber() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_BOOL IMY_GetNumber (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_INT *temp, EAS_BOOL inHeader) { EAS_BOOL ok; EAS_I8 c; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_GetNumber\n"); */ } #endif *temp = 0; ok = EAS_FALSE; for (;;) { c = IMY_GetNextChar(hwInstData, pData, inHeader); if (IsDigit(c)) { *temp = *temp * 10 + c - '0'; ok = EAS_TRUE; } else { if (c) PutBackChar(pData); #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNumber: value %d\n", *temp); */ } #endif return ok; } } } /*---------------------------------------------------------------------------- * IMY_GetVersion() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_BOOL IMY_GetVersion (S_IMELODY_DATA *pData, EAS_INT *pVersion) { EAS_I8 c; EAS_INT temp; EAS_INT version; version = temp = 0; for (;;) { c = pData->buffer[pData->index++]; if ((c == 0) || (c == '.')) { /*lint -e{701} use shift for performance */ version = (version << 8) + temp; if (c == 0) { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetVersion: version 0x%04x\n", version); */ } #endif *pVersion = version; return EAS_TRUE; } temp = 0; } else if (IsDigit(c)) temp = (temp * 10) + c - '0'; } } /*---------------------------------------------------------------------------- * IMY_MetaData() *---------------------------------------------------------------------------- * Purpose: * Prepare to parse the file. Allocates instance data (or uses static allocation for * static memory model). * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static void IMY_MetaData (S_IMELODY_DATA *pData, E_EAS_METADATA_TYPE metaType, EAS_I8 *buffer) { EAS_I32 len; /* check for callback */ if (!pData->metadata.callback) return; /* copy data to host buffer */ len = (EAS_I32) strlen((char*) buffer); if (len >pData->metadata.bufferSize) len = pData->metadata.bufferSize; strncpy((char*) pData->metadata.buffer, (char*) buffer, (size_t) len); pData->metadata.buffer[len] = 0; /* callback to host */ pData->metadata.callback(metaType, pData->metadata.buffer, pData->metadata.pUserData); } /*---------------------------------------------------------------------------- * IMY_ParseHeader() *---------------------------------------------------------------------------- * Purpose: * Prepare to parse the file. Allocates instance data (or uses static allocation for * static memory model). * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT IMY_ParseHeader (S_EAS_DATA *pEASData, S_IMELODY_DATA* pData) { EAS_RESULT result; EAS_INT token; EAS_INT temp; EAS_I8 c; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Enter IMY_ParseHeader\n"); */ } #endif /* initialize some defaults */ pData->time = 0; pData->tick = DEFAULT_TICK_CONV; pData->note = 0; pData->noteModifier = 0; pData ->restTicks = 0; pData->volume = 7; pData->octave = 60; pData->repeatOffset = -1; pData->repeatCount = -1; pData->style = 0; /* force the read of the first line */ pData->index = 1; /* read data until we get to melody */ for (;;) { /* read a line from the file and parse the token */ if (pData->index != 0) { if ((result = IMY_ReadLine(pEASData->hwInstData, pData->fileHandle, pData->buffer, &pData->startLine)) != EAS_SUCCESS) { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseHeader: IMY_ReadLine returned %d\n", result); */ } #endif return result; } } token = IMY_ParseLine(pData->buffer, &pData->index); switch (token) { /* ignore these valid tokens */ case TOKEN_BEGIN: break; case TOKEN_FORMAT: if (!IMY_GetVersion(pData, &temp)) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid FORMAT field '%s'\n", pData->buffer); */ } return EAS_ERROR_FILE_FORMAT; } if ((temp != 0x0100) && (temp != 0x0200)) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unsupported FORMAT %02x\n", temp); */ } return EAS_ERROR_UNRECOGNIZED_FORMAT; } break; case TOKEN_VERSION: if (!IMY_GetVersion(pData, &temp)) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid VERSION field '%s'\n", pData->buffer); */ } return EAS_ERROR_FILE_FORMAT; } if ((temp != 0x0100) && (temp != 0x0102)) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unsupported VERSION %02x\n", temp); */ } return EAS_ERROR_UNRECOGNIZED_FORMAT; } break; case TOKEN_NAME: IMY_MetaData(pData, EAS_METADATA_TITLE, pData->buffer + pData->index); break; case TOKEN_COMPOSER: IMY_MetaData(pData, EAS_METADATA_AUTHOR, pData->buffer + pData->index); break; /* handle beat */ case TOKEN_BEAT: IMY_GetNumber(pEASData->hwInstData, pData, &temp, EAS_TRUE); if ((temp >= 25) && (temp <= 900)) pData->tick = TICK_CONVERT / temp; break; /* handle style */ case TOKEN_STYLE: c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE); if (c == 'S') c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE); if ((c >= '0') && (c <= '2')) pData->style = (EAS_U8) (c - '0'); else { PutBackChar(pData); { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error in style command: %s\n", pData->buffer); */ } } break; /* handle volume */ case TOKEN_VOLUME: c = IMY_GetNextChar(pEASData->hwInstData, pData, EAS_TRUE); if (c != 'V') { PutBackChar(pData); if (!IsDigit(c)) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Error in volume command: %s\n", pData->buffer); */ } break; } } IMY_GetVolume(pEASData->hwInstData, pData, EAS_TRUE); break; case TOKEN_MELODY: #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Header successfully parsed\n"); */ } #endif return EAS_SUCCESS; case TOKEN_END: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unexpected END:IMELODY encountered\n"); */ } return EAS_ERROR_FILE_FORMAT; default: /* force a read of the next line */ pData->index = 1; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unrecognized token in iMelody file: %s\n", pData->buffer); */ } break; } } } /*---------------------------------------------------------------------------- * IMY_GetNextChar() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_I8 IMY_GetNextChar (EAS_HW_DATA_HANDLE hwInstData, S_IMELODY_DATA *pData, EAS_BOOL inHeader) { EAS_I8 c; EAS_U8 index; for (;;) { /* get next character */ c = pData->buffer[pData->index++]; /* buffer empty, read more */ if (!c) { /* don't read the next line in the header */ if (inHeader) return 0; pData->index = 0; pData->buffer[0] = 0; if (IMY_ReadLine(hwInstData, pData->fileHandle, pData->buffer, &pData->startLine) != EAS_SUCCESS) { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar: EOF\n"); */ } #endif return 0; } /* check for END:IMELODY token */ if (IMY_ParseLine(pData->buffer, &index) == TOKEN_END) { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar: found END:IMELODY\n"); */ } #endif pData->buffer[0] = 0; return 0; } continue; } /* ignore white space */ if (!IsSpace(c)) { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_GetNextChar returned '%c'\n", c); */ } #endif return c; } } } /*---------------------------------------------------------------------------- * IMY_ReadLine() *---------------------------------------------------------------------------- * Purpose: * Reads a line of input from the file, discarding the CR/LF * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT IMY_ReadLine (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I8 *buffer, EAS_I32 *pStartLine) { EAS_RESULT result; EAS_INT i; EAS_I8 c; /* fetch current file position and save it */ if (pStartLine != NULL) { if ((result = EAS_HWFilePos(hwInstData, fileHandle, pStartLine)) != EAS_SUCCESS) { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseHeader: EAS_HWFilePos returned %d\n", result); */ } #endif return result; } } buffer[0] = 0; for (i = 0; i < MAX_LINE_SIZE; ) { if ((result = EAS_HWGetByte(hwInstData, fileHandle, &c)) != EAS_SUCCESS) { if ((result == EAS_EOF) && (i > 0)) break; return result; } /* return on LF or end of data */ if (c == '\n') break; /* store characters in buffer */ if (c != '\r') buffer[i++] = c; } buffer[i] = 0; #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ReadLine read %s\n", buffer); */ } #endif return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * IMY_ParseLine() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_INT IMY_ParseLine (EAS_I8 *buffer, EAS_U8 *pIndex) { EAS_INT i; EAS_INT j; /* there's no strnicmp() in stdlib, so we have to roll our own */ for (i = 0; i < TOKEN_INVALID; i++) { for (j = 0; ; j++) { /* end of token, must be a match */ if (tokens[i][j] == 0) { #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseLine found token %d\n", i); */ } #endif *pIndex = (EAS_U8) j; return i; } if (tokens[i][j] != ToUpper(buffer[j])) break; } } #ifdef _DEBUG_IMELODY { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMY_ParseLine: no token found\n"); */ } #endif return TOKEN_INVALID; } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_miditypes.h0000644000000000000000000000013113532747316027123 xustar0030 mtime=1567346382.701999855 29 atime=1567346382.85400005 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_miditypes.h0000644000175000001440000001306713532747316027724 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_miditypes.h * * Contents and purpose: * Contains declarations for the MIDI stream parser. * * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 778 $ * $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_MIDITYPES_H #define _EAS_MIDITYPES_H #include "eas_data.h" #include "eas_parser.h" /*---------------------------------------------------------------------------- * S_MIDI_STREAM * * Maintains parser state for the MIDI stream parser * *---------------------------------------------------------------------------- */ typedef struct s_midi_stream_tag { EAS_BOOL8 byte3; /* flag indicates 3rd byte expected */ EAS_BOOL8 pending; /* flag indicates more data expected */ EAS_U8 sysExState; /* maintains the SysEx state */ EAS_U8 runningStatus; /* last running status received */ EAS_U8 status; /* status byte */ EAS_U8 d1; /* first data byte */ EAS_U8 d2; /* second data byte */ EAS_U8 flags; /* flags - see below for definition */ #ifdef JET_INTERFACE EAS_U32 jetData; /* JET data */ #endif } S_MIDI_STREAM; /* flags for S_MIDI_STREAM.flags */ #define MIDI_FLAG_GM_ON 0x01 /* GM System On message received */ #define MIDI_FLAG_FIRST_NOTE 0x02 /* first note received */ /* flags for S_MIDI_STREAM.jetFlags */ #define MIDI_FLAGS_JET_MUTE 0x00000001 /* track is muted */ #define MIDI_FLAGS_JET_CB 0x00000002 /* JET callback enabled */ /*---------------------------------------------------------------------------- * * S_SMF_STREAM * * This structure contains data required to parse an SMF stream. For SMF0 files, there * will be a single instance of this per file. For SMF1 files, there will be multiple instance, * one for each separate stream in the file. * *---------------------------------------------------------------------------- */ typedef struct s_smf_stream_tag { EAS_FILE_HANDLE fileHandle; /* host wrapper file handle */ EAS_U32 ticks; /* time of next event in stream */ EAS_I32 startFilePos; /* start location of track within file */ S_MIDI_STREAM midiStream; /* MIDI stream state */ } S_SMF_STREAM; /*---------------------------------------------------------------------------- * * S_SMF_DATA * * This structure contains the instance data required to parse an SMF stream. * *---------------------------------------------------------------------------- */ typedef struct s_smf_data_tag { #ifdef _CHECKED_BUILD EAS_U32 handleCheck; /* signature check for checked build */ #endif S_SMF_STREAM *streams; /* pointer to individual streams in file */ S_SMF_STREAM *nextStream; /* pointer to next stream with event */ S_SYNTH *pSynth; /* pointer to synth */ EAS_FILE_HANDLE fileHandle; /* file handle */ S_METADATA_CB metadata; /* metadata callback */ EAS_I32 fileOffset; /* for embedded files */ EAS_I32 time; /* current time in milliseconds/256 */ EAS_U16 numStreams; /* actual number of streams */ EAS_U16 tickConv; /* current MIDI tick to msec conversion */ EAS_U16 ppqn; /* ticks per quarter note */ EAS_U8 state; /* current state EAS_STATE_XXXX */ EAS_U8 flags; /* flags - see definitions below */ } S_SMF_DATA; #define SMF_FLAGS_CHASE_MODE 0x01 /* chase mode - skip to first note */ #define SMF_FLAGS_HAS_TIME_SIG 0x02 /* time signature encountered at time 0 */ #define SMF_FLAGS_HAS_TEMPO 0x04 /* tempo encountered at time 0 */ #define SMF_FLAGS_HAS_GM_ON 0x08 /* GM System On encountered at time 0 */ #define SMF_FLAGS_JET_STREAM 0x80 /* JET in use - keep strict timing */ /* combo flags indicate setup bar */ #define SMF_FLAGS_SETUP_BAR (SMF_FLAGS_HAS_TIME_SIG | SMF_FLAGS_HAS_TEMPO | SMF_FLAGS_HAS_GM_ON) /*---------------------------------------------------------------------------- * Interactive MIDI structure *---------------------------------------------------------------------------- */ typedef struct s_interactive_midi_tag { #ifdef _CHECKED_BUILD EAS_U32 handleCheck; /* signature check for checked build */ #endif S_SYNTH *pSynth; /* pointer to synth */ S_MIDI_STREAM stream; /* stream data */ } S_INTERACTIVE_MIDI; #endif /* #ifndef _EAS_MIDITYPES_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_pcmdata.c0000644000000000000000000000013113532747316026520 xustar0030 mtime=1567346382.705999859 29 atime=1567346382.85400005 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_pcmdata.c0000644000175000001440000000217013532747316027312 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_pcmdata.c * * Contents and purpose: * Contains the static data for the PCM engine. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 547 $ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ *---------------------------------------------------------------------------- */ #include "eas_data.h" /* static data allocation */ S_PCM_STATE eas_PCMData[MAX_PCM_STREAMS]; drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_audioconst.h0000644000000000000000000000013113532747316027264 xustar0030 mtime=1567346382.701999855 29 atime=1567346382.85400005 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_audioconst.h0000644000175000001440000000671313532747316030065 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_audioconst.h * * Contents and purpose: * Defines audio constants related to the sample rate, bit size, etc. * * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_AUDIOCONST_H #define _EAS_AUDIOCONST_H /*---------------------------------------------------------------------------- * These macros define the various characteristics of the defined sample rates *---------------------------------------------------------------------------- * BUFFER_SIZE_IN_MONO_SAMPLES size of buffer in samples * _OUTPUT_SAMPLE_RATE compiled output sample rate * AUDIO_FRAME_LENGTH length of an audio frame in 256ths of a millisecond * SYNTH_UPDATE_PERIOD_IN_BITS length of an audio frame (2^x samples) *---------------------------------------------------------------------------- */ #if defined (_SAMPLE_RATE_8000) #define BUFFER_SIZE_IN_MONO_SAMPLES 32 #define _OUTPUT_SAMPLE_RATE 8000 #define AUDIO_FRAME_LENGTH 1024 #define SYNTH_UPDATE_PERIOD_IN_BITS 5 #elif defined (_SAMPLE_RATE_16000) #define BUFFER_SIZE_IN_MONO_SAMPLES 64 #define _OUTPUT_SAMPLE_RATE 16000 #define AUDIO_FRAME_LENGTH 1024 #define SYNTH_UPDATE_PERIOD_IN_BITS 6 #elif defined (_SAMPLE_RATE_20000) #define BUFFER_SIZE_IN_MONO_SAMPLES 128 #define _OUTPUT_SAMPLE_RATE 20000 #define AUDIO_FRAME_LENGTH 1638 #define SYNTH_UPDATE_PERIOD_IN_BITS 7 #elif defined (_SAMPLE_RATE_22050) #define BUFFER_SIZE_IN_MONO_SAMPLES 128 #define _OUTPUT_SAMPLE_RATE 22050 #define AUDIO_FRAME_LENGTH 1486 #define SYNTH_UPDATE_PERIOD_IN_BITS 7 #elif defined (_SAMPLE_RATE_24000) #define BUFFER_SIZE_IN_MONO_SAMPLES 128 #define _OUTPUT_SAMPLE_RATE 24000 #define AUDIO_FRAME_LENGTH 1365 #define SYNTH_UPDATE_PERIOD_IN_BITS 7 #elif defined (_SAMPLE_RATE_32000) #define BUFFER_SIZE_IN_MONO_SAMPLES 128 #define _OUTPUT_SAMPLE_RATE 32000 #define AUDIO_FRAME_LENGTH 1024 #define SYNTH_UPDATE_PERIOD_IN_BITS 7 #elif defined (_SAMPLE_RATE_44100) #define BUFFER_SIZE_IN_MONO_SAMPLES 256 #define _OUTPUT_SAMPLE_RATE 44100 #define AUDIO_FRAME_LENGTH 1486 #define SYNTH_UPDATE_PERIOD_IN_BITS 8 #elif defined (_SAMPLE_RATE_48000) #define BUFFER_SIZE_IN_MONO_SAMPLES 256 #define _OUTPUT_SAMPLE_RATE 48000 #define AUDIO_FRAME_LENGTH 1365 #define SYNTH_UPDATE_PERIOD_IN_BITS 8 #else #error "_SAMPLE_RATE_XXXXX must be defined to valid rate" #endif #endif /* #ifndef _EAS_AUDIOCONST_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_mixer.c0000644000000000000000000000013113532747316026233 xustar0030 mtime=1567346382.709999865 29 atime=1567346382.85400005 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_mixer.c0000644000175000001440000003734313532747316027037 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_mixer.c * * Contents and purpose: * This file contains the critical components of the mix engine that * must be optimized for best performance. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 706 $ * $Date: 2007-05-31 17:22:51 -0700 (Thu, 31 May 2007) $ *---------------------------------------------------------------------------- */ //3 dls: This module is in the midst of being converted from a synth //3 specific module to a general purpose mix engine /*------------------------------------ * includes *------------------------------------ */ #include "eas_data.h" #include "eas_host.h" #include "eas_math.h" #include "eas_mixer.h" #include "eas_config.h" #include "eas_report.h" #ifdef _MAXIMIZER_ENABLED EAS_I32 MaximizerProcess (EAS_VOID_PTR pInstData, EAS_I32 *pSrc, EAS_I32 *pDst, EAS_I32 numSamples); #endif /*------------------------------------ * defines *------------------------------------ */ /* need to boost stereo by ~3dB to compensate for the panner */ #define STEREO_3DB_GAIN_BOOST 512 /*---------------------------------------------------------------------------- * EAS_MixEngineInit() *---------------------------------------------------------------------------- * Purpose: * Prepares the mix engine for work, allocates buffers, locates effects modules, etc. * * Inputs: * pEASData - instance data * pInstData - pointer to variable to receive instance data handle * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_MixEngineInit (S_EAS_DATA *pEASData) { /* check Configuration Module for mix buffer allocation */ if (pEASData->staticMemoryModel) pEASData->pMixBuffer = EAS_CMEnumData(EAS_CM_MIX_BUFFER); else pEASData->pMixBuffer = EAS_HWMalloc(pEASData->hwInstData, BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS * sizeof(EAS_I32)); if (pEASData->pMixBuffer == NULL) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate mix buffer memory\n"); */ } return EAS_ERROR_MALLOC_FAILED; } EAS_HWMemSet((void *)(pEASData->pMixBuffer), 0, BUFFER_SIZE_IN_MONO_SAMPLES * NUM_OUTPUT_CHANNELS * sizeof(EAS_I32)); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_MixEnginePrep() *---------------------------------------------------------------------------- * Purpose: * Performs prep before synthesize a buffer of audio, such as clearing * audio buffers, etc. * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ void EAS_MixEnginePrep (S_EAS_DATA *pEASData, EAS_I32 numSamples) { /* clear the mix buffer */ #if (NUM_OUTPUT_CHANNELS == 2) EAS_HWMemSet(pEASData->pMixBuffer, 0, numSamples * (EAS_I32) sizeof(long) * 2); #else EAS_HWMemSet(pEASData->pMixBuffer, 0, (EAS_I32) numSamples * (EAS_I32) sizeof(long)); #endif /* need to clear other side-chain effect buffers (chorus & reverb) */ } /*---------------------------------------------------------------------------- * EAS_MixEnginePost *---------------------------------------------------------------------------- * Purpose: * This routine does the post-processing after all voices have been * synthesized. It calls any sweeteners and does the final mixdown to * the output buffer. * * Inputs: * * Outputs: * * Notes: *---------------------------------------------------------------------------- */ void EAS_MixEnginePost (S_EAS_DATA *pEASData, EAS_I32 numSamples) { EAS_U16 gain; //3 dls: Need to restore the mix engine metrics /* calculate the gain multiplier */ #ifdef _MAXIMIZER_ENABLED if (pEASData->effectsModules[EAS_MODULE_MAXIMIZER].effect) { EAS_I32 temp; temp = MaximizerProcess(pEASData->effectsModules[EAS_MODULE_MAXIMIZER].effectData, pEASData->pMixBuffer, pEASData->pMixBuffer, numSamples); temp = (temp * pEASData->masterGain) >> 15; if (temp > 32767) gain = 32767; else gain = (EAS_U16) temp; } else gain = (EAS_U16) pEASData->masterGain; #else gain = (EAS_U16) pEASData->masterGain; #endif /* Not using all the gain bits for now * Reduce the input to the compressor by 6dB to prevent saturation */ #ifdef _COMPRESSOR_ENABLED if (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData) gain = gain >> 5; else gain = gain >> 4; #else gain = gain >> 4; #endif /* convert 32-bit mix buffer to 16-bit output format */ #if (NUM_OUTPUT_CHANNELS == 2) SynthMasterGain(pEASData->pMixBuffer, pEASData->pOutputAudioBuffer, gain, (EAS_U16) ((EAS_U16) numSamples * 2)); #else SynthMasterGain(pEASData->pMixBuffer, pEASData->pOutputAudioBuffer, gain, (EAS_U16) numSamples); #endif #ifdef _ENHANCER_ENABLED /* enhancer effect */ if (pEASData->effectsModules[EAS_MODULE_ENHANCER].effectData) (*pEASData->effectsModules[EAS_MODULE_ENHANCER].effect->pfProcess) (pEASData->effectsModules[EAS_MODULE_ENHANCER].effectData, pEASData->pOutputAudioBuffer, pEASData->pOutputAudioBuffer, numSamples); #endif #ifdef _GRAPHIC_EQ_ENABLED /* graphic EQ effect */ if (pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effectData) (*pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effect->pfProcess) (pEASData->effectsModules[EAS_MODULE_GRAPHIC_EQ].effectData, pEASData->pOutputAudioBuffer, pEASData->pOutputAudioBuffer, numSamples); #endif #ifdef _COMPRESSOR_ENABLED /* compressor effect */ if (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData) (*pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effect->pfProcess) (pEASData->effectsModules[EAS_MODULE_COMPRESSOR].effectData, pEASData->pOutputAudioBuffer, pEASData->pOutputAudioBuffer, numSamples); #endif #ifdef _WOW_ENABLED /* WOW requires a 32-bit buffer, borrow the mix buffer and * pass it as the destination buffer */ /*lint -e{740} temporarily passing a parameter through an existing I/F */ if (pEASData->effectsModules[EAS_MODULE_WOW].effectData) (*pEASData->effectsModules[EAS_MODULE_WOW].effect->pfProcess) (pEASData->effectsModules[EAS_MODULE_WOW].effectData, pEASData->pOutputAudioBuffer, (EAS_PCM*) pEASData->pMixBuffer, numSamples); #endif #ifdef _TONECONTROLEQ_ENABLED /* ToneControlEQ effect */ if (pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effectData) (*pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effect->pfProcess) (pEASData->effectsModules[EAS_MODULE_TONECONTROLEQ].effectData, pEASData->pOutputAudioBuffer, pEASData->pOutputAudioBuffer, numSamples); #endif #ifdef _REVERB_ENABLED /* Reverb effect */ if (pEASData->effectsModules[EAS_MODULE_REVERB].effectData) (*pEASData->effectsModules[EAS_MODULE_REVERB].effect->pfProcess) (pEASData->effectsModules[EAS_MODULE_REVERB].effectData, pEASData->pOutputAudioBuffer, pEASData->pOutputAudioBuffer, numSamples); #endif #ifdef _CHORUS_ENABLED /* Chorus effect */ if (pEASData->effectsModules[EAS_MODULE_CHORUS].effectData) (*pEASData->effectsModules[EAS_MODULE_CHORUS].effect->pfProcess) (pEASData->effectsModules[EAS_MODULE_CHORUS].effectData, pEASData->pOutputAudioBuffer, pEASData->pOutputAudioBuffer, numSamples); #endif } #ifndef NATIVE_EAS_KERNEL /*---------------------------------------------------------------------------- * SynthMasterGain *---------------------------------------------------------------------------- * Purpose: * Mixes down audio from 32-bit to 16-bit target buffer * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ void SynthMasterGain (long *pInputBuffer, EAS_PCM *pOutputBuffer, EAS_U16 nGain, EAS_U16 numSamples) { /* loop through the buffer */ while (numSamples--) { long s; /* read a sample from the input buffer and add some guard bits */ s = *pInputBuffer++; /* add some guard bits */ /*lint -e{704} */ s = s >> 7; /* apply master gain */ s *= (long) nGain; /* shift to lower 16-bits */ /*lint -e{704} */ s = s >> 9; /* saturate */ s = SATURATE(s); *pOutputBuffer++ = (EAS_PCM)s; } } #endif /*---------------------------------------------------------------------------- * EAS_MixEngineShutdown() *---------------------------------------------------------------------------- * Purpose: * Shuts down effects modules and deallocates memory * * Inputs: * pEASData - instance data * pInstData - instance data handle * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_MixEngineShutdown (S_EAS_DATA *pEASData) { /* check Configuration Module for static memory allocation */ if (!pEASData->staticMemoryModel && (pEASData->pMixBuffer != NULL)) EAS_HWFree(pEASData->hwInstData, pEASData->pMixBuffer); return EAS_SUCCESS; } #ifdef UNIFIED_MIXER #ifndef NATIVE_MIX_STREAM /*---------------------------------------------------------------------------- * EAS_MixStream *---------------------------------------------------------------------------- * Mix a 16-bit stream into a 32-bit buffer * * pInputBuffer 16-bit input buffer * pMixBuffer 32-bit mix buffer * numSamples number of samples to mix * gainLeft initial gain left or mono * gainRight initial gain right * gainLeft left gain increment per sample * gainRight right gain increment per sample * flags bit 0 = stereo source * bit 1 = stereo output *---------------------------------------------------------------------------- */ void EAS_MixStream (EAS_PCM *pInputBuffer, EAS_I32 *pMixBuffer, EAS_I32 numSamples, EAS_I32 gainLeft, EAS_I32 gainRight, EAS_I32 gainIncLeft, EAS_I32 gainIncRight, EAS_I32 flags) { EAS_I32 temp; EAS_INT src, dest; /* NOTE: There are a lot of optimizations that can be done * in the native implementations based on register * availability, etc. For example, it may make sense to * break this down into 8 separate routines: * * 1. Mono source to mono output * 2. Mono source to stereo output * 3. Stereo source to mono output * 4. Stereo source to stereo output * 5. Mono source to mono output - no gain change * 6. Mono source to stereo output - no gain change * 7. Stereo source to mono output - no gain change * 8. Stereo source to stereo output - no gain change * * Other possibilities include loop unrolling, skipping * a gain calculation every 2 or 4 samples, etc. */ /* no gain change, use fast loops */ if ((gainIncLeft == 0) && (gainIncRight == 0)) { switch (flags & (MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT)) { /* mono to mono */ case 0: gainLeft >>= 15; for (src = dest = 0; src < numSamples; src++, dest++) { pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS; } break; /* mono to stereo */ case MIX_FLAGS_STEREO_OUTPUT: gainLeft >>= 15; gainRight >>= 15; for (src = dest = 0; src < numSamples; src++, dest+=2) { pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS; pMixBuffer[dest+1] += (pInputBuffer[src] * gainRight) >> NUM_MIXER_GUARD_BITS; } break; /* stereo to mono */ case MIX_FLAGS_STEREO_SOURCE: gainLeft >>= 15; gainRight >>= 15; for (src = dest = 0; src < numSamples; src+=2, dest++) { temp = (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS; temp += ((pInputBuffer[src+1] * gainRight) >> NUM_MIXER_GUARD_BITS); pMixBuffer[dest] += temp; } break; /* stereo to stereo */ case MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT: gainLeft >>= 15; gainRight >>= 15; for (src = dest = 0; src < numSamples; src+=2, dest+=2) { pMixBuffer[dest] += (pInputBuffer[src] * gainLeft) >> NUM_MIXER_GUARD_BITS; pMixBuffer[dest+1] += (pInputBuffer[src+1] * gainRight) >> NUM_MIXER_GUARD_BITS; } break; } } /* gain change - do gain increment */ else { switch (flags & (MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT)) { /* mono to mono */ case 0: for (src = dest = 0; src < numSamples; src++, dest++) { gainLeft += gainIncLeft; pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS; } break; /* mono to stereo */ case MIX_FLAGS_STEREO_OUTPUT: for (src = dest = 0; src < numSamples; src++, dest+=2) { gainLeft += gainIncLeft; gainRight += gainIncRight; pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS; pMixBuffer[dest+1] += (pInputBuffer[src] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS; } break; /* stereo to mono */ case MIX_FLAGS_STEREO_SOURCE: for (src = dest = 0; src < numSamples; src+=2, dest++) { gainLeft += gainIncLeft; gainRight += gainIncRight; temp = (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS; temp += ((pInputBuffer[src+1] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS); pMixBuffer[dest] += temp; } break; /* stereo to stereo */ case MIX_FLAGS_STEREO_SOURCE | MIX_FLAGS_STEREO_OUTPUT: for (src = dest = 0; src < numSamples; src+=2, dest+=2) { gainLeft += gainIncLeft; gainRight += gainIncRight; pMixBuffer[dest] += (pInputBuffer[src] * (gainLeft >> 15)) >> NUM_MIXER_GUARD_BITS; pMixBuffer[dest+1] += (pInputBuffer[src+1] * (gainRight >> 15)) >> NUM_MIXER_GUARD_BITS; } break; } } } #endif #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_synth.h0000644000000000000000000000013113532747316026261 xustar0030 mtime=1567346382.709999865 29 atime=1567346382.85400005 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_synth.h0000644000175000001440000003114713532747316027061 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_synth.h * * Contents and purpose: * Declarations, interfaces, and prototypes for synth. * * Copyright Sonic Network Inc. 2004, 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 718 $ * $Date: 2007-06-08 16:43:16 -0700 (Fri, 08 Jun 2007) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_SYNTH_H #define _EAS_SYNTH_H #include "eas_types.h" #include "eas_sndlib.h" #ifdef _WT_SYNTH #include "eas_wtsynth.h" #endif #ifdef _FM_SYNTH #include "eas_fmsynth.h" #endif #ifndef NUM_OUTPUT_CHANNELS #define NUM_OUTPUT_CHANNELS 2 #endif #ifndef MAX_SYNTH_VOICES #define MAX_SYNTH_VOICES 64 #endif #ifndef MAX_VIRTUAL_SYNTHESIZERS #define MAX_VIRTUAL_SYNTHESIZERS 4 #endif /* defines */ #ifndef NUM_PRIMARY_VOICES #define NUM_PRIMARY_VOICES MAX_SYNTH_VOICES #elif !defined(NUM_SECONDARY_VOICES) #define NUM_SECONDARY_VOICES (MAX_SYNTH_VOICES - NUM_PRIMARY_VOICES) #endif #if defined(EAS_WT_SYNTH) #define NUM_WT_VOICES MAX_SYNTH_VOICES /* FM on MCU */ #elif defined(EAS_FM_SYNTH) #define NUM_FM_VOICES MAX_SYNTH_VOICES /* wavetable drums on MCU, wavetable melodic on DSP */ #elif defined(EAS_SPLIT_WT_SYNTH) #define NUM_WT_VOICES MAX_SYNTH_VOICES /* wavetable drums and FM melodic on MCU */ #elif defined(EAS_HYBRID_SYNTH) #define NUM_WT_VOICES NUM_PRIMARY_VOICES #define NUM_FM_VOICES NUM_SECONDARY_VOICES /* wavetable drums on MCU, FM melodic on DSP */ #elif defined(EAS_SPLIT_HYBRID_SYNTH) #define NUM_WT_VOICES NUM_PRIMARY_VOICES #define NUM_FM_VOICES NUM_SECONDARY_VOICES /* FM synth on DSP */ #elif defined(EAS_SPLIT_FM_SYNTH) #define NUM_FM_VOICES MAX_SYNTH_VOICES #else #error "Unrecognized architecture option" #endif #define NUM_SYNTH_CHANNELS 16 #define DEFAULT_SYNTH_VOICES MAX_SYNTH_VOICES /* use the following values to specify unassigned channels or voices */ #define UNASSIGNED_SYNTH_CHANNEL NUM_SYNTH_CHANNELS #define UNASSIGNED_SYNTH_VOICE MAX_SYNTH_VOICES /* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SAMPLES */ #define SYNTH_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(0x1L << SYNTH_UPDATE_PERIOD_IN_BITS) /* stealing weighting factors */ #define NOTE_AGE_STEAL_WEIGHT 1 #define NOTE_GAIN_STEAL_WEIGHT 4 #define CHANNEL_POLY_STEAL_WEIGHT 12 #define CHANNEL_PRIORITY_STEAL_WEIGHT 2 #define NOTE_MATCH_PENALTY 128 #define SYNTH_PRIORITY_WEIGHT 8 /* default synth master volume */ #define DEFAULT_SYNTH_MASTER_VOLUME 0x7fff #define DEFAULT_SYNTH_PRIORITY 5 /* default tuning values */ #define DEFAULT_PITCH_BEND_SENSITIVITY 200 /* 2 semitones */ #define DEFAULT_FINE_PITCH 0 /* 0 cents */ #define DEFAULT_COARSE_PITCH 0 /* 0 semitones */ /* default drum channel is 10, but is internally 9 due to unit offset */ #define DEFAULT_DRUM_CHANNEL 9 /* drum channel can simultaneously play this many voices at most */ #define DEFAULT_CHANNEL_POLYPHONY_LIMIT 2 /* default instrument is acoustic piano */ #define DEFAULT_MELODY_BANK_MSB 0x79 #define DEFAULT_RHYTHM_BANK_MSB 0x78 #define DEFAULT_MELODY_BANK_NUMBER (DEFAULT_MELODY_BANK_MSB << 8) #define DEFAULT_RHYTHM_BANK_NUMBER (DEFAULT_RHYTHM_BANK_MSB << 8) #define DEFAULT_SYNTH_PROGRAM_NUMBER 0 #define DEFAULT_PITCH_BEND 0x2000 /* 0x2000 == (0x40 << 7) | 0x00 */ #define DEFAULT_MOD_WHEEL 0 #define DEFAULT_CHANNEL_VOLUME 0x64 #define DEFAULT_PAN 0x40 /* decimal 64, center */ #ifdef _REVERB #define DEFAULT_REVERB_SEND 40 /* some reverb */ #endif #ifdef _CHORUS #define DEFAULT_CHORUS_SEND 0 /* no chorus */ #endif #define DEFAULT_EAS_FILTER_CUTOFF_FREQUENCY 0 /* EAS synth uses a different default */ #define DEFAULT_FILTER_RESONANCE 0 #define DEFAULT_EXPRESSION 0x7F #define DEFAULT_CHANNEL_PRESSURE 0 #define DEFAULT_REGISTERED_PARAM 0x3FFF #define DEFAULT_CHANNEL_STATIC_GAIN 0 #define DEFAULT_CHANNEL_STATIC_PITCH 0 #define DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS 50 #define DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS 50 #define DEFAULT_KEY_NUMBER 0x69 #define DEFAULT_VELOCITY 0x64 #define DEFAULT_REGION_INDEX 0 #define DEFAULT_ARTICULATION_INDEX 0 #define DEFAULT_VOICE_GAIN 0 #define DEFAULT_AGE 0 #define DEFAULT_SP_MIDI_PRIORITY 16 /* filter defines */ #define DEFAULT_FILTER_ZERO 0 #define FILTER_CUTOFF_MAX_PITCH_CENTS 1919 #define FILTER_CUTOFF_MIN_PITCH_CENTS -4467 #define A5_PITCH_OFFSET_IN_CENTS 6900 /*------------------------------------ * S_SYNTH_CHANNEL data structure *------------------------------------ */ /* S_SYNTH_CHANNEL.m_nFlags */ #define CHANNEL_FLAG_SUSTAIN_PEDAL 0x01 #define CHANNEL_FLAG_MUTE 0x02 #define CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS 0x04 #define CHANNEL_FLAG_RHYTHM_CHANNEL 0x08 #define CHANNEL_FLAG_EXTERNAL_AUDIO 0x10 #define DEFAULT_CHANNEL_FLAGS 0 /* macros for extracting virtual synth and channel numbers */ #define GET_VSYNTH(a) ((a) >> 4) #define GET_CHANNEL(a) ((a) & 15) typedef struct s_synth_channel_tag { /* use static channel parameters to reduce MIPs */ /* parameters shared by multiple voices assigned to same channel */ EAS_I32 staticPitch; /* (pitch bend * pitch sens) + fine pitch */ EAS_I16 staticGain; /* (CC7 * CC11 * master vol)^2 */ EAS_U16 regionIndex; /* index of first region in program */ EAS_U16 bankNum; /* play programs from this bank */ EAS_I16 pitchBend; /* pitch wheel value */ EAS_I16 pitchBendSensitivity; EAS_I16 registeredParam; /* currently selected registered param */ #if defined(_FM_SYNTH) EAS_I16 lfoAmt; /* amount of LFO to apply to voice */ #endif EAS_U8 programNum; /* play this instrument number */ EAS_U8 modWheel; /* CC1 */ EAS_U8 volume; /* CC7 */ EAS_U8 pan; /* CC10 */ EAS_U8 expression; /* CC11 */ /* the following parameters are controlled by RPNs */ EAS_I8 finePitch; EAS_I8 coarsePitch; EAS_U8 channelPressure; /* applied to all voices on a given channel */ EAS_U8 channelFlags; /* bit field channelFlags for */ /* CC64, SP-MIDI channel masking */ EAS_U8 pool; /* SPMIDI channel voice pool */ EAS_U8 mip; /* SPMIDI MIP setting */ #ifdef _REVERB EAS_U8 reverbSend; /* CC91 */ #endif #ifdef _CHORUS EAS_U8 chorusSend; /* CC93 */ #endif } S_SYNTH_CHANNEL; /*------------------------------------ * S_SYNTH_VOICE data structure *------------------------------------ */ /* S_SYNTH_VOICE.m_nFlags */ #define VOICE_FLAG_UPDATE_VOICE_PARAMETERS 0x01 #define VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF 0x02 #define VOICE_FLAG_DEFER_MIDI_NOTE_OFF 0x04 #define VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET 0x08 #define VOICE_FLAG_DEFER_MUTE 0x40 #define DEFAULT_VOICE_FLAGS 0 /* S_SYNTH_VOICE.m_eState */ typedef enum { eVoiceStateFree = 0, eVoiceStateStart, eVoiceStatePlay, eVoiceStateRelease, eVoiceStateMuting, eVoiceStateStolen, eVoiceStateInvalid /* should never be in this state! */ } E_VOICE_STATE; #define DEFAULT_VOICE_STATE eVoiceStateFree typedef struct s_synth_voice_tag { /* These parameters are common to both wavetable and FM * synthesizers. The voice manager should only access this data. * Any other data should be manipulated by the code that is * specific to that synthesizer and reflected back through the * common state data available here. */ EAS_U16 regionIndex; /* index to wave and playback params */ EAS_I16 gain; /* current gain */ EAS_U16 age; /* large value means old note */ EAS_U16 nextRegionIndex; /* index to wave and playback params */ EAS_U8 voiceState; /* current voice state */ EAS_U8 voiceFlags; /* misc flags/bit fields */ EAS_U8 channel; /* this voice plays on this synth channel */ EAS_U8 note; /* 12 <= key number <= 108 */ EAS_U8 velocity; /* 0 <= velocity <= 127 */ EAS_U8 nextChannel; /* play stolen voice on this channel */ EAS_U8 nextNote; /* 12 <= key number <= 108 */ EAS_U8 nextVelocity; /* 0 <= velocity <= 127 */ } S_SYNTH_VOICE; /*------------------------------------ * S_SYNTH data structure * * One instance for each MIDI stream *------------------------------------ */ /* S_SYNTH.m_nFlags */ #define SYNTH_FLAG_RESET_IS_REQUESTED 0x01 #define SYNTH_FLAG_SP_MIDI_ON 0x02 #define SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS 0x04 #define SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING 0x08 #define DEFAULT_SYNTH_FLAGS SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS typedef struct s_synth_tag { struct s_eas_data_tag *pEASData; const S_EAS *pEAS; #ifdef DLS_SYNTHESIZER S_DLS *pDLS; #endif #ifdef EXTERNAL_AUDIO EAS_EXT_PRG_CHG_FUNC cbProgChgFunc; EAS_EXT_EVENT_FUNC cbEventFunc; EAS_VOID_PTR *pExtAudioInstData; #endif S_SYNTH_CHANNEL channels[NUM_SYNTH_CHANNELS]; EAS_I32 totalNoteCount; EAS_U16 maxPolyphony; EAS_U16 numActiveVoices; EAS_U16 masterVolume; EAS_U8 channelsByPriority[NUM_SYNTH_CHANNELS]; EAS_U8 poolCount[NUM_SYNTH_CHANNELS]; EAS_U8 poolAlloc[NUM_SYNTH_CHANNELS]; EAS_U8 synthFlags; EAS_I8 globalTranspose; EAS_U8 vSynthNum; EAS_U8 refCount; EAS_U8 priority; } S_SYNTH; /*------------------------------------ * S_VOICE_MGR data structure * * One instance for each EAS library instance *------------------------------------ */ typedef struct s_voice_mgr_tag { S_SYNTH *pSynth[MAX_VIRTUAL_SYNTHESIZERS]; EAS_PCM voiceBuffer[SYNTH_UPDATE_PERIOD_IN_SAMPLES]; #ifdef _FM_SYNTH EAS_PCM operMixBuffer[SYNTH_UPDATE_PERIOD_IN_SAMPLES]; S_FM_VOICE fmVoices[NUM_FM_VOICES]; #endif #ifdef _WT_SYNTH S_WT_VOICE wtVoices[NUM_WT_VOICES]; #endif #ifdef _REVERB EAS_PCM reverbSendBuffer[NUM_OUTPUT_CHANNELS * SYNTH_UPDATE_PERIOD_IN_SAMPLES]; #endif #ifdef _CHORUS EAS_PCM chorusSendBuffer[NUM_OUTPUT_CHANNELS * SYNTH_UPDATE_PERIOD_IN_SAMPLES]; #endif S_SYNTH_VOICE voices[MAX_SYNTH_VOICES]; EAS_SNDLIB_HANDLE pGlobalEAS; #ifdef DLS_SYNTHESIZER S_DLS *pGlobalDLS; #endif #ifdef _SPLIT_ARCHITECTURE EAS_FRAME_BUFFER_HANDLE pFrameBuffer; #endif #if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) EAS_U16 maxPolyphonyPrimary; EAS_U16 maxPolyphonySecondary; #endif EAS_I32 workload; EAS_I32 maxWorkLoad; EAS_U16 activeVoices; EAS_U16 maxPolyphony; EAS_U16 age; /* limits the number of voice starts in a frame for split architecture */ #ifdef MAX_VOICE_STARTS EAS_U16 numVoiceStarts; #endif } S_VOICE_MGR; #endif /* #ifdef _EAS_SYNTH_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_data.h0000644000000000000000000000013113532747316026025 xustar0030 mtime=1567346382.701999855 29 atime=1567346382.85400005 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_data.h0000644000175000001440000000715513532747316026627 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_data.h * * Contents and purpose: * This header defines all types, to support dynamic allocation of the * memory resources needed for persistent EAS data. * * Copyright 2004 Sonic Network Inc. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 842 $ * $Date: 2007-08-23 14:32:31 -0700 (Thu, 23 Aug 2007) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_DATA_H #define _EAS_DATA_H #define JET_INTERFACE #include "eas_types.h" #include "eas_synthcfg.h" #include "eas.h" #include "eas_audioconst.h" #include "eas_sndlib.h" #include "eas_pcm.h" #include "eas_pcmdata.h" #include "eas_synth.h" #include "eas_miditypes.h" #include "eas_effects.h" #ifdef AUX_MIXER #include "eas_auxmixdata.h" #endif #ifdef JET_INTERFACE #include "jet.h" #endif #ifdef _METRICS_ENABLED #include "eas_perf.h" #endif #ifndef MAX_NUMBER_STREAMS #define MAX_NUMBER_STREAMS 4 #endif /* flags for S_EAS_STREAM */ #define STREAM_FLAGS_PARSED 1 #define STREAM_FLAGS_PAUSE 2 #define STREAM_FLAGS_LOCATE 4 #define STREAM_FLAGS_RESUME 8 /* structure for parsing a stream */ typedef struct s_eas_stream_tag { void *pParserModule; EAS_U32 time; EAS_U32 frameLength; EAS_I32 repeatCount; EAS_VOID_PTR handle; EAS_U8 volume; EAS_BOOL8 streamFlags; } S_EAS_STREAM; /* default master volume is -10dB */ #define DEFAULT_VOLUME 90 #define DEFAULT_STREAM_VOLUME 100 #define DEFAULT_STREAM_GAIN 14622 /* 10 dB of boost available for individual parsers */ #define STREAM_VOLUME_HEADROOM 10 /* amalgamated persistent data type */ typedef struct s_eas_data_tag { #ifdef _CHECKED_BUILD EAS_U32 handleCheck; #endif EAS_HW_DATA_HANDLE hwInstData; S_EFFECTS_MODULE effectsModules[NUM_EFFECTS_MODULES]; #ifdef _METRICS_ENABLED S_METRICS_INTERFACE *pMetricsModule; EAS_VOID_PTR pMetricsData; #endif EAS_I32 *pMixBuffer; EAS_PCM *pOutputAudioBuffer; #ifdef AUX_MIXER S_EAS_AUX_MIXER auxMixer; #endif #ifdef _MAXIMIZER_ENABLED EAS_VOID_PTR pMaximizerData; #endif S_EAS_STREAM streams[MAX_NUMBER_STREAMS]; S_PCM_STATE *pPCMStreams; S_VOICE_MGR *pVoiceMgr; #ifdef JET_INTERFACE JET_DATA_HANDLE jetHandle; #endif EAS_U32 renderTime; EAS_I16 masterGain; EAS_U8 masterVolume; EAS_BOOL8 staticMemoryModel; EAS_BOOL8 searchHeaderFlag; } S_EAS_DATA; #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_mdls.h0000644000000000000000000000013113532747316026053 xustar0030 mtime=1567346382.701999855 29 atime=1567346382.85400005 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_mdls.h0000644000175000001440000002310313532747316026644 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_mdls.h * * Contents and purpose: * Declarations, interfaces, and prototypes for eas_mdls.c * * Copyright Sonic Network Inc. 2004 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- */ #ifndef _EAS_MDLS_H #define _EAS_MDLS_H /*------------------------------------ * includes *------------------------------------ */ #include "eas_data.h" /*------------------------------------ * Some defines for dls.h *------------------------------------ */ #ifndef DWORD #define DWORD EAS_I32 #define FAR #define SHORT EAS_I16 #define USHORT EAS_U16 #define LONG EAS_I32 #define ULONG EAS_U32 #endif /* GUID struct (call it DLSID in case GUID is defined elsewhere) */ typedef struct { EAS_U32 Data1; EAS_U16 Data2; EAS_U16 Data3; EAS_U8 Data4[8]; } DLSID; #define DEFINE_DLSID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) const DLSID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } /*------------------------------------ * defines *------------------------------------ */ /* maximum sample memory for DLS query support */ #ifndef MAX_DLS_MEMORY #define MAX_DLS_MEMORY 65536 #endif /* size of conditional chunk stack */ #ifndef CDL_STACK_SIZE #define CDL_STACK_SIZE 8 #endif /* size of read buffer for sample conversion */ #ifndef SAMPLE_CONVERT_CHUNK_SIZE #define SAMPLE_CONVERT_CHUNK_SIZE 32 #endif #define ZERO_TIME_IN_CENTS -32768 /* Pan calculation macros */ #define PAN_CONVERSION_FACTOR 4129 #define MAX_PAN_VALUE 63 #define MIN_PAN_VALUE -63 /* multiplier to convert time cents to 10-bit fraction log for EAS_LogToLinear16 */ #define TIME_CENTS_TO_LOG2 27962 /* conversion factor sustain level from percent to exponent for LogToLinear16 */ #define SUSTAIN_LOG_CONVERSION_FACTOR 536871 #define SUSTAIN_LOG_CONVERSION_SHIFT 15 /* conversion factor sustain level from percent to EG full scale */ #define SUSTAIN_LINEAR_CONVERSION_FACTOR 1073709 /* conversion factor to convert frame period to decay rate */ #define DECAY_CONVERSION_FACTOR -16 /*---------------------------------------------------------------------------- * These macros define the various characteristics of the defined sample rates *---------------------------------------------------------------------------- * DLS_ATTACK_TIME_CONVERT log offset for conversion from time cents to attack rate * DLS_LFO_FREQUENCY_CONVERT pitch-cents offset for LFO frequency conversion *---------------------------------------------------------------------------- */ #if defined (_SAMPLE_RATE_8000) #define DLS_RATE_CONVERT -9559 #define DLS_LFO_FREQUENCY_CONVERT 5921 #elif defined (_SAMPLE_RATE_16000) #define DLS_RATE_CONVERT -9559 #define DLS_LFO_FREQUENCY_CONVERT 5921 #elif defined (_SAMPLE_RATE_20000) #define DLS_RATE_CONVERT -8745 #define DLS_LFO_FREQUENCY_CONVERT 5108 #elif defined (_SAMPLE_RATE_22050) #define DLS_RATE_CONVERT -8914 #define DLS_LFO_FREQUENCY_CONVERT 5277 #elif defined (_SAMPLE_RATE_24000) #define DLS_RATE_CONVERT -9061 #define DLS_LFO_FREQUENCY_CONVERT 5423 #elif defined (_SAMPLE_RATE_32000) #define DLS_RATE_CONVERT -9559 #define DLS_LFO_FREQUENCY_CONVERT 5921 #elif defined (_SAMPLE_RATE_44100) #define DLS_RATE_CONVERT -8914 #define DLS_LFO_FREQUENCY_CONVERT 5277 #elif defined (_SAMPLE_RATE_48000) #define DLS_RATE_CONVERT -9061 #define DLS_LFO_FREQUENCY_CONVERT 5423 #else #error "_SAMPLE_RATE_XXXXX must be defined to valid rate" #endif /* * FILTER_Q_CONVERSION_FACTOR convers the 0.1dB steps in the DLS * file to our internal 0.75 dB steps. The value is calculated * as follows: * * 32768 / (10 * ) * * FILTER_RESONANCE_NUM_ENTRIES is the number of entries in the table */ #define FILTER_Q_CONVERSION_FACTOR 4369 #define FILTER_RESONANCE_NUM_ENTRIES 31 /* * Multiplier to convert DLS gain units (10ths of a dB) to a * power-of-two exponent for conversion to linear gain using our * piece-wise linear approximator. Note that we ignore the lower * 16-bits of the DLS gain value. The result is a 10-bit fraction * that works with the EAS_LogToLinear16 function. * * DLS_GAIN_FACTOR = (2^18) / (200 * log10(2)) */ #define DLS_GAIN_FACTOR 4354 #define DLS_GAIN_SHIFT 8 /* * Reciprocal of 10 for quick divide by 10's * * DLS_GAIN_FACTOR = (2^18) / (200 * log10(2)) */ #define DLS_DIV_10_FACTOR 3277 #define DLS_DIV_10_SHIFT 16 /* * Multiplier to convert DLS time cents units to a power-of-two * exponent for conversion to absolute time units using our * piece-wise linear approximator. * * DLS_TIME_FACTOR = (2^22) / 1200 */ #define DLS_TIME_FACTOR 3495 #define DLS_TIME_SHIFT 22 /* LFO limits */ #define MAX_LFO_FREQUENCY_IN_HERTZ 20 #define MIN_LFO_FREQUENCY_IN_HERTZ 0.1 #define MAX_LFO_FREQUENCY_IN_PITCHCENTS 1549 #define MIN_LFO_FREQUENCY_IN_PITCHCENTS -7624 #define MAX_LFO_AMPLITUDE_DEPTH 12 /* in dB, DLS2.1 p 31*/ #define MIN_LFO_AMPLITUDE_DEPTH -12 /* in dB, DLS2.1 p 31*/ /* add to pitch cents before pow(2.0, n) to convert to frequency */ #define ABSOLUTE_PITCH_BIAS 238395828 #define A5_PITCH_OFFSET 6900 /* CHUNK_TYPE is a macro that converts the 4 input args into a 32-bit int where argument a is placed at the MSB location and argument d is placed at the LSB location. This is useful for determining the DLS chunk types */ #define CHUNK_TYPE(a,b,c,d) ( \ ( ((EAS_U32)(a) & 0xFF) << 24 ) \ + ( ((EAS_U32)(b) & 0xFF) << 16 ) \ + ( ((EAS_U32)(c) & 0xFF) << 8 ) \ + ( ((EAS_U32)(d) & 0xFF) ) ) #define CHUNK_RIFF CHUNK_TYPE('R','I','F','F') #define CHUNK_DLS CHUNK_TYPE('D','L','S',' ') #define CHUNK_CDL CHUNK_TYPE('c','d','l',' ') #define CHUNK_VERS CHUNK_TYPE('v','e','r','s') #define CHUNK_DLID CHUNK_TYPE('d','l','i','d') #define CHUNK_LIST CHUNK_TYPE('L','I','S','T') #define CHUNK_COLH CHUNK_TYPE('c','o','l','h') #define CHUNK_LINS CHUNK_TYPE('l','i','n','s') #define CHUNK_PTBL CHUNK_TYPE('p','t','b','l') #define CHUNK_WVPL CHUNK_TYPE('w','v','p','l') #define CHUNK_INFO CHUNK_TYPE('I','N','F','O') #define CHUNK_INAM CHUNK_TYPE('I','N','A','M') #define CHUNK_INS CHUNK_TYPE('i','n','s',' ') #define CHUNK_INSH CHUNK_TYPE('i','n','s','h') #define CHUNK_LRGN CHUNK_TYPE('l','r','g','n') #define CHUNK_RGN CHUNK_TYPE('r','g','n',' ') #define CHUNK_RGN2 CHUNK_TYPE('r','g','n','2') #define CHUNK_RGNH CHUNK_TYPE('r','g','n','h') #define CHUNK_WSMP CHUNK_TYPE('w','s','m','p') #define CHUNK_WLNK CHUNK_TYPE('w','l','n','k') #define CHUNK_LART CHUNK_TYPE('l','a','r','t') #define CHUNK_LAR2 CHUNK_TYPE('l','a','r','2') #define CHUNK_ART1 CHUNK_TYPE('a','r','t','1') #define CHUNK_ART2 CHUNK_TYPE('a','r','t','2') #define CHUNK_WAVE CHUNK_TYPE('w','a','v','e') #define CHUNK_FMT CHUNK_TYPE('f','m','t',' ') #define CHUNK_DATA CHUNK_TYPE('d','a','t','a') #define CHUNK_DMPR CHUNK_TYPE('d','m','p','r') #define WAVE_FORMAT_PCM 0x0001 /* Microsoft PCM format, see DLS2.1 p60 */ #define WAVE_FORMAT_EXTENSIBLE 0xffff /* defines for wave table structures */ /* initialize each articulation structure to a harmless state */ /* change art values after we've determined EAS internals */ #define DEFAULT_DLS_FILTER_CUTOFF_FREQUENCY 0x7FFF /* DLS2.1, p 31 means leave filter off */ /**********/ /* define the waves that we expect to generate instead of store */ /* NOTE: our comparison routine converts the input string to lowercase, so the following comparison values should all be in lowercase. */ #define STRING_NOISE "noise" /*------------------------------------ * type definitions *------------------------------------ */ #ifdef _STANDALONE_CONVERTER typedef struct s_dls_params { EAS_INT sampleRate; EAS_INT samplesPerFrame; EAS_INT bitDepth; double ditherLevel; double ditherFilterCoeff; EAS_BOOL compatibility; EAS_BOOL encodeADPCM; } S_DLS_PARAMS; #endif /* function prototypes */ EAS_RESULT DLSParser (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, S_DLS **pDLS); EAS_RESULT DLSCleanup (EAS_HW_DATA_HANDLE hwInstData, S_DLS *pDLS); void DLSAddRef (S_DLS *pDLS); EAS_I16 ConvertDelay (EAS_I32 timeCents); EAS_I16 ConvertRate (EAS_I32 timeCents); #ifdef _STANDALONE_CONVERTER void DLSConvParams (S_DLS_PARAMS *pParams, EAS_BOOL set); #endif #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/jet.c0000644000000000000000000000013113532747316025041 xustar0030 mtime=1567346382.705999859 29 atime=1567346382.85400005 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/jet.c0000644000175000001440000011667013532747316025646 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * jet.c * * Contents and purpose: * Implementation for JET sound engine * * Copyright (c) 2006 Sonic Network Inc. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *---------------------------------------------------------------------------- * Revision Control: * $Revision: 563 $ * $Date: 2007-02-13 20:26:23 -0800 (Tue, 13 Feb 2007) $ *---------------------------------------------------------------------------- */ //#define LOG_NDEBUG 0 #define LOG_TAG "JET_C" //#define DEBUG_JET #include "eas_data.h" #include "eas_smf.h" #include "jet_data.h" #include "eas_host.h" #include "eas_report.h" /* default configuration */ static const S_JET_CONFIG jetDefaultConfig = { JET_EVENT_APP_LOW, JET_EVENT_APP_HIGH }; /* function prototypes */ extern EAS_RESULT EAS_IntSetStrmParam (S_EAS_DATA *pEASData, EAS_HANDLE pStream, EAS_INT param, EAS_I32 value); extern EAS_RESULT EAS_OpenJETStream (EAS_DATA_HANDLE pEASData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_HANDLE *ppStream); extern EAS_RESULT DLSParser (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_DLSLIB_HANDLE *ppDLS); /*---------------------------------------------------------------------------- * JET_ParseEvent() *---------------------------------------------------------------------------- * Returns current status *---------------------------------------------------------------------------- */ EAS_PUBLIC void JET_ParseEvent (EAS_U32 event, S_JET_EVENT *pEvent) { pEvent->segment = (EAS_U8) ((event & JET_EVENT_SEG_MASK) >> JET_EVENT_SEG_SHIFT); pEvent->track = (EAS_U8) ((event & JET_EVENT_TRACK_MASK) >> JET_EVENT_TRACK_SHIFT); pEvent->channel = (EAS_U8) ((event & JET_EVENT_CHAN_MASK) >> JET_EVENT_CHAN_SHIFT); pEvent->controller = (EAS_U8) ((event & JET_EVENT_CTRL_MASK) >> JET_EVENT_CTRL_SHIFT); pEvent->value = (EAS_U8) (event & JET_EVENT_VAL_MASK); } #ifdef DEBUG_JET /*---------------------------------------------------------------------------- * JET_DumpEvent *---------------------------------------------------------------------------- * Advances queue read/write index *---------------------------------------------------------------------------- */ static void JET_DumpEvent (const char *procName, EAS_U32 event) { S_JET_EVENT sEvent; JET_ParseEvent(event, &sEvent); { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "%s: SegID=%d, TrkID=%d, channel=%d, ctrl=%d, val=%d\n", procName, sEvent.segment, sEvent.track, sEvent.channel, sEvent.controller, sEvent.value); */ } } #endif /*---------------------------------------------------------------------------- * JET_IncQueueIndex *---------------------------------------------------------------------------- * Advances queue read/write index *---------------------------------------------------------------------------- */ EAS_INLINE EAS_U8 JET_IncQueueIndex (EAS_U8 index, EAS_U8 queueSize) { if (++index == queueSize) index = 0; return index; } /*---------------------------------------------------------------------------- * JET_WriteQueue *---------------------------------------------------------------------------- * Save event to queue *---------------------------------------------------------------------------- */ EAS_INLINE void JET_WriteQueue (EAS_U32 *pEventQueue, EAS_U8 *pWriteIndex, EAS_U8 readIndex, EAS_U8 queueSize, EAS_U32 event) { EAS_U8 temp; /* check for queue overflow */ temp = JET_IncQueueIndex(*pWriteIndex, queueSize); if (temp == readIndex) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "JET_Event: Event queue overflow --- event ignored!\n"); */ } return; } /* save in queue and advance write index */ pEventQueue[*pWriteIndex] = event; *pWriteIndex = temp; } /*---------------------------------------------------------------------------- * JET_ReadQueue *---------------------------------------------------------------------------- * Read event to queue *---------------------------------------------------------------------------- */ EAS_INLINE EAS_BOOL JET_ReadQueue (EAS_U32 *pEventQueue, EAS_U8 *pReadIndex, EAS_U8 writeIndex, EAS_U8 queueSize, EAS_U32 *pEvent) { /* check for empty queue */ if (*pReadIndex == writeIndex) return EAS_FALSE; /* save in queue and advance write index */ *pEvent = pEventQueue[*pReadIndex]; *pReadIndex = JET_IncQueueIndex(*pReadIndex, queueSize); return EAS_TRUE; } /*---------------------------------------------------------------------------- * JET_NextSegment *---------------------------------------------------------------------------- * Advances segment number *---------------------------------------------------------------------------- */ EAS_INLINE EAS_INT JET_NextSegment (EAS_INT seg_num) { if (++seg_num == SEG_QUEUE_DEPTH) seg_num = 0; return seg_num; } /*---------------------------------------------------------------------------- * JET_PrepareSegment() *---------------------------------------------------------------------------- * Prepare a segment for playback *---------------------------------------------------------------------------- */ static EAS_RESULT JET_PrepareSegment (EAS_DATA_HANDLE easHandle, EAS_I32 queueNum) { EAS_RESULT result; S_JET_SEGMENT *p; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_PrepareSegment: %d\n", queueNum); */ } p = &easHandle->jetHandle->segQueue[queueNum]; result = EAS_Prepare(easHandle, p->streamHandle); if (result != EAS_SUCCESS) return result; /* pause segment - must be triggered by play or end of previous segment */ result = EAS_Pause(easHandle, p->streamHandle); if (result != EAS_SUCCESS) return result; p->state = JET_STATE_READY; /* set calback data */ result = EAS_IntSetStrmParam(easHandle, p->streamHandle, PARSER_DATA_JET_CB, queueNum); if (result != EAS_SUCCESS) return result; /* set DLS collection */ if (p->libNum >= 0) { result = EAS_IntSetStrmParam(easHandle, p->streamHandle, PARSER_DATA_DLS_COLLECTION, (EAS_I32) easHandle->jetHandle->libHandles[p->libNum]); if (result != EAS_SUCCESS) return result; } /* set transposition */ if (p->transpose) { result = EAS_SetTransposition(easHandle, p->streamHandle, p->transpose); if (result != EAS_SUCCESS) return result; } return result; } /*---------------------------------------------------------------------------- * JET_StartPlayback() *---------------------------------------------------------------------------- * Start segment playback *---------------------------------------------------------------------------- */ static EAS_RESULT JET_StartPlayback (EAS_DATA_HANDLE easHandle, EAS_I32 queueNum) { EAS_RESULT result = EAS_SUCCESS; S_JET_SEGMENT *pSeg; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_StartPlayback %d\n", queueNum); */ } /* if next segment is queued, start playback */ pSeg = &easHandle->jetHandle->segQueue[queueNum]; if (pSeg->streamHandle != NULL) { result = EAS_Resume(easHandle, pSeg->streamHandle); easHandle->jetHandle->segQueue[queueNum].state = JET_STATE_PLAYING; /* set mute flags */ if ((result == EAS_SUCCESS) && (pSeg->muteFlags != 0)) result = EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); } return result; } /*---------------------------------------------------------------------------- * JET_CloseSegment *---------------------------------------------------------------------------- * Closes stream associated with a segment *---------------------------------------------------------------------------- */ EAS_INLINE EAS_INT JET_CloseSegment (EAS_DATA_HANDLE easHandle, EAS_INT queueNum) { EAS_RESULT result; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_CloseSegment %d\n", queueNum); */ } /* close the segment */ result = EAS_CloseFile(easHandle, easHandle->jetHandle->segQueue[queueNum].streamHandle); if (result != EAS_SUCCESS) return result; easHandle->jetHandle->segQueue[queueNum].streamHandle = NULL; easHandle->jetHandle->segQueue[queueNum].state = JET_STATE_CLOSED; easHandle->jetHandle->numQueuedSegments--; return result; } /*---------------------------------------------------------------------------- * JetParseInfoChunk() *---------------------------------------------------------------------------- * Parses the JET info chunk *---------------------------------------------------------------------------- */ static EAS_RESULT JetParseInfoChunk (EAS_DATA_HANDLE easHandle, EAS_I32 pos, EAS_I32 chunkSize) { EAS_RESULT result; EAS_U32 infoType; EAS_U32 temp; /* offset to data */ result = EAS_HWFileSeek(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, pos); if (result != EAS_SUCCESS) return result; /* read the entire chunk */ result = EAS_SUCCESS; while ((result == EAS_SUCCESS) && (chunkSize > 0)) { /* get info infoType */ result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &infoType, EAS_TRUE); if (result != EAS_SUCCESS) break; /* get info field */ result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &temp, EAS_FALSE); if (result == EAS_SUCCESS) switch (infoType) { case INFO_NUM_SMF_CHUNKS: if (temp >= JET_MAX_SEGMENTS) { return EAS_ERROR_INCOMPATIBLE_VERSION; } easHandle->jetHandle->numSegments = (EAS_U8) temp; break; case INFO_NUM_DLS_CHUNKS: if (temp >= JET_MAX_DLS_COLLECTIONS) { return EAS_ERROR_INCOMPATIBLE_VERSION; } easHandle->jetHandle->numLibraries = (EAS_U8) temp; break; case INFO_JET_VERSION: /* check major version number */ if ((temp & 0xff000000) != (JET_VERSION & 0xff000000)) return EAS_ERROR_INCOMPATIBLE_VERSION; break; default: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unrecognized JET info type 0x%08x", infoType); */ } break; } chunkSize -= 8; } /* allocate pointers for chunks to follow */ return result; } /*---------------------------------------------------------------------------- * JET_OpenFile() *---------------------------------------------------------------------------- * Opens a JET content file for playback *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_OpenFile (EAS_DATA_HANDLE easHandle, EAS_FILE_LOCATOR locator) { EAS_RESULT result; EAS_U32 chunkType; EAS_I32 pos; EAS_I32 chunkSize; EAS_INT smfChunkNum; EAS_INT dlsChunkNum; EAS_I32 dataSize = 0; /* make lint happy */ /* make sure that we don't have an open file */ if (easHandle->jetHandle->jetFileHandle != NULL) return EAS_ERROR_FILE_ALREADY_OPEN; /* open the media file */ result = EAS_HWOpenFile(easHandle->hwInstData, locator, &easHandle->jetHandle->jetFileHandle, EAS_FILE_READ); if (result != EAS_SUCCESS) return result; /* check header */ result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &chunkType, EAS_TRUE); if (result == EAS_SUCCESS) { if (chunkType != JET_HEADER_TAG) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "File is not JET format\n"); */ } result = EAS_ERROR_UNRECOGNIZED_FORMAT; } } /* get the file data size */ if (result == EAS_SUCCESS) result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &dataSize, EAS_FALSE); /* parse through the file to find contents */ smfChunkNum = dlsChunkNum = 0; pos = chunkSize = 8; while ((result == EAS_SUCCESS) && (pos < dataSize)) { /* offset to chunk data */ result = EAS_HWFileSeek(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, pos); if (result != EAS_SUCCESS) break; /* get chunk size and type */ result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &chunkType, EAS_TRUE); if (result != EAS_SUCCESS) break; result = EAS_HWGetDWord(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &chunkSize, EAS_FALSE); if (result != EAS_SUCCESS) break; pos += 8; switch (chunkType) { case JET_INFO_CHUNK: result = JetParseInfoChunk(easHandle, pos, chunkSize); break; case JET_SMF_CHUNK: if (smfChunkNum < easHandle->jetHandle->numSegments) easHandle->jetHandle->segmentOffsets[smfChunkNum++] = pos; else { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring extraneous SMF chunk"); */ } break; case JET_DLS_CHUNK: if (dlsChunkNum < easHandle->jetHandle->numLibraries) result = DLSParser(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, pos, &easHandle->jetHandle->libHandles[dlsChunkNum++]); else { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring extraneous DLS chunk"); */ } break; case JET_APP_DATA_CHUNK: easHandle->jetHandle->appDataOffset = pos; easHandle->jetHandle->appDataSize = chunkSize; break; case INFO_JET_COPYRIGHT: break; default: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Ignoring unrecognized JET chunk type 0x%08x", chunkType); */ } break; } /* offset to next chunk */ pos += chunkSize; } /* close file if something went wrong */ if (result != EAS_SUCCESS) EAS_HWCloseFile(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle); return result; } /*---------------------------------------------------------------------------- * JET_GetAppData() *---------------------------------------------------------------------------- * Returns location and size of application data in the JET file *---------------------------------------------------------------------------- */ EAS_RESULT JET_GetAppData (EAS_DATA_HANDLE easHandle, EAS_I32 *pAppDataOffset, EAS_I32 *pAppDataSize) { /* check for app chunk */ if (easHandle->jetHandle->appDataSize == 0) { *pAppDataOffset = *pAppDataSize = 0; return EAS_FAILURE; } /* return app data */ *pAppDataOffset = easHandle->jetHandle->appDataOffset; *pAppDataSize = easHandle->jetHandle->appDataSize; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * JET_CloseFile() *---------------------------------------------------------------------------- * Closes a JET content file and releases associated resources *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_CloseFile (EAS_DATA_HANDLE easHandle) { EAS_INT index; EAS_RESULT result = EAS_SUCCESS; /* close open streams */ for (index = 0; index < SEG_QUEUE_DEPTH; index++) { if (easHandle->jetHandle->segQueue[index].streamHandle != NULL) { result = JET_CloseSegment(easHandle, index); if (result != EAS_SUCCESS) break; } } /* close the main file handle */ if ((result == EAS_SUCCESS) && (easHandle->jetHandle->jetFileHandle != NULL)) { result = EAS_HWCloseFile(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle); if (result == EAS_SUCCESS) easHandle->jetHandle->jetFileHandle = NULL; } return result; } /*---------------------------------------------------------------------------- * JET_Init() *---------------------------------------------------------------------------- * Initializes the JET library, allocates memory, etc. Call * JET_Shutdown to de-allocate memory. *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_Init (EAS_DATA_HANDLE easHandle, const S_JET_CONFIG *pConfig, EAS_INT configSize) { S_JET_DATA *pJet; EAS_U8 flags = 0; /* sanity check */ if (easHandle == NULL) return EAS_ERROR_HANDLE_INTEGRITY; if (easHandle->jetHandle != NULL) return EAS_ERROR_FEATURE_ALREADY_ACTIVE; if (pConfig == NULL) pConfig = &jetDefaultConfig; /* allocate the JET data object */ pJet = EAS_HWMalloc(easHandle->hwInstData, sizeof(S_JET_DATA)); if (pJet == NULL) return EAS_ERROR_MALLOC_FAILED; /* initialize JET data structure */ EAS_HWMemSet(pJet, 0, sizeof(S_JET_DATA)); easHandle->jetHandle = pJet; pJet->flags = flags; /* copy config data */ if (configSize > (EAS_INT) sizeof(S_JET_CONFIG)) configSize = sizeof(S_JET_CONFIG); EAS_HWMemCpy(&pJet->config, pConfig, configSize); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * JET_Shutdown() *---------------------------------------------------------------------------- * Frees any memory used by the JET library *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_Shutdown (EAS_DATA_HANDLE easHandle) { EAS_RESULT result; /* close any open files */ result = JET_CloseFile(easHandle); /* free allocated data */ EAS_HWFree(easHandle->hwInstData, easHandle->jetHandle); easHandle->jetHandle = NULL; return result; } /*---------------------------------------------------------------------------- * JET_Status() *---------------------------------------------------------------------------- * Returns current status *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_Status (EAS_DATA_HANDLE easHandle, S_JET_STATUS *pStatus) { S_JET_SEGMENT *pSeg; pSeg = &easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment]; if (pSeg->streamHandle != NULL) { pStatus->currentUserID = pSeg->userID; pStatus->segmentRepeatCount = pSeg->repeatCount; } else { pStatus->currentUserID = -1; pStatus->segmentRepeatCount = 0; } pStatus->paused = !(easHandle->jetHandle->flags & JET_FLAGS_PLAYING); pStatus->numQueuedSegments = easHandle->jetHandle->numQueuedSegments; pStatus->currentPlayingSegment = easHandle->jetHandle->playSegment; pStatus->currentQueuedSegment = easHandle->jetHandle->queueSegment; if (pSeg->streamHandle != NULL) { EAS_RESULT result; EAS_I32 location ; if ((result = EAS_GetLocation(easHandle, pSeg->streamHandle, &location)) == EAS_SUCCESS) if(location != 0) { pStatus->location = location; } } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * JET_GetEvent() *---------------------------------------------------------------------------- * Checks for application events *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_BOOL JET_GetEvent (EAS_DATA_HANDLE easHandle, EAS_U32 *pEventRaw, S_JET_EVENT *pEvent) { EAS_U32 jetEvent; EAS_BOOL gotEvent; /* process event queue */ gotEvent = JET_ReadQueue(easHandle->jetHandle->appEventQueue, &easHandle->jetHandle->appEventQueueRead, easHandle->jetHandle->appEventQueueWrite, APP_EVENT_QUEUE_SIZE, &jetEvent); if (gotEvent) { if (pEventRaw != NULL) *pEventRaw = jetEvent; if (pEvent != NULL) JET_ParseEvent(jetEvent, pEvent); } return gotEvent; } /*---------------------------------------------------------------------------- * JET_QueueSegment() *---------------------------------------------------------------------------- * Queue a segment for playback *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_QueueSegment (EAS_DATA_HANDLE easHandle, EAS_INT segmentNum, EAS_INT libNum, EAS_INT repeatCount, EAS_INT transpose, EAS_U32 muteFlags, EAS_U8 userID) { EAS_FILE_HANDLE fileHandle; EAS_RESULT result; S_JET_SEGMENT *p; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_QueueSegment segNum=%d, queue=%d\n", segmentNum, easHandle->jetHandle->queueSegment); */ } /* make sure it's a valid segment */ if (segmentNum >= easHandle->jetHandle->numSegments) return EAS_ERROR_PARAMETER_RANGE; /* make sure it's a valid DLS */ if (libNum >= easHandle->jetHandle->numLibraries) return EAS_ERROR_PARAMETER_RANGE; /* check to see if queue is full */ p = &easHandle->jetHandle->segQueue[easHandle->jetHandle->queueSegment]; if (p->streamHandle != NULL) return EAS_ERROR_QUEUE_IS_FULL; /* initialize data */ p->userID = userID; p->repeatCount = (EAS_I16) repeatCount; p->transpose = (EAS_I8) transpose; p->libNum = (EAS_I8) libNum; p->muteFlags = muteFlags; p->state = JET_STATE_CLOSED; /* open the file */ result = EAS_OpenJETStream(easHandle, easHandle->jetHandle->jetFileHandle, easHandle->jetHandle->segmentOffsets[segmentNum], &p->streamHandle); if (result != EAS_SUCCESS) return result; p->state = JET_STATE_OPEN; /* if less than SEG_QUEUE_DEPTH segments queued up, prepare file for playback */ if (++easHandle->jetHandle->numQueuedSegments < SEG_QUEUE_DEPTH) { result = JET_PrepareSegment(easHandle, easHandle->jetHandle->queueSegment); if (result != EAS_SUCCESS) return result; } /* create duplicate file handle */ result = EAS_HWDupHandle(easHandle->hwInstData, easHandle->jetHandle->jetFileHandle, &fileHandle); if (result != EAS_SUCCESS) return result; easHandle->jetHandle->jetFileHandle = fileHandle; easHandle->jetHandle->queueSegment = (EAS_U8) JET_NextSegment(easHandle->jetHandle->queueSegment); return result; } /*---------------------------------------------------------------------------- * JET_Play() *---------------------------------------------------------------------------- * Starts playback of the file *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_Play (EAS_DATA_HANDLE easHandle) { EAS_RESULT result; EAS_INT index; EAS_INT count = 0; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Play\n"); */ } /* sanity check */ if (easHandle->jetHandle->flags & JET_FLAGS_PLAYING) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; /* resume all paused streams */ for (index = 0; index < SEG_QUEUE_DEPTH; index++) { if (((index == easHandle->jetHandle->playSegment) && (easHandle->jetHandle->segQueue[index].state == JET_STATE_READY)) || (easHandle->jetHandle->segQueue[index].state == JET_STATE_PAUSED)) { result = JET_StartPlayback(easHandle, index); if (result != EAS_SUCCESS) return result; count++; } } /* if no streams are playing, return error */ if (!count) return EAS_ERROR_QUEUE_IS_EMPTY; easHandle->jetHandle->flags |= JET_FLAGS_PLAYING; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * JET_Pause() *---------------------------------------------------------------------------- * Pauses playback of the file *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_Pause (EAS_DATA_HANDLE easHandle) { EAS_RESULT result; EAS_INT index; EAS_INT count = 0; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Pause\n"); */ } /* sanity check */ if ((easHandle->jetHandle->flags & JET_FLAGS_PLAYING) == 0) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; /* pause all playing streams */ for (index = 0; index < SEG_QUEUE_DEPTH; index++) { if (easHandle->jetHandle->segQueue[index].state == JET_STATE_PLAYING) { result = EAS_Pause(easHandle, easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment].streamHandle); if (result != EAS_SUCCESS) return result; easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment].state = JET_STATE_PAUSED; count++; } } /* if no streams are paused, return error */ if (!count) return EAS_ERROR_QUEUE_IS_EMPTY; easHandle->jetHandle->flags &= ~JET_FLAGS_PLAYING; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * JET_SetMuteFlags() *---------------------------------------------------------------------------- * Change the state of the mute flags *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_SetMuteFlags (EAS_DATA_HANDLE easHandle, EAS_U32 muteFlags, EAS_BOOL sync) { S_JET_SEGMENT *pSeg; /* get pointer to current segment */ pSeg = &easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment]; /* unsynchronized mute, set flags and return */ if (!sync) { if (pSeg->streamHandle == NULL) return EAS_ERROR_QUEUE_IS_EMPTY; pSeg->muteFlags = muteFlags; return EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) muteFlags); } /* check for valid stream state */ if (pSeg->state == JET_STATE_CLOSED) return EAS_ERROR_QUEUE_IS_EMPTY; /* save mute flags */ pSeg->muteFlags = muteFlags; /* if repeating segment, set mute update flag */ if (sync) pSeg->flags |= JET_SEG_FLAG_MUTE_UPDATE; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * JET_SetMuteFlag() *---------------------------------------------------------------------------- * Change the state of a single mute flag *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_SetMuteFlag (EAS_DATA_HANDLE easHandle, EAS_INT trackNum, EAS_BOOL muteFlag, EAS_BOOL sync) { S_JET_SEGMENT *pSeg; EAS_U32 trackMuteFlag; /* setup flag */ if ((trackNum < 0) || (trackNum > 31)) return EAS_ERROR_PARAMETER_RANGE; trackMuteFlag = (1 << trackNum); /* get pointer to current segment */ pSeg = &easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment]; /* unsynchronized mute, set flags and return */ if (!sync) { if (pSeg->streamHandle == NULL) return EAS_ERROR_QUEUE_IS_EMPTY; if (muteFlag) pSeg->muteFlags |= trackMuteFlag; else pSeg->muteFlags &= ~trackMuteFlag; return EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); } /* check for valid stream state */ if (pSeg->state == JET_STATE_CLOSED) return EAS_ERROR_QUEUE_IS_EMPTY; /* save mute flags and set mute update flag */ if (muteFlag) pSeg->muteFlags |= trackMuteFlag; else pSeg->muteFlags &= ~trackMuteFlag; pSeg->flags |= JET_SEG_FLAG_MUTE_UPDATE; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * JET_TriggerClip() *---------------------------------------------------------------------------- * Unmute a track and then mute it when it is complete. If a clip * is already playing, change mute event to a trigger event. The * JET_Event function will not mute the clip, but will allow it * to continue playing through the next clip. * * NOTE: We use bit 7 to indicate an entry in the queue. For a * small queue, it is cheaper in both memory and CPU cycles to * scan the entire queue for non-zero events than keep enqueue * and dequeue indices. *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_TriggerClip (EAS_DATA_HANDLE easHandle, EAS_INT clipID) { EAS_INT i; EAS_INT index = -1; /* check for valid clipID */ if ((clipID < 0) || (clipID > 63)) return EAS_ERROR_PARAMETER_RANGE; /* set active flag */ clipID |= JET_CLIP_ACTIVE_FLAG; /* Reverse the search so that we get the first empty element */ for (i = JET_MUTE_QUEUE_SIZE-1; i >= 0 ; i--) { if (easHandle->jetHandle->muteQueue[i] == clipID) { index = i; break; } if (easHandle->jetHandle->muteQueue[i] == 0) index = i; } if (index < 0) return EAS_ERROR_QUEUE_IS_FULL; easHandle->jetHandle->muteQueue[index] = (EAS_U8) clipID | JET_CLIP_TRIGGER_FLAG; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * JET_Process() *---------------------------------------------------------------------------- * Called during EAS_Render to process stream states *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_Process (EAS_DATA_HANDLE easHandle) { S_JET_SEGMENT *pSeg; EAS_STATE state; EAS_INT index; EAS_INT playIndex; EAS_RESULT result = EAS_SUCCESS; EAS_BOOL endOfLoop = EAS_FALSE; EAS_BOOL startNextSegment = EAS_FALSE; EAS_BOOL prepareNextSegment = EAS_FALSE; EAS_U32 jetEvent; /* process event queue */ while (JET_ReadQueue(easHandle->jetHandle->jetEventQueue, &easHandle->jetHandle->jetEventQueueRead, easHandle->jetHandle->jetEventQueueWrite, JET_EVENT_QUEUE_SIZE, &jetEvent)) { S_JET_EVENT event; #ifdef DEBUG_JET JET_DumpEvent("JET_Process", jetEvent); #endif JET_ParseEvent(jetEvent, &event); /* check for end of loop */ if ((event.controller == JET_EVENT_MARKER) && (event.value == JET_MARKER_LOOP_END) && (easHandle->jetHandle->segQueue[easHandle->jetHandle->playSegment].streamHandle != NULL)) endOfLoop = EAS_TRUE; } /* check state of all streams */ index = playIndex = easHandle->jetHandle->playSegment; for (;;) { pSeg = &easHandle->jetHandle->segQueue[index]; if (pSeg->state != JET_STATE_CLOSED) { /* get playback state */ result = EAS_State(easHandle, pSeg->streamHandle, &state); if (result != EAS_SUCCESS) return result; /* process state */ switch (pSeg->state) { /* take action if this segment is stopping */ case JET_STATE_PLAYING: if (endOfLoop || (state == EAS_STATE_STOPPING) || (state == EAS_STATE_STOPPED)) { /* handle repeats */ if (pSeg->repeatCount != 0) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Render repeating segment %d\n", index); */ } result = EAS_Locate(easHandle, pSeg->streamHandle, 0, EAS_FALSE); if (result != EAS_SUCCESS) return result; if (pSeg->repeatCount > 0) pSeg->repeatCount--; /* update mute flags if necessary */ if (pSeg->flags & JET_SEG_FLAG_MUTE_UPDATE) { result = EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); if (result != EAS_SUCCESS) return result; pSeg->flags &= ~JET_SEG_FLAG_MUTE_UPDATE; } } /* no repeat, start next segment */ else { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Render stopping queue %d\n", index); */ } startNextSegment = EAS_TRUE; pSeg->state = JET_STATE_STOPPING; easHandle->jetHandle->playSegment = (EAS_U8) JET_NextSegment(index); } } break; /* if playback has stopped, close the segment */ case JET_STATE_STOPPING: if (state == EAS_STATE_STOPPED) { result = JET_CloseSegment(easHandle, index); if (result != EAS_SUCCESS) return result; } break; case JET_STATE_READY: if (startNextSegment) { result = JET_StartPlayback(easHandle, index); if (result != EAS_SUCCESS) return result; startNextSegment = EAS_FALSE; prepareNextSegment = EAS_TRUE; } break; case JET_STATE_OPEN: if (prepareNextSegment) { result = JET_PrepareSegment(easHandle, index); if (result != EAS_SUCCESS) return result; prepareNextSegment = EAS_FALSE; } break; case JET_STATE_PAUSED: break; default: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "JET_Render: Unexpected segment state %d\n", pSeg->state); */ } break; } } /* increment index */ index = JET_NextSegment(index); if (index == playIndex) break; } /* if out of segments, clear playing flag */ if (easHandle->jetHandle->numQueuedSegments == 0) easHandle->jetHandle->flags &= ~JET_FLAGS_PLAYING; return result; } /*---------------------------------------------------------------------------- * JET_Event() *---------------------------------------------------------------------------- * Called from MIDI parser when data of interest is received *---------------------------------------------------------------------------- */ void JET_Event (EAS_DATA_HANDLE easHandle, EAS_U32 segTrack, EAS_U8 channel, EAS_U8 controller, EAS_U8 value) { EAS_U32 event; if (easHandle->jetHandle == NULL) return; /* handle triggers */ if (controller == JET_EVENT_TRIGGER_CLIP) { S_JET_SEGMENT *pSeg; EAS_INT i; EAS_U32 muteFlag; for (i = 0; i < JET_MUTE_QUEUE_SIZE; i++) { /* search for event in queue */ if ((easHandle->jetHandle->muteQueue[i] & JET_CLIP_ID_MASK) == (value & JET_CLIP_ID_MASK)) { /* get segment pointer and mute flag */ pSeg = &easHandle->jetHandle->segQueue[segTrack >> JET_EVENT_SEG_SHIFT]; muteFlag = 1 << ((segTrack & JET_EVENT_TRACK_MASK) >> JET_EVENT_TRACK_SHIFT); /* un-mute the track */ if ((easHandle->jetHandle->muteQueue[i] & JET_CLIP_TRIGGER_FLAG) && ((value & 0x40) > 0)) { pSeg->muteFlags &= ~muteFlag; easHandle->jetHandle->muteQueue[i] &= ~JET_CLIP_TRIGGER_FLAG; } /* mute the track */ else { EAS_U32 beforeMute ; beforeMute = pSeg->muteFlags ; pSeg->muteFlags |= muteFlag; if (beforeMute != pSeg->muteFlags) easHandle->jetHandle->muteQueue[i] = 0; } EAS_IntSetStrmParam(easHandle, pSeg->streamHandle, PARSER_DATA_MUTE_FLAGS, (EAS_I32) pSeg->muteFlags); return; } } return; } /* generic event stuff */ event = (channel << JET_EVENT_CHAN_SHIFT) | (controller << JET_EVENT_CTRL_SHIFT) | value; /* write to app queue, translate queue index to segment number */ if ((controller >= easHandle->jetHandle->config.appEventRangeLow) && (controller <= easHandle->jetHandle->config.appEventRangeHigh)) { event |= easHandle->jetHandle->segQueue[(segTrack & JET_EVENT_SEG_MASK) >> JET_EVENT_SEG_SHIFT].userID << JET_EVENT_SEG_SHIFT; #ifdef DEBUG_JET JET_DumpEvent("JET_Event[app]", event); #endif JET_WriteQueue(easHandle->jetHandle->appEventQueue, &easHandle->jetHandle->appEventQueueWrite, easHandle->jetHandle->appEventQueueRead, APP_EVENT_QUEUE_SIZE, event); } /* write to JET queue */ else if ((controller >= JET_EVENT_LOW) && (controller <= JET_EVENT_HIGH)) { event |= segTrack; #ifdef DEBUG_JET JET_DumpEvent("JET_Event[jet]", event); #endif JET_WriteQueue(easHandle->jetHandle->jetEventQueue, &easHandle->jetHandle->jetEventQueueWrite, easHandle->jetHandle->jetEventQueueRead, JET_EVENT_QUEUE_SIZE, event); } } /*---------------------------------------------------------------------------- * JET_Clear_Queue() *---------------------------------------------------------------------------- * Clears the queue and stops play without a complete shutdown *---------------------------------------------------------------------------- */ EAS_RESULT JET_Clear_Queue(EAS_DATA_HANDLE easHandle) { EAS_INT index; EAS_RESULT result = EAS_SUCCESS; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "JET_Clear_Queue\n"); */ } /* pause all playing streams */ for (index = 0; index < SEG_QUEUE_DEPTH; index++) { if (easHandle->jetHandle->segQueue[index].state == JET_STATE_PLAYING) { result = EAS_Pause(easHandle, easHandle->jetHandle->segQueue[index].streamHandle); if (result != EAS_SUCCESS) return result; easHandle->jetHandle->segQueue[index].state = JET_STATE_PAUSED; } } /* close all streams */ for (index = 0; index < SEG_QUEUE_DEPTH; index++) { if (easHandle->jetHandle->segQueue[index].streamHandle != NULL) { result = JET_CloseSegment(easHandle, index); if (result != EAS_SUCCESS) return result; } } /* clear all clips */ for (index = 0; index < JET_MUTE_QUEUE_SIZE ; index++) { easHandle->jetHandle->muteQueue[index] = 0; } easHandle->jetHandle->flags &= ~JET_FLAGS_PLAYING; easHandle->jetHandle->playSegment = easHandle->jetHandle->queueSegment = 0; return result; } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/jet_data.h0000644000000000000000000000013113532747316026037 xustar0030 mtime=1567346382.709999865 29 atime=1567346382.85400005 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/jet_data.h0000644000175000001440000001410513532747316026632 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * jet_data.h * * Contents and purpose: * Internal data structures and interfaces for JET * * Copyright (c) 2006 Sonic Network Inc. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *---------------------------------------------------------------------------- * Revision Control: * $Revision: 554 $ * $Date: 2007-02-02 11:06:10 -0800 (Fri, 02 Feb 2007) $ *---------------------------------------------------------------------------- */ #ifndef _JET_DATA_H #define _JET_DATA_H #include "eas.h" #include "jet.h" /* maximum number of segments allowed in a JET file */ #ifndef JET_MAX_SEGMENTS #define JET_MAX_SEGMENTS 32 #endif /* maximum number of DLS collections allowed in a JET file */ #ifndef JET_MAX_DLS_COLLECTIONS #define JET_MAX_DLS_COLLECTIONS 4 #endif /* maximum number of JET events in internal queue */ #ifndef JET_EVENT_QUEUE_SIZE #define JET_EVENT_QUEUE_SIZE 32 #endif /* maximum number of JET events in application queue */ #ifndef APP_EVENT_QUEUE_SIZE #define APP_EVENT_QUEUE_SIZE 32 #endif /* maximum number of active mute events */ #ifndef JET_MUTE_QUEUE_SIZE #define JET_MUTE_QUEUE_SIZE 8 #endif /*---------------------------------------------------------------------------- * JET event definitions *---------------------------------------------------------------------------- */ #define JET_EVENT_APP_LOW 80 #define JET_EVENT_APP_HIGH 83 #define JET_EVENT_LOW 102 #define JET_EVENT_HIGH 119 #define JET_EVENT_MARKER 102 #define JET_EVENT_TRIGGER_CLIP 103 #define JET_MARKER_LOOP_END 0 #define JET_CLIP_ACTIVE_FLAG 0x80 #define JET_CLIP_TRIGGER_FLAG 0x40 #define JET_CLIP_ID_MASK 0x3f /*---------------------------------------------------------------------------- * JET file definitions *---------------------------------------------------------------------------- */ #define JET_TAG(a,b,c,d) (\ ( ((EAS_U32)(a) & 0xFF) << 24 ) \ + ( ((EAS_U32)(b) & 0xFF) << 16 ) \ + ( ((EAS_U32)(c) & 0xFF) << 8 ) \ + ( ((EAS_U32)(d) & 0xFF))) #define JET_VERSION 0x01000000 #define JET_HEADER_TAG JET_TAG('J','E','T',' ') #define JET_INFO_CHUNK JET_TAG('J','I','N','F') #define JET_SMF_CHUNK JET_TAG('J','S','M','F') #define JET_DLS_CHUNK JET_TAG('J','D','L','S') #define INFO_JET_COPYRIGHT JET_TAG('J','C','O','P') #define JET_APP_DATA_CHUNK JET_TAG('J','A','P','P') #define INFO_NUM_SMF_CHUNKS JET_TAG('S','M','F','#') #define INFO_NUM_DLS_CHUNKS JET_TAG('D','L','S','#') #define INFO_JET_VERSION JET_TAG('J','V','E','R') /*---------------------------------------------------------------------------- * S_JET_SEGMENT * * JET segment data *---------------------------------------------------------------------------- */ typedef struct s_jet_segment_tag { EAS_HANDLE streamHandle; EAS_U32 muteFlags; EAS_I16 repeatCount; EAS_U8 userID; EAS_I8 transpose; EAS_I8 libNum; EAS_U8 state; EAS_U8 flags; } S_JET_SEGMENT; /* S_JET_SEGMENT.state */ typedef enum { JET_STATE_CLOSED, JET_STATE_OPEN, JET_STATE_READY, JET_STATE_PLAYING, JET_STATE_PAUSED, JET_STATE_STOPPING } E_JET_SEGMENT_STATE; /* S_JEG_SEGMENT.flags */ #define JET_SEG_FLAG_MUTE_UPDATE 0x01 /*---------------------------------------------------------------------------- * S_JET_DATA * * Main JET data structure *---------------------------------------------------------------------------- */ #define SEG_QUEUE_DEPTH 3 typedef struct s_jet_data_tag { EAS_FILE_HANDLE jetFileHandle; S_JET_SEGMENT segQueue[SEG_QUEUE_DEPTH]; EAS_I32 segmentOffsets[JET_MAX_SEGMENTS]; EAS_I32 appDataOffset; EAS_I32 appDataSize; EAS_DLSLIB_HANDLE libHandles[JET_MAX_DLS_COLLECTIONS]; EAS_U32 jetEventQueue[JET_EVENT_QUEUE_SIZE]; EAS_U32 appEventQueue[APP_EVENT_QUEUE_SIZE]; S_JET_CONFIG config; EAS_U32 segmentTime; EAS_U8 muteQueue[JET_MUTE_QUEUE_SIZE]; EAS_U8 numSegments; EAS_U8 numLibraries; EAS_U8 flags; EAS_U8 playSegment; EAS_U8 queueSegment; EAS_U8 numQueuedSegments; EAS_U8 jetEventQueueRead; EAS_U8 jetEventQueueWrite; EAS_U8 appEventQueueRead; EAS_U8 appEventQueueWrite; } S_JET_DATA; /* flags for S_JET_DATA.flags */ #define JET_FLAGS_PLAYING 1 #define JET_EVENT_VAL_MASK 0x0000007f /* mask for value */ #define JET_EVENT_CTRL_MASK 0x00003f80 /* mask for controller */ #define JET_EVENT_CHAN_MASK 0x0003c000 /* mask for channel */ #define JET_EVENT_TRACK_MASK 0x00fc0000 /* mask for track number */ #define JET_EVENT_SEG_MASK 0xff000000 /* mask for segment ID */ #define JET_EVENT_CTRL_SHIFT 7 /* shift for controller number */ #define JET_EVENT_CHAN_SHIFT 14 /* shift to for MIDI channel */ #define JET_EVENT_TRACK_SHIFT 18 /* shift to get track ID to bit 0 */ #define JET_EVENT_SEG_SHIFT 24 /* shift to get segment ID to bit 0 */ /* prototype for callback function */ extern void JET_Event (EAS_DATA_HANDLE easHandle, EAS_U32 segTrack, EAS_U8 channel, EAS_U8 controller, EAS_U8 value); /* prototype for JET render function */ extern EAS_PUBLIC EAS_RESULT JET_Process (EAS_DATA_HANDLE easHandle); #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_ctype.h0000644000000000000000000000013113532747316026240 xustar0030 mtime=1567346382.701999855 29 atime=1567346382.85400005 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_ctype.h0000644000175000001440000000310513532747316027031 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_ctype.h * * Contents and purpose: * This is a replacement for the CRT ctype.h functions. These * functions are currently ASCII only, but eventually, we will want * to support wide-characters for localization. * * Copyright (c) 2005 Sonic Network Inc. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 429 $ * $Date: 2006-10-19 23:50:15 -0700 (Thu, 19 Oct 2006) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_CTYPE_H #define _EAS_CTYPE_H EAS_INLINE EAS_I8 IsDigit (EAS_I8 c) { return ((c >= '0') && (c <= '9')); } EAS_INLINE EAS_I8 IsSpace (EAS_I8 c) { return (((c >= 9) && (c <= 13)) || (c == ' ')); } EAS_INLINE EAS_I8 ToUpper (EAS_I8 c) { if ((c >= 'a') && (c <= 'z')) return c & ~0x20; else return c; } EAS_INLINE EAS_I8 ToLower (EAS_I8 c) { if ((c >= 'A') && (c <= 'Z')) return c |= 0x20; else return c; } #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_smfdata.h0000644000000000000000000000013113532747316026533 xustar0030 mtime=1567346382.705999859 29 atime=1567346382.85400005 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_smfdata.h0000644000175000001440000000375113532747316027333 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_smfdata.h * * Contents and purpose: * SMF File Parser * * This file contains data definitions for the SMF parser. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 686 $ * $Date: 2007-05-03 14:10:54 -0700 (Thu, 03 May 2007) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_SMF_DATA_H #define _EAS_SMF_DATA_H #ifndef MAX_SMF_STREAMS #define MAX_SMF_STREAMS 128 #endif /* offsets in to the SMF file */ #define SMF_OFS_HEADER_SIZE 4 #define SMF_OFS_FILE_TYPE 8 #define SMF_OFS_NUM_TRACKS 10 /* size of chunk info (chunk ID + chunk size) */ #define SMF_CHUNK_INFO_SIZE 8 /* 'MTrk' track chunk ID */ #define SMF_CHUNK_TYPE_TRACK 0x4d54726bL /* some useful meta-events */ #define SMF_META_TEXT 0x01 #define SMF_META_COPYRIGHT 0x02 #define SMF_META_SEQTRK_NAME 0x03 #define SMF_META_LYRIC 0x05 #define SMF_META_END_OF_TRACK 0x2f #define SMF_META_TEMPO 0x51 #define SMF_META_TIME_SIGNATURE 0x58 /* default timebase (120BPM) */ #define SMF_DEFAULT_TIMEBASE 500000L /* value for pSMFStream->ticks to signify end of track */ #define SMF_END_OF_TRACK 0xffffffff #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_wavefile.c0000644000000000000000000000013113532747316026711 xustar0030 mtime=1567346382.705999859 29 atime=1567346382.85400005 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_wavefile.c0000644000175000001440000007023513532747316027512 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_wavefile.c * * Contents and purpose: * This file implements the wave file parser. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 852 $ * $Date: 2007-09-04 11:43:49 -0700 (Tue, 04 Sep 2007) $ *---------------------------------------------------------------------------- */ #include "eas_data.h" #include "eas_report.h" #include "eas_host.h" #include "eas_config.h" #include "eas_parser.h" #include "eas_pcm.h" #include "eas_wavefile.h" /* lint is choking on the ARM math.h file, so we declare the log10 function here */ extern double log10(double x); /* increase gain to compensate for loss in mixer */ #define WAVE_GAIN_OFFSET 6 /* constant for 1200 / log10(2.0) */ #define PITCH_CENTS_CONVERSION 3986.313714 /*---------------------------------------------------------------------------- * WAVE file defines *---------------------------------------------------------------------------- */ /* RIFF chunks */ #define CHUNK_TYPE(a,b,c,d) ( \ ( ((EAS_U32)(a) & 0xFF) << 24 ) \ + ( ((EAS_U32)(b) & 0xFF) << 16 ) \ + ( ((EAS_U32)(c) & 0xFF) << 8 ) \ + ( ((EAS_U32)(d) & 0xFF) ) ) #define CHUNK_RIFF CHUNK_TYPE('R','I','F','F') #define CHUNK_WAVE CHUNK_TYPE('W','A','V','E') #define CHUNK_FMT CHUNK_TYPE('f','m','t',' ') #define CHUNK_DATA CHUNK_TYPE('d','a','t','a') #define CHUNK_LIST CHUNK_TYPE('L','I','S','T') #define CHUNK_INFO CHUNK_TYPE('I','N','F','O') #define CHUNK_INAM CHUNK_TYPE('I','N','A','M') #define CHUNK_ICOP CHUNK_TYPE('I','C','O','P') #define CHUNK_IART CHUNK_TYPE('I','A','R','T') /* wave file format identifiers */ #define WAVE_FORMAT_PCM 0x0001 #define WAVE_FORMAT_IMA_ADPCM 0x0011 /* file size for streamed file */ #define FILE_SIZE_STREAMING 0x80000000 /*---------------------------------------------------------------------------- * prototypes *---------------------------------------------------------------------------- */ static EAS_RESULT WaveCheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *pHandle, EAS_I32 offset); static EAS_RESULT WavePrepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT WaveState (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); static EAS_RESULT WaveClose (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT WaveReset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT WaveLocate (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 time, EAS_BOOL *pParserLocate); static EAS_RESULT WavePause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT WaveResume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT WaveSetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); static EAS_RESULT WaveGetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); static EAS_RESULT WaveParseHeader (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData); static EAS_RESULT WaveGetMetaData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pMediaLength); #ifdef MMAPI_SUPPORT static EAS_RESULT SaveFmtChunk (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData, EAS_I32 size); #endif /*---------------------------------------------------------------------------- * * EAS_Wave_Parser * * This structure contains the functional interface for the Wave file parser *---------------------------------------------------------------------------- */ const S_FILE_PARSER_INTERFACE EAS_Wave_Parser = { WaveCheckFileType, WavePrepare, NULL, NULL, WaveState, WaveClose, WaveReset, WavePause, WaveResume, WaveLocate, WaveSetData, WaveGetData, WaveGetMetaData }; /*---------------------------------------------------------------------------- * WaveCheckFileType() *---------------------------------------------------------------------------- * Purpose: * Check the file type to see if we can parse it * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT WaveCheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *pHandle, EAS_I32 offset) { S_WAVE_STATE *pWaveData; /* zero the memory to insure complete initialization */ *pHandle = NULL; /* read the file header */ if (WaveParseHeader(pEASData, fileHandle, NULL) == EAS_SUCCESS) { /* check for static memory allocation */ if (pEASData->staticMemoryModel) pWaveData = EAS_CMEnumData(EAS_CM_WAVE_DATA); else pWaveData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_WAVE_STATE)); if (!pWaveData) return EAS_ERROR_MALLOC_FAILED; EAS_HWMemSet(pWaveData, 0, sizeof(S_WAVE_STATE)); /* return a pointer to the instance data */ pWaveData->fileHandle = fileHandle; pWaveData->fileOffset = offset; *pHandle = pWaveData; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * WavePrepare() *---------------------------------------------------------------------------- * Purpose: * Prepare to parse the file. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT WavePrepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_WAVE_STATE *pWaveData; EAS_RESULT result; /* validate parser state */ pWaveData = (S_WAVE_STATE*) pInstData; if (pWaveData->streamHandle != NULL) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; /* back to start of file */ pWaveData->time = 0; if ((result = EAS_HWFileSeek(pEASData->hwInstData, pWaveData->fileHandle, pWaveData->fileOffset)) != EAS_SUCCESS) return result; /* parse the file header */ if ((result = WaveParseHeader(pEASData, pWaveData->fileHandle, pWaveData)) != EAS_SUCCESS) return result; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * WaveState() *---------------------------------------------------------------------------- * Purpose: * Returns the current state of the stream * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * pState - pointer to variable to store state * * Outputs: * * * Side Effects: * * Notes: * This interface is also exposed in the internal library for use by the other modules. *---------------------------------------------------------------------------- */ static EAS_RESULT WaveState (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState) { S_WAVE_STATE *pWaveData; /* return current state */ pWaveData = (S_WAVE_STATE*) pInstData; if (pWaveData->streamHandle) return EAS_PEState(pEASData, pWaveData->streamHandle, pState); /* if no stream handle, and time is not zero, we are done */ if (pWaveData->time > 0) *pState = EAS_STATE_STOPPED; else *pState = EAS_STATE_OPEN; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * WaveClose() *---------------------------------------------------------------------------- * Purpose: * Close the file and clean up * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT WaveClose (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_WAVE_STATE *pWaveData; EAS_RESULT result; pWaveData = (S_WAVE_STATE*) pInstData; /* close the stream */ if (pWaveData->streamHandle) { if ((result = EAS_PEClose(pEASData, pWaveData->streamHandle)) != EAS_SUCCESS) return result; pWaveData->streamHandle = NULL; } /* if using dynamic memory, free it */ if (!pEASData->staticMemoryModel) { #ifdef MMAPI_SUPPORT /* need to free the fmt chunk */ if (pWaveData->fmtChunk != NULL) EAS_HWFree(pEASData->hwInstData, pWaveData->fmtChunk); #endif /* free the instance data */ EAS_HWFree(pEASData->hwInstData, pWaveData); } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * WaveReset() *---------------------------------------------------------------------------- * Purpose: * Reset the sequencer. Used for locating backwards in the file. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT WaveReset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { EAS_PCM_HANDLE streamHandle; /* reset to first byte of data in the stream */ streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle; if (streamHandle) return EAS_PEReset(pEASData, streamHandle); return EAS_ERROR_NOT_VALID_IN_THIS_STATE; } /*---------------------------------------------------------------------------- * WaveLocate() *---------------------------------------------------------------------------- * Purpose: * Rewind/fast-forward in file. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * time - time (in msecs) * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pParserLocate) reserved for future use */ static EAS_RESULT WaveLocate (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 time, EAS_BOOL *pParserLocate) { EAS_PCM_HANDLE streamHandle; /* reset to first byte of data in the stream */ streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle; if (streamHandle) return EAS_PELocate(pEASData, streamHandle, time); return EAS_ERROR_NOT_VALID_IN_THIS_STATE; } /*---------------------------------------------------------------------------- * WavePause() *---------------------------------------------------------------------------- * Purpose: * Mute and stop rendering a PCM stream. Sets the gain target to zero and stops the playback * at the end of the next audio frame. * * Inputs: * pEASData - pointer to EAS library instance data * handle - pointer to S_WAVE_STATE for this stream * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ static EAS_RESULT WavePause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { EAS_PCM_HANDLE streamHandle; /* pause the stream */ streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle; if (streamHandle) return EAS_PEPause(pEASData, streamHandle); return EAS_ERROR_NOT_VALID_IN_THIS_STATE; } /*---------------------------------------------------------------------------- * WaveResume() *---------------------------------------------------------------------------- * Purpose: * Resume rendering a PCM stream. Sets the gain target back to its * previous setting and restarts playback at the end of the next audio * frame. * * Inputs: * pEASData - pointer to EAS library instance data * handle - pointer to S_WAVE_STATE for this stream * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ static EAS_RESULT WaveResume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { EAS_PCM_HANDLE streamHandle; /* resume the stream */ streamHandle = ((S_WAVE_STATE*)pInstData)->streamHandle; if (streamHandle) return EAS_PEResume(pEASData, streamHandle); return EAS_ERROR_NOT_VALID_IN_THIS_STATE; } /*---------------------------------------------------------------------------- * WaveSetData() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * pEASData - pointer to EAS library instance data * handle - pointer to S_WAVE_STATE for this stream * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT WaveSetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) { S_WAVE_STATE *pWaveData = (S_WAVE_STATE*) pInstData; switch (param) { /* set metadata callback */ case PARSER_DATA_METADATA_CB: EAS_HWMemCpy(&pWaveData->metadata, (void*) value, sizeof(S_METADATA_CB)); return EAS_SUCCESS; case PARSER_DATA_PLAYBACK_RATE: value = (EAS_I32) (PITCH_CENTS_CONVERSION * log10((double) value / (double) (1 << 28))); return EAS_PEUpdatePitch(pEASData, pWaveData->streamHandle, (EAS_I16) value); case PARSER_DATA_VOLUME: return EAS_PEUpdateVolume(pEASData, pWaveData->streamHandle, (EAS_I16) value); default: return EAS_ERROR_INVALID_PARAMETER; } } /*---------------------------------------------------------------------------- * WaveGetData() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * pEASData - pointer to EAS library instance data * handle - pointer to S_WAVE_STATE for this stream * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ static EAS_RESULT WaveGetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) { S_WAVE_STATE *pWaveData; pWaveData = (S_WAVE_STATE*) pInstData; switch (param) { /* return file type as WAVE */ case PARSER_DATA_FILE_TYPE: *pValue = pWaveData->fileType; break; #ifdef MMAPI_SUPPORT /* return pointer to 'fmt' chunk */ case PARSER_DATA_FORMAT: *pValue = (EAS_I32) pWaveData->fmtChunk; break; #endif case PARSER_DATA_GAIN_OFFSET: *pValue = WAVE_GAIN_OFFSET; break; default: return EAS_ERROR_INVALID_PARAMETER; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * WaveParseHeader() *---------------------------------------------------------------------------- * Purpose: * Parse the WAVE file header. * * Inputs: * pEASData - pointer to EAS library instance data * handle - pointer to S_WAVE_STATE for this stream * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT WaveParseHeader (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData) { S_PCM_OPEN_PARAMS params; EAS_RESULT result; EAS_U32 tag; EAS_U32 fileSize; EAS_U32 size; EAS_I32 pos; EAS_I32 audioOffset; EAS_U16 usTemp; EAS_BOOL parseDone; EAS_U32 avgBytesPerSec; /* init some data (and keep lint happy) */ params.sampleRate = 0; params.size = 0; audioOffset = 0; params.decoder = 0; params.blockSize = 0; params.pCallbackFunc = NULL; params.cbInstData = NULL; params.loopSamples = 0; params.fileHandle = fileHandle; params.volume = 0x7fff; params.envData = 0; avgBytesPerSec = 8000; /* check for 'RIFF' tag */ if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) return result; if (tag != CHUNK_RIFF) return EAS_ERROR_UNRECOGNIZED_FORMAT; /* get size */ if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &fileSize, EAS_FALSE)) != EAS_FALSE) return result; /* check for 'WAVE' tag */ if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) return result; if (tag != CHUNK_WAVE) return EAS_ERROR_UNRECOGNIZED_FORMAT; /* this is enough to say we recognize the file */ if (pWaveData == NULL) return EAS_SUCCESS; /* check for streaming mode */ pWaveData->flags = 0; pWaveData->mediaLength = -1; pWaveData->infoChunkPos = -1; pWaveData->infoChunkSize = -1; if (fileSize== FILE_SIZE_STREAMING) { pWaveData->flags |= PCM_FLAGS_STREAMING; fileSize = 0x7fffffff; } /* find out where we're at */ if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &pos)) != EAS_SUCCESS) return result; fileSize -= 4; parseDone = EAS_FALSE; for (;;) { /* get tag and size for next chunk */ if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) return result; if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &size, EAS_FALSE)) != EAS_FALSE) return result; /* process chunk */ pos += 8; switch (tag) { case CHUNK_FMT: #ifdef MMAPI_SUPPORT if ((result = SaveFmtChunk(pEASData, fileHandle, pWaveData, (EAS_I32) size)) != EAS_SUCCESS) return result; #endif /* get audio format */ if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE) return result; if (usTemp == WAVE_FORMAT_PCM) { params.decoder = EAS_DECODER_PCM; pWaveData->fileType = EAS_FILE_WAVE_PCM; } else if (usTemp == WAVE_FORMAT_IMA_ADPCM) { params.decoder = EAS_DECODER_IMA_ADPCM; pWaveData->fileType = EAS_FILE_WAVE_IMA_ADPCM; } else return EAS_ERROR_UNRECOGNIZED_FORMAT; /* get number of channels */ if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE) return result; if (usTemp == 2) pWaveData->flags |= PCM_FLAGS_STEREO; else if (usTemp != 1) return EAS_ERROR_UNRECOGNIZED_FORMAT; /* get sample rate */ if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, ¶ms.sampleRate, EAS_FALSE)) != EAS_FALSE) return result; /* get stream rate */ if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &avgBytesPerSec, EAS_FALSE)) != EAS_FALSE) return result; /* get block alignment */ if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE) return result; params.blockSize = usTemp; /* get bits per sample */ if ((result = EAS_HWGetWord(pEASData->hwInstData, fileHandle, &usTemp, EAS_FALSE)) != EAS_FALSE) return result; /* PCM, must be 8 or 16 bit samples */ if (params.decoder == EAS_DECODER_PCM) { if (usTemp == 8) pWaveData->flags |= PCM_FLAGS_8_BIT | PCM_FLAGS_UNSIGNED; else if (usTemp != 16) return EAS_ERROR_UNRECOGNIZED_FORMAT; } /* for IMA ADPCM, we only support mono 4-bit ADPCM */ else { if ((usTemp != 4) || (pWaveData->flags & PCM_FLAGS_STEREO)) return EAS_ERROR_UNRECOGNIZED_FORMAT; } break; case CHUNK_DATA: audioOffset = pos; if (pWaveData->flags & PCM_FLAGS_STREAMING) { params.size = 0x7fffffff; parseDone = EAS_TRUE; } else { params.size = (EAS_I32) size; params.loopStart = size; /* use more accurate method if possible */ if (size <= (0x7fffffff / 1000)) pWaveData->mediaLength = (EAS_I32) ((size * 1000) / avgBytesPerSec); else pWaveData->mediaLength = (EAS_I32) (size / (avgBytesPerSec / 1000)); } break; case CHUNK_LIST: /* get the list type */ if ((result = EAS_HWGetDWord(pEASData->hwInstData, fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) return result; if (tag == CHUNK_INFO) { pWaveData->infoChunkPos = pos + 4; pWaveData->infoChunkSize = (EAS_I32) size - 4; } break; default: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WaveParseHeader: %c%c%c%c chunk - %d byte(s) ignored\n", (char) (tag >> 24), (char) (tag >> 16), (char) (tag >> 8), (char) tag, size); */ } break; } if (parseDone) break; /* subtract header size */ fileSize -= 8; /* account for zero-padding on odd length chunks */ if (size & 1) size++; /* this check works for files with odd length last chunk and no zero-pad */ if (size >= fileSize) { if (size > fileSize) { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WaveParseHeader: '%c%c%c%c' chunk size exceeds length of file or is not zero-padded\n", (char) (tag >> 24), (char) (tag >> 16), (char) (tag >> 8), (char) tag, size); */ } break; } /* subtract size of data chunk (including any zero-pad) */ fileSize -= size; /* seek to next chunk */ pos += (EAS_I32) size; if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, pos)) != EAS_SUCCESS) return result; } /* check for valid header */ if ((params.sampleRate == 0) || (params.size == 0)) return EAS_ERROR_UNRECOGNIZED_FORMAT; /* save the pertinent information */ pWaveData->audioOffset = audioOffset; params.flags = pWaveData->flags; /* seek to data */ if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, audioOffset)) != EAS_SUCCESS) return result; /* open a stream in the PCM engine */ return EAS_PEOpenStream(pEASData, ¶ms, &pWaveData->streamHandle); } /*---------------------------------------------------------------------------- * WaveGetMetaData() *---------------------------------------------------------------------------- * Purpose: * Process the INFO chunk and return metadata to host *---------------------------------------------------------------------------- */ static EAS_RESULT WaveGetMetaData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pMediaLength) { S_WAVE_STATE *pWaveData; EAS_RESULT result; EAS_I32 pos; EAS_U32 size; EAS_I32 infoSize; EAS_U32 tag; EAS_I32 restorePos; E_EAS_METADATA_TYPE metaType; EAS_I32 metaLen; /* get current position so we can restore it */ pWaveData = (S_WAVE_STATE*) pInstData; /* return media length */ *pMediaLength = pWaveData->mediaLength; /* did we encounter an INFO chunk? */ if (pWaveData->infoChunkPos < 0) return EAS_SUCCESS; if ((result = EAS_HWFilePos(pEASData->hwInstData, pWaveData->fileHandle, &restorePos)) != EAS_SUCCESS) return result; /* offset to start of first chunk in INFO chunk */ pos = pWaveData->infoChunkPos; infoSize = pWaveData->infoChunkSize; /* read all the chunks in the INFO chunk */ for (;;) { /* seek to next chunk */ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pWaveData->fileHandle, pos)) != EAS_SUCCESS) return result; /* get tag and size for next chunk */ if ((result = EAS_HWGetDWord(pEASData->hwInstData, pWaveData->fileHandle, &tag, EAS_TRUE)) != EAS_FALSE) return result; if ((result = EAS_HWGetDWord(pEASData->hwInstData, pWaveData->fileHandle, &size, EAS_FALSE)) != EAS_FALSE) return result; /* process chunk */ pos += 8; metaType = EAS_METADATA_UNKNOWN; switch (tag) { case CHUNK_INAM: metaType = EAS_METADATA_TITLE; break; case CHUNK_IART: metaType = EAS_METADATA_AUTHOR; break; case CHUNK_ICOP: metaType = EAS_METADATA_COPYRIGHT; break; default: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WaveParseHeader: %c%c%c%c chunk - %d byte(s) ignored\n", (char) (tag >> 24), (char) (tag >> 16), (char) (tag >> 8), (char) tag, size); */ } break; } /* process known metadata */ if (metaType != EAS_METADATA_UNKNOWN) { metaLen = pWaveData->metadata.bufferSize - 1; if (metaLen > (EAS_I32) size) metaLen = (EAS_I32) size; if ((result = EAS_HWReadFile(pEASData->hwInstData, pWaveData->fileHandle, pWaveData->metadata.buffer, metaLen, &metaLen)) != EAS_SUCCESS) return result; pWaveData->metadata.buffer[metaLen] = 0; pWaveData->metadata.callback(metaType, pWaveData->metadata.buffer, pWaveData->metadata.pUserData); } /* subtract this block */ if (size & 1) size++; infoSize -= (EAS_I32) size + 8; if (infoSize == 0) break; pos += (EAS_I32) size; } /* restore original position */ return EAS_HWFileSeek(pEASData->hwInstData, pWaveData->fileHandle, restorePos); } #ifdef MMAPI_SUPPORT /*---------------------------------------------------------------------------- * SaveFmtChunk() *---------------------------------------------------------------------------- * Purpose: * Save the fmt chunk for the MMAPI library *---------------------------------------------------------------------------- */ static EAS_RESULT SaveFmtChunk (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, S_WAVE_STATE *pWaveData, EAS_I32 fmtSize) { EAS_RESULT result; EAS_I32 pos; EAS_I32 count; /* save current file position */ if ((result = EAS_HWFilePos(pEASData->hwInstData, fileHandle, &pos)) != EAS_SUCCESS) return result; /* allocate a chunk of memory */ pWaveData->fmtChunk = EAS_HWMalloc(pEASData->hwInstData, fmtSize); if (!pWaveData->fmtChunk) return EAS_ERROR_MALLOC_FAILED; /* read the fmt chunk into memory */ if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, pWaveData->fmtChunk, fmtSize, &count)) != EAS_SUCCESS) return result; if (count != fmtSize) return EAS_ERROR_FILE_READ_FAILED; /* restore file position */ return EAS_HWFileSeek(pEASData->hwInstData, fileHandle, pos); } #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_flog.c0000644000000000000000000000013213532747316026037 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.858000056 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_flog.c0000644000175000001440000000524013532747316026631 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_flog2.c * * Contents and purpose: * Fixed point square root * * * Copyright (c) 2006 Sonic Network Inc. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision$ * $Date$ *---------------------------------------------------------------------------- */ #include "eas_types.h" #include "eas_math.h" #define MANTISSA_SHIFT 27 #define MANTISSA_MASK 0x0000000f #define MANTISSA_LSB_SHIFT 7 #define MANTISSA_LSB_MASK 0x000fffff #define LOG_EXPONENT_SHIFT 10 #define INTERPOLATION_SHIFT 20 #define MAX_NEGATIVE (-2147483647-1) /* log lookup table */ static const EAS_U16 eas_log2_table[] = { 0, 90, 174, 254, 330, 402, 470, 536, 599, 659, 717, 773, 827, 879, 929, 977, 1024 }; /*---------------------------------------------------------------------------- * EAS_flog2() *---------------------------------------------------------------------------- * Purpose: * Calculates the log2 of a 32-bit fixed point value * * Inputs: * n = value of interest * * Outputs: * returns the log2 of n * *---------------------------------------------------------------------------- */ EAS_I32 EAS_flog2 (EAS_U32 n) { EAS_U32 exp; EAS_U32 interp; /* check for error condition */ if (n == 0) return MAX_NEGATIVE; /* find exponent */ for (exp = 31; exp > 0; exp--) { /* shift until we get a 1 bit in bit 31 */ if ((n & (EAS_U32) MAX_NEGATIVE) != 0) break; n <<= 1; } /*lint -e{701} use shift for performance */ exp <<= LOG_EXPONENT_SHIFT; /* get the least significant bits for interpolation */ interp = (n >> MANTISSA_LSB_SHIFT) & MANTISSA_LSB_MASK; /* get the most significant bits for mantissa lookup */ n = (n >> MANTISSA_SHIFT) & MANTISSA_MASK; /* interpolate mantissa */ interp = ((eas_log2_table[n+1] - eas_log2_table[n]) * interp) >> INTERPOLATION_SHIFT; exp += eas_log2_table[n] + interp; return (EAS_I32) exp; } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_math.c0000644000000000000000000000013213532747316026041 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.858000056 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_math.c0000644000175000001440000001141513532747316026634 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_math.c * * Contents and purpose: * Contains common math routines for the various audio engines. * * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 586 $ * $Date: 2007-03-08 20:33:04 -0800 (Thu, 08 Mar 2007) $ *---------------------------------------------------------------------------- */ #include "eas.h" #include "eas_math.h" /* anything less than this converts to a fraction too small to represent in 32-bits */ #define MIN_CENTS -18000 /*---------------------------------------------------------------------------- * EAS_Calculate2toX() *---------------------------------------------------------------------------- * Purpose: * Calculate 2^x * * Inputs: * nCents - measured in cents * psEASData - pointer to overall EAS data structure * * Outputs: * nResult - int.frac result (where frac has NUM_DENTS_FRAC_BITS) * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_I32 EAS_Calculate2toX (EAS_I32 nCents) { EAS_I32 nDents; EAS_I32 nExponentInt, nExponentFrac; EAS_I32 nTemp1, nTemp2; EAS_I32 nResult; /* check for minimum value */ if (nCents < MIN_CENTS) return 0; /* for the time being, convert cents to dents */ nDents = FMUL_15x15(nCents, CENTS_TO_DENTS); nExponentInt = GET_DENTS_INT_PART(nDents); nExponentFrac = GET_DENTS_FRAC_PART(nDents); /* implement 2^(fracPart) as a power series */ nTemp1 = GN2_TO_X2 + MULT_DENTS_COEF(nExponentFrac, GN2_TO_X3); nTemp2 = GN2_TO_X1 + MULT_DENTS_COEF(nExponentFrac, nTemp1); nTemp1 = GN2_TO_X0 + MULT_DENTS_COEF(nExponentFrac, nTemp2); /* implement 2^(intPart) as a left shift for intPart >= 0 or a left shift for intPart < 0 */ if (nExponentInt >= 0) { /* left shift for positive exponents */ /*lint -e{703} */ nResult = nTemp1 << nExponentInt; } else { /* right shift for negative exponents */ nExponentInt = -nExponentInt; nResult = nTemp1 >> nExponentInt; } return nResult; } /*---------------------------------------------------------------------------- * EAS_LogToLinear16() *---------------------------------------------------------------------------- * Purpose: * Transform log value to linear gain multiplier using piece-wise linear * approximation * * Inputs: * nGain - log scale value in 20.10 format. Even though gain is normally * stored in 6.10 (16-bit) format we use 32-bit numbers here to eliminate * the need for saturation checking when combining gain values. * * Outputs: * Returns a 16-bit linear value approximately equal to 2^(nGain/1024) * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_U16 EAS_LogToLinear16 (EAS_I32 nGain) { EAS_INT nExp; EAS_U16 nTemp; /* bias to positive */ nGain += 32767; /* check for infinite attenuation */ if (nGain < 0) return 0; /* extract the exponent */ nExp = 31 - (nGain >> 10); /* check for maximum output */ if (nExp < 0) return 0x7fff; /* extract mantissa and restore implied 1 bit */ nTemp = (EAS_U16)((((nGain & 0x3ff) << 4) | 0x4000) >> nExp); /* use shift to approximate power-of-2 operation */ return nTemp; } /*---------------------------------------------------------------------------- * EAS_VolumeToGain() *---------------------------------------------------------------------------- * Purpose: * Transform volume control in 1dB increments to gain multiplier * * Inputs: * volume - 100 = 0dB, 99 = -1dB, 0 = -inf * * Outputs: * Returns a 16-bit linear value *---------------------------------------------------------------------------- */ EAS_I16 EAS_VolumeToGain (EAS_INT volume) { /* check for limits */ if (volume <= 0) return 0; if (volume >= 100) return 0x7fff; /*lint -e{702} use shift instead of division */ return (EAS_I16) EAS_Calculate2toX((((volume - EAS_MAX_VOLUME) * 204099) >> 10) - 1); } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/dls.h0000644000000000000000000000013213532747316025047 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.858000056 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/dls.h0000644000175000001440000001765113532747316025652 0ustar00pedrousers00000000000000 /* dls.h Description: Interface defines and structures for the Instrument Collection Form RIFF DLS. Written by Sonic Foundry 1996. Released for public use. */ #ifndef _INC_DLS #define _INC_DLS /* Layout of an instrument collection: RIFF [] 'DLS ' [colh,INSTLIST,WAVEPOOL,INFOLIST] INSTLIST LIST [] 'lins' LIST [] 'ins ' [insh,RGNLIST,ARTLIST,INFOLIST] LIST [] 'ins ' [insh,RGNLIST,ARTLIST,INFOLIST] LIST [] 'ins ' [insh,RGNLIST,ARTLIST,INFOLIST] RGNLIST LIST [] 'lrgn' LIST [] 'rgn ' [rgnh,wsmp,wlnk,ARTLIST] LIST [] 'rgn ' [rgnh,wsmp,wlnk,ARTLIST] LIST [] 'rgn ' [rgnh,wsmp,wlnk,ARTLIST] ARTLIST LIST [] 'lart' 'art1' level 1 Articulation connection graph 'art2' level 2 Articulation connection graph '3rd1' Possible 3rd party articulation structure 1 '3rd2' Possible 3rd party articulation structure 2 .... and so on WAVEPOOL ptbl [] [pool table] LIST [] 'wvpl' [path], [path], LIST [] 'wave',RIFFWAVE LIST [] 'wave',RIFFWAVE LIST [] 'wave',RIFFWAVE LIST [] 'wave',RIFFWAVE LIST [] 'wave',RIFFWAVE INFOLIST LIST [] 'INFO' 'icmt' 'One of those crazy comments.' 'icop' 'Copyright (C) 1996 Sonic Foundry' */ /* FOURCC's used in the DLS file */ /* shree */ //#define FAR /* shree #define FOURCC_DLS mmioFOURCC('D','L','S',' ') #define FOURCC_COLH mmioFOURCC('c','o','l','h') #define FOURCC_WVPL mmioFOURCC('w','v','p','l') #define FOURCC_PTBL mmioFOURCC('p','t','b','l') #define FOURCC_PATH mmioFOURCC('p','a','t','h') #define FOURCC_wave mmioFOURCC('w','a','v','e') #define FOURCC_LINS mmioFOURCC('l','i','n','s') #define FOURCC_INS mmioFOURCC('i','n','s',' ') #define FOURCC_INSH mmioFOURCC('i','n','s','h') #define FOURCC_LRGN mmioFOURCC('l','r','g','n') #define FOURCC_RGN mmioFOURCC('r','g','n',' ') #define FOURCC_RGNH mmioFOURCC('r','g','n','h') #define FOURCC_LART mmioFOURCC('l','a','r','t') #define FOURCC_ART1 mmioFOURCC('a','r','t','1') #define FOURCC_WLNK mmioFOURCC('w','l','n','k') #define FOURCC_WSMP mmioFOURCC('w','s','m','p') #define FOURCC_VERS mmioFOURCC('v','e','r','s') */ /* Articulation connection graph definitions */ /* Generic Sources */ #define CONN_SRC_NONE 0x0000 #define CONN_SRC_LFO 0x0001 #define CONN_SRC_KEYONVELOCITY 0x0002 #define CONN_SRC_KEYNUMBER 0x0003 #define CONN_SRC_EG1 0x0004 #define CONN_SRC_EG2 0x0005 #define CONN_SRC_PITCHWHEEL 0x0006 /* Midi Controllers 0-127 */ #define CONN_SRC_CC1 0x0081 #define CONN_SRC_CC7 0x0087 #define CONN_SRC_CC10 0x008a #define CONN_SRC_CC11 0x008b /* Registered Parameter Numbers */ #define CONN_SRC_RPN0 0x0100 #define CONN_SRC_RPN1 0x0101 #define CONN_SRC_RPN2 0x0102 /* Generic Destinations */ #define CONN_DST_NONE 0x0000 #define CONN_DST_ATTENUATION 0x0001 #define CONN_DST_RESERVED 0x0002 #define CONN_DST_PITCH 0x0003 #define CONN_DST_PAN 0x0004 /* LFO Destinations */ #define CONN_DST_LFO_FREQUENCY 0x0104 #define CONN_DST_LFO_STARTDELAY 0x0105 /* EG1 Destinations */ #define CONN_DST_EG1_ATTACKTIME 0x0206 #define CONN_DST_EG1_DECAYTIME 0x0207 #define CONN_DST_EG1_RESERVED 0x0208 #define CONN_DST_EG1_RELEASETIME 0x0209 #define CONN_DST_EG1_SUSTAINLEVEL 0x020a /* EG2 Destinations */ #define CONN_DST_EG2_ATTACKTIME 0x030a #define CONN_DST_EG2_DECAYTIME 0x030b #define CONN_DST_EG2_RESERVED 0x030c #define CONN_DST_EG2_RELEASETIME 0x030d #define CONN_DST_EG2_SUSTAINLEVEL 0x030e #define CONN_TRN_NONE 0x0000 #define CONN_TRN_CONCAVE 0x0001 typedef struct _DLSVERSION { DWORD dwVersionMS; DWORD dwVersionLS; }DLSVERSION, FAR *LPDLSVERSION; typedef struct _CONNECTION { USHORT usSource; USHORT usControl; USHORT usDestination; USHORT usTransform; LONG lScale; }CONNECTION, FAR *LPCONNECTION; /* Level 1 Articulation Data */ typedef struct _CONNECTIONLIST { ULONG cbSize; /* size of the connection list structure */ ULONG cConnections; /* count of connections in the list */ } CONNECTIONLIST, FAR *LPCONNECTIONLIST; /* Generic type defines for regions and instruments */ typedef struct _RGNRANGE { USHORT usLow; USHORT usHigh; }RGNRANGE, FAR * LPRGNRANGE; #define F_INSTRUMENT_DRUMS 0x80000000 typedef struct _MIDILOCALE { ULONG ulBank; ULONG ulInstrument; }MIDILOCALE, FAR *LPMIDILOCALE; /* Header structures found in an DLS file for collection, instruments, and regions. */ #define F_RGN_OPTION_SELFNONEXCLUSIVE 0x0001 typedef struct _RGNHEADER { RGNRANGE RangeKey; /* Key range */ RGNRANGE RangeVelocity; /* Velocity Range */ USHORT fusOptions; /* Synthesis options for this range */ USHORT usKeyGroup; /* Key grouping for non simultaneous play 0 = no group, 1 up is group for Level 1 only groups 1-15 are allowed */ }RGNHEADER, FAR *LPRGNHEADER; typedef struct _INSTHEADER { ULONG cRegions; /* Count of regions in this instrument */ MIDILOCALE Locale; /* Intended MIDI locale of this instrument */ }INSTHEADER, FAR *LPINSTHEADER; typedef struct _DLSHEADER { ULONG cInstruments; /* Count of instruments in the collection */ }DLSHEADER, FAR *LPDLSHEADER; /* definitions for the Wave link structure */ /***** For level 1 only WAVELINK_CHANNEL_MONO is valid **** ulChannel allows for up to 32 channels of audio with each bit position specifiying a channel of playback */ #define WAVELINK_CHANNEL_LEFT 0x0001 #define WAVELINK_CHANNEL_RIGHT 0x0002 #define F_WAVELINK_PHASE_MASTER 0x0001 typedef struct _WAVELINK { /* any paths or links are stored right after struct */ USHORT fusOptions; /* options flags for this wave */ USHORT usPhaseGroup; /* Phase grouping for locking channels */ ULONG ulChannel; /* channel placement */ ULONG ulTableIndex; /* index into the wave pool table, 0 based */ }WAVELINK, FAR *LPWAVELINK; #define POOL_CUE_NULL 0xffffffff typedef struct _POOLCUE { // ULONG ulEntryIndex; /* Index entry in the list */ ULONG ulOffset; /* Offset to the entry in the list */ }POOLCUE, FAR *LPPOOLCUE; typedef struct _POOLTABLE { ULONG cbSize; /* size of the pool table structure */ ULONG cCues; /* count of cues in the list */ } POOLTABLE, FAR *LPPOOLTABLE; /* Structures for the "wsmp" chunk */ #define F_WSMP_NO_TRUNCATION 0x0001 #define F_WSMP_NO_COMPRESSION 0x0002 typedef struct _rwsmp { ULONG cbSize; USHORT usUnityNote; /* MIDI Unity Playback Note */ SHORT sFineTune; /* Fine Tune in log tuning */ LONG lAttenuation; /* Overall Attenuation to be applied to data */ ULONG fulOptions; /* Flag options */ ULONG cSampleLoops; /* Count of Sample loops, 0 loops is one shot */ } WSMPL, FAR *LPWSMPL; /* This loop type is a normal forward playing loop which is continually played until the envelope reaches an off threshold in the release portion of the volume envelope */ #define WLOOP_TYPE_FORWARD 0 typedef struct _rloop { ULONG cbSize; ULONG ulType; /* Loop Type */ ULONG ulStart; /* Start of loop in samples */ ULONG ulLength; /* Length of loop in samples */ } WLOOP, FAR *LPWLOOP; #endif /* _INC_DLS */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_reverbdata.h0000644000000000000000000000013213532747316027234 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.858000056 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_reverbdata.h0000644000175000001440000004151413532747316030032 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_reverbdata.h * * Contents and purpose: * Contains the prototypes for the Reverb effect. * * * Copyright Sonic Network Inc. 2006 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 499 $ * $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_REVERBDATA_H #define _EAS_REVERBDATA_H #include "eas_types.h" #include "eas_audioconst.h" /*------------------------------------ * defines *------------------------------------ */ /* CIRCULAR() calculates the array index using modulo arithmetic. The "trick" is that modulo arithmetic is simplified by masking the effective address where the mask is (2^n)-1. This only works if the buffer size is a power of two. */ #define CIRCULAR(base,offset,size) (EAS_U32)( \ ( \ ((EAS_I32)(base)) + ((EAS_I32)(offset)) \ ) \ & size \ ) /* reverb parameters are updated every 2^(REVERB_UPDATE_PERIOD_IN_BITS) samples */ #if defined (_SAMPLE_RATE_8000) #define REVERB_UPDATE_PERIOD_IN_BITS 5 #define REVERB_BUFFER_SIZE_IN_SAMPLES 2048 #elif defined (_SAMPLE_RATE_16000) #define REVERB_UPDATE_PERIOD_IN_BITS 6 #define REVERB_BUFFER_SIZE_IN_SAMPLES 4096 #elif defined (_SAMPLE_RATE_22050) #define REVERB_UPDATE_PERIOD_IN_BITS 7 #define REVERB_BUFFER_SIZE_IN_SAMPLES 4096 #elif defined (_SAMPLE_RATE_32000) #define REVERB_UPDATE_PERIOD_IN_BITS 7 #define REVERB_BUFFER_SIZE_IN_SAMPLES 8192 #elif defined (_SAMPLE_RATE_44100) #define REVERB_UPDATE_PERIOD_IN_BITS 8 #define REVERB_BUFFER_SIZE_IN_SAMPLES 8192 #elif defined (_SAMPLE_RATE_48000) #define REVERB_UPDATE_PERIOD_IN_BITS 8 #define REVERB_BUFFER_SIZE_IN_SAMPLES 8192 #endif // Define a mask for circular addressing, so that array index // can wraparound and stay in array boundary of 0, 1, ..., (buffer size -1) // The buffer size MUST be a power of two #define REVERB_BUFFER_MASK (REVERB_BUFFER_SIZE_IN_SAMPLES -1) #define REVERB_MAX_ROOM_TYPE 4 // any room numbers larger than this are invalid #define REVERB_MAX_NUM_REFLECTIONS 5 // max num reflections per channel /* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SAMPLES */ #define REVERB_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(0x1L << REVERB_UPDATE_PERIOD_IN_BITS) /* calculate the update counter by bitwise ANDING with this value to generate a 2^n modulo value */ #define REVERB_MODULO_UPDATE_PERIOD_IN_SAMPLES (EAS_I32)(REVERB_UPDATE_PERIOD_IN_SAMPLES -1) /* synth parameters are updated every SYNTH_UPDATE_PERIOD_IN_SECONDS seconds */ #define REVERB_UPDATE_PERIOD_IN_SECONDS (REVERB_UPDATE_PERIOD_IN_SAMPLES / _OUTPUT_SAMPLE_RATE) // xfade parameters #define REVERB_XFADE_PERIOD_IN_SECONDS (100.0 / 1000.0) // xfade once every this many seconds #define REVERB_XFADE_PERIOD_IN_SAMPLES (REVERB_XFADE_PERIOD_IN_SECONDS * _OUTPUT_SAMPLE_RATE) #define REVERB_XFADE_PHASE_INCREMENT (EAS_I16)(65536 / ((EAS_I16)REVERB_XFADE_PERIOD_IN_SAMPLES/(EAS_I16)REVERB_UPDATE_PERIOD_IN_SAMPLES)) /**********/ /* the entire synth uses various flags in a bit field */ /* if flag is set, synth reset has been requested */ #define REVERB_FLAG_RESET_IS_REQUESTED 0x01 /* bit 0 */ #define MASK_REVERB_RESET_IS_REQUESTED 0x01 #define MASK_REVERB_RESET_IS_NOT_REQUESTED (EAS_U32)(~MASK_REVERB_RESET_IS_REQUESTED) /* by default, we always want to update ALL channel parameters when we reset the synth (e.g., during GM ON) */ #define DEFAULT_REVERB_FLAGS 0x0 /* coefficients for generating sin, cos */ #define REVERB_PAN_G2 4294940151 /* -0.82842712474619 = 2 - 4/sqrt(2) */ /* EAS_I32 nPanG1 = +1.0 for sin EAS_I32 nPanG1 = -1.0 for cos */ #define REVERB_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */ /*************************************************************/ // define the input injection points #define GUARD 5 // safety guard of this many samples #define MAX_AP_TIME (double) (20.0/1000.0) // delay time in milliseconds #define MAX_DELAY_TIME (double) (65.0/1000.0) // delay time in milliseconds #define MAX_AP_SAMPLES (int)(((double) MAX_AP_TIME) * ((double) _OUTPUT_SAMPLE_RATE)) #define MAX_DELAY_SAMPLES (int)(((double) MAX_DELAY_TIME) * ((double) _OUTPUT_SAMPLE_RATE)) #define AP0_IN 0 #define AP1_IN (AP0_IN + MAX_AP_SAMPLES + GUARD) #define DELAY0_IN (AP1_IN + MAX_AP_SAMPLES + GUARD) #define DELAY1_IN (DELAY0_IN + MAX_DELAY_SAMPLES + GUARD) // Define the max offsets for the end points of each section // i.e., we don't expect a given section's taps to go beyond // the following limits #define AP0_OUT (AP0_IN + MAX_AP_SAMPLES -1) #define AP1_OUT (AP1_IN + MAX_AP_SAMPLES -1) #define DELAY0_OUT (DELAY0_IN + MAX_DELAY_SAMPLES -1) #define DELAY1_OUT (DELAY1_IN + MAX_DELAY_SAMPLES -1) #define REVERB_DEFAULT_ROOM_NUMBER 1 // default preset number #define DEFAULT_AP0_LENGTH (int)(((double) (17.0/1000.0)) * ((double) _OUTPUT_SAMPLE_RATE)) #define DEFAULT_AP0_GAIN 19400 #define DEFAULT_AP1_LENGTH (int)(((double) (16.5/1000.0)) * ((double) _OUTPUT_SAMPLE_RATE)) #define DEFAULT_AP1_GAIN -19400 #define REVERB_DEFAULT_WET 32767 #define REVERB_DEFAULT_DRY 0 #define EAS_REVERB_WET_MAX 32767 #define EAS_REVERB_WET_MIN 0 #define EAS_REVERB_DRY_MAX 32767 #define EAS_REVERB_DRY_MIN 0 /* parameters for each allpass */ typedef struct { EAS_U16 m_zApOut; // delay offset for ap out EAS_I16 m_nApGain; // gain for ap EAS_U16 m_zApIn; // delay offset for ap in } S_ALLPASS_OBJECT; /* parameters for each allpass */ typedef struct { EAS_PCM m_zLpf; // actual state variable, not a length EAS_I16 m_nLpfFwd; // lpf forward gain EAS_I16 m_nLpfFbk; // lpf feedback gain EAS_U16 m_zDelay[REVERB_MAX_NUM_REFLECTIONS]; // delay offset for ap out EAS_I16 m_nGain[REVERB_MAX_NUM_REFLECTIONS]; // gain for ap } S_EARLY_REFLECTION_OBJECT; //demo typedef struct { EAS_I16 m_nLpfFbk; EAS_I16 m_nLpfFwd; EAS_I16 m_nEarly; EAS_I16 m_nWet; EAS_I16 m_nDry; EAS_I16 m_nEarlyL_LpfFbk; EAS_I16 m_nEarlyL_LpfFwd; EAS_I16 m_nEarlyL_Delay0; //8 EAS_I16 m_nEarlyL_Gain0; EAS_I16 m_nEarlyL_Delay1; EAS_I16 m_nEarlyL_Gain1; EAS_I16 m_nEarlyL_Delay2; EAS_I16 m_nEarlyL_Gain2; EAS_I16 m_nEarlyL_Delay3; EAS_I16 m_nEarlyL_Gain3; EAS_I16 m_nEarlyL_Delay4; EAS_I16 m_nEarlyL_Gain4; EAS_I16 m_nEarlyR_Delay0; //18 EAS_I16 m_nEarlyR_Gain0; EAS_I16 m_nEarlyR_Delay1; EAS_I16 m_nEarlyR_Gain1; EAS_I16 m_nEarlyR_Delay2; EAS_I16 m_nEarlyR_Gain2; EAS_I16 m_nEarlyR_Delay3; EAS_I16 m_nEarlyR_Gain3; EAS_I16 m_nEarlyR_Delay4; EAS_I16 m_nEarlyR_Gain4; EAS_U16 m_nMaxExcursion; //28 EAS_I16 m_nXfadeInterval; EAS_I16 m_nAp0_ApGain; //30 EAS_I16 m_nAp0_ApOut; EAS_I16 m_nAp1_ApGain; EAS_I16 m_nAp1_ApOut; EAS_I16 m_rfu4; EAS_I16 m_rfu5; EAS_I16 m_rfu6; EAS_I16 m_rfu7; EAS_I16 m_rfu8; EAS_I16 m_rfu9; EAS_I16 m_rfu10; //43 } S_REVERB_PRESET; typedef struct { S_REVERB_PRESET m_sPreset[REVERB_MAX_ROOM_TYPE]; //array of presets } S_REVERB_PRESET_BANK; /* parameters for each reverb */ typedef struct { /* controls entire reverb playback volume */ /* to conserve memory, use the MSB and ignore the LSB */ EAS_U8 m_nMasterVolume; /* update counter keeps track of when synth params need updating */ /* only needs to be as large as REVERB_UPDATE_PERIOD_IN_SAMPLES */ EAS_I16 m_nUpdateCounter; EAS_U16 m_nMinSamplesToAdd; /* ComputeReverb() generates this many samples */ EAS_U8 m_nFlags; /* misc flags/bit fields */ EAS_PCM *m_pOutputBuffer; EAS_PCM *m_pInputBuffer; EAS_U16 m_nNumSamplesInOutputBuffer; EAS_U16 m_nNumSamplesInInputBuffer; EAS_U16 m_nNumInputSamplesRead; // if m_nNumInputSamplesRead >= NumSamplesInInputBuffer // then get a new input buffer EAS_PCM *m_pNextInputSample; EAS_U16 m_nBaseIndex; // base index for circular buffer // reverb delay line offsets, allpass parameters, etc: EAS_PCM m_nRevOutFbkR; // combine feedback reverb right out with dry left in S_ALLPASS_OBJECT m_sAp0; // allpass 0 (left channel) EAS_U16 m_zD0In; // delay offset for delay line D0 in EAS_PCM m_nRevOutFbkL; // combine feedback reverb left out with dry right in S_ALLPASS_OBJECT m_sAp1; // allpass 1 (right channel) EAS_U16 m_zD1In; // delay offset for delay line D1 in // delay output taps, notice criss cross order EAS_U16 m_zD0Self; // self feeds forward d0 --> d0 EAS_U16 m_zD1Cross; // cross feeds across d1 --> d0 EAS_PCM m_zLpf0; // actual state variable, not a length EAS_U16 m_zD1Self; // self feeds forward d1 --> d1 EAS_U16 m_zD0Cross; // cross feeds across d0 --> d1 EAS_PCM m_zLpf1; // actual state variable, not a length EAS_I16 m_nSin; // gain for self taps EAS_I16 m_nCos; // gain for cross taps EAS_I16 m_nSinIncrement; // increment for gain EAS_I16 m_nCosIncrement; // increment for gain EAS_I16 m_nLpfFwd; // lpf forward gain (includes scaling for mixer) EAS_I16 m_nLpfFbk; // lpf feedback gain EAS_U16 m_nXfadeInterval; // update/xfade after this many samples EAS_U16 m_nXfadeCounter; // keep track of when to xfade EAS_I16 m_nPhase; // -1 <= m_nPhase < 1 // but during sin,cos calculations // use m_nPhase/2 EAS_I16 m_nPhaseIncrement; // add this to m_nPhase each frame EAS_I16 m_nNoise; // random noise sample EAS_U16 m_nMaxExcursion; // the taps can excurse +/- this amount EAS_BOOL m_bUseNoise; // if EAS_TRUE, use noise as input signal EAS_BOOL m_bBypass; // if EAS_TRUE, then bypass reverb and copy input to output EAS_I16 m_nCurrentRoom; // preset number for current room EAS_I16 m_nNextRoom; // preset number for next room EAS_I16 m_nWet; // gain for wet (processed) signal EAS_I16 m_nDry; // gain for dry (unprocessed) signal EAS_I16 m_nEarly; // gain for early (widen) signal S_EARLY_REFLECTION_OBJECT m_sEarlyL; // left channel early reflections S_EARLY_REFLECTION_OBJECT m_sEarlyR; // right channel early reflections EAS_PCM m_nDelayLine[REVERB_BUFFER_SIZE_IN_SAMPLES]; // one large delay line for all reverb elements S_REVERB_PRESET pPreset; S_REVERB_PRESET_BANK m_sPreset; //EAS_I8 preset; } S_REVERB_OBJECT; /*------------------------------------ * prototypes *------------------------------------ */ /*---------------------------------------------------------------------------- * ReverbUpdateXfade *---------------------------------------------------------------------------- * Purpose: * Update the xfade parameters as required * * Inputs: * nNumSamplesToAdd - number of samples to write to buffer * * Outputs: * * * Side Effects: * - xfade parameters will be changed * *---------------------------------------------------------------------------- */ static EAS_RESULT ReverbUpdateXfade(S_REVERB_OBJECT* pReverbData, EAS_INT nNumSamplesToAdd); /*---------------------------------------------------------------------------- * ReverbCalculateNoise *---------------------------------------------------------------------------- * Purpose: * Calculate a noise sample and limit its value * * Inputs: * nMaxExcursion - noise value is limited to this value * pnNoise - return new noise sample in this (not limited) * * Outputs: * new limited noise value * * Side Effects: * - *pnNoise noise value is updated * *---------------------------------------------------------------------------- */ static EAS_U16 ReverbCalculateNoise(EAS_U16 nMaxExcursion, EAS_I16 *pnNoise); /*---------------------------------------------------------------------------- * ReverbCalculateSinCos *---------------------------------------------------------------------------- * Purpose: * Calculate a new sin and cosine value based on the given phase * * Inputs: * nPhase - phase angle * pnSin - input old value, output new value * pnCos - input old value, output new value * * Outputs: * * Side Effects: * - *pnSin, *pnCos are updated * *---------------------------------------------------------------------------- */ static EAS_RESULT ReverbCalculateSinCos(EAS_I16 nPhase, EAS_I16 *pnSin, EAS_I16 *pnCos); /*---------------------------------------------------------------------------- * Reverb *---------------------------------------------------------------------------- * Purpose: * apply reverb to the given signal * * Inputs: * nNu * pnSin - input old value, output new value * pnCos - input old value, output new value * * Outputs: * number of samples actually reverberated * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT Reverb(S_REVERB_OBJECT* pReverbData, EAS_INT nNumSamplesToAdd, EAS_PCM *pOutputBuffer, EAS_PCM *pInputBuffer); /*---------------------------------------------------------------------------- * ReverbReadInPresets() *---------------------------------------------------------------------------- * Purpose: sets global reverb preset bank to defaults * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ static EAS_RESULT ReverbReadInPresets(S_REVERB_OBJECT* pReverbData); /*---------------------------------------------------------------------------- * ReverbUpdateRoom *---------------------------------------------------------------------------- * Purpose: * Update the room's preset parameters as required * * Inputs: * * Outputs: * * * Side Effects: * - reverb paramters (fbk, fwd, etc) will be changed * - m_nCurrentRoom := m_nNextRoom *---------------------------------------------------------------------------- */ static EAS_RESULT ReverbUpdateRoom(S_REVERB_OBJECT* pReverbData); #endif /* #ifndef _EAS_REVERBDATA_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_chorus.c0000644000000000000000000000013213532747316026413 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.858000056 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_chorus.c0000644000175000001440000005246313532747316027216 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_chorus.c * * Contents and purpose: * Contains the implementation of the Chorus effect. * * * Copyright Sonic Network Inc. 2006 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 499 $ * $Date: 2006-12-11 16:07:20 -0800 (Mon, 11 Dec 2006) $ *---------------------------------------------------------------------------- */ #include "eas_data.h" #include "eas_effects.h" #include "eas_math.h" #include "eas_chorusdata.h" #include "eas_chorus.h" #include "eas_config.h" #include "eas_host.h" #include "eas_report.h" /* prototypes for effects interface */ static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples); static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); /* common effects interface for configuration module */ const S_EFFECTS_INTERFACE EAS_Chorus = { ChorusInit, ChorusProcess, ChorusShutdown, ChorusGetParam, ChorusSetParam }; //LFO shape table used by the chorus, larger table would sound better //this is a sine wave, where 32767 = 1.0 static const EAS_I16 EAS_chorusShape[CHORUS_SHAPE_SIZE] = { 0, 1608, 3212, 4808, 6393, 7962, 9512, 11309, 12539, 14010, 15446, 16846, 18204, 19519, 20787, 22005, 23170, 24279, 25329, 26319, 27245, 28105, 28898, 29621, 30273, 30852, 31356, 31785, 32137, 32412, 32609, 32728, 32767, 32728, 32609, 32412, 32137, 31785, 31356, 30852, 30273, 29621, 28898, 28105, 27245, 26319, 25329, 24279, 23170, 22005, 20787, 19519, 18204, 16846, 15446, 14010, 12539, 11039, 9512, 7962, 6393, 4808, 3212, 1608, 0, -1608, -3212, -4808, -6393, -7962, -9512, -11309, -12539, -14010, -15446, -16846, -18204, -19519, -20787, -22005, -23170, -24279, -25329, -26319, -27245, -28105, -28898, -29621, -30273, -30852, -31356, -31785, -32137, -32412, -32609, -32728, -32767, -32728, -32609, -32412, -32137, -31785, -31356, -30852, -30273, -29621, -28898, -28105, -27245, -26319, -25329, -24279, -23170, -22005, -20787, -19519, -18204, -16846, -15446, -14010, -12539, -11039, -9512, -7962, -6393, -4808, -3212, -1608 }; /*---------------------------------------------------------------------------- * InitializeChorus() *---------------------------------------------------------------------------- * Purpose: Initializes chorus parameters * * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ static EAS_RESULT ChorusInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData) { S_CHORUS_OBJECT *pChorusData; S_CHORUS_PRESET *pPreset; EAS_I32 index; /* check Configuration Module for data allocation */ if (pEASData->staticMemoryModel) pChorusData = EAS_CMEnumFXData(EAS_MODULE_CHORUS); /* allocate dynamic memory */ else pChorusData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_CHORUS_OBJECT)); if (pChorusData == NULL) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Chorus memory\n"); */ } return EAS_ERROR_MALLOC_FAILED; } /* clear the structure */ EAS_HWMemSet(pChorusData, 0, sizeof(S_CHORUS_OBJECT)); ChorusReadInPresets(pChorusData); /* set some default values */ pChorusData->bypass = EAS_CHORUS_BYPASS_DEFAULT; pChorusData->preset = EAS_CHORUS_PRESET_DEFAULT; pChorusData->m_nLevel = EAS_CHORUS_LEVEL_DEFAULT; pChorusData->m_nRate = EAS_CHORUS_RATE_DEFAULT; pChorusData->m_nDepth = EAS_CHORUS_DEPTH_DEFAULT; //chorus rate and depth need some massaging from preset value (which is sample rate independent) //convert rate from steps of .05 Hz to value which can be used as phase increment, //with current CHORUS_SHAPE_SIZE and rate limits, this fits into 16 bits //want to compute ((shapeSize * 65536) * (storedRate/20))/sampleRate; //computing it as below allows rate steps to be evenly spaced //uses 32 bit divide, but only once when new value is selected pChorusData->m_nRate = (EAS_I16) ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); //convert depth from steps of .05 ms, to samples, with 16 bit whole part, discard fraction //want to compute ((depth * sampleRate)/20000) //use the following approximation since 105/32 is roughly 65536/20000 /*lint -e{704} use shift for performance */ pChorusData->m_nDepth = (EAS_I16) (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); pChorusData->m_nLevel = pChorusData->m_nLevel; //zero delay memory for chorus for (index = CHORUS_L_SIZE - 1; index >= 0; index--) { pChorusData->chorusDelayL[index] = 0; } for (index = CHORUS_R_SIZE - 1; index >= 0; index--) { pChorusData->chorusDelayR[index] = 0; } //init delay line index, these are used to implement circular delay buffer pChorusData->chorusIndexL = 0; pChorusData->chorusIndexR = 0; //init LFO phase //16 bit whole part, 16 bit fraction pChorusData->lfoLPhase = 0; pChorusData->lfoRPhase = (CHORUS_SHAPE_SIZE << 16) >> 2; // 1/4 of total, i.e. 90 degrees out of phase; //init chorus delay position //right now chorus delay is a compile-time value, as is sample rate pChorusData->chorusTapPosition = (EAS_I16)((CHORUS_DELAY_MS * _OUTPUT_SAMPLE_RATE)/1000); //now copy from the new preset into Chorus pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus]; pChorusData->m_nLevel = pPreset->m_nLevel; pChorusData->m_nRate = pPreset->m_nRate; pChorusData->m_nDepth = pPreset->m_nDepth; pChorusData->m_nRate = (EAS_I16) ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); /*lint -e{704} use shift for performance */ pChorusData->m_nDepth = (EAS_I16) (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); *pInstData = pChorusData; return EAS_SUCCESS; } /* end ChorusInit */ /*---------------------------------------------------------------------------- * WeightedTap() *---------------------------------------------------------------------------- * Purpose: Does fractional array look-up using linear interpolation * * first convert indexDesired to actual desired index by taking into account indexReference * then do linear interpolation between two actual samples using fractional part * * Inputs: * array: pointer to array of signed 16 bit values, typically either PCM data or control data * indexReference: the circular buffer relative offset * indexDesired: the fractional index we are looking up (16 bits index + 16 bits fraction) * indexLimit: the total size of the array, used to compute buffer wrap * * Outputs: * Value from the input array, linearly interpolated between two actual data values * *---------------------------------------------------------------------------- */ static EAS_I16 WeightedTap(const EAS_I16 *array, EAS_I16 indexReference, EAS_I32 indexDesired, EAS_I16 indexLimit) { EAS_I16 index; EAS_I16 fraction; EAS_I16 val1; EAS_I16 val2; //separate indexDesired into whole and fractional parts /*lint -e{704} use shift for performance */ index = (EAS_I16)(indexDesired >> 16); /*lint -e{704} use shift for performance */ fraction = (EAS_I16)((indexDesired>>1) & 0x07FFF); //just use 15 bits of fractional part //adjust whole part by indexReference index = indexReference - index; //make sure we stay within array bounds, this implements circular buffer while (index < 0) { index += indexLimit; } //get two adjacent values from the array val1 = array[index]; //handle special case when index == 0, else typical case if (index == 0) { val2 = array[indexLimit-1]; //get last value from array } else { val2 = array[index-1]; //get previous value from array } //compute linear interpolation as (val1 + ((val2-val1)*fraction)) return(val1 + (EAS_I16)MULT_EG1_EG1(val2-val1,fraction)); } /*---------------------------------------------------------------------------- * ChorusProcess() *---------------------------------------------------------------------------- * Purpose: compute the chorus on the input buffer, and mix into output buffer * * * Inputs: * src: pointer to input buffer of PCM values to be processed * dst: pointer to output buffer of PCM values we are to sume the result with * bufSize: the number of sample frames (i.e. stereo samples) in the buffer * * Outputs: * None * *---------------------------------------------------------------------------- */ //compute the chorus, and mix into output buffer static void ChorusProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples) { EAS_I32 ix; EAS_I32 nChannelNumber; EAS_I16 lfoValueLeft; EAS_I16 lfoValueRight; EAS_I32 positionOffsetL; EAS_I32 positionOffsetR; EAS_PCM tapL; EAS_PCM tapR; EAS_I32 tempValue; EAS_PCM nInputSample; EAS_I32 nOutputSample; EAS_PCM *pIn; EAS_PCM *pOut; S_CHORUS_OBJECT *pChorusData; pChorusData = (S_CHORUS_OBJECT*) pInstData; //if the chorus is disabled or turned all the way down if (pChorusData->bypass == EAS_TRUE || pChorusData->m_nLevel == 0) { if (pSrc != pDst) EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM)); return; } if (pChorusData->m_nNextChorus != pChorusData->m_nCurrentChorus) { ChorusUpdate(pChorusData); } for (nChannelNumber = 0; nChannelNumber < NUM_OUTPUT_CHANNELS; nChannelNumber++) { pIn = pSrc + nChannelNumber; pOut = pDst + nChannelNumber; if(nChannelNumber==0) { for (ix = 0; ix < numSamples; ix++) { nInputSample = *pIn; pIn += NUM_OUTPUT_CHANNELS; //feed input into chorus delay line pChorusData->chorusDelayL[pChorusData->chorusIndexL] = nInputSample; //compute chorus lfo value using phase as fractional index into chorus shape table //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number lfoValueLeft = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoLPhase, CHORUS_SHAPE_SIZE); //scale chorus depth by lfo value to get relative fractional sample index //index is expressed as 32 bit number with 16 bit fractional part /*lint -e{703} use shift for performance */ positionOffsetL = pChorusData->m_nDepth * (((EAS_I32)lfoValueLeft) << 1); //add fixed chorus delay to get actual fractional sample index positionOffsetL += ((EAS_I32)pChorusData->chorusTapPosition) << 16; //get tap value from chorus delay using fractional sample index tapL = WeightedTap(pChorusData->chorusDelayL, pChorusData->chorusIndexL, positionOffsetL, CHORUS_L_SIZE); //scale by chorus level, then sum with input buffer contents and saturate tempValue = MULT_EG1_EG1(tapL, pChorusData->m_nLevel); nOutputSample = SATURATE(tempValue + nInputSample); *pOut = (EAS_I16)SATURATE(nOutputSample); pOut += NUM_OUTPUT_CHANNELS; //increment chorus delay index and make it wrap as needed //this implements circular buffer if ((pChorusData->chorusIndexL+=1) >= CHORUS_L_SIZE) pChorusData->chorusIndexL = 0; //increment fractional lfo phase, and make it wrap as needed pChorusData->lfoLPhase += pChorusData->m_nRate; while (pChorusData->lfoLPhase >= (CHORUS_SHAPE_SIZE<<16)) { pChorusData->lfoLPhase -= (CHORUS_SHAPE_SIZE<<16); } } } else { for (ix = 0; ix < numSamples; ix++) { nInputSample = *pIn; pIn += NUM_OUTPUT_CHANNELS; //feed input into chorus delay line pChorusData->chorusDelayR[pChorusData->chorusIndexR] = nInputSample; //compute chorus lfo value using phase as fractional index into chorus shape table //resulting value is between -1.0 and 1.0, expressed as signed 16 bit number lfoValueRight = WeightedTap(EAS_chorusShape, 0, pChorusData->lfoRPhase, CHORUS_SHAPE_SIZE); //scale chorus depth by lfo value to get relative fractional sample index //index is expressed as 32 bit number with 16 bit fractional part /*lint -e{703} use shift for performance */ positionOffsetR = pChorusData->m_nDepth * (((EAS_I32)lfoValueRight) << 1); //add fixed chorus delay to get actual fractional sample index positionOffsetR += ((EAS_I32)pChorusData->chorusTapPosition) << 16; //get tap value from chorus delay using fractional sample index tapR = WeightedTap(pChorusData->chorusDelayR, pChorusData->chorusIndexR, positionOffsetR, CHORUS_R_SIZE); //scale by chorus level, then sum with output buffer contents and saturate tempValue = MULT_EG1_EG1(tapR, pChorusData->m_nLevel); nOutputSample = SATURATE(tempValue + nInputSample); *pOut = (EAS_I16)SATURATE(nOutputSample); pOut += NUM_OUTPUT_CHANNELS; //increment chorus delay index and make it wrap as needed //this implements circular buffer if ((pChorusData->chorusIndexR+=1) >= CHORUS_R_SIZE) pChorusData->chorusIndexR = 0; //increment fractional lfo phase, and make it wrap as needed pChorusData->lfoRPhase += pChorusData->m_nRate; while (pChorusData->lfoRPhase >= (CHORUS_SHAPE_SIZE<<16)) { pChorusData->lfoRPhase -= (CHORUS_SHAPE_SIZE<<16); } } } } } /* end ChorusProcess */ /*---------------------------------------------------------------------------- * ChorusShutdown() *---------------------------------------------------------------------------- * Purpose: * Initializes the Chorus effect. * * Inputs: * pInstData - handle to instance data * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT ChorusShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData) { /* check Configuration Module for static memory allocation */ if (!pEASData->staticMemoryModel) EAS_HWFree(pEASData->hwInstData, pInstData); return EAS_SUCCESS; } /* end ChorusShutdown */ /*---------------------------------------------------------------------------- * ChorusGetParam() *---------------------------------------------------------------------------- * Purpose: * Get a Chorus parameter * * Inputs: * pInstData - handle to instance data * param - parameter index * *pValue - pointer to variable to hold retrieved value * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT ChorusGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) { S_CHORUS_OBJECT *p; p = (S_CHORUS_OBJECT*) pInstData; switch (param) { case EAS_PARAM_CHORUS_BYPASS: *pValue = (EAS_I32) p->bypass; break; case EAS_PARAM_CHORUS_PRESET: *pValue = (EAS_I8) p->m_nCurrentChorus; break; case EAS_PARAM_CHORUS_RATE: *pValue = (EAS_I32) p->m_nRate; break; case EAS_PARAM_CHORUS_DEPTH: *pValue = (EAS_I32) p->m_nDepth; break; case EAS_PARAM_CHORUS_LEVEL: *pValue = (EAS_I32) p->m_nLevel; break; default: return EAS_ERROR_INVALID_PARAMETER; } return EAS_SUCCESS; } /* end ChorusGetParam */ /*---------------------------------------------------------------------------- * ChorusSetParam() *---------------------------------------------------------------------------- * Purpose: * Set a Chorus parameter * * Inputs: * pInstData - handle to instance data * param - parameter index * *pValue - new paramter value * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT ChorusSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) { S_CHORUS_OBJECT *p; p = (S_CHORUS_OBJECT*) pInstData; switch (param) { case EAS_PARAM_CHORUS_BYPASS: p->bypass = (EAS_BOOL) value; break; case EAS_PARAM_CHORUS_PRESET: if(value!=EAS_PARAM_CHORUS_PRESET1 && value!=EAS_PARAM_CHORUS_PRESET2 && value!=EAS_PARAM_CHORUS_PRESET3 && value!=EAS_PARAM_CHORUS_PRESET4) return EAS_ERROR_INVALID_PARAMETER; p->m_nNextChorus = (EAS_I8)value; break; case EAS_PARAM_CHORUS_RATE: if(valueEAS_CHORUS_RATE_MAX) return EAS_ERROR_INVALID_PARAMETER; p->m_nRate = (EAS_I16) value; break; case EAS_PARAM_CHORUS_DEPTH: if(valueEAS_CHORUS_DEPTH_MAX) return EAS_ERROR_INVALID_PARAMETER; p->m_nDepth = (EAS_I16) value; break; case EAS_PARAM_CHORUS_LEVEL: if(valueEAS_CHORUS_LEVEL_MAX) return EAS_ERROR_INVALID_PARAMETER; p->m_nLevel = (EAS_I16) value; break; default: return EAS_ERROR_INVALID_PARAMETER; } return EAS_SUCCESS; } /* end ChorusSetParam */ /*---------------------------------------------------------------------------- * ChorusReadInPresets() *---------------------------------------------------------------------------- * Purpose: sets global Chorus preset bank to defaults * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ static EAS_RESULT ChorusReadInPresets(S_CHORUS_OBJECT *pChorusData) { int preset = 0; int defaultPreset = 0; //now init any remaining presets to defaults for (defaultPreset = preset; defaultPreset < CHORUS_MAX_TYPE; defaultPreset++) { S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[defaultPreset]; if (defaultPreset == 0 || defaultPreset > CHORUS_MAX_TYPE-1) { pPreset->m_nDepth = 39; pPreset->m_nRate = 30; pPreset->m_nLevel = 32767; } else if (defaultPreset == 1) { pPreset->m_nDepth = 21; pPreset->m_nRate = 45; pPreset->m_nLevel = 25000; } else if (defaultPreset == 2) { pPreset->m_nDepth = 53; pPreset->m_nRate = 25; pPreset->m_nLevel = 32000; } else if (defaultPreset == 3) { pPreset->m_nDepth = 32; pPreset->m_nRate = 37; pPreset->m_nLevel = 29000; } } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * ChorusUpdate *---------------------------------------------------------------------------- * Purpose: * Update the Chorus preset parameters as required * * Inputs: * * Outputs: * * * Side Effects: * - chorus paramters will be changed * - m_nCurrentRoom := m_nNextRoom *---------------------------------------------------------------------------- */ static EAS_RESULT ChorusUpdate(S_CHORUS_OBJECT *pChorusData) { S_CHORUS_PRESET *pPreset = &pChorusData->m_sPreset.m_sPreset[pChorusData->m_nNextChorus]; pChorusData->m_nLevel = pPreset->m_nLevel; pChorusData->m_nRate = pPreset->m_nRate; pChorusData->m_nDepth = pPreset->m_nDepth; pChorusData->m_nRate = (EAS_I16) ((((EAS_I32)CHORUS_SHAPE_SIZE<<16)/(20*(EAS_I32)_OUTPUT_SAMPLE_RATE)) * pChorusData->m_nRate); /*lint -e{704} use shift for performance */ pChorusData->m_nDepth = (EAS_I16) (((((EAS_I32)pChorusData->m_nDepth * _OUTPUT_SAMPLE_RATE)>>5) * 105) >> 16); pChorusData->m_nCurrentChorus = pChorusData->m_nNextChorus; return EAS_SUCCESS; } /* end ChorusUpdate */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_smf.c0000644000000000000000000000013213532747316025675 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.858000056 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_smf.c0000644000175000001440000011106113532747316026466 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_smf.c * * Contents and purpose: * SMF Type 0 and 1 File Parser * * For SMF timebase analysis, see "MIDI Sequencer Analysis.xls". * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 803 $ * $Date: 2007-08-01 09:57:00 -0700 (Wed, 01 Aug 2007) $ *---------------------------------------------------------------------------- */ #include "eas_data.h" #include "eas_miditypes.h" #include "eas_parser.h" #include "eas_report.h" #include "eas_host.h" #include "eas_midi.h" #include "eas_config.h" #include "eas_vm_protos.h" #include "eas_smfdata.h" #include "eas_smf.h" #ifdef JET_INTERFACE #include "jet_data.h" #endif //3 dls: The timebase for this module is adequate to keep MIDI and //3 digital audio synchronized for only a few minutes. It should be //3 sufficient for most mobile applications. If better accuracy is //3 required, more fractional bits should be added to the timebase. static const EAS_U8 smfHeader[] = { 'M', 'T', 'h', 'd' }; /* local prototypes */ static EAS_RESULT SMF_GetVarLenData (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_U32 *pData); static EAS_RESULT SMF_ParseMetaEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream); static EAS_RESULT SMF_ParseSysEx (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_U8 f0, EAS_INT parserMode); static EAS_RESULT SMF_ParseEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_INT parserMode); static EAS_RESULT SMF_GetDeltaTime (EAS_HW_DATA_HANDLE hwInstData, S_SMF_STREAM *pSMFStream); static void SMF_UpdateTime (S_SMF_DATA *pSMFData, EAS_U32 ticks); /*---------------------------------------------------------------------------- * * SMF_Parser * * This structure contains the functional interface for the SMF parser *---------------------------------------------------------------------------- */ const S_FILE_PARSER_INTERFACE EAS_SMF_Parser = { SMF_CheckFileType, SMF_Prepare, SMF_Time, SMF_Event, SMF_State, SMF_Close, SMF_Reset, SMF_Pause, SMF_Resume, NULL, SMF_SetData, SMF_GetData, NULL }; /*---------------------------------------------------------------------------- * SMF_CheckFileType() *---------------------------------------------------------------------------- * Purpose: * Check the file type to see if we can parse it * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT SMF_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) { S_SMF_DATA* pSMFData; EAS_RESULT result; /* seek to starting offset - usually 0 */ *ppHandle = NULL; if ((result = EAS_HWFileSeek(pEASData->hwInstData, fileHandle, offset)) != EAS_SUCCESS) return result; /* search through file for header - slow method */ if (pEASData->searchHeaderFlag) { result = EAS_SearchFile(pEASData, fileHandle, smfHeader, sizeof(smfHeader), &offset); if (result != EAS_SUCCESS) return (result == EAS_EOF) ? EAS_SUCCESS : result; } /* read the first 4 bytes of the file - quick method */ else { EAS_U8 header[4]; EAS_I32 count; if ((result = EAS_HWReadFile(pEASData->hwInstData, fileHandle, header, sizeof(header), &count)) != EAS_SUCCESS) return result; /* check for 'MTrk' - return if no match */ if ((header[0] != 'M') || (header[1] != 'T') || (header[2] != 'h') || (header[3] != 'd')) return EAS_SUCCESS; } /* check for static memory allocation */ if (pEASData->staticMemoryModel) pSMFData = EAS_CMEnumData(EAS_CM_SMF_DATA); else { pSMFData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_SMF_DATA)); EAS_HWMemSet((void *)pSMFData,0, sizeof(S_SMF_DATA)); } if (!pSMFData) return EAS_ERROR_MALLOC_FAILED; /* initialize some critical data */ pSMFData->fileHandle = fileHandle; pSMFData->fileOffset = offset; pSMFData->pSynth = NULL; pSMFData->time = 0; pSMFData->state = EAS_STATE_OPEN; *ppHandle = pSMFData; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * SMF_Prepare() *---------------------------------------------------------------------------- * Purpose: * Prepare to parse the file. Allocates instance data (or uses static allocation for * static memory model). * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT SMF_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_SMF_DATA* pSMFData; EAS_RESULT result; /* check for valid state */ pSMFData = (S_SMF_DATA *) pInstData; if (pSMFData->state != EAS_STATE_OPEN) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; /* instantiate a synthesizer */ if ((result = VMInitMIDI(pEASData, &pSMFData->pSynth)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } return result; } /* parse the file header and setup the individual stream parsers */ if ((result = SMF_ParseHeader(pEASData->hwInstData, pSMFData)) != EAS_SUCCESS) return result; /* ready to play */ pSMFData->state = EAS_STATE_READY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * SMF_Time() *---------------------------------------------------------------------------- * Purpose: * Returns the time of the next event in msecs * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * pTime - pointer to variable to hold time of next event (in msecs) * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_RESULT SMF_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) { S_SMF_DATA *pSMFData; pSMFData = (S_SMF_DATA*) pInstData; /* sanity check */ #ifdef _CHECKED_BUILD if (pSMFData->state == EAS_STATE_STOPPED) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Can't ask for time on a stopped stream\n"); */ } } if (pSMFData->nextStream == NULL) { { /* dpp: EAS_ReportEx( _EAS_SEVERITY_ERROR, "no is NULL\n"); */ } } #endif #if 0 /* return time in milliseconds */ /* if chase mode, lie about time */ if (pSMFData->flags & SMF_FLAGS_CHASE_MODE) *pTime = 0; else #endif /*lint -e{704} use shift instead of division */ *pTime = pSMFData->time >> 8; *pTime = pSMFData->time >> 8; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * SMF_Event() *---------------------------------------------------------------------------- * Purpose: * Parse the next event in the file * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT SMF_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) { S_SMF_DATA* pSMFData; EAS_RESULT result; EAS_I32 i; EAS_U32 ticks; EAS_U32 temp; /* establish pointer to instance data */ pSMFData = (S_SMF_DATA*) pInstData; if (pSMFData->state >= EAS_STATE_OPEN) return EAS_SUCCESS; if (!pSMFData->nextStream) { return EAS_ERROR_FILE_FORMAT; } /* get current ticks */ ticks = pSMFData->nextStream->ticks; /* assume that an error occurred */ pSMFData->state = EAS_STATE_ERROR; #ifdef JET_INTERFACE /* if JET has track muted, set parser mode to mute */ if (pSMFData->nextStream->midiStream.jetData & MIDI_FLAGS_JET_MUTE) parserMode = eParserModeMute; #endif /* parse the next event from all the streams */ if ((result = SMF_ParseEvent(pEASData, pSMFData, pSMFData->nextStream, parserMode)) != EAS_SUCCESS) { /* check for unexpected end-of-file */ if (result != EAS_EOF) return result; /* indicate end of track for this stream */ pSMFData->nextStream->ticks = SMF_END_OF_TRACK; } /* get next delta time, unless already at end of track */ else if (pSMFData->nextStream->ticks != SMF_END_OF_TRACK) { if ((result = SMF_GetDeltaTime(pEASData->hwInstData, pSMFData->nextStream)) != EAS_SUCCESS) { /* check for unexpected end-of-file */ if (result != EAS_EOF) return result; /* indicate end of track for this stream */ pSMFData->nextStream->ticks = SMF_END_OF_TRACK; } /* if zero delta to next event, stay with this stream */ else if (pSMFData->nextStream->ticks == ticks) { pSMFData->state = EAS_STATE_PLAY; return EAS_SUCCESS; } } /* find next event in all streams */ temp = 0x7ffffff; pSMFData->nextStream = NULL; for (i = 0; i < pSMFData->numStreams; i++) { if (pSMFData->streams[i].ticks < temp) { temp = pSMFData->streams[i].ticks; pSMFData->nextStream = &pSMFData->streams[i]; } } /* are there any more events to parse? */ if (pSMFData->nextStream) { pSMFData->state = EAS_STATE_PLAY; /* update the time of the next event */ SMF_UpdateTime(pSMFData, pSMFData->nextStream->ticks - ticks); } else { pSMFData->state = EAS_STATE_STOPPING; VMReleaseAllVoices(pEASData->pVoiceMgr, pSMFData->pSynth); } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * SMF_State() *---------------------------------------------------------------------------- * Purpose: * Returns the current state of the stream * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * pState - pointer to variable to store state * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_RESULT SMF_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) { S_SMF_DATA* pSMFData; /* establish pointer to instance data */ pSMFData = (S_SMF_DATA*) pInstData; /* if stopping, check to see if synth voices are active */ if (pSMFData->state == EAS_STATE_STOPPING) { if (VMActiveVoices(pSMFData->pSynth) == 0) pSMFData->state = EAS_STATE_STOPPED; } if (pSMFData->state == EAS_STATE_PAUSING) { if (VMActiveVoices(pSMFData->pSynth) == 0) pSMFData->state = EAS_STATE_PAUSED; } /* return current state */ *pState = pSMFData->state; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * SMF_Close() *---------------------------------------------------------------------------- * Purpose: * Close the file and clean up * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT SMF_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_SMF_DATA* pSMFData; EAS_I32 i; EAS_RESULT result; pSMFData = (S_SMF_DATA*) pInstData; /* close all the streams */ for (i = 0; i < pSMFData->numStreams; i++) { if (pSMFData->streams[i].fileHandle != NULL) { if ((result = EAS_HWCloseFile(pEASData->hwInstData, pSMFData->streams[i].fileHandle)) != EAS_SUCCESS) return result; } } if (pSMFData->fileHandle != NULL) if ((result = EAS_HWCloseFile(pEASData->hwInstData, pSMFData->fileHandle)) != EAS_SUCCESS) return result; /* free the synth */ if (pSMFData->pSynth != NULL) VMMIDIShutdown(pEASData, pSMFData->pSynth); /* if using dynamic memory, free it */ if (!pEASData->staticMemoryModel) { if (pSMFData->streams) EAS_HWFree(pEASData->hwInstData, pSMFData->streams); /* free the instance data */ EAS_HWFree(pEASData->hwInstData, pSMFData); } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * SMF_Reset() *---------------------------------------------------------------------------- * Purpose: * Reset the sequencer. Used for locating backwards in the file. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT SMF_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_SMF_DATA* pSMFData; EAS_I32 i; EAS_RESULT result; EAS_U32 ticks; pSMFData = (S_SMF_DATA*) pInstData; /* reset time to zero */ pSMFData->time = 0; /* reset the synth */ VMReset(pEASData->pVoiceMgr, pSMFData->pSynth, EAS_TRUE); /* find the start of each track */ ticks = 0x7fffffffL; pSMFData->nextStream = NULL; for (i = 0; i < pSMFData->numStreams; i++) { /* reset file position to first byte of data in track */ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pSMFData->streams[i].fileHandle, pSMFData->streams[i].startFilePos)) != EAS_SUCCESS) return result; /* initalize some data */ pSMFData->streams[i].ticks = 0; /* initalize the MIDI parser data */ EAS_InitMIDIStream(&pSMFData->streams[i].midiStream); /* parse the first delta time in each stream */ if ((result = SMF_GetDeltaTime(pEASData->hwInstData,&pSMFData->streams[i])) != EAS_SUCCESS) return result; if (pSMFData->streams[i].ticks < ticks) { ticks = pSMFData->streams[i].ticks; pSMFData->nextStream = &pSMFData->streams[i]; } } pSMFData->state = EAS_STATE_READY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * SMF_Pause() *---------------------------------------------------------------------------- * Purpose: * Pauses the sequencer. Mutes all voices and sets state to pause. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT SMF_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_SMF_DATA *pSMFData; /* can't pause a stopped stream */ pSMFData = (S_SMF_DATA*) pInstData; if (pSMFData->state == EAS_STATE_STOPPED) return EAS_ERROR_ALREADY_STOPPED; /* mute the synthesizer */ VMMuteAllVoices(pEASData->pVoiceMgr, pSMFData->pSynth); pSMFData->state = EAS_STATE_PAUSING; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * SMF_Resume() *---------------------------------------------------------------------------- * Purpose: * Resume playing after a pause, sets state back to playing. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_RESULT SMF_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_SMF_DATA *pSMFData; /* can't resume a stopped stream */ pSMFData = (S_SMF_DATA*) pInstData; if (pSMFData->state == EAS_STATE_STOPPED) return EAS_ERROR_ALREADY_STOPPED; /* nothing to do but resume playback */ pSMFData->state = EAS_STATE_PLAY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * SMF_SetData() *---------------------------------------------------------------------------- * Purpose: * Sets parser parameters * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_RESULT SMF_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) { S_SMF_DATA *pSMFData; pSMFData = (S_SMF_DATA*) pInstData; switch (param) { /* set metadata callback */ case PARSER_DATA_METADATA_CB: EAS_HWMemCpy(&pSMFData->metadata, (void*) value, sizeof(S_METADATA_CB)); break; #ifdef JET_INTERFACE /* set jet segment and track ID of all tracks for callback function */ case PARSER_DATA_JET_CB: { EAS_U32 i; EAS_U32 bit = (EAS_U32) value; bit = (bit << JET_EVENT_SEG_SHIFT) & JET_EVENT_SEG_MASK; for (i = 0; i < pSMFData->numStreams; i++) pSMFData->streams[i].midiStream.jetData = (pSMFData->streams[i].midiStream.jetData & ~(JET_EVENT_TRACK_MASK | JET_EVENT_SEG_MASK)) | i << JET_EVENT_TRACK_SHIFT | bit | MIDI_FLAGS_JET_CB; pSMFData->flags |= SMF_FLAGS_JET_STREAM; } break; /* set state of all mute flags at once */ case PARSER_DATA_MUTE_FLAGS: { EAS_INT i; EAS_U32 bit = (EAS_U32) value; for (i = 0; i < pSMFData->numStreams; i++) { if (bit & 1) pSMFData->streams[i].midiStream.jetData |= MIDI_FLAGS_JET_MUTE; else pSMFData->streams[i].midiStream.jetData &= ~MIDI_FLAGS_JET_MUTE; bit >>= 1; } } break; /* set track mute */ case PARSER_DATA_SET_MUTE: if (value < pSMFData->numStreams) pSMFData->streams[value].midiStream.jetData |= MIDI_FLAGS_JET_MUTE; else return EAS_ERROR_PARAMETER_RANGE; break; /* clear track mute */ case PARSER_DATA_CLEAR_MUTE: if (value < pSMFData->numStreams) pSMFData->streams[value].midiStream.jetData &= ~MIDI_FLAGS_JET_MUTE; else return EAS_ERROR_PARAMETER_RANGE; break; #endif default: return EAS_ERROR_INVALID_PARAMETER; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * SMF_GetData() *---------------------------------------------------------------------------- * Purpose: * Retrieves parser parameters * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) reserved for future use */ EAS_RESULT SMF_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) { S_SMF_DATA *pSMFData; pSMFData = (S_SMF_DATA*) pInstData; switch (param) { /* return file type */ case PARSER_DATA_FILE_TYPE: if (pSMFData->numStreams == 1) *pValue = EAS_FILE_SMF0; else *pValue = EAS_FILE_SMF1; break; /* now handled in eas_public.c */ #if 0 case PARSER_DATA_POLYPHONY: if (pSMFData->pSynth) VMGetPolyphony(pEASData->pVoiceMgr, pSMFData->pSynth, pValue); else return EAS_ERROR_NOT_VALID_IN_THIS_STATE; break; case PARSER_DATA_PRIORITY: if (pSMFData->pSynth) VMGetPriority(pEASData->pVoiceMgr, pSMFData->pSynth, pValue); break; /* set transposition */ case PARSER_DATA_TRANSPOSITION: *pValue = pSMFData->transposition; break; #endif case PARSER_DATA_SYNTH_HANDLE: *pValue = (EAS_I32) pSMFData->pSynth; break; default: return EAS_ERROR_INVALID_PARAMETER; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * SMF_GetVarLenData() *---------------------------------------------------------------------------- * Purpose: * Reads a varible length quantity from an SMF file * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT SMF_GetVarLenData (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_U32 *pData) { EAS_RESULT result; EAS_U32 data; EAS_U8 c; /* read until bit 7 is zero */ data = 0; do { if ((result = EAS_HWGetByte(hwInstData, fileHandle,&c)) != EAS_SUCCESS) return result; data = (data << 7) | (c & 0x7f); } while (c & 0x80); *pData = data; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * SMF_GetDeltaTime() *---------------------------------------------------------------------------- * Purpose: * Reads a varible length quantity from an SMF file * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT SMF_GetDeltaTime (EAS_HW_DATA_HANDLE hwInstData, S_SMF_STREAM *pSMFStream) { EAS_RESULT result; EAS_U32 ticks; if ((result = SMF_GetVarLenData(hwInstData, pSMFStream->fileHandle, &ticks)) != EAS_SUCCESS) return result; pSMFStream->ticks += ticks; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * SMF_ParseMetaEvent() *---------------------------------------------------------------------------- * Purpose: * Reads a varible length quantity from an SMF file * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT SMF_ParseMetaEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream) { EAS_RESULT result; EAS_U32 len; EAS_I32 pos; EAS_U32 temp; EAS_U8 c; /* get the meta-event type */ if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) return result; /* get the length */ if ((result = SMF_GetVarLenData(pEASData->hwInstData, pSMFStream->fileHandle, &len)) != EAS_SUCCESS) return result; /* get the current file position so we can skip the event */ if ((result = EAS_HWFilePos(pEASData->hwInstData, pSMFStream->fileHandle, &pos)) != EAS_SUCCESS) return result; pos += (EAS_I32) len; /* end of track? */ if (c == SMF_META_END_OF_TRACK) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Meta-event: end of track\n", c, len); */ } pSMFStream->ticks = SMF_END_OF_TRACK; } /* tempo event? */ else if (c == SMF_META_TEMPO) { /* read the 3-byte timebase value */ temp = 0; while (len--) { if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) return result; temp = (temp << 8) | c; } pSMFData->tickConv = (EAS_U16) (((temp * 1024) / pSMFData->ppqn + 500) / 1000); pSMFData->flags |= SMF_FLAGS_HAS_TEMPO; } /* check for time signature - see iMelody spec V1.4 section 4.1.2.2.3.6 */ else if (c == SMF_META_TIME_SIGNATURE) { pSMFData->flags |= SMF_FLAGS_HAS_TIME_SIG; } /* if the host has registered a metadata callback return the metadata */ else if (pSMFData->metadata.callback) { EAS_I32 readLen; E_EAS_METADATA_TYPE metaType; metaType = EAS_METADATA_UNKNOWN; /* only process title on the first track */ if (c == SMF_META_SEQTRK_NAME) metaType = EAS_METADATA_TITLE; else if (c == SMF_META_TEXT) metaType = EAS_METADATA_TEXT; else if (c == SMF_META_COPYRIGHT) metaType = EAS_METADATA_COPYRIGHT; else if (c == SMF_META_LYRIC) metaType = EAS_METADATA_LYRIC; if (metaType != EAS_METADATA_UNKNOWN) { readLen = pSMFData->metadata.bufferSize - 1; if ((EAS_I32) len < readLen) readLen = (EAS_I32) len; if ((result = EAS_HWReadFile(pEASData->hwInstData, pSMFStream->fileHandle, pSMFData->metadata.buffer, readLen, &readLen)) != EAS_SUCCESS) return result; pSMFData->metadata.buffer[readLen] = 0; pSMFData->metadata.callback(metaType, pSMFData->metadata.buffer, pSMFData->metadata.pUserData); } } /* position file to next event - in case we ignored all or part of the meta-event */ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pSMFStream->fileHandle, pos)) != EAS_SUCCESS) return result; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Meta-event: type=%02x, len=%d\n", c, len); */ } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * SMF_ParseSysEx() *---------------------------------------------------------------------------- * Purpose: * Reads a varible length quantity from an SMF file * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT SMF_ParseSysEx (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_U8 f0, EAS_INT parserMode) { EAS_RESULT result; EAS_U32 len; EAS_U8 c; /* get the length */ if ((result = SMF_GetVarLenData(pEASData->hwInstData, pSMFStream->fileHandle, &len)) != EAS_SUCCESS) return result; /* start of SysEx message? */ if (f0 == 0xf0) { if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, f0, parserMode)) != EAS_SUCCESS) return result; } /* feed the SysEx to the stream parser */ while (len--) { if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) return result; if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, c, parserMode)) != EAS_SUCCESS) return result; /* check for GM system ON */ if (pSMFStream->midiStream.flags & MIDI_FLAG_GM_ON) pSMFData->flags |= SMF_FLAGS_HAS_GM_ON; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * SMF_ParseEvent() *---------------------------------------------------------------------------- * Purpose: * Reads a varible length quantity from an SMF file * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT SMF_ParseEvent (S_EAS_DATA *pEASData, S_SMF_DATA *pSMFData, S_SMF_STREAM *pSMFStream, EAS_INT parserMode) { EAS_RESULT result; EAS_U8 c; /* get the event type */ if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) return result; /* parse meta-event */ if (c == 0xff) { if ((result = SMF_ParseMetaEvent(pEASData, pSMFData, pSMFStream)) != EAS_SUCCESS) return result; } /* parse SysEx */ else if ((c == 0xf0) || (c == 0xf7)) { if ((result = SMF_ParseSysEx(pEASData, pSMFData, pSMFStream, c, parserMode)) != EAS_SUCCESS) return result; } /* parse MIDI message */ else { if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, c, parserMode)) != EAS_SUCCESS) return result; /* keep streaming data to the MIDI parser until the message is complete */ while (pSMFStream->midiStream.pending) { if ((result = EAS_HWGetByte(pEASData->hwInstData, pSMFStream->fileHandle, &c)) != EAS_SUCCESS) return result; if ((result = EAS_ParseMIDIStream(pEASData, pSMFData->pSynth, &pSMFStream->midiStream, c, parserMode)) != EAS_SUCCESS) return result; } } /* chase mode logic */ if (pSMFData->time == 0) { if (pSMFData->flags & SMF_FLAGS_CHASE_MODE) { if (pSMFStream->midiStream.flags & MIDI_FLAG_FIRST_NOTE) pSMFData->flags &= ~SMF_FLAGS_CHASE_MODE; } else if ((pSMFData->flags & SMF_FLAGS_SETUP_BAR) == SMF_FLAGS_SETUP_BAR) pSMFData->flags = (pSMFData->flags & ~SMF_FLAGS_SETUP_BAR) | SMF_FLAGS_CHASE_MODE; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * SMF_ParseHeader() *---------------------------------------------------------------------------- * Purpose: * Parses the header of an SMF file, allocates memory the stream parsers and initializes the * stream parsers. * * Inputs: * pEASData - pointer to overall EAS data structure * pSMFData - pointer to parser instance data * fileHandle - file handle * fileOffset - offset in the file where the header data starts, usually 0 * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -e{801} we know that 'goto' is deprecated - but it's cleaner in this case */ EAS_RESULT SMF_ParseHeader (EAS_HW_DATA_HANDLE hwInstData, S_SMF_DATA *pSMFData) { EAS_RESULT result; EAS_I32 i; EAS_U16 division; EAS_U32 chunkSize; EAS_U32 chunkStart; EAS_U32 temp; EAS_U32 ticks; /* rewind the file and find the end of the header chunk */ if ((result = EAS_HWFileSeek(hwInstData, pSMFData->fileHandle, pSMFData->fileOffset + SMF_OFS_HEADER_SIZE)) != EAS_SUCCESS) goto ReadError; if ((result = EAS_HWGetDWord(hwInstData, pSMFData->fileHandle, &chunkSize, EAS_TRUE)) != EAS_SUCCESS) goto ReadError; /* determine the number of tracks */ if ((result = EAS_HWFileSeek(hwInstData, pSMFData->fileHandle, pSMFData->fileOffset + SMF_OFS_NUM_TRACKS)) != EAS_SUCCESS) goto ReadError; if ((result = EAS_HWGetWord(hwInstData, pSMFData->fileHandle, &pSMFData->numStreams, EAS_TRUE)) != EAS_SUCCESS) goto ReadError; /* limit the number of tracks */ if (pSMFData->numStreams > MAX_SMF_STREAMS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "SMF file contains %u tracks, playing %d tracks\n", pSMFData->numStreams, MAX_SMF_STREAMS); */ } pSMFData->numStreams = MAX_SMF_STREAMS; } else if (pSMFData->numStreams == 0) { /* avoid 0 sized allocation */ return EAS_ERROR_PARAMETER_RANGE; } /* get the time division */ if ((result = EAS_HWGetWord(hwInstData, pSMFData->fileHandle, &division, EAS_TRUE)) != EAS_SUCCESS) goto ReadError; /* setup default timebase for 120 bpm */ pSMFData->ppqn = 192; if (!division || division & 0x8000) { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING,"No support for SMPTE code timebase\n"); */ } else pSMFData->ppqn = (division & 0x7fff); pSMFData->tickConv = (EAS_U16) (((SMF_DEFAULT_TIMEBASE * 1024) / pSMFData->ppqn + 500) / 1000); /* dynamic memory allocation, allocate memory for streams */ if (pSMFData->streams == NULL) { pSMFData->streams = EAS_HWMalloc(hwInstData,sizeof(S_SMF_STREAM) * pSMFData->numStreams); if (pSMFData->streams == NULL) return EAS_ERROR_MALLOC_FAILED; /* zero the memory to insure complete initialization */ EAS_HWMemSet((void *)(pSMFData->streams), 0, sizeof(S_SMF_STREAM) * pSMFData->numStreams); } /* find the start of each track */ chunkStart = (EAS_U32) pSMFData->fileOffset; ticks = 0x7fffffffL; pSMFData->nextStream = NULL; for (i = 0; i < pSMFData->numStreams; i++) { for (;;) { /* calculate start of next chunk - checking for errors */ temp = chunkStart + SMF_CHUNK_INFO_SIZE + chunkSize; if (temp <= chunkStart) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING,"Error in chunk size at offset %d\n", chunkStart); */ } return EAS_ERROR_FILE_FORMAT; } chunkStart = temp; /* seek to the start of the next chunk */ if ((result = EAS_HWFileSeek(hwInstData, pSMFData->fileHandle, (EAS_I32) chunkStart)) != EAS_SUCCESS) goto ReadError; /* read the chunk identifier */ if ((result = EAS_HWGetDWord(hwInstData, pSMFData->fileHandle, &temp, EAS_TRUE)) != EAS_SUCCESS) goto ReadError; /* read the chunk size */ if ((result = EAS_HWGetDWord(hwInstData, pSMFData->fileHandle, &chunkSize, EAS_TRUE)) != EAS_SUCCESS) goto ReadError; /* make sure this is an 'MTrk' chunk */ if (temp == SMF_CHUNK_TYPE_TRACK) break; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING,"Unexpected chunk type: 0x%08x\n", temp); */ } } /* initalize some data */ pSMFData->streams[i].ticks = 0; pSMFData->streams[i].fileHandle = pSMFData->fileHandle; /* NULL the file handle so we don't try to close it twice */ pSMFData->fileHandle = NULL; /* save this file position as the start of the track */ pSMFData->streams[i].startFilePos = (EAS_I32) chunkStart + SMF_CHUNK_INFO_SIZE; /* initalize the MIDI parser data */ EAS_InitMIDIStream(&pSMFData->streams[i].midiStream); /* parse the first delta time in each stream */ if ((result = SMF_GetDeltaTime(hwInstData, &pSMFData->streams[i])) != EAS_SUCCESS) goto ReadError; if (pSMFData->streams[i].ticks < ticks) { ticks = pSMFData->streams[i].ticks; pSMFData->nextStream = &pSMFData->streams[i]; } /* more tracks to do, create a duplicate file handle */ if (i < (pSMFData->numStreams - 1)) { if ((result = EAS_HWDupHandle(hwInstData, pSMFData->streams[i].fileHandle, &pSMFData->fileHandle)) != EAS_SUCCESS) goto ReadError; } } /* update the time of the next event */ if (pSMFData->nextStream) SMF_UpdateTime(pSMFData, pSMFData->nextStream->ticks); return EAS_SUCCESS; /* ugly goto: but simpler than structured */ ReadError: if (result == EAS_EOF) return EAS_ERROR_FILE_FORMAT; return result; } /*---------------------------------------------------------------------------- * SMF_UpdateTime() *---------------------------------------------------------------------------- * Purpose: * Update the millisecond time base by converting the ticks into millieconds * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static void SMF_UpdateTime (S_SMF_DATA *pSMFData, EAS_U32 ticks) { EAS_U32 temp1, temp2; if (pSMFData->flags & SMF_FLAGS_CHASE_MODE) return; temp1 = (ticks >> 10) * pSMFData->tickConv; temp2 = (ticks & 0x3ff) * pSMFData->tickConv; pSMFData->time += (EAS_I32)((temp1 << 8) + (temp2 >> 2)); } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_imelodydata.h0000644000000000000000000000013213532747316027411 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.858000056 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_imelodydata.h0000644000175000001440000000607713532747316030214 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_imelodydata.h * * Contents and purpose: * SMF File Parser * * This file contains data declarations for the iMelody parser. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 778 $ * $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $ *---------------------------------------------------------------------------- */ #ifndef EAS_IMELODYDATA_H #define EAS_IMELODYDATA_H #include "eas_data.h" /* maximum line size as specified in iMelody V1.2 spec */ #define MAX_LINE_SIZE 75 /*---------------------------------------------------------------------------- * * S_IMELODY_DATA * * This structure contains the state data for the iMelody parser *---------------------------------------------------------------------------- */ typedef struct { EAS_FILE_HANDLE fileHandle; /* file handle */ S_SYNTH *pSynth; /* pointer to synth */ EAS_I32 fileOffset; /* offset to start of data */ EAS_I32 time; /* current time in 256ths of a msec */ EAS_I32 tickBase; /* basline length of 32nd note in 256th of a msec */ EAS_I32 tick; /* actual length of 32nd note in 256th of a msec */ EAS_I32 restTicks; /* ticks to rest after current note */ EAS_I32 startLine; /* file offset at start of line (for repeats) */ EAS_I32 repeatOffset; /* file offset to start of repeat section */ EAS_I32 repeatTime; /* time at start of repeat section */ S_METADATA_CB metadata; /* metadata callback */ EAS_I16 repeatCount; /* repeat counter */ EAS_U8 state; /* current state EAS_STATE_XXXX */ EAS_U8 style; /* from STYLE */ EAS_U8 index; /* index into buffer */ EAS_U8 octave; /* octave prefix */ EAS_U8 volume; /* current volume */ EAS_U8 note; /* MIDI note number */ EAS_I8 noteModifier; /* sharp or flat */ EAS_I8 buffer[MAX_LINE_SIZE+1]; /* buffer for ASCII data */ } S_IMELODY_DATA; #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_ota.c0000644000000000000000000000013213532747316025673 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.858000056 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_ota.c0000644000175000001440000010145513532747316026472 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_ota.c * * Contents and purpose: * OTA parser * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 795 $ * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ *---------------------------------------------------------------------------- */ #include "eas_data.h" #include "eas_miditypes.h" #include "eas_parser.h" #include "eas_report.h" #include "eas_host.h" #include "eas_midi.h" #include "eas_config.h" #include "eas_vm_protos.h" #include "eas_otadata.h" /* increase gain for mono ringtones */ #define OTA_GAIN_OFFSET 8 /* file definitions */ #define OTA_RINGTONE 0x25 #define OTA_SOUND 0x1d #define OTA_UNICODE 0x22 /* song type definitions */ #define OTA_BASIC_SONG_TYPE 0x01 #define OTA_TEMPORARY_SONG_TYPE 0x02 /* instruction ID coding */ #define OTA_PATTERN_HEADER_ID 0x00 #define OTA_NOTE_INST_ID 0x01 #define OTA_SCALE_INST_ID 0x02 #define OTA_STYLE_INST_ID 0x03 #define OTA_TEMPO_INST_ID 0x04 #define OTA_VOLUME_INST_ID 0x05 /* note durations */ #define OTA_NORMAL_DURATION 0x00 #define OTA_DOTTED_NOTE 0x01 #define OTA_DOUBLE_DOTTED_NOTE 0x02 #define OTA_TRIPLET_NOTE 0x03 /* loop count value for infinite loop */ #define OTA_INFINITE_LOOP 0x0f /* length of 32nd note in 1/256ths of a msec for 63 BPM tempo */ #define DEFAULT_TICK_CONV 30476 /* default channel and program for OTA playback */ #define OTA_CHANNEL 0 #define OTA_PROGRAM 80 #define OTA_VEL_MUL 4 #define OTA_VEL_OFS 67 #define OTA_VEL_DEFAULT 95 /* multiplier for fixed point triplet conversion */ #define TRIPLET_MULTIPLIER 683 #define TRIPLET_SHIFT 10 /* local prototypes */ static EAS_RESULT OTA_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); static EAS_RESULT OTA_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT OTA_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); static EAS_RESULT OTA_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode); static EAS_RESULT OTA_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); static EAS_RESULT OTA_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT OTA_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT OTA_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT OTA_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT OTA_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); static EAS_RESULT OTA_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); static EAS_RESULT OTA_ParseHeader (S_EAS_DATA *pEASData, S_OTA_DATA* pData); static EAS_RESULT OTA_FetchBitField (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, EAS_I32 numBits, EAS_U8 *pValue); static EAS_RESULT OTA_SavePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc); static EAS_RESULT OTA_RestorePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc); /*---------------------------------------------------------------------------- * * EAS_OTA_Parser * * This structure contains the functional interface for the OTA parser *---------------------------------------------------------------------------- */ const S_FILE_PARSER_INTERFACE EAS_OTA_Parser = { OTA_CheckFileType, OTA_Prepare, OTA_Time, OTA_Event, OTA_State, OTA_Close, OTA_Reset, OTA_Pause, OTA_Resume, NULL, OTA_SetData, OTA_GetData, NULL }; /*---------------------------------------------------------------------------- * * bpmTable * * BPM conversion table. Converts bpm values to 256ths of a millisecond for a 32nd note *---------------------------------------------------------------------------- */ static const EAS_U32 bpmTable[32] = { 76800, 68571, 61935, 54857, 48000, 42667, 38400, 34286, 30476, 27429, 24000, 21333, 19200, 17143, 15360, 13714, 12000, 10667, 9600, 8533, 7680, 6737, 6000, 5408, 4800, 4267, 3840, 3398, 3024, 2685, 2400, 2133 }; /*---------------------------------------------------------------------------- * OTA_CheckFileType() *---------------------------------------------------------------------------- * Purpose: * Check the file type to see if we can parse it * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT OTA_CheckFileType (S_EAS_DATA *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset) { S_OTA_DATA* pData; EAS_RESULT result; EAS_INT cmdLen; EAS_INT state; EAS_U8 temp; /* read the first byte, should be command length */ *ppHandle = NULL; if ((result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &temp)) != EAS_SUCCESS) return result; /* read all the commands */ cmdLen = temp; state = 0; while (cmdLen--) { /* read the command, upper 7 bits */ if ((result = EAS_HWGetByte(pEASData->hwInstData, fileHandle, &temp)) != EAS_SUCCESS) return result; temp = temp >> 1; if (state == 0) { if (temp != OTA_RINGTONE) break; state++; } else { if (temp == OTA_SOUND) { /* check for static memory allocation */ if (pEASData->staticMemoryModel) pData = EAS_CMEnumData(EAS_CM_OTA_DATA); else pData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_OTA_DATA)); if (!pData) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Malloc failed in OTA_Prepare\n"); */ } return EAS_ERROR_MALLOC_FAILED; } EAS_HWMemSet(pData, 0, sizeof(S_OTA_DATA)); /* return a pointer to the instance data */ pData->fileHandle = fileHandle; pData->fileOffset = offset; pData->state = EAS_STATE_OPEN; *ppHandle = pData; break; } if (temp != OTA_UNICODE) break; } } /* not recognized */ return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * OTA_Prepare() *---------------------------------------------------------------------------- * Purpose: * Prepare to parse the file. Allocates instance data (or uses static allocation for * static memory model). * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT OTA_Prepare (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_OTA_DATA* pData; EAS_RESULT result; /* check for valid state */ pData = (S_OTA_DATA*) pInstData; if (pData->state != EAS_STATE_OPEN) return EAS_ERROR_NOT_VALID_IN_THIS_STATE; /* instantiate a synthesizer */ if ((result = VMInitMIDI(pEASData, &pData->pSynth)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI returned %d\n", result); */ } return result; } pData->state = EAS_STATE_ERROR; if ((result = OTA_ParseHeader(pEASData, pData)) != EAS_SUCCESS) return result; pData->state = EAS_STATE_READY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * OTA_Time() *---------------------------------------------------------------------------- * Purpose: * Returns the time of the next event in msecs * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * pTime - pointer to variable to hold time of next event (in msecs) * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) common decoder interface - pEASData not used */ static EAS_RESULT OTA_Time (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime) { S_OTA_DATA *pData; pData = (S_OTA_DATA*) pInstData; /* return time in milliseconds */ /*lint -e{704} use shift instead of division */ *pTime = pData->time >> 8; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * OTA_Event() *---------------------------------------------------------------------------- * Purpose: * Parse the next event in the file * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT OTA_Event (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_INT parserMode) { S_OTA_DATA* pData; EAS_RESULT result; EAS_U32 duration; EAS_U8 temp; pData = (S_OTA_DATA*) pInstData; if (pData->state >= EAS_STATE_OPEN) return EAS_SUCCESS; /* initialize MIDI channel when the track starts playing */ if (pData->time == 0) { /* set program to square lead */ if (parserMode != eParserModeMetaData) VMProgramChange(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, OTA_PROGRAM); /* set channel volume to max */ if (parserMode != eParserModeMetaData) VMControlChange(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, 7, 127); } /* check for end of note */ if (pData->note) { /* stop the note */ VMStopNote(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, pData->note, 0); pData->note = 0; /* check for rest between notes */ if (pData->restTicks) { pData->time += (EAS_I32) pData->restTicks; pData->restTicks = 0; return EAS_SUCCESS; } } /* if not in a pattern, read the pattern header */ while (pData->current.patternLen == 0) { /* check for loop - don't do infinite loops when locating */ if (pData->loopCount && ((parserMode == eParserModePlay) || (pData->loopCount != OTA_INFINITE_LOOP))) { /* if not infinite loop, decrement loop count */ if (pData->loopCount != OTA_INFINITE_LOOP) pData->loopCount--; /* back to start of pattern*/ if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS) return result; } /* if no previous position to restore, continue forward */ else if (pData->restore.fileOffset < 0) { /* check for end of song */ if (pData->numPatterns == 0) { pData->state = EAS_STATE_STOPPING; VMReleaseAllVoices(pEASData->pVoiceMgr, pData->pSynth); return EAS_SUCCESS; } /* read the next pattern header */ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS) return result; if (temp != OTA_PATTERN_HEADER_ID) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA pattern header\n"); */ } return EAS_ERROR_FILE_FORMAT; } /* get the pattern ID */ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &pData->currentPattern)) != EAS_SUCCESS) return result; /* get the loop count */ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &pData->loopCount)) != EAS_SUCCESS) return result; /* get the pattern length */ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &pData->current.patternLen)) != EAS_SUCCESS) return result; /* if pattern definition, save the current position */ if (pData->current.patternLen) { if ((result = OTA_SavePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS) return result; } /* if pattern length is zero, repeat a previous pattern */ else { /* make sure it's a valid pattern */ if (pData->patterns[pData->currentPattern].fileOffset < 0) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "OTA pattern error, invalid pattern specified\n"); */ } return EAS_ERROR_FILE_FORMAT; } /* save current position and data */ if ((result = OTA_SavePosition(pEASData->hwInstData, pData, &pData->restore)) != EAS_SUCCESS) return result; /* seek to the pattern in the file */ if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->patterns[pData->currentPattern])) != EAS_SUCCESS) return result; } /* decrement pattern count */ pData->numPatterns--; } /* restore previous position */ else { if ((result = OTA_RestorePosition(pEASData->hwInstData, pData, &pData->restore)) != EAS_SUCCESS) return result; } } /* get the next event */ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS) return result; switch (temp) { case OTA_NOTE_INST_ID: /* fetch note value */ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &pData->note)) != EAS_SUCCESS) return result; /* fetch note duration */ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS) return result; duration = pData->tick * (0x20 >> temp); /* fetch note duration modifier */ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &temp)) != EAS_SUCCESS) return result; switch (temp) { case OTA_NORMAL_DURATION: break; case OTA_DOTTED_NOTE: duration += duration >> 1; break; case OTA_DOUBLE_DOTTED_NOTE: duration += (duration >> 1) + (duration >> 2); break; case OTA_TRIPLET_NOTE: duration = (duration * TRIPLET_MULTIPLIER) >> TRIPLET_SHIFT; break; default: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unrecognized note duration ignored\n"); */ } break; } /* check for note */ if (pData->note) { /* determine note length based on style */ switch (pData->style) { case 0: pData->restTicks = duration >> 4; break; case 1: pData->restTicks = 0; break; case 2: pData->restTicks = duration >> 1; break; default: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unrecognized note style ignored\n"); */ } } /* add octave */ pData->note += pData->octave; if (parserMode == eParserModePlay) VMStartNote(pEASData->pVoiceMgr, pData->pSynth, OTA_CHANNEL, pData->note, pData->velocity); pData->time += (EAS_I32) duration - (EAS_I32) pData->restTicks; } /* this is a rest */ else pData->time += (EAS_I32) duration; break; case OTA_SCALE_INST_ID: /* fetch octave */ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &temp)) != EAS_SUCCESS) return result; pData->octave = (EAS_U8) (temp * 12 + 59); break; case OTA_STYLE_INST_ID: /* fetch note style */ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 2, &pData->style)) != EAS_SUCCESS) return result; break; case OTA_TEMPO_INST_ID: /* fetch tempo */ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 5, &temp)) != EAS_SUCCESS) return result; pData->tick = bpmTable[temp]; break; case OTA_VOLUME_INST_ID: /* fetch volume */ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &temp)) != EAS_SUCCESS) return result; pData->velocity = temp ? (EAS_U8) (temp * OTA_VEL_MUL + OTA_VEL_OFS) : 0; break; default: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unexpected instruction ID in OTA stream\n"); */ } return EAS_ERROR_FILE_FORMAT; } /* decrement pattern length */ pData->current.patternLen--; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * OTA_State() *---------------------------------------------------------------------------- * Purpose: * Returns the current state of the stream * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * pState - pointer to variable to store state * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) common decoder interface - pEASData not used */ static EAS_RESULT OTA_State (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pState) { S_OTA_DATA* pData; /* establish pointer to instance data */ pData = (S_OTA_DATA*) pInstData; /* if stopping, check to see if synth voices are active */ if (pData->state == EAS_STATE_STOPPING) { if (VMActiveVoices(pData->pSynth) == 0) pData->state = EAS_STATE_STOPPED; } if (pData->state == EAS_STATE_PAUSING) { if (VMActiveVoices(pData->pSynth) == 0) pData->state = EAS_STATE_PAUSED; } /* return current state */ *pState = pData->state; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * OTA_Close() *---------------------------------------------------------------------------- * Purpose: * Close the file and clean up * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT OTA_Close (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_OTA_DATA* pData; EAS_RESULT result; pData = (S_OTA_DATA*) pInstData; /* close the file */ if ((result = EAS_HWCloseFile(pEASData->hwInstData, pData->fileHandle)) != EAS_SUCCESS) return result; /* free the synth */ if (pData->pSynth != NULL) VMMIDIShutdown(pEASData, pData->pSynth); /* if using dynamic memory, free it */ if (!pEASData->staticMemoryModel) EAS_HWFree(pEASData->hwInstData, pData); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * OTA_Reset() *---------------------------------------------------------------------------- * Purpose: * Reset the sequencer. Used for locating backwards in the file. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT OTA_Reset (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_OTA_DATA* pData; EAS_RESULT result; pData = (S_OTA_DATA*) pInstData; /* reset the synth */ VMReset(pEASData->pVoiceMgr, pData->pSynth, EAS_TRUE); pData->note = 0; /* reset file position and re-parse header */ pData->state = EAS_STATE_ERROR; if ((result = OTA_ParseHeader (pEASData, pData)) != EAS_SUCCESS) return result; pData->state = EAS_STATE_READY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * OTA_Pause() *---------------------------------------------------------------------------- * Purpose: * Pauses the sequencer. Mutes all voices and sets state to pause. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT OTA_Pause (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_OTA_DATA *pData; /* can't pause a stopped stream */ pData = (S_OTA_DATA*) pInstData; if (pData->state == EAS_STATE_STOPPED) return EAS_ERROR_ALREADY_STOPPED; /* mute the synthesizer */ VMMuteAllVoices(pEASData->pVoiceMgr, pData->pSynth); pData->state = EAS_STATE_PAUSING; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * OTA_Resume() *---------------------------------------------------------------------------- * Purpose: * Resume playing after a pause, sets state back to playing. * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) common decoder interface - pEASData not used */ static EAS_RESULT OTA_Resume (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData) { S_OTA_DATA *pData; /* can't resume a stopped stream */ pData = (S_OTA_DATA*) pInstData; if (pData->state == EAS_STATE_STOPPED) return EAS_ERROR_ALREADY_STOPPED; /* nothing to do but resume playback */ pData->state = EAS_STATE_PLAY; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * OTA_SetData() *---------------------------------------------------------------------------- * Purpose: * Return file type * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) common decoder interface - pEASData not used */ static EAS_RESULT OTA_SetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) { S_OTA_DATA *pData; pData = (S_OTA_DATA *) pInstData; switch (param) { /* set metadata callback */ case PARSER_DATA_METADATA_CB: EAS_HWMemCpy(&pData->metadata, (void*) value, sizeof(S_METADATA_CB)); break; default: return EAS_ERROR_INVALID_PARAMETER; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * OTA_GetData() *---------------------------------------------------------------------------- * Purpose: * Return file type * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) common decoder interface - pEASData not used */ static EAS_RESULT OTA_GetData (S_EAS_DATA *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) { S_OTA_DATA *pData; pData = (S_OTA_DATA*) pInstData; switch (param) { /* return file type as OTA */ case PARSER_DATA_FILE_TYPE: *pValue = EAS_FILE_OTA; break; #if 0 /* set transposition */ case PARSER_DATA_TRANSPOSITION: *pValue = pData->transposition; break; #endif case PARSER_DATA_SYNTH_HANDLE: *pValue = (EAS_I32) pData->pSynth; break; case PARSER_DATA_GAIN_OFFSET: *pValue = OTA_GAIN_OFFSET; break; default: return EAS_ERROR_INVALID_PARAMETER; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * OTA_ParseHeader() *---------------------------------------------------------------------------- * Purpose: * Prepare to parse the file. Allocates instance data (or uses static allocation for * static memory model). * * Inputs: * pEASData - pointer to overall EAS data structure * handle - pointer to file handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT OTA_ParseHeader (S_EAS_DATA *pEASData, S_OTA_DATA* pData) { EAS_RESULT result; EAS_INT i; EAS_INT state; EAS_U8 temp; EAS_U8 titleLen; /* initialize some data */ pData->flags = 0; pData->time = 0; pData->tick = DEFAULT_TICK_CONV; pData->patterns[0].fileOffset = pData->patterns[1].fileOffset = pData->patterns[2].fileOffset = pData->patterns[3].fileOffset = -1; pData->current.bitCount = 0; pData->current.patternLen = 0; pData->loopCount = 0; pData->restore.fileOffset = -1; pData->note = 0; pData->restTicks = 0; pData->velocity = OTA_VEL_DEFAULT; pData->style = 0; pData->octave = 59; /* seek to start of data */ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pData->fileHandle, pData->fileOffset)) != EAS_SUCCESS) return result; /* read the first byte, should be command length */ if ((result = EAS_HWGetByte(pEASData->hwInstData, pData->fileHandle, &temp)) != EAS_SUCCESS) return result; /* read all the commands */ i = temp; state = 0; while (i--) { /* fetch command, always starts on byte boundary */ pData->current.bitCount = 0; if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 7, &temp)) != EAS_SUCCESS) return result; if (state == 0) { if (temp != OTA_RINGTONE) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA Ring Tone Programming type\n"); */ } return EAS_ERROR_FILE_FORMAT; } state++; } else { if (temp == OTA_SOUND) break; if (temp == OTA_UNICODE) pData->flags |= OTA_FLAGS_UNICODE; else { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA Sound or Unicode type\n"); */ } return EAS_ERROR_FILE_FORMAT; } } } /* get song type */ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 3, &temp)) != EAS_SUCCESS) return result; /* check for basic song type */ if (temp == OTA_BASIC_SONG_TYPE) { /* fetch title length */ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 4, &titleLen)) != EAS_SUCCESS) return result; /* if unicode, double the length */ if (pData->flags & OTA_FLAGS_UNICODE) titleLen = (EAS_U8) (titleLen << 1); /* zero the metadata buffer */ if (pData->metadata.buffer) EAS_HWMemSet(pData->metadata.buffer, 0, pData->metadata.bufferSize); /* read the song title */ for (i = 0; i < titleLen; i++) { /* fetch character */ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &temp)) != EAS_SUCCESS) return result; /* check for metadata callback */ if (pData->metadata.callback) { if (i < (pData->metadata.bufferSize - 1)) pData->metadata.buffer[i] = (char) temp; } } /* if host has registered callback, call it now */ if (pData->metadata.callback) (*pData->metadata.callback)(EAS_METADATA_TITLE, pData->metadata.buffer, pData->metadata.pUserData); } /* must be temporary song */ else if (temp != OTA_TEMPORARY_SONG_TYPE) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected OTA basic or temporary song type\n"); */ } return EAS_ERROR_FILE_FORMAT; } /* get the song length */ if ((result = OTA_FetchBitField(pEASData->hwInstData, pData, 8, &pData->numPatterns)) != EAS_SUCCESS) return result; /* sanity check */ if (pData->numPatterns == 0) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "OTA number of patterns is zero\n"); */ } return EAS_ERROR_FILE_FORMAT; } /* at start of first pattern */ return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * OTA_FetchBitField() *---------------------------------------------------------------------------- * Purpose: * Fetch a specified number of bits from the input stream * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT OTA_FetchBitField (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, EAS_I32 numBits, EAS_U8 *pValue) { EAS_RESULT result; EAS_I32 bitsLeft; EAS_U8 value; value = 0; /* do we have enough bits? */ bitsLeft = pData->current.bitCount - numBits; /* not enough bits, assemble them from 2 characters */ if (bitsLeft < 0) { /* grab the remaining bits from the previous byte */ if (pData->current.bitCount) /*lint -e{504,734} this is a legitimate shift operation */ value = pData->current.dataByte << -bitsLeft; /* read the next byte */ if ((result = EAS_HWGetByte(hwInstData, pData->fileHandle, &pData->current.dataByte)) != EAS_SUCCESS) return result; bitsLeft += 8; } /* more bits than needed? */ if (bitsLeft > 0) { value |= pData->current.dataByte >> bitsLeft; pData->current.bitCount = (EAS_U8) bitsLeft; pData->current.dataByte = pData->current.dataByte & (0xff >> (8 - bitsLeft)); } /* exactly the right number of bits */ else { value |= pData->current.dataByte; pData->current.bitCount = 0; } *pValue = value; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * OTA_SavePosition() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT OTA_SavePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc) { EAS_HWMemCpy(pLoc, &pData->current, sizeof(S_OTA_LOC)); return EAS_HWFilePos(hwInstData, pData->fileHandle, &pLoc->fileOffset); } /*---------------------------------------------------------------------------- * OTA_RestorePosition() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT OTA_RestorePosition (EAS_HW_DATA_HANDLE hwInstData, S_OTA_DATA *pData, S_OTA_LOC *pLoc) { EAS_HWMemCpy(&pData->current, pLoc, sizeof(S_OTA_LOC)); pData->restore.fileOffset = -1; return EAS_HWFileSeek(hwInstData, pData->fileHandle, pLoc->fileOffset); } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_imaadpcm.c0000644000000000000000000000013213532747316026663 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.858000056 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_imaadpcm.c0000644000175000001440000002764213532747316027467 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_imaadpcm.c * * Contents and purpose: * Implements the IMA ADPCM decoder * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 847 $ * $Date: 2007-08-27 21:30:08 -0700 (Mon, 27 Aug 2007) $ *---------------------------------------------------------------------------- */ #include "eas_data.h" #include "eas_host.h" #include "eas_pcm.h" #include "eas_math.h" #include "eas_report.h" // #define _DEBUG_IMA_ADPCM_LOCATE /*---------------------------------------------------------------------------- * externs *---------------------------------------------------------------------------- */ extern const EAS_I16 imaIndexTable[]; extern const EAS_I16 imaStepSizeTable[]; /*---------------------------------------------------------------------------- * prototypes *---------------------------------------------------------------------------- */ static EAS_RESULT IMADecoderInit (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); static EAS_RESULT IMADecoderSample (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); static void IMADecoderADPCM (S_DECODER_STATE *pState, EAS_U8 nibble); static EAS_RESULT IMADecoderLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time); /*---------------------------------------------------------------------------- * IMA ADPCM Decoder interface *---------------------------------------------------------------------------- */ const S_DECODER_INTERFACE IMADecoder = { IMADecoderInit, IMADecoderSample, IMADecoderLocate }; /*---------------------------------------------------------------------------- * IMADecoderInit() *---------------------------------------------------------------------------- * Purpose: * Initializes the IMA ADPCM decoder * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pEASData) common decoder interface - pEASData not used */ static EAS_RESULT IMADecoderInit (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState) { pState->decoderL.step = 0; pState->decoderR.step = 0; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * IMADecoderSample() *---------------------------------------------------------------------------- * Purpose: * Decodes an IMA ADPCM sample * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT IMADecoderSample (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState) { EAS_RESULT result; EAS_I16 sTemp; /* if high nibble, decode */ if (pState->hiNibble) { IMADecoderADPCM(&pState->decoderL, (EAS_U8)(pState->srcByte >> 4)); pState->hiNibble = EAS_FALSE; } /* low nibble, need to fetch another byte */ else { /* check for loop */ if ((pState->bytesLeft == 0) && (pState->loopSamples != 0)) { /* seek to start of loop */ if ((result = EAS_HWFileSeek(pEASData->hwInstData, pState->fileHandle, (EAS_I32) (pState->startPos + pState->loopLocation))) != EAS_SUCCESS) return result; pState->bytesLeft = pState->byteCount = (EAS_I32) pState->bytesLeftLoop; pState->blockCount = 0; pState->flags &= ~PCM_FLAGS_EMPTY; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IMADecoderSample: Rewind file to %d, bytesLeft = %d\n", pState->startPos, pState->bytesLeft); */ } } /* if start of block, fetch new predictor and step index */ if ((pState->blockSize != 0) && (pState->blockCount == 0) && (pState->bytesLeft != 0)) { /* get predicted sample for left channel */ if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS) return result; #ifdef _DEBUG_IMA_ADPCM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Predictor: Was %d, now %d\n", pState->decoderL.acc, sTemp); */ } #endif pState->decoderL.acc = pState->decoderL.x1 = sTemp; /* get step index for left channel - upper 8 bits are reserved */ if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS) return result; #ifdef _DEBUG_IMA_ADPCM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Step: Was %d, now %d\n", pState->decoderL.step, sTemp); */ } #endif pState->decoderL.step = sTemp & 0xff; if (pState->flags & PCM_FLAGS_STEREO) { /* get predicted sample for right channel */ if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS) return result; pState->decoderR.acc = pState->decoderR.x1 = sTemp; /* get step index for right channel - upper 8 bits are reserved */ if ((result = EAS_HWGetWord(pEASData->hwInstData, pState->fileHandle, &sTemp, EAS_FALSE)) != EAS_SUCCESS) return result; #ifdef _DEBUG_IMA_ADPCM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Step: Was %d, now %d\n", pState->decoderR.step, sTemp); */ } #endif pState->decoderR.step = sTemp & 0xff; pState->blockCount = pState->blockSize - 8; pState->bytesLeft -= 8; } else { pState->blockCount = pState->blockSize - 4; pState->bytesLeft -= 4; } } else { /* get another ADPCM data pair */ if (pState->bytesLeft) { if ((result = EAS_HWGetByte(pEASData->hwInstData, pState->fileHandle, &pState->srcByte)) != EAS_SUCCESS) return result; /* decode the low nibble */ pState->bytesLeft--; pState->blockCount--; IMADecoderADPCM(&pState->decoderL, (EAS_U8)(pState->srcByte & 0x0f)); if (pState->flags & PCM_FLAGS_STEREO) IMADecoderADPCM(&pState->decoderR, (EAS_U8)(pState->srcByte >> 4)); else pState->hiNibble = EAS_TRUE; } /* out of ADPCM data, generate enough samples to fill buffer */ else { pState->decoderL.x1 = pState->decoderL.x0; pState->decoderR.x1 = pState->decoderR.x0; } } } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * IMADecoderADPCM() *---------------------------------------------------------------------------- * Purpose: * Decodes an IMA ADPCM sample * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static void IMADecoderADPCM (S_DECODER_STATE *pState, EAS_U8 nibble) { EAS_INT delta; EAS_INT stepSize; /* get stepsize from table */ stepSize = imaStepSizeTable[pState->step]; /* delta = (abs(delta) + 0.5) * step / 4 */ delta = 0; if (nibble & 4) delta += stepSize; if (nibble & 2) /*lint -e{702} use shift for performance */ delta += stepSize >> 1; if (nibble & 1) /*lint -e{702} use shift for performance */ delta += stepSize >> 2; /*lint -e{702} use shift for performance */ delta += stepSize >> 3; /* integrate the delta */ if (nibble & 8) pState->acc -= delta; else pState->acc += delta; /* saturate */ if (pState->acc > 32767) pState->acc = 32767; if (pState->acc < -32768) pState->acc = -32768; pState->x1 = (EAS_PCM) pState->acc; /* compute new step size */ pState->step += imaIndexTable[nibble]; if (pState->step < 0) pState->step = 0; if (pState->step > 88) pState->step = 88; #ifdef _DEBUG_IMA_ADPCM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "In=%u, Pred=%d, Step=%d\n", nibble, pState->acc, imaStepSizeTable[pState->step]); */ } #endif } /*---------------------------------------------------------------------------- * IMADecoderLocate() *---------------------------------------------------------------------------- * Locate in an IMA ADPCM stream *---------------------------------------------------------------------------- */ static EAS_RESULT IMADecoderLocate (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time) { EAS_RESULT result; EAS_I32 temp; EAS_I32 samplesPerBlock; EAS_I32 secs, msecs; /* no need to calculate if time is zero */ if (time == 0) temp = 0; /* not zero */ else { /* can't seek if not a blocked file */ if (pState->blockSize == 0) return EAS_ERROR_FEATURE_NOT_AVAILABLE; /* calculate number of samples per block */ if (pState->flags & PCM_FLAGS_STEREO) samplesPerBlock = pState->blockSize - 7; else samplesPerBlock = (pState->blockSize << 1) - 7; /* break down into secs and msecs */ secs = time / 1000; msecs = time - (secs * 1000); /* calculate sample number fraction from msecs */ temp = (msecs * pState->sampleRate); temp = (temp >> 10) + ((temp * 49) >> 21); /* add integer sample count */ temp += secs * pState->sampleRate; #ifdef _DEBUG_IMA_ADPCM_LOCATE EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000006 , time, temp); #endif /* for looped samples, calculate position in the loop */ if ((temp > pState->byteCount) && (pState->loopSamples != 0)) { EAS_I32 numBlocks; EAS_I32 samplesPerLoop; EAS_I32 samplesInLastBlock; numBlocks = (EAS_I32) (pState->loopStart / pState->blockSize); samplesInLastBlock = (EAS_I32) pState->loopStart - (numBlocks * pState->blockSize); if (samplesInLastBlock) { if (pState->flags & PCM_FLAGS_STEREO) samplesInLastBlock = samplesInLastBlock - 7; else /*lint -e{703} use shift for performance */ samplesInLastBlock = (samplesInLastBlock << 1) - 7; } samplesPerLoop = numBlocks * samplesPerBlock + samplesInLastBlock; temp = temp % samplesPerLoop; #ifdef _DEBUG_IMA_ADPCM_LOCATE EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000007 , numBlocks, samplesPerLoop, samplesInLastBlock, temp); #endif } /* find start of block for requested sample */ temp = (temp / samplesPerBlock) * pState->blockSize; #ifdef _DEBUG_IMA_ADPCM_LOCATE EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000008 , temp); #endif } /* seek to new location */ if ((result = EAS_PESeek(pEASData, pState, &temp)) != EAS_SUCCESS) return result; #ifdef _DEBUG_IMA_ADPCM_LOCATE EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x2380b977, 0x00000009 , pState->bytesLeft); #endif /* reset state */ pState->blockCount = 0; pState->hiNibble = EAS_FALSE; if ((pState->state != EAS_STATE_PAUSING) && (pState->state != EAS_STATE_PAUSED)) pState->state = EAS_STATE_READY; return EAS_SUCCESS; } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_tcdata.c0000644000000000000000000000013213532747316026350 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.858000056 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_tcdata.c0000644000175000001440000000256313532747316027147 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_tcdata.c * * Contents and purpose: * ToneControl Parser data * * This file contains static data for the ToneControl parser. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 547 $ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ *---------------------------------------------------------------------------- */ #include "eas_types.h" #include "eas_tcdata.h" /*---------------------------------------------------------------------------- * * eas_iMelodyData * * Static memory allocation for iMelody parser *---------------------------------------------------------------------------- */ S_TC_DATA eas_TCData; drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_otadata.c0000644000000000000000000000013213532747316026525 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.858000056 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_otadata.c0000644000175000001440000000251513532747316027321 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_otadata..c * * Contents and purpose: * OTA Stream Parser data module for static memory model * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 547 $ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ *---------------------------------------------------------------------------- */ #include "eas_types.h" #include "eas_otadata.h" /*---------------------------------------------------------------------------- * * eas_OTAData * * Static memory allocation for OTA parser *---------------------------------------------------------------------------- */ S_OTA_DATA eas_OTAData; drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_reverb.c0000644000000000000000000000013213532747316026375 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.858000056 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_reverb.c0000644000175000001440000011646713532747316027205 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_reverb.c * * Contents and purpose: * Contains the implementation of the Reverb effect. * * * Copyright Sonic Network Inc. 2006 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 510 $ * $Date: 2006-12-19 01:47:33 -0800 (Tue, 19 Dec 2006) $ *---------------------------------------------------------------------------- */ /*------------------------------------ * includes *------------------------------------ */ #include "eas_data.h" #include "eas_effects.h" #include "eas_math.h" #include "eas_reverbdata.h" #include "eas_reverb.h" #include "eas_config.h" #include "eas_host.h" #include "eas_report.h" /* prototypes for effects interface */ static EAS_RESULT ReverbInit (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData); static void ReverbProcess (EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples); static EAS_RESULT ReverbShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData); static EAS_RESULT ReverbGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); static EAS_RESULT ReverbSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); /* common effects interface for configuration module */ const S_EFFECTS_INTERFACE EAS_Reverb = { ReverbInit, ReverbProcess, ReverbShutdown, ReverbGetParam, ReverbSetParam }; /*---------------------------------------------------------------------------- * InitializeReverb() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ static EAS_RESULT ReverbInit(EAS_DATA_HANDLE pEASData, EAS_VOID_PTR *pInstData) { EAS_I32 i; EAS_U16 nOffset; EAS_INT temp; S_REVERB_OBJECT *pReverbData; S_REVERB_PRESET *pPreset; /* check Configuration Module for data allocation */ if (pEASData->staticMemoryModel) pReverbData = EAS_CMEnumFXData(EAS_MODULE_REVERB); /* allocate dynamic memory */ else pReverbData = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_REVERB_OBJECT)); if (pReverbData == NULL) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Failed to allocate Reverb memory\n"); */ } return EAS_ERROR_MALLOC_FAILED; } /* clear the structure */ EAS_HWMemSet(pReverbData, 0, sizeof(S_REVERB_OBJECT)); ReverbReadInPresets(pReverbData); pReverbData->m_nMinSamplesToAdd = REVERB_UPDATE_PERIOD_IN_SAMPLES; pReverbData->m_nRevOutFbkR = 0; pReverbData->m_nRevOutFbkL = 0; pReverbData->m_sAp0.m_zApIn = AP0_IN; pReverbData->m_sAp0.m_zApOut = AP0_IN + DEFAULT_AP0_LENGTH; pReverbData->m_sAp0.m_nApGain = DEFAULT_AP0_GAIN; pReverbData->m_zD0In = DELAY0_IN; pReverbData->m_sAp1.m_zApIn = AP1_IN; pReverbData->m_sAp1.m_zApOut = AP1_IN + DEFAULT_AP1_LENGTH; pReverbData->m_sAp1.m_nApGain = DEFAULT_AP1_GAIN; pReverbData->m_zD1In = DELAY1_IN; pReverbData->m_zLpf0 = 0; pReverbData->m_zLpf1 = 0; pReverbData->m_nLpfFwd = 8837; pReverbData->m_nLpfFbk = 6494; pReverbData->m_nSin = 0; pReverbData->m_nCos = 0; pReverbData->m_nSinIncrement = 0; pReverbData->m_nCosIncrement = 0; // set xfade parameters pReverbData->m_nXfadeInterval = (EAS_U16)REVERB_XFADE_PERIOD_IN_SAMPLES; pReverbData->m_nXfadeCounter = pReverbData->m_nXfadeInterval + 1; // force update on first iteration pReverbData->m_nPhase = -32768; pReverbData->m_nPhaseIncrement = REVERB_XFADE_PHASE_INCREMENT; pReverbData->m_nNoise = (EAS_I16)0xABCD; pReverbData->m_nMaxExcursion = 0x007F; // set delay tap lengths nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); pReverbData->m_zD1Cross = DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); pReverbData->m_zD0Cross = DELAY1_OUT - pReverbData->m_nMaxExcursion - nOffset; nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); pReverbData->m_zD0Self = DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset; nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); pReverbData->m_zD1Self = DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; // for debugging purposes, allow noise generator pReverbData->m_bUseNoise = EAS_FALSE; // for debugging purposes, allow bypass pReverbData->m_bBypass = EAS_TRUE; //EAS_FALSE; pReverbData->m_nNextRoom = 1; pReverbData->m_nCurrentRoom = pReverbData->m_nNextRoom + 1; // force update on first iteration pReverbData->m_nWet = REVERB_DEFAULT_WET; pReverbData->m_nDry = REVERB_DEFAULT_DRY; // set base index into circular buffer pReverbData->m_nBaseIndex = 0; // set the early reflections, L pReverbData->m_sEarlyL.m_nLpfFbk = 4915; pReverbData->m_sEarlyL.m_nLpfFwd = 27852; pReverbData->m_sEarlyL.m_zLpf = 0; for (i=0; i < REVERB_MAX_NUM_REFLECTIONS; i++) { pReverbData->m_sEarlyL.m_nGain[i] = 0; pReverbData->m_sEarlyL.m_zDelay[i] = 0; } // set the early reflections, R pReverbData->m_sEarlyR.m_nLpfFbk = 4915; pReverbData->m_sEarlyR.m_nLpfFwd = 27852; pReverbData->m_sEarlyR.m_zLpf = 0; for (i=0; i < REVERB_MAX_NUM_REFLECTIONS; i++) { pReverbData->m_sEarlyR.m_nGain[i] = 0; pReverbData->m_sEarlyR.m_zDelay[i] = 0; } // clear the reverb delay line for (i=0; i < REVERB_BUFFER_SIZE_IN_SAMPLES; i++) { pReverbData->m_nDelayLine[i] = 0; } //////////////////////////////// ///code from the EAS DEMO Reverb //now copy from the new preset into the reverb pPreset = &pReverbData->m_sPreset.m_sPreset[pReverbData->m_nNextRoom]; pReverbData->m_nLpfFbk = pPreset->m_nLpfFbk; pReverbData->m_nLpfFwd = pPreset->m_nLpfFwd; pReverbData->m_nEarly = pPreset->m_nEarly; pReverbData->m_nWet = pPreset->m_nWet; pReverbData->m_nDry = pPreset->m_nDry; pReverbData->m_nMaxExcursion = pPreset->m_nMaxExcursion; //stored as time based, convert to sample based temp = pPreset->m_nXfadeInterval; /*lint -e{702} shift for performance */ temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; pReverbData->m_nXfadeInterval = (EAS_U16) temp; //gsReverbObject.m_nXfadeInterval = pPreset->m_nXfadeInterval; pReverbData->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain; //stored as time based, convert to absolute sample value temp = pPreset->m_nAp0_ApOut; /*lint -e{702} shift for performance */ temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; pReverbData->m_sAp0.m_zApOut = (EAS_U16) (pReverbData->m_sAp0.m_zApIn + temp); //gsReverbObject.m_sAp0.m_zApOut = pPreset->m_nAp0_ApOut; pReverbData->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain; //stored as time based, convert to absolute sample value temp = pPreset->m_nAp1_ApOut; /*lint -e{702} shift for performance */ temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; pReverbData->m_sAp1.m_zApOut = (EAS_U16) (pReverbData->m_sAp1.m_zApIn + temp); //gsReverbObject.m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut; ///code from the EAS DEMO Reverb //////////////////////////////// *pInstData = pReverbData; return EAS_SUCCESS; } /* end InitializeReverb */ /*---------------------------------------------------------------------------- * ReverbProcess() *---------------------------------------------------------------------------- * Purpose: * Reverberate the requested number of samples (block based processing) * * Inputs: * pInputBuffer - src buffer * pOutputBuffer - dst buffer * nNumSamplesToAdd - number of samples to write to buffer * * Outputs: * number of samples actually written to buffer * * Side Effects: * - samples are added to the presently free buffer * *---------------------------------------------------------------------------- */ static void ReverbProcess(EAS_VOID_PTR pInstData, EAS_PCM *pSrc, EAS_PCM *pDst, EAS_I32 numSamples) { S_REVERB_OBJECT *pReverbData; pReverbData = (S_REVERB_OBJECT*) pInstData; //if bypassed or the preset forces the signal to be completely dry if (pReverbData->m_bBypass || (pReverbData->m_nWet == 0 && pReverbData->m_nDry == 32767)) { if (pSrc != pDst) EAS_HWMemCpy(pSrc, pDst, numSamples * NUM_OUTPUT_CHANNELS * (EAS_I32) sizeof(EAS_PCM)); return; } if (pReverbData->m_nNextRoom != pReverbData->m_nCurrentRoom) { ReverbUpdateRoom(pReverbData); } ReverbUpdateXfade(pReverbData, numSamples); Reverb(pReverbData, numSamples, pDst, pSrc); /* check if update counter needs to be reset */ if (pReverbData->m_nUpdateCounter >= REVERB_MODULO_UPDATE_PERIOD_IN_SAMPLES) { /* update interval has elapsed, so reset counter */ pReverbData->m_nUpdateCounter = 0; } /* end if m_nUpdateCounter >= update interval */ /* increment update counter */ pReverbData->m_nUpdateCounter += (EAS_I16)numSamples; } /* end ComputeReverb */ /*---------------------------------------------------------------------------- * ReverbUpdateXfade *---------------------------------------------------------------------------- * Purpose: * Update the xfade parameters as required * * Inputs: * nNumSamplesToAdd - number of samples to write to buffer * * Outputs: * * * Side Effects: * - xfade parameters will be changed * *---------------------------------------------------------------------------- */ static EAS_RESULT ReverbUpdateXfade(S_REVERB_OBJECT *pReverbData, EAS_INT nNumSamplesToAdd) { EAS_U16 nOffset; EAS_I16 tempCos; EAS_I16 tempSin; if (pReverbData->m_nXfadeCounter >= pReverbData->m_nXfadeInterval) { /* update interval has elapsed, so reset counter */ pReverbData->m_nXfadeCounter = 0; // Pin the sin,cos values to min / max values to ensure that the // modulated taps' coefs are zero (thus no clicks) if (pReverbData->m_nPhaseIncrement > 0) { // if phase increment > 0, then sin -> 1, cos -> 0 pReverbData->m_nSin = 32767; pReverbData->m_nCos = 0; // reset the phase to match the sin, cos values pReverbData->m_nPhase = 32767; // modulate the cross taps because their tap coefs are zero nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); pReverbData->m_zD1Cross = DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); pReverbData->m_zD0Cross = DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset; } else { // if phase increment < 0, then sin -> 0, cos -> 1 pReverbData->m_nSin = 0; pReverbData->m_nCos = 32767; // reset the phase to match the sin, cos values pReverbData->m_nPhase = -32768; // modulate the self taps because their tap coefs are zero nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); pReverbData->m_zD0Self = DELAY0_OUT - pReverbData->m_nMaxExcursion - nOffset; nOffset = ReverbCalculateNoise( pReverbData->m_nMaxExcursion, &pReverbData->m_nNoise ); pReverbData->m_zD1Self = DELAY1_OUT - pReverbData->m_nMaxExcursion + nOffset; } // end if-else (pReverbData->m_nPhaseIncrement > 0) // Reverse the direction of the sin,cos so that the // tap whose coef was previously increasing now decreases // and vice versa pReverbData->m_nPhaseIncrement = -pReverbData->m_nPhaseIncrement; } // end if counter >= update interval //compute what phase will be next time pReverbData->m_nPhase += pReverbData->m_nPhaseIncrement; //calculate what the new sin and cos need to reach by the next update ReverbCalculateSinCos(pReverbData->m_nPhase, &tempSin, &tempCos); //calculate the per-sample increment required to get there by the next update /*lint -e{702} shift for performance */ pReverbData->m_nSinIncrement = (tempSin - pReverbData->m_nSin) >> REVERB_UPDATE_PERIOD_IN_BITS; /*lint -e{702} shift for performance */ pReverbData->m_nCosIncrement = (tempCos - pReverbData->m_nCos) >> REVERB_UPDATE_PERIOD_IN_BITS; /* increment update counter */ pReverbData->m_nXfadeCounter += (EAS_U16) nNumSamplesToAdd; return EAS_SUCCESS; } /* end ReverbUpdateXfade */ /*---------------------------------------------------------------------------- * ReverbCalculateNoise *---------------------------------------------------------------------------- * Purpose: * Calculate a noise sample and limit its value * * Inputs: * nMaxExcursion - noise value is limited to this value * pnNoise - return new noise sample in this (not limited) * * Outputs: * new limited noise value * * Side Effects: * - *pnNoise noise value is updated * *---------------------------------------------------------------------------- */ static EAS_U16 ReverbCalculateNoise(EAS_U16 nMaxExcursion, EAS_I16 *pnNoise) { // calculate new noise value *pnNoise = (EAS_I16) (*pnNoise * 5 + 1); #if 0 // 1xxx, test *pnNoise = 0; #endif // 1xxx, test // return the limited noise value return (nMaxExcursion & (*pnNoise)); } /* end ReverbCalculateNoise */ /*---------------------------------------------------------------------------- * ReverbCalculateSinCos *---------------------------------------------------------------------------- * Purpose: * Calculate a new sin and cosine value based on the given phase * * Inputs: * nPhase - phase angle * pnSin - input old value, output new value * pnCos - input old value, output new value * * Outputs: * * Side Effects: * - *pnSin, *pnCos are updated * *---------------------------------------------------------------------------- */ static EAS_RESULT ReverbCalculateSinCos(EAS_I16 nPhase, EAS_I16 *pnSin, EAS_I16 *pnCos) { EAS_I32 nTemp; EAS_I32 nNetAngle; // -1 <= nPhase < 1 // However, for the calculation, we need a value // that ranges from -1/2 to +1/2, so divide the phase by 2 /*lint -e{702} shift for performance */ nNetAngle = nPhase >> 1; /* Implement the following sin(x) = (2-4*c)*x^2 + c + x cos(x) = (2-4*c)*x^2 + c - x where c = 1/sqrt(2) using the a0 + x*(a1 + x*a2) approach */ /* limit the input "angle" to be between -0.5 and +0.5 */ if (nNetAngle > EG1_HALF) { nNetAngle = EG1_HALF; } else if (nNetAngle < EG1_MINUS_HALF) { nNetAngle = EG1_MINUS_HALF; } /* calculate sin */ nTemp = EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle); nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle); *pnSin = (EAS_I16) SATURATE_EG1(nTemp); /* calculate cos */ nTemp = -EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle); nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle); *pnCos = (EAS_I16) SATURATE_EG1(nTemp); return EAS_SUCCESS; } /* end ReverbCalculateSinCos */ /*---------------------------------------------------------------------------- * Reverb *---------------------------------------------------------------------------- * Purpose: * apply reverb to the given signal * * Inputs: * nNu * pnSin - input old value, output new value * pnCos - input old value, output new value * * Outputs: * number of samples actually reverberated * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT Reverb(S_REVERB_OBJECT *pReverbData, EAS_INT nNumSamplesToAdd, EAS_PCM *pOutputBuffer, EAS_PCM *pInputBuffer) { EAS_I32 i; EAS_I32 nDelayOut; EAS_U16 nBase; EAS_U32 nAddr; EAS_I32 nTemp1; EAS_I32 nTemp2; EAS_I32 nApIn; EAS_I32 nApOut; EAS_I32 j; EAS_I32 nEarlyOut; EAS_I32 tempValue; // get the base address nBase = pReverbData->m_nBaseIndex; for (i=0; i < nNumSamplesToAdd; i++) { // ********** Left Allpass - start // left input = (left dry/4) + right feedback from previous period /*lint -e{702} use shift for performance */ nApIn = ((*pInputBuffer++)>>2) + pReverbData->m_nRevOutFbkR; // nApIn = *pInputBuffer++; // 1xxx test and debug ap // fetch allpass delay line out //nAddr = CIRCULAR(nBase, psAp0->m_zApOut, REVERB_BUFFER_MASK); nAddr = CIRCULAR(nBase, pReverbData->m_sAp0.m_zApOut, REVERB_BUFFER_MASK); nDelayOut = pReverbData->m_nDelayLine[nAddr]; // calculate allpass feedforward; subtract the feedforward result nTemp1 = MULT_EG1_EG1(nApIn, pReverbData->m_sAp0.m_nApGain); nApOut = SATURATE(nDelayOut - nTemp1); // allpass output // calculate allpass feedback; add the feedback result nTemp1 = MULT_EG1_EG1(nApOut, pReverbData->m_sAp0.m_nApGain); nTemp1 = SATURATE(nApIn + nTemp1); // inject into allpass delay nAddr = CIRCULAR(nBase, pReverbData->m_sAp0.m_zApIn, REVERB_BUFFER_MASK); pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nTemp1; // inject allpass output into delay line nAddr = CIRCULAR(nBase, pReverbData->m_zD0In, REVERB_BUFFER_MASK); pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nApOut; // ********** Left Allpass - end // ********** Right Allpass - start // right input = (right dry/4) + left feedback from previous period /*lint -e{702} use shift for performance */ nApIn = ((*pInputBuffer++)>>2) + pReverbData->m_nRevOutFbkL; // nApIn = *pInputBuffer++; // 1xxx test and debug ap // fetch allpass delay line out nAddr = CIRCULAR(nBase, pReverbData->m_sAp1.m_zApOut, REVERB_BUFFER_MASK); nDelayOut = pReverbData->m_nDelayLine[nAddr]; // calculate allpass feedforward; subtract the feedforward result nTemp1 = MULT_EG1_EG1(nApIn, pReverbData->m_sAp1.m_nApGain); nApOut = SATURATE(nDelayOut - nTemp1); // allpass output // calculate allpass feedback; add the feedback result nTemp1 = MULT_EG1_EG1(nApOut, pReverbData->m_sAp1.m_nApGain); nTemp1 = SATURATE(nApIn + nTemp1); // inject into allpass delay nAddr = CIRCULAR(nBase, pReverbData->m_sAp1.m_zApIn, REVERB_BUFFER_MASK); pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nTemp1; // inject allpass output into delay line nAddr = CIRCULAR(nBase, pReverbData->m_zD1In, REVERB_BUFFER_MASK); pReverbData->m_nDelayLine[nAddr] = (EAS_PCM) nApOut; // ********** Right Allpass - end // ********** D0 output - start // fetch delay line self out nAddr = CIRCULAR(nBase, pReverbData->m_zD0Self, REVERB_BUFFER_MASK); nDelayOut = pReverbData->m_nDelayLine[nAddr]; // calculate delay line self out nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nSin); // fetch delay line cross out nAddr = CIRCULAR(nBase, pReverbData->m_zD1Cross, REVERB_BUFFER_MASK); nDelayOut = pReverbData->m_nDelayLine[nAddr]; // calculate delay line self out nTemp2 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nCos); // calculate unfiltered delay out nDelayOut = SATURATE(nTemp1 + nTemp2); // calculate lowpass filter (mixer scale factor included in LPF feedforward) nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nLpfFwd); nTemp2 = MULT_EG1_EG1(pReverbData->m_zLpf0, pReverbData->m_nLpfFbk); // calculate filtered delay out and simultaneously update LPF state variable // filtered delay output is stored in m_zLpf0 pReverbData->m_zLpf0 = (EAS_PCM) SATURATE(nTemp1 + nTemp2); // ********** D0 output - end // ********** D1 output - start // fetch delay line self out nAddr = CIRCULAR(nBase, pReverbData->m_zD1Self, REVERB_BUFFER_MASK); nDelayOut = pReverbData->m_nDelayLine[nAddr]; // calculate delay line self out nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nSin); // fetch delay line cross out nAddr = CIRCULAR(nBase, pReverbData->m_zD0Cross, REVERB_BUFFER_MASK); nDelayOut = pReverbData->m_nDelayLine[nAddr]; // calculate delay line self out nTemp2 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nCos); // calculate unfiltered delay out nDelayOut = SATURATE(nTemp1 + nTemp2); // calculate lowpass filter (mixer scale factor included in LPF feedforward) nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_nLpfFwd); nTemp2 = MULT_EG1_EG1(pReverbData->m_zLpf1, pReverbData->m_nLpfFbk); // calculate filtered delay out and simultaneously update LPF state variable // filtered delay output is stored in m_zLpf1 pReverbData->m_zLpf1 = (EAS_PCM)SATURATE(nTemp1 + nTemp2); // ********** D1 output - end // ********** mixer and feedback - start // sum is fedback to right input (R + L) pReverbData->m_nRevOutFbkL = (EAS_PCM)SATURATE((EAS_I32)pReverbData->m_zLpf1 + (EAS_I32)pReverbData->m_zLpf0); // difference is feedback to left input (R - L) /*lint -e{685} lint complains that it can't saturate negative */ pReverbData->m_nRevOutFbkR = (EAS_PCM)SATURATE((EAS_I32)pReverbData->m_zLpf1 - (EAS_I32)pReverbData->m_zLpf0); // ********** mixer and feedback - end // ********** start early reflection generator, left //psEarly = &(pReverbData->m_sEarlyL); nEarlyOut = 0; for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) { // fetch delay line out //nAddr = CIRCULAR(nBase, psEarly->m_zDelay[j], REVERB_BUFFER_MASK); nAddr = CIRCULAR(nBase, pReverbData->m_sEarlyL.m_zDelay[j], REVERB_BUFFER_MASK); nDelayOut = pReverbData->m_nDelayLine[nAddr]; // calculate reflection //nTemp1 = MULT_EG1_EG1(nDelayOut, psEarly->m_nGain[j]); nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_sEarlyL.m_nGain[j]); nEarlyOut = SATURATE(nEarlyOut + nTemp1); } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) // apply lowpass to early reflections //nTemp1 = MULT_EG1_EG1(nEarlyOut, psEarly->m_nLpfFwd); nTemp1 = MULT_EG1_EG1(nEarlyOut, pReverbData->m_sEarlyL.m_nLpfFwd); //nTemp2 = MULT_EG1_EG1(psEarly->m_zLpf, psEarly->m_nLpfFbk); nTemp2 = MULT_EG1_EG1(pReverbData->m_sEarlyL.m_zLpf, pReverbData->m_sEarlyL.m_nLpfFbk); // calculate filtered out and simultaneously update LPF state variable // filtered output is stored in m_zLpf1 //psEarly->m_zLpf = SATURATE(nTemp1 + nTemp2); pReverbData->m_sEarlyL.m_zLpf = (EAS_PCM) SATURATE(nTemp1 + nTemp2); // combine filtered early and late reflections for output //*pOutputBuffer++ = inL; //tempValue = SATURATE(psEarly->m_zLpf + pReverbData->m_nRevOutFbkL); tempValue = SATURATE((EAS_I32)pReverbData->m_sEarlyL.m_zLpf + (EAS_I32)pReverbData->m_nRevOutFbkL); //scale reverb output by wet level /*lint -e{701} use shift for performance */ tempValue = MULT_EG1_EG1(tempValue, (pReverbData->m_nWet<<1)); //sum with output buffer tempValue += *pOutputBuffer; *pOutputBuffer++ = (EAS_PCM)SATURATE(tempValue); // ********** end early reflection generator, left // ********** start early reflection generator, right //psEarly = &(pReverbData->m_sEarlyR); nEarlyOut = 0; for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) { // fetch delay line out nAddr = CIRCULAR(nBase, pReverbData->m_sEarlyR.m_zDelay[j], REVERB_BUFFER_MASK); nDelayOut = pReverbData->m_nDelayLine[nAddr]; // calculate reflection nTemp1 = MULT_EG1_EG1(nDelayOut, pReverbData->m_sEarlyR.m_nGain[j]); nEarlyOut = SATURATE(nEarlyOut + nTemp1); } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++) // apply lowpass to early reflections nTemp1 = MULT_EG1_EG1(nEarlyOut, pReverbData->m_sEarlyR.m_nLpfFwd); nTemp2 = MULT_EG1_EG1(pReverbData->m_sEarlyR.m_zLpf, pReverbData->m_sEarlyR.m_nLpfFbk); // calculate filtered out and simultaneously update LPF state variable // filtered output is stored in m_zLpf1 pReverbData->m_sEarlyR.m_zLpf = (EAS_PCM)SATURATE(nTemp1 + nTemp2); // combine filtered early and late reflections for output //*pOutputBuffer++ = inR; tempValue = SATURATE((EAS_I32)pReverbData->m_sEarlyR.m_zLpf + (EAS_I32)pReverbData->m_nRevOutFbkR); //scale reverb output by wet level /*lint -e{701} use shift for performance */ tempValue = MULT_EG1_EG1(tempValue, (pReverbData->m_nWet << 1)); //sum with output buffer tempValue = tempValue + *pOutputBuffer; *pOutputBuffer++ = (EAS_PCM)SATURATE(tempValue); // ********** end early reflection generator, right // decrement base addr for next sample period nBase--; pReverbData->m_nSin += pReverbData->m_nSinIncrement; pReverbData->m_nCos += pReverbData->m_nCosIncrement; } // end for (i=0; i < nNumSamplesToAdd; i++) // store the most up to date version pReverbData->m_nBaseIndex = nBase; return EAS_SUCCESS; } /* end Reverb */ /*---------------------------------------------------------------------------- * ReverbShutdown() *---------------------------------------------------------------------------- * Purpose: * Initializes the Reverb effect. * * Inputs: * pInstData - handle to instance data * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT ReverbShutdown (EAS_DATA_HANDLE pEASData, EAS_VOID_PTR pInstData) { /* check Configuration Module for static memory allocation */ if (!pEASData->staticMemoryModel) EAS_HWFree(pEASData->hwInstData, pInstData); return EAS_SUCCESS; } /* end ReverbShutdown */ /*---------------------------------------------------------------------------- * ReverbGetParam() *---------------------------------------------------------------------------- * Purpose: * Get a Reverb parameter * * Inputs: * pInstData - handle to instance data * param - parameter index * *pValue - pointer to variable to hold retrieved value * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT ReverbGetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue) { S_REVERB_OBJECT *p; p = (S_REVERB_OBJECT*) pInstData; switch (param) { case EAS_PARAM_REVERB_BYPASS: *pValue = (EAS_I32) p->m_bBypass; break; case EAS_PARAM_REVERB_PRESET: *pValue = (EAS_I8) p->m_nCurrentRoom; break; case EAS_PARAM_REVERB_WET: *pValue = p->m_nWet; break; case EAS_PARAM_REVERB_DRY: *pValue = p->m_nDry; break; default: return EAS_ERROR_INVALID_PARAMETER; } return EAS_SUCCESS; } /* end ReverbGetParam */ /*---------------------------------------------------------------------------- * ReverbSetParam() *---------------------------------------------------------------------------- * Purpose: * Set a Reverb parameter * * Inputs: * pInstData - handle to instance data * param - parameter index * *pValue - new paramter value * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT ReverbSetParam (EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value) { S_REVERB_OBJECT *p; p = (S_REVERB_OBJECT*) pInstData; switch (param) { case EAS_PARAM_REVERB_BYPASS: p->m_bBypass = (EAS_BOOL) value; break; case EAS_PARAM_REVERB_PRESET: if(value!=EAS_PARAM_REVERB_LARGE_HALL && value!=EAS_PARAM_REVERB_HALL && value!=EAS_PARAM_REVERB_CHAMBER && value!=EAS_PARAM_REVERB_ROOM) return EAS_ERROR_INVALID_PARAMETER; p->m_nNextRoom = (EAS_I16)value; break; case EAS_PARAM_REVERB_WET: if(value>EAS_REVERB_WET_MAX || valuem_nWet = (EAS_I16)value; break; case EAS_PARAM_REVERB_DRY: if(value>EAS_REVERB_DRY_MAX || valuem_nDry = (EAS_I16)value; break; default: return EAS_ERROR_INVALID_PARAMETER; } return EAS_SUCCESS; } /* end ReverbSetParam */ /*---------------------------------------------------------------------------- * ReverbUpdateRoom *---------------------------------------------------------------------------- * Purpose: * Update the room's preset parameters as required * * Inputs: * * Outputs: * * * Side Effects: * - reverb paramters (fbk, fwd, etc) will be changed * - m_nCurrentRoom := m_nNextRoom *---------------------------------------------------------------------------- */ static EAS_RESULT ReverbUpdateRoom(S_REVERB_OBJECT *pReverbData) { EAS_INT temp; S_REVERB_PRESET *pPreset = &pReverbData->m_sPreset.m_sPreset[pReverbData->m_nNextRoom]; pReverbData->m_nLpfFwd = pPreset->m_nLpfFwd; pReverbData->m_nLpfFbk = pPreset->m_nLpfFbk; pReverbData->m_nEarly = pPreset->m_nEarly; pReverbData->m_nWet = pPreset->m_nWet; pReverbData->m_nDry = pPreset->m_nDry; pReverbData->m_nMaxExcursion = pPreset->m_nMaxExcursion; //stored as time based, convert to sample based temp = pPreset->m_nXfadeInterval; /*lint -e{702} shift for performance */ temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; pReverbData->m_nXfadeInterval = (EAS_U16) temp; //gpsReverbObject->m_nXfadeInterval = pPreset->m_nXfadeInterval; pReverbData->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain; //stored as time based, convert to absolute sample value temp = pPreset->m_nAp0_ApOut; /*lint -e{702} shift for performance */ temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; pReverbData->m_sAp0.m_zApOut = (EAS_U16) (pReverbData->m_sAp0.m_zApIn + temp); //gpsReverbObject->m_sAp0.m_zApOut = pPreset->m_nAp0_ApOut; pReverbData->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain; //stored as time based, convert to absolute sample value temp = pPreset->m_nAp1_ApOut; /*lint -e{702} shift for performance */ temp = (temp * _OUTPUT_SAMPLE_RATE) >> 16; pReverbData->m_sAp1.m_zApOut = (EAS_U16) (pReverbData->m_sAp1.m_zApIn + temp); //gpsReverbObject->m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut; pReverbData->m_nCurrentRoom = pReverbData->m_nNextRoom; return EAS_SUCCESS; } /* end ReverbUpdateRoom */ /*---------------------------------------------------------------------------- * ReverbReadInPresets() *---------------------------------------------------------------------------- * Purpose: sets global reverb preset bank to defaults * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ static EAS_RESULT ReverbReadInPresets(S_REVERB_OBJECT *pReverbData) { int preset = 0; int defaultPreset = 0; //now init any remaining presets to defaults for (defaultPreset = preset; defaultPreset < REVERB_MAX_ROOM_TYPE; defaultPreset++) { S_REVERB_PRESET *pPreset = &pReverbData->m_sPreset.m_sPreset[defaultPreset]; if (defaultPreset == 0 || defaultPreset > REVERB_MAX_ROOM_TYPE-1) { pPreset->m_nLpfFbk = 8307; pPreset->m_nLpfFwd = 14768; pPreset->m_nEarly = 0; pPreset->m_nWet = 27690; pPreset->m_nDry = 32767; pPreset->m_nEarlyL_LpfFbk = 3692; pPreset->m_nEarlyL_LpfFwd = 29075; pPreset->m_nEarlyL_Delay0 = 922; pPreset->m_nEarlyL_Gain0 = 22152; pPreset->m_nEarlyL_Delay1 = 1462; pPreset->m_nEarlyL_Gain1 = 17537; pPreset->m_nEarlyL_Delay2 = 0; pPreset->m_nEarlyL_Gain2 = 14768; pPreset->m_nEarlyL_Delay3 = 1221; pPreset->m_nEarlyL_Gain3 = 14307; pPreset->m_nEarlyL_Delay4 = 0; pPreset->m_nEarlyL_Gain4 = 13384; pPreset->m_nEarlyR_Delay0 = 502; pPreset->m_nEarlyR_Gain0 = 20306; pPreset->m_nEarlyR_Delay1 = 1762; pPreset->m_nEarlyR_Gain1 = 17537; pPreset->m_nEarlyR_Delay2 = 0; pPreset->m_nEarlyR_Gain2 = 14768; pPreset->m_nEarlyR_Delay3 = 0; pPreset->m_nEarlyR_Gain3 = 16153; pPreset->m_nEarlyR_Delay4 = 0; pPreset->m_nEarlyR_Gain4 = 13384; pPreset->m_nMaxExcursion = 127; pPreset->m_nXfadeInterval = 6388; pPreset->m_nAp0_ApGain = 15691; pPreset->m_nAp0_ApOut = 711; pPreset->m_nAp1_ApGain = 17999; pPreset->m_nAp1_ApOut = 1113; pPreset->m_rfu4 = 0; pPreset->m_rfu5 = 0; pPreset->m_rfu6 = 0; pPreset->m_rfu7 = 0; pPreset->m_rfu8 = 0; pPreset->m_rfu9 = 0; pPreset->m_rfu10 = 0; } else if (defaultPreset == 1) { pPreset->m_nLpfFbk = 6461; pPreset->m_nLpfFwd = 14307; pPreset->m_nEarly = 0; pPreset->m_nWet = 27690; pPreset->m_nDry = 32767; pPreset->m_nEarlyL_LpfFbk = 3692; pPreset->m_nEarlyL_LpfFwd = 29075; pPreset->m_nEarlyL_Delay0 = 922; pPreset->m_nEarlyL_Gain0 = 22152; pPreset->m_nEarlyL_Delay1 = 1462; pPreset->m_nEarlyL_Gain1 = 17537; pPreset->m_nEarlyL_Delay2 = 0; pPreset->m_nEarlyL_Gain2 = 14768; pPreset->m_nEarlyL_Delay3 = 1221; pPreset->m_nEarlyL_Gain3 = 14307; pPreset->m_nEarlyL_Delay4 = 0; pPreset->m_nEarlyL_Gain4 = 13384; pPreset->m_nEarlyR_Delay0 = 502; pPreset->m_nEarlyR_Gain0 = 20306; pPreset->m_nEarlyR_Delay1 = 1762; pPreset->m_nEarlyR_Gain1 = 17537; pPreset->m_nEarlyR_Delay2 = 0; pPreset->m_nEarlyR_Gain2 = 14768; pPreset->m_nEarlyR_Delay3 = 0; pPreset->m_nEarlyR_Gain3 = 16153; pPreset->m_nEarlyR_Delay4 = 0; pPreset->m_nEarlyR_Gain4 = 13384; pPreset->m_nMaxExcursion = 127; pPreset->m_nXfadeInterval = 6391; pPreset->m_nAp0_ApGain = 15230; pPreset->m_nAp0_ApOut = 708; pPreset->m_nAp1_ApGain = 9692; pPreset->m_nAp1_ApOut = 1113; pPreset->m_rfu4 = 0; pPreset->m_rfu5 = 0; pPreset->m_rfu6 = 0; pPreset->m_rfu7 = 0; pPreset->m_rfu8 = 0; pPreset->m_rfu9 = 0; pPreset->m_rfu10 = 0; } else if (defaultPreset == 2) { pPreset->m_nLpfFbk = 5077; pPreset->m_nLpfFwd = 12922; pPreset->m_nEarly = 0; pPreset->m_nWet = 24460; pPreset->m_nDry = 32767; pPreset->m_nEarlyL_LpfFbk = 3692; pPreset->m_nEarlyL_LpfFwd = 29075; pPreset->m_nEarlyL_Delay0 = 922; pPreset->m_nEarlyL_Gain0 = 22152; pPreset->m_nEarlyL_Delay1 = 1462; pPreset->m_nEarlyL_Gain1 = 17537; pPreset->m_nEarlyL_Delay2 = 0; pPreset->m_nEarlyL_Gain2 = 14768; pPreset->m_nEarlyL_Delay3 = 1221; pPreset->m_nEarlyL_Gain3 = 14307; pPreset->m_nEarlyL_Delay4 = 0; pPreset->m_nEarlyL_Gain4 = 13384; pPreset->m_nEarlyR_Delay0 = 502; pPreset->m_nEarlyR_Gain0 = 20306; pPreset->m_nEarlyR_Delay1 = 1762; pPreset->m_nEarlyR_Gain1 = 17537; pPreset->m_nEarlyR_Delay2 = 0; pPreset->m_nEarlyR_Gain2 = 14768; pPreset->m_nEarlyR_Delay3 = 0; pPreset->m_nEarlyR_Gain3 = 16153; pPreset->m_nEarlyR_Delay4 = 0; pPreset->m_nEarlyR_Gain4 = 13384; pPreset->m_nMaxExcursion = 127; pPreset->m_nXfadeInterval = 6449; pPreset->m_nAp0_ApGain = 15691; pPreset->m_nAp0_ApOut = 774; pPreset->m_nAp1_ApGain = 15691; pPreset->m_nAp1_ApOut = 1113; pPreset->m_rfu4 = 0; pPreset->m_rfu5 = 0; pPreset->m_rfu6 = 0; pPreset->m_rfu7 = 0; pPreset->m_rfu8 = 0; pPreset->m_rfu9 = 0; pPreset->m_rfu10 = 0; } else if (defaultPreset == 3) { pPreset->m_nLpfFbk = 5077; pPreset->m_nLpfFwd = 11076; pPreset->m_nEarly = 0; pPreset->m_nWet = 23075; pPreset->m_nDry = 32767; pPreset->m_nEarlyL_LpfFbk = 3692; pPreset->m_nEarlyL_LpfFwd = 29075; pPreset->m_nEarlyL_Delay0 = 922; pPreset->m_nEarlyL_Gain0 = 22152; pPreset->m_nEarlyL_Delay1 = 1462; pPreset->m_nEarlyL_Gain1 = 17537; pPreset->m_nEarlyL_Delay2 = 0; pPreset->m_nEarlyL_Gain2 = 14768; pPreset->m_nEarlyL_Delay3 = 1221; pPreset->m_nEarlyL_Gain3 = 14307; pPreset->m_nEarlyL_Delay4 = 0; pPreset->m_nEarlyL_Gain4 = 13384; pPreset->m_nEarlyR_Delay0 = 502; pPreset->m_nEarlyR_Gain0 = 20306; pPreset->m_nEarlyR_Delay1 = 1762; pPreset->m_nEarlyR_Gain1 = 17537; pPreset->m_nEarlyR_Delay2 = 0; pPreset->m_nEarlyR_Gain2 = 14768; pPreset->m_nEarlyR_Delay3 = 0; pPreset->m_nEarlyR_Gain3 = 16153; pPreset->m_nEarlyR_Delay4 = 0; pPreset->m_nEarlyR_Gain4 = 13384; pPreset->m_nMaxExcursion = 127; pPreset->m_nXfadeInterval = 6470; //6483; pPreset->m_nAp0_ApGain = 14768; pPreset->m_nAp0_ApOut = 792; pPreset->m_nAp1_ApGain = 15783; pPreset->m_nAp1_ApOut = 1113; pPreset->m_rfu4 = 0; pPreset->m_rfu5 = 0; pPreset->m_rfu6 = 0; pPreset->m_rfu7 = 0; pPreset->m_rfu8 = 0; pPreset->m_rfu9 = 0; pPreset->m_rfu10 = 0; } } return EAS_SUCCESS; } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_wtsynth.c0000644000000000000000000000013213532747316026630 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.858000056 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_wtsynth.c0000644000175000001440000012624613532747316027434 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_wtsynth.c * * Contents and purpose: * Implements the synthesizer functions. * * Copyright Sonic Network Inc. 2004 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 795 $ * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ *---------------------------------------------------------------------------- */ // includes #include "eas_data.h" #include "eas_report.h" #include "eas_host.h" #include "eas_math.h" #include "eas_synth_protos.h" #include "eas_wtsynth.h" #include "eas_pan.h" #ifdef DLS_SYNTHESIZER #include "eas_dlssynth.h" #endif #ifdef _METRICS_ENABLED #include "eas_perf.h" #endif /* local prototypes */ static EAS_RESULT WT_Initialize(S_VOICE_MGR *pVoiceMgr); static void WT_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); static void WT_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); static void WT_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum); static EAS_RESULT WT_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex); static EAS_BOOL WT_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples); static void WT_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); static EAS_I32 WT_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents); static EAS_I32 WT_UpdateGain (S_SYNTH_VOICE *pVoice, S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain); static void WT_UpdateEG1 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv); static void WT_UpdateEG2 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv); #ifdef EAS_SPLIT_WT_SYNTH extern EAS_BOOL WTE_StartFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffer); extern EAS_BOOL WTE_EndFrame (EAS_FRAME_BUFFER_HANDLE pFrameBuffer, EAS_I32 *pMixBuffer, EAS_I16 masterGain); #endif #ifdef _FILTER_ENABLED static void WT_UpdateFilter (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pIntFrame, const S_ARTICULATION *pArt); #endif #ifdef _STATS extern double statsPhaseIncrement; extern double statsMaxPhaseIncrement; extern long statsPhaseSampleCount; extern double statsSampleSize; extern long statsSampleCount; #endif /*---------------------------------------------------------------------------- * Synthesizer interface *---------------------------------------------------------------------------- */ const S_SYNTH_INTERFACE wtSynth = { WT_Initialize, WT_StartVoice, WT_UpdateVoice, WT_ReleaseVoice, WT_MuteVoice, WT_SustainPedal, WT_UpdateChannel }; #ifdef EAS_SPLIT_WT_SYNTH const S_FRAME_INTERFACE wtFrameInterface = { WTE_StartFrame, WTE_EndFrame }; #endif /*---------------------------------------------------------------------------- * WT_Initialize() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * pVoice - pointer to voice to initialize * * Outputs: * *---------------------------------------------------------------------------- */ static EAS_RESULT WT_Initialize (S_VOICE_MGR *pVoiceMgr) { EAS_INT i; for (i = 0; i < NUM_WT_VOICES; i++) { pVoiceMgr->wtVoices[i].artIndex = DEFAULT_ARTICULATION_INDEX; pVoiceMgr->wtVoices[i].eg1State = DEFAULT_EG1_STATE; pVoiceMgr->wtVoices[i].eg1Value = DEFAULT_EG1_VALUE; pVoiceMgr->wtVoices[i].eg1Increment = DEFAULT_EG1_INCREMENT; pVoiceMgr->wtVoices[i].eg2State = DEFAULT_EG2_STATE; pVoiceMgr->wtVoices[i].eg2Value = DEFAULT_EG2_VALUE; pVoiceMgr->wtVoices[i].eg2Increment = DEFAULT_EG2_INCREMENT; /* left and right gain values are needed only if stereo output */ #if (NUM_OUTPUT_CHANNELS == 2) pVoiceMgr->wtVoices[i].gainLeft = DEFAULT_VOICE_GAIN; pVoiceMgr->wtVoices[i].gainRight = DEFAULT_VOICE_GAIN; #endif pVoiceMgr->wtVoices[i].phaseFrac = DEFAULT_PHASE_FRAC; pVoiceMgr->wtVoices[i].phaseAccum = DEFAULT_PHASE_INT; #ifdef _FILTER_ENABLED pVoiceMgr->wtVoices[i].filter.z1 = DEFAULT_FILTER_ZERO; pVoiceMgr->wtVoices[i].filter.z2 = DEFAULT_FILTER_ZERO; #endif } return EAS_TRUE; } /*---------------------------------------------------------------------------- * WT_ReleaseVoice() *---------------------------------------------------------------------------- * Purpose: * The selected voice is being released. * * Inputs: * pEASData - pointer to S_EAS_DATA * pVoice - pointer to voice to release * * Outputs: * None *---------------------------------------------------------------------------- */ /*lint -esym(715, pVoice) used in some implementations */ static void WT_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) { S_WT_VOICE *pWTVoice; const S_ARTICULATION *pArticulation; #ifdef DLS_SYNTHESIZER if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) { DLS_ReleaseVoice(pVoiceMgr, pSynth, pVoice, voiceNum); return; } #endif pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; pArticulation = &pSynth->pEAS->pArticulations[pWTVoice->artIndex]; /* release EG1 */ pWTVoice->eg1State = eEnvelopeStateRelease; pWTVoice->eg1Increment = pArticulation->eg1.releaseTime; /* The spec says we should release EG2, but doing so with the current voicing is causing clicks. This fix will need to be coordinated with a new sound library release */ /* release EG2 */ pWTVoice->eg2State = eEnvelopeStateRelease; pWTVoice->eg2Increment = pArticulation->eg2.releaseTime; } /*---------------------------------------------------------------------------- * WT_MuteVoice() *---------------------------------------------------------------------------- * Purpose: * The selected voice is being muted. * * Inputs: * pVoice - pointer to voice to release * * Outputs: * None *---------------------------------------------------------------------------- */ /*lint -esym(715, pSynth) used in some implementations */ static void WT_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) { #ifdef DLS_SYNTHESIZER if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) { DLS_MuteVoice(pVoiceMgr, pSynth, pVoice, voiceNum); return; } #endif /* clear deferred action flags */ pVoice->voiceFlags &= ~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF | VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF | VOICE_FLAG_DEFER_MUTE); /* set the envelope state */ pVoiceMgr->wtVoices[voiceNum].eg1State = eEnvelopeStateMuted; pVoiceMgr->wtVoices[voiceNum].eg2State = eEnvelopeStateMuted; } /*---------------------------------------------------------------------------- * WT_SustainPedal() *---------------------------------------------------------------------------- * Purpose: * The selected voice is held due to sustain pedal * * Inputs: * pVoice - pointer to voice to sustain * * Outputs: * None *---------------------------------------------------------------------------- */ /*lint -esym(715, pChannel) used in some implementations */ static void WT_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum) { S_WT_VOICE *pWTVoice; #ifdef DLS_SYNTHESIZER if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) { DLS_SustainPedal(pVoiceMgr, pSynth, pVoice, pChannel, voiceNum); return; } #endif /* don't catch the voice if below the sustain level */ pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; if (pWTVoice->eg1Value < pSynth->pEAS->pArticulations[pWTVoice->artIndex].eg1.sustainLevel) return; /* sustain flag is set, damper pedal is on */ /* defer releasing this note until the damper pedal is off */ pWTVoice->eg1State = eEnvelopeStateDecay; pVoice->voiceState = eVoiceStatePlay; /* because sustain pedal is on, this voice should defer releasing its note */ pVoice->voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; #ifdef _DEBUG_SYNTH { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_SustainPedal: defer note off because sustain pedal is on\n"); */ } #endif } /*---------------------------------------------------------------------------- * WT_StartVoice() *---------------------------------------------------------------------------- * Purpose: * Assign the region for the given instrument using the midi key number * and the RPN2 (coarse tuning) value. By using RPN2 as part of the * region selection process, we reduce the amount a given sample has * to be transposed by selecting the closest recorded root instead. * * This routine is the second half of SynthAssignRegion(). * If the region was successfully found by SynthFindRegionIndex(), * then assign the region's parameters to the voice. * * Setup and initialize the following voice parameters: * m_nRegionIndex * * Inputs: * pVoice - ptr to the voice we have assigned for this channel * nRegionIndex - index of the region * pEASData - pointer to overall EAS data structure * * Outputs: * success - could find and assign the region for this voice's note otherwise * failure - could not find nor assign the region for this voice's note * * Side Effects: * psSynthObject->m_sVoice[].m_nRegionIndex is assigned * psSynthObject->m_sVoice[] parameters are assigned *---------------------------------------------------------------------------- */ static EAS_RESULT WT_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex) { S_WT_VOICE *pWTVoice; const S_WT_REGION *pRegion; const S_ARTICULATION *pArt; S_SYNTH_CHANNEL *pChannel; #if (NUM_OUTPUT_CHANNELS == 2) EAS_INT pan; #endif #ifdef EAS_SPLIT_WT_SYNTH S_WT_CONFIG wtConfig; #endif /* no samples have been synthesized for this note yet */ pVoice->regionIndex = regionIndex; pVoice->voiceFlags = VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET; /* get the articulation index for this region */ pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; pChannel = &pSynth->channels[pVoice->channel & 15]; /* update static channel parameters */ if (pChannel->channelFlags & CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS) WT_UpdateChannel(pVoiceMgr, pSynth, pVoice->channel & 15); #ifdef DLS_SYNTHESIZER if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) return DLS_StartVoice(pVoiceMgr, pSynth, pVoice, voiceNum, regionIndex); #endif pRegion = &(pSynth->pEAS->pWTRegions[regionIndex]); pWTVoice->artIndex = pRegion->artIndex; #ifdef _DEBUG_SYNTH { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_StartVoice: Voice %ld; Region %d\n", (EAS_I32) (pVoice - pVoiceMgr->voices), regionIndex); */ } #endif pArt = &pSynth->pEAS->pArticulations[pWTVoice->artIndex]; /* MIDI note on puts this voice into attack state */ pWTVoice->eg1State = eEnvelopeStateAttack; pWTVoice->eg1Value = 0; pWTVoice->eg1Increment = pArt->eg1.attackTime; pWTVoice->eg2State = eEnvelopeStateAttack; pWTVoice->eg2Value = 0; pWTVoice->eg2Increment = pArt->eg2.attackTime; /* init the LFO */ pWTVoice->modLFO.lfoValue = 0; pWTVoice->modLFO.lfoPhase = -pArt->lfoDelay; pVoice->gain = 0; #if (NUM_OUTPUT_CHANNELS == 2) /* Get the Midi CC10 pan value for this voice's channel convert the pan value to an "angle" representation suitable for our sin, cos calculator. This representation is NOT necessarily the same as the transform in the GM manuals because of our sin, cos calculator. "angle" = (CC10 - 64)/128 */ pan = (EAS_INT) pSynth->channels[pVoice->channel & 15].pan - 64; pan += pArt->pan; EAS_CalcPanControl(pan, &pWTVoice->gainLeft, &pWTVoice->gainRight); #endif #ifdef _FILTER_ENABLED /* clear out the filter states */ pWTVoice->filter.z1 = 0; pWTVoice->filter.z2 = 0; #endif /* if this wave is to be generated using noise generator */ if (pRegion->region.keyGroupAndFlags & REGION_FLAG_USE_WAVE_GENERATOR) { pWTVoice->phaseAccum = 4574296; pWTVoice->loopStart = WT_NOISE_GENERATOR; pWTVoice->loopEnd = 4574295; } /* normal sample */ else { #ifdef EAS_SPLIT_WT_SYNTH if (voiceNum < NUM_PRIMARY_VOICES) pWTVoice->phaseAccum = (EAS_U32) pSynth->pEAS->pSamples + pSynth->pEAS->pSampleOffsets[pRegion->waveIndex]; else pWTVoice->phaseAccum = pSynth->pEAS->pSampleOffsets[pRegion->waveIndex]; #else pWTVoice->phaseAccum = (EAS_U32) pSynth->pEAS->pSamples + pSynth->pEAS->pSampleOffsets[pRegion->waveIndex]; #endif if (pRegion->region.keyGroupAndFlags & REGION_FLAG_IS_LOOPED) { pWTVoice->loopStart = pWTVoice->phaseAccum + pRegion->loopStart; pWTVoice->loopEnd = pWTVoice->phaseAccum + pRegion->loopEnd - 1; } else pWTVoice->loopStart = pWTVoice->loopEnd = pWTVoice->phaseAccum + pSynth->pEAS->pSampleLen[pRegion->waveIndex] - 1; } #ifdef EAS_SPLIT_WT_SYNTH /* configure off-chip voices */ if (voiceNum >= NUM_PRIMARY_VOICES) { wtConfig.phaseAccum = pWTVoice->phaseAccum; wtConfig.loopStart = pWTVoice->loopStart; wtConfig.loopEnd = pWTVoice->loopEnd; wtConfig.gain = pVoice->gain; #if (NUM_OUTPUT_CHANNELS == 2) wtConfig.gainLeft = pWTVoice->gainLeft; wtConfig.gainRight = pWTVoice->gainRight; #endif WTE_ConfigVoice(voiceNum - NUM_PRIMARY_VOICES, &wtConfig, pVoiceMgr->pFrameBuffer); } #endif return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * WT_CheckSampleEnd *---------------------------------------------------------------------------- * Purpose: * Check for end of sample and calculate number of samples to synthesize * * Inputs: * * Outputs: * * Notes: * *---------------------------------------------------------------------------- */ EAS_BOOL WT_CheckSampleEnd (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame, EAS_BOOL update) { EAS_U32 endPhaseAccum; EAS_U32 endPhaseFrac; EAS_I32 numSamples; EAS_BOOL done = EAS_FALSE; /* check to see if we hit the end of the waveform this time */ /*lint -e{703} use shift for performance */ endPhaseFrac = pWTVoice->phaseFrac + (pWTIntFrame->frame.phaseIncrement << SYNTH_UPDATE_PERIOD_IN_BITS); endPhaseAccum = pWTVoice->phaseAccum + GET_PHASE_INT_PART(endPhaseFrac); if (endPhaseAccum >= pWTVoice->loopEnd) { /* calculate how far current ptr is from end */ numSamples = (EAS_I32) (pWTVoice->loopEnd - pWTVoice->phaseAccum); /* now account for the fractional portion */ /*lint -e{703} use shift for performance */ numSamples = (EAS_I32) ((numSamples << NUM_PHASE_FRAC_BITS) - pWTVoice->phaseFrac); if (pWTIntFrame->frame.phaseIncrement) { pWTIntFrame->numSamples = 1 + (numSamples / pWTIntFrame->frame.phaseIncrement); } else { pWTIntFrame->numSamples = numSamples; } /* sound will be done this frame */ done = EAS_TRUE; } /* update data for off-chip synth */ if (update) { pWTVoice->phaseFrac = endPhaseFrac; pWTVoice->phaseAccum = endPhaseAccum; } return done; } /*---------------------------------------------------------------------------- * WT_UpdateVoice() *---------------------------------------------------------------------------- * Purpose: * Synthesize a block of samples for the given voice. * Use linear interpolation. * * Inputs: * pEASData - pointer to overall EAS data structure * * Outputs: * number of samples actually written to buffer * * Side Effects: * - samples are added to the presently free buffer * *---------------------------------------------------------------------------- */ static EAS_BOOL WT_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples) { S_WT_VOICE *pWTVoice; S_WT_INT_FRAME intFrame; S_SYNTH_CHANNEL *pChannel; const S_WT_REGION *pWTRegion; const S_ARTICULATION *pArt; EAS_I32 temp; EAS_BOOL done; #ifdef DLS_SYNTHESIZER if (pVoice->regionIndex & FLAG_RGN_IDX_DLS_SYNTH) return DLS_UpdateVoice(pVoiceMgr, pSynth, pVoice, voiceNum, pMixBuffer, numSamples); #endif /* establish pointers to critical data */ pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; pWTRegion = &pSynth->pEAS->pWTRegions[pVoice->regionIndex & REGION_INDEX_MASK]; pArt = &pSynth->pEAS->pArticulations[pWTVoice->artIndex]; pChannel = &pSynth->channels[pVoice->channel & 15]; intFrame.prevGain = pVoice->gain; /* update the envelopes */ WT_UpdateEG1(pWTVoice, &pArt->eg1); WT_UpdateEG2(pWTVoice, &pArt->eg2); /* update the LFO */ WT_UpdateLFO(&pWTVoice->modLFO, pArt->lfoFreq); #ifdef _FILTER_ENABLED /* calculate filter if library uses filter */ if (pSynth->pEAS->libAttr & LIB_FORMAT_FILTER_ENABLED) WT_UpdateFilter(pWTVoice, &intFrame, pArt); else intFrame.frame.k = 0; #endif /* update the gain */ intFrame.frame.gainTarget = WT_UpdateGain(pVoice, pWTVoice, pArt, pChannel, pWTRegion->gain); /* calculate base pitch*/ temp = pChannel->staticPitch + pWTRegion->tuning; /* include global transpose */ if (pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) temp += pVoice->note * 100; else temp += (pVoice->note + pSynth->globalTranspose) * 100; intFrame.frame.phaseIncrement = WT_UpdatePhaseInc(pWTVoice, pArt, pChannel, temp); /* call into engine to generate samples */ intFrame.pAudioBuffer = pVoiceMgr->voiceBuffer; intFrame.pMixBuffer = pMixBuffer; intFrame.numSamples = numSamples; /* check for end of sample */ if ((pWTVoice->loopStart != WT_NOISE_GENERATOR) && (pWTVoice->loopStart == pWTVoice->loopEnd)) done = WT_CheckSampleEnd(pWTVoice, &intFrame, (EAS_BOOL) (voiceNum >= NUM_PRIMARY_VOICES)); else done = EAS_FALSE; if (intFrame.numSamples < 0) intFrame.numSamples = 0; #ifdef EAS_SPLIT_WT_SYNTH if (voiceNum < NUM_PRIMARY_VOICES) { #ifndef _SPLIT_WT_TEST_HARNESS WT_ProcessVoice(pWTVoice, &intFrame); #endif } else WTE_ProcessVoice(voiceNum - NUM_PRIMARY_VOICES, &intFrame.frame, pVoiceMgr->pFrameBuffer); #else WT_ProcessVoice(pWTVoice, &intFrame); #endif /* clear flag */ pVoice->voiceFlags &= ~VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET; /* if voice has finished, set flag for voice manager */ if ((pVoice->voiceState != eVoiceStateStolen) && (pWTVoice->eg1State == eEnvelopeStateMuted)) done = EAS_TRUE; /* if the update interval has elapsed, then force the current gain to the next * gain since we never actually reach the next gain when ramping -- we just get * very close to the target gain. */ pVoice->gain = (EAS_I16) intFrame.frame.gainTarget; return done; } /*---------------------------------------------------------------------------- * WT_UpdatePhaseInc() *---------------------------------------------------------------------------- * Purpose: * Calculate the phase increment * * Inputs: * pVoice - pointer to the voice being updated * psRegion - pointer to the region * psArticulation - pointer to the articulation * nChannelPitchForThisVoice - the portion of the pitch that is fixed for this * voice during the duration of this synthesis * pEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * set the phase increment for this voice *---------------------------------------------------------------------------- */ static EAS_I32 WT_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents) { EAS_I32 temp; /*pitchCents due to CC1 = LFO * (CC1 / 128) * DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS */ temp = MULT_EG1_EG1(DEFAULT_LFO_MOD_WHEEL_TO_PITCH_CENTS, ((pChannel->modWheel) << (NUM_EG1_FRAC_BITS -7))); /* pitchCents due to channel pressure = LFO * (channel pressure / 128) * DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS */ temp += MULT_EG1_EG1(DEFAULT_LFO_CHANNEL_PRESSURE_TO_PITCH_CENTS, ((pChannel->channelPressure) << (NUM_EG1_FRAC_BITS -7))); /* now multiply the (channel pressure + CC1) pitch values by the LFO value */ temp = MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, temp); /* add in the LFO pitch due to channel pressure and CC1 along with the LFO pitch, the EG2 pitch, and the "static" pitch for this voice on this channel */ temp += pitchCents + (MULT_EG1_EG1(pWTVoice->eg2Value, pArt->eg2ToPitch)) + (MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, pArt->lfoToPitch)); /* convert from cents to linear phase increment */ return EAS_Calculate2toX(temp); } /*---------------------------------------------------------------------------- * WT_UpdateChannel() *---------------------------------------------------------------------------- * Purpose: * Calculate and assign static channel parameters * These values only need to be updated if one of the controller values * for this channel changes * * Inputs: * nChannel - channel to update * pEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * - the given channel's static gain and static pitch are updated *---------------------------------------------------------------------------- */ /*lint -esym(715, pVoiceMgr) reserved for future use */ static void WT_UpdateChannel (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) { EAS_I32 staticGain; EAS_I32 pitchBend; S_SYNTH_CHANNEL *pChannel; pChannel = &pSynth->channels[channel]; /* nChannelGain = (CC7 * CC11)^2 * master volume where CC7 == 100 by default, CC11 == 127, master volume == 32767 */ staticGain = MULT_EG1_EG1((pChannel->volume) << (NUM_EG1_FRAC_BITS - 7), (pChannel->expression) << (NUM_EG1_FRAC_BITS - 7)); /* staticGain has to be squared */ staticGain = MULT_EG1_EG1(staticGain, staticGain); pChannel->staticGain = (EAS_I16) MULT_EG1_EG1(staticGain, pSynth->masterVolume); /* calculate pitch bend: RPN0 * ((2*pitch wheel)/16384 -1) However, if we use the EG1 macros, remember that EG1 has a full scale value of 32768 (instead of 16384). So instead of multiplying by 2, multiply by 4 (left shift by 2), and subtract by 32768 instead of 16384. This utilizes the fact that the EG1 macro places a binary point 15 places to the left instead of 14 places. */ /*lint -e{703} */ pitchBend = (((EAS_I32)(pChannel->pitchBend) << 2) - 32768); pChannel->staticPitch = MULT_EG1_EG1(pitchBend, pChannel->pitchBendSensitivity); /* if this is not a drum channel, then add in the per-channel tuning */ if (!(pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL)) pChannel->staticPitch += pChannel->finePitch + (pChannel->coarsePitch * 100); /* clear update flag */ pChannel->channelFlags &= ~CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; return; } /*---------------------------------------------------------------------------- * WT_UpdateGain() *---------------------------------------------------------------------------- * Purpose: * Calculate and assign static voice parameters as part of WT_UpdateVoice() * * Inputs: * pVoice - ptr to the synth voice that we want to synthesize * pEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * - various voice parameters are calculated and assigned * *---------------------------------------------------------------------------- */ static EAS_I32 WT_UpdateGain (S_SYNTH_VOICE *pVoice, S_WT_VOICE *pWTVoice, const S_ARTICULATION *pArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain) { EAS_I32 lfoGain; EAS_I32 temp; /* If this voice was stolen, then the velocity is actually for the new note, not the note that we are currently ramping down. So we really shouldn't use this velocity. However, that would require more memory to store the velocity value, and the improvement may not be sufficient to warrant the added memory. */ /* velocity is fixed at note start for a given voice and must be squared */ temp = (pVoice->velocity) << (NUM_EG1_FRAC_BITS - 7); temp = MULT_EG1_EG1(temp, temp); /* region gain is fixed as part of the articulation */ temp = MULT_EG1_EG1(temp, gain); /* include the channel gain */ temp = MULT_EG1_EG1(temp, pChannel->staticGain); /* calculate LFO gain using an approximation for 10^x */ lfoGain = MULT_EG1_EG1(pWTVoice->modLFO.lfoValue, pArt->lfoToGain); lfoGain = MULT_EG1_EG1(lfoGain, LFO_GAIN_TO_CENTS); /* convert from a dB-like value to linear gain */ lfoGain = EAS_Calculate2toX(lfoGain); temp = MULT_EG1_EG1(temp, lfoGain); /* calculate the voice's gain */ temp = (EAS_I16)MULT_EG1_EG1(temp, pWTVoice->eg1Value); return temp; } /*---------------------------------------------------------------------------- * WT_UpdateEG1() *---------------------------------------------------------------------------- * Purpose: * Calculate the EG1 envelope for the given voice (but do not update any * state) * * Inputs: * pVoice - ptr to the voice whose envelope we want to update * nVoice - this voice's number - used only for debug * pEASData - pointer to overall EAS data structure * * Outputs: * nValue - the envelope value * * Side Effects: * - updates EG1 state value for the given voice *---------------------------------------------------------------------------- */ static void WT_UpdateEG1 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv) { EAS_I32 temp; switch (pWTVoice->eg1State) { case eEnvelopeStateAttack: temp = pWTVoice->eg1Value + pWTVoice->eg1Increment; /* check if we have reached peak amplitude */ if (temp >= SYNTH_FULL_SCALE_EG1_GAIN) { /* limit the volume */ temp = SYNTH_FULL_SCALE_EG1_GAIN; /* prepare to move to decay state */ pWTVoice->eg1State = eEnvelopeStateDecay; pWTVoice->eg1Increment = pEnv->decayTime; } break; /* exponential decay */ case eEnvelopeStateDecay: temp = MULT_EG1_EG1(pWTVoice->eg1Value, pWTVoice->eg1Increment); /* check if we have reached sustain level */ if (temp <= pEnv->sustainLevel) { /* enforce the sustain level */ temp = pEnv->sustainLevel; /* if sustain level is zero, skip sustain & release the voice */ if (temp > 0) pWTVoice->eg1State = eEnvelopeStateSustain; /* move to sustain state */ else pWTVoice->eg1State = eEnvelopeStateMuted; } break; case eEnvelopeStateSustain: return; case eEnvelopeStateRelease: temp = MULT_EG1_EG1(pWTVoice->eg1Value, pWTVoice->eg1Increment); /* if we hit zero, this voice isn't contributing any audio */ if (temp <= 0) { temp = 0; pWTVoice->eg1State = eEnvelopeStateMuted; } break; /* voice is muted, set target to zero */ case eEnvelopeStateMuted: temp = 0; break; case eEnvelopeStateInvalid: default: temp = 0; #ifdef _DEBUG_SYNTH { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_UpdateEG1: error, %d is an unrecognized state\n", pWTVoice->eg1State); */ } #endif break; } pWTVoice->eg1Value = (EAS_I16) temp; } /*---------------------------------------------------------------------------- * WT_UpdateEG2() *---------------------------------------------------------------------------- * Purpose: * Update the EG2 envelope for the given voice * * Inputs: * pVoice - ptr to the voice whose envelope we want to update * pEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * - updates EG2 values for the given voice *---------------------------------------------------------------------------- */ static void WT_UpdateEG2 (S_WT_VOICE *pWTVoice, const S_ENVELOPE *pEnv) { EAS_I32 temp; switch (pWTVoice->eg2State) { case eEnvelopeStateAttack: temp = pWTVoice->eg2Value + pWTVoice->eg2Increment; /* check if we have reached peak amplitude */ if (temp >= SYNTH_FULL_SCALE_EG1_GAIN) { /* limit the volume */ temp = SYNTH_FULL_SCALE_EG1_GAIN; /* prepare to move to decay state */ pWTVoice->eg2State = eEnvelopeStateDecay; pWTVoice->eg2Increment = pEnv->decayTime; } break; /* implement linear pitch decay in cents */ case eEnvelopeStateDecay: temp = pWTVoice->eg2Value -pWTVoice->eg2Increment; /* check if we have reached sustain level */ if (temp <= pEnv->sustainLevel) { /* enforce the sustain level */ temp = pEnv->sustainLevel; /* prepare to move to sustain state */ pWTVoice->eg2State = eEnvelopeStateSustain; } break; case eEnvelopeStateSustain: return; case eEnvelopeStateRelease: temp = pWTVoice->eg2Value - pWTVoice->eg2Increment; if (temp <= 0) { temp = 0; pWTVoice->eg2State = eEnvelopeStateMuted; } break; /* voice is muted, set target to zero */ case eEnvelopeStateMuted: temp = 0; break; case eEnvelopeStateInvalid: default: temp = 0; #ifdef _DEBUG_SYNTH { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "WT_UpdateEG2: error, %d is an unrecognized state\n", pWTVoice->eg2State); */ } #endif break; } pWTVoice->eg2Value = (EAS_I16) temp; } /*---------------------------------------------------------------------------- * WT_UpdateLFO () *---------------------------------------------------------------------------- * Purpose: * Calculate the LFO for the given voice * * Inputs: * pLFO - ptr to the LFO data * phaseInc - phase increment * * Outputs: * * Side Effects: * - updates LFO values for the given voice *---------------------------------------------------------------------------- */ void WT_UpdateLFO (S_LFO_CONTROL *pLFO, EAS_I16 phaseInc) { /* To save memory, if m_nPhaseValue is negative, we are in the * delay phase, and m_nPhaseValue represents the time left * in the delay. */ if (pLFO->lfoPhase < 0) { pLFO->lfoPhase++; return; } /* calculate LFO output from phase value */ /*lint -e{701} Use shift for performance */ pLFO->lfoValue = (EAS_I16) (pLFO->lfoPhase << 2); /*lint -e{502} */ if ((pLFO->lfoPhase > 0x1fff) && (pLFO->lfoPhase < 0x6000)) pLFO->lfoValue = ~pLFO->lfoValue; /* update LFO phase */ pLFO->lfoPhase = (pLFO->lfoPhase + phaseInc) & 0x7fff; } #ifdef _FILTER_ENABLED /*---------------------------------------------------------------------------- * WT_UpdateFilter() *---------------------------------------------------------------------------- * Purpose: * Update the Filter parameters * * Inputs: * pVoice - ptr to the voice whose filter we want to update * pEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * - updates Filter values for the given voice *---------------------------------------------------------------------------- */ static void WT_UpdateFilter (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pIntFrame, const S_ARTICULATION *pArt) { EAS_I32 cutoff; /* no need to calculate filter coefficients if it is bypassed */ if (pArt->filterCutoff == DEFAULT_EAS_FILTER_CUTOFF_FREQUENCY) { pIntFrame->frame.k = 0; return; } /* determine the dynamic cutoff frequency */ cutoff = MULT_EG1_EG1(pWTVoice->eg2Value, pArt->eg2ToFc); cutoff += pArt->filterCutoff; /* subtract the A5 offset and the sampling frequency */ cutoff -= FILTER_CUTOFF_FREQ_ADJUST + A5_PITCH_OFFSET_IN_CENTS; /* limit the cutoff frequency */ if (cutoff > FILTER_CUTOFF_MAX_PITCH_CENTS) cutoff = FILTER_CUTOFF_MAX_PITCH_CENTS; else if (cutoff < FILTER_CUTOFF_MIN_PITCH_CENTS) cutoff = FILTER_CUTOFF_MIN_PITCH_CENTS; WT_SetFilterCoeffs(pIntFrame, cutoff, pArt->filterQ); } #endif #if defined(_FILTER_ENABLED) || defined(DLS_SYNTHESIZER) /*---------------------------------------------------------------------------- * coef *---------------------------------------------------------------------------- * Table of filter coefficients for low-pass filter *---------------------------------------------------------------------------- * * polynomial coefficients are based on 8kHz sampling frequency * filter coef b2 = k2 = k2g0*k^0 + k2g1*k^1*(2^x) + k2g2*k^2*(2^x) * *where k2g0, k2g1, k2g2 are from the truncated power series expansion on theta *(k*2^x = theta, but we incorporate the k along with the k2g0, k2g1, k2g2) *note: this is a power series in 2^x, not k*2^x *where k = (2*pi*440)/8kHz == convert octaves to radians * * so actually, the following coefs listed as k2g0, k2g1, k2g2 are really * k2g0*k^0 = k2g0 * k2g1*k^1 * k2g2*k^2 * * * filter coef n1 = numerator = n1g0*k^0 + n1g1*k^1*(2^x) + n1g2*k^2*(2^x) + n1g3*k^3*(2^x) * *where n1g0, n1g1, n1g2, n1g3 are from the truncated power series expansion on theta *(k*2^x = theta, but we incorporate the k along with the n1g0, n1g1, n1g2, n2g3) *note: this is a power series in 2^x, not k*2^x *where k = (2*pi*440)/8kHz == convert octaves to radians *we also include the optimization factor of 0.81 * * so actually, the following coefs listed as n1g0, n1g1, n1g2, n2g3 are really * n1g0*k^0 = n1g0 * n1g1*k^1 * n1g2*k^2 * n1g3*k^3 * * NOTE that n1g0 == n1g1 == 0, always, so we only need to store n1g2 and n1g3 *---------------------------------------------------------------------------- */ static const EAS_I16 nk1g0 = -32768; static const EAS_I16 nk1g2 = 1580; static const EAS_I16 k2g0 = 32767; static const EAS_I16 k2g1[] = { -11324, /* k2g1[0] = -0.3455751918948761 */ -10387, /* k2g1[1] = -0.3169878073928751 */ -9528, /* k2g1[2] = -0.29076528753345476 */ -8740, /* k2g1[3] = -0.2667120011011279 */ -8017, /* k2g1[4] = -0.24464850028971705 */ -7353, /* k2g1[5] = -0.22441018194495696 */ -6745, /* k2g1[6] = -0.20584605955455101 */ -6187, /* k2g1[7] = -0.18881763682420102 */ -5675, /* k2g1[8] = -0.1731978744360067 */ -5206, /* k2g1[9] = -0.15887024228080968 */ -4775, /* k2g1[10] = -0.14572785009373057 */ -4380, /* k2g1[11] = -0.13367265000706827 */ -4018, /* k2g1[12] = -0.1226147050712642 */ -3685, /* k2g1[13] = -0.11247151828678581 */ -3381, /* k2g1[14] = -0.10316741714122014 */ -3101, /* k2g1[15] = -0.0946329890599603 */ -2844, /* k2g1[16] = -0.08680456355870586 */ -2609, /* k2g1[17] = -0.07962373723441349 */ -2393, /* k2g1[18] = -0.07303693805092666 */ -2195, /* k2g1[19] = -0.06699502566866912 */ -2014, /* k2g1[20] = -0.06145292483669077 */ -1847, /* k2g1[21] = -0.056369289112013346 */ -1694, /* k2g1[22] = -0.05170619239747895 */ -1554, /* k2g1[23] = -0.04742884599684141 */ -1426, /* k2g1[24] = -0.043505339076210514 */ -1308, /* k2g1[25] = -0.03990640059558053 */ -1199, /* k2g1[26] = -0.03660518093435039 */ -1100, /* k2g1[27] = -0.03357705158166837 */ -1009, /* k2g1[28] = -0.030799421397205727 */ -926, /* k2g1[29] = -0.028251568071585884 */ -849 /* k2g1[30] = -0.025914483529091967 */ }; static const EAS_I16 k2g2[] = { 1957, /* k2g2[0] = 0.059711106626580836 */ 1646, /* k2g2[1] = 0.05024063501786333 */ 1385, /* k2g2[2] = 0.042272226217199664 */ 1165, /* k2g2[3] = 0.03556764576567844 */ 981, /* k2g2[4] = 0.029926444346999134 */ 825, /* k2g2[5] = 0.025179964880280382 */ 694, /* k2g2[6] = 0.02118630011706455 */ 584, /* k2g2[7] = 0.01782604998793514 */ 491, /* k2g2[8] = 0.014998751854573014 */ 414, /* k2g2[9] = 0.012619876941179595 */ 348, /* k2g2[10] = 0.010618303146468736 */ 293, /* k2g2[11] = 0.008934188679954682 */ 246, /* k2g2[12] = 0.007517182949855368 */ 207, /* k2g2[13] = 0.006324921212866403 */ 174, /* k2g2[14] = 0.005321757979794424 */ 147, /* k2g2[15] = 0.004477701309210577 */ 123, /* k2g2[16] = 0.00376751612730811 */ 104, /* k2g2[17] = 0.0031699697655869644 */ 87, /* k2g2[18] = 0.00266719715992703 */ 74, /* k2g2[19] = 0.0022441667321724647 */ 62, /* k2g2[20] = 0.0018882309854916855 */ 52, /* k2g2[21] = 0.0015887483774966232 */ 44, /* k2g2[22] = 0.0013367651661223448 */ 37, /* k2g2[23] = 0.0011247477162958733 */ 31, /* k2g2[24] = 0.0009463572640678758 */ 26, /* k2g2[25] = 0.0007962604042473498 */ 22, /* k2g2[26] = 0.0006699696356181593 */ 18, /* k2g2[27] = 0.0005637091964589207 */ 16, /* k2g2[28] = 0.00047430217920125243 */ 13, /* k2g2[29] = 0.00039907554925166274 */ 11 /* k2g2[30] = 0.00033578022828973666 */ }; static const EAS_I16 n1g2[] = { 3170, /* n1g2[0] = 0.0967319927350769 */ 3036, /* n1g2[1] = 0.0926446051254155 */ 2908, /* n1g2[2] = 0.08872992911818503 */ 2785, /* n1g2[3] = 0.08498066682523227 */ 2667, /* n1g2[4] = 0.08138982872895201 */ 2554, /* n1g2[5] = 0.07795072065216213 */ 2446, /* n1g2[6] = 0.0746569312785634 */ 2343, /* n1g2[7] = 0.07150232020051943 */ 2244, /* n1g2[8] = 0.06848100647187474 */ 2149, /* n1g2[9] = 0.06558735764447099 */ 2058, /* n1g2[10] = 0.06281597926792246 */ 1971, /* n1g2[11] = 0.06016170483307614 */ 1888, /* n1g2[12] = 0.05761958614040857 */ 1808, /* n1g2[13] = 0.05518488407540374 */ 1732, /* n1g2[14] = 0.052853059773715245 */ 1659, /* n1g2[15] = 0.05061976615964251 */ 1589, /* n1g2[16] = 0.04848083984214659 */ 1521, /* n1g2[17] = 0.046432293353298 */ 1457, /* n1g2[18] = 0.04447030771468711 */ 1396, /* n1g2[19] = 0.04259122531793907 */ 1337, /* n1g2[20] = 0.040791543106060944 */ 1280, /* n1g2[21] = 0.03906790604290942 */ 1226, /* n1g2[22] = 0.037417100858604564 */ 1174, /* n1g2[23] = 0.035836050059229754 */ 1125, /* n1g2[24] = 0.03432180618965023 */ 1077, /* n1g2[25] = 0.03287154633875494 */ 1032, /* n1g2[26] = 0.03148256687687814 */ 988, /* n1g2[27] = 0.030152278415589925 */ 946, /* n1g2[28] = 0.028878200980459685 */ 906, /* n1g2[29] = 0.02765795938779331 */ 868 /* n1g2[30] = 0.02648927881672521 */ }; static const EAS_I16 n1g3[] = { -548, /* n1g3[0] = -0.016714088475899017 */ -481, /* n1g3[1] = -0.014683605122742116 */ -423, /* n1g3[2] = -0.012899791676436092 */ -371, /* n1g3[3] = -0.01133268185193299 */ -326, /* n1g3[4] = -0.00995594976868754 */ -287, /* n1g3[5] = -0.008746467702146129 */ -252, /* n1g3[6] = -0.00768391756106361 */ -221, /* n1g3[7] = -0.006750449563854721 */ -194, /* n1g3[8] = -0.005930382380083576 */ -171, /* n1g3[9] = -0.005209939699767622 */ -150, /* n1g3[10] = -0.004577018805123356 */ -132, /* n1g3[11] = -0.004020987256990177 */ -116, /* n1g3[12] = -0.003532504280467257 */ -102, /* n1g3[13] = -0.00310336384922047 */ -89, /* n1g3[14] = -0.002726356832432369 */ -78, /* n1g3[15] = -0.002395149888601605 */ -69, /* n1g3[16] = -0.0021041790717285314 */ -61, /* n1g3[17] = -0.0018485563625771063 */ -53, /* n1g3[18] = -0.001623987554831628 */ -47, /* n1g3[19] = -0.0014267001167177025 */ -41, /* n1g3[20] = -0.0012533798162347005 */ -36, /* n1g3[21] = -0.0011011150453668693 */ -32, /* n1g3[22] = -0.0009673479079754438 */ -28, /* n1g3[23] = -0.0008498312496971563 */ -24, /* n1g3[24] = -0.0007465909079943587 */ -21, /* n1g3[25] = -0.0006558925481952733 */ -19, /* n1g3[26] = -0.0005762125284029567 */ -17, /* n1g3[27] = -0.0005062123038325457 */ -15, /* n1g3[28] = -0.0004447159405951901 */ -13, /* n1g3[29] = -0.00039069036118270117 */ -11 /* n1g3[30] = -0.00034322798979677605 */ }; /*---------------------------------------------------------------------------- * WT_SetFilterCoeffs() *---------------------------------------------------------------------------- * Purpose: * Update the Filter parameters * * Inputs: * pVoice - ptr to the voice whose filter we want to update * pEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * - updates Filter values for the given voice *---------------------------------------------------------------------------- */ void WT_SetFilterCoeffs (S_WT_INT_FRAME *pIntFrame, EAS_I32 cutoff, EAS_I32 resonance) { EAS_I32 temp; /* Convert the cutoff, which has had A5 subtracted, using the 2^x approx Note, this cutoff is related to theta cutoff by theta = k * 2^x We use 2^x and incorporate k in the power series coefs instead */ cutoff = EAS_Calculate2toX(cutoff); /* calculate b2 coef */ temp = k2g1[resonance] + MULT_AUDIO_COEF(cutoff, k2g2[resonance]); temp = k2g0 + MULT_AUDIO_COEF(cutoff, temp); pIntFrame->frame.b2 = temp; /* calculate b1 coef */ temp = MULT_AUDIO_COEF(cutoff, nk1g2); temp = nk1g0 + MULT_AUDIO_COEF(cutoff, temp); temp += MULT_AUDIO_COEF(temp, pIntFrame->frame.b2); pIntFrame->frame.b1 = temp >> 1; /* calculate K coef */ temp = n1g2[resonance] + MULT_AUDIO_COEF(cutoff, n1g3[resonance]); temp = MULT_AUDIO_COEF(cutoff, temp); temp = MULT_AUDIO_COEF(cutoff, temp); pIntFrame->frame.k = temp; } #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_voicemgt.c0000644000000000000000000000013213532747316026725 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.858000056 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_voicemgt.c0000644000175000001440000040462513532747316027531 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_voicemgt.c * * Contents and purpose: * Implements the synthesizer functions. * * Copyright Sonic Network Inc. 2004 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 794 $ * $Date: 2007-08-01 00:08:48 -0700 (Wed, 01 Aug 2007) $ *---------------------------------------------------------------------------- */ /* includes */ #include "eas.h" #include "eas_data.h" #include "eas_config.h" #include "eas_report.h" #include "eas_midictrl.h" #include "eas_host.h" #include "eas_synth_protos.h" #include "eas_vm_protos.h" #ifdef DLS_SYNTHESIZER #include "eas_mdls.h" #endif // #define _DEBUG_VM /* some defines for workload */ #define WORKLOAD_AMOUNT_SMALL_INCREMENT 5 #define WORKLOAD_AMOUNT_START_NOTE 10 #define WORKLOAD_AMOUNT_STOP_NOTE 10 #define WORKLOAD_AMOUNT_KEY_GROUP 10 #define WORKLOAD_AMOUNT_POLY_LIMIT 10 /* pointer to base sound library */ extern S_EAS easSoundLib; #ifdef TEST_HARNESS extern S_EAS easTestLib; EAS_SNDLIB_HANDLE VMGetLibHandle(EAS_INT libNum) { switch (libNum) { case 0: return &easSoundLib; #ifdef _WT_SYNTH case 1: return &easTestLib; #endif default: return NULL; } } #endif /* pointer to synthesizer interface(s) */ #ifdef _WT_SYNTH extern const S_SYNTH_INTERFACE wtSynth; #endif #ifdef _FM_SYNTH extern const S_SYNTH_INTERFACE fmSynth; #endif typedef S_SYNTH_INTERFACE *S_SYNTH_INTERFACE_HANDLE; /* wavetable on MCU */ #if defined(EAS_WT_SYNTH) const S_SYNTH_INTERFACE *const pPrimarySynth = &wtSynth; /* FM on MCU */ #elif defined(EAS_FM_SYNTH) const S_SYNTH_INTERFACE *const pPrimarySynth = &fmSynth; /* wavetable drums on MCU, FM melodic on DSP */ #elif defined(EAS_HYBRID_SYNTH) const S_SYNTH_INTERFACE *const pPrimarySynth = &wtSynth; const S_SYNTH_INTERFACE *const pSecondarySynth = &fmSynth; /* wavetable drums on MCU, wavetable melodic on DSP */ #elif defined(EAS_SPLIT_WT_SYNTH) const S_SYNTH_INTERFACE *const pPrimarySynth = &wtSynth; extern const S_FRAME_INTERFACE wtFrameInterface; const S_FRAME_INTERFACE *const pFrameInterface = &wtFrameInterface; /* wavetable drums on MCU, FM melodic on DSP */ #elif defined(EAS_SPLIT_HYBRID_SYNTH) const S_SYNTH_INTERFACE *const pPrimarySynth = &wtSynth; const S_SYNTH_INTERFACE *const pSecondarySynth = &fmSynth; extern const S_FRAME_INTERFACE fmFrameInterface; const S_FRAME_INTERFACE *const pFrameInterface = &fmFrameInterface; /* FM on DSP */ #elif defined(EAS_SPLIT_FM_SYNTH) const S_SYNTH_INTERFACE *const pPrimarySynth = &fmSynth; extern const S_FRAME_INTERFACE fmFrameInterface; const S_FRAME_INTERFACE *const pFrameInterface = &fmFrameInterface; #else #error "Undefined architecture option" #endif /*---------------------------------------------------------------------------- * inline functions *---------------------------------------------------------------------------- */ EAS_INLINE const S_REGION* GetRegionPtr (S_SYNTH *pSynth, EAS_U16 regionIndex) { #if defined(DLS_SYNTHESIZER) if (regionIndex & FLAG_RGN_IDX_DLS_SYNTH) return &pSynth->pDLS->pDLSRegions[regionIndex & REGION_INDEX_MASK].wtRegion.region; #endif #if defined(_HYBRID_SYNTH) if (regionIndex & FLAG_RGN_IDX_FM_SYNTH) return &pSynth->pEAS->pFMRegions[regionIndex & REGION_INDEX_MASK].region; else return &pSynth->pEAS->pWTRegions[regionIndex].region; #elif defined(_WT_SYNTH) return &pSynth->pEAS->pWTRegions[regionIndex].region; #elif defined(_FM_SYNTH) return &pSynth->pEAS->pFMRegions[regionIndex].region; #endif } /*lint -esym(715, voiceNum) used in some implementation */ EAS_INLINE const S_SYNTH_INTERFACE* GetSynthPtr (EAS_INT voiceNum) { #if defined(_HYBRID_SYNTH) if (voiceNum < NUM_PRIMARY_VOICES) return pPrimarySynth; else return pSecondarySynth; #else return pPrimarySynth; #endif } EAS_INLINE EAS_INT GetAdjustedVoiceNum (EAS_INT voiceNum) { #if defined(_HYBRID_SYNTH) if (voiceNum >= NUM_PRIMARY_VOICES) return voiceNum - NUM_PRIMARY_VOICES; #endif return voiceNum; } EAS_INLINE EAS_U8 VSynthToChannel (S_SYNTH *pSynth, EAS_U8 channel) { /*lint -e{734} synthNum is always 0-15 */ return channel | (pSynth->vSynthNum << 4); } /*---------------------------------------------------------------------------- * InitVoice() *---------------------------------------------------------------------------- * Initialize a synthesizer voice *---------------------------------------------------------------------------- */ void InitVoice (S_SYNTH_VOICE *pVoice) { pVoice->channel = UNASSIGNED_SYNTH_CHANNEL; pVoice->nextChannel = UNASSIGNED_SYNTH_CHANNEL; pVoice->note = pVoice->nextNote = DEFAULT_KEY_NUMBER; pVoice->velocity = pVoice->nextVelocity = DEFAULT_VELOCITY; pVoice->regionIndex = DEFAULT_REGION_INDEX; pVoice->age = DEFAULT_AGE; pVoice->voiceFlags = DEFAULT_VOICE_FLAGS; pVoice->voiceState = DEFAULT_VOICE_STATE; } /*---------------------------------------------------------------------------- * IncVoicePoolCount() *---------------------------------------------------------------------------- * Updates the voice pool count when a voice changes state *---------------------------------------------------------------------------- */ static void IncVoicePoolCount (S_VOICE_MGR *pVoiceMgr, S_SYNTH_VOICE *pVoice) { S_SYNTH *pSynth; EAS_INT pool; /* ignore muting voices */ if (pVoice->voiceState == eVoiceStateMuting) return; if (pVoice->voiceState == eVoiceStateStolen) { pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->nextChannel)]; pool = pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool; } else { pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; pool = pSynth->channels[GET_CHANNEL(pVoice->channel)].pool; } pSynth->poolCount[pool]++; #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "IncVoicePoolCount: Synth=%d pool=%d\n", pSynth->vSynthNum, pool); */ } #endif } /*---------------------------------------------------------------------------- * DecVoicePoolCount() *---------------------------------------------------------------------------- * Updates the voice pool count when a voice changes state *---------------------------------------------------------------------------- */ static void DecVoicePoolCount (S_VOICE_MGR *pVoiceMgr, S_SYNTH_VOICE *pVoice) { S_SYNTH *pSynth; EAS_INT pool; /* ignore muting voices */ if (pVoice->voiceState == eVoiceStateMuting) return; if (pVoice->voiceState == eVoiceStateStolen) { pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->nextChannel)]; pool = pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool; } else { pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; pool = pSynth->channels[GET_CHANNEL(pVoice->channel)].pool; } pSynth->poolCount[pool]--; #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "DecVoicePoolCount: Synth=%d pool=%d\n", pSynth->vSynthNum, pool); */ } #endif } /*---------------------------------------------------------------------------- * VMInitialize() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * *---------------------------------------------------------------------------- */ EAS_RESULT VMInitialize (S_EAS_DATA *pEASData) { S_VOICE_MGR *pVoiceMgr; EAS_INT i; /* check Configuration Module for data allocation */ if (pEASData->staticMemoryModel) pVoiceMgr = EAS_CMEnumData(EAS_CM_SYNTH_DATA); else pVoiceMgr = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_VOICE_MGR)); if (!pVoiceMgr) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitialize: Failed to allocate synthesizer memory\n"); */ } return EAS_ERROR_MALLOC_FAILED; } EAS_HWMemSet(pVoiceMgr, 0, sizeof(S_VOICE_MGR)); /* initialize non-zero variables */ pVoiceMgr->pGlobalEAS = (S_EAS*) &easSoundLib; pVoiceMgr->maxPolyphony = (EAS_U16) MAX_SYNTH_VOICES; #if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) pVoiceMgr->maxPolyphonyPrimary = NUM_PRIMARY_VOICES; pVoiceMgr->maxPolyphonySecondary = NUM_SECONDARY_VOICES; #endif /* set max workload to zero */ pVoiceMgr->maxWorkLoad = 0; /* initialize the voice manager parameters */ for (i = 0; i < MAX_SYNTH_VOICES; i++) InitVoice(&pVoiceMgr->voices[i]); /* initialize the synth */ /*lint -e{522} return unused at this time */ pPrimarySynth->pfInitialize(pVoiceMgr); /* initialize the off-chip synth */ #ifdef _HYBRID_SYNTH /*lint -e{522} return unused at this time */ pSecondarySynth->pfInitialize(pVoiceMgr); #endif pEASData->pVoiceMgr = pVoiceMgr; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * VMInitMIDI() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * *---------------------------------------------------------------------------- */ EAS_RESULT VMInitMIDI (S_EAS_DATA *pEASData, S_SYNTH **ppSynth) { EAS_RESULT result; S_SYNTH *pSynth; EAS_INT virtualSynthNum; *ppSynth = NULL; /* static memory model only allows one synth */ if (pEASData->staticMemoryModel) { if (pEASData->pVoiceMgr->pSynth[0] != NULL) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI: No virtual synthesizer support for static memory model\n"); */ } return EAS_ERROR_NO_VIRTUAL_SYNTHESIZER; } /* check Configuration Module for data allocation */ pSynth = EAS_CMEnumData(EAS_CM_MIDI_DATA); virtualSynthNum = 0; } /* dynamic memory model */ else { for (virtualSynthNum = 0; virtualSynthNum < MAX_VIRTUAL_SYNTHESIZERS; virtualSynthNum++) if (pEASData->pVoiceMgr->pSynth[virtualSynthNum] == NULL) break; if (virtualSynthNum == MAX_VIRTUAL_SYNTHESIZERS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI: Exceeded number of active virtual synthesizers"); */ } return EAS_ERROR_NO_VIRTUAL_SYNTHESIZER; } pSynth = EAS_HWMalloc(pEASData->hwInstData, sizeof(S_SYNTH)); } /* make sure we have a valid memory pointer */ if (pSynth == NULL) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMInitMIDI: Failed to allocate synthesizer memory\n"); */ } return EAS_ERROR_MALLOC_FAILED; } EAS_HWMemSet(pSynth, 0, sizeof(S_SYNTH)); /* set the sound library pointer */ if ((result = VMSetEASLib(pSynth, pEASData->pVoiceMgr->pGlobalEAS)) != EAS_SUCCESS) { VMMIDIShutdown(pEASData, pSynth); return result; } /* link in DLS bank if downloaded */ #ifdef DLS_SYNTHESIZER if (pEASData->pVoiceMgr->pGlobalDLS) { pSynth->pDLS = pEASData->pVoiceMgr->pGlobalDLS; DLSAddRef(pSynth->pDLS); } #endif /* initialize MIDI state variables */ pSynth->synthFlags = DEFAULT_SYNTH_FLAGS; pSynth->masterVolume = DEFAULT_SYNTH_MASTER_VOLUME; pSynth->refCount = 1; pSynth->priority = DEFAULT_SYNTH_PRIORITY; pSynth->poolAlloc[0] = (EAS_U8) pEASData->pVoiceMgr->maxPolyphony; VMInitializeAllChannels(pEASData->pVoiceMgr, pSynth); pSynth->vSynthNum = (EAS_U8) virtualSynthNum; pEASData->pVoiceMgr->pSynth[virtualSynthNum] = pSynth; *ppSynth = pSynth; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * VMIncRefCount() *---------------------------------------------------------------------------- * Increment reference count for virtual synth *---------------------------------------------------------------------------- */ void VMIncRefCount (S_SYNTH *pSynth) { pSynth->refCount++; } /*---------------------------------------------------------------------------- * VMReset() *---------------------------------------------------------------------------- * Purpose: * We call this routine to start the process of reseting the synth. * This routine sets a flag for the entire synth indicating that we want * to reset. * We also force all voices to mute quickly. * However, we do not actually perform any synthesis in this routine. That * is, we do not ramp the voices down from this routine, but instead, we * let the "regular" synth processing steps take care of adding the ramp * down samples to the output buffer. After we are sure that all voices * have completed ramping down, we continue the process of resetting the * synth (from another routine). * * Inputs: * psEASData - pointer to overall EAS data structure * force - force reset even if voices are active * * Outputs: * * Side Effects: * - set a flag (in psSynthObject->m_nFlags) indicating synth reset requested. * - force all voices to update their envelope states to mute * *---------------------------------------------------------------------------- */ void VMReset (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_BOOL force) { #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMReset: request to reset synth. Force = %d\n", force); */ } #endif /* force voices to off state - may cause audio artifacts */ if (force) { pVoiceMgr->activeVoices -= pSynth->numActiveVoices; pSynth->numActiveVoices = 0; VMInitializeAllVoices(pVoiceMgr, pSynth->vSynthNum); } else VMMuteAllVoices(pVoiceMgr, pSynth); /* don't reset if voices are still playing */ if (pSynth->numActiveVoices == 0) { EAS_INT i; #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMReset: complete the reset process\n"); */ } #endif VMInitializeAllChannels(pVoiceMgr, pSynth); for (i = 0; i < NUM_SYNTH_CHANNELS; i++) pSynth->poolCount[i] = 0; /* set polyphony */ if (pSynth->maxPolyphony < pVoiceMgr->maxPolyphony) pSynth->poolAlloc[0] = (EAS_U8) pVoiceMgr->maxPolyphony; else pSynth->poolAlloc[0] = (EAS_U8) pSynth->maxPolyphony; /* clear reset flag */ pSynth->synthFlags &= ~SYNTH_FLAG_RESET_IS_REQUESTED; } /* handle reset after voices are muted */ else pSynth->synthFlags |= SYNTH_FLAG_RESET_IS_REQUESTED; } /*---------------------------------------------------------------------------- * VMInitializeAllChannels() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * *---------------------------------------------------------------------------- */ void VMInitializeAllChannels (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) { S_SYNTH_CHANNEL *pChannel; EAS_INT i; VMResetControllers(pSynth); /* init each channel */ pChannel = pSynth->channels; for (i = 0; i < NUM_SYNTH_CHANNELS; i++, pChannel++) { pChannel->channelFlags = DEFAULT_CHANNEL_FLAGS; pChannel->staticGain = DEFAULT_CHANNEL_STATIC_GAIN; pChannel->staticPitch = DEFAULT_CHANNEL_STATIC_PITCH; pChannel->pool = 0; /* the drum channel needs a different init */ if (i == DEFAULT_DRUM_CHANNEL) { pChannel->bankNum = DEFAULT_RHYTHM_BANK_NUMBER; pChannel->channelFlags |= CHANNEL_FLAG_RHYTHM_CHANNEL; } else pChannel->bankNum = DEFAULT_MELODY_BANK_NUMBER; VMProgramChange(pVoiceMgr, pSynth, (EAS_U8) i, DEFAULT_SYNTH_PROGRAM_NUMBER); } } /*---------------------------------------------------------------------------- * VMResetControllers() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * *---------------------------------------------------------------------------- */ void VMResetControllers (S_SYNTH *pSynth) { S_SYNTH_CHANNEL *pChannel; EAS_INT i; pChannel = pSynth->channels; for (i = 0; i < NUM_SYNTH_CHANNELS; i++, pChannel++) { pChannel->pitchBend = DEFAULT_PITCH_BEND; pChannel->modWheel = DEFAULT_MOD_WHEEL; pChannel->volume = DEFAULT_CHANNEL_VOLUME; pChannel->pan = DEFAULT_PAN; pChannel->expression = DEFAULT_EXPRESSION; #ifdef _REVERB pSynth->channels[i].reverbSend = DEFAULT_REVERB_SEND; #endif #ifdef _CHORUS pSynth->channels[i].chorusSend = DEFAULT_CHORUS_SEND; #endif pChannel->channelPressure = DEFAULT_CHANNEL_PRESSURE; pChannel->registeredParam = DEFAULT_REGISTERED_PARAM; pChannel->pitchBendSensitivity = DEFAULT_PITCH_BEND_SENSITIVITY; pChannel->finePitch = DEFAULT_FINE_PITCH; pChannel->coarsePitch = DEFAULT_COARSE_PITCH; /* update all voices on this channel */ pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; } } /*---------------------------------------------------------------------------- * VMInitializeAllVoices() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * *---------------------------------------------------------------------------- */ void VMInitializeAllVoices (S_VOICE_MGR *pVoiceMgr, EAS_INT vSynthNum) { EAS_INT i; /* initialize the voice manager parameters */ for (i = 0; i < MAX_SYNTH_VOICES; i++) { if (pVoiceMgr->voices[i].voiceState != eVoiceStateStolen) { if (GET_VSYNTH(pVoiceMgr->voices[i].channel) == vSynthNum) InitVoice(&pVoiceMgr->voices[i]); } else { if (GET_VSYNTH(pVoiceMgr->voices[i].nextChannel) == vSynthNum) InitVoice(&pVoiceMgr->voices[i]); } } } /*---------------------------------------------------------------------------- * VMMuteVoice() *---------------------------------------------------------------------------- * Mute the selected voice *---------------------------------------------------------------------------- */ void VMMuteVoice (S_VOICE_MGR *pVoiceMgr, EAS_I32 voiceNum) { S_SYNTH *pSynth; S_SYNTH_VOICE *pVoice; /* take no action if voice is already muted */ pVoice = &pVoiceMgr->voices[voiceNum]; if ((pVoice->voiceState == eVoiceStateMuting) || (pVoice->voiceState == eVoiceStateFree)) return; /* one less voice in pool */ DecVoicePoolCount(pVoiceMgr, pVoice); pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; GetSynthPtr(voiceNum)->pfMuteVoice(pVoiceMgr, pSynth, pVoice, GetAdjustedVoiceNum(voiceNum)); pVoice->voiceState = eVoiceStateMuting; } /*---------------------------------------------------------------------------- * VMReleaseVoice() *---------------------------------------------------------------------------- * Release the selected voice *---------------------------------------------------------------------------- */ void VMReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 voiceNum) { S_SYNTH_VOICE *pVoice = &pVoiceMgr->voices[voiceNum]; /* take no action if voice is already free, muting, or releasing */ if (( pVoice->voiceState == eVoiceStateMuting) || (pVoice->voiceState == eVoiceStateFree) || (pVoice->voiceState == eVoiceStateRelease)) return; /* stolen voices should just be muted */ if (pVoice->voiceState == eVoiceStateStolen) VMMuteVoice(pVoiceMgr, voiceNum); /* release this voice */ GetSynthPtr(voiceNum)->pfReleaseVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum)); pVoice->voiceState = eVoiceStateRelease; } /*---------------------------------------------------------------------------- * VMInitMIPTable() *---------------------------------------------------------------------------- * Initialize the SP-MIDI MIP table in preparation for receiving MIP message *---------------------------------------------------------------------------- */ void VMInitMIPTable (S_SYNTH *pSynth) { EAS_INT i; #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMInitMIPTable\n"); */ } #endif /* clear SP-MIDI flag */ pSynth->synthFlags &= ~SYNTH_FLAG_SP_MIDI_ON; for (i = 0; i < NUM_SYNTH_CHANNELS; i++) { pSynth->channels[i].pool = 0; pSynth->channels[i].mip = 0; } } /*---------------------------------------------------------------------------- * VMSetMIPEntry() *---------------------------------------------------------------------------- * Sets the priority and MIP level for a MIDI channel *---------------------------------------------------------------------------- */ /*lint -esym(715, pVoiceMgr) reserved for future use */ void VMSetMIPEntry (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 priority, EAS_U8 mip) { #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMSetMIPEntry: channel=%d, priority=%d, MIP=%d\n", channel, priority, mip); */ } #endif /* save data for use by MIP message processing */ if (priority < NUM_SYNTH_CHANNELS) { pSynth->channels[channel].pool = priority; pSynth->channels[channel].mip = mip; } } /*---------------------------------------------------------------------------- * VMMIPUpdateChannelMuting() *---------------------------------------------------------------------------- * This routine is called after an SP-MIDI message is received and * any time the allocated polyphony changes. It mutes or unmutes * channels based on polyphony. *---------------------------------------------------------------------------- */ void VMMIPUpdateChannelMuting (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) { EAS_INT i; EAS_INT maxPolyphony; EAS_INT channel; EAS_INT vSynthNum; EAS_INT pool; #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMUpdateMIPTable\n"); */ } #endif /* determine max polyphony */ if (pSynth->maxPolyphony) maxPolyphony = pSynth->maxPolyphony; else maxPolyphony = pVoiceMgr->maxPolyphony; /* process channels */ for (i = 0; i < NUM_SYNTH_CHANNELS; i++) { /* channel must be in MIP message and must meet allocation target */ if ((pSynth->channels[i].mip != 0) && (pSynth->channels[i].mip <= maxPolyphony)) pSynth->channels[i].channelFlags &= ~CHANNEL_FLAG_MUTE; else pSynth->channels[i].channelFlags |= CHANNEL_FLAG_MUTE; /* reset voice pool count */ pSynth->poolCount[i] = 0; } /* mute any voices on muted channels, and count unmuted voices */ for (i = 0; i < MAX_SYNTH_VOICES; i++) { /* ignore free voices */ if (pVoiceMgr->voices[i].voiceState == eVoiceStateFree) continue; /* get channel and virtual synth */ if (pVoiceMgr->voices[i].voiceState != eVoiceStateStolen) { vSynthNum = GET_VSYNTH(pVoiceMgr->voices[i].channel); channel = GET_CHANNEL(pVoiceMgr->voices[i].channel); } else { vSynthNum = GET_VSYNTH(pVoiceMgr->voices[i].nextChannel); channel = GET_CHANNEL(pVoiceMgr->voices[i].nextChannel); } /* ignore voices on other synths */ if (vSynthNum != pSynth->vSynthNum) continue; /* count voices */ pool = pSynth->channels[channel].pool; /* deal with muted channels */ if (pSynth->channels[channel].channelFlags & CHANNEL_FLAG_MUTE) { /* mute stolen voices scheduled to play on this channel */ if (pVoiceMgr->voices[i].voiceState == eVoiceStateStolen) pVoiceMgr->voices[i].voiceState = eVoiceStateMuting; /* release voices that aren't already muting */ else if (pVoiceMgr->voices[i].voiceState != eVoiceStateMuting) { VMReleaseVoice(pVoiceMgr, pSynth, i); pSynth->poolCount[pool]++; } } /* not muted, count this voice */ else pSynth->poolCount[pool]++; } } /*---------------------------------------------------------------------------- * VMUpdateMIPTable() *---------------------------------------------------------------------------- * This routine is called at the end of the SysEx message to allow * the Voice Manager to complete the initialization of the MIP * table. It assigns channels to the appropriate voice pool based * on the MIP setting and calculates the voices allocated for each * pool. *---------------------------------------------------------------------------- */ /*lint -esym(715, pVoiceMgr) reserved for future use */ void VMUpdateMIPTable (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) { S_SYNTH_CHANNEL *pChannel; EAS_INT i; EAS_INT currentMIP; EAS_INT currentPool; EAS_INT priority[NUM_SYNTH_CHANNELS]; #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMUpdateMIPTable\n"); */ } #endif /* set SP-MIDI flag */ pSynth->synthFlags |= SYNTH_FLAG_SP_MIDI_ON; /* sort channels into priority order */ for (i = 0; i < NUM_SYNTH_CHANNELS; i++) priority[i] = -1; for (i = 0; i < NUM_SYNTH_CHANNELS; i++) { if (pSynth->channels[i].pool != DEFAULT_SP_MIDI_PRIORITY) priority[pSynth->channels[i].pool] = i; } /* process channels in priority order */ currentMIP = 0; currentPool = -1; for (i = 0; i < NUM_SYNTH_CHANNELS; i++) { /* stop when we run out of channels */ if (priority[i] == -1) break; pChannel = &pSynth->channels[priority[i]]; /* when 2 or more channels have the same MIP setting, they * share a common voice pool */ if (pChannel->mip == currentMIP) pChannel->pool = (EAS_U8) currentPool; /* new voice pool */ else { currentPool++; pSynth->poolAlloc[currentPool] = (EAS_U8) (pChannel->mip - currentMIP); currentMIP = pChannel->mip; } } /* set SP-MIDI flag */ pSynth->synthFlags |= SYNTH_FLAG_SP_MIDI_ON; /* update channel muting */ VMMIPUpdateChannelMuting (pVoiceMgr, pSynth); } /*---------------------------------------------------------------------------- * VMMuteAllVoices() *---------------------------------------------------------------------------- * Purpose: * We call this in an emergency reset situation. * This forces all voices to mute quickly. * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * - forces all voices to update their envelope states to mute * *---------------------------------------------------------------------------- */ void VMMuteAllVoices (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) { EAS_INT i; #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMMuteAllVoices: about to mute all voices!!\n"); */ } #endif for (i = 0; i < MAX_SYNTH_VOICES; i++) { /* for stolen voices, check new channel */ if (pVoiceMgr->voices[i].voiceState == eVoiceStateStolen) { if (GET_VSYNTH(pVoiceMgr->voices[i].nextChannel) == pSynth->vSynthNum) VMMuteVoice(pVoiceMgr, i); } else if (pSynth->vSynthNum == GET_VSYNTH(pVoiceMgr->voices[i].channel)) VMMuteVoice(pVoiceMgr, i); } } /*---------------------------------------------------------------------------- * VMReleaseAllVoices() *---------------------------------------------------------------------------- * Purpose: * We call this after we've encountered the end of the Midi file. * This ensures all voices are either in release (because we received their * note off already) or forces them to mute quickly. * We use this as a safety to prevent bad midi files from playing forever. * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * - forces all voices to update their envelope states to release or mute * *---------------------------------------------------------------------------- */ void VMReleaseAllVoices (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) { EAS_INT i; /* release sustain pedal on all channels */ for (i = 0; i < NUM_SYNTH_CHANNELS; i++) { if (pSynth->channels[ i ].channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) { VMReleaseAllDeferredNoteOffs(pVoiceMgr, pSynth, (EAS_U8) i); pSynth->channels[i].channelFlags &= ~CHANNEL_FLAG_SUSTAIN_PEDAL; } } /* release all voices */ for (i = 0; i < MAX_SYNTH_VOICES; i++) { switch (pVoiceMgr->voices[i].voiceState) { case eVoiceStateStart: case eVoiceStatePlay: /* only release voices on this synth */ if (GET_VSYNTH(pVoiceMgr->voices[i].channel) == pSynth->vSynthNum) VMReleaseVoice(pVoiceMgr, pSynth, i); break; case eVoiceStateStolen: if (GET_VSYNTH(pVoiceMgr->voices[i].nextChannel) == pSynth->vSynthNum) VMMuteVoice(pVoiceMgr, i); break; case eVoiceStateFree: case eVoiceStateRelease: case eVoiceStateMuting: break; case eVoiceStateInvalid: default: #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMReleaseAllVoices: error, %d is an unrecognized state\n", pVoiceMgr->voices[i].voiceState); */ } #endif break; } } } /*---------------------------------------------------------------------------- * VMAllNotesOff() *---------------------------------------------------------------------------- * Purpose: * Quickly mute all notes on the given channel. * * Inputs: * nChannel - quickly turn off all notes on this channel * psEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * - forces all voices on this channel to update their envelope states to mute * *---------------------------------------------------------------------------- */ void VMAllNotesOff (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) { EAS_INT voiceNum; S_SYNTH_VOICE *pVoice; #ifdef _DEBUG_VM if (channel >= NUM_SYNTH_CHANNELS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMAllNotesOff: error, %d invalid channel number\n", channel); */ } return; } #endif /* increment workload */ pVoiceMgr->workload += WORKLOAD_AMOUNT_SMALL_INCREMENT; /* check each voice */ channel = VSynthToChannel(pSynth, channel); for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) { pVoice = &pVoiceMgr->voices[voiceNum]; if (pVoice->voiceState != eVoiceStateFree) { if (((pVoice->voiceState != eVoiceStateStolen) && (channel == pVoice->channel)) || ((pVoice->voiceState == eVoiceStateStolen) && (channel == pVoice->nextChannel))) { /* this voice is assigned to the requested channel */ GetSynthPtr(voiceNum)->pfMuteVoice(pVoiceMgr, pSynth, pVoice, GetAdjustedVoiceNum(voiceNum)); pVoice->voiceState = eVoiceStateMuting; } } } } /*---------------------------------------------------------------------------- * VMDeferredStopNote() *---------------------------------------------------------------------------- * Purpose: * Stop the notes that had deferred note-off requests. * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * None. * * Side Effects: * voices that have had deferred note-off requests are now put into release * psSynthObject->m_sVoice[i].m_nFlags has the VOICE_FLAG_DEFER_MIDI_NOTE_OFF * cleared *---------------------------------------------------------------------------- */ void VMDeferredStopNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) { EAS_INT voiceNum; EAS_INT channel; EAS_BOOL deferredNoteOff; deferredNoteOff = EAS_FALSE; /* check each voice to see if it requires a deferred note off */ for (voiceNum=0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) { if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_DEFER_MIDI_NOTE_OFF) { /* check if this voice was stolen */ if (pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateStolen) { /* This voice was stolen, AND it also has a deferred note-off. The stolen note must be completely ramped down at this point. The note that caused the stealing to occur, however, must have received a note-off request before the note that caused stealing ever had a chance to even start. We want to give the note that caused the stealing a chance to play, so we start it on the next update interval, and we defer sending the note-off request until the subsequent update interval. So do not send the note-off request for this voice because this voice was stolen and should have completed ramping down, Also, do not clear the global flag nor this voice's flag because we must indicate that the subsequent update interval, after the note that caused stealing has started, should then send the deferred note-off request. */ deferredNoteOff = EAS_TRUE; #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMDeferredStopNote: defer request to stop voice %d (channel=%d note=%d) - voice not started\n", voiceNum, pVoiceMgr->voices[voiceNum].nextChannel, pVoiceMgr->voices[voiceNum].note); */ } /* sanity check: this stolen voice better be ramped to zero */ if (0 != pVoiceMgr->voices[voiceNum].gain) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMDeferredStopNote: warning, this voice did not complete its ramp to zero\n"); */ } } #endif // #ifdef _DEBUG_VM } else { /* clear the flag using exor */ pVoiceMgr->voices[voiceNum].voiceFlags ^= VOICE_FLAG_DEFER_MIDI_NOTE_OFF; #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMDeferredStopNote: Stop voice %d (channel=%d note=%d)\n", voiceNum, pVoiceMgr->voices[voiceNum].nextChannel, pVoiceMgr->voices[voiceNum].note); */ } #endif channel = pVoiceMgr->voices[voiceNum].channel & 15; /* check if sustain pedal is on */ if (pSynth->channels[channel].channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) { GetSynthPtr(voiceNum)->pfSustainPedal(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], &pSynth->channels[channel], GetAdjustedVoiceNum(voiceNum)); } /* release this voice */ else VMReleaseVoice(pVoiceMgr, pSynth, voiceNum); } } } /* clear the deferred note-off flag, unless there's another one pending */ if (deferredNoteOff == EAS_FALSE) pSynth->synthFlags ^= SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING; } /*---------------------------------------------------------------------------- * VMReleaseAllDeferredNoteOffs() *---------------------------------------------------------------------------- * Purpose: * Call this functin when the sustain flag is presently set but * we are now transitioning from damper pedal on to * damper pedal off. This means all notes in this channel * that received a note off while the damper pedal was on, and * had their note-off requests deferred, should now proceed to * the release state. * * Inputs: * nChannel - this channel has its sustain pedal transitioning from on to off * psEASData - pointer to overall EAS data structure * * Outputs: * Side Effects: * any voice with deferred note offs on this channel are updated such that * pVoice->m_sEG1.m_eState = eEnvelopeStateRelease * pVoice->m_sEG1.m_nIncrement = release increment * pVoice->m_nFlags = clear the deferred note off flag *---------------------------------------------------------------------------- */ void VMReleaseAllDeferredNoteOffs (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) { S_SYNTH_VOICE *pVoice; EAS_INT voiceNum; #ifdef _DEBUG_VM if (channel >= NUM_SYNTH_CHANNELS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMReleaseAllDeferredNoteOffs: error, %d invalid channel number\n", channel); */ } return; } #endif /* #ifdef _DEBUG_VM */ /* increment workload */ pVoiceMgr->workload += WORKLOAD_AMOUNT_SMALL_INCREMENT; /* find all the voices assigned to this channel */ channel = VSynthToChannel(pSynth, channel); for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) { pVoice = &pVoiceMgr->voices[voiceNum]; if (channel == pVoice->channel) { /* does this voice have a deferred note off? */ if (pVoice->voiceFlags & VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF) { /* release voice */ VMReleaseVoice(pVoiceMgr, pSynth, voiceNum); /* use exor to flip bit, clear the flag */ pVoice->voiceFlags &= ~VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; } } } return; } /*---------------------------------------------------------------------------- * VMCatchNotesForSustainPedal() *---------------------------------------------------------------------------- * Purpose: * Call this function when the sustain flag is presently clear and * the damper pedal is off and we are transitioning from damper pedal OFF to * damper pedal ON. Currently sounding notes should be left * unchanged. However, we should try to "catch" notes if possible. * If any notes are in release and have levels >= sustain level, catch them, * otherwise, let them continue to release. * * Inputs: * nChannel - this channel has its sustain pedal transitioning from on to off * psEASData - pointer to overall EAS data structure * * Outputs: *---------------------------------------------------------------------------- */ void VMCatchNotesForSustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel) { EAS_INT voiceNum; #ifdef _DEBUG_VM if (channel >= NUM_SYNTH_CHANNELS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMCatchNotesForSustainPedal: error, %d invalid channel number\n", channel); */ } return; } #endif pVoiceMgr->workload += WORKLOAD_AMOUNT_SMALL_INCREMENT; channel = VSynthToChannel(pSynth, channel); /* find all the voices assigned to this channel */ for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) { if (channel == pVoiceMgr->voices[voiceNum].channel) { if (eVoiceStateRelease == pVoiceMgr->voices[voiceNum].voiceState) GetSynthPtr(voiceNum)->pfSustainPedal(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], &pSynth->channels[channel], GetAdjustedVoiceNum(voiceNum)); } } } /*---------------------------------------------------------------------------- * VMUpdateAllNotesAge() *---------------------------------------------------------------------------- * Purpose: * Increment the note age for all of the active voices. * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * m_nAge for all voices is incremented *---------------------------------------------------------------------------- */ void VMUpdateAllNotesAge (S_VOICE_MGR *pVoiceMgr, EAS_U16 age) { EAS_INT i; for (i = 0; i < MAX_SYNTH_VOICES; i++) { if (age - pVoiceMgr->voices[i].age > 0) pVoiceMgr->voices[i].age++; } } /*---------------------------------------------------------------------------- * VMStolenVoice() *---------------------------------------------------------------------------- * Purpose: * The selected voice is being stolen. Sets the parameters so that the * voice will begin playing the new sound on the next buffer. * * Inputs: * pVoice - pointer to voice to steal * nChannel - the channel to start a note on * nKeyNumber - the key number to start a note for * nNoteVelocity - the key velocity from this note * * Outputs: * None *---------------------------------------------------------------------------- */ static void VMStolenVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 voiceNum, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity, EAS_U16 regionIndex) { S_SYNTH_VOICE *pVoice = &pVoiceMgr->voices[voiceNum]; /* one less voice in old pool */ DecVoicePoolCount(pVoiceMgr, pVoice); /* mute the sound that is currently playing */ GetSynthPtr(voiceNum)->pfMuteVoice(pVoiceMgr, pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)], &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum)); pVoice->voiceState = eVoiceStateStolen; /* set new note data */ pVoice->nextChannel = VSynthToChannel(pSynth, channel); pVoice->nextNote = note; pVoice->nextVelocity = velocity; pVoice->nextRegionIndex = regionIndex; /* one more voice in new pool */ IncVoicePoolCount(pVoiceMgr, pVoice); /* clear the deferred flags */ pVoice->voiceFlags &= ~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF | VOICE_FLAG_DEFER_MUTE | VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF); /* all notes older than this one get "younger" */ VMUpdateAllNotesAge(pVoiceMgr, pVoice->age); /* assign current age to this note and increment for the next note */ pVoice->age = pVoiceMgr->age++; } /*---------------------------------------------------------------------------- * VMFreeVoice() *---------------------------------------------------------------------------- * Purpose: * The selected voice is done playing and being returned to the * pool of free voices * * Inputs: * pVoice - pointer to voice to free * * Outputs: * None *---------------------------------------------------------------------------- */ static void VMFreeVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice) { /* do nothing if voice is already free */ if (pVoice->voiceState == eVoiceStateFree) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMFreeVoice: Attempt to free voice that is already free\n"); */ } return; } /* if we jump directly to free without passing muting stage, * we need to adjust the voice count */ DecVoicePoolCount(pVoiceMgr, pVoice); #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "VMFreeVoice: Synth=%d\n", pSynth->vSynthNum); */ } #endif /* return to free voice pool */ pVoiceMgr->activeVoices--; pSynth->numActiveVoices--; InitVoice(pVoice); #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMFreeVoice: free voice %d\n", pVoice - pVoiceMgr->voices); */ } #endif /* all notes older than this one get "younger" */ VMUpdateAllNotesAge(pVoiceMgr, pVoice->age); } /*---------------------------------------------------------------------------- * VMRetargetStolenVoice() *---------------------------------------------------------------------------- * Purpose: * The selected voice has been stolen and needs to be initalized with * the paramters of its new note. * * Inputs: * pVoice - pointer to voice to retarget * * Outputs: * None *---------------------------------------------------------------------------- */ static EAS_BOOL VMRetargetStolenVoice (S_VOICE_MGR *pVoiceMgr, EAS_I32 voiceNum) { EAS_U8 flags; S_SYNTH_CHANNEL *pMIDIChannel; S_SYNTH_VOICE *pVoice; S_SYNTH *pSynth; S_SYNTH *pNextSynth; /* establish some pointers */ pVoice = &pVoiceMgr->voices[voiceNum]; pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; pMIDIChannel = &pSynth->channels[pVoice->channel & 15]; pNextSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->nextChannel)]; #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMRetargetStolenVoice: retargeting stolen voice %d on channel %d\n", voiceNum, pVoice->channel); */ } { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\to channel %d note: %d velocity: %d\n", pVoice->nextChannel, pVoice->nextNote, pVoice->nextVelocity); */ } #endif /* make sure new channel hasn't been muted by SP-MIDI since the voice was stolen */ if ((pSynth->synthFlags & SYNTH_FLAG_SP_MIDI_ON) && (pMIDIChannel->channelFlags & CHANNEL_FLAG_MUTE)) { VMFreeVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum]); return EAS_FALSE; } /* if assigned to a new synth, correct the active voice count */ if (pVoice->channel != pVoice->nextChannel) { #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMRetargetStolenVoice: Note assigned to different virtual synth, adjusting numActiveVoices\n"); */ } #endif pSynth->numActiveVoices--; pNextSynth->numActiveVoices++; } /* assign new channel number, and increase channel voice count */ pVoice->channel = pVoice->nextChannel; pMIDIChannel = &pNextSynth->channels[pVoice->channel & 15]; /* assign other data */ pVoice->note = pVoice->nextNote; pVoice->velocity = pVoice->nextVelocity; pVoice->nextChannel = UNASSIGNED_SYNTH_CHANNEL; pVoice->regionIndex = pVoice->nextRegionIndex; /* save the flags, pfStartVoice() will clear them */ flags = pVoice->voiceFlags; /* keep track of the note-start related workload */ pVoiceMgr->workload += WORKLOAD_AMOUNT_START_NOTE; /* setup the voice parameters */ pVoice->voiceState = eVoiceStateStart; /*lint -e{522} return not used at this time */ GetSynthPtr(voiceNum)->pfStartVoice(pVoiceMgr, pNextSynth, &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum), pVoice->regionIndex); /* did the new note already receive a MIDI note-off request? */ if (flags & VOICE_FLAG_DEFER_MIDI_NOTE_OFF) { #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMRetargetVoice: stolen note note-off request deferred\n"); */ } #endif pVoice->voiceFlags |= VOICE_FLAG_DEFER_MIDI_NOTE_OFF; pNextSynth->synthFlags |= SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING; } return EAS_TRUE; } /*---------------------------------------------------------------------------- * VMCheckKeyGroup() *---------------------------------------------------------------------------- * If the note that we've been asked to start is in the same key group as * any currently playing notes, then we must shut down the currently playing * note in the same key group *---------------------------------------------------------------------------- */ void VMCheckKeyGroup (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U16 keyGroup, EAS_U8 channel) { const S_REGION *pRegion; EAS_INT voiceNum; /* increment frame workload */ pVoiceMgr->workload += WORKLOAD_AMOUNT_KEY_GROUP; /* need to check all voices in case this is a layered sound */ channel = VSynthToChannel(pSynth, channel); for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) { if (pVoiceMgr->voices[voiceNum].voiceState != eVoiceStateStolen) { /* voice must be on the same channel */ if (channel == pVoiceMgr->voices[voiceNum].channel) { /* check key group */ pRegion = GetRegionPtr(pSynth, pVoiceMgr->voices[voiceNum].regionIndex); if (keyGroup == (pRegion->keyGroupAndFlags & 0x0f00)) { #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMCheckKeyGroup: voice %d matches key group %d\n", voiceNum, keyGroup >> 8); */ } #endif /* if this voice was just started, set it to mute on the next buffer */ if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET) pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_DEFER_MUTE; /* mute immediately */ else VMMuteVoice(pVoiceMgr, voiceNum); } } } /* for stolen voice, check new values */ else { /* voice must be on the same channel */ if (channel == pVoiceMgr->voices[voiceNum].nextChannel) { /* check key group */ pRegion = GetRegionPtr(pSynth, pVoiceMgr->voices[voiceNum].nextRegionIndex); if (keyGroup == (pRegion->keyGroupAndFlags & 0x0f00)) { #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMCheckKeyGroup: voice %d matches key group %d\n", voiceNum, keyGroup >> 8); */ } #endif /* if this voice was just started, set it to mute on the next buffer */ if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET) pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_DEFER_MUTE; /* mute immediately */ else VMMuteVoice(pVoiceMgr, voiceNum); } } } } } /*---------------------------------------------------------------------------- * VMCheckPolyphonyLimiting() *---------------------------------------------------------------------------- * Purpose: * We only play at most 2 of the same note on a MIDI channel. * E.g., if we are asked to start note 36, and there are already two voices * that are playing note 36, then we must steal the voice playing * the oldest note 36 and use that stolen voice to play the new note 36. * * Inputs: * nChannel - synth channel that wants to start a new note * nKeyNumber - new note's midi note number * nNoteVelocity - new note's velocity * psEASData - pointer to overall EAS data structure * * Outputs: * pbVoiceStealingRequired - flag: this routine sets true if we needed to * steal a voice * * * Side Effects: * psSynthObject->m_sVoice[free voice num].m_nKeyNumber may be assigned * psSynthObject->m_sVoice[free voice num].m_nVelocity may be assigned *---------------------------------------------------------------------------- */ EAS_BOOL VMCheckPolyphonyLimiting (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity, EAS_U16 regionIndex, EAS_I32 lowVoice, EAS_I32 highVoice) { EAS_INT voiceNum; EAS_INT oldestVoiceNum; EAS_INT numVoicesPlayingNote; EAS_U16 age; EAS_U16 oldestNoteAge; pVoiceMgr->workload += WORKLOAD_AMOUNT_POLY_LIMIT; numVoicesPlayingNote = 0; oldestVoiceNum = MAX_SYNTH_VOICES; oldestNoteAge = 0; channel = VSynthToChannel(pSynth, channel); /* examine each voice on this channel playing this note */ for (voiceNum = lowVoice; voiceNum <= highVoice; voiceNum++) { /* check stolen notes separately */ if (pVoiceMgr->voices[voiceNum].voiceState != eVoiceStateStolen) { /* same channel and note ? */ if ((channel == pVoiceMgr->voices[voiceNum].channel) && (note == pVoiceMgr->voices[voiceNum].note)) { numVoicesPlayingNote++; age = pVoiceMgr->age - pVoiceMgr->voices[voiceNum].age; /* is this the oldest voice for this note? */ if (age >= oldestNoteAge) { oldestNoteAge = age; oldestVoiceNum = voiceNum; } } } /* handle stolen voices */ else { /* same channel and note ? */ if ((channel == pVoiceMgr->voices[voiceNum].nextChannel) && (note == pVoiceMgr->voices[voiceNum].nextNote)) { numVoicesPlayingNote++; } } } /* check to see if we exceeded poly limit */ if (numVoicesPlayingNote < DEFAULT_CHANNEL_POLYPHONY_LIMIT) return EAS_FALSE; /* make sure we have a voice to steal */ if (oldestVoiceNum != MAX_SYNTH_VOICES) { #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMCheckPolyphonyLimiting: voice %d has the oldest note\n", oldestVoiceNum); */ } { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "VMCheckPolyphonyLimiting: polyphony limiting requires shutting down note %d \n", pVoiceMgr->voices[oldestVoiceNum].note); */ } #endif VMStolenVoice(pVoiceMgr, pSynth, oldestVoiceNum, channel, note, velocity, regionIndex); return EAS_TRUE; } #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMCheckPolyphonyLimiting: No oldest voice to steal\n"); */ } #endif return EAS_FALSE; } /*---------------------------------------------------------------------------- * VMStartVoice() *---------------------------------------------------------------------------- * Starts a voice given a region index *---------------------------------------------------------------------------- */ void VMStartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity, EAS_U16 regionIndex) { const S_REGION *pRegion; S_SYNTH_CHANNEL *pChannel; EAS_INT voiceNum; EAS_INT maxSynthPoly; EAS_I32 lowVoice, highVoice; EAS_U16 keyGroup; pChannel = &pSynth->channels[channel]; pRegion = GetRegionPtr(pSynth, regionIndex); /* select correct synth */ #if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) { #ifdef EAS_SPLIT_WT_SYNTH if ((pRegion->keyGroupAndFlags & REGION_FLAG_OFF_CHIP) == 0) #else if ((regionIndex & FLAG_RGN_IDX_FM_SYNTH) == 0) #endif { lowVoice = 0; highVoice = NUM_PRIMARY_VOICES - 1; } else { lowVoice = NUM_PRIMARY_VOICES; highVoice = MAX_SYNTH_VOICES - 1; } } #else lowVoice = 0; highVoice = MAX_SYNTH_VOICES - 1; #endif /* keep track of the note-start related workload */ pVoiceMgr->workload+= WORKLOAD_AMOUNT_START_NOTE; /* other voices in pool, check for key group and poly limiting */ if (pSynth->poolCount[pChannel->pool] != 0) { /* check for key group exclusivity */ keyGroup = pRegion->keyGroupAndFlags & 0x0f00; if (keyGroup!= 0) VMCheckKeyGroup(pVoiceMgr, pSynth, keyGroup, channel); /* check polyphony limit and steal a voice if necessary */ if ((pRegion->keyGroupAndFlags & REGION_FLAG_NON_SELF_EXCLUSIVE) == 0) { if (VMCheckPolyphonyLimiting(pVoiceMgr, pSynth, channel, note, velocity, regionIndex, lowVoice, highVoice) == EAS_TRUE) return; } } /* check max poly allocation */ if ((pSynth->maxPolyphony == 0) || (pVoiceMgr->maxPolyphony < pSynth->maxPolyphony)) maxSynthPoly = pVoiceMgr->maxPolyphony; else maxSynthPoly = pSynth->maxPolyphony; /* any free voices? */ if ((pVoiceMgr->activeVoices < pVoiceMgr->maxPolyphony) && (pSynth->numActiveVoices < maxSynthPoly) && (EAS_SUCCESS == VMFindAvailableVoice(pVoiceMgr, &voiceNum, lowVoice, highVoice))) { S_SYNTH_VOICE *pVoice = &pVoiceMgr->voices[voiceNum]; #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "VMStartVoice: Synth=%d\n", pSynth->vSynthNum); */ } #endif /* bump voice counts */ pVoiceMgr->activeVoices++; pSynth->numActiveVoices++; #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStartVoice: voice %d assigned to channel %d note %d velocity %d\n", voiceNum, channel, note, velocity); */ } #endif /* save parameters */ pVoiceMgr->voices[voiceNum].channel = VSynthToChannel(pSynth, channel); pVoiceMgr->voices[voiceNum].note = note; pVoiceMgr->voices[voiceNum].velocity = velocity; /* establish note age for voice stealing */ pVoiceMgr->voices[voiceNum].age = pVoiceMgr->age++; /* setup the synthesis parameters */ pVoiceMgr->voices[voiceNum].voiceState = eVoiceStateStart; /* increment voice pool count */ IncVoicePoolCount(pVoiceMgr, pVoice); /* start voice on correct synth */ /*lint -e{522} return not used at this time */ GetSynthPtr(voiceNum)->pfStartVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum), regionIndex); return; } /* no free voices, we have to steal one using appropriate algorithm */ if (VMStealVoice(pVoiceMgr, pSynth, &voiceNum, channel, note, lowVoice, highVoice) == EAS_SUCCESS) VMStolenVoice(pVoiceMgr, pSynth, voiceNum, channel, note, velocity, regionIndex); #ifdef _DEBUG_VM else { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStartVoice: Could not steal a voice for channel %d note %d velocity %d\n", channel, note, velocity); */ } } #endif return; } /*---------------------------------------------------------------------------- * VMStartNote() *---------------------------------------------------------------------------- * Purpose: * Update the synth's state to play the requested note on the requested * channel if possible. * * Inputs: * nChannel - the channel to start a note on * nKeyNumber - the key number to start a note for * nNoteVelocity - the key velocity from this note * psEASData - pointer to overall EAS data structure * * Outputs: * Side Effects: * psSynthObject->m_nNumActiveVoices may be incremented * psSynthObject->m_sVoice[free voice num].m_nSynthChannel may be assigned * psSynthObject->m_sVoice[free voice num].m_nKeyNumber is assigned * psSynthObject->m_sVoice[free voice num].m_nVelocity is assigned *---------------------------------------------------------------------------- */ void VMStartNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity) { S_SYNTH_CHANNEL *pChannel; EAS_U16 regionIndex; EAS_I16 adjustedNote; /* bump note count */ pSynth->totalNoteCount++; pChannel = &pSynth->channels[channel]; /* check channel mute */ if (pChannel->channelFlags & CHANNEL_FLAG_MUTE) return; #ifdef EXTERNAL_AUDIO /* pass event to external audio when requested */ if ((pChannel->channelFlags & CHANNEL_FLAG_EXTERNAL_AUDIO) && (pSynth->cbEventFunc != NULL)) { S_EXT_AUDIO_EVENT event; event.channel = channel; event.note = note; event.velocity = velocity; event.noteOn = EAS_TRUE; if (pSynth->cbEventFunc(pSynth->pExtAudioInstData, &event)) return; } #endif /* start search at first region */ regionIndex = pChannel->regionIndex; /* handle transposition */ adjustedNote = note; if (pChannel->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) adjustedNote += pChannel->coarsePitch; else adjustedNote += pChannel->coarsePitch + pSynth->globalTranspose; /* limit adjusted key number so it does not wraparound, over/underflow */ if (adjustedNote < 0) { adjustedNote = 0; } else if (adjustedNote > 127) { adjustedNote = 127; } #if defined(DLS_SYNTHESIZER) if (regionIndex & FLAG_RGN_IDX_DLS_SYNTH) { /* DLS voice */ for (;;) { /*lint -e{740,826} cast OK, we know this is actually a DLS region */ const S_DLS_REGION *pDLSRegion = (S_DLS_REGION*) GetRegionPtr(pSynth, regionIndex); /* check key against this region's key and velocity range */ if (((adjustedNote >= pDLSRegion->wtRegion.region.rangeLow) && (adjustedNote <= pDLSRegion->wtRegion.region.rangeHigh)) && ((velocity >= pDLSRegion->velLow) && (velocity <= pDLSRegion->velHigh))) { VMStartVoice(pVoiceMgr, pSynth, channel, note, velocity, regionIndex); } /* last region in program? */ if (pDLSRegion->wtRegion.region.keyGroupAndFlags & REGION_FLAG_LAST_REGION) break; /* advance to next region */ regionIndex++; } } else #endif /* braces here for #if clause */ { /* EAS voice */ for (;;) { const S_REGION *pRegion = GetRegionPtr(pSynth, regionIndex); /* check key against this region's keyrange */ if ((adjustedNote >= pRegion->rangeLow) && (adjustedNote <= pRegion->rangeHigh)) { VMStartVoice(pVoiceMgr, pSynth, channel, note, velocity, regionIndex); break; } /* last region in program? */ if (pRegion->keyGroupAndFlags & REGION_FLAG_LAST_REGION) break; /* advance to next region */ regionIndex++; } } } /*---------------------------------------------------------------------------- * VMStopNote() *---------------------------------------------------------------------------- * Purpose: * Update the synth's state to end the requested note on the requested * channel. * * Inputs: * nChannel - the channel to stop a note on * nKeyNumber - the key number for this note off * nNoteVelocity - the note-off velocity * psEASData - pointer to overall EAS data structure * * Outputs: * Side Effects: * psSynthObject->m_sVoice[free voice num].m_nSynthChannel may be assigned * psSynthObject->m_sVoice[free voice num].m_nKeyNumber is assigned * psSynthObject->m_sVoice[free voice num].m_nVelocity is assigned *---------------------------------------------------------------------------- */ /*lint -esym(715, velocity) reserved for future use */ void VMStopNote (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 note, EAS_U8 velocity) { S_SYNTH_CHANNEL *pChannel; EAS_INT voiceNum; pChannel = &(pSynth->channels[channel]); #ifdef EXTERNAL_AUDIO if ((pChannel->channelFlags & CHANNEL_FLAG_EXTERNAL_AUDIO) && (pSynth->cbEventFunc != NULL)) { S_EXT_AUDIO_EVENT event; event.channel = channel; event.note = note; event.velocity = velocity; event.noteOn = EAS_FALSE; if (pSynth->cbEventFunc(pSynth->pExtAudioInstData, &event)) return; } #endif /* keep track of the note-start workload */ pVoiceMgr->workload += WORKLOAD_AMOUNT_STOP_NOTE; channel = VSynthToChannel(pSynth, channel); for (voiceNum=0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) { /* stolen notes are handled separately */ if (eVoiceStateStolen != pVoiceMgr->voices[voiceNum].voiceState) { /* channel and key number must match */ if ((channel == pVoiceMgr->voices[voiceNum].channel) && (note == pVoiceMgr->voices[voiceNum].note)) { #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStopNote: voice %d channel %d note %d\n", voiceNum, channel, note); */ } #endif /* if sustain pedal is down, set deferred note-off flag */ if (pChannel->channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) { pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; continue; } /* if this note just started, wait before we stop it */ if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET) { #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tDeferred: Not started yet\n"); */ } #endif pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_DEFER_MIDI_NOTE_OFF; pSynth->synthFlags |= SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING; } /* release voice */ else VMReleaseVoice(pVoiceMgr, pSynth, voiceNum); } } /* process stolen notes, new channel and key number must match */ else if ((channel == pVoiceMgr->voices[voiceNum].nextChannel) && (note == pVoiceMgr->voices[voiceNum].nextNote)) { #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStopNote: voice %d channel %d note %d\n\tDeferred: Stolen voice\n", voiceNum, channel, note); */ } #endif pVoiceMgr->voices[voiceNum].voiceFlags |= VOICE_FLAG_DEFER_MIDI_NOTE_OFF; } } } /*---------------------------------------------------------------------------- * VMFindAvailableVoice() *---------------------------------------------------------------------------- * Purpose: * Find an available voice and return the voice number if available. * * Inputs: * pnVoiceNumber - really an output, returns the voice number found * psEASData - pointer to overall EAS data structure * * Outputs: * success - if there is an available voice * failure - otherwise *---------------------------------------------------------------------------- */ EAS_RESULT VMFindAvailableVoice (S_VOICE_MGR *pVoiceMgr, EAS_INT *pVoiceNumber, EAS_I32 lowVoice, EAS_I32 highVoice) { EAS_INT voiceNum; /* Check each voice to see if it has been assigned to a synth channel */ for (voiceNum = lowVoice; voiceNum <= highVoice; voiceNum++) { /* check if this voice has been assigned to a synth channel */ if ( pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateFree) { *pVoiceNumber = voiceNum; /* this voice is available */ return EAS_SUCCESS; } } /* if we reach here, we have not found a free voice */ *pVoiceNumber = UNASSIGNED_SYNTH_VOICE; #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMFindAvailableVoice: error, could not find an available voice\n"); */ } #endif return EAS_FAILURE; } /*---------------------------------------------------------------------------- * VMStealVoice() *---------------------------------------------------------------------------- * Purpose: * Steal a voice and return the voice number * * Stealing algorithm: steal the best choice with minimal work, taking into * account SP-Midi channel priorities and polyphony allocation. * * In one pass through all the voices, figure out which voice to steal * taking into account a number of different factors: * Priority of the voice's MIDI channel * Number of voices over the polyphony allocation for voice's MIDI channel * Amplitude of the voice * Note age * Key velocity (for voices that haven't been started yet) * If any matching notes are found * * Inputs: * pnVoiceNumber - really an output, see below * nChannel - the channel that this voice wants to be started on * nKeyNumber - the key number for this new voice * psEASData - pointer to overall EAS data structure * * Outputs: * pnVoiceNumber - voice number of the voice that was stolen * EAS_RESULT EAS_SUCCESS - always successful *---------------------------------------------------------------------------- */ EAS_RESULT VMStealVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_INT *pVoiceNumber, EAS_U8 channel, EAS_U8 note, EAS_I32 lowVoice, EAS_I32 highVoice) { S_SYNTH_VOICE *pCurrVoice; S_SYNTH *pCurrSynth; EAS_INT voiceNum; EAS_INT bestCandidate; EAS_U8 currChannel; EAS_U8 currNote; EAS_I32 bestPriority; EAS_I32 currentPriority; /* determine which voice to steal */ bestPriority = 0; bestCandidate = MAX_SYNTH_VOICES; for (voiceNum = lowVoice; voiceNum <= highVoice; voiceNum++) { pCurrVoice = &pVoiceMgr->voices[voiceNum]; /* ignore free voices */ if (pCurrVoice->voiceState == eVoiceStateFree) continue; /* for stolen voices, use the new parameters, not the old */ if (pCurrVoice->voiceState == eVoiceStateStolen) { pCurrSynth = pVoiceMgr->pSynth[GET_VSYNTH(pCurrVoice->nextChannel)]; currChannel = pCurrVoice->nextChannel; currNote = pCurrVoice->nextNote; } else { pCurrSynth = pVoiceMgr->pSynth[GET_VSYNTH(pCurrVoice->channel)]; currChannel = pCurrVoice->channel; currNote = pCurrVoice->note; } /* ignore voices that are higher priority */ if (pSynth->priority > pCurrSynth->priority) continue; #ifdef _DEBUG_VM // { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStealVoice: New priority = %d exceeds old priority = %d\n", pSynth->priority, pCurrSynth->priority); */ } #endif /* if voice is stolen or just started, reduce the likelihood it will be stolen */ if (( pCurrVoice->voiceState == eVoiceStateStolen) || (pCurrVoice->voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET)) { currentPriority = 128 - pCurrVoice->nextVelocity; } else { /* compute the priority of this voice, higher means better for stealing */ /* use not age */ currentPriority = (EAS_I32) pCurrVoice->age << NOTE_AGE_STEAL_WEIGHT; /* include note gain -higher gain is lower steal value */ /*lint -e{704} use shift for performance */ currentPriority += ((32768 >> (12 - NOTE_GAIN_STEAL_WEIGHT)) + 256) - ((EAS_I32) pCurrVoice->gain >> (12 - NOTE_GAIN_STEAL_WEIGHT)); } /* in SP-MIDI mode, include over poly allocation and channel priority */ if (pSynth->synthFlags & SYNTH_FLAG_SP_MIDI_ON) { S_SYNTH_CHANNEL *pChannel = &pCurrSynth->channels[GET_CHANNEL(currChannel)]; /*lint -e{701} use shift for performance */ if (pSynth->poolCount[pChannel->pool] >= pSynth->poolAlloc[pChannel->pool]) currentPriority += (pSynth->poolCount[pChannel->pool] -pSynth->poolAlloc[pChannel->pool] + 1) << CHANNEL_POLY_STEAL_WEIGHT; /* include channel priority */ currentPriority += (EAS_I32)(pChannel->pool << CHANNEL_PRIORITY_STEAL_WEIGHT); } /* if a note is already playing that matches this note, consider stealing it more readily */ if ((note == currNote) && (channel == currChannel)) currentPriority += NOTE_MATCH_PENALTY; /* is this the best choice so far? */ if (currentPriority >= bestPriority) { bestPriority = currentPriority; bestCandidate = voiceNum; } } /* may happen if all voices are allocated to a higher priority virtual synth */ if (bestCandidate == MAX_SYNTH_VOICES) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStealVoice: Unable to allocate a voice\n"); */ } return EAS_ERROR_NO_VOICE_ALLOCATED; } #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMStealVoice: Voice %d stolen\n", bestCandidate); */ } /* are we stealing a stolen voice? */ if (pVoiceMgr->voices[bestCandidate].voiceState == eVoiceStateStolen) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMStealVoice: Voice %d is already marked as stolen and was scheduled to play ch: %d note: %d vel: %d\n", bestCandidate, pVoiceMgr->voices[bestCandidate].nextChannel, pVoiceMgr->voices[bestCandidate].nextNote, pVoiceMgr->voices[bestCandidate].nextVelocity); */ } } #endif *pVoiceNumber = (EAS_U16) bestCandidate; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * VMChannelPressure() *---------------------------------------------------------------------------- * Purpose: * Change the channel pressure for the given channel * * Inputs: * nChannel - the MIDI channel * nVelocity - the channel pressure value * psEASData - pointer to overall EAS data structure * * Outputs: * Side Effects: * psSynthObject->m_sChannel[nChannel].m_nChannelPressure is updated *---------------------------------------------------------------------------- */ void VMChannelPressure (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 value) { S_SYNTH_CHANNEL *pChannel; pChannel = &(pSynth->channels[channel]); pChannel->channelPressure = value; /* set a channel flag to request parameter updates for all the voices associated with this channel */ pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; } /*---------------------------------------------------------------------------- * VMPitchBend() *---------------------------------------------------------------------------- * Purpose: * Change the pitch wheel value for the given channel. * This routine constructs the proper 14-bit argument when the calling routine * passes the pitch LSB and MSB. * * Note: some midi disassemblers display a bipolar pitch bend value. * We can display the bipolar value using * if m_nPitchBend >= 0x2000 * bipolar pitch bend = postive (m_nPitchBend - 0x2000) * else * bipolar pitch bend = negative (0x2000 - m_nPitchBend) * * Inputs: * nChannel - the MIDI channel * nPitchLSB - the LSB byte of the pitch bend message * nPitchMSB - the MSB byte of the pitch bend message * psEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * psSynthObject->m_sChannel[nChannel].m_nPitchBend is changed * *---------------------------------------------------------------------------- */ void VMPitchBend (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 nPitchLSB, EAS_U8 nPitchMSB) { S_SYNTH_CHANNEL *pChannel; pChannel = &(pSynth->channels[channel]); pChannel->pitchBend = (EAS_I16) ((nPitchMSB << 7) | nPitchLSB); /* set a channel flag to request parameter updates for all the voices associated with this channel */ pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; } /*---------------------------------------------------------------------------- * VMControlChange() *---------------------------------------------------------------------------- * Purpose: * Change the controller (or mode) for the given channel. * * Inputs: * nChannel - the MIDI channel * nControllerNumber - the MIDI controller number * nControlValue - the value for this controller message * psEASData - pointer to overall EAS data structure * * Outputs: * Side Effects: * psSynthObject->m_sChannel[nChannel] controller is changed * *---------------------------------------------------------------------------- */ void VMControlChange (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 controller, EAS_U8 value) { S_SYNTH_CHANNEL *pChannel; pChannel = &(pSynth->channels[channel]); /* set a channel flag to request parameter updates for all the voices associated with this channel */ pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; switch ( controller ) { case MIDI_CONTROLLER_BANK_SELECT_MSB: #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMControlChange: Bank Select MSB: msb 0x%X\n", value); */ } #endif /* use this MSB with a zero LSB, until we get an LSB message */ pChannel->bankNum = value << 8; break; case MIDI_CONTROLLER_MOD_WHEEL: /* we treat mod wheel as a 7-bit controller and only use the MSB */ pChannel->modWheel = value; break; case MIDI_CONTROLLER_VOLUME: /* we treat volume as a 7-bit controller and only use the MSB */ pChannel->volume = value; break; case MIDI_CONTROLLER_PAN: /* we treat pan as a 7-bit controller and only use the MSB */ pChannel->pan = value; break; case MIDI_CONTROLLER_EXPRESSION: /* we treat expression as a 7-bit controller and only use the MSB */ pChannel->expression = value; break; case MIDI_CONTROLLER_BANK_SELECT_LSB: #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMControlChange: Bank Select LSB: lsb 0x%X\n", value); */ } #endif /* construct bank number as 7-bits (stored as 8) of existing MSB and 7-bits of new LSB (also stored as 8( */ pChannel->bankNum = (pChannel->bankNum & 0xFF00) | value; break; case MIDI_CONTROLLER_SUSTAIN_PEDAL: /* we treat sustain pedal as a boolean on/off bit flag */ if (value < 64) { /* we are requested to turn the pedal off, but first check if the pedal is already on */ if (0 != (pChannel->channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) ) { /* The sustain flag is presently set and the damper pedal is on. We are therefore transitioning from damper pedal ON to damper pedal OFF. This means all notes in this channel that received a note off while the damper pedal was on, and had their note-off requests deferred, should now proceed to the release state. */ VMReleaseAllDeferredNoteOffs(pVoiceMgr, pSynth, channel); } /* end if sustain pedal is already on */ /* turn the sustain pedal off */ pChannel->channelFlags &= ~CHANNEL_FLAG_SUSTAIN_PEDAL; } else { /* we are requested to turn the pedal on, but first check if the pedal is already off */ if (0 == (pChannel->channelFlags & CHANNEL_FLAG_SUSTAIN_PEDAL) ) { /* The sustain flag is presently clear and the damper pedal is off. We are therefore transitioning from damper pedal OFF to damper pedal ON. Currently sounding notes should be left unchanged. However, we should try to "catch" notes if possible. If any notes have levels >= sustain level, catch them, otherwise, let them continue to release. */ VMCatchNotesForSustainPedal(pVoiceMgr, pSynth, channel); } /* turn the sustain pedal on */ pChannel->channelFlags |= CHANNEL_FLAG_SUSTAIN_PEDAL; } break; #ifdef _REVERB case MIDI_CONTROLLER_REVERB_SEND: /* we treat send as a 7-bit controller and only use the MSB */ pSynth->channels[channel].reverbSend = value; break; #endif #ifdef _CHORUS case MIDI_CONTROLLER_CHORUS_SEND: /* we treat send as a 7-bit controller and only use the MSB */ pSynth->channels[channel].chorusSend = value; break; #endif case MIDI_CONTROLLER_RESET_CONTROLLERS: /* despite the Midi message name, not ALL controllers are reset */ pChannel->modWheel = DEFAULT_MOD_WHEEL; pChannel->expression = DEFAULT_EXPRESSION; /* turn the sustain pedal off as default/reset */ pChannel->channelFlags &= ~CHANNEL_FLAG_SUSTAIN_PEDAL; pChannel->pitchBend = DEFAULT_PITCH_BEND; /* reset channel pressure */ pChannel->channelPressure = DEFAULT_CHANNEL_PRESSURE; /* reset RPN values */ pChannel->registeredParam = DEFAULT_REGISTERED_PARAM; pChannel->pitchBendSensitivity = DEFAULT_PITCH_BEND_SENSITIVITY; pChannel->finePitch = DEFAULT_FINE_PITCH; pChannel->coarsePitch = DEFAULT_COARSE_PITCH; /* program change, bank select, channel volume CC7, pan CC10 are NOT reset */ break; /* For logical reasons, the RPN data entry are grouped together. However, keep in mind that these cases are not necessarily in ascending order. e.g., MIDI_CONTROLLER_DATA_ENTRY_MSB == 6, whereas MIDI_CONTROLLER_SUSTAIN_PEDAL == 64. So arrange these case statements in whatever manner is more efficient for the processor / compiler. */ case MIDI_CONTROLLER_ENTER_DATA_MSB: case MIDI_CONTROLLER_ENTER_DATA_LSB: case MIDI_CONTROLLER_SELECT_RPN_LSB: case MIDI_CONTROLLER_SELECT_RPN_MSB: case MIDI_CONTROLLER_SELECT_NRPN_MSB: case MIDI_CONTROLLER_SELECT_NRPN_LSB: VMUpdateRPNStateMachine(pSynth, channel, controller, value); break; case MIDI_CONTROLLER_ALL_SOUND_OFF: case MIDI_CONTROLLER_ALL_NOTES_OFF: case MIDI_CONTROLLER_OMNI_OFF: case MIDI_CONTROLLER_OMNI_ON: case MIDI_CONTROLLER_MONO_ON_POLY_OFF: case MIDI_CONTROLLER_POLY_ON_MONO_OFF: /* NOTE: we treat all sounds off the same as all notes off */ VMAllNotesOff(pVoiceMgr, pSynth, channel); break; default: #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMControlChange: controller %d not yet implemented\n", controller); */ } #endif break; } return; } /*---------------------------------------------------------------------------- * VMUpdateRPNStateMachine() *---------------------------------------------------------------------------- * Purpose: * Call this function when we want to parse RPN related controller messages. * We only support RPN0 (pitch bend sensitivity), RPN1 (fine tuning) and * RPN2 (coarse tuning). Any other RPNs or NRPNs are ignored for now. *. * Supports any order, so not a state machine anymore. This function was * rewritten to work correctly regardless of order. * * Inputs: * nChannel - the channel this controller message is coming from * nControllerNumber - which RPN related controller * nControlValue - the value of the RPN related controller * psEASData - pointer to overall EAS data structure * * Outputs: * returns EAS_RESULT, which is typically EAS_SUCCESS, since there are * few possible errors * * Side Effects: * gsSynthObject.m_sChannel[nChannel].m_nPitchBendSensitivity * (or m_nFinePitch or m_nCoarsePitch) * will be updated if the proper RPN message is received. *---------------------------------------------------------------------------- */ EAS_RESULT VMUpdateRPNStateMachine (S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 controller, EAS_U8 value) { S_SYNTH_CHANNEL *pChannel; #ifdef _DEBUG_VM if (channel >= NUM_SYNTH_CHANNELS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMUpdateRPNStateMachines: error, %d invalid channel number\n", channel); */ } return EAS_FAILURE; } #endif pChannel = &(pSynth->channels[channel]); switch (controller) { case MIDI_CONTROLLER_SELECT_NRPN_MSB: case MIDI_CONTROLLER_SELECT_NRPN_LSB: pChannel->registeredParam = DEFAULT_REGISTERED_PARAM; break; case MIDI_CONTROLLER_SELECT_RPN_MSB: pChannel->registeredParam = (pChannel->registeredParam & 0x7F) | (value<<7); break; case MIDI_CONTROLLER_SELECT_RPN_LSB: pChannel->registeredParam = (pChannel->registeredParam & 0x7F00) | value; break; case MIDI_CONTROLLER_ENTER_DATA_MSB: switch (pChannel->registeredParam) { case 0: pChannel->pitchBendSensitivity = value * 100; break; case 1: /*lint -e{702} */ pChannel->finePitch = (EAS_I8)((((value << 7) - 8192) * 100) >> 13); break; case 2: pChannel->coarsePitch = (EAS_I8)(value - 64); break; default: break; } break; case MIDI_CONTROLLER_ENTER_DATA_LSB: switch (pChannel->registeredParam) { case 0: //ignore lsb break; case 1: //ignore lsb break; case 2: //ignore lsb break; default: break; } break; default: return EAS_FAILURE; //not a RPN related controller } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * VMUpdateStaticChannelParameters() *---------------------------------------------------------------------------- * Purpose: * Update all of the static channel parameters for channels that have had * a controller change values * Or if the synth has signalled that all channels must forcibly * be updated * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * none * * Side Effects: * - psSynthObject->m_sChannel[].m_nStaticGain and m_nStaticPitch * are updated for channels whose controller values have changed * or if the synth has signalled that all channels must forcibly * be updated *---------------------------------------------------------------------------- */ void VMUpdateStaticChannelParameters (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth) { EAS_INT channel; if (pSynth->synthFlags & SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS) { /* the synth wants us to forcibly update all channel parameters. This event occurs when we are about to finish resetting the synth */ for (channel = 0; channel < NUM_SYNTH_CHANNELS; channel++) { #ifdef _HYBRID_SYNTH if (pSynth->channels[channel].regionIndex & FLAG_RGN_IDX_FM_SYNTH) pSecondarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); else pPrimarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); #else pPrimarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); #endif } /* clear the flag to indicates we have now forcibly updated all channel parameters */ pSynth->synthFlags &= ~SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS; } else { /* only update channel params if signalled by a channel flag */ for (channel = 0; channel < NUM_SYNTH_CHANNELS; channel++) { if ( 0 != (pSynth->channels[channel].channelFlags & CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS)) { #ifdef _HYBRID_SYNTH if (pSynth->channels[channel].regionIndex & FLAG_RGN_IDX_FM_SYNTH) pSecondarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); else pPrimarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); #else pPrimarySynth->pfUpdateChannel(pVoiceMgr, pSynth, (EAS_U8) channel); #endif } } } return; } /*---------------------------------------------------------------------------- * VMFindProgram() *---------------------------------------------------------------------------- * Purpose: * Look up an individual program in sound library. This function * searches the bank list for a program, then the individual program * list. * * Inputs: * * Outputs: *---------------------------------------------------------------------------- */ static EAS_RESULT VMFindProgram (const S_EAS *pEAS, EAS_U32 bank, EAS_U8 programNum, EAS_U16 *pRegionIndex) { EAS_U32 locale; const S_PROGRAM *p; EAS_U16 i; EAS_U16 regionIndex; /* make sure we have a valid sound library */ if (pEAS == NULL) return EAS_FAILURE; /* search the banks */ for (i = 0; i < pEAS->numBanks; i++) { if (bank == (EAS_U32) pEAS->pBanks[i].locale) { regionIndex = pEAS->pBanks[i].regionIndex[programNum]; if (regionIndex != INVALID_REGION_INDEX) { *pRegionIndex = regionIndex; return EAS_SUCCESS; } break; } } /* establish locale */ locale = ( bank << 8) | programNum; /* search for program */ for (i = 0, p = pEAS->pPrograms; i < pEAS->numPrograms; i++, p++) { if (p->locale == locale) { *pRegionIndex = p->regionIndex; return EAS_SUCCESS; } } return EAS_FAILURE; } #ifdef DLS_SYNTHESIZER /*---------------------------------------------------------------------------- * VMFindDLSProgram() *---------------------------------------------------------------------------- * Purpose: * Look up an individual program in sound library. This function * searches the bank list for a program, then the individual program * list. * * Inputs: * * Outputs: *---------------------------------------------------------------------------- */ static EAS_RESULT VMFindDLSProgram (const S_DLS *pDLS, EAS_U32 bank, EAS_U8 programNum, EAS_U16 *pRegionIndex) { EAS_U32 locale; const S_PROGRAM *p; EAS_U16 i; /* make sure we have a valid sound library */ if (pDLS == NULL) return EAS_FAILURE; /* establish locale */ locale = (bank << 8) | programNum; /* search for program */ for (i = 0, p = pDLS->pDLSPrograms; i < pDLS->numDLSPrograms; i++, p++) { if (p->locale == locale) { *pRegionIndex = p->regionIndex; return EAS_SUCCESS; } } return EAS_FAILURE; } #endif /*---------------------------------------------------------------------------- * VMProgramChange() *---------------------------------------------------------------------------- * Purpose: * Change the instrument (program) for the given channel. * * Depending on the program number, and the bank selected for this channel, the * program may be in ROM, RAM (from SMAF or CMX related RAM wavetable), or * Alternate wavetable (from mobile DLS or other DLS file) * * This function figures out what wavetable should be used, and sets it up as the * wavetable to use for this channel. Also the channel may switch from a melodic * channel to a rhythm channel, or vice versa. * * Inputs: * * Outputs: * Side Effects: * gsSynthObject.m_sChannel[nChannel].m_nProgramNumber is likely changed * gsSynthObject.m_sChannel[nChannel].m_psEAS may be changed * gsSynthObject.m_sChannel[nChannel].m_bRhythmChannel may be changed * *---------------------------------------------------------------------------- */ /*lint -esym(715, pVoiceMgr) reserved for future use */ void VMProgramChange (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel, EAS_U8 program) { S_SYNTH_CHANNEL *pChannel; EAS_U32 bank; EAS_U16 regionIndex; #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "VMProgramChange: vSynthNum=%d, channel=%d, program=%d\n", pSynth->vSynthNum, channel, program); */ } #endif /* setup pointer to MIDI channel data */ pChannel = &pSynth->channels[channel]; bank = pChannel->bankNum; /* allow channels to switch between being melodic or rhythm channels, using GM2 CC values */ if ((bank & 0xFF00) == DEFAULT_RHYTHM_BANK_NUMBER) { /* make it a rhythm channel */ pChannel->channelFlags |= CHANNEL_FLAG_RHYTHM_CHANNEL; } else if ((bank & 0xFF00) == DEFAULT_MELODY_BANK_NUMBER) { /* make it a melody channel */ pChannel->channelFlags &= ~CHANNEL_FLAG_RHYTHM_CHANNEL; } regionIndex = DEFAULT_REGION_INDEX; #ifdef EXTERNAL_AUDIO /* give the external audio interface a chance to handle it */ if (pSynth->cbProgChgFunc != NULL) { S_EXT_AUDIO_PRG_CHG prgChg; prgChg.channel = channel; prgChg.bank = (EAS_U16) bank; prgChg.program = program; if (pSynth->cbProgChgFunc(pSynth->pExtAudioInstData, &prgChg)) pChannel->channelFlags |= CHANNEL_FLAG_EXTERNAL_AUDIO; } #endif #ifdef DLS_SYNTHESIZER /* first check for DLS program that may overlay the internal instrument */ if (VMFindDLSProgram(pSynth->pDLS, bank, program, ®ionIndex) != EAS_SUCCESS) #endif /* braces to support 'if' clause above */ { /* look in the internal banks */ if (VMFindProgram(pSynth->pEAS, bank, program, ®ionIndex) != EAS_SUCCESS) /* fall back to default bank */ { if (pSynth->channels[channel].channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) bank = DEFAULT_RHYTHM_BANK_NUMBER; else bank = DEFAULT_MELODY_BANK_NUMBER; if (VMFindProgram(pSynth->pEAS, bank, program, ®ionIndex) != EAS_SUCCESS) /* switch to program 0 in the default bank */ { if (VMFindProgram(pSynth->pEAS, bank, 0, ®ionIndex) != EAS_SUCCESS) { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMProgramChange: No program @ %03d:%03d:%03d\n", (bank >> 8) & 0x7f, bank & 0x7f, program); */ } } } } /* we have our new program change for this channel */ pChannel->programNum = program; pChannel->regionIndex = regionIndex; /* set a channel flag to request parameter updates for all the voices associated with this channel */ pChannel->channelFlags |= CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; return; } /*---------------------------------------------------------------------------- * VMAddSamples() *---------------------------------------------------------------------------- * Purpose: * Synthesize the requested number of samples (block based processing) * * Inputs: * nNumSamplesToAdd - number of samples to write to buffer * psEASData - pointer to overall EAS data structure * * Outputs: * number of voices rendered * * Side Effects: * - samples are added to the presently free buffer * *---------------------------------------------------------------------------- */ EAS_I32 VMAddSamples (S_VOICE_MGR *pVoiceMgr, EAS_I32 *pMixBuffer, EAS_I32 numSamples) { S_SYNTH *pSynth; EAS_INT voicesRendered; EAS_INT voiceNum; EAS_BOOL done; #ifdef _REVERB EAS_PCM *pReverbSendBuffer; #endif // ifdef _REVERB #ifdef _CHORUS EAS_PCM *pChorusSendBuffer; #endif // ifdef _CHORUS voicesRendered = 0; for (voiceNum = 0; voiceNum < MAX_SYNTH_VOICES; voiceNum++) { /* retarget stolen voices */ if ((pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateStolen) && (pVoiceMgr->voices[voiceNum].gain <= 0)) VMRetargetStolenVoice(pVoiceMgr, voiceNum); /* get pointer to virtual synth */ pSynth = pVoiceMgr->pSynth[pVoiceMgr->voices[voiceNum].channel >> 4]; /* synthesize active voices */ if (pVoiceMgr->voices[voiceNum].voiceState != eVoiceStateFree) { done = GetSynthPtr(voiceNum)->pfUpdateVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum], GetAdjustedVoiceNum(voiceNum), pMixBuffer, numSamples); voicesRendered++; /* voice is finished */ if (done == EAS_TRUE) { /* set gain of stolen voice to zero so it will be restarted */ if (pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateStolen) pVoiceMgr->voices[voiceNum].gain = 0; /* or return it to the free voice pool */ else VMFreeVoice(pVoiceMgr, pSynth, &pVoiceMgr->voices[voiceNum]); } /* if this voice is scheduled to be muted, set the mute flag */ if (pVoiceMgr->voices[voiceNum].voiceFlags & VOICE_FLAG_DEFER_MUTE) { pVoiceMgr->voices[voiceNum].voiceFlags &= ~(VOICE_FLAG_DEFER_MUTE | VOICE_FLAG_DEFER_MIDI_NOTE_OFF); VMMuteVoice(pVoiceMgr, voiceNum); } /* if voice just started, advance state to play */ if (pVoiceMgr->voices[voiceNum].voiceState == eVoiceStateStart) pVoiceMgr->voices[voiceNum].voiceState = eVoiceStatePlay; } } return voicesRendered; } /*---------------------------------------------------------------------------- * VMRender() *---------------------------------------------------------------------------- * Purpose: * This routine renders a frame of audio * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * pVoicesRendered - number of voices rendered this frame * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT VMRender (S_VOICE_MGR *pVoiceMgr, EAS_I32 numSamples, EAS_I32 *pMixBuffer, EAS_I32 *pVoicesRendered) { S_SYNTH *pSynth; EAS_INT i; EAS_INT channel; #ifdef _CHECKED_BUILD SanityCheck(pVoiceMgr); #endif /* update MIDI channel parameters */ *pVoicesRendered = 0; for (i = 0; i < MAX_VIRTUAL_SYNTHESIZERS; i++) { if (pVoiceMgr->pSynth[i] != NULL) VMUpdateStaticChannelParameters(pVoiceMgr, pVoiceMgr->pSynth[i]); } /* synthesize a buffer of audio */ *pVoicesRendered = VMAddSamples(pVoiceMgr, pMixBuffer, numSamples); /* * check for deferred note-off messages * If flag is set, that means one or more voices are expecting deferred * midi note-off messages because the midi note-on and corresponding midi * note-off requests occurred during the same update interval. The goal * is the defer the note-off request so that the note can at least start. */ for (i = 0; i < MAX_VIRTUAL_SYNTHESIZERS; i++) { pSynth = pVoiceMgr->pSynth[i]; if (pSynth== NULL) continue; if (pSynth->synthFlags & SYNTH_FLAG_DEFERRED_MIDI_NOTE_OFF_PENDING) VMDeferredStopNote(pVoiceMgr, pSynth); /* check if we need to reset the synth */ if ((pSynth->synthFlags & SYNTH_FLAG_RESET_IS_REQUESTED) && (pSynth->numActiveVoices == 0)) { /* complete the process of resetting the synth now that all voices have muted */ #ifdef _DEBUG_VM { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "VMAddSamples: complete the reset process\n"); */ } #endif VMInitializeAllChannels(pVoiceMgr, pSynth); VMInitializeAllVoices(pVoiceMgr, pSynth->vSynthNum); /* clear the reset flag */ pSynth->synthFlags &= ~SYNTH_FLAG_RESET_IS_REQUESTED; } /* clear channel update flags */ for (channel = 0; channel < NUM_SYNTH_CHANNELS; channel++) pSynth->channels[channel].channelFlags &= ~CHANNEL_FLAG_UPDATE_CHANNEL_PARAMETERS; } #ifdef _CHECKED_BUILD SanityCheck(pVoiceMgr); #endif return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * VMInitWorkload() *---------------------------------------------------------------------------- * Purpose: * Clears the workload counter * * Inputs: * pVoiceMgr - pointer to instance data * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ void VMInitWorkload (S_VOICE_MGR *pVoiceMgr) { pVoiceMgr->workload = 0; } /*---------------------------------------------------------------------------- * VMSetWorkload() *---------------------------------------------------------------------------- * Purpose: * Sets the max workload for a single frame. * * Inputs: * pVoiceMgr - pointer to instance data * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ void VMSetWorkload (S_VOICE_MGR *pVoiceMgr, EAS_I32 maxWorkLoad) { pVoiceMgr->maxWorkLoad = maxWorkLoad; } /*---------------------------------------------------------------------------- * VMCheckWorkload() *---------------------------------------------------------------------------- * Purpose: * Checks to see if work load has been exceeded on this frame. * * Inputs: * pVoiceMgr - pointer to instance data * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_BOOL VMCheckWorkload (S_VOICE_MGR *pVoiceMgr) { if (pVoiceMgr->maxWorkLoad > 0) return (EAS_BOOL) (pVoiceMgr->workload >= pVoiceMgr->maxWorkLoad); return EAS_FALSE; } /*---------------------------------------------------------------------------- * VMActiveVoices() *---------------------------------------------------------------------------- * Purpose: * Returns the number of active voices in the synthesizer. * * Inputs: * pEASData - pointer to instance data * * Outputs: * Returns the number of active voices * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_I32 VMActiveVoices (S_SYNTH *pSynth) { return pSynth->numActiveVoices; } /*---------------------------------------------------------------------------- * VMSetSynthPolyphony() *---------------------------------------------------------------------------- * Purpose: * Set the synth to a new polyphony value. Value must be >= 1 and * <= MAX_SYNTH_VOICES. This function will pin the polyphony at those limits * * Inputs: * pVoiceMgr pointer to synthesizer data * polyphonyCount desired polyphony count * synth synthesizer number (0 = onboard, 1 = DSP) * * Outputs: * Returns error code * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT VMSetSynthPolyphony (S_VOICE_MGR *pVoiceMgr, EAS_I32 synth, EAS_I32 polyphonyCount) { EAS_INT i; EAS_INT activeVoices; /* lower limit */ if (polyphonyCount < 1) polyphonyCount = 1; /* split architecture */ #if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) if (synth == EAS_MCU_SYNTH) { if (polyphonyCount > NUM_PRIMARY_VOICES) polyphonyCount = NUM_PRIMARY_VOICES; if (pVoiceMgr->maxPolyphonyPrimary == polyphonyCount) return EAS_SUCCESS; pVoiceMgr->maxPolyphonyPrimary = (EAS_U16) polyphonyCount; } else if (synth == EAS_DSP_SYNTH) { if (polyphonyCount > NUM_SECONDARY_VOICES) polyphonyCount = NUM_SECONDARY_VOICES; if (pVoiceMgr->maxPolyphonySecondary == polyphonyCount) return EAS_SUCCESS; pVoiceMgr->maxPolyphonySecondary = (EAS_U16) polyphonyCount; } else return EAS_ERROR_PARAMETER_RANGE; /* setting for SP-MIDI */ pVoiceMgr->maxPolyphony = pVoiceMgr->maxPolyphonyPrimary + pVoiceMgr->maxPolyphonySecondary; /* standard architecture */ #else if (synth != EAS_MCU_SYNTH) return EAS_ERROR_PARAMETER_RANGE; /* pin desired value to possible limits */ if (polyphonyCount > MAX_SYNTH_VOICES) polyphonyCount = MAX_SYNTH_VOICES; /* set polyphony, if value is different than current value */ if (pVoiceMgr->maxPolyphony == polyphonyCount) return EAS_SUCCESS; pVoiceMgr->maxPolyphony = (EAS_U16) polyphonyCount; #endif /* if SPMIDI enabled, update channel masking based on new polyphony */ for (i = 0; i < MAX_VIRTUAL_SYNTHESIZERS; i++) { if (pVoiceMgr->pSynth[i]) { if (pVoiceMgr->pSynth[i]->synthFlags & SYNTH_FLAG_SP_MIDI_ON) VMMIPUpdateChannelMuting(pVoiceMgr, pVoiceMgr->pSynth[i]); else pVoiceMgr->pSynth[i]->poolAlloc[0] = (EAS_U8) polyphonyCount; } } /* are we under polyphony limit? */ if (pVoiceMgr->activeVoices <= polyphonyCount) return EAS_SUCCESS; /* count the number of active voices */ activeVoices = 0; for (i = 0; i < MAX_SYNTH_VOICES; i++) { /* is voice active? */ if ((pVoiceMgr->voices[i].voiceState != eVoiceStateFree) && (pVoiceMgr->voices[i].voiceState != eVoiceStateMuting)) activeVoices++; } /* we may have to mute voices to reach new target */ while (activeVoices > polyphonyCount) { S_SYNTH *pSynth; S_SYNTH_VOICE *pVoice; EAS_I32 currentPriority, bestPriority; EAS_INT bestCandidate; /* find the lowest priority voice */ bestPriority = bestCandidate = -1; for (i = 0; i < MAX_SYNTH_VOICES; i++) { pVoice = &pVoiceMgr->voices[i]; /* ignore free and muting voices */ if ((pVoice->voiceState == eVoiceStateFree) || (pVoice->voiceState == eVoiceStateMuting)) continue; pSynth = pVoiceMgr->pSynth[GET_VSYNTH(pVoice->channel)]; /* if voice is stolen or just started, reduce the likelihood it will be stolen */ if (( pVoice->voiceState == eVoiceStateStolen) || (pVoice->voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET)) { /* include velocity */ currentPriority = 128 - pVoice->nextVelocity; /* include channel priority */ currentPriority += pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool << CHANNEL_PRIORITY_STEAL_WEIGHT; } else { /* include age */ currentPriority = (EAS_I32) pVoice->age << NOTE_AGE_STEAL_WEIGHT; /* include note gain -higher gain is lower steal value */ /*lint -e{704} use shift for performance */ currentPriority += ((32768 >> (12 - NOTE_GAIN_STEAL_WEIGHT)) + 256) - ((EAS_I32) pVoice->gain >> (12 - NOTE_GAIN_STEAL_WEIGHT)); /* include channel priority */ currentPriority += pSynth->channels[GET_CHANNEL(pVoice->channel)].pool << CHANNEL_PRIORITY_STEAL_WEIGHT; } /* include synth priority */ currentPriority += pSynth->priority << SYNTH_PRIORITY_WEIGHT; /* is this the best choice so far? */ if (currentPriority > bestPriority) { bestPriority = currentPriority; bestCandidate = i; } } /* shutdown best candidate */ if (bestCandidate < 0) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMSetPolyphony: Unable to reduce polyphony\n"); */ } break; } /* shut down this voice */ /*lint -e{771} pSynth is initialized if bestCandidate >= 0 */ VMMuteVoice(pVoiceMgr, bestCandidate); activeVoices--; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * VMGetSynthPolyphony() *---------------------------------------------------------------------------- * Purpose: * Returns the current polyphony setting * * Inputs: * pVoiceMgr pointer to synthesizer data * synth synthesizer number (0 = onboard, 1 = DSP) * * Outputs: * Returns actual polyphony value set, as pinned by limits * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT VMGetSynthPolyphony (S_VOICE_MGR *pVoiceMgr, EAS_I32 synth, EAS_I32 *pPolyphonyCount) { #if defined(_SECONDARY_SYNTH) || defined(EAS_SPLIT_WT_SYNTH) if (synth == EAS_MCU_SYNTH) *pPolyphonyCount = pVoiceMgr->maxPolyphonyPrimary; else if (synth == EAS_DSP_SYNTH) *pPolyphonyCount = pVoiceMgr->maxPolyphonySecondary; else return EAS_ERROR_PARAMETER_RANGE; #else if (synth != EAS_MCU_SYNTH) return EAS_ERROR_PARAMETER_RANGE; *pPolyphonyCount = pVoiceMgr->maxPolyphony; #endif return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * VMSetPolyphony() *---------------------------------------------------------------------------- * Purpose: * Set the virtual synth polyphony. 0 = no limit (i.e. can use * all available voices). * * Inputs: * pVoiceMgr pointer to synthesizer data * polyphonyCount desired polyphony count * pSynth pointer to virtual synth * * Outputs: * Returns error code * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT VMSetPolyphony (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 polyphonyCount) { EAS_INT i; EAS_INT activeVoices; /* check limits */ if (polyphonyCount < 0) return EAS_ERROR_PARAMETER_RANGE; /* zero is max polyphony */ if ((polyphonyCount == 0) || (polyphonyCount > MAX_SYNTH_VOICES)) { pSynth->maxPolyphony = 0; return EAS_SUCCESS; } /* set new polyphony */ pSynth->maxPolyphony = (EAS_U16) polyphonyCount; /* max polyphony is minimum of virtual synth and actual synth */ if (polyphonyCount > pVoiceMgr->maxPolyphony) polyphonyCount = pVoiceMgr->maxPolyphony; /* if SP-MIDI mode, update the channel muting */ if (pSynth->synthFlags & SYNTH_FLAG_SP_MIDI_ON) VMMIPUpdateChannelMuting(pVoiceMgr, pSynth); else pSynth->poolAlloc[0] = (EAS_U8) polyphonyCount; /* are we under polyphony limit? */ if (pSynth->numActiveVoices <= polyphonyCount) return EAS_SUCCESS; /* count the number of active voices */ activeVoices = 0; for (i = 0; i < MAX_SYNTH_VOICES; i++) { /* this synth? */ if (GET_VSYNTH(pVoiceMgr->voices[i].nextChannel) != pSynth->vSynthNum) continue; /* is voice active? */ if ((pVoiceMgr->voices[i].voiceState != eVoiceStateFree) && (pVoiceMgr->voices[i].voiceState != eVoiceStateMuting)) activeVoices++; } /* we may have to mute voices to reach new target */ while (activeVoices > polyphonyCount) { S_SYNTH_VOICE *pVoice; EAS_I32 currentPriority, bestPriority; EAS_INT bestCandidate; /* find the lowest priority voice */ bestPriority = bestCandidate = -1; for (i = 0; i < MAX_SYNTH_VOICES; i++) { pVoice = &pVoiceMgr->voices[i]; /* this synth? */ if (GET_VSYNTH(pVoice->nextChannel) != pSynth->vSynthNum) continue; /* if voice is stolen or just started, reduce the likelihood it will be stolen */ if (( pVoice->voiceState == eVoiceStateStolen) || (pVoice->voiceFlags & VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET)) { /* include velocity */ currentPriority = 128 - pVoice->nextVelocity; /* include channel priority */ currentPriority += pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool << CHANNEL_PRIORITY_STEAL_WEIGHT; } else { /* include age */ currentPriority = (EAS_I32) pVoice->age << NOTE_AGE_STEAL_WEIGHT; /* include note gain -higher gain is lower steal value */ /*lint -e{704} use shift for performance */ currentPriority += ((32768 >> (12 - NOTE_GAIN_STEAL_WEIGHT)) + 256) - ((EAS_I32) pVoice->gain >> (12 - NOTE_GAIN_STEAL_WEIGHT)); /* include channel priority */ currentPriority += pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool << CHANNEL_PRIORITY_STEAL_WEIGHT; } /* is this the best choice so far? */ if (currentPriority > bestPriority) { bestPriority = currentPriority; bestCandidate = i; } } /* shutdown best candidate */ if (bestCandidate < 0) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "VMSetPolyphony: Unable to reduce polyphony\n"); */ } break; } /* shut down this voice */ VMMuteVoice(pVoiceMgr, bestCandidate); activeVoices--; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * VMGetPolyphony() *---------------------------------------------------------------------------- * Purpose: * Get the virtual synth polyphony * * Inputs: * pVoiceMgr pointer to synthesizer data * pPolyphonyCount pointer to variable to hold polyphony count * pSynth pointer to virtual synth * * Outputs: * Returns error code * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pVoiceMgr) reserved for future use */ EAS_RESULT VMGetPolyphony (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 *pPolyphonyCount) { *pPolyphonyCount = (EAS_U16) pSynth->maxPolyphony; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * VMSetPriority() *---------------------------------------------------------------------------- * Purpose: * Set the virtual synth priority * * Inputs: * pVoiceMgr pointer to synthesizer data * priority new priority * pSynth pointer to virtual synth * * Outputs: * Returns error code * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pVoiceMgr) reserved for future use */ EAS_RESULT VMSetPriority (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 priority) { pSynth->priority = (EAS_U8) priority ; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * VMGetPriority() *---------------------------------------------------------------------------- * Purpose: * Get the virtual synth priority * * Inputs: * pVoiceMgr pointer to synthesizer data * pPriority pointer to variable to hold priority * pSynth pointer to virtual synth * * Outputs: * Returns error code * * Side Effects: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pVoiceMgr) reserved for future use */ EAS_RESULT VMGetPriority (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_I32 *pPriority) { *pPriority = pSynth->priority; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * VMSetVolume() *---------------------------------------------------------------------------- * Purpose: * Set the master volume for this synthesizer for this sequence. * * Inputs: * nSynthVolume - the desired master volume * psEASData - pointer to overall EAS data structure * * Outputs: * * * Side Effects: * overrides any previously set master volume from sysex * *---------------------------------------------------------------------------- */ void VMSetVolume (S_SYNTH *pSynth, EAS_U16 masterVolume) { pSynth->masterVolume = masterVolume; pSynth->synthFlags |= SYNTH_FLAG_UPDATE_ALL_CHANNEL_PARAMETERS; } /*---------------------------------------------------------------------------- * VMSetPitchBendRange() *---------------------------------------------------------------------------- * Set the pitch bend range for the given channel. *---------------------------------------------------------------------------- */ void VMSetPitchBendRange (S_SYNTH *pSynth, EAS_INT channel, EAS_I16 pitchBendRange) { pSynth->channels[channel].pitchBendSensitivity = pitchBendRange; } /*---------------------------------------------------------------------------- * VMValidateEASLib() *---------------------------------------------------------------------------- * Validates an EAS library *---------------------------------------------------------------------------- */ EAS_RESULT VMValidateEASLib (EAS_SNDLIB_HANDLE pEAS) { /* validate the sound library */ if (pEAS) { if (pEAS->identifier != _EAS_LIBRARY_VERSION) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMValidateEASLib: Sound library mismatch in sound library: Read 0x%08x, expected 0x%08x\n", pEAS->identifier, _EAS_LIBRARY_VERSION); */ } return EAS_ERROR_SOUND_LIBRARY; } /* check sample rate */ if ((pEAS->libAttr & LIBFORMAT_SAMPLE_RATE_MASK) != _OUTPUT_SAMPLE_RATE) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMValidateEASLib: Sample rate mismatch in sound library: Read %lu, expected %lu\n", pEAS->libAttr & LIBFORMAT_SAMPLE_RATE_MASK, _OUTPUT_SAMPLE_RATE); */ } return EAS_ERROR_SOUND_LIBRARY; } #ifdef _WT_SYNTH /* check sample bit depth */ #ifdef _8_BIT_SAMPLES if (pEAS->libAttr & LIB_FORMAT_16_BIT_SAMPLES) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMValidateEASLib: Expected 8-bit samples and found 16-bit\n", pEAS->libAttr & LIBFORMAT_SAMPLE_RATE_MASK, _OUTPUT_SAMPLE_RATE); */ } return EAS_ERROR_SOUND_LIBRARY; } #endif #ifdef _16_BIT_SAMPLES if ((pEAS->libAttr & LIB_FORMAT_16_BIT_SAMPLES) == 0) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMValidateEASLib: Expected 16-bit samples and found 8-bit\n", pEAS->libAttr & LIBFORMAT_SAMPLE_RATE_MASK, _OUTPUT_SAMPLE_RATE); */ } return EAS_ERROR_SOUND_LIBRARY; } #endif #endif } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * VMSetGlobalEASLib() *---------------------------------------------------------------------------- * Purpose: * Sets the EAS library to be used by the synthesizer * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT VMSetGlobalEASLib (S_VOICE_MGR *pVoiceMgr, EAS_SNDLIB_HANDLE pEAS) { EAS_RESULT result; result = VMValidateEASLib(pEAS); if (result != EAS_SUCCESS) return result; pVoiceMgr->pGlobalEAS = pEAS; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * VMSetEASLib() *---------------------------------------------------------------------------- * Purpose: * Sets the EAS library to be used by the synthesizer * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT VMSetEASLib (S_SYNTH *pSynth, EAS_SNDLIB_HANDLE pEAS) { EAS_RESULT result; result = VMValidateEASLib(pEAS); if (result != EAS_SUCCESS) return result; pSynth->pEAS = pEAS; return EAS_SUCCESS; } #ifdef DLS_SYNTHESIZER /*---------------------------------------------------------------------------- * VMSetGlobalDLSLib() *---------------------------------------------------------------------------- * Purpose: * Sets the DLS library to be used by the synthesizer * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT VMSetGlobalDLSLib (EAS_DATA_HANDLE pEASData, EAS_DLSLIB_HANDLE pDLS) { if (pEASData->pVoiceMgr->pGlobalDLS) DLSCleanup(pEASData->hwInstData, pEASData->pVoiceMgr->pGlobalDLS); pEASData->pVoiceMgr->pGlobalDLS = pDLS; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * VMSetDLSLib() *---------------------------------------------------------------------------- * Purpose: * Sets the DLS library to be used by the synthesizer * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT VMSetDLSLib (S_SYNTH *pSynth, EAS_DLSLIB_HANDLE pDLS) { pSynth->pDLS = pDLS; return EAS_SUCCESS; } #endif /*---------------------------------------------------------------------------- * VMSetTranposition() *---------------------------------------------------------------------------- * Purpose: * Sets the global key transposition used by the synthesizer. * Transposes all melodic instruments up or down by the specified * amount. Range is limited to +/-12 semitones. * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ void VMSetTranposition (S_SYNTH *pSynth, EAS_I32 transposition) { pSynth->globalTranspose = (EAS_I8) transposition; } /*---------------------------------------------------------------------------- * VMGetTranposition() *---------------------------------------------------------------------------- * Purpose: * Gets the global key transposition used by the synthesizer. * Transposes all melodic instruments up or down by the specified * amount. Range is limited to +/-12 semitones. * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ void VMGetTranposition (S_SYNTH *pSynth, EAS_I32 *pTransposition) { *pTransposition = pSynth->globalTranspose; } /*---------------------------------------------------------------------------- * VMGetNoteCount() *---------------------------------------------------------------------------- * Returns the total note count *---------------------------------------------------------------------------- */ EAS_I32 VMGetNoteCount (S_SYNTH *pSynth) { return pSynth->totalNoteCount; } /*---------------------------------------------------------------------------- * VMMIDIShutdown() *---------------------------------------------------------------------------- * Purpose: * Clean up any Synth related system issues. * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * None * * Side Effects: * *---------------------------------------------------------------------------- */ void VMMIDIShutdown (S_EAS_DATA *pEASData, S_SYNTH *pSynth) { EAS_INT vSynthNum; /* decrement reference count, free if all references are gone */ if (--pSynth->refCount > 0) return; vSynthNum = pSynth->vSynthNum; /* cleanup DLS load */ #ifdef DLS_SYNTHESIZER /*lint -e{550} result used only in debugging code */ if (pSynth->pDLS != NULL) { EAS_RESULT result; if ((result = DLSCleanup(pEASData->hwInstData, pSynth->pDLS)) != EAS_SUCCESS) { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMMIDIShutdown: Error %ld cleaning up DLS collection\n", result); */ } pSynth->pDLS = NULL; } #endif VMReset(pEASData->pVoiceMgr, pSynth, EAS_TRUE); /* check Configuration Module for static memory allocation */ if (!pEASData->staticMemoryModel) EAS_HWFree(pEASData->hwInstData, pSynth); /* clear pointer to MIDI state */ pEASData->pVoiceMgr->pSynth[vSynthNum] = NULL; } /*---------------------------------------------------------------------------- * VMShutdown() *---------------------------------------------------------------------------- * Purpose: * Clean up any Synth related system issues. * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * None * * Side Effects: * *---------------------------------------------------------------------------- */ void VMShutdown (S_EAS_DATA *pEASData) { /* don't free a NULL pointer */ if (pEASData->pVoiceMgr == NULL) return; #ifdef DLS_SYNTHESIZER /* if we have a global DLS collection, clean it up */ if (pEASData->pVoiceMgr->pGlobalDLS) { DLSCleanup(pEASData->hwInstData, pEASData->pVoiceMgr->pGlobalDLS); pEASData->pVoiceMgr->pGlobalDLS = NULL; } #endif /* check Configuration Module for static memory allocation */ if (!pEASData->staticMemoryModel) EAS_HWFree(pEASData->hwInstData, pEASData->pVoiceMgr); pEASData->pVoiceMgr = NULL; } #ifdef EXTERNAL_AUDIO /*---------------------------------------------------------------------------- * EAS_RegExtAudioCallback() *---------------------------------------------------------------------------- * Register a callback for external audio processing *---------------------------------------------------------------------------- */ void VMRegExtAudioCallback (S_SYNTH *pSynth, EAS_VOID_PTR pInstData, EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, EAS_EXT_EVENT_FUNC cbEventFunc) { pSynth->pExtAudioInstData = pInstData; pSynth->cbProgChgFunc = cbProgChgFunc; pSynth->cbEventFunc = cbEventFunc; } /*---------------------------------------------------------------------------- * VMGetMIDIControllers() *---------------------------------------------------------------------------- * Returns the MIDI controller values on the specified channel *---------------------------------------------------------------------------- */ void VMGetMIDIControllers (S_SYNTH *pSynth, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl) { pControl->modWheel = pSynth->channels[channel].modWheel; pControl->volume = pSynth->channels[channel].volume; pControl->pan = pSynth->channels[channel].pan; pControl->expression = pSynth->channels[channel].expression; pControl->channelPressure = pSynth->channels[channel].channelPressure; #ifdef _REVERB pControl->reverbSend = pSynth->channels[channel].reverbSend; #endif #ifdef _CHORUSE pControl->chorusSend = pSynth->channels[channel].chorusSend; #endif } #endif #ifdef _SPLIT_ARCHITECTURE /*---------------------------------------------------------------------------- * VMStartFrame() *---------------------------------------------------------------------------- * Purpose: * Starts an audio frame * * Inputs: * * Outputs: * Returns true if EAS_MixEnginePrep should be called (onboard mixing) * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_BOOL VMStartFrame (S_EAS_DATA *pEASData) { /* init counter for voices starts in split architecture */ #ifdef MAX_VOICE_STARTS pVoiceMgr->numVoiceStarts = 0; #endif return pFrameInterface->pfStartFrame(pEASData->pVoiceMgr->pFrameBuffer); } /*---------------------------------------------------------------------------- * VMEndFrame() *---------------------------------------------------------------------------- * Purpose: * Stops an audio frame * * Inputs: * * Outputs: * Returns true if EAS_MixEnginePost should be called (onboard mixing) * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_BOOL VMEndFrame (S_EAS_DATA *pEASData) { return pFrameInterface->pfEndFrame(pEASData->pVoiceMgr->pFrameBuffer, pEASData->pMixBuffer, pEASData->masterGain); } #endif #ifdef TEST_HARNESS /*---------------------------------------------------------------------------- * SanityCheck() *---------------------------------------------------------------------------- */ EAS_RESULT VMSanityCheck (EAS_DATA_HANDLE pEASData) { S_SYNTH_VOICE *pVoice; S_SYNTH *pSynth; EAS_INT i; EAS_INT j; EAS_INT freeVoices; EAS_INT activeVoices; EAS_INT playingVoices; EAS_INT stolenVoices; EAS_INT releasingVoices; EAS_INT mutingVoices; EAS_INT poolCount[MAX_VIRTUAL_SYNTHESIZERS][NUM_SYNTH_CHANNELS]; EAS_INT vSynthNum; EAS_RESULT result = EAS_SUCCESS; /* initialize counts */ EAS_HWMemSet(poolCount, 0, sizeof(poolCount)); freeVoices = activeVoices = playingVoices = stolenVoices = releasingVoices = mutingVoices = 0; /* iterate through all voices */ for (i = 0; i < MAX_SYNTH_VOICES; i++) { pVoice = &pEASData->pVoiceMgr->voices[i]; if (pVoice->voiceState != eVoiceStateFree) { vSynthNum = GET_VSYNTH(pVoice->channel); if (vSynthNum >= MAX_VIRTUAL_SYNTHESIZERS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMSanityCheck: Voice %d has invalid virtual synth number %d\n", i, vSynthNum); */ } result = EAS_FAILURE; continue; } pSynth = pEASData->pVoiceMgr->pSynth[vSynthNum]; switch (pVoice->voiceState) { case eVoiceStateMuting: activeVoices++; mutingVoices++; break; case eVoiceStateStolen: vSynthNum = GET_VSYNTH(pVoice->nextChannel); if (vSynthNum >= MAX_VIRTUAL_SYNTHESIZERS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMSanityCheck: Voice %d has invalid virtual synth number %d\n", i, vSynthNum); */ } result = EAS_FAILURE; continue; } pSynth = pEASData->pVoiceMgr->pSynth[vSynthNum]; activeVoices++; stolenVoices++; poolCount[vSynthNum][pSynth->channels[GET_CHANNEL(pVoice->nextChannel)].pool]++; break; case eVoiceStateStart: case eVoiceStatePlay: activeVoices++; playingVoices++; poolCount[vSynthNum][pSynth->channels[GET_CHANNEL(pVoice->channel)].pool]++; break; case eVoiceStateRelease: activeVoices++; releasingVoices++; poolCount[vSynthNum][pSynth->channels[GET_CHANNEL(pVoice->channel)].pool]++; break; default: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMSanityCheck : voice %d in invalid state\n", i); */ } result = EAS_FAILURE; break; } } /* count free voices */ else freeVoices++; } /* dump state info */ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d free\n", freeVoices); */ } { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d active\n", activeVoices); */ } { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d playing\n", playingVoices); */ } { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d releasing\n", releasingVoices); */ } { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d muting\n", mutingVoices); */ } { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "%d stolen\n", stolenVoices); */ } if (pEASData->pVoiceMgr->activeVoices != activeVoices) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Active voice mismatch was %d should be %d\n", pEASData->pVoiceMgr->activeVoices, activeVoices); */ } result = EAS_FAILURE; } /* check virtual synth status */ for (i = 0; i < MAX_VIRTUAL_SYNTHESIZERS; i++) { if (pEASData->pVoiceMgr->pSynth[i] == NULL) continue; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Synth %d numActiveVoices: %d\n", i, pEASData->pVoiceMgr->pSynth[i]->numActiveVoices); */ } if (pEASData->pVoiceMgr->pSynth[i]->numActiveVoices > MAX_SYNTH_VOICES) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "VMSanityCheck: Synth %d illegal count for numActiveVoices: %d\n", i, pEASData->pVoiceMgr->pSynth[i]->numActiveVoices); */ } result = EAS_FAILURE; } for (j = 0; j < NUM_SYNTH_CHANNELS; j++) { if (poolCount[i][j] != pEASData->pVoiceMgr->pSynth[i]->poolCount[j]) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Pool count mismatch synth %d pool %d, was %d, should be %d\n", i, j, pEASData->pVoiceMgr->pSynth[i]->poolCount[j], poolCount[i][j]); */ } result = EAS_FAILURE; } } } return result; } #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_midi.c0000644000000000000000000000013213532747316026032 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.858000056 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_midi.c0000644000175000001440000004413713532747316026634 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_midi.c * * Contents and purpose: * This file implements the MIDI stream parser. It is called by eas_smf.c to parse MIDI messages * that are streamed out of the file. It can also parse live MIDI streams. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 794 $ * $Date: 2007-08-01 00:08:48 -0700 (Wed, 01 Aug 2007) $ *---------------------------------------------------------------------------- */ #include "eas_data.h" #include "eas_report.h" #include "eas_miditypes.h" #include "eas_midi.h" #include "eas_vm_protos.h" #include "eas_parser.h" #ifdef JET_INTERFACE #include "jet_data.h" #endif /* state enumerations for ProcessSysExMessage */ typedef enum { eSysEx, eSysExUnivNonRealTime, eSysExUnivNrtTargetID, eSysExGMControl, eSysExUnivRealTime, eSysExUnivRtTargetID, eSysExDeviceControl, eSysExMasterVolume, eSysExMasterVolLSB, eSysExSPMIDI, eSysExSPMIDIchan, eSysExSPMIDIMIP, eSysExMfgID1, eSysExMfgID2, eSysExMfgID3, eSysExEnhancer, eSysExEnhancerSubID, eSysExEnhancerFeedback1, eSysExEnhancerFeedback2, eSysExEnhancerDrive, eSysExEnhancerWet, eSysExEOX, eSysExIgnore } E_SYSEX_STATES; /* local prototypes */ static EAS_RESULT ProcessMIDIMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_INT parserMode); static EAS_RESULT ProcessSysExMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode); /*---------------------------------------------------------------------------- * EAS_InitMIDIStream() *---------------------------------------------------------------------------- * Purpose: * Initializes the MIDI stream state for parsing. * * Inputs: * * Outputs: * returns EAS_RESULT (EAS_SUCCESS is OK) * * Side Effects: * *---------------------------------------------------------------------------- */ void EAS_InitMIDIStream (S_MIDI_STREAM *pMIDIStream) { pMIDIStream->byte3 = EAS_FALSE; pMIDIStream->pending = EAS_FALSE; pMIDIStream->runningStatus = 0; pMIDIStream->status = 0; } /*---------------------------------------------------------------------------- * EAS_ParseMIDIStream() *---------------------------------------------------------------------------- * Purpose: * Parses a MIDI input stream character by character. Characters are pushed (rather than pulled) * so the interface works equally well for both file and stream I/O. * * Inputs: * c - character from MIDI stream * * Outputs: * returns EAS_RESULT (EAS_SUCCESS is OK) * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_ParseMIDIStream (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode) { /* check for new status byte */ if (c & 0x80) { /* save new running status */ if (c < 0xf8) { pMIDIStream->runningStatus = c; pMIDIStream->byte3 = EAS_FALSE; /* deal with SysEx */ if ((c == 0xf7) || (c == 0xf0)) { if (parserMode == eParserModeMetaData) return EAS_SUCCESS; return ProcessSysExMessage(pEASData, pSynth, pMIDIStream, c, parserMode); } /* inform the file parser that we're in the middle of a message */ if ((c < 0xf4) || (c > 0xf6)) pMIDIStream->pending = EAS_TRUE; } /* real-time message - ignore it */ return EAS_SUCCESS; } /* 3rd byte of a 3-byte message? */ if (pMIDIStream->byte3) { pMIDIStream->d2 = c; pMIDIStream->byte3 = EAS_FALSE; pMIDIStream->pending = EAS_FALSE; if (parserMode == eParserModeMetaData) return EAS_SUCCESS; return ProcessMIDIMessage(pEASData, pSynth, pMIDIStream, parserMode); } /* check for status received */ if (pMIDIStream->runningStatus) { /* save new status and data byte */ pMIDIStream->status = pMIDIStream->runningStatus; /* check for 3-byte messages */ if (pMIDIStream->status < 0xc0) { pMIDIStream->d1 = c; pMIDIStream->pending = EAS_TRUE; pMIDIStream->byte3 = EAS_TRUE; return EAS_SUCCESS; } /* check for 2-byte messages */ if (pMIDIStream->status < 0xe0) { pMIDIStream->d1 = c; pMIDIStream->pending = EAS_FALSE; if (parserMode == eParserModeMetaData) return EAS_SUCCESS; return ProcessMIDIMessage(pEASData, pSynth, pMIDIStream, parserMode); } /* check for more 3-bytes message */ if (pMIDIStream->status < 0xf0) { pMIDIStream->d1 = c; pMIDIStream->pending = EAS_TRUE; pMIDIStream->byte3 = EAS_TRUE; return EAS_SUCCESS; } /* SysEx message? */ if (pMIDIStream->status == 0xF0) { if (parserMode == eParserModeMetaData) return EAS_SUCCESS; return ProcessSysExMessage(pEASData, pSynth, pMIDIStream, c, parserMode); } /* remaining messages all clear running status */ pMIDIStream->runningStatus = 0; /* F2 is 3-byte message */ if (pMIDIStream->status == 0xf2) { pMIDIStream->byte3 = EAS_TRUE; return EAS_SUCCESS; } } /* no status byte received, provide a warning, but we should be able to recover */ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Received MIDI data without a valid status byte: %d\n",c); */ } pMIDIStream->pending = EAS_FALSE; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * ProcessMIDIMessage() *---------------------------------------------------------------------------- * Purpose: * This function processes a typical MIDI message. All of the data has been received, just need * to take appropriate action. * * Inputs: * * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_RESULT ProcessMIDIMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_INT parserMode) { EAS_U8 channel; channel = pMIDIStream->status & 0x0f; switch (pMIDIStream->status & 0xf0) { case 0x80: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOff: %02x %02x %02x\n", pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } if (parserMode <= eParserModeMute) VMStopNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); break; case 0x90: if (pMIDIStream->d2) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOn: %02x %02x %02x\n", pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } pMIDIStream->flags |= MIDI_FLAG_FIRST_NOTE; if (parserMode == eParserModePlay) VMStartNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); } else { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"NoteOff: %02x %02x %02x\n", pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } if (parserMode <= eParserModeMute) VMStopNote(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); } break; case 0xa0: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"PolyPres: %02x %02x %02x\n", pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } break; case 0xb0: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Control: %02x %02x %02x\n", pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } if (parserMode <= eParserModeMute) VMControlChange(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); #ifdef JET_INTERFACE if (pMIDIStream->jetData & MIDI_FLAGS_JET_CB) { JET_Event(pEASData, pMIDIStream->jetData & (JET_EVENT_SEG_MASK | JET_EVENT_TRACK_MASK), channel, pMIDIStream->d1, pMIDIStream->d2); } #endif break; case 0xc0: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Program: %02x %02x\n", pMIDIStream->status, pMIDIStream->d1); */ } if (parserMode <= eParserModeMute) VMProgramChange(pEASData->pVoiceMgr, pSynth, channel, pMIDIStream->d1); break; case 0xd0: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"ChanPres: %02x %02x\n", pMIDIStream->status, pMIDIStream->d1); */ } if (parserMode <= eParserModeMute) VMChannelPressure(pSynth, channel, pMIDIStream->d1); break; case 0xe0: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"PBend: %02x %02x %02x\n", pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } if (parserMode <= eParserModeMute) VMPitchBend(pSynth, channel, pMIDIStream->d1, pMIDIStream->d2); break; default: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL,"Unknown: %02x %02x %02x\n", pMIDIStream->status, pMIDIStream->d1, pMIDIStream->d2); */ } } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * ProcessSysExMessage() *---------------------------------------------------------------------------- * Purpose: * Process a SysEx character byte from the MIDI stream. Since we cannot * simply wait for the next character to arrive, we are forced to save * state after each character. It would be easier to parse at the file * level, but then we lose the nice feature of being able to support * these messages in a real-time MIDI stream. * * Inputs: * pEASData - pointer to synthesizer instance data * c - character to be processed * locating - if true, the sequencer is relocating to a new position * * Outputs: * * * Side Effects: * * Notes: * These are the SysEx messages we can receive: * * SysEx messages * { f0 7e 7f 09 01 f7 } GM 1 On * { f0 7e 7f 09 02 f7 } GM 1/2 Off * { f0 7e 7f 09 03 f7 } GM 2 On * { f0 7f 7f 04 01 lsb msb } Master Volume * { f0 7f 7f 0b 01 ch mip [ch mip ...] f7 } SP-MIDI * { f0 00 01 3a 04 01 fdbk1 fdbk2 drive wet dry f7 } Enhancer * *---------------------------------------------------------------------------- */ static EAS_RESULT ProcessSysExMessage (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode) { /* check for start byte */ if (c == 0xf0) { pMIDIStream->sysExState = eSysEx; } /* check for end byte */ else if (c == 0xf7) { /* if this was a MIP message, update the MIP table */ if ((pMIDIStream->sysExState == eSysExSPMIDIchan) && (parserMode != eParserModeMetaData)) VMUpdateMIPTable(pEASData->pVoiceMgr, pSynth); pMIDIStream->sysExState = eSysExIgnore; } /* process SysEx message */ else { switch (pMIDIStream->sysExState) { case eSysEx: /* first byte, determine message class */ switch (c) { case 0x7e: pMIDIStream->sysExState = eSysExUnivNonRealTime; break; case 0x7f: pMIDIStream->sysExState = eSysExUnivRealTime; break; case 0x00: pMIDIStream->sysExState = eSysExMfgID1; break; default: pMIDIStream->sysExState = eSysExIgnore; break; } break; /* process GM message */ case eSysExUnivNonRealTime: if (c == 0x7f) pMIDIStream->sysExState = eSysExUnivNrtTargetID; else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExUnivNrtTargetID: if (c == 0x09) pMIDIStream->sysExState = eSysExGMControl; else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExGMControl: if ((c == 1) || (c == 3)) { /* GM 1 or GM2 On, reset synth */ if (parserMode != eParserModeMetaData) { pMIDIStream->flags |= MIDI_FLAG_GM_ON; VMReset(pEASData->pVoiceMgr, pSynth, EAS_FALSE); VMInitMIPTable(pSynth); } pMIDIStream->sysExState = eSysExEOX; } else pMIDIStream->sysExState = eSysExIgnore; break; /* Process Master Volume and SP-MIDI */ case eSysExUnivRealTime: if (c == 0x7f) pMIDIStream->sysExState = eSysExUnivRtTargetID; else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExUnivRtTargetID: if (c == 0x04) pMIDIStream->sysExState = eSysExDeviceControl; else if (c == 0x0b) pMIDIStream->sysExState = eSysExSPMIDI; else pMIDIStream->sysExState = eSysExIgnore; break; /* process master volume */ case eSysExDeviceControl: if (c == 0x01) pMIDIStream->sysExState = eSysExMasterVolume; else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExMasterVolume: /* save LSB */ pMIDIStream->d1 = c; pMIDIStream->sysExState = eSysExMasterVolLSB; break; case eSysExMasterVolLSB: if (parserMode != eParserModeMetaData) { EAS_I32 gain = ((EAS_I32) c << 8) | ((EAS_I32) pMIDIStream->d1 << 1); gain = (gain * gain) >> 15; VMSetVolume(pSynth, (EAS_U16) gain); } pMIDIStream->sysExState = eSysExEOX; break; /* process SP-MIDI MIP message */ case eSysExSPMIDI: if (c == 0x01) { /* assume all channels are muted */ if (parserMode != eParserModeMetaData) VMInitMIPTable(pSynth); pMIDIStream->d1 = 0; pMIDIStream->sysExState = eSysExSPMIDIchan; } else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExSPMIDIchan: if (c < NUM_SYNTH_CHANNELS) { pMIDIStream->d2 = c; pMIDIStream->sysExState = eSysExSPMIDIMIP; } else { /* bad MIP message - unmute channels */ if (parserMode != eParserModeMetaData) VMInitMIPTable(pSynth); pMIDIStream->sysExState = eSysExIgnore; } break; case eSysExSPMIDIMIP: /* process MIP entry here */ if (parserMode != eParserModeMetaData) VMSetMIPEntry(pEASData->pVoiceMgr, pSynth, pMIDIStream->d2, pMIDIStream->d1, c); pMIDIStream->sysExState = eSysExSPMIDIchan; /* if 16 channels received, update MIP table */ if (++pMIDIStream->d1 == NUM_SYNTH_CHANNELS) { if (parserMode != eParserModeMetaData) VMUpdateMIPTable(pEASData->pVoiceMgr, pSynth); pMIDIStream->sysExState = eSysExEOX; } break; /* process Enhancer */ case eSysExMfgID1: if (c == 0x01) pMIDIStream->sysExState = eSysExMfgID1; else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExMfgID2: if (c == 0x3a) pMIDIStream->sysExState = eSysExMfgID1; else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExMfgID3: if (c == 0x04) pMIDIStream->sysExState = eSysExEnhancer; else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExEnhancer: if (c == 0x01) pMIDIStream->sysExState = eSysExEnhancerSubID; else pMIDIStream->sysExState = eSysExIgnore; break; case eSysExEnhancerSubID: pMIDIStream->sysExState = eSysExEnhancerFeedback1; break; case eSysExEnhancerFeedback1: pMIDIStream->sysExState = eSysExEnhancerFeedback2; break; case eSysExEnhancerFeedback2: pMIDIStream->sysExState = eSysExEnhancerDrive; break; case eSysExEnhancerDrive: pMIDIStream->sysExState = eSysExEnhancerWet; break; case eSysExEnhancerWet: pMIDIStream->sysExState = eSysExEOX; break; case eSysExEOX: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Expected F7, received %02x\n", c); */ } pMIDIStream->sysExState = eSysExIgnore; break; case eSysExIgnore: break; default: pMIDIStream->sysExState = eSysExIgnore; break; } } if (pMIDIStream->sysExState == eSysExIgnore) { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Ignoring SysEx byte %02x\n", c); */ } return EAS_SUCCESS; } /* end ProcessSysExMessage */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_pan.h0000644000000000000000000000013213532747316025673 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.858000056 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_pan.h0000644000175000001440000000417513532747316026473 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_pan.h * * Contents and purpose: * Calculates left and right gain multipliers based on a pan value from -63 to +63 * * NOTES: * The _CMX_PARSER and _MFI_PARSER preprocessor symbols determine * whether the parser works for those particular file formats. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ #ifndef EAS_PAN_H #define _EAS_PAN_H #include "eas_types.h" /*---------------------------------------------------------------------------- * EAS_CalcPanControl() *---------------------------------------------------------------------------- * Purpose: * Assign the left and right gain values corresponding to the given pan value. * * This routine uses sin/cos approximations for an equal power curve: * * sin(x) = (2-4*c)*x^2 + c + x * cos(x) = (2-4*c)*x^2 + c - x * * where c = 1/sqrt(2) * using the a0 + x*(a1 + x*a2) approach * * Inputs: * pan - pan value (-63 to + 63) * * Outputs: * pGainLeft linear gain multiplier for left channel (15-bit fraction) * pGainRight linear gain multiplier for left channel (15-bit fraction) * * Side Effects: *---------------------------------------------------------------------------- */ void EAS_CalcPanControl (EAS_INT pan, EAS_I16 *pGainLeft, EAS_I16 *pGainRight); #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_wtengine.c0000644000000000000000000000013213532747316026730 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.858000056 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_wtengine.c0000644000175000001440000004560513532747316027533 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_wtengine.c * * Contents and purpose: * This file contains the critical synthesizer components that need to * be optimized for best performance. * * Copyright Sonic Network Inc. 2004-2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 844 $ * $Date: 2007-08-23 14:33:32 -0700 (Thu, 23 Aug 2007) $ *---------------------------------------------------------------------------- */ /*------------------------------------ * includes *------------------------------------ */ #include "eas_types.h" #include "eas_math.h" #include "eas_audioconst.h" #include "eas_sndlib.h" #include "eas_wtengine.h" #include "eas_mixer.h" /*---------------------------------------------------------------------------- * prototypes *---------------------------------------------------------------------------- */ extern void WT_NoiseGenerator (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); extern void WT_VoiceGain (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); #if defined(_OPTIMIZED_MONO) extern void WT_InterpolateMono (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); #else extern void WT_InterpolateNoLoop (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); extern void WT_Interpolate (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); #endif #if defined(_FILTER_ENABLED) extern void WT_VoiceFilter (S_FILTER_CONTROL*pFilter, S_WT_INT_FRAME *pWTIntFrame); #endif #if defined(_OPTIMIZED_MONO) || !defined(NATIVE_EAS_KERNEL) /*---------------------------------------------------------------------------- * WT_VoiceGain *---------------------------------------------------------------------------- * Purpose: * Output gain for individual voice * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ /*lint -esym(715, pWTVoice) reserved for future use */ void WT_VoiceGain (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) { EAS_I32 *pMixBuffer; EAS_PCM *pInputBuffer; EAS_I32 gain; EAS_I32 gainIncrement; EAS_I32 tmp0; EAS_I32 tmp1; EAS_I32 tmp2; EAS_I32 numSamples; #if (NUM_OUTPUT_CHANNELS == 2) EAS_I32 gainLeft, gainRight; #endif /* initialize some local variables */ numSamples = pWTIntFrame->numSamples; pMixBuffer = pWTIntFrame->pMixBuffer; pInputBuffer = pWTIntFrame->pAudioBuffer; /*lint -e{703} */ gainIncrement = (pWTIntFrame->frame.gainTarget - pWTIntFrame->prevGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS); if (gainIncrement < 0) gainIncrement++; /*lint -e{703} */ gain = pWTIntFrame->prevGain << 16; #if (NUM_OUTPUT_CHANNELS == 2) gainLeft = pWTVoice->gainLeft; gainRight = pWTVoice->gainRight; #endif while (numSamples--) { /* incremental gain step to prevent zipper noise */ tmp0 = *pInputBuffer++; gain += gainIncrement; /*lint -e{704} */ tmp2 = gain >> 16; /* scale sample by gain */ tmp2 *= tmp0; /* stereo output */ #if (NUM_OUTPUT_CHANNELS == 2) /*lint -e{704} */ tmp2 = tmp2 >> 14; /* get the current sample in the final mix buffer */ tmp1 = *pMixBuffer; /* left channel */ tmp0 = tmp2 * gainLeft; /*lint -e{704} */ tmp0 = tmp0 >> NUM_MIXER_GUARD_BITS; tmp1 += tmp0; *pMixBuffer++ = tmp1; /* get the current sample in the final mix buffer */ tmp1 = *pMixBuffer; /* right channel */ tmp0 = tmp2 * gainRight; /*lint -e{704} */ tmp0 = tmp0 >> NUM_MIXER_GUARD_BITS; tmp1 += tmp0; *pMixBuffer++ = tmp1; /* mono output */ #else /* get the current sample in the final mix buffer */ tmp1 = *pMixBuffer; /*lint -e{704} */ tmp2 = tmp2 >> (NUM_MIXER_GUARD_BITS - 1); tmp1 += tmp2; *pMixBuffer++ = tmp1; #endif } } #endif #ifndef NATIVE_EAS_KERNEL /*---------------------------------------------------------------------------- * WT_Interpolate *---------------------------------------------------------------------------- * Purpose: * Interpolation engine for wavetable synth * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ void WT_Interpolate (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) { EAS_PCM *pOutputBuffer; EAS_I32 phaseInc; EAS_I32 phaseFrac; EAS_I32 acc0; const EAS_SAMPLE *pSamples; const EAS_SAMPLE *loopEnd; EAS_I32 samp1; EAS_I32 samp2; EAS_I32 numSamples; /* initialize some local variables */ numSamples = pWTIntFrame->numSamples; pOutputBuffer = pWTIntFrame->pAudioBuffer; loopEnd = (const EAS_SAMPLE*) pWTVoice->loopEnd + 1; pSamples = (const EAS_SAMPLE*) pWTVoice->phaseAccum; /*lint -e{713} truncation is OK */ phaseFrac = pWTVoice->phaseFrac; phaseInc = pWTIntFrame->frame.phaseIncrement; /* fetch adjacent samples */ #if defined(_8_BIT_SAMPLES) /*lint -e{701} */ samp1 = pSamples[0] << 8; /*lint -e{701} */ samp2 = pSamples[1] << 8; #else samp1 = pSamples[0]; samp2 = pSamples[1]; #endif while (numSamples--) { /* linear interpolation */ acc0 = samp2 - samp1; acc0 = acc0 * phaseFrac; /*lint -e{704} */ acc0 = samp1 + (acc0 >> NUM_PHASE_FRAC_BITS); /* save new output sample in buffer */ /*lint -e{704} */ *pOutputBuffer++ = (EAS_I16)(acc0 >> 2); /* increment phase */ phaseFrac += phaseInc; /*lint -e{704} */ acc0 = phaseFrac >> NUM_PHASE_FRAC_BITS; /* next sample */ if (acc0 > 0) { /* advance sample pointer */ pSamples += acc0; phaseFrac = (EAS_I32)((EAS_U32)phaseFrac & PHASE_FRAC_MASK); /* check for loop end */ acc0 = (EAS_I32) (pSamples - loopEnd); if (acc0 >= 0) pSamples = (const EAS_SAMPLE*) pWTVoice->loopStart + acc0; /* fetch new samples */ #if defined(_8_BIT_SAMPLES) /*lint -e{701} */ samp1 = pSamples[0] << 8; /*lint -e{701} */ samp2 = pSamples[1] << 8; #else samp1 = pSamples[0]; samp2 = pSamples[1]; #endif } } /* save pointer and phase */ pWTVoice->phaseAccum = (EAS_U32) pSamples; pWTVoice->phaseFrac = (EAS_U32) phaseFrac; } #endif #ifndef NATIVE_EAS_KERNEL /*---------------------------------------------------------------------------- * WT_InterpolateNoLoop *---------------------------------------------------------------------------- * Purpose: * Interpolation engine for wavetable synth * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ void WT_InterpolateNoLoop (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) { EAS_PCM *pOutputBuffer; EAS_I32 phaseInc; EAS_I32 phaseFrac; EAS_I32 acc0; const EAS_SAMPLE *pSamples; EAS_I32 samp1; EAS_I32 samp2; EAS_I32 numSamples; /* initialize some local variables */ numSamples = pWTIntFrame->numSamples; pOutputBuffer = pWTIntFrame->pAudioBuffer; phaseInc = pWTIntFrame->frame.phaseIncrement; pSamples = (const EAS_SAMPLE*) pWTVoice->phaseAccum; phaseFrac = (EAS_I32)pWTVoice->phaseFrac; /* fetch adjacent samples */ #if defined(_8_BIT_SAMPLES) /*lint -e{701} */ samp1 = pSamples[0] << 8; /*lint -e{701} */ samp2 = pSamples[1] << 8; #else samp1 = pSamples[0]; samp2 = pSamples[1]; #endif while (numSamples--) { /* linear interpolation */ acc0 = samp2 - samp1; acc0 = acc0 * phaseFrac; /*lint -e{704} */ acc0 = samp1 + (acc0 >> NUM_PHASE_FRAC_BITS); /* save new output sample in buffer */ /*lint -e{704} */ *pOutputBuffer++ = (EAS_I16)(acc0 >> 2); /* increment phase */ phaseFrac += phaseInc; /*lint -e{704} */ acc0 = phaseFrac >> NUM_PHASE_FRAC_BITS; /* next sample */ if (acc0 > 0) { /* advance sample pointer */ pSamples += acc0; phaseFrac = (EAS_I32)((EAS_U32)phaseFrac & PHASE_FRAC_MASK); /* fetch new samples */ #if defined(_8_BIT_SAMPLES) /*lint -e{701} */ samp1 = pSamples[0] << 8; /*lint -e{701} */ samp2 = pSamples[1] << 8; #else samp1 = pSamples[0]; samp2 = pSamples[1]; #endif } } /* save pointer and phase */ pWTVoice->phaseAccum = (EAS_U32) pSamples; pWTVoice->phaseFrac = (EAS_U32) phaseFrac; } #endif #if defined(_FILTER_ENABLED) && !defined(NATIVE_EAS_KERNEL) /*---------------------------------------------------------------------------- * WT_VoiceFilter *---------------------------------------------------------------------------- * Purpose: * Implements a 2-pole filter * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ void WT_VoiceFilter (S_FILTER_CONTROL *pFilter, S_WT_INT_FRAME *pWTIntFrame) { EAS_PCM *pAudioBuffer; EAS_I32 k; EAS_I32 b1; EAS_I32 b2; EAS_I32 z1; EAS_I32 z2; EAS_I32 acc0; EAS_I32 acc1; EAS_I32 numSamples; /* initialize some local variables */ numSamples = pWTIntFrame->numSamples; pAudioBuffer = pWTIntFrame->pAudioBuffer; z1 = pFilter->z1; z2 = pFilter->z2; b1 = -pWTIntFrame->frame.b1; /*lint -e{702} */ b2 = -pWTIntFrame->frame.b2 >> 1; /*lint -e{702} */ k = pWTIntFrame->frame.k >> 1; while (numSamples--) { /* do filter calculations */ acc0 = *pAudioBuffer; acc1 = z1 * b1; acc1 += z2 * b2; acc0 = acc1 + k * acc0; z2 = z1; /*lint -e{702} */ z1 = acc0 >> 14; *pAudioBuffer++ = (EAS_I16) z1; } /* save delay values */ pFilter->z1 = (EAS_I16) z1; pFilter->z2 = (EAS_I16) z2; } #endif /*---------------------------------------------------------------------------- * WT_NoiseGenerator *---------------------------------------------------------------------------- * Purpose: * Generate pseudo-white noise using PRNG and interpolation engine * * Inputs: * * Outputs: * * Notes: * This output is scaled -12dB to prevent saturation in the filter. For a * high quality synthesizer, the output can be set to full scale, however * if the filter is used, it can overflow with certain coefficients. In this * case, either a saturation operation should take in the filter before * scaling back to 16 bits or the signal path should be increased to 18 bits * or more. *---------------------------------------------------------------------------- */ void WT_NoiseGenerator (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) { EAS_PCM *pOutputBuffer; EAS_I32 phaseInc; EAS_I32 tmp0; EAS_I32 tmp1; EAS_I32 nInterpolatedSample; EAS_I32 numSamples; /* initialize some local variables */ numSamples = pWTIntFrame->numSamples; pOutputBuffer = pWTIntFrame->pAudioBuffer; phaseInc = pWTIntFrame->frame.phaseIncrement; /* get last two samples generated */ /*lint -e{704} */ tmp0 = (EAS_I32) (pWTVoice->phaseAccum) >> 18; /*lint -e{704} */ tmp1 = (EAS_I32) (pWTVoice->loopEnd) >> 18; /* generate a buffer of noise */ while (numSamples--) { nInterpolatedSample = MULT_AUDIO_COEF( tmp0, (PHASE_ONE - pWTVoice->phaseFrac)); nInterpolatedSample += MULT_AUDIO_COEF( tmp1, pWTVoice->phaseFrac); *pOutputBuffer++ = (EAS_PCM) nInterpolatedSample; /* update PRNG */ pWTVoice->phaseFrac += (EAS_U32) phaseInc; if (GET_PHASE_INT_PART(pWTVoice->phaseFrac)) { tmp0 = tmp1; pWTVoice->phaseAccum = pWTVoice->loopEnd; pWTVoice->loopEnd = (5 * pWTVoice->loopEnd + 1); tmp1 = (EAS_I32) (pWTVoice->loopEnd) >> 18; pWTVoice->phaseFrac = GET_PHASE_FRAC_PART(pWTVoice->phaseFrac); } } } #ifndef _OPTIMIZED_MONO /*---------------------------------------------------------------------------- * WT_ProcessVoice *---------------------------------------------------------------------------- * Purpose: * This routine does the block processing for one voice. It is isolated * from the main synth code to allow for various implementation-specific * optimizations. It calls the interpolator, filter, and gain routines * appropriate for a particular configuration. * * Inputs: * * Outputs: * * Notes: *---------------------------------------------------------------------------- */ void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) { /* use noise generator */ if (pWTVoice->loopStart == WT_NOISE_GENERATOR) WT_NoiseGenerator(pWTVoice, pWTIntFrame); /* generate interpolated samples for looped waves */ else if (pWTVoice->loopStart != pWTVoice->loopEnd) WT_Interpolate(pWTVoice, pWTIntFrame); /* generate interpolated samples for unlooped waves */ else { WT_InterpolateNoLoop(pWTVoice, pWTIntFrame); } #ifdef _FILTER_ENABLED if (pWTIntFrame->frame.k != 0) WT_VoiceFilter(&pWTVoice->filter, pWTIntFrame); #endif //2 TEST NEW MIXER FUNCTION #ifdef UNIFIED_MIXER { EAS_I32 gainLeft, gainIncLeft; #if (NUM_OUTPUT_CHANNELS == 2) EAS_I32 gainRight, gainIncRight; #endif gainLeft = (pWTIntFrame->prevGain * pWTVoice->gainLeft) << 1; gainIncLeft = (((pWTIntFrame->frame.gainTarget * pWTVoice->gainLeft) << 1) - gainLeft) >> SYNTH_UPDATE_PERIOD_IN_BITS; #if (NUM_OUTPUT_CHANNELS == 2) gainRight = (pWTIntFrame->prevGain * pWTVoice->gainRight) << 1; gainIncRight = (((pWTIntFrame->frame.gainTarget * pWTVoice->gainRight) << 1) - gainRight) >> SYNTH_UPDATE_PERIOD_IN_BITS; EAS_MixStream( pWTIntFrame->pAudioBuffer, pWTIntFrame->pMixBuffer, pWTIntFrame->numSamples, gainLeft, gainRight, gainIncLeft, gainIncRight, MIX_FLAGS_STEREO_OUTPUT); #else EAS_MixStream( pWTIntFrame->pAudioBuffer, pWTIntFrame->pMixBuffer, pWTIntFrame->numSamples, gainLeft, 0, gainIncLeft, 0, 0); #endif } #else /* apply gain, and left and right gain */ WT_VoiceGain(pWTVoice, pWTIntFrame); #endif } #endif #if defined(_OPTIMIZED_MONO) && !defined(NATIVE_EAS_KERNEL) /*---------------------------------------------------------------------------- * WT_InterpolateMono *---------------------------------------------------------------------------- * Purpose: * A C version of the sample interpolation + gain routine, optimized for mono. * It's not pretty, but it matches the assembly code exactly. * * Inputs: * * Outputs: * * Notes: *---------------------------------------------------------------------------- */ void WT_InterpolateMono (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) { EAS_I32 *pMixBuffer; const EAS_I8 *pLoopEnd; const EAS_I8 *pCurrentPhaseInt; EAS_I32 numSamples; EAS_I32 gain; EAS_I32 gainIncrement; EAS_I32 currentPhaseFrac; EAS_I32 phaseInc; EAS_I32 tmp0; EAS_I32 tmp1; EAS_I32 tmp2; EAS_I8 *pLoopStart; numSamples = pWTIntFrame->numSamples; pMixBuffer = pWTIntFrame->pMixBuffer; /* calculate gain increment */ gainIncrement = (pWTIntFrame->gainTarget - pWTIntFrame->prevGain) << (16 - SYNTH_UPDATE_PERIOD_IN_BITS); if (gainIncrement < 0) gainIncrement++; gain = pWTIntFrame->prevGain << 16; pCurrentPhaseInt = pWTVoice->pPhaseAccum; currentPhaseFrac = pWTVoice->phaseFrac; phaseInc = pWTIntFrame->phaseIncrement; pLoopStart = pWTVoice->pLoopStart; pLoopEnd = pWTVoice->pLoopEnd + 1; InterpolationLoop: tmp0 = (EAS_I32)(pCurrentPhaseInt - pLoopEnd); if (tmp0 >= 0) pCurrentPhaseInt = pLoopStart + tmp0; tmp0 = *pCurrentPhaseInt; tmp1 = *(pCurrentPhaseInt + 1); tmp2 = phaseInc + currentPhaseFrac; tmp1 = tmp1 - tmp0; tmp1 = tmp1 * currentPhaseFrac; tmp1 = tmp0 + (tmp1 >> NUM_EG1_FRAC_BITS); pCurrentPhaseInt += (tmp2 >> NUM_PHASE_FRAC_BITS); currentPhaseFrac = tmp2 & PHASE_FRAC_MASK; gain += gainIncrement; tmp2 = (gain >> SYNTH_UPDATE_PERIOD_IN_BITS); tmp0 = *pMixBuffer; tmp2 = tmp1 * tmp2; tmp2 = (tmp2 >> 9); tmp0 = tmp2 + tmp0; *pMixBuffer++ = tmp0; numSamples--; if (numSamples > 0) goto InterpolationLoop; pWTVoice->pPhaseAccum = pCurrentPhaseInt; pWTVoice->phaseFrac = currentPhaseFrac; /*lint -e{702} */ pWTVoice->gain = (EAS_I16)(gain >> SYNTH_UPDATE_PERIOD_IN_BITS); } #endif #ifdef _OPTIMIZED_MONO /*---------------------------------------------------------------------------- * WT_ProcessVoice *---------------------------------------------------------------------------- * Purpose: * This routine does the block processing for one voice. It is isolated * from the main synth code to allow for various implementation-specific * optimizations. It calls the interpolator, filter, and gain routines * appropriate for a particular configuration. * * Inputs: * * Outputs: * * Notes: * This special version works handles an optimized mono-only signal * without filters *---------------------------------------------------------------------------- */ void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame) { /* use noise generator */ if (pWTVoice->loopStart== WT_NOISE_GENERATOR) { WT_NoiseGenerator(pWTVoice, pWTIntFrame); WT_VoiceGain(pWTVoice, pWTIntFrame); } /* or generate interpolated samples */ else { WT_InterpolateMono(pWTVoice, pWTIntFrame); } } #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_tcdata.h0000644000000000000000000000013213532747316026355 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.858000056 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_tcdata.h0000644000175000001440000000471313532747316027153 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_tcdata.h * * Contents and purpose: * SMF File Parser * * This file contains data declarations for the ToneControl parser. * * Copyright Sonic Network Inc. 2006 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ #ifndef EAS_TFDATA_H #define EAS_TCDATA_H #include "eas_data.h" /*---------------------------------------------------------------------------- * * S_TC_DATA * * This structure contains the state data for the ToneControl parser *---------------------------------------------------------------------------- */ typedef struct { EAS_FILE_HANDLE fileHandle; /* file handle */ S_SYNTH *pSynth; /* synthesizer handle */ EAS_I32 fileOffset; /* offset to start of data */ EAS_I32 time; /* current time in 256ths of a msec */ EAS_I32 tick; /* tick based on current tempo and resolution */ EAS_I32 length; /* length of current note */ EAS_I32 restorePos; /* return to here after block */ EAS_U8 state; /* current state EAS_STATE_XXXX */ EAS_U8 volume; /* volume */ EAS_I8 note; /* current note */ EAS_I8 repeatCount; /* note repeat counter */ EAS_I8 tempo; /* tempo from file (bpm = tempo * 4) */ EAS_I8 resolution; /* resolution from file */ EAS_I8 dataByte; /* storage for characters that are "put back" */ EAS_BOOL8 byteAvail; /* char in "put back" buffer */ } S_TC_DATA; #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_wtengine.h0000644000000000000000000000013213532747316026735 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.858000056 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_wtengine.h0000644000175000001440000001367413532747316027541 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_wtengine.h * * Contents and purpose: * This file defines the interface for wavetable synthesis engine * * Copyright Sonic Network Inc. 2004 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 818 $ * $Date: 2007-08-02 15:19:41 -0700 (Thu, 02 Aug 2007) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_WTENGINE_H #define _EAS_WTENGINE_H /* option sanity check */ #if defined(_OPTIMIZED_MONO) && defined(_FILTER_ENABLED) #error "Incompatible build settings: _OPTIMIZED_MONO cannot be used with _FILTER_ENABLED" #endif #if defined(_OPTIMIZED_MONO) && (NUM_OUTPUT_CHANNELS != 1) #error "Incompatible build settings: _OPTIMIZED_MONO can only be used with NUM_OUTPUT_CHANNELS = 1" #endif #include "eas_wt_IPC_frame.h" /*---------------------------------------------------------------------------- * defines *---------------------------------------------------------------------------- */ #define WT_NOISE_GENERATOR 0xffffffff /*---------------------------------------------------------------------------- * typedefs *---------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------- * S_WT_INT_FRAME * * This structure includes S_WT_FRAME plus the bus mixing * parameters for the internal voices. *---------------------------------------------------------------------------- */ typedef struct s_wt_int_frame_tag { S_WT_FRAME frame; EAS_PCM *pAudioBuffer; EAS_I32 *pMixBuffer; EAS_I32 numSamples; EAS_I32 prevGain; } S_WT_INT_FRAME; #if defined(_FILTER_ENABLED) /*---------------------------------------------------------------------------- * S_FILTER_CONTROL data structure *---------------------------------------------------------------------------- */ typedef struct s_filter_control_tag { EAS_I16 z1; /* 1 sample delay state variable */ EAS_I16 z2; /* 2 sample delay state variable */ } S_FILTER_CONTROL; #endif /*------------------------------------ * S_LFO_CONTROL data structure *------------------------------------ */ typedef struct s_lfo_control_tag { EAS_I16 lfoValue; /* LFO current output value */ EAS_I16 lfoPhase; /* LFO current phase */ } S_LFO_CONTROL; /* bit definitions for S_WT_VOICE:flags */ #define WT_FLAGS_ADPCM_NIBBLE 1 /* high/low nibble flag */ #define WT_FLAGS_ADPCM_READY 2 /* first 2 samples are decoded */ #define WT_FLAGS_USE_ADPCM 4 /* sample is ADPCM encoded */ /* eg1State and eg2State */ typedef enum { eEnvelopeStateInit = 0, eEnvelopeStateDelay, eEnvelopeStateAttack, eEnvelopeStateHold, eEnvelopeStateDecay, eEnvelopeStateSustain, eEnvelopeStateRelease, eEnvelopeStateMuting, eEnvelopeStateMuted, eEnvelopeStateInvalid /* should never be in this state! */ } E_ENVELOPE_STATE; #define DEFAULT_EG1_STATE eEnvelopeStateAttack #define DEFAULT_EG1_VALUE 0 #define DEFAULT_EG1_INCREMENT 0 #define DEFAULT_EG2_STATE eEnvelopeStateAttack #define DEFAULT_EG2_VALUE 0 #define DEFAULT_EG2_INCREMENT 0 /*---------------------------------------------------------------------------- * S_WT_VOICE * * This structure contains state data for the wavetable engine *---------------------------------------------------------------------------- */ typedef struct s_wt_voice_tag { EAS_U32 loopEnd; /* points to last PCM sample (not 1 beyond last) */ EAS_U32 loopStart; /* points to first sample at start of loop */ EAS_U32 phaseAccum; /* current sample, integer portion of phase */ EAS_U32 phaseFrac; /* fractional portion of phase */ #if (NUM_OUTPUT_CHANNELS == 2) EAS_I16 gainLeft; /* current gain, left ch */ EAS_I16 gainRight; /* current gain, right ch */ #endif #if defined(_FILTER_ENABLED) S_FILTER_CONTROL filter; /* low pass filter */ #endif S_LFO_CONTROL modLFO; /* modulator LFO */ #ifdef DLS_SYNTHESIZER S_LFO_CONTROL vibLFO; /* vibrato LFO */ #endif /* envelope control */ EAS_I16 eg1Value; EAS_I16 eg2Value; EAS_I16 eg1Increment; EAS_I16 eg2Increment; EAS_U8 eg1State; EAS_U8 eg2State; EAS_U16 artIndex; /* index to articulation params */ } S_WT_VOICE; /*---------------------------------------------------------------------------- * prototypes *---------------------------------------------------------------------------- */ EAS_BOOL WT_CheckSampleEnd (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame, EAS_BOOL update); void WT_ProcessVoice (S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pWTIntFrame); #ifdef EAS_SPLIT_WT_SYNTH void WTE_ConfigVoice (EAS_I32 voiceNum, S_WT_CONFIG *pWTConfig, EAS_FRAME_BUFFER_HANDLE pFrameBuffer); void WTE_ProcessVoice (EAS_I32 voiceNum, S_WT_FRAME *pWTParams, EAS_FRAME_BUFFER_HANDLE pFrameBuffer); #endif #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_mdls.c0000644000000000000000000000013213532747316026047 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.858000056 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_mdls.c0000644000175000001440000025722513532747316026655 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_mdls.c * * Contents and purpose: * This file contains DLS to EAS converter. * * Copyright (c) 2005 Sonic Network Inc. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 818 $ * $Date: 2007-08-02 15:19:41 -0700 (Thu, 02 Aug 2007) $ *---------------------------------------------------------------------------- */ /* * NOTES: * * Processor Endian-ness: * * We use the EAS_HWGetDWord() and EAS_HWGetWord () functions * extensively in this module. It would probably be faster to read * an entire data structure, but this introduces the problem of * sensitivity to processor endian-ness to the parser. By utlilizing * the host wrapper functions, we avoid having to flip bytes around * for big-endian processors. The default host wrapper versions of * these functions are insensitive to processor endian-ness due to * the fact that they read the file as a byte stream. * * Dynamic Memory: * * Dynamic memory allocation is a risky proposition in a mobile * device. The memory can become fragmented, resulting in an * inability to allocate a memory block, or garbage collection * routines can use many CPU cycles. Either can contribute to * failures of critical systems. Therefore, we try to minimize the * number of memory allocations we make. * * We allocate a single large block of memory for the entire * converted DLS collection, including the articulation data and * samples. This block is then sub-allocated for the various * data structures. * * Parser Overview: * * We make two passes through the file, the first pass to count the * number of instruments, regions, etc. and allocate memory for * them. The second pass parses the data into the allocated data * structures. * * Conditional chunks are challenging in that they can occur * anywhere in the list chunk that contains them. To simplify, we * parse the blocks in a list in specific order, no matter which * order they appear in the file. This way we don't allocate memory * and parse a block that we end up throwing away later due to * a conditional chunk. * * Assumptions that may bite us in the future: * * We make some assumptions to simplify things. The most fundamental * assumption is that there will be no more than one of any type of * chunk in a list. While this is consistent with the block diagram * of the file layout in the mDLS spec, there is nothing in the * spec that precludes having mulitple lar2 or rgn2 chunks, with * conditional blocks that dictate their usage. * * DLS -> EAS Conversion Process: * * Another challenge is that the DLS structure does not map well to * the current EAS sound library structure. Not all DLS constructs * are supported, and data from DLS structures must sometimes be * mapped to multiple EAS data structures. To simplify the process, * the EAS region, articulation, and envelopes are treated as a * single combined unit. Thus for each region, there must be one * articulation element and two envelope elements. * * The sample processing is also a multi-step process. First the * ptbl chunk is pre-parsed to determine the number of samples * in the collection. The next step is to parse the instrument data * to determine which samples are actually used by instruments. * Some samples may not be used because they are used only in * conditional blocks that the synthesizer cannot parse, or the * author neglected to remove unused samples from the collection. * In the next step, the active samples are read into memory and * converted to the appropriate playback format. Finally, as the * instruments are processed, the links are made to the samples and * wsmp data is extracted for the region and articulation data * structures. */ #ifndef _FILTER_ENABLED #error "Filter must be enabled if DLS_SYNTHESIZER is enabled" #endif /*------------------------------------ * includes *------------------------------------ */ /* this define allows us to use the sndlib.h structures as RW memory */ #define SCNST #include "eas_data.h" #include "eas_host.h" #include "eas_mdls.h" #include "eas_math.h" #include "dls.h" #include "dls2.h" #include "eas_report.h" //2 we should replace log10() function with fixed point routine in ConvertSampleRate() /* lint is choking on the ARM math.h file, so we declare the log10 function here */ extern double log10(double x); /*------------------------------------ * defines *------------------------------------ */ // #define _DEBUG_DLS #define DLS_MAX_WAVE_COUNT 1024 #define DLS_MAX_ART_COUNT 2048 #define DLS_MAX_REGION_COUNT 2048 #define DLS_MAX_INST_COUNT 256 #define MAX_DLS_WAVE_SIZE (1024*1024) #ifndef EAS_U32_MAX #define EAS_U32_MAX (4294967295U) #endif #ifndef EAS_I32_MAX #define EAS_I32_MAX (2147483647) #endif /*------------------------------------ * typedefs *------------------------------------ */ /* offsets to articulation data */ typedef enum { PARAM_MODIFIED = 0, PARAM_MOD_LFO_FREQ, PARAM_MOD_LFO_DELAY, PARAM_VIB_LFO_FREQ, PARAM_VIB_LFO_DELAY, PARAM_VOL_EG_DELAY, PARAM_VOL_EG_ATTACK, PARAM_VOL_EG_HOLD, PARAM_VOL_EG_DECAY, PARAM_VOL_EG_SUSTAIN, PARAM_VOL_EG_RELEASE, PARAM_VOL_EG_SHUTDOWN, PARAM_VOL_EG_VEL_TO_ATTACK, PARAM_VOL_EG_KEY_TO_DECAY, PARAM_VOL_EG_KEY_TO_HOLD, PARAM_MOD_EG_DELAY, PARAM_MOD_EG_ATTACK, PARAM_MOD_EG_HOLD, PARAM_MOD_EG_DECAY, PARAM_MOD_EG_SUSTAIN, PARAM_MOD_EG_RELEASE, PARAM_MOD_EG_VEL_TO_ATTACK, PARAM_MOD_EG_KEY_TO_DECAY, PARAM_MOD_EG_KEY_TO_HOLD, PARAM_INITIAL_FC, PARAM_INITIAL_Q, PARAM_MOD_LFO_TO_FC, PARAM_MOD_LFO_CC1_TO_FC, PARAM_MOD_LFO_CHAN_PRESS_TO_FC, PARAM_MOD_EG_TO_FC, PARAM_VEL_TO_FC, PARAM_KEYNUM_TO_FC, PARAM_MOD_LFO_TO_GAIN, PARAM_MOD_LFO_CC1_TO_GAIN, PARAM_MOD_LFO_CHAN_PRESS_TO_GAIN, PARAM_VEL_TO_GAIN, PARAM_TUNING, PARAM_KEYNUM_TO_PITCH, PARAM_VIB_LFO_TO_PITCH, PARAM_VIB_LFO_CC1_TO_PITCH, PARAM_VIB_LFO_CHAN_PRESS_TO_PITCH, PARAM_MOD_LFO_TO_PITCH, PARAM_MOD_LFO_CC1_TO_PITCH, PARAM_MOD_LFO_CHAN_PRESS_TO_PITCH, PARAM_MOD_EG_TO_PITCH, PARAM_DEFAULT_PAN, PARAM_MIDI_CC91_TO_REVERB_SEND, PARAM_DEFAULT_REVERB_SEND, PARAM_MIDI_CC93_TO_CHORUS_SEND, PARAM_DEFAULT_CHORUS_SEND, PARAM_TABLE_SIZE } E_ART_INDEX; /* temporary data structure combining region, articulation, and envelope data */ typedef struct s_art_dls_tag { EAS_I16 values[PARAM_TABLE_SIZE]; } S_DLS_ART_VALUES; /* temporary data structure for wlnk chunk data */ typedef struct { EAS_I32 gain; EAS_U32 loopStart; EAS_U32 loopLength; EAS_U32 sampleRate; EAS_U16 bitsPerSample; EAS_I16 fineTune; EAS_U8 unityNote; } S_WSMP_DATA; /* temporary data structure used while parsing a DLS file */ typedef struct { S_DLS *pDLS; EAS_HW_DATA_HANDLE hwInstData; EAS_FILE_HANDLE fileHandle; S_WSMP_DATA *wsmpData; EAS_U32 instCount; EAS_U32 regionCount; EAS_U32 artCount; EAS_U32 waveCount; EAS_U32 wavePoolSize; EAS_U32 wavePoolOffset; EAS_BOOL bigEndian; EAS_BOOL filterUsed; } SDLS_SYNTHESIZER_DATA; /* connection lookup table */ typedef struct s_connection_tag { EAS_U16 source; EAS_U16 control; EAS_U16 destination; EAS_U16 connection; } S_CONNECTION; static const S_CONNECTION connTable[] = { { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_LFO_FREQUENCY, PARAM_MOD_LFO_FREQ }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_LFO_STARTDELAY, PARAM_MOD_LFO_DELAY}, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_VIB_FREQUENCY, PARAM_VIB_LFO_FREQ }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_VIB_STARTDELAY, PARAM_VIB_LFO_DELAY }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_DELAYTIME, PARAM_VOL_EG_DELAY }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_ATTACKTIME, PARAM_VOL_EG_ATTACK }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_HOLDTIME, PARAM_VOL_EG_HOLD }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_DECAYTIME, PARAM_VOL_EG_DECAY }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_SUSTAINLEVEL, PARAM_VOL_EG_SUSTAIN }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_RELEASETIME, PARAM_VOL_EG_RELEASE }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG1_SHUTDOWNTIME, PARAM_VOL_EG_SHUTDOWN }, { CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_EG1_ATTACKTIME, PARAM_VOL_EG_VEL_TO_ATTACK }, { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_EG1_DECAYTIME, PARAM_VOL_EG_KEY_TO_DECAY }, { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_EG1_HOLDTIME, PARAM_VOL_EG_KEY_TO_HOLD }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_DELAYTIME, PARAM_MOD_EG_DELAY }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_ATTACKTIME, PARAM_MOD_EG_ATTACK }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_HOLDTIME, PARAM_MOD_EG_HOLD }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_DECAYTIME, PARAM_MOD_EG_DECAY }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_SUSTAINLEVEL, PARAM_MOD_EG_SUSTAIN }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_EG2_RELEASETIME, PARAM_MOD_EG_RELEASE }, { CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_EG2_ATTACKTIME, PARAM_MOD_EG_VEL_TO_ATTACK }, { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_EG2_DECAYTIME, PARAM_MOD_EG_KEY_TO_DECAY }, { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_EG2_HOLDTIME, PARAM_MOD_EG_KEY_TO_HOLD }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_INITIAL_FC }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_FILTER_Q, PARAM_INITIAL_Q }, { CONN_SRC_LFO, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_MOD_LFO_TO_FC }, { CONN_SRC_LFO, CONN_SRC_CC1, CONN_DST_FILTER_CUTOFF, PARAM_MOD_LFO_CC1_TO_FC }, { CONN_SRC_LFO, CONN_SRC_CHANNELPRESSURE, CONN_DST_FILTER_CUTOFF, PARAM_MOD_LFO_CHAN_PRESS_TO_FC }, { CONN_SRC_EG2, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_MOD_EG_TO_FC }, { CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_VEL_TO_FC }, { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_FILTER_CUTOFF, PARAM_KEYNUM_TO_FC }, { CONN_SRC_LFO, CONN_SRC_NONE, CONN_DST_GAIN, PARAM_MOD_LFO_TO_GAIN }, { CONN_SRC_LFO, CONN_SRC_CC1, CONN_DST_GAIN, PARAM_MOD_LFO_CC1_TO_GAIN }, { CONN_SRC_LFO, CONN_SRC_CHANNELPRESSURE, CONN_DST_GAIN, PARAM_MOD_LFO_CHAN_PRESS_TO_GAIN }, { CONN_SRC_KEYONVELOCITY, CONN_SRC_NONE, CONN_DST_GAIN, PARAM_VEL_TO_GAIN }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_TUNING }, { CONN_SRC_KEYNUMBER, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_KEYNUM_TO_PITCH }, { CONN_SRC_VIBRATO, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_VIB_LFO_TO_PITCH }, { CONN_SRC_VIBRATO, CONN_SRC_CC1, CONN_DST_PITCH, PARAM_VIB_LFO_CC1_TO_PITCH }, { CONN_SRC_VIBRATO, CONN_SRC_CHANNELPRESSURE, CONN_DST_PITCH, PARAM_VIB_LFO_CHAN_PRESS_TO_PITCH }, { CONN_SRC_LFO, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_MOD_LFO_TO_PITCH }, { CONN_SRC_LFO, CONN_SRC_CC1, CONN_DST_PITCH, PARAM_MOD_LFO_CC1_TO_PITCH }, { CONN_SRC_LFO, CONN_SRC_CHANNELPRESSURE, CONN_DST_PITCH, PARAM_MOD_LFO_CHAN_PRESS_TO_PITCH }, { CONN_SRC_EG2, CONN_SRC_NONE, CONN_DST_PITCH, PARAM_MOD_EG_TO_PITCH }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_PAN, PARAM_DEFAULT_PAN }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_REVERB, PARAM_DEFAULT_REVERB_SEND }, { CONN_SRC_CC91, CONN_SRC_NONE, CONN_DST_REVERB, PARAM_MIDI_CC91_TO_REVERB_SEND }, { CONN_SRC_NONE, CONN_SRC_NONE, CONN_DST_CHORUS, PARAM_DEFAULT_CHORUS_SEND }, { CONN_SRC_CC93, CONN_SRC_NONE, CONN_DST_REVERB, PARAM_MIDI_CC93_TO_CHORUS_SEND } }; #define ENTRIES_IN_CONN_TABLE (sizeof(connTable)/sizeof(S_CONNECTION)) static const S_DLS_ART_VALUES defaultArt = { 0, /* not modified */ -851, /* Mod LFO frequency: 5 Hz */ -7973, /* Mod LFO delay: 10 milliseconds */ -851, /* Vib LFO frequency: 5 Hz */ -7973, /* Vib LFO delay: 10 milliseconds */ -32768, /* EG1 delay time: 0 secs */ -32768, /* EG1 attack time: 0 secs */ -32768, /* EG1 hold time: 0 secs */ -32768, /* EG1 decay time: 0 secs */ 1000, /* EG1 sustain level: 100.0% */ -32768, /* EG1 release time: 0 secs */ -7271, /* EG1 shutdown time: 15 msecs */ 0, /* EG1 velocity to attack: 0 time cents */ 0, /* EG1 key number to decay: 0 time cents */ 0, /* EG1 key number to hold: 0 time cents */ -32768, /* EG2 delay time: 0 secs */ -32768, /* EG2 attack time: 0 secs */ -32768, /* EG2 hold time: 0 secs */ -32768, /* EG2 decay time: 0 secs */ 1000, /* EG2 sustain level: 100.0% */ -32768, /* EG2 release time: 0 secs */ 0, /* EG2 velocity to attack: 0 time cents */ 0, /* EG2 key number to decay: 0 time cents */ 0, /* EG2 key number to hold: 0 time cents */ 0x7fff, /* Initial Fc: Disabled */ 0, /* Initial Q: 0 dB */ 0, /* Mod LFO to Fc: 0 cents */ 0, /* Mod LFO CC1 to Fc: 0 cents */ 0, /* Mod LFO channel pressure to Fc: 0 cents */ 0, /* EG2 to Fc: 0 cents */ 0, /* Velocity to Fc: 0 cents */ 0, /* Key number to Fc: 0 cents */ 0, /* Mod LFO to gain: 0 dB */ 0, /* Mod LFO CC1 to gain: 0 dB */ 0, /* Mod LFO channel pressure to gain: 0 dB */ 960, /* Velocity to gain: 96 dB */ 0, /* Tuning: 0 cents */ 12800, /* Key number to pitch: 12,800 cents */ 0, /* Vibrato to pitch: 0 cents */ 0, /* Vibrato CC1 to pitch: 0 cents */ 0, /* Vibrato channel pressure to pitch: 0 cents */ 0, /* Mod LFO to pitch: 0 cents */ 0, /* Mod LFO CC1 to pitch: 0 cents */ 0, /* Mod LFO channel pressure to pitch: 0 cents */ 0, /* Mod EG to pitch: 0 cents */ 0, /* Default pan: 0.0% */ 0, /* Default reverb send: 0.0% */ 1000, /* Default CC91 to reverb send: 100.0% */ 0, /* Default chorus send: 0.0% */ 1000 /* Default CC93 to chorus send: 100.0% */ }; /*------------------------------------ * local variables *------------------------------------ */ #if defined(_8_BIT_SAMPLES) static const EAS_INT bitDepth = 8; #elif defined(_16_BIT_SAMPLES) static const EAS_INT bitDepth = 16; #else #error "Must define _8_BIT_SAMPLES or _16_BIT_SAMPLES" #endif static const EAS_U32 outputSampleRate = _OUTPUT_SAMPLE_RATE; static const EAS_I32 dlsRateConvert = DLS_RATE_CONVERT; static const EAS_I32 dlsLFOFrequencyConvert = DLS_LFO_FREQUENCY_CONVERT; /*------------------------------------ * inline functions *------------------------------------ */ EAS_INLINE void *PtrOfs (void *p, EAS_I32 offset) { return (void*) (((EAS_U8*) p) + offset); } /*------------------------------------ * prototypes *------------------------------------ */ static EAS_RESULT NextChunk (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 *pPos, EAS_U32 *pChunkType, EAS_I32 *pSize); static EAS_RESULT Parse_ptbl (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 wsmpPos, EAS_I32 wsmpSize); static EAS_RESULT Parse_wave (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U16 waveIndex); static EAS_RESULT Parse_wsmp (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_WSMP_DATA *p); static EAS_RESULT Parse_fmt (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_WSMP_DATA *p); static EAS_RESULT Parse_data (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, S_WSMP_DATA *p, EAS_SAMPLE *pSample, EAS_U32 sampleLen); static EAS_RESULT Parse_lins(SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size); static EAS_RESULT Parse_ins (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size); static EAS_RESULT Parse_insh (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U32 *pRgnCount, EAS_U32 *pLocale); static EAS_RESULT Parse_lrgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, EAS_U16 artIndex, EAS_U32 numRegions); static EAS_RESULT Parse_rgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, EAS_U16 artIndex); static EAS_RESULT Parse_rgnh (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_DLS_REGION *pRgn); static EAS_RESULT Parse_lart (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, S_DLS_ART_VALUES *pArt); static EAS_RESULT Parse_art (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_DLS_ART_VALUES *pArt); static EAS_RESULT Parse_wlnk (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U32 *pWaveIndex); static EAS_RESULT Parse_cdl (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 size, EAS_U32 *pValue); static void Convert_rgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_U16 regionIndex, EAS_U16 artIndex, EAS_U16 waveIndex, S_WSMP_DATA *pWsmp); static void Convert_art (SDLS_SYNTHESIZER_DATA *pDLSData, const S_DLS_ART_VALUES *pDLSArt, EAS_U16 artIndex); static EAS_I16 ConvertSampleRate (EAS_U32 sampleRate); static EAS_I16 ConvertSustain (EAS_I32 sustain); static EAS_I16 ConvertLFOPhaseIncrement (EAS_I32 pitchCents); static EAS_I8 ConvertPan (EAS_I32 pan); static EAS_U8 ConvertQ (EAS_I32 q); #ifdef _DEBUG_DLS static void DumpDLS (S_EAS *pEAS); #endif /*---------------------------------------------------------------------------- * DLSParser () *---------------------------------------------------------------------------- * Purpose: * * Inputs: * pEASData - pointer to over EAS data instance * fileHandle - file handle for input file * offset - offset into file where DLS data starts * * Outputs: * EAS_RESULT * ppEAS - address of pointer to alternate EAS wavetable * *---------------------------------------------------------------------------- */ EAS_RESULT DLSParser (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE fileHandle, EAS_I32 offset, EAS_DLSLIB_HANDLE *ppDLS) { EAS_RESULT result; SDLS_SYNTHESIZER_DATA dls; EAS_U32 temp; EAS_I32 pos; EAS_I32 chunkPos; EAS_I32 size; EAS_I32 instSize; EAS_I32 rgnPoolSize; EAS_I32 artPoolSize; EAS_I32 waveLenSize; EAS_I32 endDLS; EAS_I32 wvplPos; EAS_I32 wvplSize; EAS_I32 linsPos; EAS_I32 linsSize; EAS_I32 ptblPos; EAS_I32 ptblSize; void *p; /* zero counts and pointers */ EAS_HWMemSet(&dls, 0, sizeof(dls)); /* save file handle and hwInstData to save copying pointers around */ dls.hwInstData = hwInstData; dls.fileHandle = fileHandle; /* NULL return value in case of error */ *ppDLS = NULL; /* seek to start of DLS and read in RIFF tag and set processor endian flag */ if ((result = EAS_HWFileSeek(dls.hwInstData, dls.fileHandle, offset)) != EAS_SUCCESS) return result; if ((result = EAS_HWReadFile(dls.hwInstData, dls.fileHandle, &temp, sizeof(temp), &size)) != EAS_SUCCESS) return result; /* check for processor endian-ness */ dls.bigEndian = (temp == CHUNK_RIFF); /* first chunk should be DLS */ pos = offset; if ((result = NextChunk(&dls, &pos, &temp, &size)) != EAS_SUCCESS) return result; if (temp != CHUNK_DLS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Expected DLS chunk, got %08lx\n", temp); */ } return EAS_ERROR_FILE_FORMAT; } /* no instrument or wavepool chunks */ linsSize = wvplSize = ptblSize = linsPos = wvplPos = ptblPos = 0; /* scan the chunks in the DLS list */ endDLS = offset + size; pos = offset + 12; while (pos < endDLS) { chunkPos = pos; /* get the next chunk type */ if ((result = NextChunk(&dls, &pos, &temp, &size)) != EAS_SUCCESS) return result; /* parse useful chunks */ switch (temp) { case CHUNK_CDL: if ((result = Parse_cdl(&dls, size, &temp)) != EAS_SUCCESS) return result; if (!temp) return EAS_ERROR_UNRECOGNIZED_FORMAT; break; case CHUNK_LINS: linsPos = chunkPos + 12; linsSize = size - 4; break; case CHUNK_WVPL: wvplPos = chunkPos + 12; wvplSize = size - 4; break; case CHUNK_PTBL: ptblPos = chunkPos + 8; ptblSize = size - 4; break; default: break; } } /* must have a lins chunk */ if (linsSize == 0) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No lins chunk found"); */ } return EAS_ERROR_UNRECOGNIZED_FORMAT; } /* must have a wvpl chunk */ if (wvplSize == 0) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No wvpl chunk found"); */ } return EAS_ERROR_UNRECOGNIZED_FORMAT; } /* must have a ptbl chunk */ if ((ptblSize == 0) || (ptblSize > DLS_MAX_WAVE_COUNT * sizeof(POOLCUE) + sizeof(POOLTABLE))) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No ptbl chunk found"); */ } return EAS_ERROR_UNRECOGNIZED_FORMAT; } /* pre-parse the wave pool chunk */ if ((result = Parse_ptbl(&dls, ptblPos, wvplPos, wvplSize)) != EAS_SUCCESS) return result; /* limit check */ if ((dls.waveCount == 0) || (dls.waveCount > DLS_MAX_WAVE_COUNT)) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #waves [%u]\n", dls.waveCount); */ } return EAS_ERROR_FILE_FORMAT; } /* allocate memory for wsmp data */ dls.wsmpData = EAS_HWMalloc(dls.hwInstData, (EAS_I32) (sizeof(S_WSMP_DATA) * dls.waveCount)); if (dls.wsmpData == NULL) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWMalloc for wsmp data failed\n"); */ } return EAS_ERROR_MALLOC_FAILED; } EAS_HWMemSet(dls.wsmpData, 0, (EAS_I32) (sizeof(S_WSMP_DATA) * dls.waveCount)); /* pre-parse the lins chunk */ result = Parse_lins(&dls, linsPos, linsSize); if (result == EAS_SUCCESS) { /* limit check */ if ((dls.regionCount == 0) || (dls.regionCount > DLS_MAX_REGION_COUNT)) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #regions [%u]\n", dls.regionCount); */ } return EAS_ERROR_FILE_FORMAT; } /* limit check */ if ((dls.artCount == 0) || (dls.artCount > DLS_MAX_ART_COUNT)) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #articulations [%u]\n", dls.regionCount); */ } return EAS_ERROR_FILE_FORMAT; } /* limit check */ if ((dls.instCount == 0) || (dls.instCount > DLS_MAX_INST_COUNT)) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS file contains invalid #instruments [%u]\n", dls.instCount); */ } return EAS_ERROR_FILE_FORMAT; } /* Allocate memory for the converted DLS data */ /* calculate size of instrument data */ instSize = (EAS_I32) (sizeof(S_PROGRAM) * dls.instCount); /* calculate size of region pool */ rgnPoolSize = (EAS_I32) (sizeof(S_DLS_REGION) * dls.regionCount); /* calculate size of articulation pool, add one for default articulation */ dls.artCount++; artPoolSize = (EAS_I32) (sizeof(S_DLS_ARTICULATION) * dls.artCount); /* calculate size of wave length and offset arrays */ waveLenSize = (EAS_I32) (dls.waveCount * sizeof(EAS_U32)); /* calculate final memory size */ size = (EAS_I32) sizeof(S_EAS) + instSize + rgnPoolSize + artPoolSize + (2 * waveLenSize) + (EAS_I32) dls.wavePoolSize; if (size <= 0) { return EAS_ERROR_FILE_FORMAT; } /* allocate the main EAS chunk */ dls.pDLS = EAS_HWMalloc(dls.hwInstData, size); if (dls.pDLS == NULL) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_HWMalloc failed for DLS memory allocation size %ld\n", size); */ } return EAS_ERROR_MALLOC_FAILED; } EAS_HWMemSet(dls.pDLS, 0, size); dls.pDLS->refCount = 1; p = PtrOfs(dls.pDLS, sizeof(S_EAS)); /* setup pointer to programs */ dls.pDLS->numDLSPrograms = (EAS_U16) dls.instCount; dls.pDLS->pDLSPrograms = p; p = PtrOfs(p, instSize); /* setup pointer to regions */ dls.pDLS->pDLSRegions = p; dls.pDLS->numDLSRegions = (EAS_U16) dls.regionCount; p = PtrOfs(p, rgnPoolSize); /* setup pointer to articulations */ dls.pDLS->numDLSArticulations = (EAS_U16) dls.artCount; dls.pDLS->pDLSArticulations = p; p = PtrOfs(p, artPoolSize); /* setup pointer to wave length table */ dls.pDLS->numDLSSamples = (EAS_U16) dls.waveCount; dls.pDLS->pDLSSampleLen = p; p = PtrOfs(p, waveLenSize); /* setup pointer to wave offsets table */ dls.pDLS->pDLSSampleOffsets = p; p = PtrOfs(p, waveLenSize); /* setup pointer to wave pool */ dls.pDLS->pDLSSamples = p; /* clear filter flag */ dls.filterUsed = EAS_FALSE; /* parse the wave pool and load samples */ result = Parse_ptbl(&dls, ptblPos, wvplPos, wvplSize); } /* create the default articulation */ Convert_art(&dls, &defaultArt, 0); dls.artCount = 1; /* parse the lins chunk and load instruments */ dls.regionCount = dls.instCount = 0; if (result == EAS_SUCCESS) result = Parse_lins(&dls, linsPos, linsSize); /* clean up any temporary objects that were allocated */ if (dls.wsmpData) EAS_HWFree(dls.hwInstData, dls.wsmpData); /* if successful, return a pointer to the EAS collection */ if (result == EAS_SUCCESS) { *ppDLS = dls.pDLS; #ifdef _DEBUG_DLS DumpDLS(dls.pDLS); #endif } /* something went wrong, deallocate the EAS collection */ else DLSCleanup(dls.hwInstData, dls.pDLS); return result; } /*---------------------------------------------------------------------------- * DLSCleanup () *---------------------------------------------------------------------------- * Purpose: * * Inputs: * pEASData - pointer to over EAS data instance * pEAS - pointer to alternate EAS wavetable * * Outputs: * EAS_RESULT * *---------------------------------------------------------------------------- */ EAS_RESULT DLSCleanup (EAS_HW_DATA_HANDLE hwInstData, S_DLS *pDLS) { /* free the allocated memory */ if (pDLS) { if (pDLS->refCount) { if (--pDLS->refCount == 0) EAS_HWFree(hwInstData, pDLS); } } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * DLSAddRef () *---------------------------------------------------------------------------- * Increment reference count *---------------------------------------------------------------------------- */ void DLSAddRef (S_DLS *pDLS) { if (pDLS) pDLS->refCount++; } /*---------------------------------------------------------------------------- * NextChunk () *---------------------------------------------------------------------------- * Purpose: * Returns the type and size of the next chunk in the file * * Inputs: * * Outputs: * * Side Effects: *---------------------------------------------------------------------------- */ static EAS_RESULT NextChunk (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 *pPos, EAS_U32 *pChunkType, EAS_I32 *pSize) { EAS_RESULT result; /* seek to start of chunk */ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, *pPos)) != EAS_SUCCESS) return result; /* read the chunk type */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, pChunkType, EAS_TRUE)) != EAS_SUCCESS) return result; /* read the chunk size */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, pSize, EAS_FALSE)) != EAS_SUCCESS) return result; /* get form type for RIFF and LIST types */ if ((*pChunkType == CHUNK_RIFF) || (*pChunkType == CHUNK_LIST)) { /* read the form type */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, pChunkType, EAS_TRUE)) != EAS_SUCCESS) return result; } /* calculate start of next chunk */ *pPos += *pSize + 8; /* adjust to word boundary */ if (*pPos & 1) (*pPos)++; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * Parse_ptbl () *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT Parse_ptbl (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 wtblPos, EAS_I32 wtblSize) { EAS_RESULT result; EAS_U32 temp; EAS_FILE_HANDLE tempFile; EAS_U16 waveIndex; /* seek to start of chunk */ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) return result; /* get the structure size */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &temp, EAS_FALSE)) != EAS_SUCCESS) return result; /* get the number of waves */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &pDLSData->waveCount, EAS_FALSE)) != EAS_SUCCESS) return result; #if 0 /* just need the wave count on the first pass */ if (!pDLSData->pDLS) return EAS_SUCCESS; #endif /* open duplicate file handle */ if ((result = EAS_HWDupHandle(pDLSData->hwInstData, pDLSData->fileHandle, &tempFile)) != EAS_SUCCESS) return result; /* read to end of chunk */ for (waveIndex = 0; waveIndex < pDLSData->waveCount; waveIndex++) { /* get the offset to the wave and make sure it is within the wtbl chunk */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, tempFile, &temp, EAS_FALSE)) != EAS_SUCCESS) return result; if (temp > (EAS_U32) wtblSize) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Ptbl offset exceeds size of wtbl\n"); */ } EAS_HWCloseFile(pDLSData->hwInstData, tempFile); return EAS_ERROR_FILE_FORMAT; } /* parse the wave */ if ((result = Parse_wave(pDLSData, wtblPos +(EAS_I32) temp, waveIndex)) != EAS_SUCCESS) return result; } /* close the temporary handle and return */ EAS_HWCloseFile(pDLSData->hwInstData, tempFile); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * Parse_wave () *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT Parse_wave (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U16 waveIndex) { EAS_RESULT result; EAS_U32 temp; EAS_I32 size; EAS_I32 endChunk; EAS_I32 chunkPos; EAS_I32 wsmpPos = 0; EAS_I32 fmtPos = 0; EAS_I32 dataPos = 0; EAS_I32 dataSize = 0; S_WSMP_DATA *p; void *pSample; S_WSMP_DATA wsmp; /* seek to start of chunk */ chunkPos = pos + 12; if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) return result; /* get the chunk type */ if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS) return result; /* make sure it is a wave chunk */ if (temp != CHUNK_WAVE) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Offset in ptbl does not point to wave chunk\n"); */ } return EAS_ERROR_FILE_FORMAT; } /* read to end of chunk */ pos = chunkPos; endChunk = pos + size; while (pos < endChunk) { chunkPos = pos; /* get the chunk type */ if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS) return result; /* parse useful chunks */ switch (temp) { case CHUNK_WSMP: wsmpPos = chunkPos + 8; break; case CHUNK_FMT: fmtPos = chunkPos + 8; break; case CHUNK_DATA: dataPos = chunkPos + 8; dataSize = size; break; default: break; } } // limit to reasonable size if (dataSize < 0 || dataSize > MAX_DLS_WAVE_SIZE) { return EAS_ERROR_SOUND_LIBRARY; } /* for first pass, use temporary variable */ if (pDLSData->pDLS == NULL) p = &wsmp; else p = &pDLSData->wsmpData[waveIndex]; /* set the defaults */ p->fineTune = 0; p->unityNote = 60; p->gain = 0; p->loopStart = 0; p->loopLength = 0; /* must have a fmt chunk */ if (!fmtPos) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS wave chunk has no fmt chunk\n"); */ } return EAS_ERROR_UNRECOGNIZED_FORMAT; } /* must have a data chunk */ if (!dataPos) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS wave chunk has no data chunk\n"); */ } return EAS_ERROR_UNRECOGNIZED_FORMAT; } /* parse the wsmp chunk */ if (wsmpPos) { if ((result = Parse_wsmp(pDLSData, wsmpPos, p)) != EAS_SUCCESS) return result; } /* parse the fmt chunk */ if ((result = Parse_fmt(pDLSData, fmtPos, p)) != EAS_SUCCESS) return result; /* calculate the size of the wavetable needed. We need only half * the memory for 16-bit samples when in 8-bit mode, and we need * double the memory for 8-bit samples in 16-bit mode. For * unlooped samples, we may use ADPCM. If so, we need only 1/4 * the memory. * * We also need to add one for looped samples to allow for * the first sample to be copied to the end of the loop. */ /* use ADPCM encode for unlooped 16-bit samples if ADPCM is enabled */ /*lint -e{506} -e{774} groundwork for future version to support 8 & 16 bit */ if (bitDepth == 8) { if (p->bitsPerSample == 8) size = dataSize; else /*lint -e{704} use shift for performance */ size = dataSize >> 1; if (p->loopLength) size++; } else { if (p->bitsPerSample == 16) size = dataSize; else /*lint -e{703} use shift for performance */ size = dataSize << 1; if (p->loopLength) size += 2; } /* for first pass, add size to wave pool size and return */ if (pDLSData->pDLS == NULL) { pDLSData->wavePoolSize += (EAS_U32) size; return EAS_SUCCESS; } /* allocate memory and read in the sample data */ pSample = (EAS_U8*)pDLSData->pDLS->pDLSSamples + pDLSData->wavePoolOffset; pDLSData->pDLS->pDLSSampleOffsets[waveIndex] = pDLSData->wavePoolOffset; pDLSData->pDLS->pDLSSampleLen[waveIndex] = (EAS_U32) size; pDLSData->wavePoolOffset += (EAS_U32) size; if (pDLSData->wavePoolOffset > pDLSData->wavePoolSize) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Wave pool exceeded allocation\n"); */ } return EAS_ERROR_SOUND_LIBRARY; } if ((result = Parse_data(pDLSData, dataPos, dataSize, p, pSample, (EAS_U32)size)) != EAS_SUCCESS) return result; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * Parse_wsmp () *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT Parse_wsmp (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_WSMP_DATA *p) { EAS_RESULT result; EAS_U16 wtemp; EAS_U32 ltemp; EAS_U32 cbSize; /* seek to start of chunk */ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) return result; /* get structure size */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &cbSize, EAS_FALSE)) != EAS_SUCCESS) return result; /* get unity note */ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &wtemp, EAS_FALSE)) != EAS_SUCCESS) return result; if (wtemp <= 127) p->unityNote = (EAS_U8) wtemp; else { p->unityNote = 60; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid unity note [%u] in DLS wsmp ignored, set to 60\n", wtemp); */ } } /* get fine tune */ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->fineTune, EAS_FALSE)) != EAS_SUCCESS) return result; /* get gain */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->gain, EAS_FALSE)) != EAS_SUCCESS) return result; if (p->gain > 0) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Positive gain [%ld] in DLS wsmp ignored, set to 0dB\n", p->gain); */ } p->gain = 0; } /* option flags */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, <emp, EAS_FALSE)) != EAS_SUCCESS) return result; /* sample loops */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, <emp, EAS_FALSE)) != EAS_SUCCESS) return result; /* if looped sample, get loop data */ if (ltemp) { if (ltemp > 1) { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS sample with %lu loops, ignoring extra loops\n", ltemp); */ } /* skip ahead to loop data */ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos + (EAS_I32) cbSize)) != EAS_SUCCESS) return result; /* get structure size */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, <emp, EAS_FALSE)) != EAS_SUCCESS) return result; /* get loop type */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, <emp, EAS_FALSE)) != EAS_SUCCESS) return result; /* get loop start */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->loopStart, EAS_FALSE)) != EAS_SUCCESS) return result; /* get loop length */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->loopLength, EAS_FALSE)) != EAS_SUCCESS) return result; /* ensure no overflow */ if (p->loopLength && ((p->loopStart > EAS_U32_MAX - p->loopLength) || (p->loopStart + p->loopLength > EAS_U32_MAX / sizeof(EAS_SAMPLE)))) { return EAS_FAILURE; } } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * Parse_fmt () *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT Parse_fmt (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_WSMP_DATA *p) { EAS_RESULT result; EAS_U16 wtemp; EAS_U32 ltemp; /* seek to start of chunk */ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) return result; /* get format tag */ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &wtemp, EAS_FALSE)) != EAS_SUCCESS) return result; if (wtemp != WAVE_FORMAT_PCM) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unsupported DLS sample format %04x\n", wtemp); */ } return EAS_ERROR_UNRECOGNIZED_FORMAT; } /* get number of channels */ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &wtemp, EAS_FALSE)) != EAS_SUCCESS) return result; if (wtemp != 1) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "No support for DLS multi-channel samples\n"); */ } return EAS_ERROR_UNRECOGNIZED_FORMAT; } /* get sample rate */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->sampleRate, EAS_FALSE)) != EAS_SUCCESS) return result; /* bytes/sec */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, <emp, EAS_FALSE)) != EAS_SUCCESS) return result; /* block align */ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &wtemp, EAS_FALSE)) != EAS_SUCCESS) return result; /* bits/sample */ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &p->bitsPerSample, EAS_FALSE)) != EAS_SUCCESS) return result; if ((p->bitsPerSample != 8) && (p->bitsPerSample != 16)) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unsupported DLS bits-per-sample %d\n", p->bitsPerSample); */ } return EAS_ERROR_UNRECOGNIZED_FORMAT; } return EAS_SUCCESS; } #if defined( _8_BIT_SAMPLES) /*---------------------------------------------------------------------------- * Parse_data () *---------------------------------------------------------------------------- * Purpose: * * NOTE: The optimized assembly versions of the interpolator require * an extra sample at the end of the loop - a copy of the first * sample. This routine must allocate an extra sample of data and * copy the first sample of the loop to the end. * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT Parse_data (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, S_WSMP_DATA *pWsmp, EAS_SAMPLE *pSample, EAS_U32 sampleLen) { EAS_RESULT result; EAS_U8 convBuf[SAMPLE_CONVERT_CHUNK_SIZE]; EAS_I32 count; EAS_I32 i; EAS_I8 *p; /* seek to start of chunk */ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) return result; /* 8-bit samples in an 8-bit synth, just copy the data, and flip bit 7 */ p = pSample; if (pWsmp->bitsPerSample == 8) { if ((result = EAS_HWReadFile(pDLSData->hwInstData, pDLSData->fileHandle, pSample, size, &count)) != EAS_SUCCESS) return result; for (i = 0; i < size; i++) /*lint -e{734} convert from unsigned to signed audio */ *p++ ^= 0x80; } /* 16-bit samples, need to convert to 8-bit or ADPCM */ else { while (size) { EAS_I8 *pInput; /* for undithered conversion, we're just copying the 8-bit data */ if (pDLSData->bigEndian) pInput = (EAS_I8*) convBuf; else pInput = (EAS_I8*) convBuf + 1; /* read a small chunk of data and convert it */ count = (size < SAMPLE_CONVERT_CHUNK_SIZE ? size : SAMPLE_CONVERT_CHUNK_SIZE); if ((result = EAS_HWReadFile(pDLSData->hwInstData, pDLSData->fileHandle, convBuf, count, &count)) != EAS_SUCCESS) return result; size -= count; /*lint -e{704} use shift for performance */ count = count >> 1; while (count--) { *p++ = *pInput; pInput += 2; } } } /* for looped samples, copy the last sample to the end */ if (pWsmp->loopLength) { if (sampleLen < sizeof(EAS_SAMPLE) || (pWsmp->loopStart + pWsmp->loopLength) * sizeof(EAS_SAMPLE) > sampleLen - sizeof(EAS_SAMPLE)) { return EAS_FAILURE; } pSample[pWsmp->loopStart + pWsmp->loopLength] = pSample[pWsmp->loopStart]; } return EAS_SUCCESS; } #elif defined(_16_BIT_SAMPLES) #error "16-bit DLS conversion not implemented yet" #else #error "Must specifiy _8_BIT_SAMPLES or _16_BIT_SAMPLES" #endif /*---------------------------------------------------------------------------- * Parse_lins () *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT Parse_lins (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size) { EAS_RESULT result; EAS_U32 temp; EAS_I32 endChunk; EAS_I32 chunkPos; /* seek to start of chunk */ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) return result; /* read to end of chunk */ endChunk = pos + size; while (pos < endChunk) { chunkPos = pos; /* get the next chunk type */ if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS) return result; /* only instrument chunks are useful */ if (temp != CHUNK_INS) continue; if ((result = Parse_ins(pDLSData, chunkPos + 12, size)) != EAS_SUCCESS) return result; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * Parse_ins () *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT Parse_ins (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size) { EAS_RESULT result; EAS_U32 temp; EAS_I32 chunkPos; EAS_I32 endChunk; EAS_I32 lrgnPos; EAS_I32 lrgnSize; EAS_I32 lartPos; EAS_I32 lartSize; EAS_I32 lar2Pos; EAS_I32 lar2Size; EAS_I32 inshPos; EAS_U32 regionCount; EAS_U32 locale; S_DLS_ART_VALUES art; S_PROGRAM *pProgram; EAS_U16 artIndex; /* seek to start of chunk */ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) return result; /* no chunks yet */ lrgnPos = lrgnSize = lartPos = lartSize = lar2Pos = lar2Size = inshPos = artIndex = 0; /* read to end of chunk */ endChunk = pos + size; while (pos < endChunk) { chunkPos = pos; /* get the next chunk type */ if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS) return result; /* parse useful chunks */ switch (temp) { case CHUNK_INSH: inshPos = chunkPos + 8; break; case CHUNK_LART: lartPos = chunkPos + 12; lartSize = size; break; case CHUNK_LAR2: lar2Pos = chunkPos + 12; lar2Size = size; break; case CHUNK_LRGN: lrgnPos = chunkPos + 12; lrgnSize = size; break; default: break; } } /* must have an lrgn to be useful */ if (!lrgnPos) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS ins chunk has no lrgn chunk\n"); */ } return EAS_ERROR_UNRECOGNIZED_FORMAT; } /* must have an insh to be useful */ if (!inshPos) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS ins chunk has no insh chunk\n"); */ } return EAS_ERROR_UNRECOGNIZED_FORMAT; } /* parse the instrument header */ if ((result = Parse_insh(pDLSData, inshPos, ®ionCount, &locale)) != EAS_SUCCESS) return result; /* initialize and parse the global data first */ EAS_HWMemCpy(&art, &defaultArt, sizeof(S_DLS_ART_VALUES)); if (lartPos) if ((result = Parse_lart(pDLSData, lartPos, lartSize, &art)) != EAS_SUCCESS) return result; if (lar2Pos) if ((result = Parse_lart(pDLSData, lar2Pos, lar2Size, &art)) != EAS_SUCCESS) return result; if (art.values[PARAM_MODIFIED]) { artIndex = (EAS_U16) pDLSData->artCount; pDLSData->artCount++; } /* convert data on second pass */ if (pDLSData->pDLS) { if (art.values[PARAM_MODIFIED]) Convert_art(pDLSData, &art, artIndex); /* setup pointers */ pProgram = &pDLSData->pDLS->pDLSPrograms[pDLSData->instCount]; /* initialize instrument */ pProgram->locale = locale; pProgram->regionIndex = (EAS_U16) pDLSData->regionCount | FLAG_RGN_IDX_DLS_SYNTH; } /* parse the region data */ if ((result = Parse_lrgn(pDLSData, lrgnPos, lrgnSize, artIndex, regionCount)) != EAS_SUCCESS) return result; /* bump instrument count */ pDLSData->instCount++; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * Parse_insh () *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT Parse_insh (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U32 *pRgnCount, EAS_U32 *pLocale) { EAS_RESULT result; EAS_U32 bank; EAS_U32 program; /* seek to start of chunk */ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) return result; /* get the region count and locale */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, pRgnCount, EAS_FALSE)) != EAS_SUCCESS) return result; if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &bank, EAS_FALSE)) != EAS_SUCCESS) return result; if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &program, EAS_FALSE)) != EAS_SUCCESS) return result; /* verify the parameters are valid */ if (bank & 0x7fff8080) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS bank number is out of range: %08lx\n", bank); */ } bank &= 0xff7f; } if (program > 127) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS program number is out of range: %08lx\n", program); */ } program &= 0x7f; } /* save the program number */ *pLocale = (bank << 8) | program; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * Parse_lrgn () *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT Parse_lrgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, EAS_U16 artIndex, EAS_U32 numRegions) { EAS_RESULT result; EAS_U32 temp; EAS_I32 chunkPos; EAS_I32 endChunk; EAS_U16 regionCount; /* seek to start of chunk */ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) return result; /* read to end of chunk */ regionCount = 0; endChunk = pos + size; while (pos < endChunk) { chunkPos = pos; /* get the next chunk type */ if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS) return result; if ((temp == CHUNK_RGN) || (temp == CHUNK_RGN2)) { if (regionCount == numRegions) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS region count exceeded cRegions value in insh, extra region ignored\n"); */ } return EAS_SUCCESS; } if ((result = Parse_rgn(pDLSData, chunkPos + 12, size, artIndex)) != EAS_SUCCESS) return result; regionCount++; } } /* set a flag in the last region */ if ((pDLSData->pDLS != NULL) && (regionCount > 0)) pDLSData->pDLS->pDLSRegions[pDLSData->regionCount - 1].wtRegion.region.keyGroupAndFlags |= REGION_FLAG_LAST_REGION; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * Parse_rgn () *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT Parse_rgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, EAS_U16 artIndex) { EAS_RESULT result; EAS_U32 temp; EAS_I32 chunkPos; EAS_I32 endChunk; EAS_I32 rgnhPos; EAS_I32 lartPos; EAS_I32 lartSize; EAS_I32 lar2Pos; EAS_I32 lar2Size; EAS_I32 wlnkPos; EAS_I32 wsmpPos; EAS_U32 waveIndex; S_DLS_ART_VALUES art; S_WSMP_DATA wsmp; S_WSMP_DATA *pWsmp; EAS_U16 regionIndex; /* seek to start of chunk */ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) return result; /* no chunks found yet */ rgnhPos = lartPos = lartSize = lar2Pos = lar2Size = wsmpPos = wlnkPos = 0; regionIndex = (EAS_U16) pDLSData->regionCount; /* read to end of chunk */ endChunk = pos + size; while (pos < endChunk) { chunkPos = pos; /* get the next chunk type */ if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS) return result; /* parse useful chunks */ switch (temp) { case CHUNK_CDL: if ((result = Parse_cdl(pDLSData, size, &temp)) != EAS_SUCCESS) return result; /* if conditional chunk evaluates false, skip this list */ if (!temp) return EAS_SUCCESS; break; case CHUNK_RGNH: rgnhPos = chunkPos + 8; break; case CHUNK_WLNK: wlnkPos = chunkPos + 8; break; case CHUNK_WSMP: wsmpPos = chunkPos + 8; break; case CHUNK_LART: lartPos = chunkPos + 12; lartSize = size; break; case CHUNK_LAR2: lar2Pos = chunkPos + 12; lar2Size = size; break; default: break; } } /* must have a rgnh chunk to be useful */ if (!rgnhPos) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS rgn chunk has no rgnh chunk\n"); */ } return EAS_ERROR_UNRECOGNIZED_FORMAT; } /* must have a wlnk chunk to be useful */ if (!wlnkPos) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "DLS rgn chunk has no wlnk chunk\n"); */ } return EAS_ERROR_UNRECOGNIZED_FORMAT; } /* parse wlnk chunk */ if ((result = Parse_wlnk(pDLSData, wlnkPos, &waveIndex)) != EAS_SUCCESS) return result; if (waveIndex >= pDLSData->waveCount) { return EAS_FAILURE; } pWsmp = &pDLSData->wsmpData[waveIndex]; /* if there is any articulation data, parse it */ EAS_HWMemCpy(&art, &defaultArt, sizeof(S_DLS_ART_VALUES)); if (lartPos) { if ((result = Parse_lart(pDLSData, lartPos, lartSize, &art)) != EAS_SUCCESS) return result; } if (lar2Pos) { if ((result = Parse_lart(pDLSData, lar2Pos, lar2Size, &art)) != EAS_SUCCESS) return result; } /* if second pass, process region header */ if (pDLSData->pDLS) { /* if local data was found convert it */ if (art.values[PARAM_MODIFIED] == EAS_TRUE) { Convert_art(pDLSData, &art, (EAS_U16) pDLSData->artCount); artIndex = (EAS_U16) pDLSData->artCount; } /* parse region header */ if ((result = Parse_rgnh(pDLSData, rgnhPos, &pDLSData->pDLS->pDLSRegions[regionIndex & REGION_INDEX_MASK])) != EAS_SUCCESS) return result; /* parse wsmp chunk, copying parameters from original first */ if (wsmpPos) { EAS_HWMemCpy(&wsmp, pWsmp, sizeof(wsmp)); if ((result = Parse_wsmp(pDLSData, wsmpPos, &wsmp)) != EAS_SUCCESS) return result; pWsmp = &wsmp; } Convert_rgn(pDLSData, regionIndex, artIndex, (EAS_U16) waveIndex, pWsmp); /* ensure loopStart and loopEnd fall in the range */ if (pWsmp->loopLength != 0) { EAS_U32 sampleLen = pDLSData->pDLS->pDLSSampleLen[waveIndex]; if (sampleLen < sizeof(EAS_SAMPLE) || (pWsmp->loopStart + pWsmp->loopLength) * sizeof(EAS_SAMPLE) > sampleLen - sizeof(EAS_SAMPLE)) { return EAS_FAILURE; } } } /* if local articulation, bump count */ if (art.values[PARAM_MODIFIED]) pDLSData->artCount++; /* increment region count */ pDLSData->regionCount++; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * Parse_rgnh () *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT Parse_rgnh (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_DLS_REGION *pRgn) { EAS_RESULT result; EAS_U16 lowKey; EAS_U16 highKey; EAS_U16 lowVel; EAS_U16 highVel; EAS_U16 optionFlags; EAS_U16 keyGroup; /* seek to start of chunk */ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) return result; /* get the key range */ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &lowKey, EAS_FALSE)) != EAS_SUCCESS) return result; if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &highKey, EAS_FALSE)) != EAS_SUCCESS) return result; /* check the range */ if (lowKey > 127) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS rgnh: Low key out of range [%u]\n", lowKey); */ } lowKey = 127; } if (highKey > 127) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS rgnh: High key out of range [%u]\n", lowKey); */ } highKey = 127; } /* get the velocity range */ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &lowVel, EAS_FALSE)) != EAS_SUCCESS) return result; if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &highVel, EAS_FALSE)) != EAS_SUCCESS) return result; /* check the range */ if (lowVel > 127) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS rgnh: Low velocity out of range [%u]\n", lowVel); */ } lowVel = 127; } if (highVel > 127) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "DLS rgnh: High velocity out of range [%u]\n", highVel); */ } highVel = 127; } /* get the option flags */ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &optionFlags, EAS_FALSE)) != EAS_SUCCESS) return result; /* get the key group */ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &keyGroup, EAS_FALSE)) != EAS_SUCCESS) return result; /* save the key range and key group */ pRgn->wtRegion.region.rangeLow = (EAS_U8) lowKey; pRgn->wtRegion.region.rangeHigh = (EAS_U8) highKey; /*lint -e{734} keyGroup will always be from 0-15 */ pRgn->wtRegion.region.keyGroupAndFlags = keyGroup << 8; pRgn->velLow = (EAS_U8) lowVel; pRgn->velHigh = (EAS_U8) highVel; if (optionFlags & F_RGN_OPTION_SELFNONEXCLUSIVE) pRgn->wtRegion.region.keyGroupAndFlags |= REGION_FLAG_NON_SELF_EXCLUSIVE; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * Parse_lart () *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT Parse_lart (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_I32 size, S_DLS_ART_VALUES *pArt) { EAS_RESULT result; EAS_U32 temp; EAS_I32 endChunk; EAS_I32 chunkPos; EAS_I32 art1Pos; EAS_I32 art2Pos; /* seek to start of chunk */ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) return result; /* no articulation chunks yet */ art1Pos = art2Pos = 0; /* read to end of chunk */ endChunk = pos + size; while (pos < endChunk) { chunkPos = pos; /* get the next chunk type */ if ((result = NextChunk(pDLSData, &pos, &temp, &size)) != EAS_SUCCESS) return result; /* parse useful chunks */ switch (temp) { case CHUNK_CDL: if ((result = Parse_cdl(pDLSData, size, &temp)) != EAS_SUCCESS) return result; /* if conditional chunk evaluates false, skip this list */ if (!temp) return EAS_SUCCESS; break; case CHUNK_ART1: art1Pos = chunkPos + 8; break; case CHUNK_ART2: art2Pos = chunkPos + 8; break; default: break; } } if (art1Pos) { if ((result = Parse_art(pDLSData, art1Pos, pArt)) != EAS_SUCCESS) return result; } if (art2Pos) { if ((result = Parse_art(pDLSData, art2Pos, pArt)) != EAS_SUCCESS) return result; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * Parse_art() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT Parse_art (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, S_DLS_ART_VALUES *pArt) { EAS_RESULT result; EAS_U32 structSize; EAS_U32 numConnections; EAS_U16 source; EAS_U16 control; EAS_U16 destination; EAS_U16 transform; EAS_I32 scale; EAS_INT i; /* seek to start of data */ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) return result; /* get the structure size */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &structSize, EAS_FALSE)) != EAS_SUCCESS) return result; pos += (EAS_I32) structSize; /* get the number of connections */ if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &numConnections, EAS_FALSE)) != EAS_SUCCESS) return result; /* skip to start of connections */ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos)) != EAS_SUCCESS) return result; while (numConnections--) { /* read the connection data */ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &source, EAS_FALSE)) != EAS_SUCCESS) return result; if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &control, EAS_FALSE)) != EAS_SUCCESS) return result; if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &destination, EAS_FALSE)) != EAS_SUCCESS) return result; if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &transform, EAS_FALSE)) != EAS_SUCCESS) return result; if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &scale, EAS_FALSE)) != EAS_SUCCESS) return result; /* look up the connection */ for (i = 0; i < (EAS_INT) ENTRIES_IN_CONN_TABLE; i++) { if ((connTable[i].source == source) && (connTable[i].destination == destination) && (connTable[i].control == control)) { /*lint -e{704} use shift for performance */ pArt->values[connTable[i].connection] = (EAS_I16) (scale >> 16); pArt->values[PARAM_MODIFIED] = EAS_TRUE; break; } } if (i == PARAM_TABLE_SIZE) { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "WARN: Unsupported parameter in DLS file\n"); */ } } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * Parse_wlnk () *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT Parse_wlnk (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 pos, EAS_U32 *pWaveIndex) { EAS_RESULT result; /* we only care about the the index */ if ((result = EAS_HWFileSeek(pDLSData->hwInstData, pDLSData->fileHandle, pos + 8)) != EAS_SUCCESS) return result; /* read the index */ return EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle,pWaveIndex, EAS_FALSE); } /*---------------------------------------------------------------------------- * PopcdlStack () *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT PopcdlStack (EAS_U32 *pStack, EAS_INT *pStackPtr, EAS_U32 *pValue) { /* stack underflow, cdl block has an errorr */ if (*pStackPtr < 0) return EAS_ERROR_FILE_FORMAT; /* pop the value off the stack */ *pValue = pStack[*pStackPtr]; *pStackPtr = *pStackPtr - 1; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * PushcdlStack () *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT PushcdlStack (EAS_U32 *pStack, EAS_INT *pStackPtr, EAS_U32 value) { /* stack overflow, return an error */ if (*pStackPtr >= CDL_STACK_SIZE) return EAS_ERROR_FILE_FORMAT; /* push the value onto the stack */ *pStackPtr = *pStackPtr + 1; pStack[*pStackPtr] = value; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * QueryGUID () *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_BOOL QueryGUID (const DLSID *pGUID, EAS_U32 *pValue) { /* assume false */ *pValue = 0; if (EAS_HWMemCmp(&DLSID_GMInHardware, pGUID, sizeof(DLSID)) == 0) { *pValue = 0xffffffff; return EAS_TRUE; } if (EAS_HWMemCmp(&DLSID_GSInHardware, pGUID, sizeof(DLSID)) == 0) return EAS_TRUE; if (EAS_HWMemCmp(&DLSID_XGInHardware, pGUID, sizeof(DLSID)) == 0) return EAS_TRUE; if (EAS_HWMemCmp(&DLSID_SupportsDLS1, pGUID, sizeof(DLSID)) == 0) { *pValue = 0xffffffff; return EAS_TRUE; } if (EAS_HWMemCmp(&DLSID_SupportsDLS2, pGUID, sizeof(DLSID)) == 0) return EAS_TRUE; if (EAS_HWMemCmp(&DLSID_SampleMemorySize, pGUID, sizeof(DLSID)) == 0) { *pValue = MAX_DLS_MEMORY; return EAS_TRUE; } if (EAS_HWMemCmp(&DLSID_ManufacturersID, pGUID, sizeof(DLSID)) == 0) { *pValue = 0x0000013A; return EAS_TRUE; } if (EAS_HWMemCmp(&DLSID_ProductID, pGUID, sizeof(DLSID)) == 0) { *pValue = LIB_VERSION; return EAS_TRUE; } if (EAS_HWMemCmp(&DLSID_SamplePlaybackRate, pGUID, sizeof(DLSID)) == 0) { *pValue = (EAS_U32) outputSampleRate; return EAS_TRUE; } /* unrecognized DLSID */ return EAS_FALSE; } /*---------------------------------------------------------------------------- * ReadDLSID () *---------------------------------------------------------------------------- * Purpose: * Reads a DLSID in a manner that is not sensitive to processor endian-ness * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT ReadDLSID (SDLS_SYNTHESIZER_DATA *pDLSData, DLSID *pDLSID) { EAS_RESULT result; EAS_I32 n; if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &pDLSID->Data1, EAS_FALSE)) != EAS_SUCCESS) return result; if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &pDLSID->Data2, EAS_FALSE)) != EAS_SUCCESS) return result; if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &pDLSID->Data3, EAS_FALSE)) != EAS_SUCCESS) return result; return EAS_HWReadFile(pDLSData->hwInstData, pDLSData->fileHandle, pDLSID->Data4, sizeof(pDLSID->Data4), &n); } /*---------------------------------------------------------------------------- * Parse_cdl () *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static EAS_RESULT Parse_cdl (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_I32 size, EAS_U32 *pValue) { EAS_RESULT result; EAS_U32 stack[CDL_STACK_SIZE]; EAS_U16 opcode; EAS_INT stackPtr; EAS_U32 x, y; DLSID dlsid; stackPtr = -1; *pValue = 0; x = 0; while (size) { /* read the opcode */ if ((result = EAS_HWGetWord(pDLSData->hwInstData, pDLSData->fileHandle, &opcode, EAS_FALSE)) != EAS_SUCCESS) return result; /* handle binary opcodes */ if (opcode <= DLS_CDL_EQ) { /* pop X and Y */ if ((result = PopcdlStack(stack, &stackPtr, &x)) != EAS_SUCCESS) return result; if ((result = PopcdlStack(stack, &stackPtr, &y)) != EAS_SUCCESS) return result; switch (opcode) { case DLS_CDL_AND: x = x & y; break; case DLS_CDL_OR: x = x | y; break; case DLS_CDL_XOR: x = x ^ y; break; case DLS_CDL_ADD: x = x + y; break; case DLS_CDL_SUBTRACT: x = x - y; break; case DLS_CDL_MULTIPLY: x = x * y; break; case DLS_CDL_DIVIDE: if (!y) return EAS_ERROR_FILE_FORMAT; x = x / y; break; case DLS_CDL_LOGICAL_AND: x = (x && y); break; case DLS_CDL_LOGICAL_OR: x = (x || y); break; case DLS_CDL_LT: x = (x < y); break; case DLS_CDL_LE: x = (x <= y); break; case DLS_CDL_GT: x = (x > y); break; case DLS_CDL_GE: x = (x >= y); break; case DLS_CDL_EQ: x = (x == y); break; default: break; } } else if (opcode == DLS_CDL_NOT) { if ((result = PopcdlStack(stack, &stackPtr, &x)) != EAS_SUCCESS) return result; x = !x; } else if (opcode == DLS_CDL_CONST) { if ((result = EAS_HWGetDWord(pDLSData->hwInstData, pDLSData->fileHandle, &x, EAS_FALSE)) != EAS_SUCCESS) return result; } else if (opcode == DLS_CDL_QUERY) { if ((result = ReadDLSID(pDLSData, &dlsid)) != EAS_SUCCESS) return result; QueryGUID(&dlsid, &x); } else if (opcode == DLS_CDL_QUERYSUPPORTED) { if ((result = ReadDLSID(pDLSData, &dlsid)) != EAS_SUCCESS) return result; x = QueryGUID(&dlsid, &y); } else { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unsupported opcode %d in DLS file\n", opcode); */ } /* push the result on the stack */ if ((result = PushcdlStack(stack, &stackPtr, x)) != EAS_SUCCESS) return result; } /* pop the last result off the stack */ return PopcdlStack(stack, &stackPtr, pValue); } /*---------------------------------------------------------------------------- * Convert_rgn() *---------------------------------------------------------------------------- * Purpose: * Convert region data from DLS to EAS * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static void Convert_rgn (SDLS_SYNTHESIZER_DATA *pDLSData, EAS_U16 regionIndex, EAS_U16 artIndex, EAS_U16 waveIndex, S_WSMP_DATA *pWsmp) { S_DLS_REGION *pRgn; /* setup pointers to data structures */ pRgn = &pDLSData->pDLS->pDLSRegions[regionIndex]; /* intiailize indices */ pRgn->wtRegion.artIndex = artIndex; pRgn->wtRegion.waveIndex = waveIndex; /* convert region data */ /*lint -e{704} use shift for performance */ pRgn->wtRegion.gain = (EAS_I16) (pWsmp->gain >> 16); pRgn->wtRegion.loopStart = pWsmp->loopStart; pRgn->wtRegion.loopEnd = (pWsmp->loopStart + pWsmp->loopLength); pRgn->wtRegion.tuning = pWsmp->fineTune -(pWsmp->unityNote * 100) + ConvertSampleRate(pWsmp->sampleRate); if (pWsmp->loopLength != 0) pRgn->wtRegion.region.keyGroupAndFlags |= REGION_FLAG_IS_LOOPED; } /*---------------------------------------------------------------------------- * Convert_art() *---------------------------------------------------------------------------- * Purpose: * Convert articulation data from DLS to EAS * * Inputs: * * * Outputs: * * *---------------------------------------------------------------------------- */ static void Convert_art (SDLS_SYNTHESIZER_DATA *pDLSData, const S_DLS_ART_VALUES *pDLSArt, EAS_U16 artIndex) { S_DLS_ARTICULATION *pArt; /* setup pointers to data structures */ pArt = &pDLSData->pDLS->pDLSArticulations[artIndex]; /* LFO parameters */ pArt->modLFO.lfoFreq = ConvertLFOPhaseIncrement(pDLSArt->values[PARAM_MOD_LFO_FREQ]); pArt->modLFO.lfoDelay = -ConvertDelay(pDLSArt->values[PARAM_MOD_LFO_DELAY]); pArt->vibLFO.lfoFreq = ConvertLFOPhaseIncrement(pDLSArt->values[PARAM_VIB_LFO_FREQ]); pArt->vibLFO.lfoDelay = -ConvertDelay(pDLSArt->values[PARAM_VIB_LFO_DELAY]); /* EG1 parameters */ pArt->eg1.delayTime = ConvertDelay(pDLSArt->values[PARAM_VOL_EG_DELAY]); pArt->eg1.attackTime = pDLSArt->values[PARAM_VOL_EG_ATTACK]; pArt->eg1.holdTime = pDLSArt->values[PARAM_VOL_EG_HOLD]; pArt->eg1.decayTime = pDLSArt->values[PARAM_VOL_EG_DECAY]; pArt->eg1.sustainLevel = ConvertSustain(pDLSArt->values[PARAM_VOL_EG_SUSTAIN]); pArt->eg1.releaseTime = ConvertRate(pDLSArt->values[PARAM_VOL_EG_RELEASE]); pArt->eg1.velToAttack = pDLSArt->values[PARAM_VOL_EG_VEL_TO_ATTACK]; pArt->eg1.keyNumToDecay = pDLSArt->values[PARAM_VOL_EG_KEY_TO_DECAY]; pArt->eg1.keyNumToHold = pDLSArt->values[PARAM_VOL_EG_KEY_TO_HOLD]; pArt->eg1ShutdownTime = ConvertRate(pDLSArt->values[PARAM_VOL_EG_SHUTDOWN]); /* EG2 parameters */ pArt->eg2.delayTime = ConvertDelay(pDLSArt->values[PARAM_MOD_EG_DELAY]); pArt->eg2.attackTime = pDLSArt->values[PARAM_MOD_EG_ATTACK]; pArt->eg2.holdTime = pDLSArt->values[PARAM_MOD_EG_HOLD]; pArt->eg2.decayTime = pDLSArt->values[PARAM_MOD_EG_DECAY]; pArt->eg2.sustainLevel = ConvertSustain(pDLSArt->values[PARAM_MOD_EG_SUSTAIN]); pArt->eg2.releaseTime = ConvertRate(pDLSArt->values[PARAM_MOD_EG_RELEASE]); pArt->eg2.velToAttack = pDLSArt->values[PARAM_MOD_EG_VEL_TO_ATTACK]; pArt->eg2.keyNumToDecay = pDLSArt->values[PARAM_MOD_EG_KEY_TO_DECAY]; pArt->eg2.keyNumToHold = pDLSArt->values[PARAM_MOD_EG_KEY_TO_HOLD]; /* filter parameters */ pArt->filterCutoff = pDLSArt->values[PARAM_INITIAL_FC]; pArt->filterQandFlags = ConvertQ(pDLSArt->values[PARAM_INITIAL_Q]); pArt->modLFOToFc = pDLSArt->values[PARAM_MOD_LFO_TO_FC]; pArt->modLFOCC1ToFc = pDLSArt->values[PARAM_MOD_LFO_CC1_TO_FC]; pArt->modLFOChanPressToFc = pDLSArt->values[PARAM_MOD_LFO_CHAN_PRESS_TO_FC]; pArt->eg2ToFc = pDLSArt->values[PARAM_MOD_EG_TO_FC]; pArt->velToFc = pDLSArt->values[PARAM_VEL_TO_FC]; pArt->keyNumToFc = pDLSArt->values[PARAM_KEYNUM_TO_FC]; /* gain parameters */ pArt->modLFOToGain = pDLSArt->values[PARAM_MOD_LFO_TO_GAIN]; pArt->modLFOCC1ToGain = pDLSArt->values[PARAM_MOD_LFO_CC1_TO_GAIN]; pArt->modLFOChanPressToGain = pDLSArt->values[PARAM_MOD_LFO_CHAN_PRESS_TO_GAIN]; /* pitch parameters */ pArt->tuning = pDLSArt->values[PARAM_TUNING]; pArt->keyNumToPitch = pDLSArt->values[PARAM_KEYNUM_TO_PITCH]; pArt->vibLFOToPitch = pDLSArt->values[PARAM_VIB_LFO_TO_PITCH]; pArt->vibLFOCC1ToPitch = pDLSArt->values[PARAM_VIB_LFO_CC1_TO_PITCH]; pArt->vibLFOChanPressToPitch = pDLSArt->values[PARAM_VIB_LFO_CHAN_PRESS_TO_PITCH]; pArt->modLFOToPitch = pDLSArt->values[PARAM_MOD_LFO_TO_PITCH]; pArt->modLFOCC1ToPitch = pDLSArt->values[PARAM_MOD_LFO_CC1_TO_PITCH]; pArt->modLFOChanPressToPitch = pDLSArt->values[PARAM_MOD_LFO_CHAN_PRESS_TO_PITCH]; pArt->eg2ToPitch = pDLSArt->values[PARAM_MOD_EG_TO_PITCH]; /* output parameters */ pArt->pan = ConvertPan(pDLSArt->values[PARAM_DEFAULT_PAN]); if (pDLSArt->values[PARAM_VEL_TO_GAIN] != 0) pArt->filterQandFlags |= FLAG_DLS_VELOCITY_SENSITIVE; #ifdef _REVERB pArt->reverbSend = pDLSArt->values[PARAM_DEFAULT_REVERB_SEND]; pArt->cc91ToReverbSend = pDLSArt->values[PARAM_MIDI_CC91_TO_REVERB_SEND]; #endif #ifdef _CHORUS pArt->chorusSend = pDLSArt->values[PARAM_DEFAULT_CHORUS_SEND]; pArt->cc93ToChorusSend = pDLSArt->values[PARAM_MIDI_CC93_TO_CHORUS_SEND]; #endif } /*---------------------------------------------------------------------------- * ConvertSampleRate() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * * Outputs: * * Side Effects: *---------------------------------------------------------------------------- */ static EAS_I16 ConvertSampleRate (EAS_U32 sampleRate) { return (EAS_I16) (1200.0 * log10((double) sampleRate / (double) outputSampleRate) / log10(2.0)); } /*---------------------------------------------------------------------------- * ConvertSustainEG2() *---------------------------------------------------------------------------- * Convert sustain level to pitch/Fc multipler for EG2 *---------------------------------------------------------------------------- */ static EAS_I16 ConvertSustain (EAS_I32 sustain) { /* check for sustain level of zero */ if (sustain == 0) return 0; /* convert to log2 factor */ /*lint -e{704} use shift for performance */ sustain = (sustain * SUSTAIN_LINEAR_CONVERSION_FACTOR) >> 15; if (sustain > SYNTH_FULL_SCALE_EG1_GAIN) return SYNTH_FULL_SCALE_EG1_GAIN; return (EAS_I16) sustain; } /*---------------------------------------------------------------------------- * ConvertDelay () *---------------------------------------------------------------------------- * Converts timecents to frame count. Used for LFO and envelope * delay times. *---------------------------------------------------------------------------- */ EAS_I16 ConvertDelay (EAS_I32 timeCents) { EAS_I32 temp; if (timeCents == ZERO_TIME_IN_CENTS) return 0; /* divide time by secs per frame to get number of frames */ temp = timeCents - dlsRateConvert; /* convert from time cents to 10-bit fraction */ temp = FMUL_15x15(temp, TIME_CENTS_TO_LOG2); /* convert to frame count */ temp = EAS_LogToLinear16(temp - (15 << 10)); if (temp < SYNTH_FULL_SCALE_EG1_GAIN) return (EAS_I16) temp; return SYNTH_FULL_SCALE_EG1_GAIN; } /*---------------------------------------------------------------------------- * ConvertRate () *---------------------------------------------------------------------------- * Convert timecents to rate *---------------------------------------------------------------------------- */ EAS_I16 ConvertRate (EAS_I32 timeCents) { EAS_I32 temp; if (timeCents == ZERO_TIME_IN_CENTS) return SYNTH_FULL_SCALE_EG1_GAIN; /* divide frame rate by time in log domain to get rate */ temp = dlsRateConvert - timeCents; #if 1 temp = EAS_Calculate2toX(temp); #else /* convert from time cents to 10-bit fraction */ temp = FMUL_15x15(temp, TIME_CENTS_TO_LOG2); /* convert to rate */ temp = EAS_LogToLinear16(temp); #endif if (temp < SYNTH_FULL_SCALE_EG1_GAIN) return (EAS_I16) temp; return SYNTH_FULL_SCALE_EG1_GAIN; } /*---------------------------------------------------------------------------- * ConvertLFOPhaseIncrement() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * * Outputs: * * Side Effects: *---------------------------------------------------------------------------- */ static EAS_I16 ConvertLFOPhaseIncrement (EAS_I32 pitchCents) { /* check range */ if (pitchCents > MAX_LFO_FREQUENCY_IN_PITCHCENTS) pitchCents = MAX_LFO_FREQUENCY_IN_PITCHCENTS; if (pitchCents < MIN_LFO_FREQUENCY_IN_PITCHCENTS) pitchCents = MIN_LFO_FREQUENCY_IN_PITCHCENTS; /* double the rate and divide by frame rate by subtracting in log domain */ pitchCents = pitchCents - dlsLFOFrequencyConvert; /* convert to phase increment */ return (EAS_I16) EAS_Calculate2toX(pitchCents); } /*---------------------------------------------------------------------------- * ConvertPan() *---------------------------------------------------------------------------- * Purpose: * * Inputs: * * Outputs: * * Side Effects: *---------------------------------------------------------------------------- */ static EAS_I8 ConvertPan (EAS_I32 pan) { /* multiply by conversion factor */ pan = FMUL_15x15 (PAN_CONVERSION_FACTOR, pan); if (pan < MIN_PAN_VALUE) return MIN_PAN_VALUE; if (pan > MAX_PAN_VALUE) return MAX_PAN_VALUE; return (EAS_I8) pan; } /*---------------------------------------------------------------------------- * ConvertQ() *---------------------------------------------------------------------------- * Convert the DLS filter resonance to an index value used by the synth * that accesses tables of coefficients based on the Q. *---------------------------------------------------------------------------- */ static EAS_U8 ConvertQ (EAS_I32 q) { /* apply limits */ if (q <= 0) return 0; /* convert to table index */ /*lint -e{704} use shift for performance */ q = (FILTER_Q_CONVERSION_FACTOR * q + 0x4000) >> 15; /* apply upper limit */ if (q >= FILTER_RESONANCE_NUM_ENTRIES) q = FILTER_RESONANCE_NUM_ENTRIES - 1; return (EAS_U8) q; } #ifdef _DEBUG_DLS /*---------------------------------------------------------------------------- * DumpDLS() *---------------------------------------------------------------------------- */ static void DumpDLS (S_EAS *pEAS) { S_DLS_ARTICULATION *pArt; S_DLS_REGION *pRegion; EAS_INT i; EAS_INT j; EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000022 , pEAS->numPrograms); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000023 , pEAS->numWTRegions); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000024 , pEAS->numDLSArticulations); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000025 , pEAS->numSamples); /* dump the instruments */ for (i = 0; i < pEAS->numPrograms; i++) { EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000026 , pEAS->pPrograms[i].locale >> 16, (pEAS->pPrograms[i].locale >> 8) & 0x7f, pEAS->pPrograms[i].locale & 0x7f); for (j = pEAS->pPrograms[i].regionIndex; ; j++) { EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000027 , j); pRegion = &pEAS->pWTRegions[j]; EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000028 , pRegion->gain); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000029 , pRegion->region.rangeLow, pRegion->region.rangeHigh); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002a , pRegion->region.keyGroupAndFlags); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002b , pRegion->loopStart); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002c , pRegion->loopEnd); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002d , pRegion->tuning); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002e , pRegion->artIndex); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000002f , pRegion->waveIndex); if (pRegion->region.keyGroupAndFlags & REGION_FLAG_LAST_REGION) break; } } /* dump the articulation data */ for (i = 0; i < pEAS->numDLSArticulations; i++) { /* articulation data */ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000030 , i); pArt = &pEAS->pDLSArticulations[i]; EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000031 , pArt->m_nEG2toFilterDepth); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000032 , pArt->m_nEG2toPitchDepth); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000033 , pArt->m_nFilterCutoffFrequency); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000034 , pArt->m_nFilterResonance); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000035 , pArt->m_nLFOAmplitudeDepth); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000036 , pArt->m_nLFODelayTime); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000037 , pArt->m_nLFOFrequency); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000038 , pArt->m_nLFOPitchDepth); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000039 , pArt->m_nPan); /* EG1 data */ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003a , pArt->m_sEG1.m_nAttack); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003b , pArt->m_sEG1.m_nDecay); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003c , pArt->m_sEG1.m_nSustain); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003d , pArt->m_sEG1.m_nRelease); /* EG2 data */ EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003e , pArt->m_sEG2.m_nAttack); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x0000003f , pArt->m_sEG2.m_nDecay); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000040 , pArt->m_sEG2.m_nSustain); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000041 , pArt->m_sEG2.m_nRelease); } /* dump the waves */ for (i = 0; i < pEAS->numSamples; i++) { EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000042 , i); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000043 , pEAS->pSampleLen[i]); EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x19299ed4, 0x00000044 , pEAS->ppSamples[i]); } } #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_sndlib.h0000644000000000000000000000013213532747316026370 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.858000056 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_sndlib.h0000644000175000001440000003104613532747316027165 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_sndlib.h * * Contents and purpose: * Declarations for the sound library * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 550 $ * $Date: 2007-02-02 09:37:03 -0800 (Fri, 02 Feb 2007) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_SNDLIB_H #define _EAS_SNDLIB_H #include "eas_types.h" #include "eas_synthcfg.h" #ifdef _WT_SYNTH #include "eas_wtengine.h" #endif /*---------------------------------------------------------------------------- * This is bit of a hack to allow us to keep the same structure * declarations for the DLS parser. Normally, the data is located * in read-only memory, but for DLS, we store the data in RW * memory. *---------------------------------------------------------------------------- */ #ifndef SCNST #define SCNST const #endif /*---------------------------------------------------------------------------- * sample size *---------------------------------------------------------------------------- */ #ifdef _16_BIT_SAMPLES typedef EAS_I16 EAS_SAMPLE; #else typedef EAS_I8 EAS_SAMPLE; #endif /*---------------------------------------------------------------------------- * EAS Library ID - quick check for valid library and version *---------------------------------------------------------------------------- */ #define _EAS_LIBRARY_VERSION 0x01534145 #define NUM_PROGRAMS_IN_BANK 128 #define INVALID_REGION_INDEX 0xffff /* this bit in region index indicates that region is for secondary synth */ #define FLAG_RGN_IDX_FM_SYNTH 0x8000 #define FLAG_RGN_IDX_DLS_SYNTH 0x4000 #define REGION_INDEX_MASK 0x3fff /*---------------------------------------------------------------------------- * Generic region data structure * * This must be the first element in each region structure *---------------------------------------------------------------------------- */ typedef struct s_region_tag { EAS_U16 keyGroupAndFlags; EAS_U8 rangeLow; EAS_U8 rangeHigh; } S_REGION; /* * Bit fields for m_nKeyGroupAndFlags * Bits 0-2 are mode bits in FM synth * Bits 8-11 are the key group */ #define REGION_FLAG_IS_LOOPED 0x01 #define REGION_FLAG_USE_WAVE_GENERATOR 0x02 #define REGION_FLAG_USE_ADPCM 0x04 #define REGION_FLAG_ONE_SHOT 0x08 #define REGION_FLAG_SQUARE_WAVE 0x10 #define REGION_FLAG_OFF_CHIP 0x20 #define REGION_FLAG_NON_SELF_EXCLUSIVE 0x40 #define REGION_FLAG_LAST_REGION 0x8000 /*---------------------------------------------------------------------------- * Envelope data structure *---------------------------------------------------------------------------- */ typedef struct s_envelope_tag { EAS_I16 attackTime; EAS_I16 decayTime; EAS_I16 sustainLevel; EAS_I16 releaseTime; } S_ENVELOPE; /*---------------------------------------------------------------------------- * DLS envelope data structure *---------------------------------------------------------------------------- */ typedef struct s_dls_envelope_tag { EAS_I16 delayTime; EAS_I16 attackTime; EAS_I16 holdTime; EAS_I16 decayTime; EAS_I16 sustainLevel; EAS_I16 releaseTime; EAS_I16 velToAttack; EAS_I16 keyNumToDecay; EAS_I16 keyNumToHold; } S_DLS_ENVELOPE; /*---------------------------------------------------------------------------- * LFO data structure *---------------------------------------------------------------------------- */ typedef struct s_lfo_params_tag { EAS_I16 lfoFreq; EAS_I16 lfoDelay; } S_LFO_PARAMS; /*---------------------------------------------------------------------------- * Articulation data structure *---------------------------------------------------------------------------- */ typedef struct s_articulation_tag { S_ENVELOPE eg1; S_ENVELOPE eg2; EAS_I16 lfoToPitch; EAS_I16 lfoDelay; EAS_I16 lfoFreq; EAS_I16 eg2ToPitch; EAS_I16 eg2ToFc; EAS_I16 filterCutoff; EAS_I8 lfoToGain; EAS_U8 filterQ; EAS_I8 pan; } S_ARTICULATION; /*---------------------------------------------------------------------------- * DLS articulation data structure *---------------------------------------------------------------------------- */ typedef struct s_dls_articulation_tag { S_LFO_PARAMS modLFO; S_LFO_PARAMS vibLFO; S_DLS_ENVELOPE eg1; S_DLS_ENVELOPE eg2; EAS_I16 eg1ShutdownTime; EAS_I16 filterCutoff; EAS_I16 modLFOToFc; EAS_I16 modLFOCC1ToFc; EAS_I16 modLFOChanPressToFc; EAS_I16 eg2ToFc; EAS_I16 velToFc; EAS_I16 keyNumToFc; EAS_I16 modLFOToGain; EAS_I16 modLFOCC1ToGain; EAS_I16 modLFOChanPressToGain; EAS_I16 tuning; EAS_I16 keyNumToPitch; EAS_I16 vibLFOToPitch; EAS_I16 vibLFOCC1ToPitch; EAS_I16 vibLFOChanPressToPitch; EAS_I16 modLFOToPitch; EAS_I16 modLFOCC1ToPitch; EAS_I16 modLFOChanPressToPitch; EAS_I16 eg2ToPitch; /* pad to 4-byte boundary */ EAS_U16 pad; EAS_I8 pan; EAS_U8 filterQandFlags; #ifdef _REVERB EAS_I16 reverbSend; EAS_I16 cc91ToReverbSend; #endif #ifdef _CHORUS EAS_I16 chorusSend; EAS_I16 cc93ToChorusSend; #endif } S_DLS_ARTICULATION; /* flags in filterQandFlags * NOTE: Q is stored in bottom 5 bits */ #define FLAG_DLS_VELOCITY_SENSITIVE 0x80 #define FILTER_Q_MASK 0x1f /*---------------------------------------------------------------------------- * Wavetable region data structure *---------------------------------------------------------------------------- */ typedef struct s_wt_region_tag { S_REGION region; EAS_I16 tuning; EAS_I16 gain; EAS_U32 loopStart; EAS_U32 loopEnd; EAS_U16 waveIndex; EAS_U16 artIndex; } S_WT_REGION; /*---------------------------------------------------------------------------- * DLS region data structure *---------------------------------------------------------------------------- */ typedef struct s_dls_region_tag { S_WT_REGION wtRegion; EAS_U8 velLow; EAS_U8 velHigh; } S_DLS_REGION; /*---------------------------------------------------------------------------- * FM synthesizer data structures *---------------------------------------------------------------------------- */ typedef struct s_fm_oper_tag { EAS_I16 tuning; EAS_U8 attackDecay; EAS_U8 velocityRelease; EAS_U8 egKeyScale; EAS_U8 sustain; EAS_U8 gain; EAS_U8 flags; } S_FM_OPER; /* defines for S_FM_OPER.m_nFlags */ #define FM_OPER_FLAG_MONOTONE 0x01 #define FM_OPER_FLAG_NO_VIBRATO 0x02 #define FM_OPER_FLAG_NOISE 0x04 #define FM_OPER_FLAG_LINEAR_VELOCITY 0x08 /* NOTE: The first two structure elements are common with S_WT_REGION * and we will rely on that in the voice management code and must * remain there unless the voice management code is revisited. */ typedef struct s_fm_region_tag { S_REGION region; EAS_U8 vibTrem; EAS_U8 lfoFreqDelay; EAS_U8 feedback; EAS_I8 pan; S_FM_OPER oper[4]; } S_FM_REGION; /*---------------------------------------------------------------------------- * Common data structures *---------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------- * Program data structure * Used for individual programs not stored as a complete bank. *---------------------------------------------------------------------------- */ typedef struct s_program_tag { EAS_U32 locale; EAS_U16 regionIndex; } S_PROGRAM; /*---------------------------------------------------------------------------- * Bank data structure * * A bank always consists of 128 programs. If a bank is less than 128 * programs, it should be stored as a spare matrix in the pPrograms * array. * * bankNum: MSB/LSB of MIDI bank select controller * regionIndex: Index of first region in program *---------------------------------------------------------------------------- */ typedef struct s_bank_tag { EAS_U16 locale; EAS_U16 regionIndex[NUM_PROGRAMS_IN_BANK]; } S_BANK; /* defines for libFormat field * bits 0-17 are the sample rate * bit 18 is true if wavetable is present * bit 19 is true if FM is present * bit 20 is true if filter is enabled * bit 21 is sample depth (0 = 8-bits, 1 = 16-bits) * bits 22-31 are reserved */ #define LIBFORMAT_SAMPLE_RATE_MASK 0x0003ffff #define LIB_FORMAT_TYPE_MASK 0x000c0000 #define LIB_FORMAT_WAVETABLE 0x00000000 #define LIB_FORMAT_FM 0x00040000 #define LIB_FORMAT_HYBRID 0x00080000 #define LIB_FORMAT_FILTER_ENABLED 0x00100000 #define LIB_FORMAT_16_BIT_SAMPLES 0x00200000 #ifdef DLS_SYNTHESIZER /*---------------------------------------------------------------------------- * DLS data structure * * pDLSPrograms pointer to array of DLS programs * pDLSRegions pointer to array of DLS regions * pDLSArticulations pointer to array of DLS articulations * pSampleLen pointer to array of sample lengths * ppSamples pointer to array of sample pointers * numDLSPrograms number of DLS programs * numDLSRegions number of DLS regions * numDLSArticulations number of DLS articulations * numDLSSamples number of DLS samples *---------------------------------------------------------------------------- */ typedef struct s_eas_dls_tag { S_PROGRAM *pDLSPrograms; S_DLS_REGION *pDLSRegions; S_DLS_ARTICULATION *pDLSArticulations; EAS_U32 *pDLSSampleLen; EAS_U32 *pDLSSampleOffsets; EAS_SAMPLE *pDLSSamples; EAS_U16 numDLSPrograms; EAS_U16 numDLSRegions; EAS_U16 numDLSArticulations; EAS_U16 numDLSSamples; EAS_U8 refCount; } S_DLS; #endif /*---------------------------------------------------------------------------- * Sound library data structure * * pBanks pointer to array of banks * pPrograms pointer to array of programs * pWTRegions pointer to array of wavetable regions * pFMRegions pointer to array of FM regions * pArticulations pointer to array of articulations * pSampleLen pointer to array of sample lengths * ppSamples pointer to array of sample pointers * numBanks number of banks * numPrograms number of individual program * numRegions number of regions * numArticulations number of articulations * numSamples number of samples *---------------------------------------------------------------------------- */ typedef struct s_eas_sndlib_tag { SCNST EAS_U32 identifier; SCNST EAS_U32 libAttr; SCNST S_BANK *pBanks; SCNST S_PROGRAM *pPrograms; SCNST S_WT_REGION *pWTRegions; SCNST S_ARTICULATION *pArticulations; SCNST EAS_U32 *pSampleLen; SCNST EAS_U32 *pSampleOffsets; SCNST EAS_SAMPLE *pSamples; SCNST S_FM_REGION *pFMRegions; SCNST EAS_U16 numBanks; SCNST EAS_U16 numPrograms; SCNST EAS_U16 numWTRegions; SCNST EAS_U16 numArticulations; SCNST EAS_U16 numSamples; SCNST EAS_U16 numFMRegions; } S_EAS; #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_midi.h0000644000000000000000000000013213532747316026037 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.858000056 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_midi.h0000644000175000001440000000440613532747316026634 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_midi.h * * Contents and purpose: * Prototypes for MIDI stream parsing functions * * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_MIDI_H #define _EAS_MIDI_H /*---------------------------------------------------------------------------- * EAS_InitMIDIStream() *---------------------------------------------------------------------------- * Purpose: * Initializes the MIDI stream state for parsing. * * Inputs: * * Outputs: * returns EAS_RESULT (EAS_SUCCESS is OK) * * Side Effects: * *---------------------------------------------------------------------------- */ void EAS_InitMIDIStream (S_MIDI_STREAM *pMIDIStream); /*---------------------------------------------------------------------------- * EAS_ParseMIDIStream() *---------------------------------------------------------------------------- * Purpose: * Parses a MIDI input stream character by character. Characters are pushed (rather than pulled) * so the interface works equally well for both file and stream I/O. * * Inputs: * c - character from MIDI stream * * Outputs: * returns EAS_RESULT (EAS_SUCCESS is OK) * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_ParseMIDIStream (S_EAS_DATA *pEASData, S_SYNTH *pSynth, S_MIDI_STREAM *pMIDIStream, EAS_U8 c, EAS_INT parserMode); #endif /* #define _EAS_MIDI_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_reverbdata.c0000644000000000000000000000013213532747316027227 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.858000056 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_reverbdata.c0000644000175000001440000000215113532747316030017 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_reverbdata.c * * Contents and purpose: * Contains the static data allocation for the Reverb effect * * * Copyright Sonic Network Inc. 2006 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 550 $ * $Date: 2007-02-02 09:37:03 -0800 (Fri, 02 Feb 2007) $ *---------------------------------------------------------------------------- */ #include "eas_reverbdata.h" S_REVERB_OBJECT eas_ReverbData; drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/dls2.h0000644000000000000000000000013213532747316025131 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.858000056 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/dls2.h0000644000175000001440000001147613532747316025733 0ustar00pedrousers00000000000000/* dls2.h Description: Interface defines and structures for the DLS2 extensions of DLS. Written by Microsoft 1998. Released for public use. */ #ifndef _INC_DLS2 #define _INC_DLS2 /* FOURCC's used in the DLS2 file, in addition to DLS1 chunks */ #define FOURCC_RGN2 mmioFOURCC('r','g','n','2') #define FOURCC_LAR2 mmioFOURCC('l','a','r','2') #define FOURCC_ART2 mmioFOURCC('a','r','t','2') #define FOURCC_CDL mmioFOURCC('c','d','l',' ') #define FOURCC_DLID mmioFOURCC('d','l','i','d') /* Articulation connection graph definitions. These are in addition to the definitions in the DLS1 header. */ /* Generic Sources (in addition to DLS1 sources. */ #define CONN_SRC_POLYPRESSURE 0x0007 /* Polyphonic Pressure */ #define CONN_SRC_CHANNELPRESSURE 0x0008 /* Channel Pressure */ #define CONN_SRC_VIBRATO 0x0009 /* Vibrato LFO */ #define CONN_SRC_MONOPRESSURE 0x000a /* MIDI Mono pressure */ /* Midi Controllers */ #define CONN_SRC_CC91 0x00db /* Reverb Send */ #define CONN_SRC_CC93 0x00dd /* Chorus Send */ /* Generic Destinations */ #define CONN_DST_GAIN 0x0001 /* Same as CONN_DST_ ATTENUATION, but more appropriate terminology. */ #define CONN_DST_KEYNUMBER 0x0005 /* Key Number Generator */ /* Audio Channel Output Destinations */ #define CONN_DST_LEFT 0x0010 /* Left Channel Send */ #define CONN_DST_RIGHT 0x0011 /* Right Channel Send */ #define CONN_DST_CENTER 0x0012 /* Center Channel Send */ #define CONN_DST_LEFTREAR 0x0013 /* Left Rear Channel Send */ #define CONN_DST_RIGHTREAR 0x0014 /* Right Rear Channel Send */ #define CONN_DST_LFE_CHANNEL 0x0015 /* LFE Channel Send */ #define CONN_DST_CHORUS 0x0080 /* Chorus Send */ #define CONN_DST_REVERB 0x0081 /* Reverb Send */ /* Vibrato LFO Destinations */ #define CONN_DST_VIB_FREQUENCY 0x0114 /* Vibrato Frequency */ #define CONN_DST_VIB_STARTDELAY 0x0115 /* Vibrato Start Delay */ /* EG1 Destinations */ #define CONN_DST_EG1_DELAYTIME 0x020B /* EG1 Delay Time */ #define CONN_DST_EG1_HOLDTIME 0x020C /* EG1 Hold Time */ #define CONN_DST_EG1_SHUTDOWNTIME 0x020D /* EG1 Shutdown Time */ /* EG2 Destinations */ #define CONN_DST_EG2_DELAYTIME 0x030F /* EG2 Delay Time */ #define CONN_DST_EG2_HOLDTIME 0x0310 /* EG2 Hold Time */ /* Filter Destinations */ #define CONN_DST_FILTER_CUTOFF 0x0500 /* Filter Cutoff Frequency */ #define CONN_DST_FILTER_Q 0x0501 /* Filter Resonance */ /* Transforms */ #define CONN_TRN_CONVEX 0x0002 /* Convex Transform */ #define CONN_TRN_SWITCH 0x0003 /* Switch Transform */ /* Conditional chunk operators */ #define DLS_CDL_AND 0x0001 /* X = X & Y */ #define DLS_CDL_OR 0x0002 /* X = X | Y */ #define DLS_CDL_XOR 0x0003 /* X = X ^ Y */ #define DLS_CDL_ADD 0x0004 /* X = X + Y */ #define DLS_CDL_SUBTRACT 0x0005 /* X = X - Y */ #define DLS_CDL_MULTIPLY 0x0006 /* X = X * Y */ #define DLS_CDL_DIVIDE 0x0007 /* X = X / Y */ #define DLS_CDL_LOGICAL_AND 0x0008 /* X = X && Y */ #define DLS_CDL_LOGICAL_OR 0x0009 /* X = X || Y */ #define DLS_CDL_LT 0x000A /* X = (X < Y) */ #define DLS_CDL_LE 0x000B /* X = (X <= Y) */ #define DLS_CDL_GT 0x000C /* X = (X > Y) */ #define DLS_CDL_GE 0x000D /* X = (X >= Y) */ #define DLS_CDL_EQ 0x000E /* X = (X == Y) */ #define DLS_CDL_NOT 0x000F /* X = !X */ #define DLS_CDL_CONST 0x0010 /* 32-bit constant */ #define DLS_CDL_QUERY 0x0011 /* 32-bit value returned from query */ #define DLS_CDL_QUERYSUPPORTED 0x0012 /* 32-bit value returned from query */ /* Loop and release */ #define WLOOP_TYPE_RELEASE 1 /* DLSID queries for */ DEFINE_DLSID(DLSID_GMInHardware, 0x178f2f24, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); DEFINE_DLSID(DLSID_GSInHardware, 0x178f2f25, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); DEFINE_DLSID(DLSID_XGInHardware, 0x178f2f26, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); DEFINE_DLSID(DLSID_SupportsDLS1, 0x178f2f27, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); DEFINE_DLSID(DLSID_SupportsDLS2, 0xf14599e5, 0x4689, 0x11d2, 0xaf, 0xa6, 0x0, 0xaa, 0x0, 0x24, 0xd8, 0xb6); DEFINE_DLSID(DLSID_SampleMemorySize, 0x178f2f28, 0xc364, 0x11d1, 0xa7, 0x60, 0x00, 0x00, 0xf8, 0x75, 0xac, 0x12); DEFINE_DLSID(DLSID_ManufacturersID, 0xb03e1181, 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8); DEFINE_DLSID(DLSID_ProductID, 0xb03e1182, 0x8095, 0x11d2, 0xa1, 0xef, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8); DEFINE_DLSID(DLSID_SamplePlaybackRate, 0x2a91f713, 0xa4bf, 0x11d2, 0xbb, 0xdf, 0x0, 0x60, 0x8, 0x33, 0xdb, 0xd8); #endif /* _INC_DLS2 */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_imelodydata.c0000644000000000000000000000013213532747316027404 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.858000056 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_imelodydata.c0000644000175000001440000000257413532747316030205 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_imelodydata.c * * Contents and purpose: * SMF File Parser * * This file contains data definitions for the SMF parser. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 547 $ * $Date: 2007-01-31 16:30:17 -0800 (Wed, 31 Jan 2007) $ *---------------------------------------------------------------------------- */ #include "eas_types.h" #include "eas_imelodydata.h" /*---------------------------------------------------------------------------- * * eas_iMelodyData * * Static memory allocation for iMelody parser *---------------------------------------------------------------------------- */ S_IMELODY_DATA eas_iMelodyData; drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_dlssynth.h0000644000000000000000000000013213532747316026765 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.858000056 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_dlssynth.h0000644000175000001440000000331613532747316027561 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_dlssynth.h * * Contents and purpose: * Implements the Mobile DLS synthesizer. * * Copyright Sonic Network Inc. 2006 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 143 $ * $Date: 2006-07-17 14:09:35 -0700 (Mon, 17 Jul 2006) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_DLSSYNTH_H #define _EAS_DLSSYNTH_H /* prototypes */ void DLS_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); void DLS_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); void DLS_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum); EAS_RESULT DLS_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex); EAS_BOOL DLS_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples); #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_parser.h0000644000000000000000000000013213532747316026411 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.858000056 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_parser.h0000644000175000001440000000725213532747316027210 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_parser.h * * Contents and purpose: * Interface declarations for the generic parser interface * * This header only contains declarations that are specific * to this implementation. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 767 $ * $Date: 2007-07-19 13:47:31 -0700 (Thu, 19 Jul 2007) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_PARSER_H #define _EAS_PARSER_H #include "eas_types.h" /* metadata callback */ typedef struct s_metadata_cb_tag { EAS_METADATA_CBFUNC callback; char *buffer; EAS_VOID_PTR pUserData; EAS_I32 bufferSize; } S_METADATA_CB; /* generic parser interface */ typedef struct { EAS_RESULT (* EAS_CONST pfCheckFileType)(struct s_eas_data_tag *pEASData, EAS_FILE_HANDLE fileHandle, EAS_VOID_PTR *ppHandle, EAS_I32 offset); EAS_RESULT (* EAS_CONST pfPrepare)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); EAS_RESULT (* EAS_CONST pfTime)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_U32 *pTime); EAS_RESULT (* EAS_CONST pfEvent)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_INT parseMode); EAS_RESULT (* EAS_CONST pfState)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_STATE *pState); EAS_RESULT (* EAS_CONST pfClose)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); EAS_RESULT (* EAS_CONST pfReset)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); EAS_RESULT (* EAS_CONST pfPause)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); EAS_RESULT (* EAS_CONST pfResume)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData); EAS_RESULT (* EAS_CONST pfLocate)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 time, EAS_BOOL *pParserLocate); EAS_RESULT (* EAS_CONST pfSetData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 value); EAS_RESULT (* EAS_CONST pfGetData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 param, EAS_I32 *pValue); EAS_RESULT (* EAS_CONST pfGetMetaData)(struct s_eas_data_tag *pEASData, EAS_VOID_PTR pInstData, EAS_I32 *pMediaLength); } S_FILE_PARSER_INTERFACE; typedef enum { eParserModePlay, eParserModeLocate, eParserModeMute, eParserModeMetaData } E_PARSE_MODE; typedef enum { PARSER_DATA_FILE_TYPE, PARSER_DATA_PLAYBACK_RATE, PARSER_DATA_TRANSPOSITION, PARSER_DATA_VOLUME, PARSER_DATA_SYNTH_HANDLE, PARSER_DATA_METADATA_CB, PARSER_DATA_DLS_COLLECTION, PARSER_DATA_EAS_LIBRARY, PARSER_DATA_POLYPHONY, PARSER_DATA_PRIORITY, PARSER_DATA_FORMAT, PARSER_DATA_MEDIA_LENGTH, PARSER_DATA_JET_CB, PARSER_DATA_MUTE_FLAGS, PARSER_DATA_SET_MUTE, PARSER_DATA_CLEAR_MUTE, PARSER_DATA_NOTE_COUNT, PARSER_DATA_MAX_PCM_STREAMS, PARSER_DATA_GAIN_OFFSET, PARSER_DATA_PLAY_MODE } E_PARSER_DATA; #endif /* #ifndef _EAS_PARSER_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_dlssynth.c0000644000000000000000000000013213532747316026760 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.858000056 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_dlssynth.c0000644000175000001440000005205313532747316027556 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_dlssynth.c * * Contents and purpose: * Implements the Mobile DLS synthesizer. * * Copyright Sonic Network Inc. 2006 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 795 $ * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ *---------------------------------------------------------------------------- */ // includes #include "eas_data.h" #include "eas_report.h" #include "eas_host.h" #include "eas_math.h" #include "eas_synth_protos.h" #include "eas_wtsynth.h" #include "eas_pan.h" #include "eas_mdls.h" #include "eas_dlssynth.h" #ifdef _METRICS_ENABLED #include "eas_perf.h" #endif static void DLS_UpdateEnvelope (S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, const S_DLS_ENVELOPE *pEnvParams, EAS_I16 *pValue, EAS_I16 *pIncrement, EAS_U8 *pState); /*---------------------------------------------------------------------------- * DLS_MuteVoice() *---------------------------------------------------------------------------- * Mute the voice using shutdown time from the DLS articulation data *---------------------------------------------------------------------------- */ void DLS_MuteVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) { S_WT_VOICE *pWTVoice; const S_DLS_ARTICULATION *pDLSArt; pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex]; /* clear deferred action flags */ pVoice->voiceFlags &= ~(VOICE_FLAG_DEFER_MIDI_NOTE_OFF | VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF | VOICE_FLAG_DEFER_MUTE); /* set the envelope state */ pVoiceMgr->wtVoices[voiceNum].eg1State = eEnvelopeStateRelease; pWTVoice->eg1Increment = pDLSArt->eg1ShutdownTime; pVoiceMgr->wtVoices[voiceNum].eg2State = eEnvelopeStateRelease; pWTVoice->eg2Increment = pDLSArt->eg2.releaseTime; } /*---------------------------------------------------------------------------- * DLS_ReleaseVoice() *---------------------------------------------------------------------------- * Release the selected voice. *---------------------------------------------------------------------------- */ /*lint -esym(715, pVoice) standard API, pVoice may be used by other synthesizers */ void DLS_ReleaseVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum) { S_WT_VOICE *pWTVoice; const S_DLS_ARTICULATION *pDLSArt; pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex]; /* if still in attack phase, convert units to log */ /*lint -e{732} eg1Value is never negative */ /*lint -e{703} use shift for performance */ if (pWTVoice->eg1State == eEnvelopeStateAttack) pWTVoice->eg1Value = (EAS_I16) ((EAS_flog2(pWTVoice->eg1Value) << 1) + 2048); /* release EG1 */ pWTVoice->eg1State = eEnvelopeStateRelease; pWTVoice->eg1Increment = pDLSArt->eg1.releaseTime; /* release EG2 */ pWTVoice->eg2State = eEnvelopeStateRelease; pWTVoice->eg2Increment = pDLSArt->eg2.releaseTime; } /*---------------------------------------------------------------------------- * DLS_SustainPedal() *---------------------------------------------------------------------------- * The sustain pedal was just depressed. If the voice is still * above the sustain level, catch the voice and continue holding. *---------------------------------------------------------------------------- */ /*lint -esym(715, pChannel) pChannel reserved for future use */ void DLS_SustainPedal (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum) { S_WT_VOICE *pWTVoice; const S_DLS_ARTICULATION *pDLSArt; pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex]; /* don't catch the voice if below the sustain level */ if (pWTVoice->eg1Value < pDLSArt->eg1.sustainLevel) return; /* defer releasing this note until the damper pedal is off */ pWTVoice->eg1State = eEnvelopeStateDecay; pVoice->voiceState = eVoiceStatePlay; pVoice->voiceFlags |= VOICE_FLAG_SUSTAIN_PEDAL_DEFER_NOTE_OFF; #ifdef _DEBUG_SYNTH { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "DLS_SustainPedal: defer note off because sustain pedal is on\n"); */ } #endif } /*---------------------------------------------------------------------------- * DLS_UpdatePhaseInc() *---------------------------------------------------------------------------- * Calculate the oscillator phase increment for the next frame *---------------------------------------------------------------------------- */ static EAS_I32 DLS_UpdatePhaseInc (S_WT_VOICE *pWTVoice, const S_DLS_ARTICULATION *pDLSArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 pitchCents) { EAS_I32 temp; /* start with base mod LFO modulation */ temp = pDLSArt->modLFOToPitch; /* add mod wheel effect */ /*lint -e{702} use shift for performance */ temp += ((pDLSArt->modLFOCC1ToPitch * pChannel->modWheel) >> 7); /* add channel pressure effect */ /*lint -e{702} use shift for performance */ temp += ((pDLSArt->modLFOChanPressToPitch * pChannel->channelPressure) >> 7); /* add total mod LFO effect */ pitchCents += FMUL_15x15(temp, pWTVoice->modLFO.lfoValue); /* start with base vib LFO modulation */ temp = pDLSArt->vibLFOToPitch; /* add mod wheel effect */ /*lint -e{702} use shift for performance */ temp += ((pDLSArt->vibLFOCC1ToPitch * pChannel->modWheel) >> 7); /* add channel pressure effect */ /*lint -e{702} use shift for performance */ temp += ((pDLSArt->vibLFOChanPressToPitch * pChannel->channelPressure) >> 7); /* add total vibrato LFO effect */ pitchCents += FMUL_15x15(temp, pWTVoice->vibLFO.lfoValue); /* add EG2 effect */ pitchCents += FMUL_15x15(pDLSArt->eg2ToPitch, pWTVoice->eg2Value); /* convert from cents to linear phase increment */ return EAS_Calculate2toX(pitchCents); } /*---------------------------------------------------------------------------- * DLS_UpdateGain() *---------------------------------------------------------------------------- * Calculate the gain for the next frame *---------------------------------------------------------------------------- */ static EAS_I32 DLS_UpdateGain (S_WT_VOICE *pWTVoice, const S_DLS_ARTICULATION *pDLSArt, S_SYNTH_CHANNEL *pChannel, EAS_I32 gain, EAS_U8 velocity) { EAS_I32 temp; /* start with base mod LFO modulation */ temp = pDLSArt->modLFOToGain; /* add mod wheel effect */ /*lint -e{702} use shift for performance */ temp += ((pDLSArt->modLFOCC1ToGain * pChannel->modWheel) >> 7); /* add channel pressure effect */ /*lint -e{702} use shift for performance */ temp += ((pDLSArt->modLFOChanPressToGain * pChannel->channelPressure) >> 7); /* add total mod LFO effect */ gain += FMUL_15x15(temp, pWTVoice->modLFO.lfoValue); if (gain > 0) gain = 0; /* convert to linear gain including EG1 */ if (pWTVoice->eg1State != eEnvelopeStateAttack) { gain = (DLS_GAIN_FACTOR * gain) >> DLS_GAIN_SHIFT; /*lint -e{702} use shift for performance */ #if 1 gain += (pWTVoice->eg1Value - 32767) >> 1; gain = EAS_LogToLinear16(gain); #else gain = EAS_LogToLinear16(gain); temp = EAS_LogToLinear16((pWTVoice->eg1Value - 32767) >> 1); gain = FMUL_15x15(gain, temp); #endif } else { gain = (DLS_GAIN_FACTOR * gain) >> DLS_GAIN_SHIFT; gain = EAS_LogToLinear16(gain); gain = FMUL_15x15(gain, pWTVoice->eg1Value); } /* include MIDI channel gain */ gain = FMUL_15x15(gain, pChannel->staticGain); /* include velocity */ if (pDLSArt->filterQandFlags & FLAG_DLS_VELOCITY_SENSITIVE) { temp = velocity << 8; temp = FMUL_15x15(temp, temp); gain = FMUL_15x15(gain, temp); } /* return gain */ return gain; } /*---------------------------------------------------------------------------- * DLS_UpdateFilter() *---------------------------------------------------------------------------- * Update the Filter parameters *---------------------------------------------------------------------------- */ static void DLS_UpdateFilter (S_SYNTH_VOICE *pVoice, S_WT_VOICE *pWTVoice, S_WT_INT_FRAME *pIntFrame, S_SYNTH_CHANNEL *pChannel, const S_DLS_ARTICULATION *pDLSArt) { EAS_I32 cutoff; EAS_I32 temp; /* no need to calculate filter coefficients if it is bypassed */ if (pDLSArt->filterCutoff == DEFAULT_DLS_FILTER_CUTOFF_FREQUENCY) { pIntFrame->frame.k = 0; return; } /* start with base cutoff frequency */ cutoff = pDLSArt->filterCutoff; /* get base mod LFO modulation */ temp = pDLSArt->modLFOToFc; /* add mod wheel effect */ /*lint -e{702} use shift for performance */ temp += ((pDLSArt->modLFOCC1ToFc * pChannel->modWheel) >> 7); /* add channel pressure effect */ /*lint -e{702} use shift for performance */ temp += ((pDLSArt->modLFOChanPressToFc* pChannel->channelPressure) >> 7); /* add total mod LFO effect */ cutoff += FMUL_15x15(temp, pWTVoice->modLFO.lfoValue); /* add EG2 effect */ cutoff += FMUL_15x15(pWTVoice->eg2Value, pDLSArt->eg2ToFc); /* add velocity effect */ /*lint -e{702} use shift for performance */ cutoff += (pVoice->velocity * pDLSArt->velToFc) >> 7; /* add velocity effect */ /*lint -e{702} use shift for performance */ cutoff += (pVoice->note * pDLSArt->keyNumToFc) >> 7; /* subtract the A5 offset and the sampling frequency */ cutoff -= FILTER_CUTOFF_FREQ_ADJUST + A5_PITCH_OFFSET_IN_CENTS; /* limit the cutoff frequency */ if (cutoff > FILTER_CUTOFF_MAX_PITCH_CENTS) cutoff = FILTER_CUTOFF_MAX_PITCH_CENTS; else if (cutoff < FILTER_CUTOFF_MIN_PITCH_CENTS) cutoff = FILTER_CUTOFF_MIN_PITCH_CENTS; WT_SetFilterCoeffs(pIntFrame, cutoff, pDLSArt->filterQandFlags & FILTER_Q_MASK); } /*---------------------------------------------------------------------------- * DLS_StartVoice() *---------------------------------------------------------------------------- * Start up a DLS voice *---------------------------------------------------------------------------- */ EAS_RESULT DLS_StartVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex) { S_WT_VOICE *pWTVoice; const S_DLS_REGION *pDLSRegion; const S_DLS_ARTICULATION *pDLSArt; S_SYNTH_CHANNEL *pChannel; #ifdef _DEBUG_SYNTH { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "DLS_StartVoice: Voice %ld; Region %d\n", (EAS_I32) (pVoice - pVoiceMgr->voices), regionIndex); */ } #endif pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; pChannel = &pSynth->channels[pVoice->channel & 15]; pDLSRegion = &pSynth->pDLS->pDLSRegions[regionIndex & REGION_INDEX_MASK]; pWTVoice->artIndex = pDLSRegion->wtRegion.artIndex; pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex]; /* initialize the envelopes */ pWTVoice->eg1State = eEnvelopeStateInit; DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg1, &pWTVoice->eg1Value, &pWTVoice->eg1Increment, &pWTVoice->eg1State); pWTVoice->eg2State = eEnvelopeStateInit; DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg2, &pWTVoice->eg2Value, &pWTVoice->eg2Increment, &pWTVoice->eg2State); /* initialize the LFOs */ pWTVoice->modLFO.lfoValue = 0; pWTVoice->modLFO.lfoPhase = pDLSArt->modLFO.lfoDelay; pWTVoice->vibLFO.lfoValue = 0; pWTVoice->vibLFO.lfoPhase = pDLSArt->vibLFO.lfoDelay; /* initalize the envelopes and calculate initial gain */ DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg1, &pWTVoice->eg1Value, &pWTVoice->eg1Increment, &pWTVoice->eg1State); DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg2, &pWTVoice->eg2Value, &pWTVoice->eg2Increment, &pWTVoice->eg2State); pVoice->gain = (EAS_I16) DLS_UpdateGain(pWTVoice, pDLSArt, pChannel, pDLSRegion->wtRegion.gain, pVoice->velocity); #if (NUM_OUTPUT_CHANNELS == 2) EAS_CalcPanControl((EAS_INT) pChannel->pan - 64 + (EAS_INT) pDLSArt->pan, &pWTVoice->gainLeft, &pWTVoice->gainRight); #endif /* initialize the filter states */ pWTVoice->filter.z1 = 0; pWTVoice->filter.z2 = 0; /* initialize the oscillator */ pWTVoice->phaseAccum = (EAS_U32) pSynth->pDLS->pDLSSamples + pSynth->pDLS->pDLSSampleOffsets[pDLSRegion->wtRegion.waveIndex]; if (pDLSRegion->wtRegion.region.keyGroupAndFlags & REGION_FLAG_IS_LOOPED) { pWTVoice->loopStart = pWTVoice->phaseAccum + pDLSRegion->wtRegion.loopStart; pWTVoice->loopEnd = pWTVoice->phaseAccum + pDLSRegion->wtRegion.loopEnd - 1; } else pWTVoice->loopStart = pWTVoice->loopEnd = pWTVoice->phaseAccum + pSynth->pDLS->pDLSSampleLen[pDLSRegion->wtRegion.waveIndex] - 1; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * DLS_UpdateVoice() *---------------------------------------------------------------------------- * Purpose: * Synthesize a block of samples for the given voice. * Use linear interpolation. * * Inputs: * pEASData - pointer to overall EAS data structure * * Outputs: * number of samples actually written to buffer * * Side Effects: * - samples are added to the presently free buffer * *---------------------------------------------------------------------------- */ EAS_BOOL DLS_UpdateVoice (S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples) { S_WT_VOICE *pWTVoice; S_SYNTH_CHANNEL *pChannel; const S_DLS_REGION *pDLSRegion; const S_DLS_ARTICULATION *pDLSArt; S_WT_INT_FRAME intFrame; EAS_I32 temp; EAS_BOOL done = EAS_FALSE; /* establish pointers to critical data */ pWTVoice = &pVoiceMgr->wtVoices[voiceNum]; pDLSRegion = &pSynth->pDLS->pDLSRegions[pVoice->regionIndex & REGION_INDEX_MASK]; pChannel = &pSynth->channels[pVoice->channel & 15]; pDLSArt = &pSynth->pDLS->pDLSArticulations[pWTVoice->artIndex]; /* update the envelopes */ DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg1, &pWTVoice->eg1Value, &pWTVoice->eg1Increment, &pWTVoice->eg1State); DLS_UpdateEnvelope(pVoice, pChannel, &pDLSArt->eg2, &pWTVoice->eg2Value, &pWTVoice->eg2Increment, &pWTVoice->eg2State); /* update the LFOs using the EAS synth function */ WT_UpdateLFO(&pWTVoice->modLFO, pDLSArt->modLFO.lfoFreq); WT_UpdateLFO(&pWTVoice->vibLFO, pDLSArt->vibLFO.lfoFreq); /* calculate base frequency */ temp = pDLSArt->tuning + pChannel->staticPitch + pDLSRegion->wtRegion.tuning + (((EAS_I32) pVoice->note * (EAS_I32) pDLSArt->keyNumToPitch) >> 7); /* don't transpose rhythm channel */ if ((pChannel ->channelFlags & CHANNEL_FLAG_RHYTHM_CHANNEL) == 0) temp += pSynth->globalTranspose * 100; /* calculate phase increment including modulation effects */ intFrame.frame.phaseIncrement = DLS_UpdatePhaseInc(pWTVoice, pDLSArt, pChannel, temp); /* calculate gain including modulation effects */ intFrame.frame.gainTarget = DLS_UpdateGain(pWTVoice, pDLSArt, pChannel, pDLSRegion->wtRegion.gain, pVoice->velocity); intFrame.prevGain = pVoice->gain; DLS_UpdateFilter(pVoice, pWTVoice, &intFrame, pChannel, pDLSArt); /* call into engine to generate samples */ intFrame.pAudioBuffer = pVoiceMgr->voiceBuffer; intFrame.pMixBuffer = pMixBuffer; intFrame.numSamples = numSamples; if (numSamples < 0) return EAS_FALSE; /* check for end of sample */ if ((pWTVoice->loopStart != WT_NOISE_GENERATOR) && (pWTVoice->loopStart == pWTVoice->loopEnd)) done = WT_CheckSampleEnd(pWTVoice, &intFrame, EAS_FALSE); WT_ProcessVoice(pWTVoice, &intFrame); /* clear flag */ pVoice->voiceFlags &= ~VOICE_FLAG_NO_SAMPLES_SYNTHESIZED_YET; /* if the update interval has elapsed, then force the current gain to the next * gain since we never actually reach the next gain when ramping -- we just get * very close to the target gain. */ pVoice->gain = (EAS_I16) intFrame.frame.gainTarget; /* if voice has finished, set flag for voice manager */ if ((pVoice->voiceState != eVoiceStateStolen) && (pWTVoice->eg1State == eEnvelopeStateMuted)) done = EAS_TRUE; return done; } /*---------------------------------------------------------------------------- * DLS_UpdateEnvelope() *---------------------------------------------------------------------------- * Purpose: * Synthesize a block of samples for the given voice. * Use linear interpolation. * * Inputs: * pEASData - pointer to overall EAS data structure * * Outputs: * number of samples actually written to buffer * * Side Effects: * - samples are added to the presently free buffer * *---------------------------------------------------------------------------- */ /*lint -esym(715, pChannel) pChannel not used in this instance */ static void DLS_UpdateEnvelope (S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, const S_DLS_ENVELOPE *pEnvParams, EAS_I16 *pValue, EAS_I16 *pIncrement, EAS_U8 *pState) { EAS_I32 temp; switch (*pState) { /* initial state */ case eEnvelopeStateInit: *pState = eEnvelopeStateDelay; *pValue = 0; *pIncrement = pEnvParams->delayTime; if (*pIncrement != 0) return; /*lint -e{825} falls through to next case */ case eEnvelopeStateDelay: if (*pIncrement) { *pIncrement = *pIncrement - 1; return; } /* calculate attack rate */ *pState = eEnvelopeStateAttack; if (pEnvParams->attackTime != ZERO_TIME_IN_CENTS) { /*lint -e{702} use shift for performance */ temp = pEnvParams->attackTime + ((pEnvParams->velToAttack * pVoice->velocity) >> 7); *pIncrement = ConvertRate(temp); return; } *pValue = SYNTH_FULL_SCALE_EG1_GAIN; /*lint -e{825} falls through to next case */ case eEnvelopeStateAttack: if (*pValue < SYNTH_FULL_SCALE_EG1_GAIN) { temp = *pValue + *pIncrement; *pValue = (EAS_I16) (temp < SYNTH_FULL_SCALE_EG1_GAIN ? temp : SYNTH_FULL_SCALE_EG1_GAIN); return; } /* calculate hold time */ *pState = eEnvelopeStateHold; if (pEnvParams->holdTime != ZERO_TIME_IN_CENTS) { /*lint -e{702} use shift for performance */ temp = pEnvParams->holdTime + ((pEnvParams->keyNumToHold * pVoice->note) >> 7); *pIncrement = ConvertDelay(temp); return; } else *pIncrement = 0; /*lint -e{825} falls through to next case */ case eEnvelopeStateHold: if (*pIncrement) { *pIncrement = *pIncrement - 1; return; } /* calculate decay rate */ *pState = eEnvelopeStateDecay; if (pEnvParams->decayTime != ZERO_TIME_IN_CENTS) { /*lint -e{702} use shift for performance */ temp = pEnvParams->decayTime + ((pEnvParams->keyNumToDecay * pVoice->note) >> 7); *pIncrement = ConvertRate(temp); return; } // *pValue = pEnvParams->sustainLevel; /*lint -e{825} falls through to next case */ case eEnvelopeStateDecay: if (*pValue > pEnvParams->sustainLevel) { temp = *pValue - *pIncrement; *pValue = (EAS_I16) (temp > pEnvParams->sustainLevel ? temp : pEnvParams->sustainLevel); return; } *pState = eEnvelopeStateSustain; *pValue = pEnvParams->sustainLevel; /*lint -e{825} falls through to next case */ case eEnvelopeStateSustain: return; case eEnvelopeStateRelease: temp = *pValue - *pIncrement; if (temp <= 0) { *pState = eEnvelopeStateMuted; *pValue = 0; } else *pValue = (EAS_I16) temp; break; case eEnvelopeStateMuted: *pValue = 0; return; default: { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Envelope in invalid state %d\n", *pState); */ } break; } } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_mixer.h0000644000000000000000000000013213532747316026241 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.858000056 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_mixer.h0000644000175000001440000001105113532747316027030 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_mixer.h * * Contents and purpose: * This file contains the critical components of the mix engine that * must be optimized for best performance. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 706 $ * $Date: 2007-05-31 17:22:51 -0700 (Thu, 31 May 2007) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_MIXER_H #define _EAS_MIXER_H //3 dls: This module is in the midst of being converted from a synth //3 specific module to a general purpose mix engine #define MIX_FLAGS_STEREO_SOURCE 1 #define MIX_FLAGS_STEREO_OUTPUT 2 #define NUM_MIXER_GUARD_BITS 4 #include "eas_effects.h" extern void SynthMasterGain( long *pInputBuffer, EAS_PCM *pOutputBuffer, EAS_U16 nGain, EAS_U16 nNumLoopSamples); /*---------------------------------------------------------------------------- * EAS_MixEngineInit() *---------------------------------------------------------------------------- * Purpose: * Prepares the mix engine for work, allocates buffers, locates effects modules, etc. * * Inputs: * pEASData - instance data * pInstData - pointer to variable to receive instance data handle * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_MixEngineInit (EAS_DATA_HANDLE pEASData); /*---------------------------------------------------------------------------- * EAS_MixEnginePrep() *---------------------------------------------------------------------------- * Purpose: * Performs prep before synthesize a buffer of audio, such as clearing * audio buffers, etc. * * Inputs: * psEASData - pointer to overall EAS data structure * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ void EAS_MixEnginePrep (EAS_DATA_HANDLE pEASData, EAS_I32 nNumSamplesToAdd); /*---------------------------------------------------------------------------- * EAS_MixEnginePost *---------------------------------------------------------------------------- * Purpose: * This routine does the post-processing after all voices have been * synthesized. It calls any sweeteners and does the final mixdown to * the output buffer. * * Inputs: * * Outputs: * * Notes: *---------------------------------------------------------------------------- */ void EAS_MixEnginePost (EAS_DATA_HANDLE pEASData, EAS_I32 nNumSamplesToAdd); /*---------------------------------------------------------------------------- * EAS_MixEngineShutdown() *---------------------------------------------------------------------------- * Purpose: * Shuts down effects modules and deallocates memory * * Inputs: * pEASData - instance data * pInstData - instance data handle * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_MixEngineShutdown (EAS_DATA_HANDLE pEASData); #ifdef UNIFIED_MIXER /*---------------------------------------------------------------------------- * EAS_MixStream *---------------------------------------------------------------------------- * Mix a 16-bit stream into a 32-bit buffer * * pInputBuffer 16-bit input buffer * pMixBuffer 32-bit mix buffer * numSamples number of samples to mix * gainLeft initial gain left or mono * gainRight initial gain right * gainLeft left gain increment per sample * gainRight right gain increment per sample * flags bit 0 = stereo source * bit 1 = stereo output *---------------------------------------------------------------------------- */ void EAS_MixStream (EAS_PCM *pInputBuffer, EAS_I32 *pMixBuffer, EAS_I32 numSamples, EAS_I32 gainLeft, EAS_I32 gainRight, EAS_I32 gainIncLeft, EAS_I32 gainIncRight, EAS_I32 flags); #endif #endif /* #ifndef _EAS_MIXER_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_synth_protos.h0000644000000000000000000000013213532747316027670 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.858000056 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_synth_protos.h0000644000175000001440000000456113532747316030467 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_synth_protos.h * * Contents and purpose: * Declarations, interfaces, and prototypes for synth. * * Copyright Sonic Network Inc. 2004 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_SYNTH_PROTOS_H #define _EAS_SYNTH_PROTOS_H /* includes */ #include "eas_data.h" #include "eas_sndlib.h" #ifdef _SPLIT_ARCHITECTURE typedef struct s_frame_interface_tag { EAS_BOOL (* EAS_CONST pfStartFrame)(EAS_FRAME_BUFFER_HANDLE pFrameBuffer); EAS_BOOL (* EAS_CONST pfEndFrame)(EAS_FRAME_BUFFER_HANDLE pFrameBuffer, EAS_I32 *pMixBuffer, EAS_I16 masterGain); } S_FRAME_INTERFACE; #endif /* generic synthesizer interface */ typedef struct { EAS_RESULT (* EAS_CONST pfInitialize)(S_VOICE_MGR *pVoiceMgr); EAS_RESULT (* EAS_CONST pfStartVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_U16 regionIndex); EAS_BOOL (* EAS_CONST pfUpdateVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum, EAS_I32 *pMixBuffer, EAS_I32 numSamples); void (* EAS_CONST pfReleaseVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); void (* EAS_CONST pfMuteVoice)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, EAS_I32 voiceNum); void (* EAS_CONST pfSustainPedal)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, S_SYNTH_VOICE *pVoice, S_SYNTH_CHANNEL *pChannel, EAS_I32 voiceNum); void (* EAS_CONST pfUpdateChannel)(S_VOICE_MGR *pVoiceMgr, S_SYNTH *pSynth, EAS_U8 channel); } S_SYNTH_INTERFACE; #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_smfdata.c0000644000000000000000000000013213532747316026527 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.858000056 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_smfdata.c0000644000175000001440000000441213532747316027321 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_smfdata.c * * Contents and purpose: * SMF File Parser * * This file contains data definitions for the SMF parser. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 778 $ * $Date: 2007-07-23 16:45:17 -0700 (Mon, 23 Jul 2007) $ *---------------------------------------------------------------------------- */ #include "eas_miditypes.h" #include "eas_smfdata.h" /*---------------------------------------------------------------------------- * * S_SMF_STREAM * * Static memory allocation for SMF parser *---------------------------------------------------------------------------- */ static S_SMF_STREAM eas_SMFStreams[MAX_SMF_STREAMS]; /*---------------------------------------------------------------------------- * * eas_SMFData * * Static memory allocation for SMF parser *---------------------------------------------------------------------------- */ S_SMF_DATA eas_SMFData = { eas_SMFStreams, /* pointer to individual streams in file */ 0, /* pointer to next stream with event */ 0, /* pointer to synth */ 0, /* file handle */ { 0, 0, 0, 0}, /* metadata callback */ 0, /* file offset */ 0, /* current time in milliseconds/256 */ 0, /* actual number of streams */ 0, /* current MIDI tick to msec conversion */ 0, /* ticks per quarter note */ 0, /* current state EAS_STATE_XXXX */ 0 /* flags */ }; drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/PaxHeaders.32572/eas_pcmdata.h0000644000000000000000000000013213532747316026526 xustar0030 mtime=1567346382.705999859 30 atime=1567346382.858000056 30 ctime=1567346382.705999859 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/lib_src/eas_pcmdata.h0000644000175000001440000001701513532747316027323 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_pcmdata.h * * Contents and purpose: * Data declarations for the PCM engine * * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 847 $ * $Date: 2007-08-27 21:30:08 -0700 (Mon, 27 Aug 2007) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_PCMDATA_H #define _EAS_PCMDATA_H /* sets the maximum number of simultaneous PCM streams */ #ifndef MAX_PCM_STREAMS #define MAX_PCM_STREAMS 16 #define PCM_STREAM_THRESHOLD (MAX_PCM_STREAMS - 4) #endif /* coefficents for high-pass filter in ADPCM */ #define INTEGRATOR_COEFFICIENT 100 /* coefficient for leaky integrator */ /* additional flags in S_PCM_STATE.flags used internal to module */ #define PCM_FLAGS_EMPTY 0x01000000 /* unsigned format */ /*---------------------------------------------------------------------------- * S_PCM_STATE * * Retains state information for PCM streams. *---------------------------------------------------------------------------- */ typedef struct s_decoder_state_tag { EAS_I32 output; /* last output for DC offset filter */ EAS_I32 acc; /* accumulator for DC offset filter */ EAS_I32 step; /* current ADPCM step size */ EAS_PCM x1; /* current generated sample */ EAS_PCM x0; /* previous generated sample */ } S_DECODER_STATE; typedef enum { PCM_ENV_START = 0, PCM_ENV_ATTACK, PCM_ENV_DECAY, PCM_ENV_SUSTAIN, PCM_ENV_RELEASE, PCM_ENV_END } E_PCM_ENV_STATE; typedef struct s_pcm_state_tag { #ifdef _CHECKED_BUILD EAS_U32 handleCheck; /* signature check for checked build */ #endif EAS_FILE_HANDLE fileHandle; /* pointer to input file */ EAS_PCM_CALLBACK pCallback; /* pointer to callback function */ EAS_VOID_PTR cbInstData; /* instance data for callback function */ struct s_decoder_interface_tag EAS_CONST * pDecoder; /* pointer to decoder interface */ EAS_STATE state; /* stream state */ EAS_I32 time; /* media time */ EAS_I32 startPos; /* start of PCM stream */ EAS_I32 loopLocation; /* file location where loop starts */ EAS_I32 byteCount; /* size of file */ EAS_U32 loopStart; /* loop start, offset in samples from startPos */ /* NOTE: For CMF, we use this to store total sample size */ EAS_U32 loopSamples; /* total loop length, in samples, 0 means no loop */ /* NOTE: For CMF, non-zero means looped */ EAS_U32 samplesInLoop; /* samples left in the loop to play back */ EAS_I32 samplesTilLoop; /* samples left to play until top of loop */ EAS_I32 bytesLeft; /* count of bytes left in stream */ EAS_I32 bytesLeftLoop; /* count of bytes left in stream, value at start of loop */ EAS_U32 phase; /* current phase for interpolator */ EAS_U32 basefreq; /* frequency multiplier */ EAS_U32 flags; /* stream flags */ EAS_U32 envData; /* envelope data (and LFO data) */ EAS_U32 envValue; /* current envelope value */ EAS_U32 envScale; /* current envelope scale */ EAS_U32 startOrder; /* start order index, first is 0, next is 1, etc. */ S_DECODER_STATE decoderL; /* left (mono) ADPCM state */ S_DECODER_STATE decoderR; /* right ADPCM state */ S_DECODER_STATE decoderLLoop; /* left (mono) ADPCM state, value at start of loop */ S_DECODER_STATE decoderRLoop; /* right ADPCM state, value at start of loop */ E_PCM_ENV_STATE envState; /* current envelope state */ EAS_I16 volume; /* volume for stream */ EAS_I16 pitch; /* relative pitch in cents - zero is unity playback */ EAS_I16 gainLeft; /* requested gain */ EAS_I16 gainRight; /* requested gain */ EAS_I16 currentGainLeft; /* current gain for anti-zipper filter */ EAS_I16 currentGainRight; /* current gain for anti-zipper filter */ EAS_U16 blockSize; /* block size for ADPCM decoder */ EAS_U16 blockCount; /* block counter for ADPCM decoder */ EAS_U16 sampleRate; /* input sample rate */ EAS_U8 srcByte; /* source byte */ EAS_U8 msBitCount; /* count keeps track of MS bits */ EAS_U8 msBitMask; /* mask keeps track of MS bits */ EAS_U8 msBitValue; /* value keeps track of MS bits */ EAS_U8 msBitCountLoop; /* count keeps track of MS bits, value at loop start */ EAS_U8 msBitMaskLoop; /* mask keeps track of MS bits, value at loop start */ EAS_U8 msBitValueLoop; /* value keeps track of MS bits, value at loop start */ EAS_BOOL8 hiNibble; /* indicates high/low nibble is next */ EAS_BOOL8 hiNibbleLoop; /* indicates high/low nibble is next, value loop start */ EAS_U8 rateShift; /* for playback rate greater than 1.0 */ } S_PCM_STATE; /*---------------------------------------------------------------------------- * S_DECODER_INTERFACE * * Generic interface for audio decoders *---------------------------------------------------------------------------- */ typedef struct s_decoder_interface_tag { EAS_RESULT (* EAS_CONST pfInit)(EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); EAS_RESULT (* EAS_CONST pfDecodeSample)(EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState); EAS_RESULT (* EAS_CONST pfLocate)(EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 time); } S_DECODER_INTERFACE; /* header chunk for SMAF ADPCM */ #define TAG_YAMAHA_ADPCM 0x4d776100 #define TAG_MASK 0xffffff00 #define TAG_RIFF_FILE 0x52494646 #define TAG_WAVE_CHUNK 0x57415645 #define TAG_FMT_CHUNK 0x666d7420 /*---------------------------------------------------------------------------- * EAS_PESeek *---------------------------------------------------------------------------- * Purpose: * Locate to a particular byte in a PCM stream *---------------------------------------------------------------------------- */ EAS_RESULT EAS_PESeek (EAS_DATA_HANDLE pEASData, S_PCM_STATE *pState, EAS_I32 *pLocation); #endif /* _EAS_PCMDATA_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316025237 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.858000056 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/CMakeLists.txt0000644000175000001440000000303513532747316026031 0ustar00pedrousers00000000000000set( SOURCES host_src/eas_config.c host_src/eas_hostmm.c #host_src/eas_main.c host_src/eas_report.c host_src/eas_wave.c lib_src/eas_chorus.c lib_src/eas_chorusdata.c lib_src/eas_data.c lib_src/eas_dlssynth.c lib_src/eas_flog.c #lib_src/eas_ima_tables.c #lib_src/eas_imaadpcm.c #lib_src/eas_imelody.c #lib_src/eas_imelodydata.c lib_src/eas_math.c lib_src/eas_mdls.c lib_src/eas_midi.c lib_src/eas_mididata.c lib_src/eas_mixbuf.c lib_src/eas_mixer.c #lib_src/eas_ota.c #lib_src/eas_otadata.c lib_src/eas_pan.c lib_src/eas_pcm.c lib_src/eas_pcmdata.c lib_src/eas_public.c lib_src/eas_reverb.c lib_src/eas_reverbdata.c #lib_src/eas_rtttl.c #lib_src/eas_rtttldata.c lib_src/eas_smf.c lib_src/eas_smfdata.c lib_src/eas_tcdata.c lib_src/eas_tonecontrol.c lib_src/eas_voicemgt.c #lib_src/eas_wavefile.c #lib_src/eas_wavefiledata.c lib_src/eas_wtengine.c lib_src/eas_wtsynth.c #lib_src/eas_xmf.c #lib_src/eas_xmfdata.c lib_src/jet.c lib_src/wt_22khz.c ) add_library( sonivox STATIC ${SOURCES} ) target_compile_definitions( sonivox PRIVATE UNIFIED_DEBUG_MESSAGES EAS_WT_SYNTH #_IMELODY_PARSER #_RTTTL_PARSER #_OTA_PARSER #_XMF_PARSER NUM_OUTPUT_CHANNELS=2 _SAMPLE_RATE_22050 MAX_SYNTH_VOICES=64 _8_BIT_SAMPLES _FILTER_ENABLED DLS_SYNTHESIZER _REVERB_ENABLED _CHORUS_ENABLED ) target_include_directories( sonivox PUBLIC host_src PRIVATE lib_src ) set_target_properties( sonivox PROPERTIES POSITION_INDEPENDENT_CODE true VERSION 3.6.10 ) drumstick-1.1.3/library/rt-backends/eassynth/sonivox/PaxHeaders.32572/sonivox.pro0000644000000000000000000000013213532747316024726 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.858000056 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/sonivox.pro0000644000175000001440000000455513532747316025530 0ustar00pedrousers00000000000000#------------------------------------------------- # # sonivox library # #------------------------------------------------- QT -= core gui QMAKE_LINK = $$QMAKE_LINK_C #QMAKE_LFLAGS_RPATH = QMAKE_CFLAGS_WARN_ON += -Wno-unused-parameter -Wno-unused-value -Wno-unused-variable -Wno-unused-function TARGET = sonivox TEMPLATE = lib DESTDIR = ../../../../build/lib VERSION = 3.6.10 CONFIG += staticlib \ create_prl \ stdlib \ warn_on DEFINES += \ UNIFIED_DEBUG_MESSAGES \ EAS_WT_SYNTH \ # _IMELODY_PARSER \ # _RTTTL_PARSER \ # _OTA_PARSER \ # _XMF_PARSER \ NUM_OUTPUT_CHANNELS=2 \ _SAMPLE_RATE_22050 \ MAX_SYNTH_VOICES=64 \ _8_BIT_SAMPLES \ _FILTER_ENABLED \ DLS_SYNTHESIZER \ _REVERB_ENABLED \ _CHORUS_ENABLED TARGET = sonivox INCLUDEPATH += host_src lib_src HEADERS += host_src/eas.h \ host_src/eas_chorus.h \ host_src/eas_reverb.h \ host_src/eas_types.h SOURCES += host_src/eas_config.c \ host_src/eas_hostmm.c \ # host_src/eas_main.c \ host_src/eas_report.c \ host_src/eas_wave.c \ lib_src/eas_chorus.c \ lib_src/eas_chorusdata.c \ lib_src/eas_data.c \ lib_src/eas_dlssynth.c \ lib_src/eas_flog.c \ # lib_src/eas_ima_tables.c \ # lib_src/eas_imaadpcm.c \ # lib_src/eas_imelody.c \ # lib_src/eas_imelodydata.c \ lib_src/eas_math.c \ lib_src/eas_mdls.c \ lib_src/eas_midi.c \ lib_src/eas_mididata.c \ lib_src/eas_mixbuf.c \ lib_src/eas_mixer.c \ # lib_src/eas_ota.c \ # lib_src/eas_otadata.c \ lib_src/eas_pan.c \ lib_src/eas_pcm.c \ lib_src/eas_pcmdata.c \ lib_src/eas_public.c \ lib_src/eas_reverb.c \ lib_src/eas_reverbdata.c \ # lib_src/eas_rtttl.c \ # lib_src/eas_rtttldata.c \ lib_src/eas_smf.c \ lib_src/eas_smfdata.c \ lib_src/eas_tcdata.c \ lib_src/eas_tonecontrol.c \ lib_src/eas_voicemgt.c \ # lib_src/eas_wavefile.c \ # lib_src/eas_wavefiledata.c \ lib_src/eas_wtengine.c \ lib_src/eas_wtsynth.c \ # lib_src/eas_xmf.c \ # lib_src/eas_xmfdata.c \ lib_src/jet.c \ lib_src/wt_22khz.c drumstick-1.1.3/library/rt-backends/eassynth/sonivox/PaxHeaders.32572/res0000644000000000000000000000013213532747316023213 xustar0030 mtime=1567346382.697999849 30 atime=1567346382.858000056 30 ctime=1567346382.697999849 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/res/0000755000175000001440000000000013532747316024061 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/eassynth/sonivox/res/PaxHeaders.32572/test.ota0000644000000000000000000000013213532747316024754 xustar0030 mtime=1567346382.697999849 30 atime=1567346382.858000056 30 ctime=1567346382.697999849 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/res/test.ota0000644000175000001440000000003613532747316025544 0ustar00pedrousers00000000000000J:Qѕ Ua`UPT@Idrumstick-1.1.3/library/rt-backends/eassynth/sonivox/res/PaxHeaders.32572/abba.imy0000644000000000000000000000013213532747316024675 xustar0030 mtime=1567346382.697999849 30 atime=1567346382.858000056 30 ctime=1567346382.697999849 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/res/abba.imy0000644000175000001440000000066613532747316025476 0ustar00pedrousers00000000000000BEGIN:IMELODY VERSION:1.2 FORMAT:CLASS1.0 NAME:DanceQueen COMPOSER: downloaded at www.ringtones.perbang.dk BEAT:112 STYLE:S1 VOLUME:V10 MELODY:*5#c1*4b2*5d1*5#c4*4b3*4a4*4b3.*5#c3*5#c2*5a4*5a3*5#g4*5#g3*5#f4*5#f1*5#c1*4b2*5d1*5#c4*4b3*4a4*4b3.*5#c3*5#c2*4b2*4a1.r2*5#c2*4b3*4b1r4r5*5#c2*4b3*4b2*5#c2*4a3.*4b3.*4#g3*4a3.*4b3.*4#g3*4a4*4#g4*4#f2.*5#c3*4b3.*4a3*4#g2*4a3*4a1r4*4#g2*4a3*4a2.*4b4*4a3*4#g4*4#g3.*4a3.*4a1 END:IMELODY drumstick-1.1.3/library/rt-backends/eassynth/sonivox/res/PaxHeaders.32572/ants.mid0000644000000000000000000000013213532747316024730 xustar0030 mtime=1567346382.697999849 30 atime=1567346382.858000056 30 ctime=1567346382.697999849 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/res/ants.mid0000644000175000001440000000561413532747316025527 0ustar00pedrousers00000000000000MThdxMTrk vuntitledCopyright 2001 by davedaveXYQu A*v$! A&dd (x 2CZ xAZ Z>Bi A A7z39>]2vJd37*$92J>> *%& *-*v(*(=Z%X*b$*&]%>B=$ *zBZ*K &>*B*%]=O9>2g*V *29> &X>R%=*v(*Bd >& *>v92o( >X&r**]$ B*'>$7]&*Z+j>~;~2*9>>+;7*D */(**#%j=K*b(*&X>N=%L*+CbNd&>L* NC+L0JbLCI;+g**Q+z>LoJ** ;L+>G]C$n+ G$JrCg+z*(*-o>~Ez;++bCJL*]$l(Ng*L $>N >b>E*v$2d&z9j;+- *>92>$ *K&* (*r*(=2*b$%g*=>8&j%$B]*Z*z>&*%B=K9~2o*D>*%r* 29> =&r>\%*z(Bd*z >&*9r>2g (B>^Qz*&v*^$X8X*Q So S$>7d*VSz+j;r>&2>9*TmSSoT+;7>S*%Qo*QS*(SQo*QOvO%r=:Nz*g(*N&g>Q%=JQJC\+v*LB&>*LC+*<Nr*NJv;+v>CV*b+~;J>*+GFC+$u G $L+~Cd(*9~1v 19 *ErC-b>L+J;+dJGm*b$^( *EbG$> 2m*r$&>b9m>7b3-E;+73*29>$>&EGm*Q*G)(*v*(*g$=?%r*&Z=%>F$BR*v*b &>*#BS2r>T9~%m=I*7*S2>9*%&g=>VB^(*v*v >&*9z>2o(B>\*b$&v**>$7d+m;~>*d2SD9&>T S*TbSv>+;7T *^SQ*Q (*m*!(=:*^$%o*$&X>N%=CX*o$+zO >&*OC+Q$Q;>*$CK+d+z>;+$C+*$Cb*r(+~JJ*Eo>+bC-m;z+ ( *d$L*$NL >&*o$>^3v72b>E9m;N-37+ *92>$> *X&*!*v(*&*j$=I%r(*=%&j>I$BX*r*Z >& *B *=QJVNv9v2j>*R%r *NJ29>&Z%>R=BZ*z(*v >& *9rN2]JX>B*j$>Z&v* ( *J $ N>Jv7bOr;v*b+d>92j>*JO&+ ;>7 *V9g1v* 19%*z(*(=D*]%z7U *7 >:=&b%( CZ+z*37>&73*C**+*OJb*mCU+z;~>+\ OJ;>+C$x*+$+z*(Cz9~1z19 -rE\Oo>vJOC*;++g(*b* J>Nr>VJ^2m3v7&~>-O9~E;+37 NJ29>>&/drumstick-1.1.3/library/rt-backends/eassynth/sonivox/res/PaxHeaders.32572/test.mid0000644000000000000000000000013213532747316024742 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.858000056 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/res/test.mid0000644000175000001440000000025713532747316025537 0ustar00pedrousers00000000000000MThdxMTrk/Copyright (C) 2006-2019 Pedro López-CabanillasQ 'X$Y AB@Ax<>@x<@AxM%;qHb%?i=V Ia #^-S aI#P;k9m LJ e * gE1$*0Kj&{QU !#+%&(&*+}-,/0h23S4:4K474E404?4)4<4#4944644444;43V43&5*r`Z#Ixhl'H4jNgvSy9RR9D*bx>V-Wu)Dg /NtNXRC) j'D6uL}=e.b3z'( f % r <jb " $%Q')*r,./G123@44;4 4744643443343543<43J43k4o3Z3[ d7'jwtFN5qe{ E2eO`fhWvq7}n^[;B!Yk+=r s@m"R*lPk  o 3 >hyc}!"$B&()Y+,.<01M3(43&43"43 43 43!43#43-43E4s3425HwLTc-9FK<^Qn ""?;Z^l_kD~9_Hi$Gn!Cb6[{%Dg (D h-QW;t:i)U S79 W  { X=-""/Hm/bh !#;%&(3*+-4/0e2343333333333333333334,tBDQ& &3)VOik(L w-ܭrB!qWFF#1m{EV1`w,An 3Lv(iuqf@k/94q9e.ZF)m f$ R % t|vY ge!"7$%')*k,../j12333333333333333~34U3?4244 QD} (Q$eC[w7Z V6J.+huAX2az.Qv?_#DdBkf9q x!bZ6a6S~$Jh1Xu4Vv9JLE1G^ Z=n 8dQzK23 V  ]E2-.AXH "#^%'(V*+-M/0v233333333333333333333.a6P'D,_J[{'`ilb߷' kjER1cy4PzFb *Mh *ZJj? CN:qAp)R|Oft c ! 9i !"J$ &'^)*,3./g1333333333y33k33Y33>333'424a*,rr>SVt1<ETavv] iaSD)*ov DT&Xj%7jx+?n~v " W77r@o8eK|!`Je  w > ".kD$ !M#$&C()+0-.p02J33333333z33o33b33N33)3325t%m:Asbz+Pa)5CP]ivf'YcjA];f:[)Nj4Wv3Yz)jhAd!sK{Do)PY2< ] * vRP@PXzG= `"#%,'(*A,-/12y3333{33t33l33c33W33I33933O303>&i.jiX.(L<jRftvK-x< m@4.|y QW+es/?q 7Jv 6Lv2bk(e \OFo7aK2xp3 c : HaG[!"$&'g),+,x./123m33f33]33S33G334333324\2 5dgc&,[}-s!}Yk1D$b:Ncu9ٖ.C*Qc(9i:W~"Fa (Ij 'FF[he[>}?XE XCl,Y$j_s + [ 5 0[~Yd !#%%&o( *+l-/0&2X3z33q3}3j3x3b3u3Z3t3Q3u3B3}3'3324(;y?;}S FR"FVf`9/RDrYiH1cJڈw /Qx .Tt$Gn<[$Eb%Hc6QxK A?.b&S~;h,dOH ~ : ipn[ln !"7$%}')*^,./L123]33W3~3P3{3G3{3<3|3.3333232\2 :6%@yskDa2eL_ $; e.+u\0&ttCT$Ul 8c{&?d'Bd~i.COKA*g"?+i <H R 4 -IE~ !G#$& ()Y+-.b0143Y3}3L3}3A3}373~3*33332323A250SZo)/443BCe[vx!8.VAuPfQݎx bY.3sx4>Olf1$ >"#{%'(d* ,-P/0g2U3`3`3Z3Z3U3S3P3N3L3I3I3@3G313T323t,L`;,0#8?VVlt =%`/*{ -Wr&Ei9Y|"?a$Aa;\< $/1"Mo"q LJx*O{Oaq h %  U@(8!"g$+&'t)*,6./^12F3n3;3o333p3&3q33u3332323^23sK}>4]q40 )(D>^ZlzEj 8 ڌ۫j0eWJ ad-3lv0?q/@my&85kiO_ j[([#Lp&S(jU w ( T :9T+vSX !#0%&s(*+M-/0&2"3f3>3a383_3/3_3$3b33h32y323T24",$  ?&S=kUo4 Ue?4@_&zgef9t >gAk9jNW { G {|s"c!"3$%p'#)*m,-/'12G3S3A3O383L313J3*3G3"3D33B33/3Y3/k"$IM)r -)BFV`ox8 aA9ޯ>FtF[(Qj2Yq3[q)Sg2kfB U_ RIx>^@qU=^ m 3 )pB !?#$t&4()|+-.5012e3+3_3#3^33_3 3c32n32323.2z4f;@4D"]4uPd}-Wl`Zr A!wj9F|>QD[@Y7Qs $  l0V S.f'Pw .W R;7 e $ wbOTNn2}F8 S"#%5'({*,-O/0Y2J343R3.3O3&3M33M33O32\323u24&cUq}z+1BJY_qu &7*Dy0gY'.gq*>l}+?n%?gz0Unv(g{^5FT>yAn)Hs1d?.A | J  ?ri!#$:&'z)5+,u./12W3-3P3%3L33K33K3 3M32S32`321fCU2WB81,p*?1UBn^s!P݃٢x ?f-Jp2Ru2Pp 'Fe;W d#NF,X@c&Qu={*~ R  PG&4#GSE "#>%&{(C*+-.0 2D3&3\33\33\33b32m3232324u*#.J#v$+=@Mabvw'_3i4ߌ1mW)$kg*2is"-`q(Vesm'fwr])9N5m >_?_$U*nw) l - MF*7!"a$&'E)*,"./F12A3>3:3<34383+353#3433833P324h*l ~f31KGb]wsOؙܲߌS[!Ub$Ma !I]=Ry  dJ>$S6[Fr3n pz ? n ?/ .7qgi !#%&G( *+O-.01+3)3U33U33V3 3Z32a32q323x22 rSvy0@jy 42FHZ^px/;Sp\=߫ߪ"/dl'7hq"3`u+Rg GYSv/fu\,7O2l 5_5Z"Q`k [  3h "&$%^')*[,-/02-3P3'3O33Q33U33^32s323124 R*m 6L,c?|Tm}R 7-݀R߯߇!\Z"Xh O`AT|.Cf+]E<{ O| 3Tz4e0eWl ) x P ,It\., !K#$&()Z+-.6012A3A383>31393)353%313 3'3"333-2p@N*C6VMkat0]qxJߖ߇ HO>S5Ns&?c|,Kf/y0]|sT)~3E,f.T~/OyF{W^ x I  vva|{ <e_ r"#%'(_*%,-c/0j23Z3"3[33]3 3a32k32323>24og*$\^pt) @$Q8mL}cv. H.A_kߑ߫)Ok (Hg!=Zz,Ji1M7[CALq 4Wz-U'dLg  q 4   \+!#$<&'})6+,r./12_3)3W3"3W33W3 3^32m323X24N$lWL42FDbTvjx2}eۭHuAߧ߆UO JP8Er|#1Zo[+?iX1~;G1j+Vx /Sw:t RR q 7 d_P_e|?. >"#p%&(3*+j-/0/23W333S3*3P3"3P33R3 3U32T33O0e}M*Kk%-7AMX_nuW= 93= \@ߏ߆ BF1As!1Ym DX~H\&ACIp 2Xz)R~&a@_  h ( Gh}]h!"$ &'A) +,F./h12m3%3l33l33o32z32323&24)(F{o[r $ 45GKZfh|84(eeߢߢ%U^ GT 4Gm~.Te11Jn^8?G6l1Q|3Tx 7oRI s , v`LHI[u] "#9%&p(*+V-.|01&3I3Q3@3O383M3-3N33U33v32Y4(5 $zNn| $;&O7fJz^l~/q*ځBnRߣߕSS =Iy*7\nCU{d +(/k4NK"N>\ -W(aC`  a ' 6]gCK!"p$%'))*d,./B12e363f3-3f3#3f33k33x3232%2 A6Imu)>.P@bTyfx#W]ߒߠ BX| -Jh*Pj-KfJ[lFNWBq4Y7Z :lVD r & iX=C5MY;us !# %&A()x+9-.g01(3B3n333o3$3s33}32323?25=-yXwh$ 9 J4`IrWk|mi*ܒ-9ivߣ߳.Th:Os9[r4Ql y6;6%w7ZS+^8]|4Z _FQ P $ N:!"3$%h' )*H,-v/0y2O3[3W3W3P3R3I3O3@3P313^323$,0U'D@o!:%K9bGu\k{"jSޠ7jZߢߖJM.;gxHX~$8bZ&dvJQ[Cz3o383b3t3l/b",1J1Ol#!9/JEaStds~rt.fؽ+ݰtި B(ueߩߢPP,2di:Gt~FIT_LGKt`@v&HcFm#_ TQ  E $ ;dr "#%'(N*,-I/0T2.33J33=33-333323a24#n5c|wkio 5G3UFhU~h|ݥފ޾,9duߘ߬ >Vw1Rk+C]|'Wk7qy\,Wz &Lf"O~WR h + cB4'+E]X! !&#$N&'~)*+,[./w123f33^33S33C33"3324+'s<FcXy  1!<3U@gTyctd6ُHuޫޝ HP|߅߽߰"1Zg 0Cdw8Lnf 7dnxh]8`#)rP5Yr +Mu1hVV  M % 0]qV ^"#%'(>*+o- /0+2533e33\33P33A33*3331o ;2&%+% S}+9O.^@sP`n|%qfQئ݊T޳މC=xx߭߯!OW%5Wk +?]sH(sJ3,o =e7Qs 1Y] ] j 9 n=9*#ENJ!#$-&'])!+,S./o123_33T33B33'3324l2*5l,65J i}2'@<QJe_pvLۧ݇cޤޓ ;Eu|ߨ߱$LU|0Qa&6Vi(`yoR(2C([$Np2WFx[h  ^ & #gaB M"#k% '(<*+p-.02M33333x33k33W333k4*Ht_ + 52KAYOra~r}"fj/z1Pޒz޸ް"#Q[ߊߕ߿'6\k-?`r.DmqM e(IB~Pw(K^=i/gc p ? wD<-$HRJ !"$ &'Q)+,C./]123r33f33W33C33"332 3 ~GI q~ "39>ML\aqjzx/ޝ`ޠ$ZKߍ߃߾߻&$ZZ'+[d'0K Fn=CW4m<^$@`(Uds  k ( hR/ 1"#O%'~(>*+o-.01^333u33c33J33342O5>&G-w  );-GA\Mmbxr-hۢ[Mz|ާ޷&D]}ߑ߬-Ga0Ja|Q9w$6?;, AaX5a<]y.Lt >{"m F  yTA/,/I`Q!#$#&'X)*,%./>123333333333a3 46-}C8tq$ 62FBVPi^|k}/hnSr#+uUޞޏ63dhߙߚ09cm.:[k }9nX+_rN$Op(>AhSnf!#|$%&'U)*,-/12333333p33I342D5#,e~!*)<6OHX[ley}Iۄ<,[]ދސ޹+N`߂ߓ߳+I\}"?Uu$Rt?|,)f2_|0LkBm=. 8 { < ^N& &"#?%&h( *+A-.e01?333333333333/X:<7Q3Xz  -:)P5]IlU~fs @f KUQ6vlީޠ 6(=c>yb6 '%38CERSddnuU׮n8ra!"q$%')*-,-M/ 1M23343&43843o435"*(2V\1"''66?CQPYhfqw| @rרڮ )M)uYޡލ޼#PM{{ߧ߬,3W_"XNObr`W4j)6#Y?]z $E_~D~a m # m 9/]K "#(%&J()r+,.01 34343 4343374v/|h[ `@'40<@LG[\fdzrp׍: 18\hމޔ޺ !>Khzߗߣ,OVwr1 [P?C}Ch%D`w?b <ze " ?  yP]Dig;qa!"q$%'(*,-=/19233:43E43\4343'5J0EH2<4@@RK^Xkmq{*T@ܽݶ *TAނoޫޞ+*XT߄߃߭߰ /3Zb wCp~yO2FJ=v-Rq%<Z{$W3t z 5 w N.kD "#%&8()`+-.*01 33-43.43943a4g3a5}'tZJAr9%0 #4$?0L=]HhZsep}1I6יڙݯ + S?|mޡޚ% NOyߨߩ&-OW{\8~i8U[,[UB׎ڃݕ5!_Lރzޫާ*)NU|߂ߥ߫!)EU{fd!`f:w+*h5^/H`~+OrR5 S  h2/x@  !#%&()D+-b.#0o133f4 4j43y43434_=rVi}#>G(?3Y:_PiXxgu#=stݲ,1Q^{ކާ޴".HYu߄ߞ߫#@LB2?Si`Q4k-;-bB]~+Bb 7dO F  } 2 hzrdZB!"F$%]')*:,-]/0g23m44u43434Y35"+xs^K?Q9?C9YH[^fdvs{ 1Lst;ۖݏݳ"E9nbޓޏ޼޼ 69`d߈߇߯ߵ$-i.Y_PE$U| *G`y %Ei(hU j  |L,  0K W" "#%&7()\+,|.0134Z4B4Q4<4H4B4&44.l<i~O0'PGCV[Zdphw|&7I`לځ݊ݳ'K:sfޚލ޺޷53[]߁߄߫߮#+oCtY;QU K9[x+F`|$Lz$f [  E |w hM!"J$%e' )*G,-f/0q234!44 443434`6W L6Y\?ZDoQpd~jz .Elݟݪݼ,EUkޗޥ޼ 2B\k߂ߐ߽߫ XWT1 }=ja>n#BYw;Z<sg  t 6 c5'   -a k0 #"#-%&G()k+,./12A4E44/44 4435%]" ,8RvSZ #l#MN]GoVucpx#0E]Lsݛ'KEqkޙޕ55U^߄ߣ߬ %*=k}Z#mt!`+Tu %@Ws:b3x l & W *(quT!"X$%j' )*3,-S/0V23y4P4}4D4484{4_4?1F 7I+TV.mMd\u^l{&3FYg=גrܩqݙ'KFqmޕޔ޹޺ +4PZv߁ߝߧ߿Vb9AG6_1~Y;\u6SpO+  H uA703q xB ."#5%&S()x+,./12[4E44(443435R#bC$Ev-nVoXfr} '1 C\/b܏ݍݪݭ%?Icrއޔެ޺/EUkzߑߣ߷_b!cuG ;9xKn8Sk/R} J+ 0 o 2 8sl!"j$%'(*,-:/0823c44^44D44359*H?@vLRtchzzw-= M h'>m^ݯݭ /&QIvrޛޙ޿ .1QYt}ߚߥ^4%:[efP<{4J4n0Nn-Ee3bA * W  ~M@$4;swA '"#-%&G()l+,./12U4_44J44-4443B|y`67goBhuoy#-9M`q|MܓQݱvݢ -MBpgޖސ޸޲'&HGllߑߓMg"[N1a ,K]{-GiQ> 9  ;!Fpk!"m$%'(* ,-/023U44K44 4536 ^V3o1XE}s}lz &++<2C6`q Dqt݌ݕݮ*9Rbrނޘެ޾%5K_n߮|jY=c}uZ9 Qb SCi.@[y"IwS A b  ]H1-(:Mtv: !"#$%&=()[+,z./12=444444`45a.4Y4<Qeg}~ $-;I]y :ZEݝjݰݐݹ7+WPzuޞޚ)*MKkt 9F~!D vgMx&Ea{ '>^}1bW M  J,Qwx!"q$%'(* ,-/023`44\4474535|n3L(ZSPtPv{ . 6DT`$tzrFyEݘjݯݏݺ*)NMooޑޔ޶޺$:E^ߠߥ2e^(u"'i4`)>Yp:a$b W o 8 yQH6A>dz2r5 "#%&0()M+,f.0n13"44q44O4536~%PbFh` #*#7(A5K9]9q(=`aw~ݗݥݺ -AOeuއޖި޶1?b {]7EG<#i'<*e%Dc <Sn L"j j ' g<!^2~!"y$%')*!,-;/0<234444444098/y?4'Ohk + 7DJ%^n"bFI6݅Tݘ{ݷݣ60UUxxޗޛ޻޾ &>ߩY[iRFD%S| ,AZp7W{:y$ w   M _aE[P~OB &"##%&3()M+-c..0g1/344n45D495355@",s;bm (1&=,H2T9c:q6:AׅSq'J~U  `  x Er+Wx Z"#Y%&l()+,./124454M54V69$*od1,#*)5)=6C<O<YDeGrJ|LFHo_;V f?cݛ݆ݶݥ%!BAaa}~ޗޗqXYl\'QV.`4Rcw5Nt6j Y  m , uT.,Xb& !#$&'!)*=,-S/0U2344444!50YhrtKi  #!,&6/=6B=N?VN[RgVmXR-Yۙ-4GVgr}݌ݞݪݻ 28HZkxޅޖ /@/!JhsyjS2O h O%Il&<Sc<_$b  r  \z2X c"#c%&s()+,./1244954l5)45-H#{i}!&'#7,;5@8P9XCbDkHyID4_&w:K#eC݀eݙ݁ݯݠ:4URqn޵ލ "G tBk oDr/Pez)CaL g   3 \C ?]a# ! #$ &')*/,-?/0?234!54C5c4,6(lJ,T   '.8);/E2M:W@\JhEqPxPROTLqN2@!YCtb݋|ݦݛݷ ,,EEdmZqZMnwL&j'$i ;b "=Rcz*Mt:v (  ( i-@m g"#e%&s()+,.01244%54*542l :^X^Zb3 #!*'/.46<9CEHMRST^Zabkdwf_6_ڃ&7AV^rzݍݓݦݯݿ/7KSް޿BV-z*2$d9$b'Jgw)@Yp 2_. { . E jV--)'Rf-h* ! #$ &')*-,-:/10234O54554V6U5TEjt! "--6A&D,O2S8]9eDhFxENKF6"l%2 D)\Fsfݎ݀ݥݟݺ ('?`:ߘ328zqJF@&V{ #ASh %:\N 4 > xAA+ e"#\%&h()~+-.#013[4"547545p,153J(  )*(5+;2@7J=OCWG_LeSpYvY[_Z`% D%7#M=hZ݀xݘݓݳݫ:޶{_%@XXQ8BVD~?]z2AYt EvD C Z &mAA/@6dy@~? !#$&'')*7,-B/1?234O54e54E4:WtRe8]H  *+!3%8*@2E:K>QB]IZRiSl]s^~ab\* %o 0:MXeo|݈ݗݤݱ `_gi)rg2`e=l'D[p4Oo4h E Y  ^! ,LI!j"$]%'d(*v+4-.J01H3C4\545T46"`IgAwvJ6    #$(*051>8B<JANF]J_KiVmT|VX[S?l~)Tܫ&; P=fU݀rݚݐݴݨݾ$8UA"Zm~y\Eet"e,Vv 8J`t7Y$`  V v 8aQFO^vL[ !B#$?&'J)*_,-s/0n234!5(545/ OlC$)%0+61;7B:JALFTMZQaUiXpauecihet?ܬ 1!F:_Ruo݋݆ݦݟݾݼmގ4 Z V |2V@`s0H`J Y  t  v8?][*!z"$k%'u()*+C-.[01Z3I4l5454v5|"G ^P  %$.$0(81:7??GAMGQPRZZYab`lhpjxpnqf6M_ܹ+*EE[_su݌ݐݢݣݺvy Wf46<Gn.A7F;L@RDVGZOdRdXo]pa|djloppcytAܖܰ 51JE^bzyݍݑݤݧݼ>ߺPO U]&[[8fQ@VH\IaSaTnXn^sb~ckinj`)$Kܚܸܱ 16DM_ap|ݎݓݠݫ,z?^jrfP0U h]+Ko1:Thz!Dp E 2 S q?+  <Z.q=!" $% '(-*+;-.?01'34 554`6L)&hlAu`mO1"# #*'-,1473?9>AI=MERIWK^OdWhXo[w\xh_ggbZJwiF<ۧn܉ܨ  1$E9ZOnh݃|ݡ!tHA x$sQ1Qgu*=Wv3d ? H u?H* !#$&')*,./123:55p5$53 78nt)!."03)-1;2::@<BFGEMONRTVY\]_`gfjiriypzut{||~f:ڷ۬{ܽܒܯ &>6PNgb|wYx_ ;usZ%|)6w;d6HWl4W$b D k RH% .'\iG H!",$%''(0*+;- />0234454r6~ [s_-=-#*9#6,:0<4C6H?JFLKRMTVYW\`\cckdpiprxoruturc*+Fyܥ܎ܸܥܷ&%:;RQddݐP޽AQ+540i-D8p+Ki}2EUrBx Y [  P%UJ "#%&()+,../812"45{54"6,uW: l D$.+&8(:2;4B:D<ICNBVGUP\ObPgYg^qZxaxfdhmjlicO _I+ےZܹqܻ܍ܣܼ#6)H9ZTߠ#ClFGS'V3O]o.Gl;r X  /f\4;$>AqZ \!"A$%>'(E*+R- /X02834554Z4 s2C@(5'E'@6F3L9N?PAXCXJ]N`U`ZkXp_lavgwkkusw{~h7ڭۄcܛ{ܤܕܵܧܽ!#7=J݂݂߉f%HZaUB$Lc Q!Eg#1D[n1U+ u  j , e@>bh ;"#(%&+()>+,U./g12W44546m"!$^}aL"V =0;*E1E6K8P8RBSE[F[O]PcUfWoXp`rayf|hlnsqtpl`"/bض-Y܆oܑ܄ܢܕܰܩܼ#!/BOkc'ql>hn Ds)F\p0CeH % u " FePFCN`~_ ~!"d$%a'(j*+z-/01s34p5'55.T&a%L3"G38<G4K?GDP@UITL\MaRaXgVl\n_raybh~iklomnlaS+HW t7ܖQܜiܤ}ܰܗܬ+݇ݺ.M9/Qx~{gDd#'k9^~ $5JXl $Dg? % ~ ; tPTw| J"#9%&A()N+,b./o12`4454I57Zc\Q1/<QK8=5O7J>OAQGUIVPWS_S`Yc]fch`liknorystz{{|zT)ڕd?sT{i܌}ܙ܍ܩܢܺܶ:ސ*bT4*aEJFLJMQOQRUUXY\Va]d_h_obqfrexkxmjntkqrlgS+Y-?J k#o;vN܆cܔvܟ܈ܯܚܾܰܿ?>NX/ ?8?m9JCy-Qk$7E]r7c L < u)|~dqdM$ !"$%'(*+-.013454 67%lN@f!SDJ>X@WD[IZL`OaReVeZfZn`igo`wirk|lyr{st{{|{Et5C+K?YQjfvt܅܅ܔܓܠܤܷܸܹ߮=:HV#RV4a5H[n|,Lj$^ L W hC Bh; U"#?%&=()C+,J./D12455y6)]fm0XJ/s2FQR@[GUPWO^P]W`Vd\g\k_lapereviwj|lp~qossutqgV%Qz9A+R9YJg^xl܇}ܖ܏ܤܝܴܳGu %f3Lf_aD-TaW"Gg$5FSj$Hw Z P  ;v| [B !#$&')* ,- /02345X5;33>$4-[^/bJUJaJaLaRfPhVhWlZm]qat^xdwdg~hnlpompopgdT& ,)DFJ*Y?hOq_܁s܌ܛܗܬTxp-~tDn&uK|1I`l,B_{4k  `  f 1yW,  (]x_!`"#I%&D()E+-F.0<13354t6^.N&=Cl(Jq8\SVObL`U`UgXe_j]lajglfqkrmsoxowwyrz|{z|~p=:b$ +6.E>SNa]njzy܈܍ܰ_JfK9csL)q,.r@d &7KVe{"<c) k  m  Y.fj !9#$$&'))*5,-?/0D23505D6, ##kg 4(=uNFeUUV`X^^aYf]bdfbldmeneskqlxlzm~omsquqtvmkfP Q'd'1<.IPUO6D\ H@^x$5DVj9` < / TaL857Kd5B!"$% '( *+-.0134956.v6(H)0CA[RpeYigcglalllevhnmqjymsswoznr~qrvrsqttqnjaJb0Oڿ۲ %+7%B6ܪܻOqe#as.j` Ds9Jbl{ 4KfO A A D'c- !}#$e&'c)*r,-~/023V5(55A2e_=k?y^k\sXu^r^z`rfxc{gsh}ixk~kiomomroppsqnkbUAQ{5ٷ۝۴ (1J8ݕ7K2OcywX?dv!g.Qq'6EUf| $Ht H G _)rSN?QTyMK!"$%'(*+-.012446&$m<WQgpj]velhtgnlulsjwkussozsvuysyw}qz{}}wz{~~}~rI..5۽۷ "ܵ݅&R P.!W5Uet +@[v1d  L U [5 5qI "#$q&'m)*q,-y/0s2355 1 vy\AKNsT}enhwbvkvdxkwk}kyl}nxqlmqqmrnqrqopjjdZH! 0ڛۇۛ۫۶LjzoJ}g02<{Dl)>JZhz8] [  [  u;jgRkg k ]!"7$%%'(*+-.0124459Fq T2AsOvtne{jsounuqtpxrtvtuvqyysyvzxxtv}w}uuwuvtqrgdZDL&ٔڷsۈەۤ۱<޸]`6y!)<(!r*M1f ,Ogx)6NaCv U  i q< Pzb )"# %t&(l)+g, .c/1H2446)kpGb_kyniynostnurtqturuwrvvtywszzuxv}zvw~xz{|z}y}||zvyxnj6$׻ۋی۔ۖۛ۞ۦۭۨ۲۷ۼ^ܐ߯>4?z~OPS0Y ':NYgv+Fo. h  f  K {xdvy#w" p!"K$%:'(8*+0-.'013452JR5aKz[ukrxovqwrusxuuvtvvyr{uxt|q|t}v{tprqptljif^R> rUۨlۥtۧۅ۰ۏ۸ۜ۽ۣ۰ۼ~ߡo$ORfPFF eGGd{*9D`u 0V  g  } +L7 ,f H"#-%&"(x)'+r,*.e/71B2?44;6]qvOx4#JtTyxhj}o}lj}qjq~oomq~qnrqlqqmnlnlie`UN;DـڈPۙaۖnۛx۠ۄۥۑۮۚ۶ۦۺۄm{8vt:oiIt!;Rak~&=W~D ' u ( ^# H1 !"q$%d'(b*+g-.e01h3W4D6,=|Y;aPbmpuu~uzwvyxu~szyxu|wxw{xyv}uyyzwzx}v{v|w{v}s~v|tspri[+hמ]glolsuۀ~ۆۅۑۏەۖ۟ۛ 3ݾM]F,W{zhEf"|%d4Xy"0@P`n=h 6 } - D hL" 3H5 ^"#A%&9()9+,D./>1q2$4537b?NZeuV[|{olq}umq~pnq|rpnrqlmkiiieec][TD1*Q(y8rDxRzYۀfۅpێ~ے۳۱ޱ4=n#Y3+a:Qcw '7Pj%V 4 @ p@c@ ! #$%'(*+-.01304K6!%v 2%Pyczuu~|yx~y|x{zxw{zxyyxwzzyt}uztzuyspysxm~szhj}mfb`Tc b^$e.b=hJhPm\sd|jێ܀ޠ2`o8 8CDl,>IYet/Gv L < ZZA/$"1EiU !k"#L%&>()C+,?./01235-hAEtKU]gzpyz}v}}z}{|x~x|y|w~xzx~r|t{u}rxr}p|rwrynyn{k|i|i}gdZF/׆(<7D7G?KHWQ[Vc^hۿ] O1EHC-}:T=w 2Ofy &1L]x9g A Q ~R ,zV !#$&'(*+-.013y4t4A]Ray}yyz}z|z|yw}zwx{sytztws{n{oyo|hxmxg|g}ba~^~\WL@,v@)KFIJ%J+P3U=~9ܻ5TI^S)N ])W{)=O\ju2\~" Z E lbT86.GM~n!q"#O%&?():+,0./1336`%V'#BWriwvzvwuuu~rzuzq|r{o{owpxixkyhulwdwfvduft`x_v\yY{UzNta9A<'1- ,.3 ;'>9ݡ$:6\es_Q*O j OGcx %4DXmHq  S ` ^( Dm !;#$&')*,-/0 2j350 .8:d/Anenz}|{|{~z|{zxyyuxyrwutvwmvsrkykooqfwephqdrbq[y[tWzO<:[ٲ  &oly<tBkoCk%;O[nz +Gi1 j  W  ~4vhGK@\d$7!" $b%&T()K+,A.0$1335*`vu|{{z||zyxyztyuqtxmumsmsnoiqinhp`pcjan^j^mWjYlPnNmHb_j۩#IIu"V1|&Z5I[ku )>Zw < x  i  Iw^\Wiy?G!"$%'p(*l+,d./_12l41L -[lL4ujn|y}~zu{}t~r|tyo}lxnvnshthscqfobq^l^oZkXmSmSmNpEs@{'4وڷ܁ߤ7(,kj>=>{De%2?LYfx:\ 6 x  z 7tT&3{8 !w#$[&'Y)*^,-g/0w2,344#y]H]p}w}||x|ws}rtrunvnrnpevdqeoan`oZmZnSmTkNpFsDt9~. ؊ڔڟڭڱڸھڇi% V$1SLL'z@LEq&C]mx #,BPoH - + ^yjw{] U!"%$%'(*+,./12 5*:3F hv~~|{~z|x|t}rtsymuqplrimjiflck`h_e_f[fV`Y`RcM^R\I\IXFFj&|zַٽڔڝڣھڧڿکڿڰڴ)@Up_gZ'RU*Vw !8EPaix)Gk B , Gg3  2MS "#$r&'i)*k,-n/0b23 2=e?4uj'bq}zz|xxypwwnpprknlodoghdiagad[fVcWaPcQ_L`Fd>e:e/s{fyګچګڌڪڊکړڧڑڦړګ+ݯO\=N_xomN8YcV9Tl| '.:V`,Y ? ; t0{+|$ g!"8$%'( *+-./124{K6ek}yytuqo~p|h|jwgvctco_o]pZk[hUkMiPdMeGgDb@f8f7g+ot \cٛZڮeڥpڡtڝvښ|ژڋFyޛ>= MxJl$q @l#8%umqy|yturk}oujzerhq_n_k^i[kTfWaNeN]MaD\DY@Z9^5Y1]'cl!@CQvSqVsZq]pڃfۻ]xC"-6)f!:$V1FYcqz 0Ki% \  Q e)d?4$#BT, Q"#-%&(t)+d,$.M/>11x4"fe%'0 cz}x~yuxwrssoreqkkei`hcbYgW`U`N]P[HYGUCW@R<X5R1W(V!^cs.m;g#x-j2d9^;]>c$ܖD߽ZI7iG@6wGc$0<FWg{'G{  V _ R$!U@ !#n$%U'(G*+F-.G013-M;mj5\rzy}}y|wxsxrqprkmleii`cd^__[Z\TWTRRTLLNJHHEGBBA?<<:9748-< xM5qإE+I-E0=0@0<1x܄.f$;NKI/w9I9lP:K3M0H*J#LPZuyֹ E@96.EW|v/c_YK)Uu$0?ET_p5Y  a  k `, ,mH ! #$%n'(h*+n-.0f13&MT%2 l||zw~q}rwjxjqdmfi_k[h[cUcN\NZJXFWASBS9M8L3M+J+F#HLNTa 2;-(& ڑڣDkmKU]{llK6UZ N .I`o| "*9Oh= v  l  F]R=GEdu [!t"#S%&B()7+,5./12/ ^Rm2{TFrv|wx{szrtorkoembff`\eZ[XYTSSSLMMHFLAEAC;<::6842/3-+)'-1p'N؁ 1%ۏ$޹HB] y@ka8c%8DQ\br'?j . p  } ({?!?\ !#$%'(*+-.0o1^3t@AqUjs~zxynpzkyfqcrdg\nVgV_TaK[NUIXAQBO:M5J4F.G)C&C<?CBOk֎٣ۀߢ {HymRkq`?\s  )6CUoN ' s " JmWRLVh#p!x"#L%&6()&+,./093i); $Pnx}yw}owqqlqekbj`e\aZ[U[OXIUHPCM?K:I6C3A,@(<%<;98 ::@K֘ٲںٺټپP۶e߀x@{-\x/uFk4ATXdpz*Jo : z ) 3I&)L#h !&#$&'(*+-.010_dhx}*iq~wxryqxhskpbj`fb`V`XXTWPPMMGOAGB??>6<3532,-**",&(i{FٽٹٸٷٽٴٴܭI\E=wd:|5.m 4Sq(7=O`t1\ / 7 Y(hj[tz/>!"$W%&?()++,.00'3 l~O>bv}}tzwroukglhebca]X]UWQQKPHNDI=I;D5B.?+:'6#33.,0-3=Wu:wٰ\ةٕٙٙ٘ٵٗ2ڌܪ&2 yIHT=2w)H$Y4HV_lw#8R} J 6 H_4=l8 !S#$0&')*,-/Y0|2E+jGnV1c,nzr|}}tysqorgkgfbf[aX^SXQRNQGO@G>E7@3?0:'7'3 /-*( (#(&-9Dւ׬عr~ٴ{٩}٠|hݍ 6f|[N=yGi%2>JXh=g : B e5uzk@M!"$i%'N()<+,#.01k1)rhn{v~vkunpikdkaaZcYVWZLQPLDLEC?A:;592.3,)*)!""   gللنـ{{wqُRڵCeqC"Iems`J'CW:j&?Tenx /@c" W B Vn>%,J= !m#$O&'?)*?,q-S/(028#AI7grxtvzoyiqin_h\gU`V[MVLUDSDF@H4B5>09';#32*'& %  $+FnO1ؚ)nNٖVنR}UzW۩%G>ht/dN/Wt07AHWfs #Dv  J N s=~%\Y!"'$% 'r()e+,a./1I- R[lDSxst~r~owntimdj^eZ`T\SVLVDQCJ>F7C4:1=&5&/!-$"!   ^{z:~;n@e<[xيې߱%EudD_ eO3K_ny(=Nm. b L  hO:AXQ "#$e&'[)*[,}-o/K01>Kw)=b bkwq|pvjvcmdjWgX\RXMVGQFHBD<@8;26+4(+#)$    Z`޵ռIHGF>;83DJlߋx>"#I pk;_!1?HMYdw(Ow  V S G/w ]!")$%'()+,./2 &s <#9 dzz}y~vtspqkjfe`a[XV[MULOFJBE<C4>04/3"1!'(#   ,]"Uz1SE81vپK]COqf&w x$b"=[ly  &5D^z 7 m Y o.]B("$*Pm(h "#$q&'h)*Z,-J/0G. Eq+vS=hjyv|qvoohige]^]XTVSNMHGE>@@7855,0*+!(  L8G7>/ Jڗ ݼ4:~EET6.m:Jq 3HP[eku4V ) m  a T.>2 o!"9$%'()+,./1Wt> lJZi|o{kqlo`gac]ZUXQPLLFGB@=<7242*)*'"#   rTݧՎ׺ ؗoޙ)#2xJ=8t1Qh{$*6BRmD {  h  ~:qQ?./2Ea3 :"#%x&'`)*F,-/f1':"#Gfqvy{pwpqhkbj]`Y^SUQRGLBG<B8;29+6%/ )#HaֿB1Fi nA(?k`qPH2K#V|1ASWdju !>_ 5 w  n +`;)PA !"N$%('(*+,./emq&ectvozeqdi_fW`QZMSJQ@J<C6?08*3%/$# ؼعض۷8TFed$RD}Acw&)8>J`u!N  * t  LZQ;D>\jB X"#3%}&(^)+A,,..^1^lL3^hygzhobj^cY[U[JUIKAF>B5<16+1$+ "    Y>F܂X~ؽػرؾصCw ܔ3߶A&Plzd: M]:l$:M[emu 3Jt > } # { 4wF 9pM ! #t$%U'(G*+E-.0$*5^O+Q"gbp}jorrodo]c^aQ[RSIOCJ>D6?/6-2&/&" l6:L֏؆؍؈رOw')@ /= i U,Zq ',<>LZk .Y 4 , [mfPYPn~$V w"#M%&7(u).+[,:.;//uJ k^^wtgudj^bX_WTLTHEHD8>7700-*$(  +D״~زy؞wذJ8bkQMqz]$mhR ,AVbpq}*B] H 6 ?L/(EY !#$%'(x*+-_.0F"2 H+  Ryfq}linbda\WXSNMJFDB?:7502+&'"  y1/(aHp،n؂g{ ڒ7ݼXX*t%6N?:X}!l ?e| ,2<CMWaw7g  > 9 g&qcfg6v!"#U%&;()++, ./+'=]`.Ledxa~ohhh\^_YRSOIKCB<>9512**$'!  y\$<m*Q7،Nk Q E I_G   G]9o !/#$%'(*+-./ L\NR{pg[nU^WYLRDN>E9?4504$+"$  zձ֯`8_6JD IoߌW(JhjpV?v+<Lp-8DIPWdo~ $Hs N K s:{tD?9?/4,.$)#  sPkUI;؝ؤ>۽cxf$_U":=q+G]o} $4@Xr* [  N YoN%"PsG !D#$&')*+-/N,8 LrM5]:0aXwQwcbWcQWISAM;D8;07(0!.# |o]Dv 7?(8v1ܥT\<[ioc- =R+Y}&;EQX\cmx.P  U W |N-S[!"*$l% 'C(*"+--/ D- PsFJvRpccTaOVMLEJ<@6<,3*,!'   {tNԃ؜nݘ0-O%x5XLD^t&0;J_~; n Z  o$Y;! ?[O "o#$J&'5)*<,J-/%ZT"wIf`^lZW\SOOGI?B7833*,"&  ~mdP5].ի%\ٸh݌k?xG P `6f2DNZ]dkw ;]  _ e V9ej!"2$|%'^(*@+,B.U- 4YPeLqLr[SUXHQEC>?66.0&&& xodVG/APףץأ7ږWoi8o()I04 Ar R%Sm "+0@L`}E {  Z  |+\N*),+We(X "#$j&'\){*h,6-/SXB)?eH^`SKVBNC@9>-6*+!%{|xsmlhebTe,A8ק׻תAnێ'ޯ;-2rb-iiHv";HV]elp#?d ' h  k _&@{ p!"6$%'()+,. (6}?|1TGQ~XMcRIOHC@?670/)'!!  zvj^U~E3i֕׼{iۓߩiMMhRP%[` 8[y!!02;GXl$L  d  6l[27#76fv9k "#$|&'j)*h,v--0q/Mdf;rr;cNPDQ6E59,7#.$  utf[|PwFs9s*t{Oթ՚֢XסwlؑG۶n~eR= ~'u$X -AR_hksx +Hh 3 q  n %d6I+ q!"1$% '()+,/Q %35XxBOTK@K::17*/"$ }z|qqofedW^URKNCH0O_l[m ق!ܮCI#{ A`tzs^Dp(0s=_z+/3<FR\u%L ! m  @u\B;/<Eg<| ,"#$v&'])*8,-)(8GgQ7/@BsX:]D@?C/:,1#*   zoiz]xWkKk>f6c&ffo!F0hi׊لܪJ~W#:/h7N`hrwz4Os > }  w 3mD9UF !#@$%'()+, ..):{i1aj2UK>9@08*/!%  |n|lq^rWeN`EZ9W+R"PRRvaxYV jU٩nݍc0pvqc(4HEg$/9?AIQ[j+U 2 z $ PbYBEC_qC N"#%r&(G)+,u.e#&qh+Hr??O@7:41('$  }ysqog`d[WWTEMD@9>.5%19zR3շ'׈לڨD\Sm !*%p-L:p.E\irz &5Rx F # ~ <sK>cP ! #T$%)'(*+#-D+ /(B>! C3bS2K=926'*$ ~q}nt`n\hO`FZ;S0O)EHDKctשP׈ک޿$.P|>GW"Qo .6DHMPZct .V 8 & XiaGVLpwG f"#:%l& (A)/++$.t[*TCp%Me*G<5+8#)" yp{hs^kTdOYCV7L6D%C98420:9֧ץbۉޘN14M24;_@t8Oeq~ (?W} E . A~R&>uO !#n$%L'(A*v+-&a @&9`8/E1(,&wuqngdb\WRNKGB<?03,+  ZBtg&ؑ*ۻQ_AB{U%SZ1Z} -:>GJRYfq2^ 8 . `ogKXQq|"N l"#>%|&&(R) +8,T,V_y3<E!PRB/.1zp{mr_nQfL\DS8M1B&<50-'&,DkRfԏծִ֫؎۷&rLMdIJE iK~AFOP\ju>e = : c&~l]]f{(c !p"#:%&()*,(H]"F(Q19"  zvpqff]_RVMMBE8;31&+  IJ\2#ִ(ٸMhk=!Lgyzp[>bu]$E]o| !,;Mk O C G]B>T2^ !#$%'(*w+,)) PFBD4& wynoeg^aOXJM?J2?+3!-' #L+:G{ןٺ1.cE"oQz.;BLRWWdo(Hs  D H p7wyj}50!y"#=%& ()*8- i;Xz,O", ~x|fs`hV^NUDL:F09)2* wgԿԆֹׁڞ޶{:{n] ~#2r)Qbu !'*7EWr% V  K VhKIj=y !0#$%'(k*+) fySC. )  zztmjf]\WTKNA;?8-0'$" g4 ܘGIo߁r2*)-a%9,Z'8HRTZadnv0S~  P U wJ z&LS!"$K%&()*,pA6VR Y@-?${w~jsbkVdOVFM:C1=$3*$q-  !Y#$0&s'$).*,"3c{E6p;  ztoncdZ[PSDI<@07'+!# dMӇԪՍؤ'(o>AP<4 ~1P1b2LR\a`hor1X  W  Z O1Z]!""$f%&=()@+) k4 "|~ovghb^P[JJBE3=..#' w0%cԮ?nݔ%q$mZ&NMLj)'(29@Pb? s  X t(]I%%('Ra"N !#$f&}'a),*H,N am:$+ |ytqgj]\UVFIAB18*,"'  oT9>74,'## |vTFӛs֘1E<]u3h V2Xw%*+23<FQgL |  \  |2eT-163bp1^ "#$o&'V)*&*d/u # }yumic_[VMME?<:,/)! |eMZLղRۉ5ޠ<fHawi:Us I|6N[invv|!=c 0 t  g '_6$B1 i!"$%&()+e.LozRqI< {sugo\cSYGO?C2<(0$reP3)F> U k^! ?w_Gg9{ )"#$a&'")+h%h!9`ytuig`^WSLK?@82.(!! {nych`HfEM]pE ~  m  CZI398Td2 C"#%B&((\+89<#|%4 {tmm`_XVNKCC69.-!" xh^M}?y+z ;2`"jFUi}k+|x)d:N_hnut|,Eh 3 q  t 'i; 3Y? !">$%'(!*' yQ\ qrlh`aUOMJ==8/,( u}omchS\LS=K.%g5|@g&05=@ABITcwF z # t  MXV8H;_c0 X"}#(%<&((*zp# "{Cy{rmccZWSJDG:41+% xjv`kRhB^7W%Xg@Hو;ݪE2%u~?00n'@Vervy| !2Nm 4 x  { .sB5p? !"h$%Q'a(*v!"? cz4vqkk]\STIJ=<24') }ocxYlJk8a-XTYc> d`Aހ:xG5:t_xPN,LRm%3?DGMIQWak#P 4 $ \igP]Qy#L n"#:%o&(j)'s x"J}rthi[_QRFJ:;12$% r|gi\cNWFM8C.5/$ #G׮ZgWkc"K;x7Sev}  '<Wx < ~ - 9J,/DI !"$%'W(t*\ig,twon]fTZIJ?A29&( |q|crXfK\@R2J$>;65GنY ۧc`9z Sdm`, ?V+[})2AJESLSY]r.Z 6 / ] ndci*r!h"#%%&'*!~fv=h*uzkgccTVHK?<42'(xmy_rTbJ\8S.H">8--*8|׃3zVߎBu,% z+aE}B_s| +=[ E 1 AX7 @W.] ! #$%'(J( o4z3ypskfY`OLHC89/-!#wumegZURKG@;7-($ MH`EPutPDeoN_Z>n(=>IMKNRXcq:j 7 > ]3u{k6>!f" $%&'* a>RyvplcbXRNJ@;9-,# rxcoZ`NX@M3B$=. ',[57{vB݉o7e""G-2ApV/Me}!3F_ R 7 N jD! %Gt5 !G#$&T'X)#ICEE{\snmd]\OPJ?850, zst`lU_NR?J0>$7) 4s,eݧwS (u+zk!W!6?KOTUW^ajy )Ju  A Q pF{4Oc!"'$A%'(:( ,0Ti!rzhi_`ORJD<;,/"# xqpjb]WNLH=86,($/}5,޲/a#JZe\Q0 b#*i5[v "(.@Om, e J fQ> #"O^I !#$p&=')`|9&|;yzmuaeYWHQ=@15#) yqz_nVaLT?J2A!6% ! p׾ڕ޹D19+)#5~,ܐߋX`jk[$4BEi}$%+).14?L^z5 p W  x/gY7:*A@sIm "#$&''j *IX |sgp^^NYDJ7>*/"& wxjnZcPSGF7>)0(iNXڪL?o!$ h6IX`jnqnuv} "6[ ) i f "c:>XN v!#%$%&)!Y`@k*ptvqtab_TLM@:9/('qrhjZ_KRBF4;$,# n[Pdi{BC"=H@"H a+Qr-3:>5?BANZqC w  n  H iWLJRc[ U"#%%]&\(+"G)(UP8purnhbV\IJ@@/3'# }wmhf]VTIF=83(% wWXXT ڞݶ\8BSA;Jh N=Yjrx )Ac 9 |  t 8tT _xx !6#N$&'E'_ 4FlepicdOUKG8;0,"# |xmm_aURFG9<.0& tUWQ ٱf HqaC`$q:e/=FBKFKOT[i~!M 0 & _yw]niFj!"#x%E&(7+$O'X`cwseX`QQAD86'+txmj[dPRBF7;*/! zeR^׋r@$(n^\e']"Y.Odv 0Nq H ' E`1:p' !2#$%'X"5FC)~^rq`r_\QOE@;9(%"wymce\ONK<>10( xiyXxM1 EJ R }2Ot'4BJOOQPVW`t ,W ; 1 m#p{b!"#%&& is,u_{OqYWES6@/3' z~lr[eSVEL4?,2(  vgV?) gH6MYW|J8p9)n>]q  ,A[ K 8 NhJ' $/d~\ ",#$%({3k?HtL[]PCG77,,xqlb_VQIE9<3(""wfuWhKZAmc)$5e'7)3e2B7h/@ISTTXYY`jv<l  D I }B6v Z!"$i%>'C"/2eH_\HcFG;>*.$u{hmZaPPGF1;(+ wiXyFq6j 8ޮ#2wd]L1Xs"&(&)26GZx2 g `  v9WU7I?dm< k"#A%6&&u@SieJpo:`EC6@!. vvgnT_NP?D3<#, uhWHm6ozr}6a1@@kip6$`$X.Japw0Iq < , ?[; TpO} "!#$%(6J$U%;aw?RL@2?&'! vyhj_`LTCA69&,! {iZG{5u"|uf_p/G*zP)Y!7GTXZa]_bht@k  R M M%,T< !"H$%a'"en[7y%. U?LrP=Q:63.!  zvjl]^QOFG3:*,zl^L{8u#v?BLi@w=VW+0% tbS?',5'g AmLw%38DDCGIT]l 1] B A ~@-IF l!#!$%&6' J`?IN2ZZ$J1/-vzlo\eRUDM7@-1 %tiUJ* #8TׂYތ`/jTQC&Kl ('+6I[| 9 p  i  JtpbnlV!"#%e&(#qI|'Nd'@:-!+ zmrbgU[JO=B53'+# o]Q8L3Hg b60?xofi4Y%X(Fal{ "7Rw N ; ^YG/*$6EiC >"#%K&M(! l S)?h6.D."(  }vqghYXQOCE76,,! |eZB m֜nݶT.)B')w+S0^#DFGIMR`p *`  I D B$?Z\ !#2$&& )qRX't P^%?5(#&}yojcbTWIGA>42&'veS0USڪ؋.=2Un89E>aq#&)1:H] > t  n  V{vz#gK!"$%&( HX^$G_53C+%$  }qqffX\PNBE58-+! ~o]=PN_uk<CQofhL6\ kY.a3?PYY_bajp6X , q  u 9`0!  >SE !#$~&I'R)R&l(h!Q]A7' * wxoo`eSULL>C52+*" qR*ۣԌەߖw(fk2e]>c+49>==HOYg3g F O R%Exd !!#h$&'Z) % f_$>`1-=+#$ {{qmfe\UPKE@7:+-# wb'[Tקَ(ݩ.r Nt\6~<5wB^w "+6D`zF   o & U*Ak {!"D$%'(&{*x1./62ZI#C.&#& }tpqgaYWNKE=<20-  l6Գ4&۸EDp&JU`UF$L h N;Wfqz %<V [ E w&ogEQAcc5!Z"$%&')m]K1vb$TZ$E1,")xqlk`]VSLIA<63*%$ {DDPYغK]Mea>)]0ETU^_ehls 7_ 1 | " DhG/,Rp2p "#$&')R5t$Hc45?0(, xsmgb\WTLGB?32-%  OBݔQGpuU M]'a ]5c )3>>=DHQ\n@o  N [ d,6Q4j !'#$%')&4lr+;068aK*G2/'* yxuqhe\^SQHE:=3+((]Gma|wO1X}oJ't,/k 8\p)+7J\H  t . Y3Vx !"h$|%^',(*~ty2m-Va+I96+1" |vomf`YWRKDC:45*'! ,߸7fڑݛI)6H9. ;ZDr2L^kuy| #>Y Y K k+xcNJM\o+{)!z"#9%&'0*H!|c+Kl;9L303)" ~zlqe`[YNPCE<:.2"* sԟS~(ߊn#zsHs*xKw'7DKSXVZbix6[ & m  0W? )8ty 2"i#%6&'!)W( gZ ] >9I9dY0S9;)8( ~pvkm]fTYIP=E3?*0' o m٠ܱ {=~l3 ;HIk%/248?IRcx 1a ? P S"?"T !#$%'s(*[K/Q}P$/]m5NB?0;'.$ xrqho\_TZ?S>B/?%2)  wӞӃL/ۀ@ޓ>N*3`Q^:/[h!`BYk{'1E\z 5 q  p  W}3y m!"3$%'W(f*#!S=LsL?SA7=4/&% y{rvcj[cOZEL:J.;+/+ms[Ջ+#g !Y-:;q7LV`gjptv '?Y G K ^.|PP7QGv}:`!"#j%&U(l)w)B q\QR ]>ra;[GB?=11)("w|prdgZ\MYBM:E/;%2* $ k8ӸgUڣqwY5n&rbIv)6BDOSV\en:^ $ n # 1ZE/:~ ?"n#%2&((B+EG-8gzCVWE@G851,$"{txot\lX]NUCO7B.>!4* % fuh iԱ0SW65F~zJ6v?9z%Qq"+.48>KPd8i  J R Y-(X!w !7#$&'(*$G0 UBV{YIcIEAF1;-0!' xu{dq\iRaGX@K5G(?2-'"#2`u"0IօmٿڎݚR74U9=D n Q(Iax )8D\}A z $ x & c%:8 l!",$%&()$*#.WfiLxt?mMPFO5D2:"/& xk{ir[kQbIV xedfuQJ!"$x%&h()+%rs9/I"c]gq]yd[[^LTGH<?75-0%$wswdp]gTaGY=P3L$KKU7cMKշ0Zw }XGqqNY _>m 4BNUYbgjx  >h ? * P{MB!*7:q[!>"#%&')*q+i*EoZX}ng]kSXMTAJ<?39(0$# oyhlbeUaLUBR3J,IW\JխpR}ޓXEZb^Q2j'0xCg"'4=?FIVcsBu  [  a iB$=< !p#$R&'T)1*,6Hh'H(^luxlcn\`VVMNEE;=24*+#" }wxmmfe]^RWLM=M*PW}pX4l؀ܥ/߲+S! {:` T Hbt &,5ASk#V 2 B tC/qM ! #$%]'(8*+'%'8~Gd>hqwltkos^b^\QQLJCA<8.1+' tutiig`[YSRDQL,ӊp}ڧEQ?GL3,j(FYjx%6Nj4 r c  Emxo5[y!"C$x%,'J(.*+H,c1 0x%ok}}q~bnbeV_OSEO?F5=/0),  |w}mtfnYfTXO7://(%" ~tmzauWjOThckӟs/֟֟Bٺl݀}G >H`XP*g36yQu&3;BJHV^g1T  h  } ,U9 !9mu -"~#$Y&'A)*o,(RRs_zPo|}~ttllea^^SOQKCB?823.&'!  zwj`zPtXFRӯԁU֊DHr߆s1{9h O)Sp#(/1>I`v7h ? W `!/I6h ! #$%'(*+, V;/0v{s}uqhmcd[YURLLC?><211&'# zpaPKӵԊp'րyٖݵ,c /Kdu/?WxC  r ' X-L| !"^$%G'z(M*3+- B;RxV12'y~{urmoea^]VSPJGD:?95+0"&  taUr -:V]gmuw$8[ T M m0}`SGRZz=})!"#l%&R()1+,a)2Fmcp{w{nuhnaiU_QWHOAG8B/8+0 ("  {lT28Թԡդ\֦֖־ض$CCLGU80s$?Ir /?IMSXdkz9d / w ' >dL'" :L- V"#.%d&(<)!+,}-O;JI6 smvjp_hWaRYFS>K8C4;)3-$  rZ*`ԸԪվr։r׋Fڳm|k._oB]^'Pm"*0<>GNbs?q  V d h>CkF "P#$&&'(*+2.!?3C_4M0|z}mvjjbgY_SXJOEI9D27.3!-# `)$YչԼ֓֗A-Fq}_ h|=.6v-G_v%,5EXnH 4 3 w62\V !#i$%G'(5*+^-1* #r{wvtlifdZ^VYLNIH@B79/4(- &   f)ձ֬װsږ޳|2qt{VE_]R(AU`gpw~ #4Sp# `  i vMqu^wno E!" $%&()+,*.EjWnGwyskogdc]\YRNLK@D9<45,0"+  u/wֱ #"וl,ܛL߰L"_&-T@E d13~)[ !7EKU]_lx-Lv C ; R{d?8*37XoW s"#K%&9({)<+7,.\#y$6e8`E ||urlrcbabS^LTJJ@D;<1<)1"-#   80ן8&\ץٴ*C:bx1k Z7^z%-;@DPVi (L ! c  p ,xO( 1QW "#$e&'Q)*B,-}+8 X>~,|x}q{gsdh\eV[NYEPAF9D0=,4$-)"  HG<؈N9@=؉6۵_oR;~bA~50m 5Vk}'.:F]w*Z ? B F"Lnt !8#~$&X')4*",,.r/Qr]Iyt{ivdn_dZaMZMNBP9F1>27(2 /&  \`ق 3>j:TB,Ss rJ2Lsyj^5Q lK{5Rap +>Tv > w  n  T|7y" w!"?$%'()+,'/%hu'X}syvtkneg_cT[SQGR?E?D2:15%."&$ pl)Be׈bx\dی ߡW/3C-!n%?%V2CT^gmt~1U{ Y E o%lbIOD`i)9!" $Y%&;()(+,7., nz4y<~}wssjjjbc_[XVNMKJA@==360.** %  t{4S׋ן׉ג{ײ׀~"ݩ;4Dq;cd1^}'4?HNV`j|/] 6 { # | Cj</#Uj?u +"#$&')*,n-/,>L_+Y!~{ysoopcbf`XXUQNKIE@>@4650).%#  f7mt7O׬׭שץםק<؈ ۥ5E03gi946y6^u &*2?EUj;j M Y _1 +a- !P#$.&'")~*),@-/}&YBO}!i4wx|qlpjed`^YYSQNIIG>E=874./')!# e*muLY׹׿ײ&٧9^a;DhqulY.Y mQ?Uh{)7JdR *  9 e;c9 !"$%i'(`*+Z-.- ,^<\kK{w{nmnjef^[\WTPLOEGA=>8621-,#%" Q Za>gރy?-7)l$C)_6OWipw )Eb* i  Y  : |_h\y!Ma!"2$|%!'Z(*>+,-->0']Ge'|wuvopjhec]\YWRTINEL@A8?47.0#3)#=^e ؀Jxq"rf5_b3b%9DLS]gs  >f > . O yR:',EfO ["#/%&()*,-00(7k' H x~uypqjobh]bU^OYJRFL<J7D,D'= 96&"u[c55!IuڅިM~e14;x:bw"*4<DO_t$F  [ p yA' RwZ "f#$?&'))*,-/.)xYSyszn|dsdm]kSeQ_F\CY<Q8O+M$KJ>{^kRSB33!mܔ9߱Bh0Ig]\B,UcQ;Vg| *2BUl$Z 9 E uG 1|S !#$%'(*+-k.0~6pWMel/$~ur~lyft`qZmSgMeDc;]9W,]_Y P1j{t/w8g4Y9 ڳ+LH}'' ^*90f7O\huz $=Vs3 r  l  V}v~0u t!"D$%*'( *+)-[.0);Uyx~oh|ds_sSrMiHl:i4g#ms@\{דJؖM؅JwGػإA۸k}i%Um)o\ Bn);GR\apw9U H M _/zNM7KKs@r!"#|%&j()g+,k./I/I(8Wa wsl~g|^yWwNtJs:u0zU\փת`صfأfؔbرYOw~]PgV;zC5zQo -6:JQ\o7` $ r # 8]H 5?~# O"#-%x&"(a)+@,2..j1R;Xqx|:;!~|vpdcWPF50MY֔؈؅ص؄ص|ۛ߷rUTmUQ"NsU'Me|+2ARa|:o  P [ a14c: !W#$9&'$)*,-. 1)9)e!|yshaVN>#"P֣؜ئئآu+ݡKJW(j I/e'G\i{5F^K ~ -  , i.#OQ !#k$%L'(3*+#-. 00z4ATUp"|vvj_UG){wo<֬ػ ؿ۽;RBZd;foEp%;KXemr%Ae& `  Z x?leWej _ L!"$%&()+,./1 nOBH 2  wjeS5 -ֺ%؍٪Pv^/qxc0:GKl2:q&E[oz$5EVq"T @ > @Is t !A#$'&x')h*,H-4/02"25>Y9   ~^ "3 ";hEaDYAU>T ۂ)ޫC74}g,kfHx&;N[fr} 2On2 q  f  Nxuy7w }!"P$%:'(-*+%-.01,eb9L{1  =$ ,   y:1,0gقiyhtbpfn٤ٯܴAQ7)QyvV0!"$d%&O()?+,(. 001O!=>L:1A-  &  M1A9ًًْْٛٔويميٝaڸKqp@ 0FQI9 W r`.Wl!+3@NZi,S * s  z :`;#  Km8| 9"#%&')*,-/03%7 $?qN!-$(    xP߼/٫٢٭٣٪٣٥٣٣ٟ٣Da}l,sX>1l*Icw )4>[w .f E R W%&T3 !M#$-&'#)*,-/0>2.Z lI3:'!"*"  D-ٵٰٳٷٽٲٵU~ mX{U`c@p!AQbk{#7Oo ; }  n & V%S) !"y$%i'(h*+n-.0P12e[ oK 5K4,,/(&%!   r)٠ۂ ߣ"s3]q{pdCw16Ms0?HUdk}/S} U K o+ufQLLbu@O!""$%'t( *h+-S.!0 138'Gaj<$Y$+83#3()%*&# #    ?5 rڌݥDLg)=3/ DlZ+Uv+2?OYm:_ - w ( ? hM,#!AYJ n"#J%&>();+,5./%12/' LV%-R?"B3.02,-+*#)#&#    &7,2("Q&ۭ1MEdW?*f1Shy);I]{=o  N e m/ Lm\ !"j#$N&';)*-,-/113%+'{^ AX>=0,9(/+.&)%)"""  >J4CKC;56DIܼhw] <~}F!Uh@o .C\it )>ZL % 4 l=/w[ !(#$&'(*+-.014(O IY{6,`5/G:/:9-603-+)/#,$%!'        ;`h!])Z3X3R4WڦNxzM.DifmQEw*@Ks!9FT^kv !@_$ `  Z ~@wngq}+u u!"B$%.'(%*+"-.01307(5#WO&Q9=5A/D0:.:(8(5'1$-"-(((#!     !1Cu1ډ>{EvQuRqRnڇڌ܎ [&".|F_Y'Pp$2?IWfu >i : 3 OzaC;)67^s+i!"#}%&s()v+,./1S2Q4O<EicjBi$ODA5N/E4B.B.:.<(9&6$5#/2,)*&&# " !!#1CtFيMڥYڗ^ڑeڎlڐoڐڄF{ޙ?6?I53o*Lbw!*7FXkFu  a  m %{N*8b"y B"# %&()+w,.g/!1#24*fMm ;)/m9?LD;H;B9?9@4>1<28.8+6+2(1%3!,!-.&)(% % # "#"'/:O1רFٛbڶpڰxگځڮچڪچکڎܲ-D0<\gN^] Lz'AVdu|(;QmR A @ H$], !f#$N&'G)*J,-P/0@231G.lV2(H&`W5QIDFH@FAB>@>8@:5:73:2314-2(2*-&,"1 *++(&)' $**/1@])ci؝Wٮ{ډڑڙڝڠکNqyKKQnXZ2m04'W|:DUbmx 4Ms/ m  q  _~EQ !#l$&[')R*,I-/.0&224LmYx x#Oj7MQIAPCFAIBDBA?>@;;:=6<3846/915+5+4$2'1 1 -0+,., 25;GckA8}\ٸڜګڴڸھ|U{r7 '9i U,[{"7GL[mz*Kw I F d-x\UIU\~TU!")$%'( *+ -./125+QRlk8/;sJ@]NFOOFNHKBKFFCE?J;B>A6C8<2@1>3:/<-;*8)9(6$573848 <BQkbgڼJ~ݑ :ktK 80j5Pn#0?K^v$M # r  } :h=)%4_Y !e"#A%&2()0+,,./1232,4)8j2?O/ch4`OPGUETFOBS>PBL?M>K>F<J8G8C5D4B1B1=0?+@-<)?$:&<=:@A HPm@p  1%܄"ߩ<&ZvlAQ dFv.Icq{/>Yv+_  L T `7 !>V "#$&')*,-/02L3v5y [J* ,Sw<[UXI\JZGXKQGVCRGNBS@LDL@N>H?K;I9G:F5D8F1F/E1?-E*A(B$F GKXp3}%' &)*.15(ݼDS+3TX`G7q'=!Q},>Vak~ $8SxA % 0 l9  ?|w !F#$-&'))*),-1/072@3e5$,RKPVNRb$=<DyRO`ZO^TUTTQVNUOTKQMSHPMLFRFIHMAJFG@N>GBI<H;G9C7E3F4G,H+I&M"R q2׀8#8%=,A3D7I?ME۰Ikg0r  s=_[(Ys !4@M]fz1N~ ] O ~8 ~fph;o !"r$%`'(d*+j-.o01e3Q43=U_2mn@f[YUbN]U[O[OVOUPVPRRUKRQNJTMILMKHLIIHIGIDGEDBG@H;G>F:M3L-V hր8KAJBRKXQ[V^\g_ۑkfi fvA 31p/Pq*9E^j1Y 9 ' QTJ08,HW(C!"$w% 'k(*e+-b.*0A1.336|#-6UJ[a`ReW]Z^S^S^T\UZSXSZQWSSRWPTPTQQMNSLKTMJNNKMIKNGLIKFMBN?R2b.ք^XaZbcklrsrs|{ۀێ&pޏm @iw^7Q`Fu +Kaq #5C]x6l S  e vE'8g. L"#+%&%()'+,'./1235._5_S73*HAz`Nh`Z^`Y^]\Y]\YX\TXY[QXYUTWVSUVTTRSSQQRRPMQRNPNMOPMNMMMNKIP>Y pzx_h{oxۆ~ۋۃۑۋۖۓ݃#f5>F4c2}Is %;R_kz 7QuJ % } < iA !E: !O#$:&'1)*-,-&/02344yji2uj8jxAkb^WjUbZ`XaXaVaW]U]Z]T[XZU\VW[WVWZUTWWSXUSUWPVSWRVNXNWOVMXM<~vږlۜ{۝ۄ۟ۊۥےۨ۞۰ۣ۵۬ۤޞ<: L`/SR Ml-:LXgv-P! a  Q  ?nzrO/ !#$%'(*+-.013&4C6%I ,M6s<TO^gaZg]^`c\d^_^aa^^^^c]]`]^[cZ\_^ZcW^[`XaV_YbSeS^XdOcRdMhKfIZclڰۀۼۍۺۚۺۢۮ۹ۿ]ܯ*H6Sh|3_ 4 - PdH?4CNmFM!"'$%'(*+-.012W450# WP>LEnGw`cbmZj`d`kZkae\m[h]e]j[f\lYe^hWmYf\lWjVlWiWoSnSoQqOtKwI~:;Uێۢ۰ۺ2KݷXhDJ[qgaA&@P:m AYg|.>Xz 7s  S  i |I3  *>~2 o"#W%&R()[+,f./j1m2e4459O$w=gCrakYtZnYr[n[o^m]p]l]o_oXq_o[o^p[p]n_q[s\sXvWvVwUyT|MO@8%P;ۣ۲ۿ Fhf6'" JujCp3AVes "6SyF + 9 wF._N "s#$`&'\)*\,.R/11234K6(t } kCQUein[pbjcq_nbo`lfnas]ncpar`rdpbsau_rav_tbv\{_w^~Z~XTPG1]r%ٽ۲   'ܳw0czWI:y Lm !-?MYl7V Z  ^ }O {#Ua !1#$!&')*%,-&/{0#2\34h51l m4H% SDoRve`klakjfkiikjhkjijkgrhniqhqgthtftiuf{dyczb|dc]ZWJ5I ٸ $&+ 4;"G-܍y߄%o Wqv@"\wP'Kgx )9I^w6b , | 7 N vKS;WPd V!"4$%('( *+-.012445 WJ7=iLrmheugmiojohrkmppmqomroslunuotlymyn{n|mj|nefgbYP7a]ع<77BG'O7V@_L܂%ݙ'wJKY@3 z(J'Y ARlz(;Yt7q  V  m Q7  5N O !"#i%&f()i+,j./q12f44(6+vSTDTb^uihkqhnlqjqooltjvnukwowl}kzp|o~lnlonmljie_T;ٜخFBJ&O1Y?aMkVsb܀!ޕ7= Rn:``6_,&'@)*E,-Z/0d2U3=54T6!SXEaMwmub~d|h}j|j~m~klpqvsrvvrzyxvxutsscV #o>ر&7nBnQs^n܊zܓ܇ܞܔܨܝܻܲxݾVjH"Si}upQ6O[ K8Rm} ):Gdz*Z 6 - Xr]NNYj k ~!"c$%V'(Q*+V-.[01:3455-'8O?a3GQRibzqkynuovuur|uzw|u}||{z~~~~{ub"-ذ)R}_l܉wܒ܄ܟܒܨܠܴܩܵ;Sei82+-W,{X -CWex(<\x-a  ^ e -wa3)  -2k u5!"$p%'a( *c+-j.)0Z1&34544S@jmGzQnsjjxq~p}suv~z}}v>"ץ!n܉w܏܆ܛܓܦܠܴܭܹܿmx2m` WO,[| 3EXbs1Oz?  1 7 I)$B f ."#%&() +,./123v54x6Q%"DbVottj|jyq{u}qw{wz}y[P߮ח܌܊ܓܕܞܤܩܮܶܿ ݥy nJqqLfx!`,Mo1>Tf|%Gx Y U G/xr !I#$4&'4)*?,-H/0@234A55f04 kp0:)ROtZ{rmqxmwtzq}x{x{}~t\׊ۤ܏ܮܝܴܫܿܺn݃ a";QME1q:I5m(A[p1DZx N 4 % YleJVNx5h !"$%t'(*+-.013j4545d .0g1xEqOrqli}t~nuy|xDܝܬܾ *$\*ޛ!+Z{=rg Dq8K^l 4Oq,a V f +}b4(1@wD!""$%'(!*+6-.B01?3>454o6'qARzC^]oyuj~vwvv~~| sܪܿ(64E@Z.߱L@B|oE @ ' ? Q"&\% U"#;%&A()J+,_./b12B45\5Y5 2l (! B%QT~Uqvrntvx}|2Rܽ +9+C\Pn^zp݅ݛyfo;"+9'e=\=Wi"9Oj N ) { * Wt`VZ_w74 !#$%'(*,-/0234{54467+$:oL_HU\nyxlqyvx|~}aoG./;H&T8`JmZ~oݍ݃ݟݔ&Rf_pX+O Z*W|1A\kv ?`-d J  n SD!$&Vi;w3!"$%'(*+#-.)01 345x553B=:[G}Xouq|t}w{TM(?FM"[;iJza݆oݒ݂ݧݓݷݥwEn[!w}/q1Yt$8HWm9b?  } C vY#p& n"#`%&d()z+,./124454r6 [;^\Sm$ BiTxwuls|{xN'ٹ5V\'c=rP݂cݏwݞ݌ݯݜݳݤ)b1CaXZ5!~EOE~ 1Pj"5E\r@t X X  M"!UC "#%z&()+,!.//1244k54 6,]CKB[gbpty{wzEٻ6c%iT !2#$.&'9)*K,-^/0g2355544VJ: h4\_JsLm|kjtww~HJ6ٱ.(k8pP~fݏ}ݡݑݱݤݻ;>ߨ>:?tKGC$Qw!7I]q| =^"` H i XD&$+4c|DM!"2$%.'(8*+F-.E02+344546#-EC\Qxp{dktrzzNi1ؤ+?uRfݎyݟݑݰݣݹ +4H1#Kpwk^6TpW)Nl !5CVn;c2 u $ 4 M)<gB!p"#_%&f()y+-.013`435=555/I@>E/0HQi`so|~u|nk>Iݽ؛&X݂lݍ~ݠݔݲݩݿ ! 65ޫR`4"*9'i @&a(Hc| !/Hc{Bt F X  }VdA "#%&() +,./123]54545;l z.xjIpRsxnpzzeބؕ$zݐ݉ݠݟݵݭ*+9:NNލlhc"pe/[`8g:Qbz  ;ZxE p ) Pfg^xHh !H#$C&'P)*c,-y/023&5454u6'%Q'AZWs}tnv|O[N؅ݚݚݦݪݷݹ&.7>KWbl kiKyzX-w//o@c):Q_t6WS N a %cB6$*)N^M ~!"j$%m'({*+-/0234Q55B5O51 f_0MPxZsvvt}>1 ݴݟݲ 36EJ_`swފދk&IX`Q>@_GyA_~';Md|8b) p & 0 J5 Olj5!""$z%"'~(4*+M-.f01b3R4y545t46BSkBlMmzmmz}$ !pݨݺ21JF\[rpޅއޜޜޭ/ V T}/V=Sn-B^z<o J V  T1xf ="#,%&4()C+,Y.0_13-4N54~54[6G)k aVi<R]i{slx{,Vݰ /(D=YUljރކޙޗެްZ߫).Cx{IIM)X,CXi{;Xy <} " z $ Z{hxyou !V#$R&'^)+s,./*1|244U55U552 E'.!FKzxKhtomx|V'5ݴ'=1PNeb||ޒޓާާ޹޿$EJ8 Uiu^>bu a.Wz5CWn.[O N a ,oHD+<1Vd*` !"$%'(*,-"/0234y545f4S6,= k@[Ezj|bhswy !=ݼ *>+QEi`}uޑގީާ޿޼ EV0465h.C6l*Mi 4Fby,U- s  5 W0 (Wq?!"-$%4'(I*+_-.p01i34I55a54 6+P21V:GUattf}r|x| '=y )>T8bMzjޓނާޛ޽޳ߞig(fl.h ^ Gt @Tj)?Vw&[ L F G(Go c"#^%&k()+,./1244^54r544b+(/J<qvFyiml~s{y~ ;Zجگ1<N$_D{[ލzޣޏ޹ުplmYTqQ5u8/uJq.DXk1Qv1q & w  Z~a~u&: "g# %f&(w)4+,L./`12O44n545Y46%!CM[Y}2VHjlpdp|z}#GmxڥBO`9sVތsޣސ޸ީ/'\kKSbLDCcKIh $5K`y 'NyJ D a 'lQ=06?[~1? !"#$"&'6)*I,-_/0b234455>545 .C^ /2K{`T}dnp|py-Kz83ڙLX/kPށiޖބޮޠ޻ *(>B]!H R}/X=[q(<Ts"K% t  x : ~], >X;}J!":$%?'(O* ,h-%/s052\344^54545 @t8(IJF<c9ct^aoqy .OzqٓY$bCwbޏ}ަޗ޿޶ #<=SXlߪ߰(Bu|KHN+]4L_y/Mi ^ K L M(], "#%&()+-.01344X545`46O$q6 z2KAngrXepu}+Q۹ٌ#d9oYއvޜލ޵ެ42OQjj߃ߘZ@4Oh|y[Bcsk4\v$@Siz@e4u  i  P sxwKB "#%& ()7+,Q./_12=4 55$55 5l5=0 .&5<xaLqhfpup|}"Cpx;nNkޘވެޥ޿0.JKfg߁߁ߚߟFK)405j3E=x1Mp/FWx9iM ; j \X5C/UZ 6k !T#$[&'r)*,-/023254d545Z45Ja_Q4[~8qbma~er| 6C4i On`ބ{ޟޘ޺޷ %#F݂tޒތިެ!2:TZkq߉ߔߨ߰Vv{S!=XUP7E[ TGg.FZv2Z/p  ` ! E!tya L '"##%&.()G+ -].#0f1)344H54_54554G6M1.rQ.K{3jZkU|dwmr}K "ݚsޥތ޼ޯ *&EG_c|ߝߣ߶ߺ1 }G H |$v Y>Xs1Hav .]; . Y \G475LaAl !S#$[&'s)*, ./12354.54L546*5?S|=;r@Me\[khisxu}  !:ܹݥu޵ޔ޶55PQmrߊߐߧߪ &|*hnE FK)]4Ohy2Nt :r X q " xE,%;}C !"$%')*,-2/0;234654;54M543];u#/We/mNgSx\zhly{$'cۢݱxޚ޼ $CCb`}߀ߙߟ߹߽.~ 9^nwiS0 Yr^-_y'?Vk (NwI ) ? nG 7]c8!"-$%='(Z*+-.0134B54S545(46$&R":w(cPeKvWvdho{1=Cآۏރޢ ;/WOtoߒߎ߲߯ *.FfI6e-"f D0j4Zq,CZt $Q~Z  Z | B |x[l K"#J%&]()}+-.!013u45454545~-H^P#-lAF]\Qgdiixo|||&1O/nwފި0M6gY߃yߢߙ߿߼@9Z_.4WY/Yh8l .Qi/Gf,^) u 8 D xk>C)LF}c!k "W#$`&(u)4+,V./r12Z44654E54l5a44)"N^,dN^Vh_thzsz%:[}T/aޑޭ&A"\F{iߛ߈߳ߦ2-PLqlHD%budNv0{>f#@Ul >^-h H e  u=--<N !"$%')*4,-K/ 1L234154?54q5-46_$W#vyce 4k+MYUNi\clsl{}!>c)Jޡ/J1jV߈xߢߙ߻#!EEa^gL1%@<="s:KE?b*@Xp>g8y | * l8-m_3!"+$%<'(W*+v-/0"234454544<5p0 'VH/cHYOmUpbzls~ )Be|%ڄ7޴3OApbߏ߆߫ߨ .3LRku#`\'it9opO7Zr0C`}=rI S j >x|i$T| a"#f%&~()+-.01344,54B54w5$45VoNB@*4ea=[DqGuY}`jq*=e ='ݿ7*WMtsߕߒߴ߶7?Zb{f] P{^;=?V/Oey:WG p  > wY=7/?Gp f} "n#%x&():+,a./w12\4454 54J5K4G6'0 C`  b!FHSBdNg\razlq 5Z2ݴ ?:bZ߀ߡߟ ',GKgpz_"GSaOCFi T.Sz!8Qi7XN F M  cE Vxi4 !&#$/&'J)*q,-/02344545454w2 zjN HD%WAOM^Ugaoizu(Hޜܩ &!GFlhߌߐ߮߭8>[a~c E X6!`)Tp#?[s1b#d  q  o++}a:!"5$%C'(c*$,-I/0Z2344)54>5|4x54V6jmpVvy3*\P?P>dIf\r^ny 8Oܔ,4NUpyߕߟ߷,GNfp>"5pzMLW7g&Eay1Rl/`< > g 2xrm#c g"#o%&(*+0-.I01G34444545w45+H<|QlR&3EF>RSTYjbmsyy 'Sٿw"'CHdo߉ߕ߽߭%=L_l(x>`ntjW3Zyc :d.K_x *Gp+d _  o = qIB&8*S`Q !#$& ()-+,L.0]13.45454&54F5T4n4Vjl 5FN8H=]FdRmcqjt N؎L-@"ZL{qߞߘ߽ ,2PSsz ,0 [(eC0k 9a 6Ni Aq8y / 7  P9 Rpk; !-#$;&'[)*,-/0235454+5{4b536N": miU9Q;:D7YEZU`_qgvz~"Y*5HdK߅uߧߜ77[\3>t;!JV&XbBo0Qm(D`@vS Y  T#-i mI!"G$%]'(|*,-+/092344444444@5/ kx<-J.F?UF]Wf^rgs#.@W"FX+uZߖ߀߷ߪ!GGhl *ERp60 ZsfJn%-sEt$?[s<_E-  ) ` {w`smr&q Y"#e%'|(3*+^-.013u45454'5n4Z5 45 <=uLL*L,`6eFqQz]hu+=]zNj7߄eߥߍߴ 11UX}~5A^f;*";8:#u6REHi4Kd0UV N g + hC4#(1Kb_ "# %&#()J+,j.013I444445415%476s'@Tkb/C L 3/C-R?WIhQp_|iy~*Bf4lُXu:ߏh߯ߖ߽E]{*B\|'T.z  y ; }U!&B`1 !"#$1&'O)+v,(./H1214444444444(2 #vp0,<.7:JFRR\^dmqxz'AfyAW}?ߘn߸ߝ'PCti 20XZ,KCFiR7y;6|&Z *Jg4Qv&ZO B ?!7Za!"b$%'(*,-'/032345454%5W4b53K6 Zo._\=1,7*L5QJZTg_oq{y?dnڣI}Aߘr߻ߠ*NFvo:;af_KAFXC:AgO)W{#?Vt&Go.q n  M sg\gmf{ j"#v%'(6*+_-.01~344444445K45*X?V<dP11%-9C>KMYVdaul|} 9hۊڎ93yOߔ߀߽ߪ -'VV"BJhr]1|J y,}$^'Ni1Mk?mI 6 Y  L<#.3fi/ "#$%&C()o+,./134444445w45M4388\q$@4$L'T;`FiRx]jy 7^4z"Atbߒ߉߷߷ .8Wb #1N[tSvj]pA FN3h"B^} 'BcArf  j * mK&=^5 !*#$<&'])+,B./c12K4444445W4L53l6 \3z<BL 7-0F&L9YBgMt\}lt-Q^Wupߔߙ߼ 8Eap 2AZi}0zg2ShebL/Vpe9e9Xn9YN5 > r = +qx]!"b$%|')*7,-`/0o2344444444z4f5-jK> _I' $ 156ADJT[^fno|}?t6ߔEcwyߗߪ#COk|%BOhw# \^$:8v 7Z~1Md ,U*j W  8 {WdUw},` "#% '(2*+Z-/x052p344444y45Q45535p{<b_#.(@"F5S@bPk\wn| (2Kos߈ߚ߭!.FZr /HZu)A[ _ `E{ 2St!AZy (Y< . W  }J=%4=szD 5"#D%&g()+-.%01&34444444W4/53V6#WM:C>xjM3%*$8#?3K=^Of[tht[ބpߗߖ:Mgx'BRi})AmD$Wr{cGn%0vGu ,Mj,Mp 5lS  g  m;M|U !U#$i&')+,F./c12644444444444N0f4kK$#0'<:FGUV_doux 9 ܥޗkߪߎ ILwz$.OYz (3Qb(~765p6MMEm&B^| ?iE y 5 a = %/v a!"c$&}'A)*n,-/023444{44c4 544D535v?J  5=.IAQLc\ohz{&J؜܀ޥa߸ߋ/"XM} 13]a 6@bn:Zq3okV@d2Oq?sW H  y 3 }pV[Tq+k#!"$%''(Q*+--/0D234444444c4536(Y4v<:Y2#"*57AHNSc\on|y'9<Xcާdߑ8(bW@Dko)ANm}h=AjX2}:@&];`x #>`J#s ! >  hK* "F_&p9 -"#9%&^(*+9-.`01h3k44444444j44j42 O9sL  1<&I0[CfMv[kw6S:/ Kީjߔ=1g`ENq{#4VaXC;HRH5Cb Y-X5Ql8U"`@ ]  c,Tyh !g#$&')!+,L. 0g13*4444t44\44-4653E6.]y9w!4/>I*X8fGuWbq6Xٮ'ޥlߗ@4lf!'MS| 1<^nO*{{I x/a.Uw&?]z/`+l o ! ^ %8z%|!"$&'8)*i,./&124444444444C4q5|,rp(n/ '"7.G?UMgWuiv2^DdIޟsߝG8ul..Y[CJqvXIk4 ;N+a,Ir*Fi5d6 D X - zPX=ZTw9#!"+$%M'(|*+-/0%23x44}44l44V44/4534[*Mp!C= )%7.FFRS^fnr} &Y<ݕ|ߠ" P>zl57ed%MTzQ`I*@^W^>(Xgf1`#Be{>f8wX  } $ TABS#e1 &"#9%&`(*+K-.v01}3]44}44n44W44-453G6#}-&PK!2,?BKMYbeqvNvrtڿ{ߊ߱ MI~| 9@iq*3Vd,lD S61p8]2PkBoC1 >  N#=vT !Y#$s&()@+,u./13T444444444444 0WM|kK* -8,D?VEg\tiw"ARڤaߟ#JX~"@Po3Gcw&r/n}PT a]qvnZ: e|+rGv2Pm2X~Q+} 1 S  mONATY!}@,!"8$%\'(*,-?/0M234444r44`44<4435A'Ec%.+93IBVUeewq"nd-߼߹6Ki3If{(C_x4c-g %,$k)KAHuJ`|5a \S c ( yZ," #4eW R"#h%&(*+I-.r02p3444v44k44_44N44]41t_riL[" .!<4KEYUkcyvVG17߿߳8Kl6Oi/Nf'B\N_0enN"Jm6Mu 8`.s* / } ;$ ;4{_ !c#%&>()q+,. 01 3y4q44a44O445444536v3ZY+=!J8YDoVyhy3Jn߭ ALo ;Pn :Sk.Jd!0c}sO$y/dT5^7St+Q{:z%|  W b]>KGl};y<,!"<$%a')*L,-~/0234h44_44S44A44%44 4*3 gq"4]N6  -*8>LOWfhq|hثܫߚ% XEy!SU"(U^!,S^<wwKu0_7a'Ka"SIL V $ lZ&"*.t$t q"#%&(0*+a-'/0G234_44Q44@44'4435k366l2Y:'(5:FHT`crsevj܌ߗ* WC|%#YY)3^c,:`iOOn>BU6n 5Y{Bb%T'm | 0 z D$S@ "#&%&T()+-.L01N3f4}44s44k44`44M444J5B,,/(o -#<5W?dWrgp3 :sߙ*_L+*`e1 R){*8T-^DvOdtFm,q6ߤ+_U49is AOw)M_ j/xY^ c OAh:[ 7m G9 W  vF."JlF u u"$%:'(p*+-1/0H23m4y4k4v4d4q4^4k4Z4c4_4>44.V1h-^e%#<7OCdVsgw 9nN$ߤ-eR98mqKS"/Wf}!Fpwth?!h*1|$[;_x9[ :w!n i . e H  n: "#0%&^(#*+_-.013B44H44<44,444434}3 5( 19btu'-:=JWVij~v,mnd_ݸߧ+bN?;uvSZ+5ank,<*$|0YJ/_7Pt 3[IA 7 z 4 #NlS !e#$& ();+,t.101?3-44N44B44444 4434w36$v[  ),<AOOea{q'srsݝ߯ ZU:Es{*R` 0Dkx X/Zl:n$w_,\|+Oq)U&i [  < lTOE[o Kwt!"$&'I)*,,./W124e4q4Y4n4Q4l4G4j4>4k464]4o40&BS!+Lz *>0PDdSzexzڵw߻!N\5Ln3Sm1Mk)G!2c{U,~7B,g%Kj$Fk&R=& O  o<0 TlV$z!"-$%['(*,-B/1W23L44@44244 444434S35*j._uuhfm&9&R9_Ox]s {?ߤٓZ ,De6Sm9Vs"=Yq7O&0CME6Ad[9i&Ai@k.hU ^  d 3'hO+ +"#N%&(/*+h-.023Q4n4P4k4G4l4<4o4+4{4 4435:(L'2G~Mpz&)>>OScdyuO&N^3,=g~3Wr#B]y 'Dc&?\T!zK11r ;dD`=hB%} 9 c 3 ` bK !\#%&5()v+,.,0133X4N4r4C4p474p4+4s44|4443q2 (l Ceq "2+E;YRmgx%{50Eq 9Zx,Hg2Ql8MnG[oGOVD|<[>b=u\N z 1  wlISDbkP!#$)&'^)+,]./12>4B4w444z4(4~4443434<35:.cRub  2K3YJl\o 8Es+Bcy1Pk?Xt#>\vO2VfmfP3^~(tP}6_7ZO.{' I  pD+2Z e8/!"J$%x')*Q,-/%123X4W4M4V4E4T4<4V4.4[44w43L5*D1_:]r#<1MKcU~n߸ ?5yv*7jv,Ym FW -Dh|O"_,FHSx8[}.X,dJ `  i +Fk |` e"#% '(D*,~-=/0_23p444p4,4n4 4p44w4343433 /  <U|j.1@HYYol{ؗܪ߮I-p66tw)1en#R`9ItFi6b$eh["Iq /Ww*W5{o 2 [ 1 p$pa "w#(%&]()+-.H02Q3b404m4&4n44r44z43434336e{-f7a[$';<TNm[t}H܁ߡF'}j31qr'2gm%TbBTzs"Jt~ynE"r0:*aIl'Kw3h LI m 1 ~fPNRe|j- !/#$Y&')8+,w.01304K4K4C4G4=4C464A4.4@44O434,Bm~nd*Tmj+A,Y>nNdsz~lznߦ >)ym56nt,8fu2Zj!Ha q&7C9+ =`^8i&Nn"KrCm# :  fM%! A^(qB@!"\$ &'K)*, ./5123d4+4_4 4]44a44j43|434u3D4``%C_Cv+HY2o@ThmlQ{]oٻTߩ:+zr09mx.=h!9bx,NlobuDz*'k35!/*vW,FDv| "=P*i=S_ef?T(ߣ8&rl19lx-?n}&;fx1Yp C3?th7 DS=o>f<`&U&jt c & ?z,  "#?%&v(%*+e-.02384F454C4-4A4'4<4!48441444z4 /Xm`6t\_$>.ZBqUdkg?%޺ߤ9!ti33ry4As1?o(7et69YWV;)U m%n Cn;e2[,d=I ] 3 ZbHa]!QD !_#$&()I+-.R01\34\44Z4 4[43a43k43434/3%5HI("Sx<r/2GDdUfnn?E۟ݨߡ1vh46ty8@t5Iw1Al"4-| T"<@Fs:Z 6_5u^ . ]E  D^/|UT!"t$#&'d)*,/./\123N4!4J44I44I44N43]434W35% 9lzpJ`:v@_xyy'&F6[Qr\hmCX;ڬzߤ!bg(3iy0Ao3Hp,Dl";zP]uOUeNIt)Uw :l>4 D  P +G1t!"%$%X'(*0,-k/123/4>4#4>44<44;44=43?43@44C1,? R(S_8d}*C-^BtVemFO ޸ٍY߹+Vq?e .Op5Wu7Wt/NqF6WprkT9k4Q%Lw&PxD\ j  _  M8 *"#R%'(U*+-/0.234J44J44M43Q43\43t43435Z w;",l6r'{\n'@*UCmUevV>tit? 4S}$Lh2Yw =d>d8_zI")$j1UQ'`#Nr'Q~S4; _ ' ~^YUeq<c\ !u#%&>()+5-.q01r3#454!4344144/44243<43`4y3U5(w{Xac*](g1Wjmr//CFaZwrl &D3N{Jf5Zx!?c*Gk %IcCf7n'}`7d Fk.[$b _ o 5 f<-5E~9! #$9&'z)4+,|./13)44<44;44:43;43>43H43^432 |0=:V=Y'qWzk!30NDe`yyoi ߻-EsEb5V{'He+Ol -Pk9p*_xrU&7J,l ;d<g1a2|0 ?  M 01UQ.0!"U$%')*V,./U12 44=44?43@43D43O43f43435D,NjddNrYr 0"L7eO{g}Z޺ߪ'8n=] 0Vs&Eg .Mo0Qp q*?HC0Hga=t 6_Ei3p [`  V  S]G V"#%*'(p*,-L/0q23'4$44!444 44443!43<435x*W]}-4MHL!?R]Z|u #B.WKwWp_{؟ܤ޽ߒ('ku@O*Wm&>k 5Mv;S}mR<1oI 7^ HzC2+ f  xrWgb_pq "#;%&(*+N-/062z3:44643543343443:43H43g4w3'36 1x3:Sro1<\JXh~s51PCoUe)s܁߅3ukIK)`o0CtAUJZn PxCO hE%T 6T!NX ^ k 7 n@8)IRS !2#$d&'()q+,.00163143643643743;43E43[43425}g$;EHIHYWzt2&Q9nKU]5_߂2xkLK*fr8HzI^%Qh@84NijiP7 g8yR(X~5\"W0~. B  \ 5 EwoKW!"$&'^)+,M./1244444444 43 43 43434A,7vV }TQ2%UA\a{n7U'v8<3B޷)qgHM0dw ;O| Ng5Yu,4! h.SJ-c&S{:b(hWX  T , 5j| "$%S')*[,-/123-43'43&43%43(43/43A43n4>33K\UBWg @\+b@\v 9Vz%)72ى ަ{ fiAQ3ex :R'Pn:`|'-}c/kr`9g%Lu 8i9}&& a  }rajoq, 2"#d%&(7*+-8/0d23(43!434343"43(43:43u435"m<^X8)E@+U;yRq0Rr$ݑu߸ bb=L.cx =R'Un%?e1n`Io}}kD%v5>4o4f-O| ;nTH n % `K+,!3?msFF !g#$&6()+9-.u01v344443 43 434343333/43/~.jkN?(<<BZ\ry@]&# کڽ{o߱[Z>F(fs @Q([o,@pa7Z~ .Kt6v=T\RC#Vy uZ%Pz?j'`OB k ! [P-2$CH~#ik !#%&Z("*+p-.02334343434343#43;4a3|42O5J]e5 0<*^:z]{6c A3zߔߺ,X}Fp2V=cAi?e:X{u_ED-c)U{@q:w oz ; X .9[>} !5#$v& ()Z+-.X01Z3343333333333343.483-5'&`Z@5&(JBafx|$D.ps5|߃߶%QuCg2V;a Gi#Di<_dW&_o`3h1XBvU@U  X  KQ7E!"x$&'P) +,W./1233434343333343 43432D 7LSaQM/& -(P@k]y "(;J9ؾܰuuߩ߿Jj:d*Ryp'91n9g0ZG~)l d" I  mroKQF a"$%Y'(*3,-}/7123343434343 4343.4U3q425D3@iE,O-cPm&E1G|u؃܃ocߥ߱F`5W%Ht8` Cj$Ij"Gj+/ )'t2[ \>s @j+U!X@; _ ! fI907A\E| "#N%&(D*+-3/0\233333333333333333b34* . 96MPnk CWOFSJSuO߰ߠIS;M-G{6gNi.Ly )Ro %o8v!/wBzFq*Y4r Z| & K 9 4vA !F#$&F()+"-.h02_3 434333333343434d3<4)3W3 V\VR';9S[nv<Z1D(u<߲ߌID=H-? 2m !Xn8P/_w*^X8FSLNIv1cH-O y V  1WmYo!"$-&'v)A+,.013334333333343 4~3 4M3`425Mm '"& 10FV`p|@lY]ؿl.ߨA46=,9|0l~Wl9T0c~bT.;L@8F uqZ#U~Gt ?vad S  zw|Xzw!"6$%'&)*y,"./\12333333333333333333\48-2rwko :&YDud{IxacP#ߘv2/(7}#:q0fPp L[k{YmRߺ߱ gijz*l|'h #_wOh5Q3a|ka(o!z1uLSx 6i G)z3 S # oNI=KS{II m"#%B')*\,-/,123333333333333333[34255%6)cZ :>Y[yxL5ۋSOߤ߫Ue]s (`*b~(XvKg 0W;dIvoL#}=NE"XNyH\Wn * ~ \ 5 2b$p~ "#E%&(U*+-C/0l233333333333333333v3330gXFU P;)ZC|cC 'ܨ 9Oߋ߮CgOx,Y/Z,S~#Mt:bGiY4=;) Gq$xW-c"M}S+v,8 E % B?) !X#$&2()+W-.0 23333333333333r33W34%3I42D5.lX7pjk3R:uZ|-ز{&Uyߴ 6jFz+R0Y1V)Ny:i&Mp"3}L@G,c7f(Y*hP[ P  FG;T!"$@&')=+,.D01C33333333333333333h33 34Q(>pLv ;<[\{||{TIhߣ(]>m#M}-V,W~'Py@f.Ry#qi=Q i[:r5f-f8y(}% Z  lbJOOpB^_!"<$%'&)*,>./{123333333333333{33h33L3303K2 $.yw@b )E=g]Kx\><0<^ߕ߾P}7eKu)U{*V)RwIm 4VF\[^B(d?0nG{ =i ;x OPg / b 1*1A}>   /"#y%7'(*$,-v/,1233333333333|33j33O333<42g5[s_Quq $@(cOn 8Kߑ߫Jt1aDq$Q})V&Ry#Jo 7_RZc-X`DQ~BuM'v$8 P ' 2_Y=N !#%&w(2*+-"/0Q2333333333333333k33G342"5o%ADws:do:"VIvd58ߏߝFb#\:r%N|+Q+U'Lx=h7R]+r'0|U$UK"^KX Q  d hc!,#$x&()t+3-.}01i3333333333333|33i33F3324R}~yd8Xb .W8tZrׄۥ-'߆ߐBY\~5s(L1T5V.T#Dp /BkvcJ:XI/e)[)^/v$% c  wlWeb c&7!"y$ &'g),+,.01333333333333w33h33P333c4,.f]Y4}f{ @?e\w eIw޲4ߎBH `r.s,B6Q=U7T-G|2:36"Tu.]=t0a<s HUh 4 n ::*"KX]34 b"&$%|')*e,4./s12333333333u33e33O33,342+4!r J=t$Unt6=[Ur )Eޢ-߂oAA^j(s+?7QBY:\1U>{1TJS;uJ}>wJ,z(E ^ 5 %J"~h| "#h%'(j*",-|/ 1233333333333333j33*3f4,Z_ 9hOS0LBml(A%p>[v*mء(ݿޤws4D Vo/o)L=^DjHj>b*T}"xzQ$h!'tX$X%U%e ]a$ a 8  Q6/ !j#!%&~(*+s-7/0l2333333333333n33U33-3v3 SN2 U_vjr+Ou:Zr|3bxUݳެ sv5IYv:v/T EhPu%SxNt>b`mpneC"|BV S3i 9n0i K5E t C   S_X~!)#$z&()|+;-.0 2v3333333333333n33%34 +d 0`o}]?I} ?.dHg{,fMܭަ zt;F`y"<~@_Vq (`3h0a"Vs'30, U/1zLzOC*rj% M  |[\PkuU -!"p$4&')'+,.F01O3333333333333v33`3 3Z A ) e~p8\t194cXu)q{ڴܢޮ yyBNk,I Li%b8o%Ex#Dv;mTma%] bT/_*a-g PNs . g G3''/Eg wMV ",$%'1)*,F./133333333333333134n* <'K|/P_D7hXv+}Zٻ܊wߊB],p4[X9r*K4\ 9]0Y=!ub67B4t EzCwP54P  m D "7e7 B"#%>'(*N,./L123333333333333326N S s|pJQ ^uqHJ>m`})٦x-yߚEksBxFzXKZ X * 3t& ! !\#%&e(*+v--/0i233333333333332~W CVJ"E^c"8f)2KUqv߂oOO{߸S'[)\#THz5bJv)U|(Y|!LvQ9? [1g-e L1F r A  ~NOHt!.#$&()y+Q-.0233 43 4343 43F4235-)  `+2l pY 86V_}pbR\8l߆;^6uAi 8r5`!V~5iDt%IyDnVi4o!v&o H~NQ2zv- X # f`[q}_!:!"$?&')E+ -.e01y33 43 43 43434323e C ntBg1T{ y (7NXvz c2=;,)$}ߌMp FZ&QMz9n)V ;e=i=g6;qBO_P1s9e A~_f| G VO1A=`p:|Tb!"W$%'F)+,.01(3&43,43043<43c4N305) ,  [{9.!5I?+B0oPv *F?:#=5ߐߞa6]2m:k/c)WGq+T 3` 3]5OoP#|6N="\(_2l NTl 1 i =2?QY08 i"$%}')*,M./1 3!44/43.43543D43Y3J| _ IG* uYx. # )!D>w\? `9FQ:ߨߨ{LnBT|!GIq 0f"I|0S2S+HN`eWI'\ 1/tCwSQC3_  { C 2  :Q>q H"#%)')*l,-/?1 33K43N43Z43~4u3K5)   U'&Zc:fs3'E DHSvH{2asB߱2& k|BV(zBa&j+MCeQs!VyRh0>,+?rof2g?vB9"N f * ,}[B^ "#h%&(Z*>,-/123[4 4[43c43w433 2 u=W %pD<zx!$ M\d-^#&XRش݃SF7 Xn)E[x)H Mn .g>u#D{ Csg&W\J&_)d=~o|3 { B DB'@ !#%&|(G*+-G/12 434]44i4443X5E* >  h J m>T\t@w_x9'B@]!Qq x݈rVW+@!qCgfFoFoh{G@N:wQR/p X o j * mqj !O#$&=(*+- /0P23<4y4(44 4434 c ;?aG )^;8b>h:h&9ݔߍfr?]9]0Y%`(RHv.d;mAl VUW+o,4)k>vK^SV M  8QKr!#$`&"()+5-.0N234F44/443^5+" $ O ] n 4)\Td'RrTBu2B%Yݡߢ \q7Q2 Pu!CNq7o,S?dEg6b"Yvd:U}$o[.dAv IHA { 2  gyj p.%M!"$ &')l+,.[082{34C44%4434; / I ' ! )l Hq.@^`uF3~NbBK;C۵ݮ߾8* ~Zq3O,vEg4v:`W|3e=o0``pkSEAic M \/gC4: i - yfUUWm?lu !"S$&'o)%+,.K013r44q4434N5=- & Hx 7 A[R]EyV7<]-$`Igw ]xMZrݴJK#9%tOv,P$e3Y"]F|3\?h=Z,KF6#q.QSFat%٫ݡS}wV*]*d,ZQ} 9e?re 0p5[Rv*_(]E-8Z>z H9"~? h > ~^ip"!"q$%'g)X+,.@0d2f34; u   V C % R]R #;_h> +^4Um_ܒI6+,1 )|gIk&N&e4]%bI~3Z.W6j2n#},w\6n F,y~/ d - {pq3SW "1$%'Z)+,.[014. #G  f M b  #(B}i< -]*H"Eh|7k<ۜܟ]_IV=\'Q@'o Ny'V*a-YLx2f8b;eW"avjS+fE%m!y, f ! ~u_kkzGH " $%j'T)*,C.{0v14!3 a n z f % v|Gzq7^;bNTcܟlh~]}Nv?g$S6yQ'O#ZH~9aEgEkyqHW mf M)dC$nt& X  rbYXZxW P"#%M')*,>.01W0!} ;< t  5 } Y ' >tz &<?k_\03ܟ߀ocMw.V;~U|#JLr 5gDy!Duj||[:M_eE)c7x#o f# H  pPQ<V\2 "#p%O'(*H,j./m2& r N $ Y:^p.]B^+7,?d}~!gj6ܞߒ19&BD:*x^>f@Nw@};`MxPt mLiD)GV^@(c5x"l d& F  |lDJ/LMs !#O%='(*$,Z./0 =5 !! T # KJ=_&ln0EXUv7{ L{ۦߛOkFoBo8j,\D$iDpA}Hv 6k$P)S1X-]pW3t6TS@~\6vc b C v[C1,4@fkHX !#G%&(q*C,-)0*-o`LC M  [ (  zy )>M3FkTr|}P&ۯߢ5f`"aZN=v"Y:pBzHw >n(T2Z 9]#,XCk'PK?U=uXf | H ~KB+CJ E' !e#K%&(#*m,n--0w  Bp  #  e 5 `2 nzAR6U2"eJQ[ۯߠiRNJAu/dJ,iAo?u?i'Y8d>l.3.\C?7yN3r Wc u 8 k=1 /6t, !D#%&(*,-,: j> P e ? u?2W0`OR!=Pg| }8ۙߡs$y&u"hZEx([5m Ao 7q,\EmGrLJ 8B/lM'lYX v 0 \:2Q%}i !E#$&6(>*+M.D$ _+4msP ^ o E -Ji |XJ`Ee)IF{l 0zߤ;HOL D.oT.b7l9h.\EqKv"Pxq7w'6#i O` WL s  G4%0~Q7U!2#$&';*A+~-3 LW J | 6 +AiM=\A$mMvn ;PߚCT>f?q:k2f S =zZ/e/c*\GsN{*R}`'j-|`CeSI h w E( $dE(F!#$d&')+(5):, 8J  1 nz!219MoMK.K1Rm PP ߔ6 -75 +jKr*Lb.NOr 'Y{0f0pc1 Gtd[,r`:M P  U <-`^;!"$%(&)*$T&^np  v < du"x!J \xo0!UTgw(t$ދI#99:M>U5S/O?'r Pu$IW}?z3U<^@bJ{qH?e ^ O,hQ5; E  O +\VR ":$%')$%IhqDz r %  m F ?E#G!E4(e9::scjuMy ܎ސVMR_UtW|W}M{=j'V ;xM|IHr/`:hEn;Ob; u:X XE0mM=. P X 3`a "#& '*y~ K [Q o 8  { I 3gv X! 0 nlfz|'npUޛauh n!v(s)pe L.^ :uHv>r0\ =jFq:F(e(IS=+hA7% H s P LI "#%.'d' /l7(} K  G 9[vv #,NvxKgf4~,k*\6m!Hz"PZ@G;^F,}* < s : Y $"#W%': pL=peXju S D &Jq,, "Q *#Y^v@A0Xvzݍ%60S=gBnEp;i,ZB%e;f 3l-T?cQu Uw wP{;68|SDl- * w # ix+ !$$'AWpW`V ] I &Ph !"# <|>,,'ODf[iz݆I]Qw`lmeXAl&P)j5`%_?q(L0Se?p1-.u L>i$ ' q }^}il !##%$%iOf# _ T 6r" "$O2 8.R3j]o*wSc+y< BC7y%g I{#S)]%SDo#Rz+XU%e})gM0ujq ' [ # i_Wkb+' !;#%l u * ~ T X :1 \"$ "wP~p^%<)->6st:p}E]=wQe#k%h"cR:lDSL BkP{)` /o@ Z m%yYIgka ) F $ F[7kT$""%k: F Q #|8s:m "|#%8_`U<@^N`]qurf|3>G@5z"b@nE~Ku 6m I4V5XZ`/K`l O@_c\  :  ur>O*XD!#L" -TLPs3 >  O ,#e  V"#,&"o 1=.2(_OJmwERl>s9dFx.\ 6^;TSz4X[L3vaOW x ? zQ?*.,I_#f9 "!#B_zf;h_/gB L  O ''Q "#s%$ ~JSu{K*3 q/0[ByS XV L8pR/d3h0bBq-X4c:!;q#PKJ'h_A] k @ x7? 3 J4)(' }# S>G@8$xJ d  a W ! $%'q{ H} 8*M[v4w{m7HLse!w+z1x/r bFy$V)_(ZFn+Y 7d C_BF@`R<O b 2 }j..3(~#!YFn_hT v k   em~ #"#W%' ![ mQ~I^g|HH `\[s=K"R KD+p L|#LXAq+T8^ >`|K3C/uaHD: f  J9   8EBn:.!fY o  f kUX F"#%&q'  sz\#OWݐP o 66T?dIoFh9^"L +tJo<|@cTw )d0ed+rx7]Y,{:% b  |'/5 zEP! XN_V]P^ \  T TKK -"~#%&)'+ =I'xvz-<%4LIk^~` ^XBm)P*m%bT! B5^Vt9HOK A}*d BrG{Dy0_Jv*U%m8Ux&OGE hdN z  v %UeF 1pEK! S v N }|ke/9 !~#%'U(+U 3  m#YC{:_=ug7Q%c/j.f'^I(_5j8g)Q=o&Mz(L+ dC:9[ZA k  k pn<7rO[.Eu5}fp4 [ j T oYv)L !P#8%&(p*c(a s~AXeY8uG~h9]yV&O2kGO QF~2hK%\.\Qv5gKv'KyzK u+/}!jTB@ X  L ypymP]3N;AA`@$ L l H lrWyqA!3#8%&()^,zd 9 reA3a|mVEb?)hJ`"l'm!cR7iDP{@s1XBjJpd*el%pUP5~= 8  + vKzGh  iV>q6p> 7  | 1 w^b^wJ  !D#$&( *,o$ Y+fm iUUYLݰ5j a8\0u?DA~3lV2e 8m8aQ~ 2h?oJLUcE@j, # s  Vt$b9/E**[D %  ~  nxAgCxmNvR p!Q#$&0(c*++{& ?MB3RnC2kOag`T;qM$X"T Bo,Y 8b 9pt7x4CH5~(vbt  W  MM9N>f@Iz9e2_C ( v  jm;Y:kg<lJ `!C#$&(i*q+c.A ,=a:?Njv(SMk'}37-v^=mBIs.h%L3[ 5X:Pk;10tYXV  6 aV,'^5l$"ewd{<u%y 5 _ # pTE<?SntOi!#$|&7(*+.(E_ OXIII.Ahg$ @KQJ 6{_8`1n'OIm![{ *]|* \m0m#qDTA    ?W.0lS-OT,eq)wCm = P - yBI,I?ouXy!"$U&Y() ,d-._F) T;Q=r&f1&?Q|z :"P6f9i4e!O6{S}"IFh 0e!@x(H~`=Xr T[4C/  n *9  6[MFg8! x)} e 3 J  yd:9!47_w\8V!"$G&8()+0-0T"f| P];odF{l$2Gd I6hExN|Hu9k!O-k|8)!"y$X&')+-}/J, 7[1"[AnlL.ARu 00^L}_ic U)o&q ^& -  7,R{mO a}a9 Ow  t V 9A )8'}!"R$]&')U+-.0'^ UV")c&<u_<,)PcDDo`r-~-y&mU9e ;u=j+]Iv'Y}(Xdc)^!v/}[cH ~   vTT9h+*M8APw: m g H }u*/!_v  "C$/&')N+-.1& 3,#1'~oBCKrQIg,= ?=}+j K|"T#WFu4`DpFu20Fh _cDH8 _ y X mOao:}2KAZ<S b 2 |X*>lk] "I$%')l+&- /0/W Xpj-v9D0[J(#eR'sCRYQ A'a;m =q3` Q 5f;g b1LTF;*}2 ; z 1 v}Go1!\ o}0  :8?< j  zA,(lOD v"D$%'])u+,F/n03yR I%8 (r|mP:1wd;W(g5l1h!Y<S&SPw 9o)N1P?'D%q2 [)  x  B@MfGH-=}?. g x7"_D9 l"($%'a)O+-/0B3*?oH RK:3U5#߸{VC?nF)f>vEE{8j"P0o>h(g,Q BgPnk l' [lIy o _ |'e` )}0 K/5u+! V  d-A9* f"#%x'h)+-.0n2a2FA  uojJxRފ[NF'{S7vNYY M9jHZH Do*]7k6khPZbRR=X k ; k-( z{2 Gw {#qz H V(1x* R"#%a'U)* -.024%# |2&,J&EV|}^Y`L9h=X%f*e ]I+f:h,e*UHoW|'Y:8|.NBD'{4' h  ,;7e "?]76A)sclh 3 ~ E_  -"#%]'#)*,.0D24.J lO h%#&~pc,8nY2)InFGw B'^7m=q6e%T 7zPw>xBg&`5r%8v\h9n4 V) m ` ^ =`C7@`AClKaQ y & o 7Co "#j%W'(*,.B0234ff W]z6V9={EXI:gJ{M~Kz9dH&e4M[|;y3Q9Sq4MvXhBj U B M ^ZVKQ6L@ D<Z?QE i  b &1Xj !#R%;'(*,./0236' 5['4W?ާ8BC(Ja'#TEuV _ZJy1^9w Ii 4n0YCkLs^;QGG9F T  L %avQK''E7>< X S |!o=K !#I%'(*,j.F0.236I2Y 2Q~YsE =K&Te71fOb$l#fW@tP"WM?q+Z 6b taSq)+;"l.{ M Z P .yJ*;,T @^@(8!z5 @  9 ~jjn X) !q#3%&(*,7.I01#4`5=7} Qqab9%|9Q(_gC3tV$l2w2y*iO-d9j3g,SHiVtn&1Jq d"yQsR A 0 H Q2$k%7P`8_/ ' w ytL_Qw~Iy !`# %&(~*S,3.013Y58, gNmph\L^=O(Zn D;x _(w:@6w"a=wFzBu9i"Y| 2h7kn"MGW7U<    >rRiI e'FO+xP  g [d3R4je7lQ {!R#$&j(w*,4./135575O'  l/:F,VtBCv i+ ?D<-nP'TVJ ;fNy#PzKy'34,}.7 `  }L+hI~r0$++`J _F j | U  PO&<"RQY=^!9#$&N(c*+$./1Y356#9#+Z4 n tUE@o4E/[xGOt5J!RN <`9e+m3YOv ,d4i}.id!x ]t]/ /  8hMQv1}R-G$-zC? J<EN } 8 lL6# 2KwT6_!#$&P(2*,-/1w356 90 r~?x[ ;/Pl%Iz#] sNNw=R%Z'XD/l Gs;Ci)d>v*CF]xM@\7Z4  y \N yL"NExGuA,  r  JC  =M@$M!"$O&C()+-/e135L777F C"_;&E$9 O hfd UH)wJ `,f+_U?vSNRz8w/Q;Y' Q* y<l? z j _ 3z()ix0> b5_- b  ~7/(3(t v/!"$0&$()+-/H1}34F779($W t[zKT _fc ZE-vS$g0m/m&`C#]%Y%["O;aIn"-\ [jWmi 9 X ? 5N0]cE'fWcU i  @ [* #X_d "V$ &')+-]/S1!356688\4{[ 'pޟHT]\QA't Q&f3u4q+gQ0g0f5e-aGv+V-h1F@HBc  w X 2 r-,=QANG u # ~ ="7RU ")$&')f+-(/X12)5k687"9 J`HN^\UD/x Y-t8>6r$]>o9|Is8r.VD`HdAtk2k4 lW ; Z 0H_e^b=M+~G*~B4 g j $%v/0 r"$%')X+Y-!/&124r6[88t9-{K E58v _#Nz:_L[?6u `*~; D;)l Nw!DW|@C\Vq ]w-oQEnFyH@  D FB/:k, h4m)& N  S N ?"$%'[)[+-0/024678@86> !l(&&R\g(mDh <@r n.@KG 3z^4S&h2VUr %i1sM'&J*O2   V*qs9h[l \j 3 u 8 t-y "#%'4)M+,/02c467879#c*`  1ދ![Z l@i 6Hv p1H"R M>#gzl8O![XH4i=oGz@w9cQv(]zh/@`JdL(   { j<`QiCA4D9Z  M  n^PKWmU-G !#p%/')*,.0i246 8A888*8AhT sދ*SF@K>3|eAY a_V;nH|U~'G Nl'f2rS'tmD oP t  I gp-M _ D`z_3l1I e < ~SF0;9Wo<+ !#L%'(*,.0S2_467=8879(a ?W/atC<8I9/zgB[(h'gZ Av&R [(ZQ|4m$C~=FKuR+cZ 5 e 4{"RPKsbCtO#zg> M 1 zp5=+JN-ri !u#% '(*,.N0`24$678L8r883 ?} \ El^k}+9m%N+4r i9X,d.c%[C$^0`/h)WIr,U4t3F@SU 8   ;,CUa=2[@`Q" 4  ^X&2-I? t!`#$&(*N,.0Y23)6_78787I9 )OI oSd~6\Hv!6io4#R5_6e.]H(j?e7w=bZ}3m 8wbht2 ~R J G ;G* xrOXJY{.76=K x - U: #b@-j!7#$&(*B,U. 0-235k788879+  Qyu})ii'^@z$3k l8"Y7i?j6c"R5sIo? Jh )g$=|.F2B< kH$zMJ  L p  VgLlSO%i.|B Y & m O :8)b!#$&(O*G,.01357N8t8C8q8`85  7:wrH[u'w!|!l _;X0n7r4i$V8vLw"IRv4p,J:SmqD$za)) 2 I q|q8CB1qLw_1 6  L ?p jzJ!"$^&j(*/,- 013q57 887879> 7X, F<<߸rh.Xcx!oo T<^.s6u3p%] @|N'R!S}?y5UEaJT|\3qs H I rLS-N6UN ' 9 JRi!"$M&9(*+-/13v5h7>8o8/887P9.~ KR&zp^[ H\eicR5\.o8w5m'cG~!V0Y(_!I %46e^tk1@ >  hud]$: "+$&')+-r/1K3k56r88878m79$va R5ݭ13m2a CNYPG.x T)o4y;w-kS,_4q>h+f%G>T $ _C#H\ ( HCbso qlzPD`]* m + lSTUi7{  ["!$%')+p-o/X1R3*5 758J8F8>8O8881 AxDV_@? g+d'QBY84o]%v32*u\9^5Kk/u5KLZ yiBogA} p uLM}_j4+AEa O  iKE-CAp zk '"$%'`)+9-k/1T347787878|78Tg g[6] Bg~$EO{,U(5a^w*3&{d>c: Sr4~AUVf s^N\8  n  T )Wy0+d>Txs+1J { : qU/-*'Tj\Fv "#%'I)b+-L/153467t87878Z79L({ ?]$1ݤM"Rn5?m%Hy#*^Sq+}1)w[:fDNzC;aWv #|;/|/JBbm9 bi]dt>KK;Y[lu3 ] ! \41W1E !#w%T'6)(+-/12468<84838.848883 S B5.^(h/k%m"1t#{[Fe0y6z2q [:nJ}OO;v0PBfApj4"~t  6 FN4/l6l!6ENa G h > =j~ !~#Y% ')*,.024~6!88Y87l878^789}Y Siyp4['Lcsti[9\0n7t2i$X4vT~&R Z|?;Y Pd T9?l M R0;q7:"? u p5+Me 1 q P PMV!_##%'(*,.024t67+8488=87`87R9], <+Nߛ^%j> @PjcgO9\'m3w2l([9xV,U#d'DCbZlix_1gbO` rj)12hu bIxe?? N A <Xb!I#$&(*,.p02P4{67[87[87e87u87{6L tw\c#B~@u5hOe?;r]"s+x+r`@zW.`)d-Q Hm"`{0C7 mI8U 4 >gDZ~jhI0gN++  2 ( y"8;!,#$&|(*],.G02'4j67e87j8787879 ` ]&;Aaz:m h !  bsn#c!"$&f(i*I,W.80J2467788087387I878/ CE"uA Y;?D0#gMc(o*l^<2Ud @ߠr(gk >"B|}>@j S V@$$5Yz {"H$"&()+-/135t787 8787777}81 C/j6rP&SN Zt!ij O8vYh#icFt.W 3xNn7AXem* ~f)FZ =6zr,bh%*Oy : h D#$;v_N i"$&')+-/135I7,87+87287F87w8(7b8y  \QY>_@_/@BlVf@3kUihbFs1Y4 So;G]jy#0g<x ;W YRjHQ nx>b & } Q /([I7 O" $%')+-/135C7878787287l8 79&EZ &_8xQ%g)|;[TY<,jL]b_Cz+^O#WS <#iFtHS{A{@aU8^<4qbޝj=__iVGZ)N t{9Ay% A *  j` W !#%'`)+S-/H13(5N7787 87,87D8V7868uI yl'! oGhAv1bN}(9ik*A!KG1mSr*Gax%EO] lu'Jj/ ?D3= sE{8Qf3^ d -  DBb' !#m%x'E)d+:-g/51f35)7787 8787%8p7Z86|9)h DoKr$W,^S ;s/b`)?IF /kPp*Fc~.DUdsxtkScy \~'F-O#*UX!7 C  wywf2S!|#`%<'8)&++-'/,1$3567777777777774 = :rP2nL'n5K l!pt`O$wCLK.#iLs(Mc5I Ym!~U|IF(@jۚPpjzEG}|/ u p?: v q   ywXeR|I2!M#D%')*-.12 56777777778^7K869]8 "%ޣ;t[=}O>X dcVDk< I J0y$h Jy'P"e1Q\t-z"?#z2trPP%>}YPlOU}%X O aS::<Pdpaa!.# %&(*,.024677777777777B78,G q%` L=) j< \EJVC6{e0x> =(xbHs#O!d1S[~!4hc: n4>y|AOwme5t@n&@X w+i " ` L#$MfRH! #$&(*,.024677777777k7 8H7/876E ].e4?u-S*2f_{15"rcGp(N$d0U^F|>Kh!Be@ZR\$GOUL2WNf*6`{Q  z 9 /29/ a "$&c(*[,.^02U46777777n78O7$87n8}69!Ln ]uRiCrJl+d@v,]Tr*|1}&m_Gw$V,c.a.YSzeacD3BK+PVd4)' h>s9M uAi3 } Z '  _ax0 "x$q&M(c*L,g.O0o2I4W67777777777o77$78/M7 ړz{iO4h@L _y%uv[B^/q6v*aT ;|\4_+n7Weu'<'/3Z+݊1- hOv?S0Tf'P h 6  3M[ ~"[$;&6(#*3,+.@012=46777777777y77Z777~7T@/&^6\"V Z oXT.O*d4f)[O8b٭߁ bFrC EJ`LK$}F'Z/`&SM5c>^-wH\t?2b2WkkY:#la}EBhOZ*g k $  p}.X 3"#%')+-/135`7777777777}77u777)3<|"W9Stj_L6g8f'>JF< pEZ(c"WM<c=b3yIc$xAA#R'SUؒݨQ-7+ZTbbD^.5o xLp O  klKfSw[' "#%')+-/13577777z77l77[77B777!868 cN#A;6.wQ"{G v04?)b@X aUM8yY:i8vJj/v@NeD_J0ج݄FCL~F4S)5AG xLb,[ + { NG.:7RiH)[ !#%x')y+-/135177777777w77f77F7768*a&,))" v`I#g3Ut(y$zjS1~ KVMH9y\`fO d,t+R r'OG  P D  %&_~#!#\%l'G)o+M-}/_13V5?777z77m77b77S77?77%77#7T5 G;)2;%CA<-e.t6o%b yYT$|>OED0x[:lA{HvCz=mtngI>d7%؄M4$jy;M/_o>^6 l 1 ,  FZus!t#+%L')R+!-d//1u3&527v77e77U77D77/77776=8;6L9{ivHT]Ok GKs5 GA C2vZ6pDwHOs5y'HP5b SLv/c'~gTz+j|ASC a L  9GLN!;#%'(+,)/1<35777u77k77`77R77=777768 - joK"{Lh.Cp!Y h 2  DmG !"$&(*,.02467o77h77`77U77G77377 7768!"ҚI-.:85#wV$}Dw.y'0rrF)b>uApBn9b&M ,{ Vs/Gkt<7/qm^ؗY"V)*?l;#N2<"B"^qEu T  i(b9\$ "$&r(*,.0246o77g77_77U77L77@77477.7h770umnLBZ7n82-}qZG t<O s!ksXBa1v4p3r.gO/zTy,Kjz8E EZ]LߵQE5(% |sljGN0N @ ^tCw]3) "N$&<(*I,._02i46I77?7707777 776767|6`858R:eJA)99,;6)p8g0p"QoCDve!z$u/u(jY:tO)V%i:U p\Xy܋\vWQksTU096 ( z CV$ZAq "&$Z&(]*,|.:02?46@77;77,777777676 8`68`5:;8  W%V_Ac7>h^r"p't'kY=sR+c1h8a$nc}ԥ xN=5l/Uz@%o?c.Cx#p( m Z 3'-.]xng` A"$&(*,:.50[2E4Q6]7y7a7v7X7s7O7s7E7r787v7!7767x6!9(%,؎ "  tO&U9CH:%nP"d&g,q+iW>wZ1d6n@k 5kTep)Obؿۖ޿/]|qH-_Um:NG# t f ( .-&r3&n^ !$%(),-;02W457:77-77 7777676767x6;866+qMtSN&H7=D3>3%]$O Gv%@lo6$S*V3`,^ N 4}[8d6r ?wHdDu4\5 {ipAUVKlGMdFh@I) Q P   Z]29 !#%')+-019457(777777676767}638684j;s٥Ba42( {Ij1')L+-r/13577 7777776767676 8'68Y58qNhf^Z&T5F767!' Gd #x"8+'y"ޒ+Kiy ~|hP2p=`t'|)ugI*i8sHQIw9i)K1^p7@ lxJjaEe?Pd( \?W!+z$"m Y}Y Q V $6D9+G# "$&(*,/0435627`7#7`77`7 7`76d76j76x767q6 83"`Tօw$6::/i2y=n\ oQHf*s;@=z7gT0yWz4N}kUZӐ{d$k_$&fR^xL^8]; l 3 4 Yl "d$&i(*,.0346/7Y77[77\77]76a76k76767.6m8*+ئܒyzrFc.X S]E8x[#k7}?~;w3k!N2}Z5T#Rл;_lvtUXR's7k'RP w C * &dW^ ^"[$H&a(]*,.0246[7'7P7!7K77H77G77G76H76V7673< ( Le)x,|*|n ]@n27]EP&P-`?tHzDw=i*W:b=b:BXtfڔܾ2]\Sg2ubAeZ{HoE i )  Uv-4 /"Q$&X(4*,^.024p6r7 7m77l76n76u76767676\8(jRi݁v %@"M#MD5i0d#Y9PH0[BsLyJzAo-]C$e?tN}7%ۧѹy׾"\ޥ!@sjDB8n%]'{ C  (f"zF ""$ &(#*:,X.q024z6F737;70757,707&7(7!7!777"76g73|TsLamIf$?9/|nRk6F{ vu֪Geui :-;o'3{i|+  mptJu!#%')+-)0"2S4&6U77V77T7 7T77X76c76767&fwH!/u@ۢ4\7Zny^=p;j$q%(ufJ'f; HJF;&n[y@R, !πВӤV_xyg<>uuXsg\f }  Yo]`2W!#%')+-02?46R7%7Q77K77G77@77477 7~720N$0MMft}~{nS8\(fm)rkG*iBKQND -~iTZA,<4t2KWDڥܦ,(a, yJaFa QyJQ u k RXQnF@!}#u%')+-/246@7=7@7;76797*7;77C77`767%1@ cpӏJ x/ER\WL;W,Xn#z!wcO)tBO%V%U#H8yfdQ8NFX^2Բ׫SQ:DC%K0yL{Fo9tD k ] DKH`t4 0}!s#g%y')+-/246H777K727H7)7G77J7 7\767v1An=ϒڜ^:[ #/1.\*Io%o|_V*x B$S+\1`2O!>& ut_J[3zЈ-ҐRI݇bzt:i7i3b+k- ~ ` L 868Kh|wh!R#P%X'n)+-/146B7A7K777H7.7I7 7R77q767$P< DI@^} Z,t8v'e"\a)F/[=c?d;[3K!5q]ie+гJЮBؗۧ.8t\5XmZ)V&^#Y] p S 7 . 02]~rkl]!3#I%8'k)f+-/136)7b707a7%7b77h76768u1 yCJkPx qխ! >+sUy{T&r:u(j*ff1N6cFpKqDk:_0H/ }wp@=υАӖ֚:QH@m9"S6qu}{UDIKD G g D - .Iw_VgG!*#1%1'S)_+-/13657^7=7]7/7b77n76767# ] 0=gEx,Um{ ~oY9|Fdw'y!t bB_7xI LSDu5_$I,tmIВNM݉ߜ3|,|ZX~_o>80502 r h - 3  2.};2q !6#%C'%)w+f-/145k7.7~7 7777676-81K V!CI!b֑)k8KUWN?OR4p#[Qp8JVSN@{,dL)oTG'D!џү؎ڸ6VLV;=bIT+"o&,&~&  g ] ! '  !l(!jZ !##$+')f+T-/135n7/7777 776768P#I #APB!xD"8tѶH/W0FRQL8yA R|/ucTsBTb"`UJ8s%Z =xGy.^iѳҝәլ`Tri1 (76/Sg+d&a+ k ; )  ,D5.y&!"%&-))+t-q/135.7|7A7z7477 77681y " gXߕR:TenlfM6Y)j$k4sxL1pUi'r)r'maN8p]TKχҼTpn9IU*f(7Q+N$I(w m & ) ,.9v-x!"%&/)+y-K/13677"77 77676d8#% x#G93Z#0SOu^jjbN6oIn.b:sP;wb#x7~67~2n$[C @p϶ &.ky]Ck3LNM| Y ,  8wY "$& )'+Q-s/135M7n7n7c7m7T7y7'77_2M Rt* Y$_fІPLt*;@f6L*%Bee؟lGك1o4&wS,zJM|O C 1 >T3& "$'(<+-/l1357;77!776768$ X*hU!"s!7cͰ1MUv vIH E{%Aq96dS}g mmg^qRQJ-j%ѿ~h#Aۂ!pf[uLu;y>w>x @ % -U|6 "$&(#+0-w/135e7o77h7~7l7]77<3}e+wQ>kF!!&'4A'DW|qBQF}/HB?m]nz |v qcjdB &Wӱӹ>շւ%ݧ09nE6zCk\Fs#}){+ \ F   ^ YtD "$&)*M-A/135)77D77 7768b&j 5 oA `>x@e!"F&;$ۨyI|(Sw qR+f$9B>/Y<](u10, zvUvhЈalջCش_߂5 U'FL8jvu!V D  [Mi< "$&(*F-C/135=77e77b7774aCAI- #}$%WwXF]'m*s#jY>p0u0QA>gBk5BE=3 hJӱпѬEգ f|3m*(v~xp<)ZfdQ 3  FRo "$&(+-Y/t135w7t77M7768N( a-B'. K$ $#J) >5]]D_ qv paF e'>SJB(nT*v@N%S*N&B$/$z3&TԀ"/Yh=_ ]e}h],wOXS}P % 5Jh  "$&(*-\/q135u777v7775 [hI}JHJ!n#%K(>NΙڎg2 r9Yr~nS2TMF^=9%M~6B0ԐԿ%2wޝ$uXd 5=KtfvTKiAPOwE ! 4s8U  "$&(*-5/135C77a7778* : bx!!"2&&(QוJR88lYtqV5sGS ?h ?Ht z3)P>\KePcR`NSO8`>7 zчv`pؾ٢*T6 0 3_Qf?= ]7xGwJ r9  *k0G "$&(*-4/~135R77}77k76x`  EE*>!"E&t&+NьBgq5 i3Rfko_F)uMPIbIO~{>-\HqWu]u]t_d_Kl bѯѾҪ;֛֭$ؚQvnm?2K*#N&l6hAg0 Z#; y"s$&(*,>/W135777678. >6 L+N YCi!#q%'9*!#`*|R0?E<* V"D[^YI#zP4rK[ h jj}kex85D{b؝ۄݧ+GnCH)9@_-`6^' O.| h"l$}&(*,1/P135777H77 y> D J7`,H40 !6$$((,H$pK l}|/uc 9"T$J&(*,.\1I35 7'8&78#  n@"y#!&'k*,(0NW|6 Z&x5=:({`: RSt Ze/1dYu,678!-(-PїӒ"סן1ڶ:r;"|pLz=Mn< t ug}6lK J"<$`&n(*,/71}35{77 83cZ K 6 b/okD"h#~&Z'++/\Ϥ݄M)s @ `4s<:y,kR2WR)au =Bqi"8H,K0M2@552LJ!O[u^ۓ܊.sZh;p7tD k0 j ob~8v^= O")$j&](*,0/13T57;78(3 P-k@ "#7&'*+N0lώ_^!Mp|a>N`{'op H@k8M*Y4^7b;]:X0?Ql ֑֝*ٹ٤HیPެC]hM?pT4k"w;Z3 x o ]fj"llJ 5";$Q&r(*,/?135775C?& X C3[xh !f$%(**-y.,WHQOAktP&p,hKf-v:z@E}Dy-`HӮEhaڇۘbK.\!Lxv<*`u&J0 e l HgS~jEN "D$!&(h*,.n1-3568k,@  x tey !$%()--2W rӈݗ.},/m^ztN$k2t/k0n f E7tZ s< FOQO65vzr اؕ: ۸H*(gvf_.wM d!@ _ ] DUNylVE: "2$&l(k*,.Z133577U[v Fb"kXrL 6"G$M&(*-.2#gvCI;YhlcO2 wAd{+|&}bS9Z4vHY`ec(C )ߛѦ0ՠL=}RUXnDdovk[@#q6JjC  l b A D<TYK.mI "#1&3(*,/13B580P Ey [ - |CEM<5| "$&&(7+`,/01:G:e{(2c2A;.OQ A# e"$&(*2-i/}14E*z;p k^O /CMH8$]0f"w)9&z_Q*{ K*g?wJX aO2*B>؟y7ܤbx3utg ,&2 |;Z6] k _ , 5 .NW>&g !$%F(3*,.Y12L6*] n M Az J"$]&=)*-.2256߳Lx|I;rQWVJ1kIs2jE{ )`b.!N=iR}` nN$ 9~>uG"ٻ~Qݥގ 3rHCi2Q+uM  b U & . #GO7|b !#%C(+*,.P134zm@ VnB - |"$&B)*-&/22Y8Ѷ܁!+|yFn.;<0nKm)n&C**id3%]Iv\o|!WndҦ~ׂ֡M!ھUޮ/dfsR&yNq; ~ b @ .  (U<!#% (P*v,.03J.  q 2 >n9j "$'(m+_-/1G46. ͲDSuS2a|W-Kz50;{!v\C!nC`!p+ 0']ڣvb۰ܙJ.SB5Xy6$eLr! i b $ ,  Wa!# &'t*5,/}03!U6F a gX^" #$R'(+#-y0h1K5358meG,R]{]1r9:t';xZN tHc2y994(gA;أٙD3}d p T,au`& T8b] P   C[r!#%'O*B,.004  (& C  FxS~ "$8')+{-P01559$!H6E!qMbKix|u]@wC o-05!veO-vSr1@-BN,l+.(&(f޼ޚU-VP}s>xgCQ|D` 4   !aL]!#%(*,Q.1M(  # : w H?]0ZX!"3%&)X+./2-4$77 3@m`'M}!9C>3TTDy%0f s?Akf2(=<A_3kF\UWQںۚY3ߐ^X 0gs>jOzfV# eEu& jS   Yo(3`!#t%(), .1~ ,   P hCT*Sm6!"T%&)=+T./337F6::-v7Er#'SEDn7bz=Hnl 74DLJr;zV*4ӇՊׄ؅=+܊j+g(A<>4YqzzkW=Y2`"bC  Bv-8l!#%')T,.,= F  S G G 1~YW!#9%:')+*.02u4_779&"g6wd`"-." f6S |1|((otMB{ l.G7SS[}F+k%sӬרck ݺݯ\J  3aWkJNwXB%zh'   >Ne!Z#%'A*+V/"|    j b 6c ^# %'\)),-0F2e5h68 75xIpxAL/Z3v@<1t]; \`4v{bW4c;S4bOn}Z3oCؒيڞ8Cދ߂'_ch G7T-9bJ-f^  z4uGB!0#%c'C*+(.k#C7  y T w$Dw!x#%'g)K,-0B25E696:dS$h>!Z0n-m%d R.ZZ2tya]=!gD"[AjbsaA0(ڿsv߸_N6^fZ/=$8P4l%dD Yz#S`!O#%')j,(+7 '  o c K|XN!T#l%'),S.02=57/8O7L9f*}a=[D+Tq|~t\?s;e#k%gpNIy :4SQgqu]\-.].SۤܢRG{3#*K& b  yFO"_' 0Yp!~#,%'Q),xJ  u  b yj)bB9!/#%l'1*+.X0x347)7867<Vr!A`iiIv Ks+R-R}AZs 5@Sagr]kl\փVx#'݈t4j@%\9\6w7lR q w;g!r#%'i)*5m  Ea ` xi(sCP!K#%'>*+.|0347 78.6;Pnҍ FS IBx_msiU7k?e#N'Tv?Uy9@Wbn|kvX/{֯}٤CUޱޫ^Ly5ckN[1e2 r n nwlKH%! #G%Q'*$[E . ~ r B]!#%')f,.035F7877v86/ ʹ[/Z]Ok #J$'V e89 ` \ r;{bl!t#&'*F,PTO<c,Pfl#nv_^12^e7 ~ٚzܠH_tc2(BXteQ.]'pN" OweR "W/0z ] o RoDn!#?&(*,x/D1 458S778,7]868s6^7@.'1XQybeZFt)R-[Bw)S"De9NnrD Ֆܴ۟qv6/F^zQh~}_N,v1zc& #eL: |XX)3f S m q [c4e!#C&(*,}/L12458?7@8 7x8695c;|ЀެOMN .,P@hHq?j0X:Oo /j Ar;`y9FjnA'թݏޕVNfAD z]6N$BXZWB,wSeE i p_\~p!Vh(#h$ p k A ve40 !#&`(*,5/13C67777777E78,t{;Y-u` ?]s|o^@Wu3EEUAB~OXv 0Gկ/ݚ޵iu&*nmN!n!'?&+g*sY e e Z jtDN+ L.{7.! M V & J/!($%(d*E-.23697!8%7>86q8685W9˵7B9Jomz}ydG W*{9v"H8?0 p WF!+w&տ9M޷߅CQ7#*:J/ WRNFl y ; _ - bB F9 z&?2>mH ` U ; jR!$%(|*5-!/136R77;787D8685;sчD sFtV6PYS@(lId$k;29&yh LDy $'!Cc0ߣclXBP4nfl~@99/U b # H  K+nAMZFa g-l e w & _ AsmN#V!#F&c(*-/1D4U67z77p77g77h77720xHh/N236 7777686[8:685;$ ̭OoFP4U   7#EQ:!#L&L(*-/14a67 7777676768n6o5{pDZdE[ ['`"^M/] $Rl /Me^ dڛ۰܏ݓmpK@|Wdv(i(oVA cJ U n G p P o\ ;GDUF   2m&38{!#S&3( +,/14C676767676386847; lu\-4LmnEp=Nw 4nGpB_%DV{L۶Xڧۯܚݖ}sVD& g,w)5d:_hY,yE'ec 7 F ( E 8srycukKQ08,  T|6D!#&W(* -/1l46s767h7/7f7#7k77{767a69(L۶:f$WR-QaebK1 m7io2ICJ=C"+Yx2rSܜLڦ۲ܡݟބbU/y> ;Ie)QTaaU@,uS"kN8 #    .5oz\%{[07: %Vdu{!#%(*c-a/B2%467767676767I6I857\hؚT8,\~f8n9r.i"B.;)$n[dRܖRڱۼܭݬސߌmc>+P N]s*1:({W( r>8   iH_lK  H5. Pjy!$&(*-/2^4767676767z67685;ЌҬvk ڲ^<*h;Y_ZN1a*t(^W y(g ~#Yq:s^3/5ؘ}mB'b E?czd8zK+ ;hn @2S6~# q $b1!u#&(*,/1436}76{76767~67J675w849փFN0>TyS"^$^_1|-).kz"9MZMe%֗4L,x=L~X' tB+I'<G>^\%+   BEgT=z O_^"n4J* '8f  !=$J&(+-/2466D76K76V76i767868M5=:qЬܝ67 U{ Y9\hndN1p EiWG|*O{Bh0?h-Y 1WS1 VJvP?-Di`Y(yC$uk I S @ [ \%['4 O k|aB &  '#l~%yv:f T"$&f)+7.k03(576276576976B76P76^762i ˼ٝ72niPwtN(r<z,~1OFTD;)|oD)9ԓR^KK.(I(o=D7:T?bK !Z-iwv>)^r B _ 0 i H + *#%'),r.a14366O76]76q7a67*675i84:<"ՂjL-%3M^e{op_Fb#@Ri"u'A*=x&a\a.RjI={]ۣW}>T"T;vAJ8q#DCNE@$Q.aG' FyC5EXC&:!W} x *wbb:l!j#%'*,R/146'7676"76,76H7Z675`9$nٵ#'ZFalk\D"c/P^u&u*g vE`{[&&eֆohݬO~.GaS}PK .-spd:vI#r_ L @ D H [x5jrt|ZZ 0  ]p.I8"#n&p()+5-014J6:76876D7t6W7N6|7 675$6Zʈ؎/84:FJv/N:k?W1 :>-[^J=VFK;$|WdyM$%dbݰ߅KI P*J {7$FbdeXO4\-g<& B[(8:4k A Y C N Z/3 "%b'),w.0<356666666666c67,8ڠ>$.Z5g"a; g-TTlbsM^!FPm=;>ՀNQ޿ߕ_lX?K[,ZsD+}G+p[ B ? < > Rm)vs% q[!X e f _^<)ws!#m%+(*,.1q3V6667k6J7H6g7675848jrRfv ]Z ' *)Qr89`Gl:T}+T_5=4}Yvx-c1u@u=dVT$(-iP_P n. [#6^ V{>P*!#Y&Y(* -/146!76&7g6>7=6l7574?:@Ч܁Q1P&;woh7v B Av0W9L)2eh8;e[.ݚهvmQ?" X&Bn&J ]xqrG:^D]W (+H%Z{A"![`MRCK 2    &CmE<STF t"$&)}+-E0w24666666666660Uڿ3GJhn3z*o\s \ ThU!#%(4*,.1366667h6'7(67d5r9B",nBOP(OfpkYAl:}C8WHV7:sr D:rj: 4lt9ݝޡd\dFo<<_!yF>D<GT %  $cMryV/-  C_!7$1&(*e-i/%24667m67L6376e75|4b8#N]|S#b*eU vbg SG0|f4;Rl+Pޠߜ_RC6G d 3$!_*yLr g P Y N mw@p`Q7wIJ;Mf 1 u  h $_J/ "q$1'(+-0&295 6@716Y7575&84m:F&T&)>YrvkPu&J=^QlNb+>en5#o:Y9׏Aډ%K߼߾wl&X)g,8ew`A)L+w9- 14)L!:&ot/? o  i<h( #J%~'),x.0"3L566666[6.758 'p}8QE gn/^i ;:kg)&Ii3@nք۠ܐcKuF V kxFcpto^A_+pE z l {B(= -#1 :.0[? ? ] Z&{Cu] !$J&)*-j/u236@6K767584`:KӾ:2!)+\FzQVH2pI&z<}6QDN8+x]I~8MCN28܎ݬH^ G:TKf7#QREC.|;4 #"Oa/ 0$ig M h m i R F "$*'w)+.i024666666!6 8*"){B<IcsoeI+q:N r"av]d:8kk"/?eJ D<ב nݪe߁&YPd_~!/%#W6T,JA+%H \  J  X48~ !%;^ GmKM    w,b1d !#L%'),c.S125G6676f757$57MN5f8 2Ea]ygbY|;b@~;bQt'Ip%LX}==[az tYסUj"$ޜ߆G'P `U;w3i|Q/T!d9 q?h!p"%[ 9  < E/5ScW"#\&,(*,/L1845?76h7574$:>ҼDݯOW} 5O"a#]O4~G{;tJmDV $QRv u &69̣IBLK8L[SI+ Z+n*j$>t8f v>Edr.*\3jY{Խٶڇ۪G[R>uFL.%S @psY5 [1n2 b _ I a Qse;` "#r'; j $|3&!"k%!')+.50I34(76y75748i\gߵN'W*>4X:d2b%W8{Bx3cFZ@5}fJt=-RZ]O&Z,b,ۢd݆)_[|Z9 m1rWQA 1\|! #$' Y* - AEckdV!#%+( *,.v135J6;767)59 vAj1tr6:;* xEK 2q+j oH>yg5U8rM*K&m/.ܤ݋O1a=aclWP1m1 iAaO ( $   1A \]!#%(""B 5hXiE  N F * faA"aQ$ !N$D&(*[-T/13O666h66601ٟTOo17.lK)s39VBI0 lM2x[ 32>Q؅2{eل(6ݒވ7#dH2piJ Q0d) q z m 4}czMM P"$&F)L%flq U t A4'[ "$H'(+o-014557574l9lށXBz2: 4"Rz88[+Hk(F@;#xXFm1G@Va^^[F&٪mۇ!'o^ve:ynJ%f/]6c \ 5 > % C<x!#%i([*(*7 & i . > X J !Xm;V!#1&(*,Q/"13p5$786>7:6M34])3$Yi* JX]Q:K Gz$^mIP"O:wXs/A?#Jz9ڮۖ[9ߚp,lw'.$!}QQ].  T)pz j"$&()"++cO .d NC  u tnf4HG$ "$W&=)*-A/2365749 +ԣMl'eu PTE4@{^O(tNn/8A: _׮i*[ܓܢ;=r`Nxo2_cmxzH<~=dKSJ   aw_aJ!#%Z'*+-(I = V  4btI #%X'})+.}02 5F6 75{8&WV/v#Tz~cCi-\YoMR)%\T~ v$7;@b9B\'ԁr:ٌ)ܦL\}jeHRq L>pH= d y A l Iy]>t"#W&(*[,M/   W p  X$alhI!#z%$(),V.[125 6{75{5G)ئ.VG++ YM Gv=b }=Hnm84KHW`Wm+sٜ-7xg~ZG0 <"P]n`_A,JyH }Q0 3n,?} "$&(+6-`06!h iI    wsKF"#&2(+,/1e457 59zpAqv{P a%]Kf>D{J9mUj(~7?=I,VݯҢՒغ٩gFݢz7 - ^.~_;k0^3Z F '  "!FeNCMN,!a#Y%')[,-`1"UO ,  @ Cx8L  "$&)d+-/,2T4i6h67*\S. cG)G]_\G+Na8z&+bg8.cVt"0,5K*%׌+ڦګJBރc}l#8E@5 ^*TL* { o $Z2^@ !$ &(k*'-.@2Q&d R " * u  L&zwWf!"%;'*+. 0]3:47t57i**G?| W#a#YI\62ta>_-z;"C5JX; fB։GکOjކ߇*Zmpn.pIx+ iX  U@U "$&)W+-/2*y Yt  = Jc (!!#%Z(*,u.12T6]5>9VВ~!cIljFd/m%c*be<;ke! 8%F7PCXXYoh֦)Qywߡߊ8qQJ l/ P0}Wr e = > ( <:aze]cZA!d#k%')",`.0B3. Z  4 .  \p)=Y *"x$[&(*V-@/136 7/Y[.L(+"}Td%LCM("^Nu?W-k8q9B)-2BݍaQקsM۬xBߎO{`x Kt}|pR;P$w@p= )]?" $;&e(*,,/_131c| P * ;8'4O)]s !#$s'(+L-01z54 8`՗ߖ-0`q|W(\%r&Y(T^$-RRsl$/(.= |,ӦפسOE܂a߰65sX]g> h)U`E  3[e} "$&6)A+-/M2644[ " ^ p v,[eZ Pl!N#%'*+.G0S3(4o8!KE1i7JUPF) p? m&;9<oN;t^ |29*<88P![i,بSo܈݀ l_c3%6WQU?*^(xFj: m e F N B^h#bSCg!E#%')+.b0!346N86  a  "#G&(*h,J/0315V2]Y i#@XpuOc']Qe N?zmI#j9L$Q.T5SJEo'|ҝIUغc~ݓ݉< T0+l7]XB}7 O#zY  9ZB!$/&M(*,&/%13957$k B P >[~n@ ""$E&,)*-.227m#Ӿ!ZF`osfV=V'm'e4p|DBy j.C!S,`5f<f;i%@ 9Pْv"ݴ݌Hߤt] Y*Ic1vJ ,   3g\d "$&(O+g-/1f457+e q # g2P{F' " %'Y)+-01\5(C͙0S*Z} }^5_#AHH8!dL-qM_&p,y0-  4\ڎ'*<)ٺiFyޘNs ^kx\R# oD[; X Z > YL}tdYV)!S#J%'),.025B67a0     sxU!#-%(j),-V1194T#%Mai}w]BtEj"S*Uk(1RQvp !.+' 4jt=j՗9[ndݝ;4%r~Y(Tg._7 9b3!#&/(*,.1p3l56640 c *#l'*"#I&'*<,/0758RKt!/0%sP)d$|1=6'vN8} ^#x4>?'>0,@sunӫ>؀y|&oKXEEWC8vHf'uC U A   '0wVc& "$&(A+?-/1?45)7Y66#%= I BCTBG ] "e$&(<+-/1,K^ 0ZWoqZ3|PU Of MGp J*l>MP#S(R)G+88<_)!rc؉یۄ3޶ &xq2m-znYV,f7\# t _ Z Wk{scjM3!D#O%')+ .k0l24@6#7467S"F*  t(yO!"y%&)*..f3, N դ`I2lCGH6{"e=c!_6r|UAvh0H"Y.^,a*d#^^Rh үԋםs*ڰs?ݟޫ+GV4o "}Gg6qFv?# PQvI!$%F(?*,.71 35k6'767(( U dWO4z!#%')m,-1 BܤUi 1O`gaP8[ w3L@D&|J7oRe!v')$}]6hؖiVnܧ[߷+"5)DSykk7,q 2 F(u : ;  Tf{ v"$&)*s-g/13+667>67A. b X !Z,~K !_$%( *J-_.(." L 9TNs[]RCt%Y3]K*Tm 40UV~ t '(&|&G^n>t>%JckۖSHe@w}Gv?Jh< } t ` kn nfU0!J#I%')+-Q0i24Z666662(  A b'INMU "G$7'T(+,`1d*E X_ZH-Zf%>/-rb5[,v9 ??:2^A{esj},@W^1:YEI$m,H P~P)  S[{E!#%/(7*,. 12d5|66z66]66 + q[AM& !# %A'y)k+.$ V,|AHIC+d9>G\LE$wE)h? JTQL@ 4%|MP0sلr*Ax Kqk=wEUa(m P 6 "  *Kyjp z"$&(*C-]/13566r666a7! %Q {tc">"#?&'*+[.ZIד'FTYQ<"OR .hzQId1HW$^#][ONzKW]?]/ج`=ܾ۠Psl  [8X_}/ c u \}y4jN x"=!#M%8')+./u2A4z6w66K6757(z&h` dCC%? !X$%()k.mG:iu#(rHXC5D{J/iP isuzqg}daq*PA]ҁԒEURڦ\INzF.Y +mhiuA;:L!O+ug$  !>p !#%'J*I,.0346w66\6667`. c a"$q&/)*'ͨ 0H VS H2}Ay5jIa+,ZGvh{#!tsrV)@ҭ2?$}<U"b#t> p d bv$oM^ !#(%)'j)x+-/32)4;666n66T66'6J6~) S&>Pq!i#%C'2+>q@WnpfV=[t3E>4kFc2w?E F70wk YyIfWѴC`_ڻC|+7vsC,Yc o(U2  HYv$!#%'*7,w.0246{66f66B665}7# Mhd)!"#&'(ec ^-o1bXgK=y b#u>MNP L9t+c!BS~ӵ֓@&ٙ\|<6yiMmr y)l f + 1 <9QPP y"M$&(*,G/013\56O66<666657* 5. .| !&"`%%* )'{vkssT#_.z.f7et :2^Hq\ ebc]wPbAJ7)? ՚֩'ؚY]l.IBJq]oE< Q(`7i5oR ~ { c ngy^E* #%2'<)+-/10456b66X66C666M7/ nl8^r5-!+# %'/hψ nBVE6AK=lT dol ibwU_IE?E~4 z*֏ַWWCOMUEGsa;e*m/o:]&  5Yz !#%'* ,b.e024m6_66P66F66;66N64v 0K!g}0 !h$$'dMس{MU~d?vH]EgIJr>P!c)g$jhULnx03@*bE`%l1w9{5t*hS<"hUh`o10ֈ^ߐ;%oUy-(,OB On7R&}!#%')&,.0\2466/66"6666565}7-az 5R*!PZc""B&(L@*. ^TL_hav\{No:bFR{ 7nC] G9[IlRqQrIg?Y0F , vqDXySO՚Zici OL[?=b2t@t:yC~ P ;   %AjVRoN ?"?$Q&k(*,.1*395Z6P6Y6K6R6H6K6G6A6K6!662 8_[1 !4%l۱ ީc6O^fcYB&i3Xjri `:"Y9lD{RM~Ko>_.E)qr=\pt-lFnlJy2dGy:~6t<N | u ] k` qS( "$ ')R+L-/135z6$6q66q6 6u65}65655 p/k ! TڡyU$SPWgTrJp;l#S2 n.bB!*_Y#t9} CM ICz5e$L. ky\I_vBҕәջC1TEQXR/oCk=k>V# *w;P|!o#}%')+.,0F2b46M686G606F6$6I66T65|657&q}yPn$ҙՠ߆$;B?2Ui+NAL%T8pHzR T OEw6` J ,w `z>YuXd՟6ܭ %E.P`rc^A&n2x9t0r4l E &    +R;7@) "$&;(L*,.025&6F6(6F66F66J66U65x65)7F-rs!%*][|rU0m0O^ `U@k< DNUMB-hM9iCqwSm]k֣J݋C _kM}2}-u$~6 x Q W ?_[9D "$&(*:-4/1n35$6A66B6 6A66B65D65R656A2p$*g!2zzDu ;3b+T_: E*L'O$A5vavES++F*`O ֡Ў%1׳OmA>+!b-z8t(k'A  R!yC!X#>%q'l)+-/1645H66@65>65>65C65L65^655 ulwq! QmF!k9{2x)8zzR9zNRZWK 4qUj:D '0AwO׵ڮ>9iQp 8spqmD2q+t.d$a,Y 3  3)j !#% (*T,H.0245865765765;65B65S65~695 7(357T]uJSL;K) ]C ZV`XM5{hIf+Cx'dB"qѕرۓ1O|`-9$c:]2P(Z7 N I , :)Pa/z~/| }"f$&(*,/1=3%5"656565 6565555 656.{Xd9 'jQ-oAS Gk INy >!Q$S/V(PF .~bI_(:sz[<wҫّܓ L *5/5 ar+eXj5 ~ <p i7 ! #%'?)V+-/135665655555555565B62^PWF+=!u[7 }BXqnfN4tQad#b^I3rU2dA}S"mp?mݐ| /e}oT,f'f$XWt@  Of'!#%')+.30P2X4555555555555555555[$K>Q]|sph\F(rL g!j 6u}OCz ckkiaQy9`DiIa'/aN،פ Fގ|'ltMm%eU^ O M  % ([hrsai '"T$*&s(X*,.02 55 65 65656565"6m576B5g6475*;hV\OP#*ZB9AI;N*J3j.aO/?ws:X+c,f*bZ G|2^=d{@R#uԲѼNsߍt-$'R:I an^ MY  s e doiL@ "$&)+?-R/}13f55555555555555555R5l6/5ޘypLLME6|Z3t7EWNA&sKd'n$m"gXJs,U4`u@@d&o]}D:Du5Ajm!U6R,?3WG Kr6Nr!#i%')+-01;455555555555555r55b55g54 PڝjB1)+76 .v@s4v"Sr@Cm_v!yvq bKg-K#Xg48\yeSMKT: uRjZ D{Gx G -    2^HBU+ "$&&(B*[,}.0245555555555555555555]5'Ն_$ qLu>i#r!}#l `<\/n5k-l)aR:oP*kCg= Vm\[%OX ~-UPb?:T$Z D 4C s R U KYbO)[ "$&(*-/<183&555555555555555v55Z55 5c6,  NAPOE4g6_ 27,fE a2o4l-j%]L2oP~*[+mBc)8h'h'dާnA~Y9c_ Ck8zY  o6H\b!1#V%;'y)g+-/1355555}55r55f55W55D55*5556460 e^b8g>K4W22eZp-{*t+o bJ,h Ju!KeAJX"~lv7צreP&-]sVe Oi8_5~f . 1*!h !#%')#,.X0C2h45555}55u55l55b55T55A55)554 6n46tЭܖtVUO=(qR*|=?a JS#K0a;l5b5\%N7eDc9cj;35)9Xװ۴W!9_81qNr6G>">#wv f h " @ H-y~  M"$J&(m*,.124o55b55V55I55;55*555545464l635 nɥ֬%n ftwHT"-m'A*Hk )F?^Ef>]:W+A, fvER%[Z3{Cӣ ٺܜ:SV/IP7]Ke0Vb8 z s v5p]/ !"$')*+?-\/i1x3%55w55s55l5}5e5z5\5x5R5w5F5{5255 5547j'$ڍ7tV5r;\n vm Z;Y0i7o+c*TF,s Ts.NsDQsi)o0Ӳږx&!r6Ft4WDaD  SxC[2r!#d%'{)+-014.55C55755,5555 55454546T4y63Q6Mf[$<7Ygdq]IA"#~8R Li.PX| t!)vd N}3a<~R"U(T\{0[HO%{U]NeaNwLYjQtHU/92f e # + *t5-|q /"#(&'I*!,y.K02B45955055$555555454546F46839#9i W!E))#f+MTx%Io ~8/Y?e@g3^'Q8f@iAO{GIu |~M7D{abX&ruQ~=z)Y|@yH  m d B KLlU6c  "$&(*,.034{5J5p5F5l5@5g585c505b5'5`55^55Z55855-/ ʲ)wo[~Iv5o^?p2{1XHN%M.i>t?s2h!VB#`4l ?o@vHi0{I ل>*?aJ&u%0zXiFrd ~{>SGl!#[%'r)7+-Z/1c3V5&55555545454545p464628ʜӺ܌kH-OR4F#9Tlu*)}hPi0G #sF]'RO'_;*/Cڨ/0Fzlf`2xGw@]>{7j F N3)t4 !#%') ,.302234J5M5K5J5D5F5=5D565A5.5?5"5@55J54v546' o;+ z_;}G c~0(~hN$s< C @/whLq)O rFV"~LC^UHg֠۾ߣZ4 H~d)>t+N5~6 ~ t G P 0HD++ ^"$X&(m*,.024*5l55o5 5q54u545454545?4<6z36'\ԈYx?$ aw'CU},U|#OApT VPx?o(] By"P$e7Xq~9> |'VDܼol!K= hNyPc-:|(@% ErJ!#%')2+3-X/Q1^34Q515G5-5C5&5>55<55;5 5>54I54y5\46T$]΋0X!gI&WFQ]NAj=JPD3zeMp#Dg5Ndy18"Pf\2ޥK.Dn)4zz]W6-j tHe>j + 'wwV!#%')+-/135J5$5G55E55C5 5B54D54F54P54`542>~Ӎ[(+^-p:q$ew#]Z)G$U&UG :$lLq%Kb.Q`w':d9ՀU߂@n^> lIR y:V~7t> b N < ::Kf-.o `"H$S&K(c*f,.02e4I55A55<55:5 5954;54?54N54}5N46 ֣%fCf5s+w*=%^D`"l#iUH{-d AyT}SVF~ DgUL߷֩܄L!5[YaH9LKy&Pp<xO Nxu'!"$&)*#-/=134$5;55:5 5855854:54@54P54}5A46$)Z߇q\D'mM"s6~9TBH$y H!c/n1i V G/f >yR~ GTu7~CUtI ݹ \~l6ZEgBr5_ 7  1c}7!#%')+-/1355355/5 5,55)54(54+54/54454-3 $u>qQ*uMPVl[V5[/m6u2q\ L/d <|OwH No1wADNLs9kYIIn' 2s_ mxLO)* n o 5 K "I7sz kq #"F$ &E(*a,0.062e45A54C54F54K54R54b545W4537[<|tmnL[,G"b!N =l)U[{)6 .p [u;Z3Vl#;Sd!|yH/#<#_{6\QpZfU1H%Yp>tS ~=bU  "$&(*,.1245555 5555454544545E-1?}ߏDa?d2v3{4K55r c- =C=$q\;`8Ti:MZyvC;Zcfe;Dmhrpcw"[n'A|7e 9   !cgx1~!#_%y'b)+x-/}134054-54,54-54254=54S545&45j@bW=uO/gI"~AAjVd?-mLY\O5s!\9mB|Nr:K` ow7"~ $(׿)'cC_Q/i5M ]Ee6@ sLwI \ T 4 >8TctmE 0"$& (*",6.50724555454545454"54S564l6"Y܆kmO'd0Zr'~)|!q\7T!a$`S8|"bBm@}Ms9|AXauVf[9A  'Ulri[7s GX<Q% 9nN "$&(*,.0245 55 555454444454{5]/K~g-8a2U=?G6(lMd-q/l!`D)_=rDx Hv:s8_Vs,;TmN@l0`Ml@@b4T @c A   5]n!\#b%I'b)V+s-e/~1Y34454545454!54154`5,45G:ّPTjD+b(v6cZi M?f+}86|'m Q2`3]7()e!=vWbQevy_FH7cq0F B w J R .KF _S "$%()&,-60144&54&54)54-54654O5p4536I& mWUm:g.6j;qyE4lMRK=pR4p H{MB~Cg'a!9g`zh۟$U}?S8Xl#M ], JjN "$&(*,.0245 54 54 54 54 54 545419 K? u]4Xc$PAM/`C QYQD} ^AlDPzBBafz"0*uDp1 p& 8#j:`#.sknD=wf = <  ,0`n?d!x#=%m'9)r+?-/B1v34.54*54,54254?54[5U4536!( p&ݟ$,c/Xn#T|$S_$E,W5^.S@ pIm#C\t"9IX fq("x9BcbWFA|7*^:K~IV$U) W X CVV~'xmF "$%'),- 0134444444444445p45o*  %]u C$K^;0;zqD%d:pt+\8xT~(QX DCYckt/ZcZDa:h\~15pXfA? on:W2z i / * [u!Q#^%5'W);+b-C/d1+3445454545425z4n536<_} j| kEc/f j-pt M8qR^\Q;dCa-Wb*BGW^nO^V--!]EIR 7C~*JU}0r7 u e \eq=vL "$%'),-013454545454 54%5f45- Uq"N$y9w.T=BtC"^-h+aT=tN&_-^(\ FD^Vp{,(nYFێ>O:qN`1&dXo$4Mz.K ( m$wa "$&(*,.0n2t44545454&54:5q4j54(5$6o`p)E fGzR^+Q5f>q&\0B r m3; 1  e V " + BL>Bi!r#9%W'&)Y+(-]/1C34 5454 54(54<5l4z536}$L] 8 [vLr.gD#.c]'y8A >0pS{)[4h8g.^K4aHrp>B4*\,$4l-uFQqJxO x z `xt >lT "$%')+-/134 54 54 54 54 54441 ov`p"D [Ai BM~v6N"PJ8|[0a6q=j-`N{ 5aA}Vb2(~B3 2cQ<s~@CfJg *  8e @ "$&{(*s,.p02*4545454!5485r4t53(6S Eu(ڿ Ec,]h-uyVC~`!p'ofS2Z4rJm8u9\Xu.o 5gV bs Aߘ} jKLd"%AVI { ` A ( ""(Bh86{!X#H%7'4)-+2-(/&1 34444444454(5T46) |sb+q7]?FJ?.s W+q7z9}-sY5a;{ LuC{;bXu+k H52tNSr" !TzGUM&?k k*2]`% yX/|D "#%')+-/134444444444543h Kkoۙ߁+:w;Hlkp\I#o?JH <}"lChFSC~B]\s*j%0qB6+Ij$-ޑ;H `i|YHy nAM-f X   &.H? "$w&(g*,a.0B2`4454"54.54F5c4536S 4M0H >dP&Anv3"M-X*U!F ,| Np&G^}&?I]`o!rxYg\0'</ 5yQ\H\33[S{*j, r \ @ :7F[~N2Z!k#L%D'1);+*-5/134 545454 54'5e458, /MNtS{M!,X?@v f2)]X s s Ud`^%!#g%g'K)Y+D-O/01(345444444445.S Pq>]$s(h4s~TDe$s+s$jV5h0pFp7s5WPk_{)fW+lF0bKA/?Qd(,^\wx8Ui ?  Vm~ k"9$*&(*+ ./1344545454C5V44siVt^ܲ0'^*QOVH5~a3{EE<}+c DxA~M~By9bM|+[ 2`~,GH!k (#dlzx'=d{FB d\$m ` Y * 5;5rlT!"%&(*,.0o2t4454#54754o546#(% <?{i%O 9q)`].I%V"TH2wR!IWK =eTy,_ /U4z6>B\;% Jbu"^N] 8GOa }5{A   P b$ !#%'z)x+j-k/P1@3454444454n5/G"4*ޖ>i.Y N\<0rU"n/{.t$fL~)Z%\-\!V@s'R4Y`%b">|5N;W[+~#u@/aV[  S 4>L^nj=Bnz).<ZR n ` KPOjQ+H_!M#%'(*,.02F454 54-54\5.4k6&S Im3@RNN8#kE[c[J1e Cs  >xT&QQ|:u3UE_ K^Le1C-{ [:gd6e 0 + U9Ty?saU0q1(Fi3 ^ @ ! ;U@(T n"i$"&3(),-/134354;54O5435`YC 0b;z\݆fQb -M[~x- : 6+qW/Z/d#VJv3^DfHgFZ~g,eH*+ ] . 0 Q1y;mC&`0 j83 5  g}gn=UM!>#$&(*,.`0y23254F54z5)4l6\ z &)CܖFbH?k=T^XE|*`9s>k,d$Q=bIiKhj,f ]*~ `8  ufM if-S' p M F6>JlrX4 "$s&M(H*&,&./1354*54C54c4F/zHAdB8vc-{AF?~*hI{"PQ@s1]CiPlJkSNZtb%}l??- N m / D _?e[5f9_C , ` Sk=!L#`%'*)* -.0X244P545+46m"pT 55Va7[i&C+R-U%I5\1U%` D};\PlRpLj Bpdy e.(  h l ?[W>1D;Ws: i > )  &O} D"$%')+-/_1@3454$545.KC_~.Vo߇OeE7u \&o4~7x,jR3i8k6j"R AjNq"TvNmlYpg#ug%` x ( & N ^e7UD486:Y U  ~ fxBaG!"$&(]*,-.i0144O54o5t44 vbE0^t~Me7mU ?Pk6?D8 kEk>} Fj(a@v'O~+P}$KrJfmjr}9f4 ~ e 4 *w+&y?(o4+` v : "  L|+Z( !#o%r'6)F+-/02C4N54w5M4n6$` rPx4ݦW.pWP+zN `*j)jY;vNTMy7b!Kw*S+T}!Opw_ioiir&H ] ( KA s=rlnrq||<e6 | X O5FKljKp  "i$3&+()+-/1}345 54v5/RG{ zeHY'3g^ x; ? =.qW.[,d+V El%V~0a .\~%Tv Mfinm{1_, { ? ^ 5e*#NI4b!edm>~ P   ?]qj!H#%&(*,.]0m23<54e5495 @ `IJ1Z9Ft@\)OY"EV&]U E(d;l 8n2`Gt*X 4a5[*Kgoqgkm#: E / Ztm g\h~ heZ nR z J ;  #Zy |P 5"#%')Y+}-%/N1244p5b4`63&X Xw9(p6TzD.[>p>t:k%V8xOxE} p9l-U8dEoDm ;^Zft bgY$ (  L/!q&&)2K  P ( =u;=R!"$&(h*p,/.=01345<5W1 K%mO6^Vq ~ 0"J)Q$PC+oJuF~Eo,_:iGrCk)L+,/024v545v b-@v){p| 5'X7k>q;n)^ @}U%SL;fGnQuKm@_Ho epVlf8U @ S2"7v>b/l`~.k 5  tu@j7 "l$X&(*+-/1-354#6W)! '$>d^45(cESU K>rU+b/d'Y>lKv"Px"Po>a]Nhdl WaT/ I L W]n*{DxU k t@ X (  5z/!S##%&(*,._0A235/512|f? pz  ?{ 1O/`2c*^H,l@m 7r5\MoR{&Uv"No>_Kak V]O rc  c 9* nfA!J2UJ7  s v =Q/VH- \ O"#%')>+-.Q124z45] #Jݧ;HLeUrPoFi0T5~ Sr=>^QlXz#[vRm@Z\``sYaFef? i a  Vr _ UYCg6>9^ ` %  +r,%c!!"$y&f(.**,-/1345+ E#cva;S[VJ6qO W$ODq%Ux*\.\$PrC]> h_bK]V$= & t 5k~"  "V(aJ5Af T = Kg^Hs !#u%"'*)*,.092U443:]`?=S޴1DDZIiCh3ZD&c9b*f!H5Y8^1^(Oy?Xm gfPUJ { / ' g2 tOMKMw/9 4  ozx%\w o"U$&')+k-/1e3%45E!" T<}S-/ELmZ ]VEt([8s Bp6j%S 6` 9e 4`'TtMHYbNTA`tO E [My'F. -MVSrF b .  )iml e!%#$&(*V,D. 0 2z35-?6]oe>1:di3U&e+k%`O5l DzH{@l&Z6`7c0c!Pq P] eTQ>MU% W = n9 x/ BtvH4X$X Y$I  i GC5BPs)tN "#%r'D)2+,.02+437 @*#aj7f%+8A`MuHs@o+[;X#ONq-d7f:i4d%Mo0? \ U M:DCx- Z R 10 o>yT P6toLq s #  l){$[ "g$k&($*+-b/12z5#z |9'fJ-CTZhok ]In'O(k3XX~4o;l=m5e$Oo>a[ ]?A8_ ]  u 8*Gh* ] 6  2_8@![#'%&(*,`.[01R4q. \0(4EߪK*f7p8q'cN*g9m5h,Y@kBlBl6g!No/ MX \CA0F\, q a % !#zY ~{VCQkA_R5r&Co @ nsawyT!+r T"#%')8+g-.21p23/ `}gCQPC_l_wZwHh.Q0y Ip;y8ZFiFmAh 8Z Gl5TWO;00D <  ivjg1vUWm:l.I X +  OE<r1!"$n&b(*),-/A14k&|( =;:0LDwbWe} rqjY@kFTK~ )LM?,q%mx,] ! p QE8BNoi(njRzn:y%d~KNt > leZctD[ "#%n'8)+,.0 /r_D+x o#1,>nJF|=o$X9vH|Fx8fOz)W} KvBk0SzdO3KMD1}%ql!7 G #j ; R~d )8 I 7 (>3e "W$g&'*+- /1 "rpo-;5whyk~\vA[;[{%DCdXs$ZxNqB_,Fxs'G^Mz*:L\N`* ^ /  :y>I \"#%')1+R-..OH/|~#DW-]saR|Af$N)m;c(a F~0U/V$Kt;b!Imr A?6a^]9  \ P " BG;pf.0 Ddx^} J 3 4v \RG!"$i&r(*A,}-70 o:XC0[& qUx6[7wHo 2m(N4Z3\!Jt=aBhce?<9}a\Kk _  i-Gb WJ SQn ; a^J\]&g! !#\%)'(*,.**q|,2IW0%0*xa@nB~Iv 8m&R5[ 0WGo 5]8g^ 29"f^BVc0 o [  GIyv t'7V% B ' Yu i"@$%')+-W.U, f+Ur6 d\AY| [Kx2_@}NMDl&X 0`*[}Hf5R{4]gW '7%k^?FG  4  y zPdH}tGj@Js !2"\S/{VdY 7 ?$*qD!9#$&I(*+.p"89 2mJ1SKU"u3 kPe(Cc-KMl%^|._ )\wFa-Mz*^ax4$rgCD6c s +  Wd =!A"w#* {RQP6=d4 K - mli*.k !#~%l' )+ -E*7 ]7~zq#8Cj/4&s P-X-c.YKr+\ 0a(Xw@`)Es#p_s-'s%nDC(F^ 9 FW,R9~wf""$e  P7R${Fs o ?  !CF5j "S$_&'*T+]- IR 7gT<S.i.svizLi/O(sAc+f"G~0W3Z(Oy4_Ai5Ox${%p NA'|7? E / rK FCn "#% F6iu2S 1 x PL5EInjB\!P#/%&(@*-"J}3=vnaD p`\ |]q9T0|Cg -i$F0W.S#Fp ,V{7Y}Gpv&qWE&q$$^  O I+:9~-!#e$'V@ "me. ~ 7  JDJ Y"#%}'r)J+) E6k~Y[F&B20ߧ k1~0oY8lCs@t6cMy)W*TxEe*Ly +YxP n"u[H(n#tr< l @ T[ !>$&%'D8s"+./)sQ g 3 #  Hv hV~B!"$F&l() ,< (&MFeI__>0ߣw&_oOi0S 2w Ir=z<`Ns$Tw TqAV!Ao!Mi~{9`n\L'rh a:  ] E &8W?cS!"$%( [N2Pix 6  [fU{A]t3 !#2%>'(R+#dr_$n~4y #hzreqBX7 Vv>=^PoRtLm8N}6f?b =_ Z L.ub Uk X  wewz?# "s#%&)y|MSs6 [ % 4\ ]"H$%'{)F)f{<q\7>tOD=mW$j^ArJSH{7dHrJuEg*Kp/]| 5T{$WZR4{gKSd, q N  $B?-X ":$\&'*kn F~=!vJ  O A$67u"?!>#$&'*; SSAWkp'|YQDK2 ^z)FSo0h=r>r8eCe'Jq#Xt6QO?cK?Lu 6 ~ dMEGZne9Q!h#%'k(&+!"ak"N 1>VK` a + vxu ]U !#|%!'o)-$}/u`>&#g"[gTl}f`JZ$;b~,IOs +c:n7l ,[~ :_=jmEIC#f N58O S , `im `"$%'P)+%  u @  "AF1_ "3$P&'(NjW7Tot>,// K>}X.X#\Ey3] =b^8M!#/%n&!)F<{!vP }C~'v9MhDB)4g7TdB}5T9Z2S!AkJo(Jq{T~-:*jQ3{s|1 f <  x;7r "#y%d' )*,n* s%Vrc ] 1  6v:8s %"#%')$aGw-}49fK ;:݈uYGL)<e2T\>s)N.S&Kx5`<]9\ Sy.%mY4s!ha0  Z @  2yQ8[&!"$)&(()+m-, 7W^=Q v W ) ,kK4P,!"$%'(2RLU2q>( (rT)\*^#Q=l Mw OwFm/Ny ,Tw +Ms|;mzoZ8yePb O  xp_kq4u !r#V%&(z*,..=W; 04_,N < m rCX<mg4_8G& !#$'(P,MJ1a \2V*ޟP$kx:Og*CDaKiJh ;W"CoHb=j@ ki`:u!bFJZ f >  4-; "($&').+j-.@0(  2 I ;ot /"$%# JX=Nq5K}sަ`.%i}5Sa!E9Y ?b ?].K}6_x 6V'wqZ_]:|$dA?<r # g ^9@/RU G(i!K#$&[(x*+2.F/1Fw N V ; St| #@$[&sHmx,/_Z ,;Zt0La*OGm'^ -_(YzEi&Ik Di-j5MR?~!b>,!B y J ;]^ !"$%').+,./2Z _ T<N'% 9 2  ncT`k4p !B#%WZYS| 1$jBk3'og;Ag,EGcWp"TuLj 7S8Xv5UmuR>K@$c;$rm B  l I $  1LrbB!"$T&<()+f-/03% = Do.x m [ / neg' z"$3#^ 4 /++-UU'X^w-Q\G|:_CmEk 9c%Lo'Fe@gS78&eB%j Wg X  ylx J1 !#b% '(*,&.?0r104h))} rdA q ; ! :S2~g$|!"$e*FlJ'PkW'(G^(NLr,`7h5c+Ty;\/X|0Px_j4o#.~$g G$aONc m B  M8"C "M$&')c+=-.0H245-^rU I zdgaSsU !!$s~/vQ:XD&Ffk-y ]:5 eq)?EaYq$\}$U{Cf*ItDg;b|= l!se H$dG5Bk 3 z VKAGOtoHX!B# %&(S*-,-/n134.0  4. v +  ;e  ]"o" xYo^f#GNp}SgE8\(;Vx>z7[HlLqEg1U6_0Sv$rQSUfaI&`C){'=  B   O_\ M"#%t'S)+,.~023V4|2Lq {t d(  ^ w A @'9+ #gn%(Mr7W+@*W(H߻NYh:Daa{.g6f .\yGc%Dn?\]RPH#_@dk}H m = + +c4!#$~&(*+-1/@12c43Q4?F} N~ @ Y Xw`g*$< H"}VYyXB>z!S">R/9&}|[\ /BWTm ]y"[vKi2R/Zu(DqE@;r4?E"_B}UTQ B  gvf_w O !#@%4'(*N,d./1343*5Vi ,^ 0 e  0~3|(z_ ! VuCeW+Vj);St]|Jެa)dd?a,Vr~5w$/y[>yQA5U c )  Ix# + z"R$%'o)g+,/z02343b5%P k& { N 7 #GRF%hM`!g>"g )lG(f Eެf@=q4M Nj [w +b *YvEg)Gr!Hg2^* QpjW7s K.zu(I  | a >0$27\Z2C!%#$&('*,-/'133e435*" zl  y ]lQgl A r Xz5N$z6.V<uW  *;b:- gt'?=XKgOmDa.M}2Yv 0Ji  7A U   @Z L{C69#Y 5,XbP *ނAPu:r)R5]9]*O{5cD`-Tv6b(AG-hF]NBb q > ! 1pXBi!!"$+&()+<-%/023&43#43'2#m|   H R  'S 4 hfQ|39 [Iv){{rG\c){6R GbNoMk :[$Ak"Ch1Z~esfk/ eES= y7U ' u LQ4QKi!R#6%&(L*L,-/A1;33043Q4a3?4b[ W 8 j n MCATe~H_w?M$)7Y%BCsoG|[Gqy*;9Q@W7S%Ct )Vr.Nv=^n9go_A{L,ubv" n - `ej d"#%v'`)*,}.w013343K4-3 5!c9  rzz888wl~f^,EWw.$0q-[S 7gGv"LsAl3Y}:^3X{DaG^2@[R=|O)fJPh) x V + %Y o4cJh(Bl>[xE2X{+}$gFS1ufz) s :  4|0= "4$%')1+-.02333333330a: v  i o w~4$z1Y[Al8>hfH _*d0UHs&X}/\,U}Ck*Mq)Io:V~FO eYAP,gHQf0 ~ b 2 $ (:u=&g!0#$&H(+*+-I/%123z33k33O3333se - 2Pj5: HvUajEx->(ElߠY84Tj *h9r=r5d&Or2Q{ )Rm3^{b$MG8y F`931i (  ~ u`jhm67l "#g%<'(*h,K./133d33Q33/33245! b H>ZCk K(o/XQft) \+E\# 'N-DM TfYpXsMf8Q/`z4Nx;SSxK` .}.p@{W)jg m0 l F  S8*N!"i$&')k+-.t0M2>33R33@33 3324'H?B ] )e` h91T{ "a B8Xo KC<F0gq,`Kx0b6d3])Nv6\<_~ -Tt;b1ioc=~T#aNGr% [ H $!-0\ pMb!C#%&(4* ,-/12\3x3R3y3D3}30332$4- oj z N D .]33O\!3Igh&`v:;1JTVgXmPf=V :pGb0YqL5U 8`UBM#a;48t 4  w=`g :"#%n'%)*,r.013e3H3]3B3Z3<3U363F3c30bX  ] 4+J_jg y(8:,cKvCn&;Fc$&|1E8R5U/K};jLh%?g5Ntd<|:?6y K|$W)lko6 u N  )scUy9!"$8&()+1-/0c2$3Z3$3[33a33l3232Y3X 2 e eRf'v{oL "%=RhzBW'U}h)K9aDkBf 2W!Go&Im>f/NkN {%z)j C}T%\ OHu* e T 16(@Ey)z !p#C%&([*?,-/2123H33K32R32d323a2E4."V  ma@"T0l_':n$V<dbbSqV$&.:3E+C|8h Oj*GsDa %Dzm: ShdFxOYC(Cm D   iv }0 |"$%'h)*,t.Q0133;32=32B32Q32{3R2O4'  ` aw  "Rih3jb0>[`oogQ> bjfw'i{ #\xLa.Fz%Om =b~+]LN?xL S-rh}6 Q ( Q. X!#${&4()+u-"/0Y23232323232#3236-NS *]J " V6*W`M.z)o =2gUvzVVRu 1f=nB9Q\FF "#f% '(*\,-/R1223232323222220^ -a!y.!p]2ghv(W7UbM۵{Q>VZ YcNc@X*Fx #Sj$@k 5QxQ(\nb@wKQ5&:l =  #t/ E "2$%'v)+,.T01222222222232)3=243 "BNQKPW"9QHn  83_UvUYChn,-0B3J+C{8j"Mn,JnD` )Pj'.j&NQ3sH|G%h\ t% I +   !\7(g!'#$&:(*+-"/0C222222222222c2'323$i  aX_3{X;EUvjAt1<#qnpv+K7Z2Y/O}?g!Il'Dm>\~ywIo#:+gDz DxX:Hg/ u S J5DJpc27j "#a%0'(*L,./n12222222222}22b2223*3 [&|5';V_JX'N(jMjDtR"ZqY r}5u4m +_zHd&Et"Ii1Ywo6gr_;s={L+sx.h 3  .}81T "O$&'z)2+,.O0122222222222222~22/I ^ )>iZ(r*(%FPjs 2(Fl`UKEPfRjKf ;Y"Dl#Ln!Cd2Qr>R_<w5SN/l =r=x`Rm w @ *  )gF';z!:#$&L(!*+-%/0/2222|22t22j22_22P22622 2U2S PQ|3]U K.!Nc+Q8}_&f>޶ Kn Sy%SvLq<_ Cj!Ge8]&Egd1x+8$e;m=lI49^$ n R E4DMr j=Ax "#u%6'(*[, ./k1g22x22q22h22^22R22A22221`3$ Z)tdJ5sbV;(gDl[ރD7BN>P1H4iJg#>j6T{P,$xBi sU3k/iCzbq!b %  @~<2X!"^$&'|)E+,.B01m2y2e2w2]2v2T2t2J2t2>2w2.22221H3?* PV*o} sY`cIhF:laڀs#k/m0`'Vw>^?h:] )Nii{oN'>UJ*f.a5m LI[ i C    8aZ>W!:#$&h(*+-=/0*2]2c2R2`2J2\2E2Z2?2W272U2-2T22]212.! (6fJlb;nku?6cYo c}vbyhbSxu#0v"7v3k "Zt >Z9f8S|Ha}= 0:!Z0l.\=!|2U j H E8IOvyJU "#%H'(*\,(./e1:2Y2>2U262R2.2O2%2O22O22R22W21k211b9 wyRpKHO*h2e:i&CTG>MڨmaHX_Rj G^4J}3b} >V,Tn6`3We;O o&uS0g+]7tYo` # KOCj!!"{$&')Y+,.?0122G2(2F2 2D22B22A22D21I21V21z2q12$ }3uEv0) :*pR} 9)[Q|v"Tw"(=}(Jy!Gt>g)Ru 0Ux +Tu$Bc (g@GYH$_)V)_;=N b <   :mbMf!M#%&k(*+-:/02%2+22(22%22 2 2222121#21=212*.mrka>5RWvA p$#y35=3H+E}6e!Om.Nu"Kf7Ys%L67~U%T"X/soH ] G 99;Pp"vLQ 3"#%A'(*k,./E1222 22221 21 21212121 21H2.x_ tHB%F=j`,`&]l#thft Wg DX(@tLe!IblE3ܤ80R>CK7G'>z&]t;T.[u'Bl <7A0T2,r JyEv E`] v; p M < '(.GanCJ +"#%4'(*Z,-/$1111111111111111111111p12z-n2nWLv* b N - -9<k|Zc %"#}%H'(*C, ./&11111111111x11l11_11L1121112x02fZl@^[ sFd5[0?7+!2;}.62p&Zs?Z;d;X~ &Ih|}S[qc %1*Tf/tO[ E"#%3')*a,-/01j11d11]11U11L11A11311!111102D0*36y-b* %EG[ky"L z26ܕ Z@FA/6z#am=N&Xq*@j2Hw7y!&tFwEp3hF1?p8  Wjg2!"$4&')D+,.%0U1z1y1r1u1l1q1g1m1b1h1Z1d1S1`1K1`1?1e1)1}10>2()h$Wy %+AM\m 6$'Cu;e(Ss 9Y7[} 1PwAa > JslaG-Nnl J!M=pI#k&5 T 9  !]&% !o#2%&(**+-8/01[11T11L1|1F1{1=1z131z1&1|111110100 .X,l7DReo&f~ڳޏ`J@17'gtEY 4g|5NF[{[\_ S$U&TB#i_?  p N RG`lQ& e""$%')*s,../"1`1t1V1r1O1p1E1n1=1n131p1'1s11{10101A03-/xj/R.sJjFMחG߈;',v%\sC] j*7Z|"Jr5_Bi!CiAa 0Yq:^Ki=|8C6q9i5[ VE:] } O 6    +[}h@Cr !#R%'(p*,-@/0S1j1J1h1A1g1:1f111e1&1f11i11r10101`017W"0\j_0 S$rC[qEglRٟZ;)'i|Jg/L{ (Rq%Ch7W|="92)`92vMCk 6h;.2l)  p9[Xu!"L$ &'m)+,L./1o1F1h1?1e161b1/1a1'1a11d1 1k10101I02 ^|oe*Wc28SOwl,f$3 zd Z^>J-bt 9PNg5`tG1yW&p#3}W'VFv B$q|8 U +  Fycv ![#$&U( *+_-.|0L1[1O1W1I1R1B1N1<1K161I1/1D1'1A11>11(1l1,l0Q @roa"A<_U|qkݝngIj 2Y:b@e:] /Ou<[~!!Kn*z_;m&U!U`k|L ` [ ATPwYt z( c"#%B')*e,-/0s181l121j1+1i1"1i11i11o10y10101-0r2q"~- TsE87[KbtxOؔ߂߾0xj YZ7AVe-PDZ%yeIcs&n DxEs.]3kQ b^ ) A7*_!"$J&()X+,.0A1M1\1E1X1>1U171S101Q1&1Q11T11b101v02$&Tob|]?I *v3orz$ @)_C}[shPm܏޺s߷^a;O/by =T*Up">b|)Dev>do S)ZBq =uJOg, f = 1 " CW`14[ "#X%&(K*,-@/0g1C1d1?1_171[101Y1(1X11Y11Y11`10l10/K1C}LP<~f*:FX^yviD^Ayr߆ߘ0e|Gc+EqJc4_z'Ei 0O#n\: Z eb6o 9cMz[:PxJ YYKh!"a$%'I)+,T./'1J1f1>1f171d1-1c1!1e11j11t10101)02J]PJr nzRf~=Z!x7FI(C~[ڼc:ߎu_j;Q-]z4Qz Id,Jjj{j1] bL Nx:f,bB8S o C $ 3Y/q !]#$&P(*+S-.r0J1^1Q1Z1K1W1E1T1>1Q161N1,1O11V11u10G2'uX{35t[NL2GKQ\c 4"W5BG%Di%OߋnaY6< S\1cs+?n/Eo)^x{iS(D_O.c#L{;i:"|%R n V LGRc5\\ "#]%'(e*+-4/0d1f1_1d1Z1_1T1[1N1V1H1P1C1K1A1@1I111-+b1ZL> .SQ[sw4&T?oWfU׸4vk߽ߺNS!2hx 9P N_)Tk+Vv1uf%[SC{=k3\G.{v:l D Gs!"]$#&'y)*,;./11N11G11?1~1511(11110101h023|L=X^)\bA VAaYp+;>]PZ?&llMؙ܎;J߅ߒ(_q5J} !Oh5]y&:c}(>/\v{hV,IgP0a Mr6g4tqH { R ? 01.J`[#8 !u#&%&u( *+V-.p0r1c1~1\1z1U1w1L1v1B1y141~11101}02!e(]UL-+OH:bHd #B _$|3.U 9ާF2߅߂Ze/ApBV %Ld+SlH4n,aXDDj /ZJ'no+d 5   VcPd "1$%}'.)*{, ./01i11d1|1_1x1X1t1P1r1H1r1=1q131h1b1-Nj2y]'.^:^^k; T7tJa׎ަ88|߁߿M_9d/Mv<\}=\}4e{rU4PhR0d#Ks 7f,onz@ o ? 0 4?w*|!6#$w&=()+-.,0r1k11`11X11M11@11.111102X02)T2}A`FZ4bJ`2P+lBG'2'K(sLު޾Bfߌ߰>_5Wx#Dh ,Kn +Ko*7k6chGzIt/X}Jgp^ 8u. N"#%H'(*(,-Y/011{11r11k11b11X11G11(11024&8-B]E9 8+TFXk|v8]*z::ݬnުVFߚߔ"&jq6Av@RBX[q^11"11 1 0O' 9f,3TA[\yt.2KFhZs//ۖݮlޮJFߐߓ _j+:l~6Ct 9Ky 4Eo#M " zIn&|O,U0`*X!jwd  ._  %"#a%+'(x*+-$/0{11}11t11h11Z11I11.1102n0@3i8CPH MC\S|k**D@gMS,00sSR7iޞޕ $doߨ߶0?w?UG\H_@VZsU"o/t Hz=eGq B} o= b ?  (O _44W!"$7&')$+,b./A111111111111x11c111w2(7`Bs1'M?I ^ E  (9zC.!"f$&'k)*,,./1111111111r11Z11*1/20i3/75:BWY _AlTk1 J#e7DF DڀQBvsެ޸3Duߋ߼@Y Ee'Ib!B];67FJ=(m,F8yGo .T{<g>'3i + y GWK` !#.%&v(*+\-.w0111111111111111u102+^){mA;/fOrj} !6V*o5N f C  -a$mt "'$%g')*^,-/01111111111111111- L}YHAmir 'F,]FuR\aM!I@h2ޜ} WNߔߔRY MWBQ3Cl,bMc|olN8[kg6a .T{(L!_4Hh > xn6i  !;#$x&>()+,.011 21 212121 2172Z1w20=3P:C &"u7r'|`m 1(L<_XsjhV!gd#DSނޓ޽>_߁ߠ"@`~9^{5Sn B^6|Cs'w_'W<\FrPE_ u D (  0U"sNS r"$%]'(*2,-^/01 21 212121 2121A281L31%}&$~oM`0}:jpr " =U6jIW`b2R8ٺ.:&sjޫް-5hwߨ߹*:hw#6^r(Ng;h@;qnQ"u(9T}Cm@k7oJX| H v1m$ !;#$r&)()l+,.0122121212121!21+21/ 8e @]pAm4I)d<~L_opl-hEwe޲ޫ.1jrߩ߱!3`r/Tk "Ca-e "-%d A5Fm -Vw(V*mT y! O = =S,rCD d"$%Y'(*,-?/01921621921>21I21a21203RM:1TCv.!B7VNjbw0*O׍a 16lxާ޹(:ezߠ߸!6_s1Ri?Vv\`(nsGKQ,Q?kPcoyrHC20 `QޚޔQUߎߖ EN| 5Do3Vl2CVVmev֝7iMޤގSRߐߓ DM1=jz*UdfRm-om^&Lr4X/Y8v7 c : )6| !>#$w&')3+,d.0^1[2"2c22d2 2g21q21212#13j-P|eDi]'";8LNair{Yݛטt 5Hqބޮ-Cg}ߤ߼3Vq !F\ ,Fe~gEjy~s_=i$3{S9g>g'T63U   X <,#$2Np*UQ m"$%<'(z*,-E/0 2V2O2L2M2F2J2=2H232L22b213)8~YaEh}1#F5_EqYhy+^'f[A$R9ދ|޿::w|߭ߵ&.`k JW*;gq?Y!;@Es 0Pw JzY7P | Q  <B" !D#$y&')7+,g.0g1p2D2y2:2x2.2z2 22 221211 zChw1Qqv 1D)[?mReu6MHއފ4Dq߁ߩ߼6\q>Zx!=Xv 3Hxh> JW@w7b:]<pVCr & e W8=/LU-ea |"#%*'(e*$,-S/0&2Y22L22>22.222212Z1!48W'!c{  0D2XFmWl} ׸v#<\tޙ޲)Lf߄ߠ߿7Po7To4Pjq6=8* Bd]5l(HmDn4m Yb a 4  T> !7#$h& ()F+,w./z1j2}2x2w2r2t2k2p2b2q2T2~223R+Vn@eU &?-TAfQ|fuEשKݭ>%vcެަVZߏߘ:Hs-Ug4Fqi7r_0hs\,Z{2Vv(U*r[ 6 u dEO9WY/fa |"#%'(U*,-N/0.2r22d22W22F22/222212CW(Adz ,":;OM]cryݳ 8(qfެަTWߊߔ 9Bq|&M\)8>N]j\Q+`$.u!Y?a>`E&rr6 k I _2 !#$J&()C+,u./1a22y22n22^22G222 31?4+!,}w*,=@JY`es} 9H(ط~ݲOTވޑ2;izߥ߳&O_(9}Mx -Kq"AtC"s) M  qWWI[j5\S e"#%'(V*,-//022222222222~222-Uc>?Ko.3DCXSmg}u$SJݕ* `Iޔކ=9qr߫߭ RT'1^k|$NV8GQD<_C_3c I*Q b ( 'r@ !##$Q&()I+,./1n222222q22X22*25313YGLk`!):!M5^KnZq Bݽ&Veވޟ2Fh߁ߤ߻+Fd 9VrVhI,*|>e][NoQv7,:*O8aKs^o(Fd>|S"dݎMBނ~޷޳!(V]ߊߕ/GKX^kl| 6T~tٿۉ݊ݹ:.mhޠޟ >Er|ߨ߲FTx"EXxzP?`l[1I[FFs(C] 9b<}u0 ^ 3 v"t` l"$%D'(z*+-/02323232 32)32<32J1% 4<[0 &/G:QTbbox %:[y/5M2X{ݯC)qaޤޙBAvvߧߩBKy@Ju 1z|8nc M{ .Su &MjS;& S  v E= -/k uB6 !J#$r&')+,B.0I122132632A32X32314[U >N:6!='Z;dQr_q" .68Q!8g7ݭݫ/Fdޙް5Og߄ߜ߷6Pi4Qg2k~U+n"%i :m"@az .SO7B y B  4vo y"$%/'(_*+-(/0&2 3 333 333"32:323$*9TE~?0YK@'=>5ZM``tl'; Ts ۇ݄ݱ* ]Zސގ(/V_ߍߖ߽%0Uc-Sk(rY 2OD@# e/<3m/Wx.Mi:rVB m " aS/6%AH}OA !T#${&')!+,J.0R123E33I32O32_32322 *${ +IX6];uNds"7 Lax #;btܵ݃ݰ.%[Xގސ&2Xeߋߙ#1Sf,LT%nVLM.cDa~*Us2jXX  U 7 K{! "#%&'(P*,{-;/0=23]33_33f32|323424# Z^g0bTF]KwYt *?/L<h=#)ޒSݞݚݽ%8Vjދޙ޸ 6Qi߄ߙߵ/Ia|&_F0"OnyvjW.Pf X(Sx)Jg~5a/ld B  y`ODBMa2M> !J#$n&()7+,_./j12M3B3G3?3C383@3*3L323,=,X>-TD9iSki{q$1NX*t(#`.$ۉsݡ LD|wެު =Gqvߠߪ1Acs,[~Ft rPEc3Sp"Q1wt ; p P e1 " $%-'(Y*,-H/0L23}3)3333332323 %Ng4s[uiy" 4,H6[DnKP_H}+׋vܵrݝ%SHބzޱުCDqvߡߧ 3:fkhwi^~V3o0-vOz)Gf8\F1* _  qmR`\OS= !K#$i&()N+,y./123?331333323v25@"D^Atc H|?rmxq #+38DE[Lj\W1 'a݆ݟݪ.<\oޑޟ"3Pd߁ߕ߲'CXrZF -@E<)r+M>w>e5UqCsM7 Q c 5=vL!"$%E'(s*,-D/0B2?33b3}3\3y3U3s3T3Z33.%\S/:(Fd].B&T6e>{HK>0dێdݒC2thޣޘ..]]߉ߐ߼"GOzCW_\TBy.Kl%A_ 1dWF  4  k}vkeN !U#%s&1()_+,./123S33D33,33342n4Lbh2} PGKhLy" 0<'P3_DkOZhn7׶ژܡwݽݢ?Altޛޢ'8Xe߅ߕ߲!=Rl+IfzysW2 [wfZv$Em*g] m - } Y. +^ q=1!"F$%h'(* ,-4/0/2v3z33i33U332332 5$~X'qEfc#0&C0R@bMoWbjj5B؂+~ݠݤ"/ScޅޑޯNOY^bqq{TGڡܙhݷݙ2,Z[ފދ޳޽=Hlpߖߣ'JWwH8.9H=1{8ZF#Vy%B^y.L~ G: 8 { :  M/ !# %&/()Y+ -|.*013333333k3435L'#oNfr&b "50?:QHZWo_|mv|H\_؏:hݡݏݻIKuzޟި$0R^~߉߬߻/>ZlJ&Pc/gnPA`.Kd<hL@ j  dU8<.NX5hY!"f$%'(*%,-C/0>23333333z33w31 \L;W;5x $"05<<RG]Uo^}mqX^3 ܏Nݼ~ݱ*RB}oުޠ)'WW߃߃߯߯ -2Za|9jj~jc6e%$qP|+Dc}6Wv*_X V  W 7m:  "#%&3()Y+!-x.A01/3333 434U3^42[5pTGilOyI! 0:-D9UBcSo`|ky&Ifں܉qݦݞ'GWtހޞ޲ !5L_yߍߡ߷ &9P|r@ ]B9t;f2Ke7Z(k _  | @  lVQU^{ To^!"i$%')*G,-i/0j23333333 4c34=*1,X?D %0(>5MAZQeYwdr| YnN*۠آC^ݞ݅ݳ>v.Lm!5Tz#L1v s < v X"&>\/ %"#0%&P(*v+--.T01>33 434343:4p32 u#6EyB/ %2>!I,V;^GpR|`ix~ (܇Pݭ}ݮ ?;jfޓޓ޼9?bpߍߖ߲ 24$&BKE0Kl`8d:Qp9]C0 + b " ~f{u{+{ f!#o$&'H)*n,-/023+43143D43435-\swb $0#;1E=WJ]Zggxo:ZB܃hݛݒ?Egpޒޙ޹ 6@\n߉ߘ߲߿M&El;s'{\)Ov6RlDkA6 N f? ,UrD 8"#F%&f()+-.901#344 43 43434,i4uA, !($:2G=OL]Un_zmu 7mئDMݗuݱݡ(#OPx|ޡޣ(FMkwߗߢ߽rY7Wqvn]@p):#Z8Wt"9W{._M C  } 9 ~.> r!#}$-&'P)*w,-/023D43H43Y434\34#p7k.SJ  ) 6.?:JISW`birr'6)܀;ݫkݙ -XL~uާޡJKsrߛߝTY[* n)UC$V|#7Tq#Ck^ [ e . {c5/4A})h Z"#o%&()+-.2013943O43_434<35Q"mPMwqH4#& 11)@2KAXM^[lfyp~`N"lh݉ݐݭݹ #4J`sއޙެ'9ebގވ޳޲((NVxyߝߤ_b2E61Lxe GsAYp#C`As&u  } H {IB#1%IP:w k"#y%&()+-.5013R44n43434\3 5k6 _p ;97L#T9[?lNqWdmy,>P;v>ݚlݱݕC@dgދގޱ޷'0MYt{ߖߣ߻wu1ws={/)m7^| *DZr#Hr9~+ 4 | ? &kT( !#$,&'G)*j,./31|23+4d44s43435%c-wv_.; B//9+J<OI]Pf_si|t3o6df}݆ݡݬ"9G[pޅޕެ 1EXi{ߎߤ߈iR/YqyteH$|:E0l&Hd'@]{1c? 5 a  o^GGF^v\ }"#%'(%*+F-.\01E3O4=4c424b4)4X4Y40v&Am86P/H=XDdLm]vdq{-Doy;M8݊]ݦ݇ݱ2-RRywޞޡ2:Xb{߅ߥHQ'oo3[V.^0Le~)Fm)^O P  [= +>-j= !2#$>&'[)+x,E./Z124.444434r356S5% 2WP>RDbOiZrf|v!5> ׌Hw8ݓ\ݩ݉ݱ3(WO{uޟޟ 16XZ|~߯,30q{L%^v T+Pp,HZz .ZY ]  y E pj^qt+;!"$%,'(N*+p-.01y3;44B44%4435~(>m(d-CXRMe^glqs~2OLHI_b~݊ݨݮ6E\gހގަ޵3BXh߈4f6FD7 Y.yP4Pl.FfA|#i m 2 xV%C`@[ !S#$[&(v))+,K./[12 4[44J44744C42g sci&]T1hU]bpdww~*>UyJ/~N݃Cݗlݹݛ >._Vށ|ޫޢ33WYxz4ivP A4tJu-Jct.Rz:v( }  b s>\8!":$%J'(p*+-.013944;444535Q )rJ(F}-o\nX_s| !19DF52צYY/sS݌{ݫݨ7:Xa{ރޞު+:NicM0]o|kM-ESCx4Zu2Kj8h= / K nO,3OO !x#$&()$+,D./Q1244l44V4445(* MP'HMbnuix  /?VtIW1XPutݘݕݺݼ 'GLdkފޑޫ޳8J9Gt<laAr"?Wr4Ku(]L E  A<exY!"U$%h'(*+- /023`44f44O44@43 n6e9LpIjuy .: A [q2ؿLx>݉fݦݐݳ'"IDkgފގޫޫ3߈߮%/>na-u'%m6\ &CRq9c^ Y e 5 wGH)>6bn0g& "# %&()2+,N.0P1344X44/4#536ORc # vCgU~{    (+01=6H<9{ZhN(hI݁rݞݒݾݹ @C^dނކޣީ Gi!EJRB-n'B,]%Hb|8Kj"Lb g  b/ G,e!"]$%o')*!,->/0C2344444E45 ,-CUcZHcyv #/9JUn'܂bS>maݍ݄ݬݦ )2JQmuދޕޭ޴ߟmn+sV!MI'Y)D^p8T| =v% v  M a]DXO{G~@ !"#%&/()E+-`.0e1344v44X45%434S7ILfco  %);G"U%b$)IJn*~Rݚxݸݙݽ3$OGofޑތްޫPNTD9W}}ma/MjJ$Mn '6QjAo5z / 3 H/<[S n!#i$&s'%)*E,-d/0l23445X4653?6 l%t%]s & .(9.>;FBPKR_9|/$ODdi݄݆ݟݪݿ )@M`mހފޝީ޽4Eq L u!oL| 0Nh} !5St,Y< > d &thksZb F"#C%&T()r+-.01 3S444444Y5 .8)|Ghd %-5!F&M,Z,p(  gI \?vcݔ݅ݲݩ,&JKkjފމޥާ\ߎ!'+n^5t5*nCl0AXo<bQ L S  fJWvl2 ! #$%&'=)*],-x/023445u455244&o51mW|y, 0=E!P&Z.e0v*%,K[;w_ݑ}ݮݢ" BEab|ރޜޣ޸t Z 9ONF) q2H4n.Rp#8TlPxT  \  y J }7g  n"#n%&()+,. 0124454F54Q6#+(#w"/%/1<4B>KFSK]OjTx1 v0+IMfi݄ݍݠݧݽ#5BT`sޏޜ޽w`al[#RP1a8Ngx7Sz 7p a u 2 ]5#%>iy> !*#$/&'C)*[,-q/0r234444415/AZf1i }  ! .1 ;$G*N-Y5c6s76&f4E&_Iymݕ݉ݰݩ $'@D]a|ނޖ8L6OezxlU5S dQ$Km(@Tk;e&g  v  `Ho "#}%&()+,. 01244254e5&45(]t  $*(3):2C7M>X?eEpG}DB25#;M b@}cݙ݁ݰݢݼ!>5UQur޼ޚ3 UxPp*zJ{8Um4Jh$T& q ' ? eO,,+-Wn6x= !*#$(&'5)*K,-[/1X234%54I5S4<6'dVn%@   +%.465?D@ILOQ[Wb\jbt_8q)6JSdt~ݎݛݩݻ /:EVg~%rvZ[/{23tCj1F[n5VH 3 5 ;^9!"#%&( *+!-.10134454542 W&Gjem'   ,!5,70E4I?OAbEeLrJ}MG4 d+;Q1iS݃oݘ݊ݷݧ "?:VUh{O 6E@NINN[Sd\g]qdxhid9Bv*1DN`ky݇ݗݠݱݹ $8J$=,HkuylW2WsZ0Rw5CZm<_ c ` } IlhZlnw- "e#$_&(r)+,5./F12.44A54J54:3 J8A~dqK  # $,98*A)L0N9V?_>gGkNsNRUWK@e|4l%="R9iX݀uݗݒݲݩ.xޔ ^N*{W@Zo $4Qg!O e  | ( J5&d[!"M$%W'(g*+-.013r4l545M4j6VXiSz :2 #%(-*728<=?GHIPOVQaZb\o^uf{mmmq|\ܽ 3J9`Ruiݎ݇ݩݣݺ ?rxRd32:Fl%=Oc|/Or@  t ( [&w{x?5 "#$&()+,1./012 4%55S5467,6=KY=  &!%'0+2597B?FDOHUM]T`Xg]mewg}jolb,"Rt%,@CW\ry݌ݏݠݧݹ ފOa9':C: s3N9x9[v(<Qf~<g3 ~ 4 A eL   1:}0v!"a$%c'(v*+-.0134j54~54<4{auQ}W #%,-,424<8BBDFPFYLZScRnXt`vbcea]J^`ܞ !4K0^Nud݋}ݥݙݾݲ?2߽:B^W.Wf6e(EXs.Cf.b 8 K oFfF "#%&()"+,2./2124a545o46m!rXN;-% '(42&<'B1B4M;OATE[M`OhWk\ubvejrsy{kܯ) ;4SOhi݂݁ݙݙݮݰݾ1Agsyl]3\xb4]z3G]m4TW M f %hN7&&3Jia !"v$%x')*,-$/0*23445Q545-pJ=o}V- "$)$-*5177@:EBCIQGXOYV`Wg^laudwmlsqtt^*.Cxܧܿ' =8RPkg݀ݘݘݮݮP~JW~4W"@cu $3Hc~F{ Q f  c%0 e 9"#)%&,()<+,K. 0O1 34i54544G~u1+$576"@%A2G.O7R>X?^FbIhPpTuUza~``gjkjaS%2 |؃d܋ܧ&;-SFe[{xݓ݌ݧݦݼ]|eTzb:$"$45(7/92@7E@HENHTOSV\T_a`djhluosxy{~~v۹ܗܲ(%C?VUim݆݀ݖݝkOZ7#>?<' u;NDz9[y.@Ni/[* o  x . rC#T1 ^"#N%&V()k+,w.0|12Y4?5U5355/w{8 9(+5&82;3A7G<MBOGTJ[MaTbVj\mbtb{h~lpqtsxp_9b^g܁ܺܚܵ+%<;TOhl݂݀ݕ)ߤ>=L_%] ]>l!AXp+D]!T % x 1 Q%^gUqn 8\ !9#$2&'<)*T,-k/0u2z3355545E^(T2 ~,: <%1*;*>2@:F>EGLGPOUSW[]`\idjfokvmytnv|vxyp^<(ؑS۬g܀ܠܸ&<.PDeYyoݵ݅$e;MndgG5] kb'Po 8IXm#>o G ( H ],+o6 ~"#o%&u()+,./124 5546L'o|7|B\Q047+D3?9E:K@OGOMVM[S_YeZhahjqgup{r|uxybےxܢ܍ܳܪܽ&):?NQcqXzp4zNx'~W;Xq+AXw 3b ; D d7zylOf !D#$;&'F)*U,-e/0j235Q5q551 RXK8H76;G<BFKHIQQNSVV^[^adbl`qmknzn|qu{}z{z`$2fmWdܤ|ܯܑܦܹ.&C;TMݶݼHfO4k~r\',;Fk$;N_s6Y$_ ? c zF3  ;KM!"#%&()+,./124554;6*_:5[Q6H3Y6U@XB_EbLbPgQkYoYw]uf|ajmosuxzz{xviMnקSېSܨlܱ܇ܻܛܳ%93JgHޠ>M%q*8)"t/Q?s9Yt!:IZv!Hx X Y I+xr !R#$A&'J)*T,-\/1Q234546)SqL{:(a0:JF?QFMLTPSS[Y^Vd`acgikgrossrx|t}w1fqc܅{ܓ܎ܟܤܳܶ%)>ߑ#$9tSQX9g!=Oiy#7Wt<u  ^  y ,`K*&',Vq0s4!"$%'(*+-.'0134D55i52 4j$$VO&c=MH\@ZM`KdUgTh\l]r`rcxhzlimysxx{{||saeڜH<܈Y܏qܞ܂ܭܘܻܮ%fߋ h*R]k\L)Tr]-Vr/@Ub{:c4 v  n - ]9(FD "c#%U&'X)+^,".c/31P2.44546=(?_ ]Ji)XOOI_K[S_Vd[c`ecihkkonqspyw|wy~uj׸Cq.܉H܎aܛvܨ܋ܷܠܲ 0Vtp3j= z$t [5Ogz,ATq!O , y $ L \H397Ne@Z!"@$%8'(B*+M-.]01W345!5`6 ,go7#2pFAaSP^XW^aZbbafgfmkkrnovws}yx~g^MJ[Yfjy}܆܏ܝܢܭܰܺsݧ1M;*[ymN s&4wCi2EYc{,KrH ' ~ ? sL7\P "v#%c&(h)+p,(.u/41g2%44515_4GO$@)/G/ba;gV[TgVbbd^jcimkkskpxrwx{wz}}}g!Dڒظ.m5rE\܍nܚ܁ܨܕܵܤܵ)ޑ%e%^)=ZOob]jifkjklpqqstvzwv|{^ ߊHڱ+5;>BLP^clo|܀܊ܐܚܠܪܱܾ/NeoC6PPI4JaS!Gl%6FVp %Fy W G  ~0}bka:o !"s$%o'(x*+-.013|45"515o}4\X@h@w`m[x\y`ze|hhqkuutyw{}|q` ٫رI K"S6aInY{j܈xܒ܇ܤܞܱ$IH _i;lo Ix0F`o -B[| 4g  X _ #kK  9Y5x :"#%&()+,./123556%{.?ZVinmeuitoqryswwz|zx~6^׭2>>H+U@dKj]}m܇}ܗ܌ܭ<ݓ.@mvqd;h&(l>c &5EZf~>a' i b  Kyz~F; !#$%v'(*+-/02w34550 Wr4: &LQrW~nrn{nuuzr|v{zy{|I-dޚ>ڤ'(67CEPU_aip{}܆r HZ6,f%E^t 5E[tK~ ( p  r :d2(  VpS !T"#/%&%()'+,,./"133555&%/c8yCuQsrok}uyw}yy~w`(ټؚ)-1 ;G)P:^IjZxhܣa[wWTsbEIE+]#9KZo|  =Uy; x $  % f&'Za !0#$&~')*",-4/0;2U3'5!56( t;jJ_^sxmp|{tx{z{>פ '7"?0L>ULea(޾FQ)=;;"wBTLTlHx  Z  j j: 4hF "p#$Z&'W)*U,-U/0E234X6-jei; NifpzW גڰۅ۹ە۾ۢ۰۽^uߌ'!*pwSWQ4g,@Sgk~!5Sy4 o  n  P rp^qng Z!"0$%'(*+-.0124J5l4,?s/lxgtvc#-۷_v۩ۂ۬ێ۲ۚ۹ۣۿ۰۶ bXBLZLBI k Q&Lj%4@Tf6Z & n   .M0Syi +"# %j&(a)+_, .N/1,2446#VLp  + fuyukU-QڒSۮhۧu۫ۃ۰ێ۴ۙۻۥ۬rܩKh`#]s0qjL|(=Vht/I^C * z - ^!~ry)t v!"N$%='(:*+=-.:01/3e464/zY"of'\qu~wx{_ۈmۉxۍۂۑۈۘېۢ۟ۨۧ۳ݏ-C(Ec{yu^@f{(l 6]|-8HUfy!Bm 7 - C_B!2k{ A"#%|&(p)+l,&.d/'1=2!44?53!5"5h osyyiU F۳:G~U|aۃiۉuۋ}ۓۄۚی۠۷۔ݍS W6-a!BXk~.:Wq*\ 9 = l<K) !"v$%c'(`*+m-.w01|3%4}6&"zt(j|~pljR+Xױ,i%7{EyOہ_ۄgۊnۏ{ۘWvgB|{i05BKk4@L_gx1Oz J = UwS2!4N{2 O"#-%&() +,$./1w23g5X1b 'kkU@wMP|d\٢I3V`& _  K k"aO2-%9FjU!a"#<%&/())+,$./123 6)v( O x~{}vrqg_P7%H׵@KGGH(L.N4R?܃s$SXiTP"Lp W,Jk".>K\s'O}  X  c `$ /uQ !#$%'(*+-.01t34c2m=||xsLBي !!(',01f\`p*stAr#tGu -EXju"8Pm 8 r [  }3raCF5NXn!m"#H%&5(),+,"./1235U!QdQw{}{vurpieaO<ٯד$"%# ݿEV>-P}}nB%k*(k yV%,q+ !f#$M&'F)*I,-S/m0i23h5;!ea1pPHw~vysoljc]ZF+Ve٭oګڴ{QvvB*KIM*}?NE 2Pez-8E`t*V 6 2 ^#skosPJ!"$%'()+,./124,>Txm>y7}~ywpnnhd~eYUGE ֖ڜڨڭڳڸھ-,ܿC[Mc_-\c4d2FRcly3Rw M 1 Sn5"0D F !#$d&'^)*`,-c/0f2p3W3%B-|~}}y}zzt{ryo{kvkvd|^vZC TڣڳڪڶڭڹڬڹڲڹڴڶڬݦAQ3GbxwpW;aqa&Lg{ )0=N]r9g  J E y9$r _!"0$%'(*+,./125Y#b}88N<'}}zuqsqjhd_[YLH6"qA~ؾU٣qڽچڶڌڶڍڮڎڱڠCgދ--DzPw-|Hy 0FTjm~ ,Ed$ _ I _{Q4 "=`f %"#$t&'d)*e,-X/0.2 4B.PLy{zzrq{m|kxhxev`r^sZoUrPuHoFgO=Nւشٟhڣrښtڛ{ڕzڔڃڗMv^Jn|R/u++r;_y'6@JXj~$Gv  W T I9, v!"@$%''(*+ -./123KRO'(~|}uv}txpiwkufxbrbm^mUqRkMr@}./ݾ)jڀsr~n}rt}ڏV۬Cbc.}'.'g%@,a9Sdo{(=Wq, h [ k,d=0 7Jz# ="#%s&(e)+Z, .A/ 114i&;D~tv~v}j~nxjzcvbvZs[sRqRqGt?t;y(:Rا)o4ڋ>~HyJsQpPs܈5߯O=2yjK IB%Os!2@JTbt-V ! c  c X+K7 !"X$%<'(/*+,-.$01D3/p g2vUee |~|y{uxtsoslrhnenam]g_bThU_R`GdG[C\9NRW`؍j4o:d:]A\G\Cڏmq' [$7TMO/zBRF{,KYo$+<Le : t  i u@{KD*6+Q\6 W"#3%&$(n)#+a,,.J/?123!(9u ~}{w~suwsorlokkfkbeafYfU_VcJ]J]Ba=]2ghܣֲ'J+F1E/@/=+LJkn%bf&^Y4c #3DMXgm !Ch / k  p "i1 'cA !#t$%a'(V*+U-.i0i13 )p;c)}~vwr}l{lugv_r^sYi[kQiMdKgBd?c9e1h'jsI׏7O?< 4 0ڒږ3ݰYd@O^}mpP;]gZ9\l}'18K]sK - x QcWCJFdvU q"#I%&:()2+,0.}/)120qr= 1Tx{{u{nxntjpjldk\k\dXaV]O\NWKTGVAMAN7M5D6,[-?k(,!2"ۃޫDB XLv%rHs#6GU`lu 6Pu @  , 7G& >V !#$%'(*+-.0a13>t\ ~{vspzsxftimel]n\hVdReO`H\IWDV>V5U0X%W _wۗ֌ ٦sޝyJzsV'u&*m-Rj#16GVe~ -\ 6 2 \}eYV`s$p!y"#P%&;(),+, ./0$3*S>r9|ysxuyi|hpgq_l^jZfUcPbJ`JWCY;Y:O5S(V XV au7׃ ([۹h߇~J%(;'j>$V4GWfqz *?^ M 9 FY6 5W.p !2#$&'(*+-.011Qs?=z}}wxqvomnnehhc_c[[[XVUPQMJLFIA@C@:=5854.4*'1 ] Dٻ+ܴShQ FtLG=Ji(3>ES`qFp  C H g8ste{ 7B!"$^%&@()1+,.00D3\!Kzy!\Q|z{zwsslsjkfi`g^`V`RYPWJVEQ?N<K5H1H+A%BCKOkvڕaة٦٪٫٫٧:ڏݫ(4}%MTdLBR=L6I4E+G&> =>?@FPwצ}مًٹلٯمqݘ ?ol"\O/^}%4=FR[k{-P  M R uEv%LX!"%$r% 'S()A+--.0 11]k E 2yxxuxmwgpifef[cY]XVQXIQKHDHBC<?7:53/4,(**!$" fqٙىًٞٔنُقمٚ_ڶGpvM,Sm|mZ6 Th M~9Qfw /?Ux6 i  P  g O25QE !q#$P&'B)*C,{-V/002#|HP%tI)8||ws}svnsfobnZhZbTaO[HYGOCO=J7G4>/C!@$664448@Yم.sc٣hٔgٍdكfۯ/SGp A se Bn%4DJT^ov7[ ]  b Q.cb!"1$%'y(*j+,f./1- jr^k zv}symwiren\kZcRaSZHZFRBN:I:F0A,A(8%74/,.+-1; gPx؎HٓOمNzMnهٜ۞1-SwY"s!|'g%Fbu  +0BNjC |  _  }-`I*&&'Rf'\ "#$l&'e)*g,-x/Q01q|@^{$~wwyuuoseoibafX^WZPUNNGNDD>C8>38/2,-(+ $ ` qbYcTZLPG[ \܂S)6;/a4~Sz &:MWdgr~&?e 1 s  l (a1A$ q!"8$%'(*+,./,2g&'\> J'|z{uympmoeg_e[^TXPWHQGI@F<B3B-8-7 8*+*& % $.JmXu?c%X#K"Fٌ0\pU_{@5@v 7Yn%+6?N\s%O # m  @ t]B8+;Ef@} 0"#%&'v)*n,-_/0.O ]HoV~wwupqmihi`d]ZXVPTILIGAF7@89.:(.'-*$  K7NO O A 4Zڦ@G (WUaI@1N,_8L[fow /Jo B  u 5jD/OA !#G$%#'(*+,./1hCg 'jz}{yvxmugnbe_`[\TTMRMHFIA;?;7321)*+ %!   \)]ޞՑ׸ ٨{ަ3'?\'QHFfz &26>HYe~,X / w ) K `K<9?Nj< C"#%&'i)*P,-/f1i(u+;\*~}}yxmtkneh`eY\T[LXJKFL:E8@1;,6#3 -&"      -Y9PXR?Sx{M8Pxvc](F_7m .DZeqz#6Uv G & ~ AyP=`R !#]$%7'(!*+ -.0y/J6h"?~{x~vlxmpen]h]`R]NTIQBM=D;@1=*8'/!,$ G"Kc_!}}:i\6^t%59CJYct8b  = 6 asePURq~S q"#A%&,(q)*+P,?./v1z,fI s}{ulvmndm``\`SYPRHO@I<A:<.7/-&-$   wN)`݀^ׁNكܥJ<=6?';).!.$ Cy1ֈؘؒؐغKx#(@6$)Mwe ?c-9@GP[iy>f  F < j#xnX`Wz*Z u"#L%&6(x)6+X,:.//0O7 %tw~v}zwmthkgf\_YXRPNLJDE>:;530*-&$!  '|؁؅ز{عN3bmTRvi/x"w'b;Tds|/<To T C O Z9-K] !#$%'(v*+-b.0'#2D(l>$k}}zywunmmgbb^]XURNLHDEA9:83*/)'$"  [=\(C؇ؔ؇؎|؈"ڜ;\Y//CTMH+ j%7|Lq.7INUahv *Gv  Q H v3{fom<r!"#W%&?()/+,./d, dazSXxw~}vvrskih`^`\VVOLHJBB9:98)3&)!#  p.Q׋P؟N؋Lذmr1ޠC90B8C7@13+5"(!" yw:թ֣{B|AeMBi߈Y2Nonx\J8L(U*8<.0--'   w5*v>J9?5>+6%/)!  uTYGU ?/:t/ܢW߾Z<`n{k3M`5g7EVZggv{!A\ e f Q*RW!"$e%'?()+--0-tcoS\i~wnxijffZaUXMRFGCE9<51.*'&  {l.+)ؙfݕ4/J+" ?f T)Qm$+39LSlA z  ` v/^>$!=a N !e#$A&'*)*,,Q-/V'{ )C~_twmqksn`f_YXWNNII?B6>31-.) oU ժ 2Yٺb݇jE~R#al Fv (@P]elrw +Gj * i  k [9ag!"0$u%'U(*6+,'.-0<uoo'_a~vlfl`^[\PTHJEA?>531,)"$    vmT>U״ر؟6ڕYrm9r,0P;BM~` ;]~",/=@L]t-R  h  7iT0101Wh&Z "#$g&'W)|*e,2-/e M2Rz\tuiblV`XWJSBH?B59-4&+$#}xgzhY;)׬ׯLjۄ)ީ@+1vp4x#u Z1EYcjry}!3Or 5 p  q $c- Ax n!"5$%'~()s+,.)']G+N_``r]zi_d_TYRMKHD:>911.&(   vl\I0m֔הגlۓ ߮p"U\w`_6j/0sMn)16CDO\g7` , x . F|mBF0HCtHx %"#$&'w)*w,---SP azVQzfdZhNXLT@L:D3<,5"/!  ysbXO=$Iiկդֳk׵׈׀بd܈ߔ}7g S#;9p%CVms{ $0F] I - ?zM7YB !"G$%'()+,%/JZe6IoUig`T`NPIL<E;;/7(&)!   }ywumfmb`Y\Ib Vq ׂm}(٢@ahE*]yy^3DJ'Wx 1;ALOS]j{ 8f : 7 \!x\SNXbS N"#%&'p)*C,0.(@9PCONZiOpYTRUBP?D7>11+,#  }oi~`O|Gx:v%| #1\:x~ת٫;9p(#1r=UP:Wg{ (/<Pi$ Z ; Re.[{k !,#h$&='(*+,-^U"WxwJwzHhYVNVBGA>78,.(&"  ztjvdsXnMeCd8])a[LԖtc|׀ڢ ޻ 8ZO+Uf9h$2CRX^ajsz&It  S F x1grn;i !"#W%&E(r)L+#,.4uO*;fL[\QJOB@?<22.*"# y}rthoaeYaNWCW8L,O[O-ןKx ߎK6QTR=#V o_(Ke|!'/:H\v 3 e  N ctF'!=o" !9#$&r'(_*+-(l'Fo:FEL|WI`KEKE8:8/**%! {r~iz^pUnIdCa2\(V\]qo(QeLjjLp-~Kv2BS^fjmy|3Q # b S =yzW}!"#x%&d()c+K,-Gsj9lk7aHH@I1?./$+" yrzgw]gYeJ^GP<L1I'@A 7%Sl= أ8@7fihc7g&&j 7[q#+/4BRb; k X  f'|V1(SwB !<#$ &'(*+.!^=}1Ox?IQE8?56,0"$  yymxdk]cUZKTAK7E.@ :75Cd$Ԗ՜Q_tݙ.(AY;&Z8IWgjps{#=Y ' h  ^ L"a>!"#~%&^()D+,) x(<5$>@iT4V;?5<'5 % xq~ev\kVcIa=T6N,J!C@9:>PGԻ&Su uOK`U:|@9|Ij')15=DO_rI x " g  t:k@6#6<rh "Q#$&'(*+f-"o_u|5~k*Yg.JD70>$*("#tvmlbd]XPVFJ@A5=,.#,"  ^58׸E^T~)%/h4F>n$=P^iot{~ 2Jl - i  o a';q b!"*$~% 'S(*+l-#x`%Cg99I3/3*!% wzkrcfZaOYIN:J3<-5#2* 0zyPU_kۙ>޳I2"ilINE&Pq -26>CHXbyL } * k  {AvK?$-"AKw ("i#$9&')*,* <C6!=-_K(G3.'+   {wxhqbdW]KYCK8F.>$6.(#'tT^՚pծAAr7ߍ1| B %T?M(yLR N+DVeltw (;Wz 6 t % ~ %q4Zz !"T$%5'Q(7*+--}BFiI["93.+ {vtklb`VZRKHH<>26)0"   #Do z]c_3\_3Z} -:=CJPU^l,T . y ! I]J89>Ol4 +"#$f&'])*,$\C1Z)(:!$twloddY\OUFK;@3<&2* QK9 n{+ِKܻec5yDOociG6\dY9Pfoz} "-H\ = . 2~>"%n( !"f$%G'v(6*c+*xL#!1IB4$!!{m~fl^eT^JQBJ4D+8!.)  ckT%A#vAݜO?8 uIm%tBf+;EHKQT\gu6b 6 3 UvWUEW[Z 5"#$&')o*,zZj#{`6J+&y{rlig`XWQHNC::4-,&! j$L~ޗ# f@fqO$n&%c-Mfu )7Ld P 5 EW, EU !#m$%>'(*,%*>ou% $G!+r~nqeiXaNWFL;C/;'-* p" n^6׍eۈޖBq2d>Sw$w$Il~ #(4BTm 3 e B bx@2 -7 !U#~$,&G'")*+hM*}|&%$~wzjqaeW[MQBD9?(5#) |p[Y?ٛt݂wB|BImZ^<*FS>m3HSVa_hlp{-Qy  T P |=|O"!"#j%&^(P)+u{7?S-{vmij]`RUMF@<65)+  }lKbӴ ١)ݽ:(D|f(XM'Jk$'-8A\n / f K czH/  /B~+ !L#$ &n'(*'i%v   xpqhgZ^LWEG;@/3"/ykXB#kԮUٽڢݰi[`lsF5SWDt6D\Z_eglu~1Nx  V N >y[#!"#%&y(K)6+8*.9azqojaaZSOKE?:11(& vgYxHw6d4#ӧNڤzބm"Qi#$&'(*")9 DqV|vwmk`^WTLKA?53-)"  |m~`pWiDj+tԶ6ۯ6<CqdCZ f Jw(BRYeggqpw0N|  ^ O Ai /!"#%&h()( Xf ~yrmgc\XRJF@=41,(}sf~WvLp4o#n3WFׂz ߽T}!0}Wj'n-Vr$+046<>IRk 3 h  [  f2h7/18rj "?#$&'(*/B}F syjh_`QYFHA;34$, pcvZnKe@Y3VR EԼ }ܤߜs<\8l)X"DHP`r? v  l  xA}KE)5+OT 6"h#%(&' )(: ORw|kvbeSaLKAH19++({oc{VpLe:]-UO PRc*-sپ*RkuX@'f .K\m{x| /Ej . q  q #n1c !"`$z%S' (r**_5m-sthi_]UPHD@81-*  wugo^`QXEL6C+8 0&1Pڮ rWZyfe=$t:>(Wy'28==@HKTbu$O " r  E cR@=FWrB 6"#$w&')c#Xe!_<Y4{7suih\`PRHE;:.0## o}hn[gNZDQ7D*?7 ,)&9x\ fybz k"Q>s8Tgs} '8Tz 7 y ( 0D" 1: !"$%`'x(j( _eC;z}kle^TXNFA=30+#  nwdmYaI[GWLZN>n "+:CAEFNQYh9_ . z 7 S%`fQkgt!C"#$&')cK_D(Yrplj\XSRAG=5..# ~~tpii[WUOBF941+#  5ٶH; h$(.EbTF^s '.D\ E 1 C\6 3Xd ! #$%9'/)E#P3;'JOh"}vvlfb\UKJC;71)&qyij\dLXCJ6B#:*"  I`5H!ݏW6mr{zgqbPz2;DLOOSU]cs!Bl 8 C `8t~j/;!e"$%&'5(D'06`n,w~lsbeTWHR9?56"' |pzdeZaGU?G2;'1) ] .ذ5w.kjO lugh[\LTBD47+( zpsdkV^HS;I/=!3#f:.׳تx޺߆OnWVoZV)B=bv $%***028E]t / e  N  l]H"&('Yd%M !#$c&v''. GGYc|lq_gSWII?=/2#' {wnhc[UPJD?51*&N*j(f߸RF l&S5i.EYbkrpqxu}.R # e  ] S.'B: ]!"$%&(3`lr*|5y{v|hg`^QQBD<1.+wxfo^XTU?H5:+.$ vYhF&^۲!0I?"I^*Vx .49<9?BCO\lD v  h  A_I@AFZu@ ?"#%:&W(!J@@XJ6pxpog]]SMFB;2.'"rwfjV]OL?D28%, }k,JA!i~@0Z4D > oG}$BZou|&?a 8 {  m 7lLOfd !#<$%'& {ikZtX{lonbjSWLK:A1/(#}uokdZTPKB<6/+#r~lj۰ދa_ksfTy\XNW>E1:$, |rqdeXWIM:?00!' q]Pw97"(gRdT:z;2u>Zu#2H^ L > OmR$ %,cw] "!#$%'B6%+e}U U|SfaWER=?00%$ ||nkccTRGG<:-- tavVk?v`|j,^ 7?O?2=]Aq .FW_jjnlnrs/R{  `  ` ]1*^4 !"Z$%' %W2 6"LmVZgHHM=33*# |unjb\WNHE880'!w~gqZgHd|w:<zHt+uEk.>?CHKHKRag}!T 8 ) djsX|!"#|%&.&( k<?Xu;YK5[ShEeGK=C03%% }qphcWWNJ?=41'||km_dL]`0pzg߈׀ZQ+Yh:Pp% Z  Q f)nC=!4)QU# M"_#4%%2( YfGBpwB[OH;@00"& ~pqjcZWNKD;51(# xrpbdWZL\F<3# H~(Q[cVD#N g P:Pbisvwx|z,Cf 4 y  ~ 8U*>j/{ !)#$%' M# 'rBYyQDXD;=3)%  zwqgg[URK@>6/*# x}io_aUTC{>}e S_:Py+:HOUVTXZalz9f M F @#(>9 b!"$%&G& Q'Vd1O=)RIr`9YE<59$* {vtkc_YUKCC84+)!yny[nT\lw bDYuQ+P X%Rm$+12566>HUk= t $ s  T ptXpdMk!"#%N&}(J cKB~9en:OL94:$) xtnh[[ULEB<3/+  wmYyKkH0ֆ;ܧߝf_axZLo{*n&E_oz !/B[ N @ \^@/!$-@W/ 6"}# %%&S(:  n5VnG?Q;51.!  vxkh]^TPDJ8;,/! {k^Lw;T8|5m3A4Bp>I?s7MU[ddeklt~ 0X ( o  q 1tN  0u !N#$$&f'O& G&pR7A5#JGhZ2S9<,4' u~incaQ[EJ>>-6"& paR6:հUPo; {iJs'4=G@GHMT\t1d K D D7KK p!#$%&(({Bo6af0R=717) zzqt_hVZKN=E17', vcT:u@jݯrH~r~eLN=~"Mm"$)19Cb|> x  n  H|ohjt L-!"#z%&(9E&HS{/Rn:AG31/#!zspghY[ONAE6:(-$ yeS7[: ?)j[[^"S|Q%G^qw 6Qz R : bVM.2>?pQ -"#$&'%Ynr4N8*<=lL-M:--,! vsfk\[UQDF8<,-$# yjU8CuQمݟ>^ 4rJ"X!;H][bhghpv&S - q n 4sX!28 * !x#$_&-'(X1Cxh.a`.J>3)0  uvpi]eVQJG>A-3") jY7 jj]:m$Qv_:\ l/]+3 x  m Puwu(YY!"$l%&}(i%>wO!g*06EeK.M44+." zrwap][RUDJ8?+6!)  s`A1Iև:ۆbޝY(R02cNa2/V^T7Q`lxz}';Z V C j!h\;A3OQp!A"#$&')t?j_4[g'N95*5%w{lq^iXYFT9F4:$1$xgG<ղ81s R,22c,:OSY^fedq|8^ . t  9_7 >ZQ !#$s&X')Om/-Sl1EB5-6!# ~~qxal[\RW@J;>,9)  oP PqVմaڹۘޔq"=n$n X?j )3::9CIQ[k?p  H [ ]& #H^ !#$%V')$D)}*C7HiH9N733+"#yymoaeWZLLAH18,+' [0rSL0t/sHMXM;s@/qHi~!!&08Ma!N t 7 ]5Sp !"^$r%K':( )rlp<]HY\7c].RB10; & }~rrhe]`NSGD=>,7#+!  a#HNaըڽiF;\=C> nG| B[kx )=`% _ K  t*wjMTFcg!4!c"#!%&'>*8H(4*]k6FN72;(#" yviqadR]JQAB6?'1&c %X^G܌Nߔ:y2[ x;Qy3@R[\ccgnv9_ 1 y ! ;dE$  -Csy ("}#$U&'})i%7;|/ ?8KmR5V<;.8$'  }mvjm^bNXFO:E-;#0& j$iՋr&1Q}CFY)Pv)28@=@HNXh8k  E T \% '?#T !#$%'()[Ftc;ii1XB?2?&1$u~lqcjU^KU@K5@-90 y-${QjA۞VޱR&h=GoamJ7fq'h'Kdv&*6G]z : z  p ! V 7j q!">$y%-'$(*=-o16Uw?LR?6A.1)&vyinbfU]HQCF6?-5, =CJc3J> p!'e5F?x&=T^fpuv| '@] O K b/}TO:LFm0`!"#R%&,()6' 26VD5FKz[>^F>B?+5*% }vrjm^_XWLM>D:6,1(  WL8zy֍Mku\Fm1pkLy1>GNQVZbhq7a & l $ 1V@ +3v  7"`#%!&((*4}V`Oy>or>]QH=H17/+ % xptheb[UVLJ>C77.-!" sM`(\!WoqI2YzU1<= Np'+378AKRg6g D R T&E` !#$%'(* D{ Jp<`MOaFEJ>480(%% zwrqdf]\QUGH?A73)*$HWղOzގ F 0DMI9P kZ(Ebu~  .6Ca~ = v $ x  ^!y /% c!"#$%&()2( aO@R8.WSzkEfQMFL9A02)+ ~zurmcg^YQTGFB>65)+" :=afsMܝߥ?~W!A4k"42.'& |{rrgj[aTTJPAB8;-1#( |`Ҷԍנ6@9gtohD#v28~Ij !'16:=GOZm9k R Q Y7 !b !M#$)&d' )f*( ;be>^G6c_xQuZ[RWFN:D45.3&x{oshiYeRVIP>G5>*6 ,&! oӳBz<٬crk5v$1D70JnV)Lf}  -/@QjH 0  , m, $HD v!#5$%&()+FR9^WWRRsjcRfISDJ;>46&.$   wnvfnYfQXHV:J4C(;6-(Ӥ:eu `t^F/i-EXktv.Ec' a  U };pb^_mO;!"#~%&q()+R"A0$Wwejtg[eXSNOCB>;13*(  x~pvdlZfR\EW8Q0E(D= 8,1<Ӝձqّܬ &KR,Yq?o(>KW^gdop !<g B ) WOA*49nT 7"#%&')*})B Yfs@mW=whd{mk`cW\OLGF=<63**# ~vlybqYiQ_B`6T-N N KI`ӥSS#~?ޞA_?K}jxVL~'CGk-7@DMMRcm@w  c b (hL&91 !x#$V&o'\)$*S,[Ey``evkgj_^TTMKEC>721*)  xm~buWnMhAd5\']^eӲԿ ֞ز.-p-";|Oa`#Fdw $*+5?C\p$V 9 ; wA/_M !#h$%<'()<,#"gy6=b|sornj_dWYMSHG<?84+/!$ }si^|WqHr9l.kmvyhxBtEڦiv^HI7:p*DYmr~ &<Rs9 m  d  Insp,\k!"7$}%'V( *S+K*y >CB{iBtku{nw`pXbTXHR@G;?-:'.%  }sf_~O~Dv6s$| 2X]@HajUd b It 8HW\eimu -Nr H 9 \^N56,EL~ m!S"#%&')*,kG2 dihyq~dqceWaQTHO8I69,9"+"}ohXJA~.*7gզ֢gڐݣaRUr]a5 n=9})V}&5ABJQSfn0] & h  { 1X68ce "#$f&'b){*,#hU7CH pxstljeaY]QQJL>C:8,3&*! ~riUN5VՁJ^(܌Bߠ? E6"(Bu[9[}*-/;BQc|;n E X _% ,F-e !&#$%'(*+*+ :^PjV{|}~qtnoef^[TSOIDD;971,&(! pfWD%[Q)f֜&:1W|^I3m:Xs $5D^|L  t 3 ^4V{ !"o$%Y'p(^*(+I-9z1R/w!r~}{uulldc\\UMNKC??852+'$~maQ,5^ֵ-؃H۳ipM)s|H)Z q Fw5K[hlw|&?[# b M  s0}hRRRfu:6!"$_%&6()*H-\$RH| 3JT3zzvtmpde_\VXKODH:>64,0$(  |qY>N(E0k֍Mjg86``kOF3M&U{&8GPU\cir &@j 7 ~ 0 E mR.%  DT7 X"#*%s&(S)+Q,E+% x\BP^{t{gvai]cT^JSGH=C6<*3%+%  {pM <^\֊ւz׾mے ߥ O. Qni4\)5:AGOVey&Nz  [ l !x>& PpZ "P#$#&'(*+-cI;~4ywvqtcl^aW\JUGK<G4<04(*!(   {aXo{֥։)*,B. &[  "6e |Py}rsplhbb]UYQNIFG;:>7/.-&$ /qӓՏHM\܂ seOBDB`t&+5:HVe 1b  M L P)X} !C#$&&f')I*,D-,)SBIm+~|txloih^a\WQRNHFD=;:312')$  Vӣ՘.(=kړް(}EuiKmq^ :Xjr ,7M]? } ( % d"95 s!"<$%'()+,/( A)Mwxoqljcb`ZUVQKIFEA79703)'&# QOԶեR)T'F׷ ~*ܮMO'q.F\RS5|@K:l!6I[emvy -C`! a  W  s7iWUXd{C:!"$w%&c()`+,.M'tt hv j,}|sxmokh_eZ[SUMNFG>A7>22*0 (#  GմxErC^׍׺F]SwM|&sFu/=HSXals !@k < . T ~O9#39gR D"#%&')*,-y-8*^S{@zs{oufq^f^cO[QQEO>J5C39,5#/+%  Mwռ֙[ז\ׂzhاR~߉oT~ZOF'Kn (07CEVfv Ex  `  e kC$AB !y#$X&'O)z*a,0-/KID)AS }w~mviobj\dU]LXFO@M9F0B':%3 .*$տֶo׵pסv'?\ ހ \D_{rD!e%~`)Ngv$4>So&X 5 B wD+lO !#$%c'(M*+-./(}<~y}vznsen_f[_TZLUER>I8F0A*7"700&'.)1''אב׌}ۦ߽lDCX?:2W3g -F]hu} 1Hk8 v ^  Agre,Sn!"?$%&'e(*E+"-*.z._p x-;E~~txougmde[fR\RVBW>L:I1A+=";5542;G"սץרפ׉z6ݤPHGyPo,y Di #9DV^bpt&Go Q 9 a\M17*EK~ n!\"#2%&()*,-+0b-m`f!|t}numnbm[gSbM\HVBS7O4G,FA> C@HZVֵؼ ؿFت6E8NpFDPJk*2?CMRco*S ( m  x 2Y/5`i $"#$k&'Z)*W,-/)APup{kwar]mXeSbIaBY=T1T+R!IO QVkxְ2(U٥^݁[$encNpy(l)Oi}##06AMe7i  I W Y&&F-n !.#$ &'(*+-.8/H.HIAU|uvo|gw_s[lTiLeEd=`4[0X$[[d}MAנ6O>,;c߅|E)J@H)x@LGw+G`jx&3G^F % x / [+K) !"m$%V'(Q*+a-8.0  -}n(5tt}j}dv]rWqLlIeDd4a5\"cmYז E!k([$L%~ܧN D#rS$8HW_ioz *>` V V k7`TJVVyF4!"#{%&f()U+,6.0 +~.a}wm|f|br_oQqKhGi8h1hp9xPA}@o=`7؞؀ۇ6ެJ8(sqOOG0W}$6AEOXhs"@i - w , <aN#$;G. X"#1%y&"(`) +G,/./ 0rr[v/] {q~nxex`qXqNlHn=p.uj^]ؓ_؉_}V؊)ٜ;I&?lokc5_"b4Xr!,08EUkFr Q  g j5=eG "Q#$-&')*+-.B1#$C}tqyk~_y^sTtHu={!\U*\؀ئ؄؛ؓ|،3ڨPmi5~+<+$t1U;p 0Nbt ,9LiK 1 5 n4 &ZL !#q$%U'(E*+>-.v0a,F >sKGJ%l! ~yxii{a}VzMy: X@6cئظاخآئ؛ؠ9dwe ouBv$vL{ '>QZhrv-Hm' _  ^  wBpmVfic G!"$%&()+,./0 #6c#|xli}`JNSa(7!"$c%&N()B+,7./Q1. @1y9* (   zL`u3w;k9`9[:مSXyzI#8^X[@0ar&k/Tp)3>HRao*S 0 w  x >d3'Nf:s 0"#%&')*,-/0y2 llI/A($!   wlES׀؍HٕOنQUvPـpܒ O_+DBz1Jfz%2:Oa|3b J R V-![+ !X#$=&'2)*3,->/H02( {Ie"}J 4   xRU@ׄثcٴl٦nٟu٘pّ r!ޚ?2.}k/pmR(DXbsx *=Zx ?   w + [(U. !"{$%f'(_*+_-.Z01i0Y X6%=?4(&0&!   wJ%1גلهّپِٺٰٔٻٷܱ.A**J}zS3@B,X(4IRZhs  3X Z K  q.zhPQNfw =T!"&$~%'f(*U+->./00?3B(2po[ 1S5,0!2/%#"    DA_הٙ٥٧٪٬ٹqڜDfg>|/:SA?Oz_9]|%/9FS`s<c 3 | ( F kN1#<\J `"#=%&'()+,./03*cP@HR"V+%:1#3((&&$  EחٲA:Pma!{ dK2o;Xt #)@Mb~Av N  f o7Ln] "j#$M&'<)*2,-"/02~1gVK9-h$.>MH C6/16).*-'+##$    "O#֨$.kݐ~)XX3e v I~:Obr{.E^!Q - @ kB,{W !#$%'(*+-.0w13 , ot:_&9D30=/3-0).**)$$%%   )XV֫9/-*.ڧqߘ4lE[}fQ#3J#Xy*@OZin{$>e) f  ]  @ zkhh{$f s!"E$%/'(**+.-.30c13F, M8 -^=-I=46>-904+2*/&+"*"% $&         0dx5ڳָ JF!A&?&;(9vڙݧ,5q 8:A)Rl d3Xw+6ELWk{!?o ; 7 O~a;5(23Zo'c!"#p%&g()j+,k./r1{222,p"OJ!RV'N>?5H.A2<-='9)2$5$.!-!''% !      .ےֿ7[AWAYBTDTFQf?ۘ6TMUV?9u6Ti #-:HWpF  _  t $|I1 -ey >"#%x&(j)+_,.G/311o4,# fj|#;j-DIB7J5A8>1>27.9*3+1%-$0"(!($""  ,QXm[m^l_lamcqr6VmRKx}[ cmO.Lai}+=Om#X ? D J P* !S#$9&'/)*-,-!/013->*\A&(0/iG5SI=ED>?=?:9<9476142+00)/%))'$( #!#!   (pwڅ|ڂ|چ~ڈڀڈڊڃ[ހX%Qfsn_@"y4A*[ )!"$%&()+,./1y24$'. Hk(Bs;JOP@NFICI@E@E:B==9?7=7858/713,3,-.-(-(*")$$!"# `;^ڷڤڽڬںڭڸڰھڵںMۅ ޡ4-DR=8t 4Xo$7ANbz%J & p  z 8f="   ,UzD W"#8%&*()'+,$./!1~2M4/ Fmc-81oQ:ZPHJNGIHGBGDDAB>>A>;=;;<68676423/2.0./*-**#/ (&&'$!$"Ez`ڲڸ&ܠ(?,1]iL] bJ} *F^l{.?Zu'V  H L S5,u> !#$o&'k)*o,-|/02R3N4/7V*rd*^i8ZRQIUHOFREIGI@JED@I=B=A>><;<8999655507/2/3+.,1$2#- .",--2.w!qھ2ݲV`6@HD}ֵ  ۀ7\U!z v4aR-Sq'8DP_m*Kw O C k*wdQPRf}S`!"8$%)'((*+.-.&01341 R):G<mb?gSVRZI^LQOXEVJQDWGOGQ?QCLAO>I<M:L7J9B:H/L0E/E,F*G&H%HMPUd֜'9.,. /62ZflnUfBv2)c.Nk}#0:Naw&R * u  } @lB3/;hb!m"#M%&<()9+,/./133I57K98v0^<e[_KfO_Q\JcJ[L]HYJYHUH[BSFV?WCP@U?OAR<R<P7R6P5N1R,S*X"[ ]j{HQ׉ HWQP$Q-R2S;WW_߃ cG`tc/H ]>p .K]m)?Uq .a  I Y b8Nb ""#%&')*,-/0235*pZV<HOVcbSeV]W^V]V]RZT]M\O]KXMYHYMYHUHVETGV?ZASBX;S=U8Y3[1\.`&guiq Xr$h0i?mElMpUv^ܗ(p<@N0%f}5Lp '@Q_mz,OpB  r 4 c8 -d !4#$&')*,- /01342 %rcG;[;toIhbX_aWbZ[Y]WX]VWZZUZUXSXP[OWPZMXMVKYIWFXEWFZA\@Z>`3e1e-m{6mSM g+ۃ;ۂIۀTۀYۄdۉlۍqەޚAC N]3K PIk-:IZcw (Jy _ K  {1 {]la:i !"o$%d'(d*+n-.~01345X ZK 7_KafbYg`a\`]a[]_`^ZbZX]\Z\X\U_RZU]N_SYQ[M_L^IaFaJaBa>g8m1s& M ,rJۚV۔bۖkۘv۝}۟ۅۨۏ۸Lܹ0H:Kpf*~#{)h%J_z&3DTf~'W 4 y # GwUA+((=Qz({5!" $y%&s()q+-q.0`1235,2_XRZt&D?Q|bUo^`dd]g]d\b_b\bYeXeYcWeXaYbWdT`UbSaSeOeNeOdIgIgHjCo=s6z,w`ۦlۤ|ۨۄ۫ۍ۲ۙ۵ۡۼ۪LݾaoGJ]ugcB(BM9l#CXhy )?Yp /k  M b k>".e M"#/%&)()1+,<./>1c2$44388sX?U^DozEs_d[pWmZiYlYj[jYh[mZi[fZjWhViXfXlRkWfUkTjUlMmRlNrFsGvB}7  |ہ۹ی۹ۛۿۤۿ۩۰ۼKmm5)""Lt"k Hm3EUbp1Ps? # { 3 j9>0 !N#$9&'-)*.,-%/013X4I6#\=9s@\Kiih\s_kbkYr]kaj_p]k`j_i^n`j^m^m`n[m^k^mZp\nZl\rUtTuQzLB/ܢۭۡ۶ۡx}3tVK?Fi 2=L[j,U T V  y?ysmy>7 ! #w$%e'(h*+o-.j01Z345/xx+aQH86PJfUvkajlanjdkihighiklhjkkfmgjljfnhlijeqeodmfqdsbrbtcs`yXTF w}~  l}ߌ tStrJ[sP"Bby%6FYt /Z ( v ) Cva;<(=:i{B{4!"$%&()+,./12445qn|7pEtPwjldvcrgoereqgqinjrfsmnipksjnorjqoolrnqoqnntksnsnslwh}dZ$ Qx  &!P#ݏ+p#EKVF0 u.C*`8Tfu(9Qr6l  O e xC, $:y6 n"#T%&N()U+,^./d1|2b44c6&AY;B_WorpcwkqgxgopnlsltmtlqntoqpworrwputuqvrxuxrwutuzvwxvyyzrmD!= o ('11<;BMު9< _ w9ea6e+vM\܅k܎zܗ܆ܡܘܬܠܵ`~ o)vY$MO%Rs2GPds,In6 y ' , s;#i@ "#$&')*,-/023l54C6T`bhj1KiM}oycfhlojrpqutvvw{wz~{y}{u{ne]6ׄ3v5܌F܈Xܓlܚ{ܢ܋ܫܖܷܤܴܞބqEyjMira#Mf/?PauFt S O  y>yyZV !,#$&')*,--/0.2x3456 -O3Puy,URQhfxyj|sws~uyvt{yzy{~~|vo[)>Bv^0ۋOܩ`ܨsܪ܁ܷܕܠܴdy& ^'6THK&k6C:l:Vkx .=RrA~ * z  NWN3C4Ye@r!"T$%J'(M*+]-.n01f3T454w4LtXIZiJWtron|xzy~z~}p`!"'(ەbܽuܿ܇ܙܫܻAޞ"Y 5m] Bp/GVdw-JgQ M R gMToZ!j"#I%&@()F+-N.0@133546 $VId AjZszvm~tyvw}}}ze$"ۖv܈ܞܬܾ  1*ߥB:3zcC;5vEi "6DW`| Ag/ s  v , k:3jW #"#%{&() +,./1235355/I*\ZK:3LVxXstuptxzy|k*5۱ۘܖܦܹ!1)>ݍݹ,F+?cisbM(JbF|+,U./e1|2V4454"6^@ P'HnRv~lpyv&~ #-0=CLU]flv{݅ݏݙݙݒ߁[9LMD/v:J7p,Jiy'8Lg5e F B t;|'uk !D#$9&'>)*I,-R/0K23454P6V* ]qH`aovov~~{!q *6-A>TQ`bts݄݀ݒݔݧݥݳOމ#N |Dn p En (E[m~%;XzD~  g A zhGI:SZu# t!"`$%Y'(d*,q- /t0'2T345q5%5$3zX-<2 VR{Zmyurz~~_9AM5[Hk]|pݍ݀ݛݕݮݧݽݹߝ5cm9 7=~Aj4GWg|,OyW 6 Y q>/  ?R#W!"#%&()+-.0124454s6{[>gY/EjT~xzqpzRT^2jFu[݃oݔ݂ݦݖݲݩݺ.E1E_wnjI3VcVCc "/EVi .U+ o  s + k< My J"#:%&?()O+,_./i12L45n546,sE UC[igqy|zרMj+zB~[ݎrݝ݈ݭݙݽݲއBS'/))^"5)bAWq 1@Yx 0e C J n?Cn !p#$k&'|)*,-/023;5554^4h !>R=NXRyOmnnwx _4؉J?ݍRݓkݡ݃ݯݛݯ([dia_a$ZU4e0K]p5Os <w  g  = {lKNBX`7 !#u$&r')}*.,-E/0P2j354546#O J`Q~rkmv|{ %q9RB-܈Hݡ^ݧyݱݐݦݼ/$=J TgQAasF%f*"h =]!0CUj|/PyK > O iJ# $:eyC!".$%('(5*+N-.X01H34@5<5!55/C?8N08KRneuq~} *d- $ܕYݳoݼ݉ݢݺ4'F;YRwU ==P;5~-T5m7Xt -?Sn ,U [  o  l.$9/n B"#2%&5()B+-O.0P134q54545Dl|-vlItUs{tw 6_"ܞr݃ݣݵ$2%H:[Pneެނy8pDj#sBt1Kcu0Ie*^ 4 ? g7@u# !#${&')*,./ 123C5454~6U'b=a[s{vrx5d\ڑܜ݅ݘݵ 5'G?\Trmޅރޥ:ߕ .bn9 7BJq 9M^q&Gg,j  ^ v <\NAIKi2u2 !#$ &')*$,-7/04234S55G5D51 gP.FRvSnwso|7eO ܒݜݭ-'C 7 I cM +4t$b!"L$%Q'(f*+-.013{4~545r4-6wzPWkDjJj~jnuz/z ۅݶ+(>;TTllހޑޗޫޯ)8l X6(^@[r 7Og@x V  d  c0 I1 ^"#U%&Z()k+ -.013T4J55n54;6*nGsb8PYfuuj{u}{}޸r33FL\_syދސޠޥ޸޼t߱>AJVRL2`2F^n)BdH 1 + l"|1; "q# %n&(x)(+,>./R12<44_54l543>(:.'GGvwKhtlo{z bLc'.;GV]owޅތޛޢް޻9@G5'Ru~ub;`w!_4Z 3DZl9]U X h 6|PP6D>fv=q0 !#$ &')*,,-=/13234x545`46 9Q;<Gy8]FymzdmwzA8ZضU 12CI\`r{ލޒޢެ޻$Qa56?7 p.I9t2Wo):Ne 6d6 | ' D eB#?k8_!"M$%O'(f*+-/0234?55N545[-0%~v G8O`^tpmwy|}*TtDثE# 4$C~mllfw~ `>ؕ8-9 H.]Hteފ~ޢޗ޺޲34߅vzfX{\9:5~Ru5K_r 8W|<w * ! fr>P +"#"%&1()J+,i./z12g44h545`46#E0TIlkqbo{y{WMa6IX1mQނjޙޅާޡ޹ %&A@nf$KQ]O@EbN#Kj$:Mf| 'Q~T J o 0pXA:?Me?V !:#$<&'G)*f,-|/0}235%5"5&555/JF"-FvdMyank~hw|/dd4D["d@z^ސ|ާޘ޳" <;WVp J  Q/\@_s+DYw&P/ x   > g3 OhJ ]!"L$%T')j*#,z-=/0M2o354d545k45![wt`K=Z9{]w]bjpy .G5Tp2}Sޏrޣސ޻ު75URkl߇߶߳;q{LIQ*^2Rex2Ln*] H L  U*"aB!"#%&(*++-.:01+345K54s5{4k6'WlUq1H@gjn_equ 4TRٻ`">ވ_ޡނ޷ޞ޿6,NKif߅߀ߟߩa<1PhyxV@ fq$j1Zx*>Yl@e:z  j ) R%z~ZL ""#%&,()C+,[.0e1384254=54855-2 ;?>k19u`Gsdjjusu}}2S*-~h2ގMޜp޳ގޯ1"I?dZ߂wߜߔ߶߱,:C"9-5g/Ajdl_}h{t| 5Xn?:eFޛcުޡ޾ #B5]Ptpߒߋ߮߫ X^ \n0kbJ|.Fcv 6LjF|% q  x : Z-&UyW !#q$&|')*4,-S/0^2345654S54&6*3`/SOIuKXkcfnos{w 2U`^]ޞsްޑ޲ 1+OLif߅߆ߢߡ߽bQIlzV0{47zNv$;Ym}  ?_$X > Q  W<he;!",$%5'(R*+v-.0134?54E54U543eF/8^k8wVn]aor~/R[ܜٷQuޤވ޵ެ!$54j5L4r68&Aubcg6r1XW]Qr[rh{n{ 2 z,ޡ *'EFdl߇߉ߢߧ&>Ibz6M  W9!_+Nm%9Rj$L}Q Y  r AzwlNg J"#L%&c()+,. 01 3445454551?1 l8'^O7eTY`gauluz  ' ,ޣ޾ @-YNysߙߑ߸߶56TVvy=nIIV1a#Edz&A[$T n , : na3>$@:s]a !N#$T& (h)-+,S./m12W44;54O5454?62(U;Ah'`QXOrYsiwqz 2<P ۲ި5P7p`ߏ߂߬ߡ *$KHij*'{Nb~uwU> hu'm2`6Na{6[%\ D Z l:"!;{K !#$&')*?,-X/0\2345454>5u46w*ed)};z 2c5A`OV_ebnmwx} ';X^ُ۟޴'>#^I}mߚߍ߻߳9;Z^|~[.u,*-h-F;r 6]y "7Lf9_,o  s  h+ gM#!"$%&'(>*+a-/x0*2l34454+54C543>/jj&IWhB]KqNz]zhlw/Ck5ۆ޿/ M/eV߆yߦߜ߾(,KJim D? Pf(dgGs 0Ug $:[v6iA I d 4sra}Jm X"#[%&w()+,.01 344'54;54u546^ Jzzx@*i\A\@pGuYz^iw| *Kn<6#p!4O9p^ߏ߃߮ߦ21UZxz=66[tL&p+,tKv%?Ym0Qs6q d v 8 lJ6%(-D^Ny !i#$v&')$+,D./\1274444444453.19 | Z66NNG]V\cphwt~|+@lڗV+?[C}kߠߏߴ#DBih]A69N:24_F#Mp/C^w 2TD @ B  T>  Rhh0 !##$0&'M)*t,-/023 54&54754b574(5n <SWBLHcKj[pkvu}&3c>A/F)gRߋy߫ߠ 30TRvvb^V#zpFo${OGb/Li$Q[  e  `kP.!"!$%6'(P*,o-+/0C234454(54Z54r6$yabvPQ#WCDJBZMb]icutx 1Z$,J7h\ߋ߆߬ߪ9>]d EkbM~f8;D&W:Tl)Ai"R6 1 _ qcjrZ l T"#X%&q( *+3-.Q01Q3444444445~0hazC5P6JF[Jd[lfvmv,Lwgޚݽ &&ADfl߇ߒ߭ߵ&=K]p(=rX EX`UBLl W,Z(>WpAd"^ X f / l;:.$KVH !#$&()"+,E.0U13)454 5435r4j545bD*.!z$NN/K6\?cMkY{box'<Wݪ%6AWf}ߎߤߴ#9J]m#:KJ V6)e.Wu2Hh=f7u + 8 R3 Irc1 !$#$6&'T)*y,-/ 1234454 54656446&(n} vo2KN36C7NETVaZnksu}*|܌2DCcm߇ߍ߮߷.ETj{ "2FZ{1~1lxKPU7k'Fbx &=^~ 5n Q P  K!.]qM!"N$%f'(*,-#/0/234444454 542 oI8~.6H,?9U=]Od[rb}q} PFiخs:$SFqrߖߜ߹*7O`u !/CWj}u Bctzj[7`}#g >k7Nk6X}?y$ |  [ urUkf jk V"#_% 'v(2*+Z-.013o45454)5d4e53[6QJ}?[iN>-C(X:ZDnKt`|gv$"'R؂`P!bGyߥߡ\0 ! #$2&'P) +w,6./Y12@4444545x4,5H44E .0ls"09+8/N<PN^Wifrp}1Gwd&'q#߅Kߡ}߬8*]Q~ "CGot3B:HjqZufVn=CM/c!Fby #A`Bz i o . sL  *M'sH !@#$U&(v))+,X./x12S4444444e4553W6*$KKQKvX;38'.D)J5\?gOr\ir$BmrgHߛl߷ߝ,#VR|{%)OUv>s`3NffcH2] p!g5a@Xt3]W7 E x I;- p!"u$&'5)*`,-/12344444444440UHApO & 005BEJXS_cspy~6e\aۺڳaQߣr߾ߠ7-cY 36\`4>_""\'<=u 5[|5Pl /V4r _ ! D eydIv-!"$%,'(S*,{-B/0\2344444l45?4G535v  WS#)$>#C8PD\Ufcss~+Y]ښO]ߢ߁߯ ?8lgCBipCE;^ _` Jz 2Vr#@\| ,_A 0 Z  WD*- =Iz%T H"#U%&t()+ -.E01B34444444m4546(YB,uLMa:%" ,-3:EEPT^diqv~ $Eu1tߚߒ߼߼ACjr%@Qq|,H[=Hl{xa;j!*vIt +Im)Lm4p P  h  u?# !^#k !j#$&()'+,W.0q13844444444s44v42f 'rBQ% 4B1J>ZNfZvhuARߡe߇ߑߟߴ(?Ul3F_r&@Rk~1w252q6SKHq &D_~%FmJ' C n G=G y!#$0&'X)*,-/123444z44`4514C5396h~A%4>"1>&I8ZAiUoep1\Hߕߎ߬ߴ1Abp#@Uq "4M`y8_p9rsWIk2Rq Hz\ V ? yfhl?B*!"0$%Q'(y*,-E/0[234444444w44&45*Q{)!i7$ !#(0<=ENWXfirxc`B+$ޥߎ߼߶o 1Mo-HtFi " 9 hW310.asM` V"#j%'(M*+}-.023o44{44k44T44*453E6H#j*HJ++:;ARV[asn~ $F\FNLzߨ 6aKML{ z@f ;Yy)I{Q= R a7 5aF "#%&E()v+-./0163m444444444}444/RNl`?|#$3F3U?fPq^k| *Tٜ/޸߁߭2^Q!"OWAOq5 }5{[$Y b G}=b)Le'Tb q  f % \C !#$<&'d)%+,Y./12R4}44m44[44A444535_c* %6J&U5hBvTbv .Y|Ij@ޮߋ߷3(b]'0Xa(L_~!=!OwyhCl)2~S8]v&:g+]= = c / gi]m{ HgU!"f$%')*@,-n/1~2444~44p44]44;4435&%  );%H7\FkTbw!Sz2ݠߐ߻9-k_+0^g#/Ve,LpGu!/=."x/XH&X +Lh=l/ig r 8 qD:)"ASE "#%'(P*,-6/0M234{44q44f44Y44J44`41DJKqd>\%24<INZ]ll{|Hۢݕߔ߼ <1ld58io 4ڻ݁ߣ =6mo :Bqy 9Fn}9Hly>@q|e37I.c.Mr6XJ{[ i  _ %g `C !I#$n&()G+,x./13R444u44j44Z44@4435)HGBffZ!| $-/@BMVbavr-GD٥i߲ 7Cm{>Ns!CXz$B[st@@TYV<Npc>l"Fd~6]J6 1 l # y`nh cpc!#t$&'Q)*,./%1234g44]44N44=44443t3 Kf|2OR-x1"?3SEdTtiyB~A-Me&<\u-E`x4Jfz/Z6 V8/nAk9Pu 1Y \ \ k 3 o@</#MYN!"$%:'(h*,,-a/0x234\44P44A44'443 5j366_d* U4+7/J@YRmb}w`CY ߿ )T`-?bx:Nn #>Ssa)bwIP[Ay`r/w:}[&cfSDn A_AmO? e  UA%!*4cd/ !"2$%`'(*,-R/0k23j4{4b4y4Y4w4Q4u4J4s4E4^44 0wW%j,G^} !#63IG]Wsey9R܆ߠ 9lY FE}|#-[a 7@kv#"Hr{vjA#i,.}'_=bx8bEy+t o : n R 2W. 1"#K% '}(G*+-.023G44E44644%44 4434_35Vk>vZ-rxm#&2=CRTeg|o!?@@`ߝ <oT LD*/dl?Ir%j-B-%}4^J0a8Uw5]SF E  > 0c ~l !x#$&'()^+-.H01R3;44S4}4I4}4=44+4444359'Pq[qU.#<:RHkX}ky.q٤Eߥ;s_NP3?it IX'4p3_j>o%x_2X0Pt)].lb  E  uX_Wn`! #$/&'b)+,Q./{1274\4u4P4t4G4t4;4w4,4}4444#27 [-IB'Kyz 2E%Y:lLZj| 5`0{?-߲ 2"lbNZ 2Dk|+Qd)@e):ky`4;G0i-Vo+Qr+`@1 \  M> $/8k wB8!"S$%'(*6,-j/,124N4~4@44044444434G35#hJkaxe!+?T1iB~Vcw0Wh9޶߳.%feLZ 6Ip3Wh5Ml%2INL4Jeb8l&Lm Fn9q\ k ! o C@znK P"#p% '(K*+-/0523\4`4Y4_4P4^4F4]494b4"443P5*-eBiDix.!A2ZEkYg~ _iK( > h =  u"ud "r#%%&X()+-.?01D3d4?4v444v4(4z444443433ph<Qn G]o-/;CNZ`mttxٮ݂߾)*cg$R` DP|-<NWdfw|9vC;W1 8Hv 0Hm$@a3Ql@V{}8 W"<<Hl /Zy&T(dC ] j ,Hn b l"#%'(I* ,-L/0o23q4,4o4"4o44s44}43434Q35y2?DpS !94LM^]tu/ A?|6Br+?hy5]o$J^?W#j{U] _MEm)Op%X3vm * Z 0 u${n "#,%&d()++-.`02^3Y454`4,4^4!4a44g44x434^35$6^wdyt*YV*59LQ^fwxߴ@7{|6?t1Ai$:cy,RlY@^p|o_>j#4YBl!Fn2hFL m / z_VKT`s5$ !7#$e&')5+,o.01-3#4T4:4O434K4*4I4!4G44G44<4C4|0Jg!KsyT~':*T>gRexXظ߲=7y~6Ft 3Go)Bg9\tZ'.*q3VR+\GhCp@h 5  _J&EY+rB?!"`$&'R)*,./<123e4#4a44a4 4f43o43434.35/)[I;/6U=q&>T.nCXkw_sܧ߬;3y{8Ev 5Ku 2Jl&A`~mPj9o#{"a0a@aHtP? Q ` - N#w "$%@'(**,-h/023R414L4*4H4!4H44L44X434z35'W9+zYi=Exw|2K*_AzPbpti&xߞB*zq8Az;| DJCM=P 7FjH26z ?j 2Xz 0\1q_ y / aD# !Ec4^b!"$)&'i)+,?./m13 4A4)4:4"4744644544;43V43*5*M`yv5`HRyk1I-e=LZZ-J޶ߔ/pe8;u >OAUBX9RANxjA NUAwCn(Js9c<5 B  N *!F7v !".$%g'(*4,-o/!123%4D44C4 4C44E43M43[43433| J[3to%=g#Vl~/ Fe,DNO!<4ۤݑߚ`d*9k 5N{@ZB]<\|)AX`VD&Xv)nD~@iEr <vP_  V  C{4 '"#S% '(N*+-/01234A44B44C43F43P43e43435)hC7JTl# #mnQ{_x &AW-s@NO!MGڽwߜ `h(f L{K/0 Z ! q^OOXl9VO !i#%&E()++-.d01g3.4%4-4 4%44!4444444434)- s(B1!nfV4Bfcf*!F5eI}[Y5E6ٖeߢXh.@oBT "Nh.Wl0Woo)iX*^tQ-b9^%UX Z e 4  f2,2;|2!#$9&'z)?+,./1 3144B44A43A43E43N43`434@3[4*HXz~2UgTlg|(5:QPlbeE0sQޠmKߠWf-@nC[%Uj5]v!:cz2PHf{{cJq)>!a3\5_([0x, 7 G ,0PO+,!"T$%')*d, ./T1244544543543643=43P434!35"[@6Ps{RE=+VMSdZs +5DPZanWb 4;߫߼Gf!@j?]/Qq=`~&FeK)0-u6\S3i)R~9c+d QU J  JSD V"#%'(a*,-W/0x23/44'4 4#44!434343434.4/'\lxe;4$ZKej|~&-@FW`rqi޹ߦ-8sHc"9h9R~!Jh)PlIn=r."e >r'Nv?o3x&} Z  ggN]Q}Q b] "{#4%&u()+@- /x0/2n3<43943743843=43G43_4342D5$PgMVCbVp  !(5CR[gvzA޾ߘ2,u{N]$6j?W #Pm1[sbq1j~x_3>U7vEr'OyGxNL c * _8+:KM !.#$d&()e+,./0183"44(43%43#43"43'43443c483}5;&t7=US:.E3ONOrq|)'J=aU~hJ[أܠ޻ߎ.(uuN[$= !a#$&()k+3-.u01w334343434343 43-43J4k32c /w1Z}jG6/@J`fr6U$" @9jݜcߪfSEF$+nzIY$7i|

E  C  0r!"/$%x'!)*o, ./B123 43433333333333 434+40 P$+4>A`Txs /Qyiڧڵl`ߤTS7E3iK^%@pDc2ZybRokM#|6D6v Bl2[G"i ` B  {^aXr|'f( 0"#h%'(p*+-A/0e23343 43 43434343)4x3V4)33 :~,%i4B8 @$d;~[x ,Ks`4ڒJb߬ߧCN(D{2`Df#EkFg<]K296# Aa`CAp0ZS90 X  P=,7e}OS !w#%&M( *+Y-.023343434343 4343$4p3_425!>h]v82 2U7oVo=d  ܶY`ߙߤ1K"Aq1^?f&Gr'Nn$AhAwB {)2zNGp)X.i V h " q D Pl!#$K&')M+,.,016333333333333333333.4.b&Q!$5DOalx"Ib1aߔߠ/F~%>s.`~Kg1Lz +Tr-Jq5i^@DTPRKt0aF&D n G  -<1!"_$%'.)*~,J./1233 43 4343 43 4343/4S3k42413t:YY #)M6aX}u2$a W _߃ߜ%At9n )[{Hi-Ly.Wv 1MzNg;LXNAQ{'v]#XJt 7oZT C w^c`u7{=8 Q"#%C'(*(,-u/"12333333333333333b3%42H5%|{{ =.TUom !ܳbkߠߺ?e9b,T|Bh-Sx6Y@c6q  f'MN2o 8f!O[8> \ $ nJD5AEkU|  ("#c%&(:*+-3/0R2343333333,32R33,32>32;32&0 qcF*X'=:[[p{yت܀lUߦߧKWs *Yx 9W/R%G$xA18U(S :iD!s+ B  o [2.*#Od7~UY "#9%&v()+6-.e02N343433333212Z22 2213m13z"><0SPqo-<e~zuZpDߨߔEJ>N2H$;t+_yA^?aEij ch s1beR#V~#GyD&ot0 j = MJ0>!"m$&'#)*8,-M/0@2333333333'2 //g0//0///0?(6n/"FCiWt2LaxQ+ߝ{;66A2E*@|8k!WsjX.e1p|N GE6s9g7b*c_V O ' "z, w!"C$%z'(*+-.01b3333333332X/"./4////././ u .G*0FU\xwB3>۪Aߙo7,5=3B.>|4n "Wqj gIt $|Q$a('uWP}N~NEB } 4 funTWI e"$%I'(N*+W-.Q013333333333S0 -..o.8.#/. /-80];0y 15PUrkK /|ڌ.߈j.(,8/>*?{;n(^vh0x$g8ltY-IgY:r8m1e9(~2 _ # w_VOXh%w9( D"#x%'(*+ -./p123333333331,F-.--3.---b.(=WF[f 8!Z@v\vvXhۙt "xp,t&>(H}&F}@m4_#d=A~1SYWH/m(D>V$TL'ld B x `E>->EkU| "#O%&x()f+,W./71{2333333333 3-+ .y-,!--,-,-8$- du<X3uNkFeo+U\"jp߶-m=t"Iv#Gw@n 2[#aAV)'Kv+{&g>r ;k5qXRp / d E+ *Mm1\Z !}# %&J()3+,./0E2|3333333333/*,^-a,7,?-.,,,.> Z^\*G7gPjnV6B!`q߱ -e?s%Hz&Kx!Ds,#,+,*,( }\_QHl!(?RWqylzKݼUm߫"b7l@x$Ex"Et;i ,]E3tJCog64H0mDt 6j G"q&6 R 1 0T=x !*#$a&'m)*?,-/]0123333333333, )B,+*++*+*\,~UvXb|#<AWay,t9IE4߽ܟDeߝ߿Xw1i@s&Fx%FxVQl ]} )_ +_&Vy4]l SW!YjX1k9g8s_] F  q[QL]j/K8 N"#%'(*c+,.H/01333333333331'%)B(t'()  Tql$?72a3X>{Xy2`HWK*|r,=C`Yw ,d9l=k1b,e"~%sbh6>P@TU(fJOt 2 u XE6:?Urc" $"#S%&():+,-!/c01233333333333*$((&w',& " <=dd3V;YwXrf(߁o2=I`^y0m >x$Bv@p+i+=NKszaHo$:%k F{ ?tW5=Y $  e >5& ?Q=zz !##%&]()+s,-/&012333333333\3=4.I$%(&&P N "Ag*j @s (F~ 0&ODv^yWa) ߈m<=Tc !k9{+I2M0N,k8UU ?hdX@&V q&tU1e0gC'y+K  p O *  <g#TS !r#%&>()+I,-. 0M1r2333333333332r&,#' '"9 z ho$ 5 UDzZtdVں ߅r9A Wm,p%D6S:\7[4|kAij>@7 x:__G W&[3umA b 6 *L`0- !K#$&/()*-,-./1Y2P3333333333e34_*!p%' v 7  d}i>!_A[vg6qy-wې$ߊ߁BQaz8{6T DgJmLpD}lM9 _(LT9rIJ$i ]w/ Q + =kM !3#$l&()*,V-./0!2<33333333333&4/?"u#$# \ @ c[E] :*\Lc)"n۵-ߓߋIY $n.IDcWu)` 0b (XhW,TD6D'c ?s>v^Lk s 9 (M9k u!#$W&')*,1-./01)3333333333332@%C!\q 5 9Ro;:3:XPqKf@ۤ7ߒߔQb,w6TQm (e8olAjRhW3_q~^5 Nd]?xGT5+= { @  LH(/!"X$%'1)*+-1.Z/u012333333333334a0" , c G $\W+<Iei %04ڐmߓ-a+]$VEy1bFr%T}*S~La\A{`WyweF{;QN/k ?tE,x|3 j 7 =|)  !"6$%r')*+,+.;/k0q12z33333333343T4) E >Y N  GQFKMu::Uaz#.MD$چ|ߜJzޑߚMk;{ Do 4k)TBk!Qz)W~([Wm`Au ,C1[82wW&\7u^ l T  |nahkWdQ i"$%K'(*+,../,0W1G2_33 43 4343)434)T' % tU @ ~ JqJM"5P[nv8{ioޢߜ_p*DXyA~=bW{ 3fzTBDo ( m V:5/@Jrf( -"#^%&(4*+,..012234 43!43432  0Xh J: p  8"179,^Bh%MwFa=3ݳ߸"#Rn@ Ms8t2XIn&X}*\+foIvADYF+c2hM1=] %  f =2("CSC !#.%&t(0*+-- //1133>43D43]434+2t. Z } D h W I 29 %=_Oy,]!ݤ߽3)ev1I`|(F Hh$a9p>t0[db+4K7yZ'`E%z4L  o W *% 1;x&ln !#%&V(*+ -- //1123C43G43L43e3&"%n Qc y0 o N $ X*4'0Dg[5T3OݠC4 uAW (r9VZz8w+L3U8K ynKo':,qL\7|#t#G  j B ' 3X qFB !g# %&U()+,../0123 4G43\434.-"uq z | F ? Z x )(Y$I?65y]J,Fk'5ܢFF'~Li=Jn 2m+R AhIoL5do^: `0'i D~V0qpD c 6 (Ia62 !R#$&E()+,../0123 4S44\433#$ gD   F 3 > AsS%BnCW.n#Y]tobܨS["=_.R]"L Cm$X4f7f**(JTJ)V v&{^@y J-pd4 Q 1 @hW+) !K#$&()c+-.//012g3C44l434.` $ B v Y? d ] , F cmYFR3<q9+`OPl=޺ܫ bq3Q+tFk8w=d%]Au*P2U~483E91HgpW:vA$k \z- H ) 3ZG !>#$z&()P+- .//012X3G44x43E4#&F^ &   0 | ) F ZUm 'T{2hKwެܱ!mDfCX(OV@x3\DnNtr:MNG v;bg W0i@cY j) n E  R,|!#$V&()Q+,2.//012~34{444#0 j 5 * nU#~Cp ?nz_+<ߤܻ=wO,[2j{ZUf# h ?   G|o!#$D&')H+,?. /001s2z334 44( drne '  Y   I ( u IpyWfzwA&q/>|OT$_+- gx < t w*ge,CVC@lP9dg9rP']1g6e-a$R $`1mVIa c ,  &l bFR!"$8&')+,6.N//012(3C4&44*T Y  j M  }?xL/IUuf)y߂U4dA{ONK{?p-Y@hCm(J{ MGL?Y6sRM\ Y 0 &UcIX!"$&'h)++,\.J/0001t2j334;2"  q m  H fdL   N luC`5<Wg{ߤ !x Wy.U.p@h 5p5_Qy 0d9gP,6|I EJ>W5t ONV T - KYBQ!"$ &'Z)%+,d.X/K001g2334,>!] ` :3! E  V Qg"&Q">U[XMl:5%2uMp"J_,RT{=q(Q4ZK!CNq>:D8}V.k REV V G?".!"_$ &'_)*,A./8011273)4!3% ) s(  u 2<'J H% <>  n tk|n0q$@5zX]Fq-;K8a;e=z Gp9s/[It$T|-F+Ugg75D7yW*k RDZ V  G4%!"U$ &'_)*,9./B021123j4.-!" $ <:k F ) C  # ;UM ).#[:c~l33k T`2L3}Y,V(c-ZR}5hDw$Gi<1`|w[0u2>6zR0pNHR O 23(!"Y$%'D)*,I./u0112Y3h3(w@ 2A Z ! c F98.\3 E v Z ' c(0+e7 1-9iLwd& uuQg0K ,yOrEQv9v0V AhHgT23lhN.q096}Q2oJIN H ! &~0"!"Y$%'2)*,S./012q230"!A"\ H ! M f3Xf) E   G`Q(-6B~_ `,} l|Kb*F nAb 1q6ZSv ,f6iB8y1bB&l,95yS0k LEQ L  %m!"B$%'5)*,9./0C122]3+    + N 5WYJ vu  ? / j8=XC&BOEl'7[_g3-3!eDeC]+QW| ,~\9`6x Hs=v9^Nt(X~=8)Sm%a 61wS0l KDR G  zz}Y ph "*$%w' )*~,+./0t122. O. 20 v ^h%o @ x W3 ^  j2yW;'IVNqv|TGk<[!H 0xU-W)e1\ W~=q%L|"O72e ]11rN.nLGO D  pvuSb] y"%$%p')*u,,./0172_2)D" S a g_BW1#^ 5> b( Q 4 #qCBy ZWOEiYUx@e&M/r Nx#KU~Dz6aIpGpt6:o&X..sQ.i OEN  D  pksF`W x"$%`')*x,./01W20$ U ]`  ) Hv*:1 w]AV  4 Q:VpH+ei}ik[?n#Q-j@m=s~4X/*uV.l PFS ~ D zqhr};YO q"$%T' )*p,./11_2, " $ MR  M*"  k ;! 7 +!D|w[ 3nU=lHߗ|C0u_?r"Q)c4b.`"M~6aAffI%BDR/1rT2nPGO ?  }hif|<E? ]" $%Y'(*T,!./?111' b! J s r % }_bcpzN   |] M:3w3I:)߭%bQ:x#^>tJTPCq/]:ga,C.VT +/uS7qRKP @  }dc`y4w<2 N"$%X'(*N, ./D12/#" p ]d : 9 W yGBS ;4B   j)!+DMV{d8?;/t aFz)]7nEvAv9g$T2_ 4m@i!N+f;h 5h-XCp"Kv"{m-S:v:v+/z^>aTX E  rZVReuV  *"#n%5'(*/,./&0($!6<$ f   B D  v ef K> ( q+Up=Ga4sR&%41({gHn%N#d2[W|:r&Hu"FY['[F}:w0/}&h>~$kS ` O mcM]X}_# <"#%'(o*h,-0n-& x3V /A M V  3  `<  M07s/-;EWj>JT9Q)H8kGj"FY} G~>bOpOp>C^T@x32|/oB.s Vl V lhLbVd%} G"#%'(f*y,-/*%. % TfL \  _ . !9 i|hN-#wNH%9/FqObsXtJj3YB&kDl>{Aj)aAtBs0U[@|39*rL-p\ h R  taRU]xQ )"#t%'(*;,.5.v(" )15 : i 4 nh"hg @Qn+i~;bc:~oeR~?j J'f7e3i)S@jEn8P e J2>/oR.sj n$ P  }]^PhpH "#Z%?'(*,g.+.':<(< X  y 6  Sc5 4] {@ O^<aaex\=; 8-s^Bq!Q%^*WQ| 9j?mLM oY:B4wW5z!mr' X ! }d^Pfq E "#[%0'(*#,-)t$sdgC) 9 46b:M a3I-+B?\c6v&[/W*WK <}"dCqHN{@w3\ :cEkJp i>D<YA!m z( c  ynS]]~Pu ."#~%'(f*,},(a\. w   K C]C ~X)m;*"G4w I# '-(B|M}Lx>o1_G'k>m;w@g']2g=o}Fv)|GGB_ H(r), m " zwSg\^nu ?"#%&)N*,*&I y X M $ m D ca PZ*5 &Q9 ,[=7!/a([nkeT>l R-g9j/g(O <_?iv@y/$JOG#i K0}.9 n , q_a`Ry *"#x%'(*,)!?$Pj }  E3    7O%  > ucF%R)r' /?uT^.{VRgoL ID9v&` E~"W*^([!O} 6` ?gx`g613FXI2q L@,B i 9 hm\stA "#S%L'(**\(J 3 " SAWNsN oSm/e`X 13AQp.e)A$ t#t'ob O7hDW"PKs /`6j:9M*}0@I^J9xQD0K m > loXtq ; "#I%F'(*)+% xs&f * iI,!#Qfk`EB tX4 nm/2c7![Rk$QY,)Q*>EF@3v]>mE~Kw>q/[:d=j&u4FJ[R<|\G;D w :  yhbk}Ht !"#m% '(9*b)1pFT*$- | 9  |N@"-DH=0. (K}B<5|e1jO<^;i7k2h"V @%aC   7 |]k\P Ze 0"#%&")p)'+< H  aI15,OP$33 \+jfo^t ,pu1N_UoYzYXSDw2dH$]1`)^$M~+X%G'`((+*1{p k : Oa5`K} >$C1aExx6w"^| n$+<+I(K D4iJm@StE><[<;E7L;7;D;>K > CKAJCA?T?>I?I>? L>?G ?KA:T>@:R_@M_RJdMOqJ@ O3[ @7N3 :_7 @?m:?C[@CFiJTFJHMHEK ED?DEK EHMHEK ED?DEK EKDKHF HC=CEI E KJKHLHCLE]C E J_H[JHBYE_B@E QsH_@QBJHEfB E@Nm @ HbN H >REd>E@H]EO@H BiE B6?269F9 >J><> <:J:9B9:D : 7F:K7>G:CG>FJCE[FEC]EbC CREBfC @bB @>_:_<:9V:R9 : 7L:T7:>J>CD C FJFEE ECECBE>JBBJ>EGB EJVHNJ HFCFEJEFN FCKFYCJ] FO_JRbOQiRQOkQkOO] QNoOL[N LJbHdJFkHFEdE7_F_FC[F_C @FJ]7OoJ@JMOF[JFCJ C 5f!OkJdO@ Gf 5J CbGGkC@JkGObJ OHJ?B?H CRC OEO CD CH>?; ?HCLC OO OC= C GB>C >GCDCMB M C9 CGJ>J G> CMCMA CNMCKT0b HLGCG LCHGHRNRHCHPN P/drumstick-1.1.3/library/rt-backends/eassynth/sonivox/PaxHeaders.32572/host_src0000644000000000000000000000013213532747316024246 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.930000148 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/0000755000175000001440000000000013532747316025114 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/PaxHeaders.32572/eas_host.h0000644000000000000000000000013213532747316026301 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.930000148 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/eas_host.h0000644000175000001440000000724313532747316027100 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_host.h * * Contents and purpose: * This header defines the host wrapper functions for stdio, stdlib, etc. * The host application must provide an abstraction layer for these functions * to support certain features, such as SMAF and SMF-1 conversion. * * DO NOT MODIFY THIS FILE! * * Copyright 2005 Sonic Network Inc. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ // sentinel #ifndef _EAS_HOST_H #define _EAS_HOST_H #include "eas_types.h" /* for C++ linkage */ #ifdef __cplusplus extern "C" { #endif /* initialization and shutdown routines */ extern EAS_RESULT EAS_HWInit(EAS_HW_DATA_HANDLE *hwInstData); extern EAS_RESULT EAS_HWShutdown(EAS_HW_DATA_HANDLE hwInstData); /* threading */ extern void* EAS_HWRegisterSignalHandler(); extern EAS_RESULT EAS_HWUnRegisterSignalHandler(void *cookie); /* memory functions */ extern void *EAS_HWMemSet(void *s, int c, EAS_I32 n); extern void *EAS_HWMemCpy(void *s1, const void *s2, EAS_I32 n); extern EAS_I32 EAS_HWMemCmp(const void *s1, const void *s2, EAS_I32 n); /* memory allocation */ extern void *EAS_HWMalloc(EAS_HW_DATA_HANDLE hwInstData, EAS_I32 size); extern void EAS_HWFree(EAS_HW_DATA_HANDLE hwInstData, void *p); /* file I/O */ extern EAS_RESULT EAS_HWOpenFile(EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode); extern EAS_RESULT EAS_HWReadFile(EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead); extern EAS_RESULT EAS_HWGetByte(EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p); extern EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst); extern EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst); extern EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition); extern EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position); extern EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position); extern EAS_RESULT EAS_HWFileLength (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pLength); extern EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE* pFile); extern EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file); /* vibrate, LED, and backlight functions */ extern EAS_RESULT EAS_HWVibrate(EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state); extern EAS_RESULT EAS_HWLED(EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state); extern EAS_RESULT EAS_HWBackLight(EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state); #ifdef __cplusplus } /* end extern "C" */ #endif /* host yield function */ extern EAS_BOOL EAS_HWYield(EAS_HW_DATA_HANDLE hwInstData); #endif /* end _EAS_HOST_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/PaxHeaders.32572/eas_report.c0000644000000000000000000000013213532747316026632 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.930000148 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/eas_report.c0000644000175000001440000001472413532747316027433 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_report.c * * Contents and purpose: * This file contains the debug message handling routines for the EAS library. * These routines should be modified as needed for your system. * * Copyright 2005 Sonic Network Inc. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 659 $ * $Date: 2007-04-24 13:36:35 -0700 (Tue, 24 Apr 2007) $ *---------------------------------------------------------------------------- */ #ifdef _lint #include "lint_stdlib.h" #else #include #include #include #endif #include "eas_report.h" static int severityLevel = 9999; /* debug file */ static FILE *debugFile = NULL; int flush = 0; #ifndef _NO_DEBUG_PREPROCESSOR /* structure should have an #include for each error message header file */ S_DEBUG_MESSAGES debugMessages[] = { #ifndef UNIFIED_DEBUG_MESSAGES #include "eas_config_msgs.h" #include "eas_host_msgs.h" #include "eas_hostmm_msgs.h" #include "eas_math_msgs.h" #include "eas_midi_msgs.h" #include "eas_mixer_msgs.h" #include "eas_pcm_msgs.h" #include "eas_public_msgs.h" #include "eas_smf_msgs.h" #include "eas_wave_msgs.h" #include "eas_voicemgt_msgs.h" #ifdef _FM_SYNTH #include "eas_fmsynth_msgs.h" #include "eas_fmengine_msgs.h" #endif #ifdef _WT_SYNTH #include "eas_wtsynth_msgs.h" #include "eas_wtengine_msgs.h" #endif #ifdef _ARM_TEST_MAIN #include "arm_main_msgs.h" #endif #ifdef _EAS_MAIN #include "eas_main_msgs.h" #endif #ifdef _EAS_MAIN_IPC #include "eas_main_ipc_msgs.h" #endif #ifdef _METRICS_ENABLED #include "eas_perf_msgs.h" #endif #ifdef _COMPRESSOR_ENABLED #include "eas_compressor_msgs.h" #endif #ifdef _ENHANCER_ENABLED #include "eas_enhancer_msgs.h" #endif #ifdef _WOW_ENABLED #include "eas_wow_msgs.h" #endif #ifdef _SMAF_PARSER #include "eas_smaf_msgs.h" #endif #ifdef _OTA_PARSER #include "eas_ota_msgs.h" #endif #ifdef _IMELODY_PARSER #include "eas_imelody_msgs.h" #endif #ifdef _WAVE_PARSER #include "eas_wavefile_msgs.h" #endif #if defined(_CMX_PARSER) || defined(_MFI_PARSER) #include "eas_cmf_msgs.h" #endif #if defined(_CMX_PARSER) || defined(_MFI_PARSER) || defined(_WAVE_PARSER) #include "eas_imaadpcm_msgs.h" #endif #else #include "eas_debugmsgs.h" #endif /* denotes end of error messages */ { 0,0,0 } }; /*---------------------------------------------------------------------------- * EAS_ReportEx() * * This is the error message handler. The default handler outputs error * messages to stdout. Modify this as needed for your system. *---------------------------------------------------------------------------- */ void EAS_ReportEx (int severity, unsigned long hashCode, int serialNum, ...) { va_list vargs; int i; /* check severity level */ if (severity > severityLevel) return; /* find the error message and output to stdout */ /*lint -e{661} we check for NULL pointer - no fence post error here */ for (i = 0; debugMessages[i].m_pDebugMsg; i++) { if ((debugMessages[i].m_nHashCode == hashCode) && (debugMessages[i].m_nSerialNum == serialNum)) { /*lint -e{826} */ va_start(vargs, serialNum); if (debugFile) { vfprintf(debugFile, debugMessages[i].m_pDebugMsg, vargs); if (flush) fflush(debugFile); } else { vprintf(debugMessages[i].m_pDebugMsg, vargs); } va_end(vargs); return; } } printf("Unrecognized error: Severity=%d; HashCode=%lu; SerialNum=%d\n", severity, hashCode, serialNum); } /* end EAS_ReportEx */ #else /*---------------------------------------------------------------------------- * EAS_Report() * * This is the error message handler. The default handler outputs error * messages to stdout. Modify this as needed for your system. *---------------------------------------------------------------------------- */ void EAS_Report (int severity, const char *fmt, ...) { va_list vargs; /* check severity level */ if (severity > severityLevel) return; /*lint -e{826} */ va_start(vargs, fmt); if (debugFile) { vfprintf(debugFile, fmt, vargs); if (flush) fflush(debugFile); } else { vprintf(fmt, vargs); } va_end(vargs); } /* end EAS_Report */ /*---------------------------------------------------------------------------- * EAS_ReportX() * * This is the error message handler. The default handler outputs error * messages to stdout. Modify this as needed for your system. *---------------------------------------------------------------------------- */ void EAS_ReportX (int severity, const char *fmt, ...) { va_list vargs; /* check severity level */ if (severity > severityLevel) return; /*lint -e{826} */ va_start(vargs, fmt); if (debugFile) { vfprintf(debugFile, fmt, vargs); if (flush) fflush(debugFile); } else { vprintf(fmt, vargs); } va_end(vargs); } /* end EAS_ReportX */ #endif /*---------------------------------------------------------------------------- * EAS_SetDebugLevel() * * Sets the level for debug message output *---------------------------------------------------------------------------- */ void EAS_SetDebugLevel (int severity) { severityLevel = severity; } /* end EAS_SetDebugLevel */ /*---------------------------------------------------------------------------- * EAS_SetDebugFile() * * Redirect debugger output to the specified file. *---------------------------------------------------------------------------- */ void EAS_SetDebugFile (void *file, int flushAfterWrite) { debugFile = (FILE*) file; flush = flushAfterWrite; } /* end EAS_SetDebugFile */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/PaxHeaders.32572/eas_chorus.h0000644000000000000000000000013213532747316026627 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.930000148 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/eas_chorus.h0000644000175000001440000000272613532747316027427 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_chorus.h * * Contents and purpose: * Contains parameter enumerations for the Chorus effect * * * Copyright Sonic Network Inc. 2006 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 309 $ * $Date: 2006-09-12 18:52:45 -0700 (Tue, 12 Sep 2006) $ *---------------------------------------------------------------------------- */ #ifndef EAS_CHORUS_H #define EAS_CHORUS_H /* enumerated parameter settings for Chorus effect */ typedef enum { EAS_PARAM_CHORUS_BYPASS, EAS_PARAM_CHORUS_PRESET, EAS_PARAM_CHORUS_RATE, EAS_PARAM_CHORUS_DEPTH, EAS_PARAM_CHORUS_LEVEL } E_CHORUS_PARAMS; typedef enum { EAS_PARAM_CHORUS_PRESET1, EAS_PARAM_CHORUS_PRESET2, EAS_PARAM_CHORUS_PRESET3, EAS_PARAM_CHORUS_PRESET4 } E_CHORUS_PRESETS; #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/PaxHeaders.32572/eas_hostmm.c0000644000000000000000000000013213532747316026626 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.930000148 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/eas_hostmm.c0000644000175000001440000004213713532747316027426 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_hostmm.c * * Contents and purpose: * This file contains the host wrapper functions for stdio, stdlib, etc. * This is a sample version that reads from a filedescriptor. * The file locator (EAS_FILE_LOCATOR) handle passed to * HWOpenFile is the same one that is passed to EAS_OpenFile. * * Modify this file to suit the needs of your particular system. * * EAS_MAX_FILE_HANDLES sets the maximum number of MIDI streams within * a MIDI type 1 file that can be played. * * EAS_HW_FILE is a structure to support the file I/O functions. It * comprises the file descriptor, the file read pointer, and * the dup flag, which when set, indicates that the file handle has * been duplicated, and offset and length within the file. * * Copyright 2005 Sonic Network Inc. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 795 $ * $Date: 2007-08-01 00:14:45 -0700 (Wed, 01 Aug 2007) $ *---------------------------------------------------------------------------- */ #ifdef _lint #include "lint_stdlib.h" #else #include #include #include #include #include #include #include #include #include #include #include #include //#include #endif #include "eas_host.h" /* Only for debugging LED, vibrate, and backlight functions */ #include "eas_report.h" /* this module requires dynamic memory support */ #ifdef _STATIC_MEMORY #error "eas_hostmm.c requires the dynamic memory model!\n" #endif #ifndef EAS_MAX_FILE_HANDLES // 100 max file handles == 3 * (nb tracks(32) + 1 for the segment) + 1 for jet file // 3 == 1(playing segment) + 1(prepared segment) // + 1(after end of playing segment, before files closed) #define EAS_MAX_FILE_HANDLES 100 #endif /* * this structure and the related function are here * to support the ability to create duplicate handles * and buffering it in memory. If your system uses * in-memory resources, you can eliminate the calls * to malloc and free, the dup flag, and simply track * the file size and read position. */ typedef struct eas_hw_file_tag { int (*readAt)(void *handle, void *buf, int offset, int size); int (*size)(void *handle); int filePos; void *handle; } EAS_HW_FILE; typedef struct eas_hw_inst_data_tag { EAS_HW_FILE files[EAS_MAX_FILE_HANDLES]; } EAS_HW_INST_DATA; pthread_key_t EAS_sigbuskey; /*---------------------------------------------------------------------------- * EAS_HWInit * * Initialize host wrapper interface * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_HWInit (EAS_HW_DATA_HANDLE *pHWInstData) { EAS_HW_FILE *file; int i; /* need to track file opens for duplicate handles */ *pHWInstData = malloc(sizeof(EAS_HW_INST_DATA)); if (!(*pHWInstData)) return EAS_ERROR_MALLOC_FAILED; EAS_HWMemSet(*pHWInstData, 0, sizeof(EAS_HW_INST_DATA)); file = (*pHWInstData)->files; for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) { file->handle = NULL; file++; } return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * EAS_HWShutdown * * Shut down host wrapper interface * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_HWShutdown (EAS_HW_DATA_HANDLE hwInstData) { free(hwInstData); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * * EAS_HWMalloc * * Allocates dynamic memory * *---------------------------------------------------------------------------- */ /*lint -esym(715, hwInstData) hwInstData available for customer use */ void *EAS_HWMalloc (EAS_HW_DATA_HANDLE hwInstData, EAS_I32 size) { /* Since this whole library loves signed sizes, let's not let * negative or 0 values through */ if (size <= 0) return NULL; return malloc((size_t) size); } /*---------------------------------------------------------------------------- * * EAS_HWFree * * Frees dynamic memory * *---------------------------------------------------------------------------- */ /*lint -esym(715, hwInstData) hwInstData available for customer use */ void EAS_HWFree (EAS_HW_DATA_HANDLE hwInstData, void *p) { free(p); } /*---------------------------------------------------------------------------- * * EAS_HWMemCpy * * Copy memory wrapper * *---------------------------------------------------------------------------- */ void *EAS_HWMemCpy (void *dest, const void *src, EAS_I32 amount) { if (amount < 0) { EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000004 , amount); exit(255); } return memcpy(dest, src, (size_t) amount); } /*---------------------------------------------------------------------------- * * EAS_HWMemSet * * Set memory wrapper * *---------------------------------------------------------------------------- */ void *EAS_HWMemSet (void *dest, int val, EAS_I32 amount) { if (amount < 0) { EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000005 , amount); exit(255); } return memset(dest, val, (size_t) amount); } /*---------------------------------------------------------------------------- * * EAS_HWMemCmp * * Compare memory wrapper * *---------------------------------------------------------------------------- */ EAS_I32 EAS_HWMemCmp (const void *s1, const void *s2, EAS_I32 amount) { if (amount < 0) { EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000006 , amount); exit(255); } return (EAS_I32) memcmp(s1, s2, (size_t) amount); } /*---------------------------------------------------------------------------- * * EAS_HWOpenFile * * Open a file for read or write * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_HWOpenFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_LOCATOR locator, EAS_FILE_HANDLE *pFile, EAS_FILE_MODE mode) { EAS_HW_FILE *file; int fd; int i, temp; /* set return value to NULL */ *pFile = NULL; /* only support read mode at this time */ if (mode != EAS_FILE_READ) return EAS_ERROR_INVALID_FILE_MODE; /* find an empty entry in the file table */ file = hwInstData->files; for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) { /* is this slot being used? */ if (file->handle == NULL) { file->handle = locator->handle; file->readAt = locator->readAt; file->size = locator->size; file->filePos = 0; *pFile = file; return EAS_SUCCESS; } file++; } /* too many open files */ return EAS_ERROR_MAX_FILES_OPEN; } /*---------------------------------------------------------------------------- * * EAS_HWReadFile * * Read data from a file * *---------------------------------------------------------------------------- */ /*lint -esym(715, hwInstData) hwInstData available for customer use */ EAS_RESULT EAS_HWReadFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *pBuffer, EAS_I32 n, EAS_I32 *pBytesRead) { EAS_I32 count; /* make sure we have a valid handle */ if (file->handle == NULL) return EAS_ERROR_INVALID_HANDLE; if (n < 0) return EAS_EOF; /* calculate the bytes to read */ count = file->size(file->handle) - file->filePos; if (n < count) count = n; if (count < 0) return EAS_EOF; /* copy the data to the requested location, and advance the pointer */ if (count) { count = file->readAt(file->handle, pBuffer, file->filePos, count); } file->filePos += count; *pBytesRead = count; /* were n bytes read? */ if (count!= n) return EAS_EOF; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * * EAS_HWGetByte * * Read a byte from a file * *---------------------------------------------------------------------------- */ /*lint -esym(715, hwInstData) hwInstData available for customer use */ EAS_RESULT EAS_HWGetByte (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p) { EAS_I32 numread; return EAS_HWReadFile(hwInstData, file, p, 1, &numread); } /*---------------------------------------------------------------------------- * * EAS_HWGetWord * * Read a 16 bit word from a file * *---------------------------------------------------------------------------- */ /*lint -esym(715, hwInstData) hwInstData available for customer use */ EAS_RESULT EAS_HWGetWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) { EAS_RESULT result; EAS_U8 c1, c2; /* read 2 bytes from the file */ if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS) return result; if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS) return result; /* order them as requested */ if (msbFirst) *((EAS_U16*) p) = ((EAS_U16) c1 << 8) | c2; else *((EAS_U16*) p) = ((EAS_U16) c2 << 8) | c1; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * * EAS_HWGetDWord * * Returns the current location in the file * *---------------------------------------------------------------------------- */ /*lint -esym(715, hwInstData) hwInstData available for customer use */ EAS_RESULT EAS_HWGetDWord (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, void *p, EAS_BOOL msbFirst) { EAS_RESULT result; EAS_U8 c1, c2,c3,c4; /* read 4 bytes from the file */ if ((result = EAS_HWGetByte(hwInstData, file, &c1)) != EAS_SUCCESS) return result; if ((result = EAS_HWGetByte(hwInstData, file, &c2)) != EAS_SUCCESS) return result; if ((result = EAS_HWGetByte(hwInstData, file, &c3)) != EAS_SUCCESS) return result; if ((result = EAS_HWGetByte(hwInstData, file, &c4)) != EAS_SUCCESS) return result; /* order them as requested */ if (msbFirst) *((EAS_U32*) p) = ((EAS_U32) c1 << 24) | ((EAS_U32) c2 << 16) | ((EAS_U32) c3 << 8) | c4; else *((EAS_U32*) p)= ((EAS_U32) c4 << 24) | ((EAS_U32) c3 << 16) | ((EAS_U32) c2 << 8) | c1; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * * EAS_HWFilePos * * Returns the current location in the file * *---------------------------------------------------------------------------- */ /*lint -esym(715, hwInstData) hwInstData available for customer use */ EAS_RESULT EAS_HWFilePos (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 *pPosition) { /* make sure we have a valid handle */ if (file->handle == NULL) return EAS_ERROR_INVALID_HANDLE; *pPosition = file->filePos; return EAS_SUCCESS; } /* end EAS_HWFilePos */ /*---------------------------------------------------------------------------- * * EAS_HWFileSeek * * Seek to a specific location in the file * *---------------------------------------------------------------------------- */ /*lint -esym(715, hwInstData) hwInstData available for customer use */ EAS_RESULT EAS_HWFileSeek (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) { /* make sure we have a valid handle */ if (file->handle == NULL) return EAS_ERROR_INVALID_HANDLE; /* validate new position */ if ((position < 0) || (position > file->size(file->handle))) return EAS_ERROR_FILE_SEEK; /* save new position */ file->filePos = position; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * * EAS_HWFileSeekOfs * * Seek forward or back relative to the current position * *---------------------------------------------------------------------------- */ /*lint -esym(715, hwInstData) hwInstData available for customer use */ EAS_RESULT EAS_HWFileSeekOfs (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_I32 position) { /* make sure we have a valid handle */ if (file->handle == NULL) return EAS_ERROR_INVALID_HANDLE; /* determine the file position */ position += file->filePos; if ((position < 0) || (position > file->size(file->handle))) return EAS_ERROR_FILE_SEEK; /* save new position */ file->filePos = position; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * * EAS_HWDupHandle * * Duplicate a file handle * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_HWDupHandle (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file, EAS_FILE_HANDLE *pDupFile) { EAS_HW_FILE *dupFile; int i; /* make sure we have a valid handle */ if (file->handle == NULL) return EAS_ERROR_INVALID_HANDLE; /* find an empty entry in the file table */ dupFile = hwInstData->files; for (i = 0; i < EAS_MAX_FILE_HANDLES; i++) { /* is this slot being used? */ if (dupFile->handle == NULL) { /* copy info from the handle to be duplicated */ dupFile->handle = file->handle; dupFile->filePos = file->filePos; dupFile->readAt = file->readAt; dupFile->size = file->size; *pDupFile = dupFile; return EAS_SUCCESS; } dupFile++; } /* too many open files */ return EAS_ERROR_MAX_FILES_OPEN; } /*---------------------------------------------------------------------------- * * EAS_HWClose * * Wrapper for fclose function * *---------------------------------------------------------------------------- */ EAS_RESULT EAS_HWCloseFile (EAS_HW_DATA_HANDLE hwInstData, EAS_FILE_HANDLE file1) { EAS_HW_FILE *file2,*dupFile; int i; /* make sure we have a valid handle */ if (file1->handle == NULL) return EAS_ERROR_INVALID_HANDLE; file1->handle = NULL; return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * * EAS_HWVibrate * * Turn on/off vibrate function * *---------------------------------------------------------------------------- */ /*lint -esym(715, hwInstData) hwInstData available for customer use */ EAS_RESULT EAS_HWVibrate (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) { EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000001 , state); return EAS_SUCCESS; } /* end EAS_HWVibrate */ /*---------------------------------------------------------------------------- * * EAS_HWLED * * Turn on/off LED * *---------------------------------------------------------------------------- */ /*lint -esym(715, hwInstData) hwInstData available for customer use */ EAS_RESULT EAS_HWLED (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) { EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000002 , state); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * * EAS_HWBackLight * * Turn on/off backlight * *---------------------------------------------------------------------------- */ /*lint -esym(715, hwInstData) hwInstData available for customer use */ EAS_RESULT EAS_HWBackLight (EAS_HW_DATA_HANDLE hwInstData, EAS_BOOL state) { EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0x1a54b6e8, 0x00000003 , state); return EAS_SUCCESS; } /*---------------------------------------------------------------------------- * * EAS_HWYield * * This function is called periodically by the EAS library to give the * host an opportunity to allow other tasks to run. There are two ways to * use this call: * * If you have a multi-tasking OS, you can call the yield function in the * OS to allow other tasks to run. In this case, return EAS_FALSE to tell * the EAS library to continue processing when control returns from this * function. * * If tasks run in a single thread by sequential function calls (sometimes * call a "commutator loop"), return EAS_TRUE to cause the EAS Library to * return to the caller. Be sure to check the number of bytes rendered * before passing the audio buffer to the codec - it may not be filled. * The next call to EAS_Render will continue processing until the buffer * has been filled. * *---------------------------------------------------------------------------- */ /*lint -esym(715, hwInstData) hwInstData available for customer use */ EAS_BOOL EAS_HWYield (EAS_HW_DATA_HANDLE hwInstData) { /* put your code here */ return EAS_FALSE; } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/PaxHeaders.32572/jet.h0000644000000000000000000000013213532747316025256 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.930000148 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/jet.h0000644000175000001440000001751413532747316026057 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * jet.h * * Contents and purpose: * Public interface for JET sound engine * * Copyright (c) 2006 Sonic Network Inc. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *---------------------------------------------------------------------------- * Revision Control: * $Revision: 554 $ * $Date: 2007-02-02 11:06:10 -0800 (Fri, 02 Feb 2007) $ *---------------------------------------------------------------------------- */ #ifndef _JET_H #define _JET_H #include "eas_types.h" #include "eas.h" /* for C++ linkage */ #ifdef __cplusplus extern "C" { #endif /* opaque handle types for JET interface */ typedef struct s_jet_data_tag *JET_DATA_HANDLE; typedef struct s_jet_config_tag { EAS_U8 appEventRangeLow; EAS_U8 appEventRangeHigh; } S_JET_CONFIG; typedef struct s_jet_status_tag { EAS_INT currentUserID; EAS_INT segmentRepeatCount; EAS_INT numQueuedSegments; EAS_BOOL paused; EAS_I32 location; EAS_U8 currentPlayingSegment; EAS_U8 currentQueuedSegment; } S_JET_STATUS; typedef struct s_jet_event_tag { EAS_U8 segment; EAS_U8 channel; EAS_U8 track; EAS_U8 controller; EAS_U8 value; } S_JET_EVENT; /*---------------------------------------------------------------------------- * JET_Init() *---------------------------------------------------------------------------- * Initializes the JET library, allocates memory, etc. Call * JET_Shutdown to de-allocate memory. Pass NULL for pConfig * to use defaults. If passing config data, configSize should be * sizeof(S_JET_CONFIG). This allows for future expansion of the * config structure while maintaining compatibility. *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_Init (EAS_DATA_HANDLE easHandle, const S_JET_CONFIG *pConfig, EAS_INT configSize); /*---------------------------------------------------------------------------- * JET_Shutdown() *---------------------------------------------------------------------------- * Frees any memory used by the JET library *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_Shutdown (EAS_DATA_HANDLE easHandle); /*---------------------------------------------------------------------------- * JET_OpenFile() *---------------------------------------------------------------------------- * Opens a JET content file for playback *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_OpenFile (EAS_DATA_HANDLE easHandle, EAS_FILE_LOCATOR locator); /*---------------------------------------------------------------------------- * JET_GetAppData() *---------------------------------------------------------------------------- * Returns location and size of application data in the JET file *---------------------------------------------------------------------------- */ EAS_RESULT JET_GetAppData (EAS_DATA_HANDLE easHandle, EAS_I32 *pAppDataOffset, EAS_I32 *pAppDataSize); /*---------------------------------------------------------------------------- * JET_CloseFile() *---------------------------------------------------------------------------- * Closes a JET content file and releases associated resources *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_CloseFile (EAS_DATA_HANDLE easHandle); /*---------------------------------------------------------------------------- * JET_Status() *---------------------------------------------------------------------------- * Returns current status *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_Status (EAS_DATA_HANDLE easHandle, S_JET_STATUS *pStatus); /*---------------------------------------------------------------------------- * JET_GetEvent() *---------------------------------------------------------------------------- * Checks for application events *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_BOOL JET_GetEvent (EAS_DATA_HANDLE easHandle, EAS_U32 *pEventRaw, S_JET_EVENT *pEvent); /*---------------------------------------------------------------------------- * JET_ParseEvent() *---------------------------------------------------------------------------- * Returns current status *---------------------------------------------------------------------------- */ EAS_PUBLIC void JET_ParseEvent (EAS_U32 event, S_JET_EVENT *pEvent); /*---------------------------------------------------------------------------- * JET_QueueSegment() *---------------------------------------------------------------------------- * Queue a segment for playback *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_QueueSegment (EAS_DATA_HANDLE easHandle, EAS_INT segmentNum, EAS_INT libNum, EAS_INT repeatCount, EAS_INT transpose, EAS_U32 muteFlags, EAS_U8 userID); /*---------------------------------------------------------------------------- * JET_Play() *---------------------------------------------------------------------------- * Starts playback of the file *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_Play (EAS_DATA_HANDLE easHandle); /*---------------------------------------------------------------------------- * JET_Pause() *---------------------------------------------------------------------------- * Pauses playback of the file *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_Pause (EAS_DATA_HANDLE easHandle); /*---------------------------------------------------------------------------- * JET_SetMuteFlags() *---------------------------------------------------------------------------- * Change the state of the mute flags *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_SetMuteFlags (EAS_DATA_HANDLE easHandle, EAS_U32 muteFlags, EAS_BOOL sync); /*---------------------------------------------------------------------------- * JET_SetMuteFlag() *---------------------------------------------------------------------------- * Change the state of a single mute flag *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_SetMuteFlag (EAS_DATA_HANDLE easHandle, EAS_INT trackNum, EAS_BOOL muteFlag, EAS_BOOL sync); /*---------------------------------------------------------------------------- * JET_TriggerClip() *---------------------------------------------------------------------------- * Unmute a track and then mute it when it is complete *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_TriggerClip (EAS_DATA_HANDLE easHandle, EAS_INT clipID); /*---------------------------------------------------------------------------- * JET_Clear_Queue() *---------------------------------------------------------------------------- * Clears all segments in the queue *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT JET_Clear_Queue (EAS_DATA_HANDLE easHandle); #ifdef __cplusplus } /* end extern "C" */ #endif #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/PaxHeaders.32572/eas_types.h0000644000000000000000000000013213532747316026470 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.930000148 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/eas_types.h0000644000175000001440000001671513532747316027273 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_types.h * * Contents and purpose: * The public interface header for the EAS synthesizer. * * This header only contains declarations that are specific * to this implementation. * * DO NOT MODIFY THIS FILE! * * Copyright Sonic Network Inc. 2004 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 726 $ * $Date: 2007-06-14 23:10:46 -0700 (Thu, 14 Jun 2007) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_TYPES_H #define _EAS_TYPES_H /* EAS_RESULT return codes */ typedef long EAS_RESULT; #define EAS_SUCCESS 0 #define EAS_FAILURE -1 #define EAS_ERROR_INVALID_MODULE -2 #define EAS_ERROR_MALLOC_FAILED -3 #define EAS_ERROR_FILE_POS -4 #define EAS_ERROR_INVALID_FILE_MODE -5 #define EAS_ERROR_FILE_SEEK -6 #define EAS_ERROR_FILE_LENGTH -7 #define EAS_ERROR_NOT_IMPLEMENTED -8 #define EAS_ERROR_CLOSE_FAILED -9 #define EAS_ERROR_FILE_OPEN_FAILED -10 #define EAS_ERROR_INVALID_HANDLE -11 #define EAS_ERROR_NO_MIX_BUFFER -12 #define EAS_ERROR_PARAMETER_RANGE -13 #define EAS_ERROR_MAX_FILES_OPEN -14 #define EAS_ERROR_UNRECOGNIZED_FORMAT -15 #define EAS_BUFFER_SIZE_MISMATCH -16 #define EAS_ERROR_FILE_FORMAT -17 #define EAS_ERROR_SMF_NOT_INITIALIZED -18 #define EAS_ERROR_LOCATE_BEYOND_END -19 #define EAS_ERROR_INVALID_PCM_TYPE -20 #define EAS_ERROR_MAX_PCM_STREAMS -21 #define EAS_ERROR_NO_VOICE_ALLOCATED -22 #define EAS_ERROR_INVALID_CHANNEL -23 #define EAS_ERROR_ALREADY_STOPPED -24 #define EAS_ERROR_FILE_READ_FAILED -25 #define EAS_ERROR_HANDLE_INTEGRITY -26 #define EAS_ERROR_MAX_STREAMS_OPEN -27 #define EAS_ERROR_INVALID_PARAMETER -28 #define EAS_ERROR_FEATURE_NOT_AVAILABLE -29 #define EAS_ERROR_SOUND_LIBRARY -30 #define EAS_ERROR_NOT_VALID_IN_THIS_STATE -31 #define EAS_ERROR_NO_VIRTUAL_SYNTHESIZER -32 #define EAS_ERROR_FILE_ALREADY_OPEN -33 #define EAS_ERROR_FILE_ALREADY_CLOSED -34 #define EAS_ERROR_INCOMPATIBLE_VERSION -35 #define EAS_ERROR_QUEUE_IS_FULL -36 #define EAS_ERROR_QUEUE_IS_EMPTY -37 #define EAS_ERROR_FEATURE_ALREADY_ACTIVE -38 /* special return codes */ #define EAS_EOF 3 #define EAS_STREAM_BUFFERING 4 #define EAS_BUFFER_FULL 5 /* EAS_STATE return codes */ typedef long EAS_STATE; typedef enum { EAS_STATE_READY = 0, EAS_STATE_PLAY, EAS_STATE_STOPPING, EAS_STATE_PAUSING, EAS_STATE_STOPPED, EAS_STATE_PAUSED, EAS_STATE_OPEN, EAS_STATE_ERROR, EAS_STATE_EMPTY } E_EAS_STATE; /* constants */ #ifndef EAS_CONST #define EAS_CONST const #endif /* definition for public interface functions */ #ifndef EAS_PUBLIC #define EAS_PUBLIC #endif /* boolean values */ typedef unsigned EAS_BOOL; typedef unsigned char EAS_BOOL8; #define EAS_FALSE 0 #define EAS_TRUE 1 /* scalar variable definitions */ typedef unsigned char EAS_U8; typedef signed char EAS_I8; typedef char EAS_CHAR; typedef unsigned short EAS_U16; typedef short EAS_I16; typedef unsigned long EAS_U32; typedef long EAS_I32; typedef unsigned EAS_UINT; typedef int EAS_INT; typedef long EAS_LONG; /* audio output type */ typedef short EAS_PCM; /* file open modes */ typedef EAS_I32 EAS_FILE_MODE; #define EAS_FILE_READ 1 #define EAS_FILE_WRITE 2 /* file locator e.g. filename or memory pointer */ typedef struct s_eas_file_tag { void *handle; int(*readAt)(void *handle, void *buf, int offset, int size); int(*size)(void *handle); } EAS_FILE, *EAS_FILE_LOCATOR; /* handle to stream */ typedef struct s_eas_stream_tag *EAS_HANDLE; /* handle to file */ typedef struct eas_hw_file_tag *EAS_FILE_HANDLE; /* handle for synthesizer data */ typedef struct s_eas_data_tag *EAS_DATA_HANDLE; /* handle to persistent data for host wrapper interface */ typedef struct eas_hw_inst_data_tag *EAS_HW_DATA_HANDLE; /* handle to sound library */ typedef struct s_eas_sndlib_tag *EAS_SNDLIB_HANDLE; typedef struct s_eas_dls_tag *EAS_DLSLIB_HANDLE; /* pointer to frame buffer - used in split architecture only */ typedef struct s_eas_frame_buffer_tag *EAS_FRAME_BUFFER_HANDLE; /* untyped pointer for instance data */ typedef void *EAS_VOID_PTR; /* inline functions */ #ifndef EAS_INLINE #if defined (__XCC__) #define EAS_INLINE __inline__ #elif defined (__GNUC__) #define EAS_INLINE inline static #else #define EAS_INLINE __inline #endif #endif /* define NULL value */ #ifndef NULL #define NULL 0 #endif /* metadata types for metadata return codes */ typedef enum { EAS_METADATA_UNKNOWN = 0, EAS_METADATA_TITLE, EAS_METADATA_AUTHOR, EAS_METADATA_COPYRIGHT, EAS_METADATA_LYRIC, EAS_METADATA_TEXT } E_EAS_METADATA_TYPE; /* metadata callback function */ typedef void (*EAS_METADATA_CBFUNC) (E_EAS_METADATA_TYPE metaDataType, char *metaDataBuf, EAS_VOID_PTR pUserData); /* file types for metadata return codes */ typedef enum { EAS_FILE_UNKNOWN = 0, EAS_FILE_SMF0, EAS_FILE_SMF1, EAS_FILE_SMAF_UNKNOWN, EAS_FILE_SMAF_MA2, EAS_FILE_SMAF_MA3, EAS_FILE_SMAF_MA5, EAS_FILE_CMX, EAS_FILE_MFI, EAS_FILE_OTA, EAS_FILE_IMELODY, EAS_FILE_RTTTL, EAS_FILE_XMF0, EAS_FILE_XMF1, EAS_FILE_WAVE_PCM, EAS_FILE_WAVE_IMA_ADPCM, EAS_FILE_MMAPI_TONE_CONTROL } E_EAS_FILE_TYPE; /* enumeration for synthesizers */ typedef enum { EAS_MCU_SYNTH = 0, EAS_DSP_SYNTH } E_SYNTHESIZER; /* external audio callback program change */ typedef struct s_ext_audio_prg_chg_tag { EAS_U16 bank; EAS_U8 program; EAS_U8 channel; } S_EXT_AUDIO_PRG_CHG; /* external audio callback event */ typedef struct s_ext_audio_event_tag { EAS_U8 channel; EAS_U8 note; EAS_U8 velocity; EAS_BOOL8 noteOn; } S_EXT_AUDIO_EVENT; typedef struct s_midi_controllers_tag { EAS_U8 modWheel; /* CC1 */ EAS_U8 volume; /* CC7 */ EAS_U8 pan; /* CC10 */ EAS_U8 expression; /* CC11 */ EAS_U8 channelPressure; /* MIDI channel pressure */ #ifdef _REVERB EAS_U8 reverbSend; /* CC91 */ #endif #ifdef _CHORUS EAS_U8 chorusSend; /* CC93 */ #endif } S_MIDI_CONTROLLERS; /* iMode play modes enumeration for EAS_SetPlayMode */ typedef enum { IMODE_PLAY_ALL = 0, IMODE_PLAY_PARTIAL } E_I_MODE_PLAY_MODE; typedef EAS_BOOL (*EAS_EXT_PRG_CHG_FUNC) (EAS_VOID_PTR pInstData, S_EXT_AUDIO_PRG_CHG *pPrgChg); typedef EAS_BOOL (*EAS_EXT_EVENT_FUNC) (EAS_VOID_PTR pInstData, S_EXT_AUDIO_EVENT *pEvent); #endif /* #ifndef _EAS_TYPES_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/PaxHeaders.32572/eas_wave.c0000644000000000000000000000013213532747316026261 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.930000148 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/eas_wave.c0000644000175000001440000002565113532747316027063 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_wave.c * * Contents and purpose: * This module contains .WAV file functions for the EAS synthesizer * test harness. * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *---------------------------------------------------------------------------- * Revision Control: * $Revision: 658 $ * $Date: 2007-04-24 13:35:49 -0700 (Tue, 24 Apr 2007) $ *---------------------------------------------------------------------------- */ /* lint complaints about most C library headers, so we use our own during lint step */ #ifdef _lint #include "lint_stdlib.h" #else #include #include #endif #include "eas_wave.h" /* .WAV file format tags */ const EAS_U32 riffTag = 0x46464952; const EAS_U32 waveTag = 0x45564157; const EAS_U32 fmtTag = 0x20746d66; const EAS_U32 dataTag = 0x61746164; #ifdef _BIG_ENDIAN /*---------------------------------------------------------------------------- * FlipDWord() *---------------------------------------------------------------------------- * Purpose: Endian flip a DWORD for big-endian processors * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ static void FlipDWord (EAS_U32 *pValue) { EAS_U8 *p; EAS_U32 temp; p = (EAS_U8*) pValue; temp = (((((p[3] << 8) | p[2]) << 8) | p[1]) << 8) | p[0]; *pValue = temp; } /*---------------------------------------------------------------------------- * FlipWord() *---------------------------------------------------------------------------- * Purpose: Endian flip a WORD for big-endian processors * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ static void FlipWord (EAS_U16 *pValue) { EAS_U8 *p; EAS_U16 temp; p = (EAS_U8*) pValue; temp = (p[1] << 8) | p[0]; *pValue = temp; } /*---------------------------------------------------------------------------- * FlipWaveHeader() *---------------------------------------------------------------------------- * Purpose: Endian flip the wave header for big-endian processors * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ static void FlipWaveHeader (WAVE_HEADER *p) { FlipDWord(&p->nRiffTag); FlipDWord(&p->nRiffSize); FlipDWord(&p->nWaveTag); FlipDWord(&p->nFmtTag); FlipDWord(&p->nFmtSize); FlipDWord(&p->nDataTag); FlipDWord(&p->nDataSize); FlipWord(&p->fc.wFormatTag); FlipWord(&p->fc.nChannels); FlipDWord(&p->fc.nSamplesPerSec); FlipDWord(&p->fc.nAvgBytesPerSec); FlipWord(&p->fc.nBlockAlign); FlipWord(&p->fc.wBitsPerSample); } #endif /*---------------------------------------------------------------------------- * WaveFileCreate() *---------------------------------------------------------------------------- * Purpose: Opens a wave file for writing and writes the header * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ WAVE_FILE *WaveFileCreate (const char *filename, EAS_I32 nChannels, EAS_I32 nSamplesPerSec, EAS_I32 wBitsPerSample) { WAVE_FILE *wFile; /* allocate memory */ wFile = malloc(sizeof(WAVE_FILE)); if (!wFile) return NULL; wFile->write = EAS_TRUE; /* create the file */ wFile->file = fopen(filename,"wb"); if (!wFile->file) { free(wFile); return NULL; } /* initialize PCM format .WAV file header */ wFile->wh.nRiffTag = riffTag; wFile->wh.nRiffSize = sizeof(WAVE_HEADER) - 8; wFile->wh.nWaveTag = waveTag; wFile->wh.nFmtTag = fmtTag; wFile->wh.nFmtSize = sizeof(FMT_CHUNK); /* initalize 'fmt' chunk */ wFile->wh.fc.wFormatTag = 1; wFile->wh.fc.nChannels = (EAS_U16) nChannels; wFile->wh.fc.nSamplesPerSec = (EAS_U32) nSamplesPerSec; wFile->wh.fc.wBitsPerSample = (EAS_U16) wBitsPerSample; wFile->wh.fc.nBlockAlign = (EAS_U16) (nChannels * (EAS_U16) (wBitsPerSample / 8)); wFile->wh.fc.nAvgBytesPerSec = wFile->wh.fc.nBlockAlign * (EAS_U32) nSamplesPerSec; /* initialize 'data' chunk */ wFile->wh.nDataTag = dataTag; wFile->wh.nDataSize = 0; #ifdef _BIG_ENDIAN FlipWaveHeader(&wFile->wh); #endif /* write the header */ if (fwrite(&wFile->wh, sizeof(WAVE_HEADER), 1, wFile->file) != 1) { fclose(wFile->file); free(wFile); return NULL; } #ifdef _BIG_ENDIAN FlipWaveHeader(&wFile->wh); #endif /* return the file handle */ return wFile; } /* end WaveFileCreate */ /*---------------------------------------------------------------------------- * WaveFileWrite() *---------------------------------------------------------------------------- * Purpose: Writes data to the wave file * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ EAS_I32 WaveFileWrite (WAVE_FILE *wFile, void *buffer, EAS_I32 n) { EAS_I32 count; /* make sure we have an open file */ if (wFile == NULL) { return 0; } #ifdef _BIG_ENDIAN { EAS_I32 i; EAS_U16 *p; p = buffer; i = n >> 1; while (i--) FlipWord(p++); } #endif /* write the data */ count = (EAS_I32) fwrite(buffer, 1, (size_t) n, wFile->file); /* add the number of bytes written */ wFile->wh.nRiffSize += (EAS_U32) count; wFile->wh.nDataSize += (EAS_U32) count; /* return the count of bytes written */ return count; } /* end WriteWaveHeader */ /*---------------------------------------------------------------------------- * WaveFileClose() *---------------------------------------------------------------------------- * Purpose: Opens a wave file for writing and writes the header * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ EAS_BOOL WaveFileClose (WAVE_FILE *wFile) { EAS_I32 count = 1; /* return to beginning of file and write the header */ if (wFile->write) { if (fseek(wFile->file, 0L, SEEK_SET) == 0) { #ifdef _BIG_ENDIAN FlipWaveHeader(&wFile->wh); #endif count = (EAS_I32) fwrite(&wFile->wh, sizeof(WAVE_HEADER), 1, wFile->file); #ifdef _BIG_ENDIAN FlipWaveHeader(&wFile->wh); #endif } } /* close the file */ if (fclose(wFile->file) != 0) count = 0; /* free the memory */ free(wFile); /* return the file handle */ return (count == 1 ? EAS_TRUE : EAS_FALSE); } /* end WaveFileClose */ #ifdef _WAVE_FILE_READ #ifdef _BIG_ENDIAN #error "WaveFileOpen not currently supported on big-endian processors" #endif /*---------------------------------------------------------------------------- * WaveFileOpen() *---------------------------------------------------------------------------- * Purpose: Opens a wave file for reading and reads the header * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ WAVE_FILE *WaveFileOpen (const char *filename) { WAVE_FILE *wFile; struct { EAS_U32 tag; EAS_U32 size; } chunk; EAS_U32 tag; EAS_I32 startChunkPos; EAS_INT state; EAS_BOOL done; /* allocate memory */ wFile = malloc(sizeof(WAVE_FILE)); if (!wFile) return NULL; /* open the file */ wFile->write = EAS_FALSE; wFile->file = fopen(filename,"rb"); if (!wFile->file) { free(wFile); return NULL; } /* make lint happy */ chunk.tag = chunk.size = 0; startChunkPos = 0; /* read the RIFF tag and file size */ state = 0; done = EAS_FALSE; while (!done) { switch(state) { /* read the RIFF tag */ case 0: if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1) done = EAS_TRUE; else { if (chunk.tag != riffTag) done = EAS_TRUE; else state++; } break; /* read the WAVE tag */ case 1: if (fread(&tag, sizeof(tag), 1, wFile->file) != 1) done = EAS_TRUE; else { if (tag != waveTag) done = EAS_TRUE; else state++; } break; /* looking for fmt chunk */ case 2: if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1) done = EAS_TRUE; else { startChunkPos = ftell(wFile->file); /* not fmt tag, skip it */ if (chunk.tag != fmtTag) fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET); else state++; } break; /* read fmt chunk */ case 3: if (fread(&wFile->wh.fc, sizeof(FMT_CHUNK), 1, wFile->file) != 1) done = EAS_TRUE; else { fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET); state++; } break; /* looking for data chunk */ case 4: if (fread(&chunk, sizeof(chunk), 1, wFile->file) != 1) done = EAS_TRUE; else { startChunkPos = ftell(wFile->file); /* not data tag, skip it */ if (chunk.tag != dataTag) fseek(wFile->file, startChunkPos + (EAS_I32) chunk.size, SEEK_SET); else { wFile->dataSize = chunk.size; state++; done = EAS_TRUE; } } break; default: done = EAS_TRUE; break; } } /* if not final state, an error occurred */ if (state != 5) { fclose(wFile->file); free(wFile); return NULL; } /* return the file handle */ return wFile; } /* end WaveFileOpen */ #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/PaxHeaders.32572/eas_main.c0000644000000000000000000000013213532747316026243 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.930000148 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/eas_main.c0000644000175000001440000003620513532747316027042 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_main.c * * Contents and purpose: * The entry point and high-level functions for the EAS Synthesizer test * harness. * * Copyright Sonic Network Inc. 2004 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 775 $ * $Date: 2007-07-20 10:11:11 -0700 (Fri, 20 Jul 2007) $ *---------------------------------------------------------------------------- */ #ifdef _lint #include "lint_stdlib.h" #else #include #include #include #include #endif #include "eas.h" #include "eas_wave.h" #include "eas_report.h" /* determines how many EAS buffers to fill a host buffer */ #define NUM_BUFFERS 8 /* default file to play if no filename is specified on the command line */ static const char defaultTestFile[] = "test.mid"; EAS_I32 polyphony; /* prototypes for helper functions */ static void StrCopy(char *dest, const char *src, EAS_I32 size); static EAS_BOOL ChangeFileExt(char *str, const char *ext, EAS_I32 size); static EAS_RESULT PlayFile (EAS_DATA_HANDLE easData, const char* filename, const char* outputFile, const S_EAS_LIB_CONFIG *pLibConfig, void *buffer, EAS_I32 bufferSize); static EAS_BOOL EASLibraryCheck (const S_EAS_LIB_CONFIG *pLibConfig); /* main is defined after playfile to avoid the need for two passes through lint */ /*---------------------------------------------------------------------------- * PlayFile() *---------------------------------------------------------------------------- * Purpose: * This function plays the file requested by filename * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ static EAS_RESULT PlayFile (EAS_DATA_HANDLE easData, const char* filename, const char* outputFile, const S_EAS_LIB_CONFIG *pLibConfig, void *buffer, EAS_I32 bufferSize) { EAS_HANDLE handle; EAS_RESULT result, reportResult; EAS_I32 count; EAS_STATE state; EAS_I32 playTime; char waveFilename[256]; WAVE_FILE *wFile; EAS_INT i; EAS_PCM *p; EAS_FILE file; /* determine the name of the output file */ wFile = NULL; if (outputFile == NULL) { StrCopy(waveFilename, filename, sizeof(waveFilename)); if (!ChangeFileExt(waveFilename, "wav", sizeof(waveFilename))) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error in output filename %s\n", waveFilename); */ } return EAS_FAILURE; } outputFile = waveFilename; } /* call EAS library to open file */ file.path = filename; file.fd = 0; if ((reportResult = EAS_OpenFile(easData, &file, &handle)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_OpenFile returned %ld\n", reportResult); */ } return reportResult; } /* prepare to play the file */ if ((result = EAS_Prepare(easData, handle)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Prepare returned %ld\n", result); */ } reportResult = result; } /* get play length */ if ((result = EAS_ParseMetaData(easData, handle, &playTime)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_ParseMetaData returned %ld\n", result); */ } return result; } EAS_ReportEx(_EAS_SEVERITY_NOFILTER, 0xe624f4d9, 0x00000005 , playTime / 1000, playTime % 1000); if (reportResult == EAS_SUCCESS) { /* create the output file */ wFile = WaveFileCreate(outputFile, pLibConfig->numChannels, pLibConfig->sampleRate, sizeof(EAS_PCM) * 8); if (!wFile) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Unable to create output file %s\n", waveFilename); */ } reportResult = EAS_FAILURE; } } /* rendering loop */ while (reportResult == EAS_SUCCESS) { /* we may render several buffers here to fill one host buffer */ for (i = 0, p = buffer; i < NUM_BUFFERS; i++, p+= pLibConfig->mixBufferSize * pLibConfig->numChannels) { /* get the current time */ if ((result = EAS_GetLocation(easData, handle, &playTime)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_GetLocation returned %d\n",result); */ } if (reportResult == EAS_SUCCESS) reportResult = result; break; } { /* dpp: EAS_ReportEx(_EAS_SEVERITY_DETAIL, "Parser time: %d.%03d\n", playTime / 1000, playTime % 1000); */ } /* render a buffer of audio */ if ((result = EAS_Render(easData, p, pLibConfig->mixBufferSize, &count)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Render returned %d\n",result); */ } if (reportResult == EAS_SUCCESS) reportResult = result; } } if (result == EAS_SUCCESS) { /* write it to the wave file */ if (WaveFileWrite(wFile, buffer, bufferSize) != bufferSize) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "WaveFileWrite failed\n"); */ } reportResult = EAS_FAILURE; } } if (reportResult == EAS_SUCCESS) { /* check stream state */ if ((result = EAS_State(easData, handle, &state)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_State returned %d\n", result); */ } reportResult = result; } /* is playback complete */ if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR)) break; } } /* close the output file */ if (wFile) { if (!WaveFileClose(wFile)) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error closing wave file %s\n", waveFilename); */ } if (reportResult == EAS_SUCCESS) result = EAS_FAILURE; } } /* close the input file */ if ((result = EAS_CloseFile(easData,handle)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "EAS_Close returned %ld\n", result); */ } if (reportResult == EAS_SUCCESS) result = EAS_FAILURE; } return reportResult; } /* end PlayFile */ /*---------------------------------------------------------------------------- * main() *---------------------------------------------------------------------------- * Purpose: The entry point for the EAS sample application * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ int main( int argc, char **argv ) { EAS_DATA_HANDLE easData; const S_EAS_LIB_CONFIG *pLibConfig; void *buffer; EAS_RESULT result, playResult; EAS_I32 bufferSize; int i; int temp; FILE *debugFile; char *outputFile = NULL; /* set the error reporting level */ EAS_SetDebugLevel(_EAS_SEVERITY_INFO); debugFile = NULL; /* process command-line arguments */ for (i = 1; i < argc; i++) { /* check for switch */ if (argv[i][0] == '-') { switch (argv[i][1]) { case 'd': temp = argv[i][2]; if ((temp >= '0') || (temp <= '9')) EAS_SetDebugLevel(temp); else { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Invalid debug level %d\n", temp); */ } break; case 'f': if ((debugFile = fopen(&argv[i][2],"w")) == NULL) { /* dpp: EAS_ReportEx(_EAS_SEVERITY_WARNING, "Unable to create debug file %s\n", &argv[i][2]); */ } else EAS_SetDebugFile(debugFile, EAS_TRUE); break; case 'o': outputFile = &argv[i][2]; break; case 'p': polyphony = atoi(&argv[i][2]); if (polyphony < 1) polyphony = 1; { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Polyphony set to %d\n", polyphony); */ } break; default: break; } continue; } } /* assume success */ playResult = EAS_SUCCESS; /* get the library configuration */ pLibConfig = EAS_Config(); if (!EASLibraryCheck(pLibConfig)) return -1; if (polyphony > pLibConfig->maxVoices) polyphony = pLibConfig->maxVoices; /* calculate buffer size */ bufferSize = pLibConfig->mixBufferSize * pLibConfig->numChannels * (EAS_I32)sizeof(EAS_PCM) * NUM_BUFFERS; /* allocate output buffer memory */ buffer = malloc((EAS_U32)bufferSize); if (!buffer) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Error allocating memory for audio buffer\n"); */ } return EAS_FAILURE; } /* initialize the EAS library */ polyphony = pLibConfig->maxVoices; if ((result = EAS_Init(&easData)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_Init returned %ld - aborting!\n", result); */ } free(buffer); return result; } /* * Some debugging environments don't allow for passed parameters. * In this case, just play the default MIDI file "test.mid" */ if (argc < 2) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Playing '%s'\n", defaultTestFile); */ } if ((playResult = PlayFile(easData, defaultTestFile, NULL, pLibConfig, buffer, bufferSize)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d playing file %s\n", playResult, defaultTestFile); */ } } } /* iterate through the list of files to be played */ else { for (i = 1; i < argc; i++) { /* check for switch */ if (argv[i][0] != '-') { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "Playing '%s'\n", argv[i]); */ } if ((playResult = PlayFile(easData, argv[i], outputFile, pLibConfig, buffer, bufferSize)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_ERROR, "Error %d playing file %s\n", playResult, argv[i]); */ } break; } } } } /* shutdown the EAS library */ if ((result = EAS_Shutdown(easData)) != EAS_SUCCESS) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "EAS_Shutdown returned %ld\n", result); */ } } /* free the output buffer */ free(buffer); /* close the debug file */ if (debugFile) fclose(debugFile); /* play errors take precedence over shutdown errors */ if (playResult != EAS_SUCCESS) return playResult; return result; } /* end main */ /*---------------------------------------------------------------------------- * StrCopy() *---------------------------------------------------------------------------- * Purpose: * Safe string copy * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ static void StrCopy(char *dest, const char *src, EAS_I32 size) { int len; strncpy(dest, src, (size_t) size-1); len = (int) strlen(src); if (len < size) dest[len] = 0; } /* end StrCopy */ /*---------------------------------------------------------------------------- * ChangeFileExt() *---------------------------------------------------------------------------- * Purpose: * Changes the file extension of a filename * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ static EAS_BOOL ChangeFileExt(char *str, const char *ext, EAS_I32 size) { char *p; /* find the extension, if any */ p = strrchr(str,'.'); if (!p) { if ((EAS_I32)(strlen(str) + 5) > size) return EAS_FALSE; strcat(str,"."); strcat(str,ext); return EAS_TRUE; } /* make sure there's room for the extension */ p++; *p = 0; if ((EAS_I32)(strlen(str) + 4) > size) return EAS_FALSE; strcat(str,ext); return EAS_TRUE; } /* end ChangeFileExt */ /*---------------------------------------------------------------------------- * EASLibraryCheck() *---------------------------------------------------------------------------- * Purpose: * Displays the library version and checks it against the header * file used to build this code. * * Inputs: * pLibConfig - library configuration retrieved from the library * * Outputs: * returns EAS_TRUE if matched * * Side Effects: * *---------------------------------------------------------------------------- */ static EAS_BOOL EASLibraryCheck (const S_EAS_LIB_CONFIG *pLibConfig) { /* display the library version */ { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "EAS Library Version %d.%d.%d.%d\n", pLibConfig->libVersion >> 24, (pLibConfig->libVersion >> 16) & 0x0f, (pLibConfig->libVersion >> 8) & 0x0f, pLibConfig->libVersion & 0x0f); */ } /* display some info about the library build */ if (pLibConfig->checkedVersion) { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tChecked library\n"); */ } { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tMaximum polyphony: %d\n", pLibConfig->maxVoices); */ } { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tNumber of channels: %d\n", pLibConfig->numChannels); */ } { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tSample rate: %d\n", pLibConfig->sampleRate); */ } { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tMix buffer size: %d\n", pLibConfig->mixBufferSize); */ } if (pLibConfig->filterEnabled) { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tFilter enabled\n"); */ } #ifndef _WIN32_WCE { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tLibrary Build Timestamp: %s", ctime((time_t*)&pLibConfig->buildTimeStamp)); */ } #endif { /* dpp: EAS_ReportEx(_EAS_SEVERITY_INFO, "\tLibrary Build ID: %s\n", pLibConfig->buildGUID); */ } /* check it against the header file used to build this code */ /*lint -e{778} constant expression used for display purposes may evaluate to zero */ if (LIB_VERSION != pLibConfig->libVersion) { { /* dpp: EAS_ReportEx(_EAS_SEVERITY_FATAL, "Library version does not match header files. EAS Header Version %d.%d.%d.%d\n", LIB_VERSION >> 24, (LIB_VERSION >> 16) & 0x0f, (LIB_VERSION >> 8) & 0x0f, LIB_VERSION & 0x0f); */ } return EAS_FALSE; } return EAS_TRUE; } /* end EASLibraryCheck */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/PaxHeaders.32572/eas_wave.h0000644000000000000000000000013213532747316026266 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.930000148 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/eas_wave.h0000644000175000001440000000372713532747316027070 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_wave.h * * Contents and purpose: * Writes output to a .WAV file * * DO NOT MODIFY THIS FILE! * * Copyright Sonic Network Inc. 2005 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ #include "eas_types.h" /* sentinel */ #ifndef _EAS_WAVE_H #define _EAS_WAVE_H /* .WAV file format chunk */ typedef struct { EAS_U16 wFormatTag; EAS_U16 nChannels; EAS_U32 nSamplesPerSec; EAS_U32 nAvgBytesPerSec; EAS_U16 nBlockAlign; EAS_U16 wBitsPerSample; } FMT_CHUNK; /* .WAV file header */ typedef struct { EAS_U32 nRiffTag; EAS_U32 nRiffSize; EAS_U32 nWaveTag; EAS_U32 nFmtTag; EAS_U32 nFmtSize; FMT_CHUNK fc; EAS_U32 nDataTag; EAS_U32 nDataSize; } WAVE_HEADER; typedef struct { WAVE_HEADER wh; FILE *file; EAS_BOOL write; EAS_U32 dataSize; } WAVE_FILE; WAVE_FILE *WaveFileCreate (const char *filename, EAS_I32 nChannels, EAS_I32 nSamplesPerSec, EAS_I32 wBitsPerSample); EAS_I32 WaveFileWrite (WAVE_FILE *wFile, void *buffer, EAS_I32 n); EAS_BOOL WaveFileClose (WAVE_FILE *wFile); WAVE_FILE *WaveFileOpen (const char *filename); #endif /* end #ifndef _EAS_WAVE_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/PaxHeaders.32572/eas_debugmsgs.h0000644000000000000000000000013213532747316027304 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.930000148 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/eas_debugmsgs.h0000644000175000001440000001272313532747316030102 0ustar00pedrousers00000000000000/* Auto-generated from source file: eas_chorusdata.c */ /* Auto-generated from source file: eas_xmfdata.c */ /* Auto-generated from source file: eas_mdls.c */ { 0x19299ed4, 0x00000022, "eas_mdls.c[2561]: #Instruments: %u\n" }, { 0x19299ed4, 0x00000023, "eas_mdls.c[2562]: #Regions: %u\n" }, { 0x19299ed4, 0x00000024, "eas_mdls.c[2563]: #Articulations: %u\n" }, { 0x19299ed4, 0x00000025, "eas_mdls.c[2564]: #Waves: %u\n" }, { 0x19299ed4, 0x00000026, "eas_mdls.c[2569]: Locale: %lu:%lu:%lu\n" }, { 0x19299ed4, 0x00000027, "eas_mdls.c[2576]: \tRegion: %u\n" }, { 0x19299ed4, 0x00000028, "eas_mdls.c[2578]: \t\tm_nGain: %d\n" }, { 0x19299ed4, 0x00000029, "eas_mdls.c[2579]: \t\trangeLow:rangeHigh %u:%u\n" }, { 0x19299ed4, 0x0000002a, "eas_mdls.c[2580]: \t\tm_nKeyGroupAndFlags: %04x\n" }, { 0x19299ed4, 0x0000002b, "eas_mdls.c[2581]: \t\tm_nLoopStart: %u\n" }, { 0x19299ed4, 0x0000002c, "eas_mdls.c[2582]: \t\tm_nLoopEnd: %u\n" }, { 0x19299ed4, 0x0000002d, "eas_mdls.c[2583]: \t\tm_nNetTuningInCents: %d\n" }, { 0x19299ed4, 0x0000002e, "eas_mdls.c[2584]: \t\tArt Index: %u\n" }, { 0x19299ed4, 0x0000002f, "eas_mdls.c[2585]: \t\tWave Index: %u\n" }, { 0x19299ed4, 0x00000030, "eas_mdls.c[2597]: Articulation: %u\n" }, { 0x19299ed4, 0x00000031, "eas_mdls.c[2599]: \t\tm_nEG2toFilterDepth: %d\n" }, { 0x19299ed4, 0x00000032, "eas_mdls.c[2600]: \t\tm_nEG2toPitchDepth: %d\n" }, { 0x19299ed4, 0x00000033, "eas_mdls.c[2601]: \t\tm_nFilterCutoffFrequency: %d\n" }, { 0x19299ed4, 0x00000034, "eas_mdls.c[2602]: \t\tm_nFilterResonance: %u\n" }, { 0x19299ed4, 0x00000035, "eas_mdls.c[2603]: \t\tm_nLFOAmplitudeDepth: %d\n" }, { 0x19299ed4, 0x00000036, "eas_mdls.c[2604]: \t\tm_nLFODelayTime: %d\n" }, { 0x19299ed4, 0x00000037, "eas_mdls.c[2605]: \t\tm_nLFOFrequency: %d\n" }, { 0x19299ed4, 0x00000038, "eas_mdls.c[2606]: \t\tm_nLFOPitchDepth: %d\n" }, { 0x19299ed4, 0x00000039, "eas_mdls.c[2607]: \t\tm_nPan: %d\n" }, { 0x19299ed4, 0x0000003a, "eas_mdls.c[2610]: \t\tm_nAttack: %d\n" }, { 0x19299ed4, 0x0000003b, "eas_mdls.c[2611]: \t\tm_nDecay: %d\n" }, { 0x19299ed4, 0x0000003c, "eas_mdls.c[2612]: \t\tm_nSustain: %d\n" }, { 0x19299ed4, 0x0000003d, "eas_mdls.c[2613]: \t\tm_nRelease: %d\n" }, { 0x19299ed4, 0x0000003e, "eas_mdls.c[2616]: \t\tm_nAttack: %d\n" }, { 0x19299ed4, 0x0000003f, "eas_mdls.c[2617]: \t\tm_nDecay: %d\n" }, { 0x19299ed4, 0x00000040, "eas_mdls.c[2618]: \t\tm_nSustain: %d\n" }, { 0x19299ed4, 0x00000041, "eas_mdls.c[2619]: \t\tm_nRelease: %d\n" }, { 0x19299ed4, 0x00000042, "eas_mdls.c[2626]: Wave Index: %d\n" }, { 0x19299ed4, 0x00000043, "eas_mdls.c[2627]: \tSize %u\n" }, { 0x19299ed4, 0x00000044, "eas_mdls.c[2628]: \tPointer %08lx\n" }, /* Auto-generated from source file: eas_mididata.c */ /* Auto-generated from source file: eas_pan.c */ /* Auto-generated from source file: eas_wavefiledata.c */ /* Auto-generated from source file: eas_reverbdata.c */ /* Auto-generated from source file: eas_imelodydata.c */ /* Auto-generated from source file: eas_ota.c */ /* Auto-generated from source file: eas_mixbuf.c */ /* Auto-generated from source file: eas_tcdata.c */ /* Auto-generated from source file: jet.c */ /* Auto-generated from source file: eas_rtttl.c */ /* Auto-generated from source file: eas_reverb.c */ /* Auto-generated from source file: eas_pcmdata.c */ /* Auto-generated from source file: eas_chorus.c */ /* Auto-generated from source file: eas_math.c */ /* Auto-generated from source file: eas_xmf.c */ /* Auto-generated from source file: eas_smfdata.c */ /* Auto-generated from source file: eas_imelody.c */ /* Auto-generated from source file: eas_dlssynth.c */ /* Auto-generated from source file: eas_public.c */ /* Auto-generated from source file: eas_rtttldata.c */ /* Auto-generated from source file: eas_voicemgt.c */ /* Auto-generated from source file: eas_tonecontrol.c */ /* Auto-generated from source file: eas_wtengine.c */ /* Auto-generated from source file: eas_imaadpcm.c */ { 0x2380b977, 0x00000006, "eas_imaadpcm.c[305]: IMADecoderLocate: Time=%d, samples=%d\n" }, { 0x2380b977, 0x00000007, "eas_imaadpcm.c[328]: IMADecoderLocate: Looped sample, numBlocks=%d, samplesPerLoop=%d, samplesInLastBlock=%d, samples=%d\n" }, { 0x2380b977, 0x00000008, "eas_imaadpcm.c[335]: IMADecoderLocate: Byte location in audio = %d\n" }, { 0x2380b977, 0x00000009, "eas_imaadpcm.c[345]: IMADecoderLocate: bytesLeft = %d\n" }, /* Auto-generated from source file: eas_flog.c */ /* Auto-generated from source file: eas_midi.c */ /* Auto-generated from source file: eas_otadata.c */ /* Auto-generated from source file: eas_ima_tables.c */ /* Auto-generated from source file: eas_data.c */ /* Auto-generated from source file: eas_pcm.c */ /* Auto-generated from source file: eas_mixer.c */ /* Auto-generated from source file: eas_wavefile.c */ /* Auto-generated from source file: eas_wtsynth.c */ /* Auto-generated from source file: eas_smf.c */ /* Auto-generated from source file: eas_wave.c */ /* Auto-generated from source file: eas_hostmm.c */ { 0x1a54b6e8, 0x00000001, "eas_hostmm.c[586]: Vibrate state: %d\n" }, { 0x1a54b6e8, 0x00000002, "eas_hostmm.c[601]: LED state: %d\n" }, { 0x1a54b6e8, 0x00000003, "eas_hostmm.c[616]: Backlight state: %d\n" }, { 0x1a54b6e8, 0x00000004, "eas_hostmm.c[162]: HWMemCpy: bad amount: %d\n" }, { 0x1a54b6e8, 0x00000005, "eas_hostmm.c[179]: HWMemSet: bad amount: %d\n" }, { 0x1a54b6e8, 0x00000006, "eas_hostmm.c[196]: HWMemCmp: bad amount: %d\n" }, /* Auto-generated from source file: eas_config.c */ /* Auto-generated from source file: eas_main.c */ { 0xe624f4d9, 0x00000005, "eas_main.c[106]: Play length: %d.%03d (secs)\n" }, drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/PaxHeaders.32572/eas_config.c0000644000000000000000000000013213532747316026564 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.930000148 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/eas_config.c0000644000175000001440000004031313532747316027356 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_config.c * * Contents and purpose: * This file contains the Configuration Module interface (CM). The CM * is a module compiled external to the library that sets the configuration * for this build. It allows the library to find optional components and * links to static memory allocations (when used in a static configuration). * * DO NOT MODIFY THIS FILE! * * NOTE: This module is not intended to be modified by the customer. It * needs to be included in the build process with the correct configuration * defines (see the library documentation for information on how to configure * the library). * * Copyright Sonic Network Inc. 2004-2006 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 796 $ * $Date: 2007-08-01 00:15:25 -0700 (Wed, 01 Aug 2007) $ *---------------------------------------------------------------------------- */ #include "eas.h" #include "eas_config.h" #ifdef _MFI_PARSER /*---------------------------------------------------------------------------- * Vendor/Device ID for MFi Extensions * * Define the preprocessor symbols to establish the vendor ID and * device ID for the MFi PCM/ADPCM extensions. *---------------------------------------------------------------------------- */ const EAS_U8 eas_MFIVendorIDMSB = (MFI_VENDOR_ID >> 8) & 0xff; const EAS_U8 eas_MFIVendorIDLSB = MFI_VENDOR_ID & 0xff; const EAS_U8 eas_MFIDeviceID = MFI_DEVICE_ID; #endif /*---------------------------------------------------------------------------- * * parserModules * * This structure is used by the EAS library to locate file parsing * modules. *---------------------------------------------------------------------------- */ /* define the external file parsers */ extern EAS_VOID_PTR EAS_SMF_Parser; #ifdef _XMF_PARSER extern EAS_VOID_PTR EAS_XMF_Parser; #endif #ifdef _SMAF_PARSER extern EAS_VOID_PTR EAS_SMAF_Parser; #endif #ifdef _WAVE_PARSER extern EAS_VOID_PTR EAS_Wave_Parser; #endif #ifdef _OTA_PARSER extern EAS_VOID_PTR EAS_OTA_Parser; #endif #ifdef _IMELODY_PARSER extern EAS_VOID_PTR EAS_iMelody_Parser; #endif #ifdef _RTTTL_PARSER extern EAS_VOID_PTR EAS_RTTTL_Parser; #endif #if defined (_CMX_PARSER) || defined(_MFI_PARSER) extern EAS_VOID_PTR EAS_CMF_Parser; #endif /* initalize pointers to parser interfaces */ /*lint -e{605} not pretty, but it works */ EAS_VOID_PTR const parserModules[] = { &EAS_SMF_Parser, #ifdef _XMF_PARSER &EAS_XMF_Parser, #endif #ifdef _WAVE_PARSER &EAS_Wave_Parser, #endif #ifdef _SMAF_PARSER &EAS_SMAF_Parser, #endif #ifdef _OTA_PARSER &EAS_OTA_Parser, #endif #ifdef _IMELODY_PARSER &EAS_iMelody_Parser, #endif #ifdef _RTTTL_PARSER &EAS_RTTTL_Parser, #endif #if defined (_CMX_PARSER) || defined(_MFI_PARSER) &EAS_CMF_Parser #endif }; #define NUM_PARSER_MODULES (sizeof(parserModules) / sizeof(EAS_VOID_PTR)) /*---------------------------------------------------------------------------- * Data Modules *---------------------------------------------------------------------------- */ #ifdef _STATIC_MEMORY extern EAS_VOID_PTR eas_SMFData; extern EAS_VOID_PTR eas_Data; extern EAS_VOID_PTR eas_MixBuffer; extern EAS_VOID_PTR eas_Synth; extern EAS_VOID_PTR eas_MIDI; extern EAS_VOID_PTR eas_PCMData; extern EAS_VOID_PTR eas_MIDIData; #ifdef _XMF_PARSER extern EAS_VOID_PTR eas_XMFData; #endif #ifdef _SMAF_PARSER extern EAS_VOID_PTR eas_SMAFData; #endif #ifdef _OTA_PARSER extern EAS_VOID_PTR eas_OTAData; #endif #ifdef _IMELODY_PARSER extern EAS_VOID_PTR eas_iMelodyData; #endif #ifdef _RTTTL_PARSER extern EAS_VOID_PTR eas_RTTTLData; #endif #ifdef _WAVE_PARSER extern EAS_VOID_PTR eas_WaveData; #endif #if defined (_CMX_PARSER) || defined(_MFI_PARSER) extern EAS_VOID_PTR eas_CMFData; #endif #endif /*---------------------------------------------------------------------------- * * Effects Modules * * These declarations are used by the EAS library to locate * effects modules. *---------------------------------------------------------------------------- */ #ifdef _ENHANCER_ENABLED extern EAS_VOID_PTR EAS_Enhancer; #define EAS_ENHANCER_INTERFACE &EAS_Enhancer #ifdef _STATIC_MEMORY extern EAS_VOID_PTR eas_EnhancerData; #define EAS_ENHANCER_DATA &eas_EnhancerData #else #define EAS_ENHANCER_DATA NULL #endif #else #define EAS_ENHANCER_INTERFACE NULL #define EAS_ENHANCER_DATA NULL #endif #ifdef _COMPRESSOR_ENABLED extern EAS_VOID_PTR EAS_Compressor; #define EAS_COMPRESSOR_INTERFACE &EAS_Compressor #ifdef _STATIC_MEMORY extern EAS_VOID_PTR eas_CompressorData; #define EAS_COMPRESSOR_DATA &eas_CompressorData #else #define EAS_COMPRESSOR_DATA NULL #endif #else #define EAS_COMPRESSOR_INTERFACE NULL #define EAS_COMPRESSOR_DATA NULL #endif #ifdef _MAXIMIZER_ENABLED extern EAS_VOID_PTR EAS_Maximizer; #define EAS_MAXIMIZER_INTERFACE &EAS_Maximizer #ifdef _STATIC_MEMORY extern EAS_VOID_PTR eas_MaximizerData; #define EAS_MAXIMIZER_DATA &eas_MaximizerData #else #define EAS_MAXIMIZER_DATA NULL #endif #else #define EAS_MAXIMIZER_INTERFACE NULL #define EAS_MAXIMIZER_DATA NULL #endif #ifdef _REVERB_ENABLED extern EAS_VOID_PTR EAS_Reverb; #define EAS_REVERB_INTERFACE &EAS_Reverb #ifdef _STATIC_MEMORY extern EAS_VOID_PTR eas_ReverbData; #define EAS_REVERB_DATA &eas_ReverbData #else #define EAS_REVERB_DATA NULL #endif #else #define EAS_REVERB_INTERFACE NULL #define EAS_REVERB_DATA NULL #endif #ifdef _CHORUS_ENABLED extern EAS_VOID_PTR EAS_Chorus; #define EAS_CHORUS_INTERFACE &EAS_Chorus #ifdef _STATIC_MEMORY extern EAS_VOID_PTR eas_ChorusData; #define EAS_CHORUS_DATA &eas_ChorusData #else #define EAS_CHORUS_DATA NULL #endif #else #define EAS_CHORUS_INTERFACE NULL #define EAS_CHORUS_DATA NULL #endif #ifdef _WIDENER_ENABLED extern EAS_VOID_PTR EAS_Widener; #define EAS_WIDENER_INTERFACE &EAS_Widener #ifdef _STATIC_MEMORY extern EAS_VOID_PTR eas_WidenerData; #define EAS_WIDENER_DATA &eas_WidenerData #else #define EAS_WIDENER_DATA NULL #endif #else #define EAS_WIDENER_INTERFACE NULL #define EAS_WIDENER_DATA NULL #endif #ifdef _GRAPHIC_EQ_ENABLED extern EAS_VOID_PTR EAS_GraphicEQ; #define EAS_GRAPHIC_EQ_INTERFACE &EAS_GraphicEQ #ifdef _STATIC_MEMORY extern EAS_VOID_PTR eas_GraphicEQData; #define EAS_GRAPHIC_EQ_DATA &eas_GraphicEQData #else #define EAS_GRAPHIC_EQ_DATA NULL #endif #else #define EAS_GRAPHIC_EQ_INTERFACE NULL #define EAS_GRAPHIC_EQ_DATA NULL #endif #ifdef _WOW_ENABLED extern EAS_VOID_PTR EAS_Wow; #define EAS_WOW_INTERFACE &EAS_Wow #ifdef _STATIC_MEMORY #error "WOW module requires dynamic memory model" #else #define EAS_WOW_DATA NULL #endif #else #define EAS_WOW_INTERFACE NULL #define EAS_WOW_DATA NULL #endif #ifdef _TONECONTROLEQ_ENABLED extern EAS_VOID_PTR EAS_ToneControlEQ; #define EAS_TONECONTROLEQ_INTERFACE &EAS_ToneControlEQ #ifdef _STATIC_MEMORY extern EAS_VOID_PTR eas_ToneControlEQData; #define EAS_TONECONTROLEQ_DATA &eas_ToneControlEQData #else #define EAS_TONECONTROLEQ_DATA NULL #endif #else #define EAS_TONECONTROLEQ_INTERFACE NULL #define EAS_TONECONTROLEQ_DATA NULL #endif /*lint -e{605} not pretty, but it works */ EAS_VOID_PTR const effectsModules[] = { EAS_ENHANCER_INTERFACE, EAS_COMPRESSOR_INTERFACE, EAS_REVERB_INTERFACE, EAS_CHORUS_INTERFACE, EAS_WIDENER_INTERFACE, EAS_GRAPHIC_EQ_INTERFACE, EAS_WOW_INTERFACE, EAS_MAXIMIZER_INTERFACE, EAS_TONECONTROLEQ_INTERFACE }; EAS_VOID_PTR const effectsData[] = { EAS_ENHANCER_DATA, EAS_COMPRESSOR_DATA, EAS_REVERB_DATA, EAS_CHORUS_DATA, EAS_WIDENER_DATA, EAS_GRAPHIC_EQ_DATA, EAS_WOW_DATA, EAS_MAXIMIZER_DATA, EAS_TONECONTROLEQ_DATA }; /*---------------------------------------------------------------------------- * * Optional Modules * * These declarations are used by the EAS library to locate * effects modules. *---------------------------------------------------------------------------- */ #ifdef _METRICS_ENABLED extern EAS_VOID_PTR EAS_Metrics; #define EAS_METRICS_INTERFACE &EAS_Metrics #ifdef _STATIC_MEMORY extern EAS_VOID_PTR eas_MetricsData; #define EAS_METRICS_DATA &eas_MetricsData #else #define EAS_METRICS_DATA NULL #endif #else #define EAS_METRICS_INTERFACE NULL #define EAS_METRICS_DATA NULL #endif #ifdef MMAPI_SUPPORT extern EAS_VOID_PTR EAS_TC_Parser; #define EAS_TONE_CONTROL_PARSER &EAS_TC_Parser #ifdef _STATIC_MEMORY extern EAS_VOID_PTR eas_TCData; #define EAS_TONE_CONTROL_DATA &eas_TCData #else #define EAS_TONE_CONTROL_DATA NULL #endif #else #define EAS_TONE_CONTROL_PARSER NULL #define EAS_TONE_CONTROL_DATA NULL #endif /*lint -e{605} not pretty, but it works */ EAS_VOID_PTR const optionalModules[] = { EAS_TONE_CONTROL_PARSER, EAS_METRICS_INTERFACE }; EAS_VOID_PTR const optionalData[] = { EAS_TONE_CONTROL_DATA, EAS_METRICS_DATA }; /*---------------------------------------------------------------------------- * EAS_CMStaticMemoryModel() *---------------------------------------------------------------------------- * Purpose: * This function returns true if EAS has been configured for * a static memory model. There are some limitations in the * static memory model, see the documentation for more * information. * * Outputs: * returns EAS_TRUE if a module is found *---------------------------------------------------------------------------- */ EAS_BOOL EAS_CMStaticMemoryModel (void) { #ifdef _STATIC_MEMORY return EAS_TRUE; #else return EAS_FALSE; #endif } /*---------------------------------------------------------------------------- * EAS_CMEnumModules() *---------------------------------------------------------------------------- * Purpose: * This function is used to find pointers to optional modules. * * Inputs: * module - module number * * Outputs: * returns a pointer to the module function table or NULL if no module *---------------------------------------------------------------------------- */ EAS_VOID_PTR EAS_CMEnumModules (EAS_INT module) { if (module >= (EAS_INT) NUM_PARSER_MODULES) return NULL; return parserModules[module]; } /*---------------------------------------------------------------------------- * EAS_CMEnumData() *---------------------------------------------------------------------------- * Purpose: * This function is used to find pointers to static memory allocations. * * Inputs: * dataModule - enumerated module number * * Outputs: * Returns handle to data or NULL if not found *---------------------------------------------------------------------------- */ /*lint -esym(715, dataModule) used only when _STATIC_MEMORY is defined */ EAS_VOID_PTR EAS_CMEnumData (EAS_INT dataModule) { #ifdef _STATIC_MEMORY switch (dataModule) { /* main instance data for synthesizer */ case EAS_CM_EAS_DATA: return &eas_Data; /* mix buffer for mix engine */ case EAS_CM_MIX_BUFFER: /*lint -e{545} lint doesn't like this because it sees the underlying type */ return &eas_MixBuffer; /* instance data for synth */ case EAS_CM_SYNTH_DATA: return &eas_Synth; /* instance data for MIDI parser */ case EAS_CM_MIDI_DATA: return &eas_MIDI; /* instance data for SMF parser */ case EAS_CM_SMF_DATA: return &eas_SMFData; #ifdef _XMF_PARSER /* instance data for XMF parser */ case EAS_CM_XMF_DATA: return &eas_XMFData; #endif #ifdef _SMAF_PARSER /* instance data for SMAF parser */ case EAS_CM_SMAF_DATA: return &eas_SMAFData; #endif /* instance data for the PCM engine */ case EAS_CM_PCM_DATA: /*lint -e{545} lint doesn't like this because it sees the underlying type */ return &eas_PCMData; case EAS_CM_MIDI_STREAM_DATA: return &eas_MIDIData; #ifdef _OTA_PARSER /* instance data for OTA parser */ case EAS_CM_OTA_DATA: return &eas_OTAData; #endif #ifdef _IMELODY_PARSER /* instance data for iMelody parser */ case EAS_CM_IMELODY_DATA: return &eas_iMelodyData; #endif #ifdef _RTTTL_PARSER /* instance data for RTTTL parser */ case EAS_CM_RTTTL_DATA: return &eas_RTTTLData; #endif #ifdef _WAVE_PARSER /* instance data for WAVE parser */ case EAS_CM_WAVE_DATA: return &eas_WaveData; #endif #if defined (_CMX_PARSER) || defined(_MFI_PARSER) /* instance data for CMF parser */ case EAS_CM_CMF_DATA: return &eas_CMFData; #endif default: return NULL; } #else return NULL; #endif } /*---------------------------------------------------------------------------- * EAS_CMEnumFXModules() *---------------------------------------------------------------------------- * Purpose: * This function is used to find pointers to optional effects modules. * * Inputs: * module - enumerated module number * pModule - pointer to module interface * * Outputs: * Returns pointer to function table or NULL if not found *---------------------------------------------------------------------------- */ EAS_VOID_PTR EAS_CMEnumFXModules (EAS_INT module) { if (module >= NUM_EFFECTS_MODULES) return NULL; return effectsModules[module]; } /*---------------------------------------------------------------------------- * EAS_CMEnumFXData() *---------------------------------------------------------------------------- * Purpose: * This function is used to find pointers to static memory allocations. * * Inputs: * dataModule - enumerated module number * pData - pointer to handle variable * * Outputs: * Returns handle to data or NULL if not found *---------------------------------------------------------------------------- */ EAS_VOID_PTR EAS_CMEnumFXData (EAS_INT dataModule) { if (dataModule >= NUM_EFFECTS_MODULES) return NULL; return effectsData[dataModule]; } /*---------------------------------------------------------------------------- * EAS_CMEnumOptModules() *---------------------------------------------------------------------------- * Purpose: * This function is used to find pointers to optional modules. * * Inputs: * module - enumerated module number * * Outputs: * returns pointer to function table or NULL if no module *---------------------------------------------------------------------------- */ EAS_VOID_PTR EAS_CMEnumOptModules (EAS_INT module) { /* sanity check */ if (module >= NUM_OPTIONAL_MODULES) return EAS_FALSE; return optionalModules[module]; } /*---------------------------------------------------------------------------- * EAS_CMEnumOptData() *---------------------------------------------------------------------------- * Purpose: * This function is used to find pointers to static memory allocations. * * Inputs: * dataModule - enumerated module number * * Outputs: * Returns handle to data or NULL if not found *---------------------------------------------------------------------------- */ EAS_VOID_PTR EAS_CMEnumOptData (EAS_INT dataModule) { if (dataModule >= NUM_OPTIONAL_MODULES) return NULL; return optionalData[dataModule]; } drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/PaxHeaders.32572/eas.h0000644000000000000000000000013213532747316025244 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.930000148 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/eas.h0000644000175000001440000011002013532747316026027 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas.h * * Contents and purpose: * The public interface header for the EAS synthesizer. * * This header only contains declarations that are specific * to this implementation. * * DO NOT MODIFY THIS FILE! * * Copyright Sonic Network Inc. 2005, 2006 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 852 $ * $Date: 2007-09-04 11:43:49 -0700 (Tue, 04 Sep 2007) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_H #define _EAS_H #include "eas_types.h" /* for C++ linkage */ #ifdef __cplusplus extern "C" { #endif /* library version macro */ #define MAKE_LIB_VERSION(a,b,c,d) (((((((EAS_U32) a <<8) | (EAS_U32) b) << 8) | (EAS_U32) c) << 8) | (EAS_U32) d) #define LIB_VERSION MAKE_LIB_VERSION(3, 6, 10, 14) typedef struct { EAS_U32 libVersion; EAS_BOOL checkedVersion; EAS_I32 maxVoices; EAS_I32 numChannels; EAS_I32 sampleRate; EAS_I32 mixBufferSize; EAS_BOOL filterEnabled; EAS_U32 buildTimeStamp; EAS_CHAR *buildGUID; } S_EAS_LIB_CONFIG; /* enumerated effects module numbers for configuration */ typedef enum { EAS_MODULE_ENHANCER = 0, EAS_MODULE_COMPRESSOR, EAS_MODULE_REVERB, EAS_MODULE_CHORUS, EAS_MODULE_WIDENER, EAS_MODULE_GRAPHIC_EQ, EAS_MODULE_WOW, EAS_MODULE_MAXIMIZER, EAS_MODULE_TONECONTROLEQ, NUM_EFFECTS_MODULES } E_FX_MODULES; /* enumerated optional module numbers for configuration */ typedef enum { EAS_MODULE_MMAPI_TONE_CONTROL = 0, EAS_MODULE_METRICS } E_OPT_MODULES; #define NUM_OPTIONAL_MODULES 2 /* enumerated audio decoders for configuration */ typedef enum { EAS_DECODER_PCM = 0, EAS_DECODER_SMAF_ADPCM, EAS_DECODER_IMA_ADPCM, EAS_DECODER_7BIT_SMAF_ADPCM, EAS_DECODER_NOT_SUPPORTED } E_DECODER_MODULES; #define NUM_DECODER_MODULES 4 /* defines for EAS_PEOpenStream flags parameter */ #define PCM_FLAGS_STEREO 0x00000100 /* stream is stereo */ #define PCM_FLAGS_8_BIT 0x00000001 /* 8-bit format */ #define PCM_FLAGS_UNSIGNED 0x00000010 /* unsigned format */ #define PCM_FLAGS_STREAMING 0x80000000 /* streaming mode */ /* maximum volume setting */ #define EAS_MAX_VOLUME 100 /*---------------------------------------------------------------------------- * EAS_Init() *---------------------------------------------------------------------------- * Purpose: * Initialize the synthesizer library * * Inputs: * polyphony - number of voices to play (dynamic memory model only) * ppLibData - pointer to data handle variable for this instance * * Outputs: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_Init (EAS_DATA_HANDLE *ppEASData); /*---------------------------------------------------------------------------- * EAS_Config() *---------------------------------------------------------------------------- * Purpose: * Returns a pointer to a structure containing the configuration options * in this library build. * * Inputs: * * Outputs: * *---------------------------------------------------------------------------- */ EAS_PUBLIC const S_EAS_LIB_CONFIG *EAS_Config (void); /*---------------------------------------------------------------------------- * EAS_Shutdown() *---------------------------------------------------------------------------- * Purpose: * Shuts down the library. Deallocates any memory associated with the * synthesizer (dynamic memory model only) * * Inputs: * pEASData - handle to data for this instance * * Outputs: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_Shutdown (EAS_DATA_HANDLE pEASData); /*---------------------------------------------------------------------------- * EAS_Render() *---------------------------------------------------------------------------- * Purpose: * Parse the Midi data and render PCM audio data. * * Inputs: * pEASData - buffer for internal EAS data * pOut - output buffer pointer * nNumRequested - requested num samples to generate * pnNumGenerated - actual number of samples generated * * Outputs: * EAS_SUCCESS if PCM data was successfully rendered * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_Render (EAS_DATA_HANDLE pEASData, EAS_PCM *pOut, EAS_I32 numRequested, EAS_I32 *pNumGenerated); /*---------------------------------------------------------------------------- * EAS_SetRepeat() *---------------------------------------------------------------------------- * Purpose: * Set the selected stream to repeat. * * Inputs: * pEASData - handle to data for this instance * streamHandle - handle to stream * repeatCount - repeat count (0 = no repeat, -1 = repeat forever) * * Outputs: * * Side Effects: * * Notes: * 0 = no repeat * 1 = repeat once, i.e. play through twice * -1 = repeat forever *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 repeatCount); /*---------------------------------------------------------------------------- * EAS_GetRepeat() *---------------------------------------------------------------------------- * Purpose: * Gets the current repeat count for the selected stream. * * Inputs: * pEASData - handle to data for this instance * streamHandle - handle to stream * pRrepeatCount - pointer to variable to hold repeat count * * Outputs: * * Side Effects: * * Notes: * 0 = no repeat * 1 = repeat once, i.e. play through twice * -1 = repeat forever *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetRepeat (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pRepeatCount); /*---------------------------------------------------------------------------- * EAS_SetPlaybackRate() *---------------------------------------------------------------------------- * Purpose: * Set the playback rate. * * Inputs: * pEASData - handle to data for this instance * streamHandle - handle to stream * rate - rate (28-bit fractional amount) * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetPlaybackRate (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U32 rate); #define MAX_PLAYBACK_RATE (EAS_U32)(1L << 29) #define MIN_PLAYBACK_RATE (EAS_U32)(1L << 27) /*---------------------------------------------------------------------------- * EAS_SetTransposition) *---------------------------------------------------------------------------- * Purpose: * Sets the key tranposition for the synthesizer. Transposes all * melodic instruments by the specified amount. Range is limited * to +/-12 semitones. * * Inputs: * pEASData - handle to data for this instance * streamHandle - handle to stream * transposition - +/-12 semitones * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetTransposition (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 transposition); #define MAX_TRANSPOSE 12 /*---------------------------------------------------------------------------- * EAS_SetSynthPolyphony() *---------------------------------------------------------------------------- * Purpose: * Set the polyphony of the synthesizer. Value must be >= 1 and <= the * maximum number of voices. This function will pin the polyphony * at those limits * * Inputs: * pEASData - pointer to overall EAS data structure * synthNum - synthesizer number (0 = onboard, 1 = DSP) * polyphonyCount - the desired polyphony count * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 polyphonyCount); /*---------------------------------------------------------------------------- * EAS_GetSynthPolyphony() *---------------------------------------------------------------------------- * Purpose: * Returns the current polyphony setting of the synthesizer * * Inputs: * pEASData - pointer to overall EAS data structure * synthNum - synthesizer number (0 = onboard, 1 = DSP) * pPolyphonyCount - pointer to variable to receive polyphony count * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetSynthPolyphony (EAS_DATA_HANDLE pEASData, EAS_I32 synthNum, EAS_I32 *pPolyphonyCount); /*---------------------------------------------------------------------------- * EAS_SetPolyphony() *---------------------------------------------------------------------------- * Purpose: * Set the polyphony of the stream. Value must be >= 1 and <= the * maximum number of voices. This function will pin the polyphony * at those limits * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - handle returned by EAS_OpenFile * polyphonyCount - the desired polyphony count * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 polyphonyCount); /*---------------------------------------------------------------------------- * EAS_GetPolyphony() *---------------------------------------------------------------------------- * Purpose: * Returns the current polyphony setting of the stream * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - handle returned by EAS_OpenFile * pPolyphonyCount - pointer to variable to receive polyphony count * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetPolyphony (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pPolyphonyCount); /*---------------------------------------------------------------------------- * EAS_SetPriority() *---------------------------------------------------------------------------- * Purpose: * Set the priority of the stream. Determines which stream's voices * are stolen when there are insufficient voices for all notes. * Value must be in the range of 1-255, lower values are higher * priority. The default priority is 50. * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - handle returned by EAS_OpenFile * polyphonyCount - the desired polyphony count * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 priority); /*---------------------------------------------------------------------------- * EAS_GetPriority() *---------------------------------------------------------------------------- * Purpose: * Returns the current priority setting of the stream * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - handle returned by EAS_OpenFile * pPriority - pointer to variable to receive priority * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetPriority (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pPriority); /*---------------------------------------------------------------------------- * EAS_SetVolume() *---------------------------------------------------------------------------- * Purpose: * Set the master volume for the mixer. The default volume setting is * 90 (-10 dB). The volume range is 0 to 100 in 1dB increments. * * Inputs: * pEASData - pointer to overall EAS data structure * volume - the desired master volume * * Outputs: * * * Side Effects: * overrides any previously set master volume from sysex * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 volume); /*---------------------------------------------------------------------------- * EAS_GetVolume() *---------------------------------------------------------------------------- * Purpose: * Returns the master volume for the mixer in 1dB increments. * * Inputs: * pEASData - pointer to overall EAS data structure * volume - the desired master volume * * Outputs: * * * Side Effects: * overrides any previously set master volume from sysex * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_I32 EAS_GetVolume (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); /*---------------------------------------------------------------------------- * EAS_SetMaxLoad() *---------------------------------------------------------------------------- * Purpose: * Sets the maximum workload the parsers will do in a single call to * EAS_Render. The units are currently arbitrary, but should correlate * well to the actual CPU cycles consumed. The primary effect is to * reduce the occasional peaks in CPU cycles consumed when parsing * dense parts of a MIDI score. Setting maxWorkLoad to zero disables * the workload limiting function. * * Inputs: * pEASData - handle to data for this instance * maxLoad - the desired maximum workload * * Outputs: * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetMaxLoad (EAS_DATA_HANDLE pEASData, EAS_I32 maxLoad); /*---------------------------------------------------------------------------- * EAS_SetMaxPCMStreams() *---------------------------------------------------------------------------- * Sets the maximum number of PCM streams allowed in parsers that * use PCM streaming. * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - handle returned by EAS_OpenFile * maxNumStreams - maximum number of PCM streams *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetMaxPCMStreams (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 maxNumStreams); /*---------------------------------------------------------------------------- * EAS_OpenFile() *---------------------------------------------------------------------------- * Purpose: * Opens a file for audio playback. * * Inputs: * pEASData - pointer to overall EAS data structure * locator - pointer to filename or other locating information * pStreamHandle - pointer to stream handle variable * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_OpenFile (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *pStreamHandle); #ifdef MMAPI_SUPPORT /*---------------------------------------------------------------------------- * EAS_MMAPIToneControl() *---------------------------------------------------------------------------- * Purpose: * Opens a ToneControl file for audio playback. * * Inputs: * pEASData - pointer to overall EAS data structure * locator - pointer to filename or other locating information * pStreamHandle - pointer to stream handle variable * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_MMAPIToneControl (EAS_DATA_HANDLE pEASData, EAS_FILE_LOCATOR locator, EAS_HANDLE *pStreamHandle); /*---------------------------------------------------------------------------- * EAS_GetWaveFmtChunk *---------------------------------------------------------------------------- * Helper function to retrieve WAVE file fmt chunk for MMAPI *---------------------------------------------------------------------------- * pEASData - pointer to EAS persistent data object * streamHandle - stream handle * pFmtChunk - pointer to pointer to FMT chunk data *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetWaveFmtChunk (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_VOID_PTR *ppFmtChunk); #endif /*---------------------------------------------------------------------------- * EAS_GetFileType *---------------------------------------------------------------------------- * Returns the file type (see eas_types.h for enumerations) *---------------------------------------------------------------------------- * pEASData - pointer to EAS persistent data object * streamHandle - stream handle * pFileType - pointer to variable to receive file type *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetFileType (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pFileType); /*---------------------------------------------------------------------------- * EAS_ParseMetaData() *---------------------------------------------------------------------------- * Purpose: * * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - file or stream handle * playLength - pointer to variable to store the play length (in msecs) * * Outputs: * * * Side Effects: * - resets the parser to the start of the file *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_ParseMetaData (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pPlayLength); /*---------------------------------------------------------------------------- * EAS_Prepare() *---------------------------------------------------------------------------- * Purpose: * Prepares the synthesizer to play the file or stream. Parses the first * frame of data from the file and arms the synthesizer. * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - file or stream handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_Prepare (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); /*---------------------------------------------------------------------------- * EAS_State() *---------------------------------------------------------------------------- * Purpose: * Returns the state of an audio file or stream. * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - file or stream handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_State (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_STATE *pState); /*---------------------------------------------------------------------------- * EAS_RegisterMetaDataCallback() *---------------------------------------------------------------------------- * Purpose: * Registers a metadata callback function for parsed metadata. To * de-register the callback, call this function again with parameter * cbFunc set to NULL. * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - file or stream handle * cbFunc - pointer to host callback function * metaDataBuffer - pointer to metadata buffer * metaDataBufSize - maximum size of the metadata buffer * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_RegisterMetaDataCallback ( EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_METADATA_CBFUNC cbFunc, char *metaDataBuffer, EAS_I32 metaDataBufSize, EAS_VOID_PTR pUserData); /*---------------------------------------------------------------------------- * EAS_GetNoteCount () *---------------------------------------------------------------------------- * Returns the total number of notes played in this stream * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - file or stream handle * pNoteCount - pointer to variable to receive note count *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetNoteCount (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 *pNoteCount); /*---------------------------------------------------------------------------- * EAS_CloseFile() *---------------------------------------------------------------------------- * Purpose: * Closes an audio file or stream. Playback should have either paused or * completed (EAS_State returns EAS_PAUSED or EAS_STOPPED). * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - file or stream handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_CloseFile (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); /*---------------------------------------------------------------------------- * EAS_OpenMIDIStream() *---------------------------------------------------------------------------- * Purpose: * Opens a raw MIDI stream allowing the host to route MIDI cable data directly to the synthesizer * * Inputs: * pEASData - pointer to overall EAS data structure * pStreamHandle - pointer to variable to hold file or stream handle * streamHandle - open stream or NULL for new synthesizer instance * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_OpenMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE *pStreamHandle, EAS_HANDLE streamHandle); /*---------------------------------------------------------------------------- * EAS_WriteMIDIStream() *---------------------------------------------------------------------------- * Purpose: * Send data to the MIDI stream device * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - stream handle * pBuffer - pointer to buffer * count - number of bytes to write * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_WriteMIDIStream(EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U8 *pBuffer, EAS_I32 count); /*---------------------------------------------------------------------------- * EAS_CloseMIDIStream() *---------------------------------------------------------------------------- * Purpose: * Closes a raw MIDI stream * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - stream handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_CloseMIDIStream (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); /*---------------------------------------------------------------------------- * EAS_Locate() *---------------------------------------------------------------------------- * Purpose: * Locate into the file associated with the handle. * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - file handle * milliseconds - playback offset from start of file in milliseconds * * Outputs: * * * Side Effects: * the actual offset will be quantized to the closest update period, typically * a resolution of 5.9ms. Notes that are started prior to this time will not * sound. Any notes currently playing will be shut off. * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_Locate (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 milliseconds, EAS_BOOL offset); /*---------------------------------------------------------------------------- * EAS_GetRenderTime() *---------------------------------------------------------------------------- * Purpose: * Returns the current playback offset * * Inputs: * pEASData - pointer to overall EAS data structure * * Outputs: * Gets the render time clock in msecs. * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetRenderTime (EAS_DATA_HANDLE pEASData, EAS_I32 *pTime); /*---------------------------------------------------------------------------- * EAS_GetLocation() *---------------------------------------------------------------------------- * Purpose: * Returns the current playback offset * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - file handle * * Outputs: * The offset in milliseconds from the start of the current sequence, quantized * to the nearest update period. Actual resolution is typically 5.9 ms. * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetLocation (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_I32 *pTime); /*---------------------------------------------------------------------------- * EAS_Pause() *---------------------------------------------------------------------------- * Purpose: * Pauses the playback of the data associated with this handle. The audio * is gracefully ramped down to prevent clicks and pops. It may take several * buffers of audio before the audio is muted. * * Inputs: * psEASData - pointer to overall EAS data structure * streamHandle - file or stream handle * * Outputs: * * * Side Effects: * * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_Pause (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); /*---------------------------------------------------------------------------- * EAS_Resume() *---------------------------------------------------------------------------- * Purpose: * Resumes the playback of the data associated with this handle. The audio * is gracefully ramped up to prevent clicks and pops. * * Inputs: * psEASData - pointer to overall EAS data structure * streamHandle - file or stream handle * * Outputs: * * * Side Effects: * * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_Resume (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle); /*---------------------------------------------------------------------------- * EAS_GetParameter() *---------------------------------------------------------------------------- * Purpose: * Set the parameter of a module. See E_MODULES for a list of modules * and the header files of the modules for a list of parameters. * * Inputs: * psEASData - pointer to overall EAS data structure * module - enumerated module number * param - enumerated parameter number * pValue - pointer to variable to receive parameter value * * Outputs: * * * Side Effects: * * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 *pValue); /*---------------------------------------------------------------------------- * EAS_SetParameter() *---------------------------------------------------------------------------- * Purpose: * Set the parameter of a module. See E_MODULES for a list of modules * and the header files of the modules for a list of parameters. * * Inputs: * psEASData - pointer to overall EAS data structure * handle - file or stream handle * module - enumerated module number * param - enumerated parameter number * value - new parameter value * * Outputs: * * * Side Effects: * * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetParameter (EAS_DATA_HANDLE pEASData, EAS_I32 module, EAS_I32 param, EAS_I32 value); #ifdef _METRICS_ENABLED /*---------------------------------------------------------------------------- * EAS_MetricsReport() *---------------------------------------------------------------------------- * Purpose: * Displays the current metrics through the EAS_Report interface. * * Inputs: * pEASData - instance data handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_MetricsReport (EAS_DATA_HANDLE pEASData); /*---------------------------------------------------------------------------- * EAS_MetricsReset() *---------------------------------------------------------------------------- * Purpose: * Displays the current metrics through the EAS_Report interface. * * Inputs: * pEASData - instance data handle * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_MetricsReset (EAS_DATA_HANDLE pEASData); #endif /*---------------------------------------------------------------------------- * EAS_SetSoundLibrary() *---------------------------------------------------------------------------- * Purpose: * Sets the location of the sound library. * * Inputs: * pEASData - instance data handle * streamHandle - file or stream handle * pSoundLib - pointer to sound library * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetSoundLibrary (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_SNDLIB_HANDLE pSndLib); /*---------------------------------------------------------------------------- * EAS_SetHeaderSearchFlag() *---------------------------------------------------------------------------- * By default, when EAS_OpenFile is called, the parsers check the * first few bytes of the file looking for a specific header. Some * mobile devices may add a header to the start of a file, which * will prevent the parser from recognizing the file. If the * searchFlag is set to EAS_TRUE, the parser will search the entire * file looking for the header. This may enable EAS to recognize * some files that it would ordinarily reject. The negative is that * it make take slightly longer to process the EAS_OpenFile request. * * Inputs: * pEASData - instance data handle * searchFlag - search flag (EAS_TRUE or EAS_FALSE) *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetHeaderSearchFlag (EAS_DATA_HANDLE pEASData, EAS_BOOL searchFlag); /*---------------------------------------------------------------------------- * EAS_SetPlayMode() *---------------------------------------------------------------------------- * Some file formats support special play modes, such as iMode partial * play mode. This call can be used to change the play mode. The * default play mode (usually straight playback) is always zero. * * Inputs: * pEASData - instance data handle * handle - file or stream handle * playMode - play mode (see eas_types.h for enumerations) *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetPlayMode (EAS_DATA_HANDLE pEASData, EAS_HANDLE pStream, EAS_I32 playMode); #ifdef DLS_SYNTHESIZER /*---------------------------------------------------------------------------- * EAS_LoadDLSCollection() *---------------------------------------------------------------------------- * Purpose: * Downloads a DLS collection * * Inputs: * pEASData - instance data handle * streamHandle - file or stream handle * locator - file locator * * Outputs: * * * Side Effects: * May overlay instruments in the GM sound set * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_LoadDLSCollection (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_FILE_LOCATOR locator); #endif /*---------------------------------------------------------------------------- * EAS_SetFrameBuffer() *---------------------------------------------------------------------------- * Purpose: * Sets the frame buffer pointer passed to the IPC communications functions * * Inputs: * pEASData - instance data handle * locator - file locator * * Outputs: * * * Side Effects: * May overlay instruments in the GM sound set * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_SetFrameBuffer (EAS_DATA_HANDLE pEASData, EAS_FRAME_BUFFER_HANDLE pFrameBuffer); #ifdef EXTERNAL_AUDIO /*---------------------------------------------------------------------------- * EAS_RegExtAudioCallback() *---------------------------------------------------------------------------- * Purpose: * Registers callback functions for audio events. * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - file or stream handle * cbProgChgFunc - pointer to host callback function for program change * cbEventFunc - pointer to host callback functio for note events * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_RegExtAudioCallback (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_VOID_PTR pInstData, EAS_EXT_PRG_CHG_FUNC cbProgChgFunc, EAS_EXT_EVENT_FUNC cbEventFunc); /*---------------------------------------------------------------------------- * EAS_GetMIDIControllers() *---------------------------------------------------------------------------- * Purpose: * Returns the current state of MIDI controllers on the requested channel. * * Inputs: * pEASData - pointer to overall EAS data structure * streamHandle - file or stream handle * pControl - pointer to structure to receive data * * Outputs: * * * Side Effects: * *---------------------------------------------------------------------------- */ EAS_PUBLIC EAS_RESULT EAS_GetMIDIControllers (EAS_DATA_HANDLE pEASData, EAS_HANDLE streamHandle, EAS_U8 channel, S_MIDI_CONTROLLERS *pControl); #endif /*---------------------------------------------------------------------------- * EAS_SearchFile *---------------------------------------------------------------------------- * Search file for specific sequence starting at current file * position. Returns offset to start of sequence. * * Inputs: * pEASData - pointer to EAS persistent data object * fileHandle - file handle * searchString - pointer to search sequence * len - length of search sequence * pOffset - pointer to variable to store offset to sequence * * Returns EAS_EOF if end-of-file is reached *---------------------------------------------------------------------------- */ EAS_RESULT EAS_SearchFile (EAS_DATA_HANDLE pEASData, EAS_FILE_HANDLE fileHandle, const EAS_U8 *searchString, EAS_I32 len, EAS_I32 *pOffset); #ifdef __cplusplus } /* end extern "C" */ #endif #endif /* #ifndef _EAS_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/PaxHeaders.32572/eas_report.h0000644000000000000000000000013213532747316026637 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.930000148 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/eas_report.h0000644000175000001440000000421113532747316027426 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_report.h * * Contents and purpose: * This file contains the debug message handling routines for the EAS library. * These routines should be modified as needed for your system. * * DO NOT MODIFY THIS FILE! * * Copyright 2005 Sonic Network Inc. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ /* sentinel */ #ifndef _EAS_REPORT_H #define _EAS_REPORT_H #define _EAS_SEVERITY_NOFILTER 0 #define _EAS_SEVERITY_FATAL 1 #define _EAS_SEVERITY_ERROR 2 #define _EAS_SEVERITY_WARNING 3 #define _EAS_SEVERITY_INFO 4 #define _EAS_SEVERITY_DETAIL 5 /* for C++ linkage */ #ifdef __cplusplus extern "C" { #endif #ifndef _NO_DEBUG_PREPROCESSOR /* structure for included debug message header files */ typedef struct { unsigned long m_nHashCode; int m_nSerialNum; char *m_pDebugMsg; } S_DEBUG_MESSAGES; /* debug message handling prototypes */ extern void EAS_ReportEx (int severity, unsigned long hashCode, int serialNum, ...); #else /* these prototypes are used if the debug preprocessor is not used */ extern void EAS_Report (int severity, const char* fmt, ...); extern void EAS_ReportX (int severity, const char* fmt, ...); #endif extern void EAS_SetDebugLevel (int severity); extern void EAS_SetDebugFile (void *file, int flushAfterWrite); #ifdef __cplusplus } /* end extern "C" */ #endif #endif drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/PaxHeaders.32572/eas_reverb.h0000644000000000000000000000013213532747316026611 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.930000148 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/eas_reverb.h0000644000175000001440000000271113532747316027403 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_reverb.h * * Contents and purpose: * Contains parameter enumerations for the Reverb effect * * * Copyright Sonic Network Inc. 2006 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 300 $ * $Date: 2006-09-11 17:37:20 -0700 (Mon, 11 Sep 2006) $ *---------------------------------------------------------------------------- */ #ifndef _EAS_REVERB_H #define _EAS_REVERB_H /* enumerated parameter settings for Reverb effect */ typedef enum { EAS_PARAM_REVERB_BYPASS, EAS_PARAM_REVERB_PRESET, EAS_PARAM_REVERB_WET, EAS_PARAM_REVERB_DRY } E_REVERB_PARAMS; typedef enum { EAS_PARAM_REVERB_LARGE_HALL, EAS_PARAM_REVERB_HALL, EAS_PARAM_REVERB_CHAMBER, EAS_PARAM_REVERB_ROOM, } E_REVERB_PRESETS; #endif /* _REVERB_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/PaxHeaders.32572/eas_build.h0000644000000000000000000000013213532747316026423 xustar0030 mtime=1567346382.697999849 30 atime=1567346382.930000148 30 ctime=1567346382.697999849 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/eas_build.h0000644000175000001440000000242013532747316027212 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * host_src\eas_build.h * * Contents and purpose: * This file contains the build configuration for this * build. The buildGUIDStr is a GUID created during * the build process and is guaranteed to be unique * for each build. * * Copyright Sonic Network Inc. 2006 * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file was autogenerated by buildid.exe *---------------------------------------------------------------------------- */ #ifndef _GUID_1feda229b9a845e996f473c0a80e7220_ #define _GUID_1feda229b9a845e996f473c0a80e7220_ #define _BUILD_VERSION_ "1feda229-b9a8-45e9-96f4-73c0a80e7220" #define _BUILD_TIME_ 0x4743badd #endif /* _GUID_1feda229b9a845e996f473c0a80e7220_ */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/PaxHeaders.32572/eas_config.h0000644000000000000000000000013213532747316026571 xustar0030 mtime=1567346382.701999855 30 atime=1567346382.930000148 30 ctime=1567346382.701999855 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/host_src/eas_config.h0000644000175000001440000001421013532747316027360 0ustar00pedrousers00000000000000/*---------------------------------------------------------------------------- * * File: * eas_config.h * * Contents and purpose: * This header declares the Configuration Module interface (CM). The CM * is a module compiled external to the library that sets the configuration * for this build. It allows the library to find optional components and * links to static memory allocations (when used in a static configuration). * * NOTE: This module is not intended to be modified by the customer. It * needs to be included in the build process with the correct configuration * defines (see the library documentation for information on how to configure * the library). * * DO NOT MODIFY THIS FILE! * * Copyright 2005 Sonic Network Inc. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *---------------------------------------------------------------------------- * Revision Control: * $Revision: 82 $ * $Date: 2006-07-10 11:45:19 -0700 (Mon, 10 Jul 2006) $ *---------------------------------------------------------------------------- */ // sentinel #ifndef _EAS_CONFIG_H #define _EAS_CONFIG_H #include "eas_types.h" /* list of enumerators for optional modules */ typedef enum { EAS_CM_FILE_PARSERS = 1 } E_CM_ENUM_MODULES; /* list of enumerators for module and memory pointers */ typedef enum { EAS_CM_EAS_DATA = 1, EAS_CM_MIX_BUFFER, EAS_CM_SYNTH_DATA, EAS_CM_MIDI_DATA, EAS_CM_SMF_DATA, EAS_CM_XMF_DATA, EAS_CM_SMAF_DATA, EAS_CM_PCM_DATA, EAS_CM_MIDI_STREAM_DATA, EAS_CM_METRICS_DATA, EAS_CM_OTA_DATA, EAS_CM_IMELODY_DATA, EAS_CM_RTTTL_DATA, EAS_CM_WAVE_DATA, EAS_CM_CMF_DATA } E_CM_DATA_MODULES; typedef struct { int maxSMFStreams; void *pSMFData; void *pSMFStream; } S_EAS_SMF_PTRS; typedef struct { int maxSMAFStreams; void *pSMAFData; void *pSMAFStream; } S_EAS_SMAF_PTRS; /*---------------------------------------------------------------------------- * EAS_CMStaticMemoryModel() *---------------------------------------------------------------------------- * Purpose: * This function returns true if EAS has been configured for * a static memory model. There are some limitations in the * static memory model, see the documentation for more * information. * * Outputs: * returns EAS_TRUE if a module is found *---------------------------------------------------------------------------- */ EAS_BOOL EAS_CMStaticMemoryModel (void); /*---------------------------------------------------------------------------- * EAS_CMEnumModules() *---------------------------------------------------------------------------- * Purpose: * This function is used to find pointers to optional modules. * * Inputs: * module - module number * * Outputs: * returns a pointer to the module function table or NULL if no module *---------------------------------------------------------------------------- */ EAS_VOID_PTR EAS_CMEnumModules (EAS_INT module); /*---------------------------------------------------------------------------- * EAS_CMEnumData() *---------------------------------------------------------------------------- * Purpose: * This function is used to find pointers to static memory allocations. * * Inputs: * dataModule - enumerated module number * * Outputs: * Returns handle to data or NULL if not found *---------------------------------------------------------------------------- */ EAS_VOID_PTR EAS_CMEnumData (EAS_INT dataModule); /*---------------------------------------------------------------------------- * EAS_CMEnumFXModules() *---------------------------------------------------------------------------- * Purpose: * This function is used to find pointers to optional effects modules. * * Inputs: * module - enumerated module number * pModule - pointer to module interface * * Outputs: * Returns pointer to function table or NULL if not found *---------------------------------------------------------------------------- */ EAS_VOID_PTR EAS_CMEnumFXModules (EAS_INT module); /*---------------------------------------------------------------------------- * EAS_CMEnumFXData() *---------------------------------------------------------------------------- * Purpose: * This function is used to find pointers to static memory allocations. * * Inputs: * dataModule - enumerated module number * pData - pointer to handle variable * * Outputs: * Returns handle to data or NULL if not found *---------------------------------------------------------------------------- */ EAS_VOID_PTR EAS_CMEnumFXData (EAS_INT dataModule); /*---------------------------------------------------------------------------- * EAS_CMEnumOptModules() *---------------------------------------------------------------------------- * Purpose: * This function is used to find pointers to optional modules. * * Inputs: * module - enumerated module number * * Outputs: * returns pointer to function table or NULL if no module *---------------------------------------------------------------------------- */ EAS_VOID_PTR EAS_CMEnumOptModules (EAS_INT module); /*---------------------------------------------------------------------------- * EAS_CMEnumOptData() *---------------------------------------------------------------------------- * Purpose: * This function is used to find pointers to static memory allocations. * * Inputs: * dataModule - enumerated module number * * Outputs: * Returns handle to data or NULL if not found *---------------------------------------------------------------------------- */ EAS_VOID_PTR EAS_CMEnumOptData (EAS_INT dataModule); #endif /* end _EAS_CONFIG_H */ drumstick-1.1.3/library/rt-backends/eassynth/sonivox/PaxHeaders.32572/NOTICE0000644000000000000000000000013213532747316023403 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.930000148 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/eassynth/sonivox/NOTICE0000644000175000001440000000106513532747316024176 0ustar00pedrousers00000000000000Copyright (c) 2004-2019 Sonic Network Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. drumstick-1.1.3/library/rt-backends/eassynth/PaxHeaders.32572/src0000644000000000000000000000013213532747316021504 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.930000148 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/eassynth/src/0000755000175000001440000000000013532747316022352 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/eassynth/src/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316024321 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.930000148 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/eassynth/src/CMakeLists.txt0000644000175000001440000000244313532747316025115 0ustar00pedrousers00000000000000link_directories( ${PULSE_LIBRARY_DIRS} ) set( HEADERS ../../../include/drumstick/rtmidioutput.h synthcontroller.h synthrenderer.h ) set( SOURCES synthcontroller.cpp synthrenderer.cpp ) qt5_wrap_cpp( MOC_SRCS ${HEADERS} OPTIONS -I ${DRUMSTICK_SOURCE_DIR}/library/include ) if(STATIC_DRUMSTICK) add_library( drumstick-rt-eassynth STATIC ${MOC_SRCS} ${SOURCES} ) target_compile_definitions(drumstick-rt-eassynth PRIVATE QT_STATICPLUGIN) set_target_properties(drumstick-rt-eassynth PROPERTIES STATIC_LIB "libdrumstick-rt-eassynth") else() add_library( drumstick-rt-eassynth MODULE ${MOC_SRCS} ${SOURCES} ) target_compile_definitions(drumstick-rt-eassynth PRIVATE QT_PLUGIN) endif() target_link_libraries( drumstick-rt-eassynth sonivox Qt5::Core ${PULSE_LIBRARIES} ) target_include_directories( drumstick-rt-eassynth PRIVATE ${PULSE_INCLUDE_DIRS} ${DRUMSTICK_SOURCE_DIR}/library/include ) set_target_properties(drumstick-rt-eassynth PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/drumstick) install( TARGETS drumstick-rt-eassynth RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick) drumstick-1.1.3/library/rt-backends/eassynth/src/PaxHeaders.32572/synthcontroller.cpp0000644000000000000000000000013213532747316025536 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.930000148 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/eassynth/src/synthcontroller.cpp0000644000175000001440000000710513532747316026332 0ustar00pedrousers00000000000000/* Sonivox EAS Synthesizer for Qt applications Copyright (C) 2016-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include "synthcontroller.h" #include "synthrenderer.h" namespace drumstick { namespace rt { SynthController::SynthController(QObject *parent) : MIDIOutput(parent) { m_renderer = new SynthRenderer(); m_renderer->moveToThread(&m_renderingThread); connect(&m_renderingThread, &QThread::started, m_renderer, &SynthRenderer::run); } SynthController::~SynthController() { //qDebug() << Q_FUNC_INFO; if (m_renderingThread.isRunning()) { stop(); } delete m_renderer; m_renderer = 0; } void SynthController::start() { //qDebug() << Q_FUNC_INFO; m_renderingThread.start(QThread::HighPriority); } void SynthController::stop() { //qDebug() << Q_FUNC_INFO; m_renderer->stop(); m_renderingThread.quit(); m_renderingThread.wait(); } void SynthController::initialize(QSettings* settings) { m_renderer->initialize(settings); //qDebug() << Q_FUNC_INFO; } QString SynthController::backendName() { return QSTR_SONIVOXEAS; } QString SynthController::publicName() { return QSTR_SONIVOXEAS; } void SynthController::setPublicName(QString name) { Q_UNUSED(name) } QStringList SynthController::connections(bool advanced) { Q_UNUSED(advanced) return QStringList(QSTR_SONIVOXEAS); } void SynthController::setExcludedConnections(QStringList conns) { Q_UNUSED(conns) } void SynthController::open(QString name) { Q_UNUSED(name) //qDebug() << Q_FUNC_INFO; start(); } void SynthController::close() { //qDebug() << Q_FUNC_INFO; stop(); } QString SynthController::currentConnection() { return m_renderer->connection(); } void SynthController::sendNoteOff(int chan, int note, int vel) { m_renderer->sendMessage(MIDI_STATUS_NOTEOFF + chan, note, vel); } void SynthController::sendNoteOn(int chan, int note, int vel) { m_renderer->sendMessage(MIDI_STATUS_NOTEON + chan, note, vel); } void SynthController::sendKeyPressure(int chan, int note, int value) { m_renderer->sendMessage(MIDI_STATUS_KEYPRESURE + chan, note, value); } void SynthController::sendController(int chan, int control, int value) { m_renderer->sendMessage(MIDI_STATUS_CONTROLCHANGE + chan, control, value); } void SynthController::sendProgram(int chan, int program) { m_renderer->sendMessage(MIDI_STATUS_PROGRAMCHANGE + chan, program); } void SynthController::sendChannelPressure(int chan, int value) { m_renderer->sendMessage(MIDI_STATUS_CHANNELPRESSURE + chan, value); } void SynthController::sendPitchBend(int chan, int v) { // -8192 <= v <= 8191; 0 <= value <= 16384 int value = 8192 + v; m_renderer->sendMessage(MIDI_STATUS_PITCHBEND + chan, MIDI_LSB(value), MIDI_MSB(value)); } void SynthController::sendSysex(const QByteArray &data) { Q_UNUSED(data) } void SynthController::sendSystemMsg(const int status) { Q_UNUSED(status) } }} drumstick-1.1.3/library/rt-backends/eassynth/src/PaxHeaders.32572/src.pro0000644000000000000000000000013213532747316023072 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.930000148 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/eassynth/src/src.pro0000644000175000001440000000126213532747316023664 0ustar00pedrousers00000000000000TEMPLATE = lib TARGET = drumstick-rt-eassynth DESTDIR = ../../../../build/lib/drumstick include (../../../../global.pri) CONFIG += plugin link_prl static { CONFIG += staticlib create_prl } DEPENDPATH += ../sonivox DEPENDPATH += ../../../include INCLUDEPATH += ../sonivox/host_src INCLUDEPATH += ../../../include QT -= gui LIBS += -L../../../../build/lib \ -lsonivox HEADERS += ../../../include/drumstick/rtmidiinput.h \ ../../../include/drumstick/rtmidioutput.h \ synthcontroller.h \ synthrenderer.h SOURCES += synthcontroller.cpp synthrenderer.cpp CONFIG += link_pkgconfig packagesExist(libpulse-simple) { PKGCONFIG += libpulse-simple } drumstick-1.1.3/library/rt-backends/eassynth/src/PaxHeaders.32572/synthrenderer.cpp0000644000000000000000000000013213532747316025161 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.930000148 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/eassynth/src/synthrenderer.cpp0000644000175000001440000002224413532747316025756 0ustar00pedrousers00000000000000/* Sonivox EAS Synthesizer for Qt applications Copyright (C) 2016-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "synthrenderer.h" namespace drumstick { namespace rt { const QString QSTR_PREFERENCES("SonivoxEAS"); const QString QSTR_BUFFERTIME("BufferTime"); const QString QSTR_REVERBTYPE("ReverbType"); const QString QSTR_REVERBAMT("ReverbAmt"); const QString QSTR_CHORUSTYPE("ChorusType"); const QString QSTR_CHORUSAMT("ChorusAmt"); SynthRenderer::SynthRenderer(QObject *parent) : QObject(parent), m_Stopped(true), m_bufferTime(60) { initEAS(); } void SynthRenderer::initEAS() { /* SONiVOX EAS initialization */ EAS_RESULT eas_res; EAS_DATA_HANDLE dataHandle; EAS_HANDLE handle; const S_EAS_LIB_CONFIG *easConfig = EAS_Config(); if (easConfig == 0) { qCritical() << "EAS_Config returned null"; return; } eas_res = EAS_Init(&dataHandle); if (eas_res != EAS_SUCCESS) { qCritical() << "EAS_Init error: " << eas_res; return; } eas_res = EAS_OpenMIDIStream(dataHandle, &handle, NULL); if (eas_res != EAS_SUCCESS) { qCritical() << "EAS_OpenMIDIStream error: " << eas_res; EAS_Shutdown(dataHandle); return; } m_easData = dataHandle; m_streamHandle = handle; Q_ASSERT(m_streamHandle != 0); m_sampleRate = easConfig->sampleRate; m_bufferSize = easConfig->mixBufferSize; m_channels = easConfig->numChannels; //qDebug() << Q_FUNC_INFO << "EAS bufferSize=" << m_bufferSize << " sampleRate=" << m_sampleRate << " channels=" << m_channels; } void SynthRenderer::initPulse() { pa_sample_spec samplespec; pa_buffer_attr bufattr; int period_bytes; char *server = 0; char *device = 0; int err; samplespec.format = PA_SAMPLE_S16LE; samplespec.channels = m_channels; samplespec.rate = m_sampleRate; //period_bytes = m_bufferSize * sizeof (EAS_PCM) * m_channels; period_bytes = pa_usec_to_bytes(m_bufferTime * 1000, &samplespec); bufattr.maxlength = (int32_t)-1; bufattr.tlength = period_bytes; bufattr.minreq = (int32_t)-1; bufattr.prebuf = (int32_t)-1; bufattr.fragsize = (int32_t)-1; m_pulseHandle = pa_simple_new (server, "SonivoxEAS", PA_STREAM_PLAYBACK, device, "Synthesizer output", &samplespec, NULL, /* pa_channel_map */ &bufattr, &err); if (!m_pulseHandle) { qCritical() << "Failed to create PulseAudio connection"; } //qDebug() << Q_FUNC_INFO << "period_bytes=" << period_bytes; } void SynthRenderer::uninitEAS() { EAS_RESULT eas_res; if (m_easData != 0 && m_streamHandle != 0) { eas_res = EAS_CloseMIDIStream(m_easData, m_streamHandle); if (eas_res != EAS_SUCCESS) { qWarning() << "EAS_CloseMIDIStream error: " << eas_res; } eas_res = EAS_Shutdown(m_easData); if (eas_res != EAS_SUCCESS) { qWarning() << "EAS_Shutdown error: " << eas_res; } m_streamHandle = 0; m_easData = 0; } //qDebug() << Q_FUNC_INFO; } void SynthRenderer::uninitPulse() { if (m_pulseHandle != 0) { pa_simple_free(m_pulseHandle); m_pulseHandle = 0; } //qDebug() << Q_FUNC_INFO; } SynthRenderer::~SynthRenderer() { uninitEAS(); } void SynthRenderer::initialize(QSettings *settings) { settings->beginGroup(QSTR_PREFERENCES); m_bufferTime = settings->value(QSTR_BUFFERTIME, 60).toInt(); int reverbType = settings->value(QSTR_REVERBTYPE, EAS_PARAM_REVERB_HALL).toInt(); int reverbAmt = settings->value(QSTR_REVERBAMT, 25800).toInt(); int chorusType = settings->value(QSTR_CHORUSTYPE, -1).toInt(); int chorusAmt = settings->value(QSTR_CHORUSAMT, 0).toInt(); settings->endGroup(); initReverb(reverbType); setReverbWet(reverbAmt); initChorus(chorusType); setChorusLevel(chorusAmt); } bool SynthRenderer::stopped() { QReadLocker locker(&m_mutex); return m_Stopped; } void SynthRenderer::stop() { QWriteLocker locker(&m_mutex); //qDebug() << Q_FUNC_INFO; m_Stopped = true; } void SynthRenderer::run() { int pa_err; unsigned char data[1024]; //qDebug() << Q_FUNC_INFO << "started"; try { initPulse(); m_Stopped = false; while (!stopped()) { EAS_RESULT eas_res; EAS_I32 numGen = 0; size_t bytes = 0; QCoreApplication::sendPostedEvents(); if (m_easData != 0) { EAS_PCM *buffer = (EAS_PCM *) data; eas_res = EAS_Render(m_easData, buffer, m_bufferSize, &numGen); if (eas_res != EAS_SUCCESS) { qWarning() << "EAS_Render error:" << eas_res; } bytes += (size_t) numGen * sizeof(EAS_PCM) * m_channels; // hand over to pulseaudio the rendered buffer if (pa_simple_write (m_pulseHandle, data, bytes, &pa_err) < 0) { qWarning() << "Error writing to PulseAudio connection:" << pa_err; } } } uninitPulse(); } catch (...) { qWarning() << "Exception in rendering loop - exiting"; } //qDebug() << Q_FUNC_INFO << "ended"; emit finished(); } void SynthRenderer::writeMIDIData(const QByteArray& message) { EAS_RESULT eas_res = EAS_ERROR_ALREADY_STOPPED; if (m_easData != 0 && m_streamHandle != 0) { //count = m_codec->decode((unsigned char *)&buffer, sizeof(buffer), ev->getHandle()); if (message.length() > 0) { //qDebug() << Q_FUNC_INFO << message.toHex(); eas_res = EAS_WriteMIDIStream(m_easData, m_streamHandle, (EAS_U8 *)message.data(), message.length()); if (eas_res != EAS_SUCCESS) { qWarning() << "EAS_WriteMIDIStream error: " << eas_res; } } } } void SynthRenderer::initReverb(int reverb_type) { EAS_RESULT eas_res; EAS_BOOL sw = EAS_TRUE; if ( reverb_type >= EAS_PARAM_REVERB_LARGE_HALL && reverb_type <= EAS_PARAM_REVERB_ROOM ) { sw = EAS_FALSE; eas_res = EAS_SetParameter(m_easData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_PRESET, (EAS_I32) reverb_type); if (eas_res != EAS_SUCCESS) { qWarning() << "EAS_SetParameter error:" << eas_res; } } eas_res = EAS_SetParameter(m_easData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, sw); if (eas_res != EAS_SUCCESS) { qWarning() << "EAS_SetParameter error: " << eas_res; } } void SynthRenderer::initChorus(int chorus_type) { EAS_RESULT eas_res; EAS_BOOL sw = EAS_TRUE; if (chorus_type >= EAS_PARAM_CHORUS_PRESET1 && chorus_type <= EAS_PARAM_CHORUS_PRESET4 ) { sw = EAS_FALSE; eas_res = EAS_SetParameter(m_easData, EAS_MODULE_CHORUS, EAS_PARAM_CHORUS_PRESET, (EAS_I32) chorus_type); if (eas_res != EAS_SUCCESS) { qWarning() << "EAS_SetParameter error:" << eas_res; } } eas_res = EAS_SetParameter(m_easData, EAS_MODULE_CHORUS, EAS_PARAM_CHORUS_BYPASS, sw); if (eas_res != EAS_SUCCESS) { qWarning() << "EAS_SetParameter error:" << eas_res; } } void SynthRenderer::setReverbWet(int amount) { EAS_RESULT eas_res = EAS_SetParameter(m_easData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_WET, (EAS_I32) amount); if (eas_res != EAS_SUCCESS) { qWarning() << "EAS_SetParameter error:" << eas_res; } } void SynthRenderer::setChorusLevel(int amount) { EAS_RESULT eas_res = EAS_SetParameter(m_easData, EAS_MODULE_CHORUS, EAS_PARAM_CHORUS_LEVEL, (EAS_I32) amount); if (eas_res != EAS_SUCCESS) { qWarning() << "EAS_SetParameter error:" << eas_res; } } void SynthRenderer::sendMessage(int m0) { QByteArray m; m.resize(1); m[0] = m0; writeMIDIData(m); } void SynthRenderer::sendMessage(int m0, int m1) { QByteArray m; m.resize(2); m[0] = m0; m[1] = m1; writeMIDIData(m); } void SynthRenderer::sendMessage(int m0, int m1, int m2) { QByteArray m; m.resize(3); m[0] = m0; m[1] = m1; m[2] = m2; writeMIDIData(m); } QString SynthRenderer::connection() { if (stopped()) { return QString(); } else { return QSTR_SONIVOXEAS; } } void SynthRenderer::setBufferTime(int milliseconds) { //qDebug() << Q_FUNC_INFO << milliseconds; m_bufferTime = milliseconds; } }} drumstick-1.1.3/library/rt-backends/eassynth/src/PaxHeaders.32572/synthrenderer.h0000644000000000000000000000013213532747316024626 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.930000148 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/eassynth/src/synthrenderer.h0000644000175000001440000000444313532747316025424 0ustar00pedrousers00000000000000/* Sonivox EAS Synthesizer for Qt applications Copyright (C) 2016-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef SYNTHRENDERER_H_ #define SYNTHRENDERER_H_ #include #include #include #include #include "eas.h" #define cvtstr(s) #s #define stringify(s) cvtstr(s) const QString QSTR_SONIVOXEAS(QLatin1String("SonivoxEAS")); namespace drumstick { namespace rt { class SynthRenderer : public QObject { Q_OBJECT public: explicit SynthRenderer(QObject *parent = 0); virtual ~SynthRenderer(); void stop(); bool stopped(); void initReverb(int reverb_type); void initChorus(int chorus_type); void setReverbWet(int amount); void setChorusLevel(int amount); void sendMessage(int m0); void sendMessage(int m0, int m1); void sendMessage(int m0, int m1, int m2); QString connection(); void setBufferTime(int milliseconds); void initialize(QSettings* settings); private: void initEAS(); void initPulse(); void uninitEAS(); void uninitPulse(); void writeMIDIData(const QByteArray& message); public slots: void run(); signals: void finished(); private: bool m_Stopped; QReadWriteLock m_mutex; /* SONiVOX EAS */ int m_sampleRate, m_bufferSize, m_channels; EAS_DATA_HANDLE m_easData; EAS_HANDLE m_streamHandle; EAS_HANDLE m_fileHandle; /* pulseaudio */ int m_bufferTime; pa_simple *m_pulseHandle; }; }} #endif /*SYNTHRENDERER_H_*/ drumstick-1.1.3/library/rt-backends/eassynth/src/PaxHeaders.32572/synthcontroller.h0000644000000000000000000000013213532747316025203 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.930000148 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/eassynth/src/synthcontroller.h0000644000175000001440000000464313532747316026003 0ustar00pedrousers00000000000000/* Sonivox EAS Synthesizer for Qt applications Copyright (C) 2016-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef SYNTHCONTROLLER_H #define SYNTHCONTROLLER_H #include #include #include #include "synthrenderer.h" namespace drumstick { namespace rt { class SynthController : public MIDIOutput { Q_OBJECT Q_PLUGIN_METADATA(IID "net.sourceforge.drumstick.rt.MIDIOutput") Q_INTERFACES(drumstick::rt::MIDIOutput) public: explicit SynthController(QObject *parent = 0); virtual ~SynthController(); void start(); void stop(); // MIDIOutput interface public: virtual void initialize(QSettings* settings); virtual QString backendName(); virtual QString publicName(); virtual void setPublicName(QString name); virtual QStringList connections(bool advanced); virtual void setExcludedConnections(QStringList conns); virtual void open(QString name); virtual void close(); virtual QString currentConnection(); public slots: virtual void sendNoteOff(int chan, int note, int vel); virtual void sendNoteOn(int chan, int note, int vel); virtual void sendKeyPressure(int chan, int note, int value); virtual void sendController(int chan, int control, int value); virtual void sendProgram(int chan, int program); virtual void sendChannelPressure(int chan, int value); virtual void sendPitchBend(int chan, int value); virtual void sendSysex(const QByteArray &data); virtual void sendSystemMsg(const int status); private: QThread m_renderingThread; SynthRenderer *m_renderer; }; }} #endif // SYNTHCONTROLLER_H drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/net-in0000644000000000000000000000013013532747316020247 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/net-in/0000755000175000001440000000000013532747316021117 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/net-in/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316023066 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/net-in/CMakeLists.txt0000644000175000001440000000441313532747316023661 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . find_package(Qt5Network REQUIRED) set(CMAKE_INCLUDE_CURRENT_DIR ON) #include_directories(../common) set(drumstick-rt-net-in_QTOBJ_SRCS ../../include/drumstick/rtmidiinput.h ../../include/drumstick/rtmidioutput.h ../common/midiparser.h netmidiinput_p.h netmidiinput.h ) set(drumstick-rt-net-in_SRCS ../common/midiparser.cpp netmidiinput_p.cpp netmidiinput.cpp ) qt5_wrap_cpp(drumstick-rt-net-in_MOC_SRCS ${drumstick-rt-net-in_QTOBJ_SRCS} OPTIONS -I ${DRUMSTICK_SOURCE_DIR}/library/include ) if(STATIC_DRUMSTICK) add_library(drumstick-rt-net-in STATIC ${drumstick-rt-net-in_MOC_SRCS} ${drumstick-rt-net-in_SRCS}) target_compile_definitions(drumstick-rt-net-in PRIVATE QT_STATICPLUGIN) set_target_properties(drumstick-rt-net-in PROPERTIES STATIC_LIB "libdrumstick-rt-net-in") else() add_library(drumstick-rt-net-in MODULE ${drumstick-rt-net-in_MOC_SRCS} ${drumstick-rt-net-in_SRCS}) target_compile_definitions(drumstick-rt-net-in PRIVATE QT_PLUGIN) endif() target_include_directories(drumstick-rt-net-in PRIVATE ${DRUMSTICK_SOURCE_DIR}/library/include ../common ) target_link_libraries(drumstick-rt-net-in Qt5::Network) set_target_properties(drumstick-rt-net-in PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/drumstick) install(TARGETS drumstick-rt-net-in RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick) drumstick-1.1.3/library/rt-backends/net-in/PaxHeaders.32572/net-in.pro0000644000000000000000000000013013532747316022240 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/net-in/net-in.pro0000644000175000001440000000110113532747316023024 0ustar00pedrousers00000000000000TEMPLATE = lib CONFIG += plugin static { CONFIG += staticlib create_prl } TARGET = drumstick-rt-net-in DESTDIR = ../../../build/lib/drumstick DEPENDPATH += . ../../include ../common INCLUDEPATH += . ../../include ../common include (../../../global.pri) QT -= gui HEADERS += ../../include/drumstick/rtmidiinput.h \ ../../include/drumstick/rtmidioutput.h \ ../common/midiparser.h \ netmidiinput.h \ netmidiinput_p.h SOURCES += netmidiinput.cpp \ netmidiinput_p.cpp \ ../common/midiparser.cpp QT += network drumstick-1.1.3/library/rt-backends/net-in/PaxHeaders.32572/netmidiinput_p.h0000644000000000000000000000013213532747316023527 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/net-in/netmidiinput_p.h0000644000175000001440000000322213532747316024317 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef NETMIDIINPUT_P_H #define NETMIDIINPUT_P_H #include #include #include #include "midiparser.h" namespace drumstick { namespace rt { class MIDIOutput; class NetMIDIInput; class NetMIDIInputPrivate : public QObject { Q_OBJECT public: NetMIDIInput *m_inp; MIDIOutput *m_out; QUdpSocket *m_socket; MIDIParser *m_parser; int m_thruEnabled; quint16 m_port; QString m_publicName; QHostAddress m_groupAddress; QString m_currentInput; QStringList m_inputDevices; QStringList m_excludedNames; QNetworkInterface m_iface; bool m_ipv6; NetMIDIInputPrivate(QObject *parent = nullptr); void open(QString portName); void close(); void initialize(QSettings* settings); void setMIDIThruDevice(MIDIOutput* device); public slots: void processIncomingMessages(); }; }} #endif // NETMIDIINPUT_P_H drumstick-1.1.3/library/rt-backends/net-in/PaxHeaders.32572/netmidiinput_p.cpp0000644000000000000000000000013213532747316024062 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/net-in/netmidiinput_p.cpp0000644000175000001440000000760013532747316024656 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include "netmidiinput_p.h" #include "netmidiinput.h" namespace drumstick { namespace rt { static QString DEFAULT_PUBLIC_NAME(QLatin1String("MIDI In")); NetMIDIInputPrivate::NetMIDIInputPrivate(QObject *parent) : QObject(parent), m_inp(qobject_cast(parent)), m_out(nullptr), m_socket(nullptr), m_parser(nullptr), m_thruEnabled(false), m_port(0), m_publicName(DEFAULT_PUBLIC_NAME), m_groupAddress(QHostAddress(STR_ADDRESS_IPV4)), m_ipv6(false) { for(int i=MULTICAST_PORT; i -1) { //qDebug() << Q_FUNC_INFO << portName; m_socket = new QUdpSocket(); m_parser = new MIDIParser(m_inp); m_port = static_cast(MULTICAST_PORT + p); m_currentInput = portName; bool res = m_socket->bind(m_ipv6 ? QHostAddress::AnyIPv6 : QHostAddress::AnyIPv4, m_port, QUdpSocket::ShareAddress); if (res) { #ifdef Q_OS_WIN // https://docs.microsoft.com/es-es/windows/desktop/WinSock/ip-multicast-2 m_socket->setSocketOption(QAbstractSocket::MulticastLoopbackOption, 0); #endif if (m_iface.isValid()) { res = m_socket->joinMulticastGroup(m_groupAddress, m_iface); } else { res = m_socket->joinMulticastGroup(m_groupAddress); } connect(m_socket, SIGNAL(readyRead()), this, SLOT(processIncomingMessages())); } if (!res) { qWarning() << "Socket error. err:" << m_socket->error() << m_socket->errorString(); } } } void NetMIDIInputPrivate::close() { delete m_socket; delete m_parser; m_socket = nullptr; m_parser = nullptr; m_currentInput.clear(); } void NetMIDIInputPrivate::initialize(QSettings *settings) { if (settings != nullptr) { settings->beginGroup("Network"); QString ifaceName = settings->value("interface", QString()).toString(); m_ipv6 = settings->value("ipv6", false).toBool(); QString address = settings->value("address", m_ipv6 ? STR_ADDRESS_IPV6 : STR_ADDRESS_IPV4).toString(); settings->endGroup(); if (!ifaceName.isEmpty()) { m_iface = QNetworkInterface::interfaceFromName(ifaceName); } if (address.isEmpty()) { m_groupAddress.setAddress(m_ipv6 ? STR_ADDRESS_IPV6 : STR_ADDRESS_IPV4); } else { m_groupAddress.setAddress(address); } } } void NetMIDIInputPrivate::setMIDIThruDevice(MIDIOutput* device) { m_out = device; if (m_parser != nullptr) { m_parser->setMIDIThruDevice(device); } } void NetMIDIInputPrivate::processIncomingMessages() { while (m_socket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(static_cast(m_socket->pendingDatagramSize())); m_socket->readDatagram(datagram.data(), datagram.size()); if (m_parser != nullptr) { m_parser->parse(datagram); } } } }} drumstick-1.1.3/library/rt-backends/net-in/PaxHeaders.32572/netmidiinput.cpp0000644000000000000000000000013213532747316023543 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/net-in/netmidiinput.cpp0000644000175000001440000000367113532747316024343 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include "netmidiinput.h" #include "netmidiinput_p.h" namespace drumstick { namespace rt { NetMIDIInput::NetMIDIInput(QObject *parent): MIDIInput(parent), d(new NetMIDIInputPrivate(this)) { } void NetMIDIInput::initialize(QSettings *settings) { d->initialize(settings); } QString NetMIDIInput::backendName() { return QLatin1String("Network"); } QString NetMIDIInput::publicName() { return d->m_publicName; } void NetMIDIInput::setPublicName(QString name) { d->m_publicName = name; } QStringList NetMIDIInput::connections(bool advanced) { Q_UNUSED(advanced) return d->m_inputDevices; } void NetMIDIInput::setExcludedConnections(QStringList conns) { d->m_excludedNames = conns; } void NetMIDIInput::open(QString name) { d->open(name); } void NetMIDIInput::close() { d->close(); } QString NetMIDIInput::currentConnection() { return d->m_currentInput; } void NetMIDIInput::setMIDIThruDevice(MIDIOutput *device) { d->setMIDIThruDevice(device); } void NetMIDIInput::enableMIDIThru(bool enable) { d->m_thruEnabled = enable; } bool NetMIDIInput::isEnabledMIDIThru() { return d->m_thruEnabled && (d->m_out != 0); } }} drumstick-1.1.3/library/rt-backends/net-in/PaxHeaders.32572/netmidiinput.h0000644000000000000000000000013013532747316023206 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/net-in/netmidiinput.h0000644000175000001440000000414013532747316024000 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef NETMIDIINPUT_H #define NETMIDIINPUT_H #include #include #include #include namespace drumstick { namespace rt { const QString STR_ADDRESS_IPV4(QLatin1Literal("225.0.0.37")); const QString STR_ADDRESS_IPV6(QLatin1Literal("ff12::37")); const int MULTICAST_PORT(21928); const int LAST_PORT(21948); class NetMIDIInputPrivate; class NetMIDIInput : public MIDIInput { Q_OBJECT Q_PLUGIN_METADATA(IID "net.sourceforge.drumstick.rt.MIDIInput") Q_INTERFACES(drumstick::rt::MIDIInput) public: explicit NetMIDIInput(QObject *parent = nullptr); // MIDIInput interface public: virtual void initialize(QSettings* settings); virtual QString backendName(); virtual QString publicName(); virtual void setPublicName(QString name); virtual QStringList connections(bool advanced); virtual void setExcludedConnections(QStringList conns); virtual void open(QString name); virtual void close(); virtual QString currentConnection(); virtual void setMIDIThruDevice(MIDIOutput *device); virtual void enableMIDIThru(bool enable); virtual bool isEnabledMIDIThru(); private: NetMIDIInputPrivate * const d; }; }} #endif // NETMIDIINPUT_H drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/fluidsynth0000644000000000000000000000013013532747316021246 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/fluidsynth/0000755000175000001440000000000013532747316022116 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/fluidsynth/PaxHeaders.32572/synthengine.h0000644000000000000000000000013013532747316024027 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/fluidsynth/synthengine.h0000644000175000001440000000471113532747316024625 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas 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, see . */ #ifndef SynthEngine_H #define SynthEngine_H #include #include #include #include #include #include #define cvtstr(s) #s #define stringify(s) cvtstr(s) const QString QSTR_FLUIDSYNTH(QLatin1String("FluidSynth")); class SynthEngine : public QObject { Q_OBJECT Q_PROPERTY(QString soundFont READ soundFont WRITE setSoundFont) public: SynthEngine(QObject *parent = 0); virtual ~SynthEngine(); QString soundFont() const { return m_soundFont; } void setSoundFont(const QString &value); Q_INVOKABLE void initialize(QSettings *settings); Q_INVOKABLE void readSettings(QSettings *settings); Q_INVOKABLE void scanSoundFonts(); Q_INVOKABLE void panic(); Q_INVOKABLE void setInstrument(const int channel, int i); Q_INVOKABLE void noteOn(const int channel, const int midiNote, const int velocity); Q_INVOKABLE void noteOff(const int channel, const int midiNote, const int velocity); Q_INVOKABLE void controlChange(const int channel, const int ctl, const int value); Q_INVOKABLE void bender(const int channel, const int value); Q_INVOKABLE QString version() const { return stringify(VERSION); } QString currentConnection() const { return m_currentConnection; } void close(); void open(); void uninitialize(); private: void scanSoundFonts(const QDir &dir); void initializeSynth(QSettings *settings = 0); void loadSoundFont(); int m_sfid; QString m_currentConnection; QString m_soundFont; QString m_defSoundFont; fluid_settings_t* m_settings; fluid_synth_t* m_synth; fluid_audio_driver_t* m_driver; QStringList m_soundFontsList; }; #endif // SynthEngine_H drumstick-1.1.3/library/rt-backends/fluidsynth/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013013532747316024063 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/fluidsynth/CMakeLists.txt0000644000175000001440000000447113532747316024664 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(CMAKE_INCLUDE_CURRENT_DIR ON) #pkg_check_modules(FLUIDSYNTH fluidsynth>=1.1.1 fluidsynth<=1.1.11) link_directories(${FLUIDSYNTH_LIBDIR}) set(drumstick-rt-fluidsynth_QTOBJ_SRCS ../../include/drumstick/rtmidioutput.h synthengine.h synthoutput.h ) set(drumstick-rt-fluidsynth_SRCS synthengine.cpp synthoutput.cpp ) qt5_wrap_cpp(drumstick-rt-fluidsynth_MOC_SRCS ${drumstick-rt-fluidsynth_QTOBJ_SRCS} OPTIONS -I ${DRUMSTICK_SOURCE_DIR}/library/include ) if(STATIC_DRUMSTICK) add_library(drumstick-rt-fluidsynth STATIC ${drumstick-rt-fluidsynth_MOC_SRCS} ${drumstick-rt-fluidsynth_SRCS}) target_compile_definitions(drumstick-rt-fluidsynth PRIVATE QT_STATICPLUGIN) set_target_properties(drumstick-rt-fluidsynth PROPERTIES STATIC_LIB "libdrumstick-rt-fluidsynth") else() add_library(drumstick-rt-fluidsynth MODULE ${drumstick-rt-fluidsynth_MOC_SRCS} ${drumstick-rt-fluidsynth_SRCS}) target_compile_definitions(drumstick-rt-fluidsynth PRIVATE QT_PLUGIN) endif() target_include_directories(drumstick-rt-fluidsynth PRIVATE ${DRUMSTICK_SOURCE_DIR}/library/include ${FLUIDSYNTH_INCLUDEDIR} ) target_link_libraries(drumstick-rt-fluidsynth Qt5::Core ${FLUIDSYNTH_LIBRARIES}) set_target_properties(drumstick-rt-fluidsynth PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/drumstick) install(TARGETS drumstick-rt-fluidsynth RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick) drumstick-1.1.3/library/rt-backends/fluidsynth/PaxHeaders.32572/synthoutput.cpp0000644000000000000000000000013013532747316024455 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/fluidsynth/synthoutput.cpp0000644000175000001440000000511413532747316025251 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "synthoutput.h" namespace drumstick { namespace rt { SynthOutput::SynthOutput(QObject *parent) : MIDIOutput(parent), m_synth(new SynthEngine(this)) { } SynthOutput::~SynthOutput() { } void SynthOutput::initialize(QSettings *settings) { m_synth->readSettings(settings); m_synth->initialize(settings); } QString SynthOutput::backendName() { return QSTR_FLUIDSYNTH; } QString SynthOutput::publicName() { return QSTR_FLUIDSYNTH; } void SynthOutput::setPublicName(QString name) { Q_UNUSED(name) } QStringList SynthOutput::connections(bool advanced) { Q_UNUSED(advanced) return QStringList(QSTR_FLUIDSYNTH); } void SynthOutput::setExcludedConnections(QStringList conns) { Q_UNUSED(conns) } void SynthOutput::open(QString name) { Q_UNUSED(name) m_synth->open(); } void SynthOutput::close() { m_synth->close(); } QString SynthOutput::currentConnection() { return m_synth->currentConnection(); } void SynthOutput::sendNoteOff(int chan, int note, int vel) { m_synth->noteOff(chan, note, vel); } void SynthOutput::sendNoteOn(int chan, int note, int vel) { m_synth->noteOn(chan, note, vel); } void SynthOutput::sendKeyPressure(int chan, int note, int value) { Q_UNUSED(chan) Q_UNUSED(note) Q_UNUSED(value) } void SynthOutput::sendController(int chan, int control, int value) { m_synth->controlChange(chan, control, value); } void SynthOutput::sendProgram(int chan, int program) { m_synth->setInstrument(chan, program); } void SynthOutput::sendChannelPressure(int chan, int value) { Q_UNUSED(chan) Q_UNUSED(value) } void SynthOutput::sendPitchBend(int chan, int value) { m_synth->bender(chan, value); } void SynthOutput::sendSysex(const QByteArray &data) { Q_UNUSED(data) } void SynthOutput::sendSystemMsg(const int status) { Q_UNUSED(status) } }} drumstick-1.1.3/library/rt-backends/fluidsynth/PaxHeaders.32572/synthengine.cpp0000644000000000000000000000013013532747316024362 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/fluidsynth/synthengine.cpp0000644000175000001440000001757513532747316025174 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas 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, see . */ #include #include #include #include #include #include #include "synthengine.h" const QString QSTR_PREFERENCES("FluidSynth"); const QString QSTR_INSTRUMENTSDEFINITION("InstrumentsDefinition"); const QString QSTR_DATADIR("soundfonts"); const QString QSTR_DATADIR2("sounds/sf2"); const QString QSTR_SOUNDFONT("default.sf2"); const QString QSTR_AUDIODRIVER("AudioDriver"); const QString QSTR_PERIODSIZE("PeriodSize"); const QString QSTR_PERIODS("Periods"); const QString QSTR_SAMPLERATE("SampleRate"); const QString QSTR_CHORUS("Chorus"); const QString QSTR_REVERB("Reverb"); const QString QSTR_GAIN("Gain"); const QString QSTR_POLYPHONY("Polyphony"); const QString QSTR_DEFAULT_AUDIODRIVER = #if defined(Q_OS_LINUX) QLatin1Literal("pulseaudio"); #elif defined(Q_OS_WIN) QLatin1Literal("dsound"); #elif defined(Q_OS_OSX) QLatin1Literal("coreaudio"); #else QLatin1Literal("oss"); #endif const int DEFAULT_PERIODS = 1; const int DEFAULT_PERIODSIZE = 3072; const double DEFAULT_SAMPLERATE = 48000.0; const int DEFAULT_CHORUS = 0; const int DEFAULT_REVERB = 0; const double DEFAULT_GAIN = .4; const int DEFAULT_POLYPHONY = 32; SynthEngine::SynthEngine(QObject *parent) : QObject(parent), m_settings(0), m_synth(0), m_driver(0) { } SynthEngine::~SynthEngine() { uninitialize(); } void SynthEngine::uninitialize() { if (m_driver != 0) { ::delete_fluid_audio_driver(m_driver); m_driver = 0; } if (m_synth != 0) { ::delete_fluid_synth(m_synth); m_synth = 0; } if (m_settings != 0) { ::delete_fluid_settings(m_settings); m_settings = 0; } } void SynthEngine::initializeSynth(QSettings* settings) { QString fs_audiodriver = QSTR_DEFAULT_AUDIODRIVER; int fs_periodSize = DEFAULT_PERIODSIZE; int fs_periods = DEFAULT_PERIODS; double fs_sampleRate = DEFAULT_SAMPLERATE; int fs_chorus = DEFAULT_CHORUS; int fs_reverb = DEFAULT_REVERB; double fs_gain = DEFAULT_GAIN; int fs_polyphony = DEFAULT_POLYPHONY; if (settings != 0) { settings->beginGroup(QSTR_PREFERENCES); fs_audiodriver = settings->value(QSTR_AUDIODRIVER, QSTR_DEFAULT_AUDIODRIVER).toString(); fs_periodSize = settings->value(QSTR_PERIODSIZE, DEFAULT_PERIODSIZE).toInt(); fs_periods = settings->value(QSTR_PERIODS, DEFAULT_PERIODS).toInt(); fs_sampleRate = settings->value(QSTR_SAMPLERATE, DEFAULT_SAMPLERATE).toDouble(); fs_chorus = settings->value(QSTR_CHORUS, DEFAULT_CHORUS).toInt(); fs_reverb = settings->value(QSTR_REVERB, DEFAULT_REVERB).toInt(); fs_gain = settings->value(QSTR_GAIN, DEFAULT_GAIN).toDouble(); fs_polyphony = settings->value(QSTR_POLYPHONY, DEFAULT_POLYPHONY).toInt(); settings->endGroup(); } uninitialize(); m_settings = ::new_fluid_settings(); ::fluid_settings_setstr(m_settings, "audio.driver", qPrintable(fs_audiodriver)); ::fluid_settings_setint(m_settings, "audio.period-size", fs_periodSize); ::fluid_settings_setint(m_settings, "audio.periods", fs_periods); ::fluid_settings_setnum(m_settings, "synth.sample-rate", fs_sampleRate); ::fluid_settings_setint(m_settings, "synth.chorus.active", fs_chorus); ::fluid_settings_setint(m_settings, "synth.reverb.active", fs_reverb); ::fluid_settings_setnum(m_settings, "synth.gain", fs_gain); ::fluid_settings_setint(m_settings, "synth.polyphony", fs_polyphony); m_synth = ::new_fluid_synth(m_settings); m_driver = ::new_fluid_audio_driver(m_settings, m_synth); } void SynthEngine::setInstrument(int channel, int pgm) { ::fluid_synth_program_change(m_synth, channel, pgm); } void SynthEngine::noteOn(int channel, int midiNote, int velocity) { ::fluid_synth_noteon(m_synth, channel, midiNote, velocity); } void SynthEngine::noteOff(int channel, int midiNote, int /*velocity*/) { ::fluid_synth_noteoff(m_synth, channel, midiNote); } void SynthEngine::loadSoundFont() { if (m_sfid != -1) { ::fluid_synth_sfunload(m_synth, unsigned(m_sfid), 1); } m_sfid = ::fluid_synth_sfload(m_synth, qPrintable(m_soundFont), 1); } void SynthEngine::initialize(QSettings *settings) { initializeSynth(settings); scanSoundFonts(); loadSoundFont(); if (m_sfid < 0) { m_soundFont = m_defSoundFont; loadSoundFont(); } } void SynthEngine::panic() { ::fluid_synth_system_reset(m_synth); } void SynthEngine::controlChange(const int channel, const int midiCtl, const int value) { ::fluid_synth_cc(m_synth, channel, midiCtl, value); } void SynthEngine::bender(const int channel, const int value) { ::fluid_synth_pitch_bend(m_synth, channel, value + 8192); } void SynthEngine::setSoundFont(const QString &value) { if (value != m_soundFont) { m_soundFont = value; loadSoundFont(); } } void SynthEngine::scanSoundFonts(const QDir &initialDir) { QDir dir(initialDir); dir.setFilter(QDir::Files | QDir::AllDirs | QDir::NoDotAndDotDot); dir.setSorting(QDir::Name); QStringList filters; filters << "*.sf2" << "*.SF2"; QFileInfoList entries= dir.entryInfoList(filters); foreach(const QFileInfo &info, entries) { QString name = info.absoluteFilePath(); if (info.isFile() && info.fileName().toLower() == QSTR_SOUNDFONT) { m_soundFontsList << name; } else if (info.isDir()){ scanSoundFonts(name); } } } void SynthEngine::scanSoundFonts() { m_soundFontsList.clear(); QStringList paths = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); #if defined(Q_OS_OSX) paths << (QCoreApplication::applicationDirPath() + QLatin1Literal("../Resources")); #endif foreach(const QString& p, paths) { QDir d(p + QDir::separator() + QSTR_DATADIR); if (!d.exists()) { d = QDir(p + QDir::separator() + QSTR_DATADIR2); } if (d.exists()) { scanSoundFonts(d); } } if (m_defSoundFont.isEmpty() && m_soundFontsList.length() > 0) { m_defSoundFont = m_soundFontsList.first(); } } void SynthEngine::readSettings(QSettings *settings) { QDir dir; #if defined(Q_OS_OSX) dir = QDir(QCoreApplication::applicationDirPath() + QLatin1Literal("/../Resources")); #elif defined(Q_OS_UNIX) dir = QDir(QCoreApplication::applicationDirPath() + QLatin1Literal("/../share/soundfonts/")); if (!dir.exists()) { dir = QDir(QCoreApplication::applicationDirPath() + QLatin1Literal("/../share/sounds/sf2/")); } #else dir = QDir(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QSTR_DATADIR, QStandardPaths::LocateDirectory)); #endif QFileInfo sf2(dir, QSTR_SOUNDFONT); if (sf2.exists()) { m_defSoundFont = sf2.absoluteFilePath(); } m_sfid = -1; qDebug() << "defSoundFont:" << m_defSoundFont; settings->beginGroup(QSTR_PREFERENCES); m_soundFont = settings->value(QSTR_INSTRUMENTSDEFINITION, m_defSoundFont).toString(); settings->endGroup(); } void SynthEngine::close() { m_currentConnection.clear(); uninitialize(); } void SynthEngine::open() { m_currentConnection = QSTR_FLUIDSYNTH; } drumstick-1.1.3/library/rt-backends/fluidsynth/PaxHeaders.32572/fluidsynth.pro0000644000000000000000000000013013532747316024236 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/fluidsynth/fluidsynth.pro0000644000175000001440000000133613532747316025034 0ustar00pedrousers00000000000000TEMPLATE = lib TARGET = $$qtLibraryTarget(drumstick-rt-fluidsynth) DESTDIR = ../../../build/lib/drumstick include (../../../global.pri) CONFIG += plugin #create_prl static DEPENDPATH += ../../include INCLUDEPATH += ../../include QT -= gui HEADERS += ../../include/drumstick/rtmidiinput.h \ ../../include/drumstick/rtmidioutput.h \ synthengine.h \ synthoutput.h SOURCES += synthoutput.cpp synthengine.cpp macx { INCLUDEPATH += /Library/Frameworks/FluidSynth.framework/Headers QMAKE_LFLAGS += -F/Library/Frameworks LIBS += -framework FluidSynth } else { CONFIG += link_pkgconfig packagesExist(fluidsynth) { PKGCONFIG += fluidsynth } } win32 { TARGET_EXT = .dll } drumstick-1.1.3/library/rt-backends/fluidsynth/PaxHeaders.32572/synthoutput.h0000644000000000000000000000013013532747316024122 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/fluidsynth/synthoutput.h0000644000175000001440000000442013532747316024715 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef SynthOUTPUT_H #define SynthOUTPUT_H #include #include #include "synthengine.h" namespace drumstick { namespace rt { class SynthOutput : public MIDIOutput { Q_OBJECT Q_PLUGIN_METADATA(IID "net.sourceforge.drumstick.rt.MIDIOutput") Q_INTERFACES(drumstick::rt::MIDIOutput) public: SynthOutput(QObject *parent = 0); virtual ~SynthOutput(); // MIDIOutput interface public: virtual void initialize(QSettings* settings); virtual QString backendName(); virtual QString publicName(); virtual void setPublicName(QString name); virtual QStringList connections(bool advanced); virtual void setExcludedConnections(QStringList conns); virtual void open(QString name); virtual void close(); virtual QString currentConnection(); public slots: virtual void sendNoteOff(int chan, int note, int vel); virtual void sendNoteOn(int chan, int note, int vel); virtual void sendKeyPressure(int chan, int note, int value); virtual void sendController(int chan, int control, int value); virtual void sendProgram(int chan, int program); virtual void sendChannelPressure(int chan, int value); virtual void sendPitchBend(int chan, int value); virtual void sendSysex(const QByteArray &data); virtual void sendSystemMsg(const int status); private: SynthEngine *m_synth; }; }} #endif // SynthOUTPUT_H drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/dummy-in0000644000000000000000000000013213532747316020616 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/dummy-in/0000755000175000001440000000000013532747316021464 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/dummy-in/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316023433 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/dummy-in/CMakeLists.txt0000644000175000001440000000337113532747316024230 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(CMAKE_INCLUDE_CURRENT_DIR ON) set(drumstick-rt-dummy-in_QTOBJ_SRCS ../../include/drumstick/rtmidiinput.h ../../include/drumstick/rtmidioutput.h dummyinput.h ) set(drumstick-rt-dummy-in_SRCS dummyinput.cpp ) qt5_wrap_cpp(drumstick-rt-dummy-in_MOC_SRCS ${drumstick-rt-dummy-in_QTOBJ_SRCS} OPTIONS -I ${DRUMSTICK_SOURCE_DIR}/library/include ) add_library(drumstick-rt-dummy-in MODULE ${drumstick-rt-dummy-in_MOC_SRCS} ${drumstick-rt-dummy-in_SRCS} ) target_compile_definitions(drumstick-rt-dummy-in PRIVATE QT_PLUGIN) target_link_libraries(drumstick-rt-dummy-in Qt5::Core) target_include_directories(drumstick-rt-dummy-in PRIVATE ${DRUMSTICK_SOURCE_DIR}/library/include ) set_target_properties(drumstick-rt-dummy-in PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/drumstick) install(TARGETS drumstick-rt-dummy-in RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick) drumstick-1.1.3/library/rt-backends/dummy-in/PaxHeaders.32572/dummy-in.pro0000644000000000000000000000013213532747316023154 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/dummy-in/dummy-in.pro0000644000175000001440000000062113532747316023744 0ustar00pedrousers00000000000000TEMPLATE = lib TARGET = drumstick-rt-dummy-in DESTDIR = ../../../build/lib/drumstick include (../../../global.pri) CONFIG += plugin static { CONFIG += staticlib create_prl } DEPENDPATH += ../../include INCLUDEPATH += ../../include QT -= gui HEADERS += ../../include/drumstick/rtmidiinput.h \ ../../include/drumstick/rtmidioutput.h \ dummyinput.h SOURCES += dummyinput.cpp drumstick-1.1.3/library/rt-backends/dummy-in/PaxHeaders.32572/dummyinput.cpp0000644000000000000000000000013213532747316023612 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/dummy-in/dummyinput.cpp0000644000175000001440000000317413532747316024410 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "dummyinput.h" namespace drumstick { namespace rt { void DummyInput::initialize(QSettings* settings) { Q_UNUSED(settings) } QString DummyInput::backendName() { return "DUMMY"; } QString DummyInput::publicName() { return QString(); } void DummyInput::setPublicName(QString name) { Q_UNUSED(name) } QStringList DummyInput::connections(bool advanced) { Q_UNUSED(advanced) return QStringList(); } void DummyInput::setExcludedConnections(QStringList conns) { Q_UNUSED(conns) } QString DummyInput::currentConnection() { return QString(); } void DummyInput::open(QString name) { Q_UNUSED(name) } void DummyInput::close() { } void DummyInput::setMIDIThruDevice(MIDIOutput *device) { Q_UNUSED(device) } void DummyInput::enableMIDIThru(bool enable) { Q_UNUSED(enable) } bool DummyInput::isEnabledMIDIThru() { return false; } }} drumstick-1.1.3/library/rt-backends/dummy-in/PaxHeaders.32572/dummyinput.h0000644000000000000000000000013213532747316023257 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/dummy-in/dummyinput.h0000644000175000001440000000357213532747316024057 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DUMMYINPUT_H #define DUMMYINPUT_H #include #include #include namespace drumstick { namespace rt { class DummyInput : public MIDIInput { Q_OBJECT #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) Q_PLUGIN_METADATA(IID "net.sourceforge.drumstick.rt.MIDIInput") #endif Q_INTERFACES(drumstick::rt::MIDIInput) public: DummyInput(QObject *parent = 0) : MIDIInput(parent) {} virtual ~DummyInput() {} // MIDIInput interface public: virtual void initialize(QSettings* settings); virtual QString backendName(); virtual QString publicName(); virtual void setPublicName(QString name); virtual QStringList connections(bool advanced); virtual void setExcludedConnections(QStringList conns); virtual void open(QString name); virtual void close(); virtual QString currentConnection(); virtual void setMIDIThruDevice(MIDIOutput *device); virtual void enableMIDIThru(bool enable); virtual bool isEnabledMIDIThru(); }; }} #endif // DUMMYINPUT_H drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/rt-backends.pro0000644000000000000000000000013213532747316022053 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.930000148 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/rt-backends.pro0000644000175000001440000000101013532747316022634 0ustar00pedrousers00000000000000TEMPLATE = subdirs dummy { SUBDIRS += dummy-in dummy-out } linux* { SUBDIRS += alsa-in alsa-out } unix:!macx { SUBDIRS += oss-in oss-out } macx { SUBDIRS += mac-in mac-out macsynth exists(/Library/Frameworks/FluidSynth.framework/Headers/*) { SUBDIRS += fluidsynth } } else { packagesExist(fluidsynth) { SUBDIRS += fluidsynth } packagesExist(libpulse-simple) { SUBDIRS += eassynth } } win32 { SUBDIRS += win-in win-out } SUBDIRS += net-in net-out drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/win-in0000644000000000000000000000013013532747316020256 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/win-in/0000755000175000001440000000000013532747316021126 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/win-in/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013013532747316023073 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/win-in/CMakeLists.txt0000644000175000001440000000414713532747316023674 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(CMAKE_INCLUDE_CURRENT_DIR ON) set(drumstick-rt-win-in_QTOBJ_SRCS ../../include/drumstick/rtmidiinput.h ../../include/drumstick/rtmidioutput.h winmidiinput.h ) set(drumstick-rt-win-in_SRCS winmidiinput.cpp ) qt5_wrap_cpp(drumstick-rt-win-in_MOC_SRCS ${drumstick-rt-win-in_QTOBJ_SRCS} OPTIONS -I ${DRUMSTICK_SOURCE_DIR}/library/include ) if(STATIC_DRUMSTICK) add_library(drumstick-rt-win-in STATIC ${drumstick-rt-win-in_MOC_SRCS} ${drumstick-rt-win-in_SRCS}) target_compile_definitions(drumstick-rt-win-in PRIVATE QT_STATICPLUGIN) set_target_properties(drumstick-rt-win-in PROPERTIES STATIC_LIB "libdrumstick-rt-win-in") else() add_library(drumstick-rt-win-in MODULE ${drumstick-rt-win-in_MOC_SRCS} ${drumstick-rt-win-in_SRCS}) target_compile_definitions(drumstick-rt-win-in PRIVATE QT_PLUGIN) endif() target_link_libraries(drumstick-rt-win-in Qt5::Core winmm) target_include_directories(drumstick-rt-win-in PRIVATE ${DRUMSTICK_SOURCE_DIR}/library/include) set_target_properties(drumstick-rt-win-in PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/drumstick) install(TARGETS drumstick-rt-win-in RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick) drumstick-1.1.3/library/rt-backends/win-in/PaxHeaders.32572/winmidiinput.h0000644000000000000000000000013013532747316023224 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/win-in/winmidiinput.h0000644000175000001440000000371613532747316024026 0ustar00pedrousers00000000000000/* Drumstick RT Windows Backend Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef WINMIDIINPUT_H #define WINMIDIINPUT_H #include #include #include namespace drumstick { namespace rt { class WinMIDIInput : public MIDIInput { Q_OBJECT #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) Q_PLUGIN_METADATA(IID "net.sourceforge.drumstick.rt.MIDIInput") #endif Q_INTERFACES(drumstick::rt::MIDIInput) public: class WinMIDIInputPrivate; explicit WinMIDIInput(QObject *parent = nullptr); virtual ~WinMIDIInput(); // MIDIInput interface public: virtual void initialize(QSettings* settings); virtual QString backendName(); virtual QString publicName(); virtual void setPublicName(QString name); virtual QStringList connections(bool advanced); virtual void setExcludedConnections(QStringList conns); virtual void open(QString name); virtual void close(); virtual QString currentConnection(); virtual void setMIDIThruDevice(MIDIOutput *device); virtual void enableMIDIThru(bool enable); virtual bool isEnabledMIDIThru(); private: WinMIDIInputPrivate * const d; }; }} #endif // WINMIDIINPUT_H drumstick-1.1.3/library/rt-backends/win-in/PaxHeaders.32572/winmidiinput.cpp0000644000000000000000000000013013532747316023557 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/win-in/winmidiinput.cpp0000644000175000001440000002423513532747316024360 0ustar00pedrousers00000000000000/* Drumstick RT Windows Backend Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include "winmidiinput.h" namespace drumstick { namespace rt { static QLatin1Literal DEFAULT_PUBLIC_NAME = QLatin1Literal("MIDI In"); void CALLBACK midiCallback( HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2 ); class WinMIDIInput::WinMIDIInputPrivate { public: WinMIDIInput *m_inp; MIDIOutput *m_out; bool m_thruEnabled; bool m_clientFilter; HMIDIIN m_handle; QString m_publicName; QString m_currentInput; QStringList m_excludedNames; QMap m_inputDevices; WinMIDIInputPrivate(WinMIDIInput *inp): m_inp(inp), m_out(nullptr), m_thruEnabled(false), m_clientFilter(true), m_handle(nullptr), m_publicName(DEFAULT_PUBLIC_NAME) { reloadDeviceList(true); } int deviceIndex( const QString& newDevice ) { int index = -1; QMap::ConstIterator it; for( it = m_inputDevices.constBegin(); it != m_inputDevices.constEnd(); ++it ) { if (it.value() == newDevice) { index = it.key(); break; } } return index; } void open(QString name) { MMRESULT res; if (name != m_currentInput) { if (m_handle != nullptr) close(); reloadDeviceList(!m_clientFilter); int dev = deviceIndex(name); if (dev > -1) { res = midiInOpen(&m_handle, dev, (DWORD_PTR) midiCallback, (DWORD_PTR) this, CALLBACK_FUNCTION | MIDI_IO_STATUS ); if (res != MMSYSERR_NOERROR) qDebug() << "midiInOpen() err:" << mmErrorString(res); res = midiInStart(m_handle); if (res != MMSYSERR_NOERROR) qDebug() << "midiInStart() err:" << mmErrorString(res); m_currentInput = name; } } } void close() { MMRESULT res; if (m_handle != nullptr) { res = midiInStop(m_handle); if (res != MMSYSERR_NOERROR) qDebug() << "midiInStop() err:" << mmErrorString(res); res = midiInReset( m_handle ); if (res != MMSYSERR_NOERROR) qDebug() << "midiInReset() err:" << mmErrorString(res); res = midiInClose( m_handle ); if (res != MMSYSERR_NOERROR) qDebug() << "midiInClose() err:" << mmErrorString(res); m_handle = nullptr; } m_currentInput.clear(); } void reloadDeviceList(bool advanced) { MMRESULT res; MIDIINCAPS deviceCaps; QString devName; unsigned int dev, max = midiInGetNumDevs(); m_inputDevices.clear(); m_clientFilter = !advanced; for ( dev = 0; dev < max; ++dev) { bool excluded = false; res = midiInGetDevCaps( dev, &deviceCaps, sizeof(MIDIINCAPS)); if (res != MMSYSERR_NOERROR) break; #if defined(UNICODE) devName = QString::fromWCharArray(deviceCaps.szPname); #else devName = QString::fromLocal8Bit(deviceCaps.szPname); #endif foreach(const QString& n, m_excludedNames) { if (devName.startsWith(n)) { excluded = true; break; } } if (!excluded) m_inputDevices[dev] = devName; } } void setPublicName(QString name) { if (m_publicName != name) { m_publicName = name; } } void emitSignals(int status, int channel, int data1, int data2) { switch (status) { case MIDI_STATUS_NOTEOFF: if(m_out != nullptr && m_thruEnabled) m_out->sendNoteOff(channel, data1, data2); emit m_inp->midiNoteOff(channel, data1, data2); break; case MIDI_STATUS_NOTEON: if(m_out != nullptr && m_thruEnabled) m_out->sendNoteOn(channel, data1, data2); emit m_inp->midiNoteOn(channel, data1, data2); break; case MIDI_STATUS_KEYPRESURE: if(m_out != nullptr && m_thruEnabled) m_out->sendKeyPressure(channel, data1, data2); emit m_inp->midiKeyPressure(channel, data1, data2); break; case MIDI_STATUS_CONTROLCHANGE: if(m_out != nullptr && m_thruEnabled) m_out->sendController(channel, data1, data2); emit m_inp->midiController(channel, data1, data2); break; case MIDI_STATUS_PROGRAMCHANGE: if(m_out != nullptr && m_thruEnabled) m_out->sendProgram(channel, data1); emit m_inp->midiProgram(channel, data1); break; case MIDI_STATUS_CHANNELPRESSURE: if(m_out != nullptr && m_thruEnabled) m_out->sendChannelPressure(channel, data1); emit m_inp->midiChannelPressure(channel, data1); break; case MIDI_STATUS_PITCHBEND: { int value = (data1 + data2 * 0x80) - 8192; if(m_out != nullptr && m_thruEnabled) m_out->sendPitchBend(channel, value); emit m_inp->midiPitchBend(channel, value); } break; default: qDebug() << "MIDI in status?" << status; } } void emitSysex(QByteArray data) { if(m_out != nullptr && m_thruEnabled) m_out->sendSysex(data); emit m_inp->midiSysex(data); } QString mmErrorString(MMRESULT err) { QString errstr; #ifdef UNICODE WCHAR buffer[1024]; midiInGetErrorText(err, &buffer[0], sizeof(buffer)); errstr = QString::fromUtf16((const ushort*)buffer); #else char buffer[1024]; midiOutGetErrorText(err, &buffer[0], sizeof(buffer)); errstr = QString::fromLocal8Bit(buffer); #endif return errstr; } }; void CALLBACK midiCallback( HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2 ) { //Q_UNUSED(hMidiIn) Q_UNUSED(dwParam2) WinMIDIInput::WinMIDIInputPrivate* object = (WinMIDIInput::WinMIDIInputPrivate*) dwInstance; switch( wMsg ) { case MIM_OPEN: qDebug() << "Open input" << hMidiIn; break; case MIM_CLOSE: qDebug() << "Close input" << hMidiIn; break; case MIM_ERROR: case MIM_LONGERROR: qDebug() << "Errors input"; break; case MIM_LONGDATA: qDebug() << "Sysex data input"; break; case MIM_DATA: case MIM_MOREDATA: { int status = dwParam1 & 0xf0; int channel = dwParam1 & 0x0f; int data1 = (dwParam1 & 0x7f00) >> 8; int data2 = (dwParam1 & 0x7f0000) >> 16; object->emitSignals(status, channel, data1, data2); } break; default: qDebug() << "unknown input message:" << hex << wMsg; break; } } WinMIDIInput::WinMIDIInput(QObject *parent) : MIDIInput(parent), d(new WinMIDIInputPrivate(this)) { } WinMIDIInput::~WinMIDIInput() { delete d; } void WinMIDIInput::initialize(QSettings *settings) { Q_UNUSED(settings) } QString WinMIDIInput::backendName() { return QLatin1Literal("Windows MM"); } QString WinMIDIInput::publicName() { return d->m_publicName; } void WinMIDIInput::setPublicName(QString name) { d->setPublicName(name); } QStringList WinMIDIInput::connections(bool advanced) { d->reloadDeviceList(advanced); return d->m_inputDevices.values(); } void WinMIDIInput::setExcludedConnections(QStringList conns) { d->m_excludedNames = conns; } void WinMIDIInput::open(QString name) { d->open(name); } void WinMIDIInput::close() { d->close(); } QString WinMIDIInput::currentConnection() { return d->m_currentInput; } void WinMIDIInput::setMIDIThruDevice(MIDIOutput *device) { d->m_out = device; } void WinMIDIInput::enableMIDIThru(bool enable) { d->m_thruEnabled = enable; } bool WinMIDIInput::isEnabledMIDIThru() { return d->m_thruEnabled && d->m_out != nullptr; } }} // namespace drumstick::rt drumstick-1.1.3/library/rt-backends/win-in/PaxHeaders.32572/win-in.pro0000644000000000000000000000013013532747316022256 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/win-in/win-in.pro0000644000175000001440000000075513532747316023060 0ustar00pedrousers00000000000000TEMPLATE = lib CONFIG += plugin static { CONFIG += staticlib create_prl } TARGET = drumstick-rt-win-in DESTDIR = ../../../build/lib/drumstick DEPENDPATH += . ../../include INCLUDEPATH += . ../../include include (../../../global.pri) DEPENDPATH += ../../include INCLUDEPATH += ../../include QT -= gui HEADERS += ../../include/drumstick/rtmidiinput.h \ ../../include/drumstick/rtmidioutput.h \ winmidiinput.h SOURCES += \ winmidiinput.cpp LIBS += -lwinmm drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/dummy-out0000644000000000000000000000013213532747316021017 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/dummy-out/0000755000175000001440000000000013532747316021665 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/dummy-out/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316023634 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/dummy-out/CMakeLists.txt0000644000175000001440000000333513532747316024431 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(CMAKE_INCLUDE_CURRENT_DIR ON) set(drumstick-rt-dummy-out_QTOBJ_SRCS ../../include/drumstick/rtmidioutput.h dummyoutput.h ) set(drumstick-rt-dummy-out_SRCS dummyoutput.cpp ) qt5_wrap_cpp(drumstick-rt-dummy-out_MOC_SRCS ${drumstick-rt-dummy-out_QTOBJ_SRCS} OPTIONS -I ${DRUMSTICK_SOURCE_DIR}/library/include ) add_library(drumstick-rt-dummy-out MODULE ${drumstick-rt-dummy-out_MOC_SRCS} ${drumstick-rt-dummy-out_SRCS} ) target_compile_definitions(drumstick-rt-dummy-out PRIVATE QT_PLUGIN) target_link_libraries(drumstick-rt-dummy-out Qt5::Core) target_include_directories(drumstick-rt-dummy-out PRIVATE ${DRUMSTICK_SOURCE_DIR}/library/include ) set_target_properties(drumstick-rt-dummy-out PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/drumstick) install(TARGETS drumstick-rt-dummy-out RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick) drumstick-1.1.3/library/rt-backends/dummy-out/PaxHeaders.32572/dummyoutput.h0000644000000000000000000000013213532747316023661 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/dummy-out/dummyoutput.h0000644000175000001440000000442513532747316024457 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DUMMYOUTPUT_H #define DUMMYOUTPUT_H #include #include namespace drumstick { namespace rt { class DummyOutput : public MIDIOutput { Q_OBJECT #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) Q_PLUGIN_METADATA(IID "net.sourceforge.drumstick.rt.MIDIOutput") #endif Q_INTERFACES(drumstick::rt::MIDIOutput) public: DummyOutput(QObject *parent = 0) : MIDIOutput(parent) {} virtual ~DummyOutput() {} // MIDIOutput interface public: virtual void initialize(QSettings* settings); virtual QString backendName(); virtual QString publicName(); virtual void setPublicName(QString name); virtual QStringList connections(bool advanced); virtual void setExcludedConnections(QStringList conns); virtual void open(QString name); virtual void close(); virtual QString currentConnection(); public slots: virtual void sendNoteOff(int chan, int note, int vel); virtual void sendNoteOn(int chan, int note, int vel); virtual void sendKeyPressure(int chan, int note, int value); virtual void sendController(int chan, int control, int value); virtual void sendProgram(int chan, int program); virtual void sendChannelPressure(int chan, int value); virtual void sendPitchBend(int chan, int value); virtual void sendSysex(const QByteArray &data); virtual void sendSystemMsg(const int status); }; }} #endif // DUMMYOUTPUT_H drumstick-1.1.3/library/rt-backends/dummy-out/PaxHeaders.32572/dummyoutput.cpp0000644000000000000000000000013213532747316024214 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/dummy-out/dummyoutput.cpp0000644000175000001440000000457013532747316025013 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "dummyoutput.h" namespace drumstick { namespace rt { void DummyOutput::initialize(QSettings* settings) { Q_UNUSED(settings) } QString DummyOutput::backendName() { return QLatin1String("DUMMY"); } QString DummyOutput::publicName() { return QString(); } void DummyOutput::setPublicName(QString name) { Q_UNUSED(name) } QStringList DummyOutput::connections(bool advanced) { Q_UNUSED(advanced) return QStringList(); } void DummyOutput::setExcludedConnections(QStringList conns) { Q_UNUSED(conns) } void DummyOutput::open(QString name) { Q_UNUSED(name) } void DummyOutput::close() { } QString DummyOutput::currentConnection() { return QString(); } void DummyOutput::sendNoteOff(int chan, int note, int vel) { Q_UNUSED(chan) Q_UNUSED(note) Q_UNUSED(vel) } void DummyOutput::sendNoteOn(int chan, int note, int vel) { Q_UNUSED(chan) Q_UNUSED(note) Q_UNUSED(vel) } void DummyOutput::sendKeyPressure(int chan, int note, int value) { Q_UNUSED(chan) Q_UNUSED(note) Q_UNUSED(value) } void DummyOutput::sendController(int chan, int control, int value) { Q_UNUSED(chan) Q_UNUSED(control) Q_UNUSED(value) } void DummyOutput::sendProgram(int chan, int program) { Q_UNUSED(chan) Q_UNUSED(program) } void DummyOutput::sendChannelPressure(int chan, int value) { Q_UNUSED(chan) Q_UNUSED(value) } void DummyOutput::sendPitchBend(int chan, int value) { Q_UNUSED(chan) Q_UNUSED(value) } void DummyOutput::sendSysex(const QByteArray &data) { Q_UNUSED(data) } void DummyOutput::sendSystemMsg(const int status) { Q_UNUSED(status) } }} drumstick-1.1.3/library/rt-backends/dummy-out/PaxHeaders.32572/dummy-out.pro0000644000000000000000000000013213532747316023556 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/dummy-out/dummy-out.pro0000644000175000001440000000070613532747316024352 0ustar00pedrousers00000000000000TEMPLATE = lib TARGET = drumstick-rt-dummy-out DESTDIR = ../../../build/lib/drumstick include (../../../global.pri) CONFIG += plugin static { CONFIG += staticlib create_prl } DEPENDPATH += ../../include INCLUDEPATH += ../../include QT -= gui HEADERS += ../../include/drumstick/rtmidiinput.h \ ../../include/drumstick/rtmidioutput.h \ dummyoutput.h SOURCES += \ dummyoutput.cpp OTHER_FILES += \ CMakeLists.txt drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/win-out0000644000000000000000000000013013532747316020457 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/win-out/0000755000175000001440000000000013532747316021327 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/win-out/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013013532747316023274 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/win-out/CMakeLists.txt0000644000175000001440000000412113532747316024065 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(CMAKE_INCLUDE_CURRENT_DIR ON) set(drumstick-rt-win-out_QTOBJ_SRCS ../../include/drumstick/rtmidioutput.h winmidioutput.h ) set(drumstick-rt-win-out_SRCS winmidioutput.cpp ) qt5_wrap_cpp(drumstick-rt-win-out_MOC_SRCS ${drumstick-rt-win-out_QTOBJ_SRCS} OPTIONS -I ${DRUMSTICK_SOURCE_DIR}/library/include ) if(STATIC_DRUMSTICK) add_library(drumstick-rt-win-out STATIC ${drumstick-rt-win-out_MOC_SRCS} ${drumstick-rt-win-out_SRCS}) target_compile_definitions(drumstick-rt-win-out PRIVATE QT_STATICPLUGIN) set_target_properties(drumstick-rt-win-out PROPERTIES STATIC_LIB "libdrumstick-rt-win-out") else() add_library(drumstick-rt-win-out MODULE ${drumstick-rt-win-out_MOC_SRCS} ${drumstick-rt-win-out_SRCS}) target_compile_definitions(drumstick-rt-win-out PRIVATE QT_PLUGIN) endif() target_include_directories(drumstick-rt-win-out PRIVATE ${DRUMSTICK_SOURCE_DIR}/library/include) target_link_libraries(drumstick-rt-win-out Qt5::Core winmm) set_target_properties(drumstick-rt-win-out PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/drumstick) install(TARGETS drumstick-rt-win-out RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick) drumstick-1.1.3/library/rt-backends/win-out/PaxHeaders.32572/winmidioutput.h0000644000000000000000000000013013532747316023626 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/win-out/winmidioutput.h0000644000175000001440000000461213532747316024424 0ustar00pedrousers00000000000000/* Drumstick RT Windows Backend Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef WINMIDIOUTPUT_H #define WINMIDIOUTPUT_H #include #include #include #include namespace drumstick { namespace rt { class WinMIDIOutput : public MIDIOutput { Q_OBJECT #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) Q_PLUGIN_METADATA(IID "net.sourceforge.drumstick.rt.MIDIOutput") #endif Q_INTERFACES(drumstick::rt::MIDIOutput) public: class WinMIDIOutputPrivate; explicit WinMIDIOutput(QObject *parent = nullptr); virtual ~WinMIDIOutput(); // MIDIOutput interface virtual void initialize(QSettings* settings); virtual QString backendName(); virtual QString publicName(); virtual void setPublicName(QString name); virtual QStringList connections(bool advanced); virtual void setExcludedConnections(QStringList conns); virtual void open(QString name); virtual void close(); virtual QString currentConnection(); public slots: virtual void sendNoteOff(int chan, int note, int vel); virtual void sendNoteOn(int chan, int note, int vel); virtual void sendKeyPressure(int chan, int note, int value); virtual void sendController(int chan, int control, int value); virtual void sendProgram(int chan, int program); virtual void sendChannelPressure(int chan, int value); virtual void sendPitchBend(int chan, int value); virtual void sendSysex(const QByteArray &data); virtual void sendSystemMsg(const int status); private: WinMIDIOutputPrivate * const d; }; }} #endif // WINMIDIOUTPUT_H drumstick-1.1.3/library/rt-backends/win-out/PaxHeaders.32572/win-out.pro0000644000000000000000000000013013532747316022660 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/win-out/win-out.pro0000644000175000001440000000074313532747316023457 0ustar00pedrousers00000000000000TEMPLATE = lib CONFIG += plugin static { CONFIG += staticlib create_prl } TARGET = drumstick-rt-win-out DESTDIR = ../../../build/lib/drumstick DEPENDPATH += . ../../include INCLUDEPATH += . ../../include include (../../../global.pri) DEPENDPATH += ../../include INCLUDEPATH += ../../include QT -= gui HEADERS += ../../include/drumstick/rtmidiinput.h \ ../../include/drumstick/rtmidioutput.h \ winmidioutput.h SOURCES += winmidioutput.cpp LIBS += -lwinmm drumstick-1.1.3/library/rt-backends/win-out/PaxHeaders.32572/winmidioutput.cpp0000644000000000000000000000013013532747316024161 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/win-out/winmidioutput.cpp0000644000175000001440000002601013532747316024753 0ustar00pedrousers00000000000000/* Drumstick RT Windows Backend Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include "winmidioutput.h" namespace drumstick { namespace rt { union WinMIDIPacket { WinMIDIPacket() : dwPacket(0) {} DWORD dwPacket; quint8 data[sizeof(DWORD)]; }; static QLatin1Literal DEFAULT_PUBLIC_NAME = QLatin1Literal("MIDI Out"); void CALLBACK midiCallback( HMIDIOUT hmo, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2); class WinMIDIOutput::WinMIDIOutputPrivate { public: HMIDIOUT m_handle; bool m_clientFilter; QString m_publicName; QString m_currentOutput; QMap m_outputDevices; MIDIHDR m_midiSysexHdr; QByteArray m_sysexBuffer; QStringList m_excludedNames; WinMIDIOutputPrivate(): m_handle(nullptr), m_clientFilter(true), m_publicName(DEFAULT_PUBLIC_NAME) { reloadDeviceList(true); } void reloadDeviceList(bool advanced) { MMRESULT res; MIDIOUTCAPS deviceCaps; QString devName; unsigned int dev, max = midiOutGetNumDevs(); m_outputDevices.clear(); m_clientFilter = !advanced; for ( dev = 0; dev < max; ++dev) { res = midiOutGetDevCaps( dev, &deviceCaps, sizeof(MIDIOUTCAPS)); if (res != MMSYSERR_NOERROR) break; if (m_clientFilter && (deviceCaps.wTechnology == MOD_MAPPER)) continue; #if defined(UNICODE) devName = QString::fromWCharArray(deviceCaps.szPname); #else devName = QString::fromLocal8Bit(deviceCaps.szPname); #endif m_outputDevices[dev] = devName; } if (!m_clientFilter) { dev = MIDI_MAPPER; res = midiOutGetDevCaps( dev, &deviceCaps, sizeof(MIDIOUTCAPS)); if (res == MMSYSERR_NOERROR) { #if defined(UNICODE) devName = QString::fromWCharArray(deviceCaps.szPname); #else devName = QString::fromLocal8Bit(deviceCaps.szPname); #endif m_outputDevices[dev] = devName; } } } void setPublicName(QString name) { if (m_publicName != name) { m_publicName = name; } } int deviceIndex( const QString& newOutputDevice ) { int index = -1; QMap::ConstIterator it; for( it = m_outputDevices.constBegin(); it != m_outputDevices.constEnd(); ++it ) { if (it.value() == newOutputDevice) { index = it.key(); break; } } return index; } void open(QString name) { MMRESULT res; int dev = -1; if (m_handle != nullptr) close(); reloadDeviceList(!m_clientFilter); dev = deviceIndex(name); if (dev > -1) { res = midiOutOpen( &m_handle, dev, (DWORD_PTR) midiCallback, (DWORD_PTR) this, CALLBACK_FUNCTION); if (res == MMSYSERR_NOERROR) m_currentOutput = name; else qDebug() << "midiStreamOpen() err:" << mmErrorString(res); } } void close() { MMRESULT res; if (m_handle != nullptr) { res = midiOutReset( m_handle ); if (res != MMSYSERR_NOERROR) qDebug() << "midiOutReset() err:" << mmErrorString(res); res = midiOutClose( m_handle ); if (res == MMSYSERR_NOERROR) m_currentOutput.clear(); else qDebug() << "midiStreamClose() err:" << mmErrorString(res); m_handle = nullptr; } } void doneHeader( LPMIDIHDR lpMidiHdr ) { MMRESULT res; res = midiOutUnprepareHeader( m_handle, lpMidiHdr, sizeof(MIDIHDR) ); if (res != MMSYSERR_NOERROR) qDebug() << "midiOutUnprepareHeader() err:" << mmErrorString(res); if ((lpMidiHdr->dwFlags & MHDR_ISSTRM) == 0) return; // sysex header? } void sendShortMessage(WinMIDIPacket &packet) { MMRESULT res; res = midiOutShortMsg( m_handle, packet.dwPacket ); if ( res != MMSYSERR_NOERROR ) qDebug() << "midiOutShortMsg() err:" << mmErrorString(res); } void sendSysexEvent(const QByteArray& data) { MMRESULT res; m_sysexBuffer = data; m_midiSysexHdr.lpData = (LPSTR) m_sysexBuffer.data(); m_midiSysexHdr.dwBufferLength = m_sysexBuffer.size(); m_midiSysexHdr.dwBytesRecorded = m_sysexBuffer.size(); m_midiSysexHdr.dwFlags = 0; m_midiSysexHdr.dwUser = 0; res = midiOutPrepareHeader( m_handle, &m_midiSysexHdr, sizeof(MIDIHDR) ); if (res != MMSYSERR_NOERROR) qDebug() << "midiOutPrepareHeader() err:" << mmErrorString(res); else { res = midiOutLongMsg( m_handle, &m_midiSysexHdr, sizeof(MIDIHDR) ); if (res != MMSYSERR_NOERROR) qDebug() << "midiOutLongMsg() err:" << mmErrorString(res); } } QString mmErrorString(MMRESULT err) { QString errstr; #ifdef UNICODE WCHAR buffer[1024]; midiOutGetErrorText(err, &buffer[0], sizeof(buffer)); errstr = QString::fromUtf16((const ushort*)buffer); #else char buffer[1024]; midiOutGetErrorText(err, &buffer[0], sizeof(buffer)); errstr = QString::fromLocal8Bit(buffer); #endif return errstr; } }; void CALLBACK midiCallback( HMIDIOUT hmo, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { //Q_UNUSED(hmo) Q_UNUSED(dwParam2) WinMIDIOutput::WinMIDIOutputPrivate* obj = (WinMIDIOutput::WinMIDIOutputPrivate*) dwInstance; switch( wMsg ) { case MOM_DONE: obj->doneHeader( (LPMIDIHDR) dwParam1 ); break; case MOM_OPEN: qDebug() << "Open output" << hmo; break; case MOM_CLOSE: qDebug() << "Close output" << hmo; break; default: qDebug() << "unknown output message:" << hex << wMsg; break; } } WinMIDIOutput::WinMIDIOutput(QObject *parent) : MIDIOutput(parent), d(new WinMIDIOutputPrivate) { } WinMIDIOutput::~WinMIDIOutput() { delete d; } void WinMIDIOutput::initialize(QSettings *settings) { Q_UNUSED(settings) } QString WinMIDIOutput::backendName() { return "Windows MM"; } QString WinMIDIOutput::publicName() { return d->m_publicName; } void WinMIDIOutput::setPublicName(QString name) { d->setPublicName(name); } QStringList WinMIDIOutput::connections(bool advanced) { d->reloadDeviceList(advanced); return d->m_outputDevices.values(); } void WinMIDIOutput::setExcludedConnections(QStringList conns) { d->m_excludedNames = conns; } void WinMIDIOutput::open(QString name) { d->open(name); } void WinMIDIOutput::close() { d->close(); } QString WinMIDIOutput::currentConnection() { return d->m_currentOutput; } void WinMIDIOutput::sendNoteOn(int chan, int note, int vel) { WinMIDIPacket packet; packet.data[0] = MIDI_STATUS_NOTEON | (chan & MIDI_CHANNEL_MASK); packet.data[1] = note; packet.data[2] = vel; d->sendShortMessage(packet); } void WinMIDIOutput::sendNoteOff(int chan, int note, int vel) { WinMIDIPacket packet; packet.data[0] = MIDI_STATUS_NOTEOFF | (chan & MIDI_CHANNEL_MASK); packet.data[1] = note; packet.data[2] = vel; d->sendShortMessage(packet); } void WinMIDIOutput::sendController(int chan, int control, int value) { WinMIDIPacket packet; packet.data[0] = MIDI_STATUS_CONTROLCHANGE | (chan & MIDI_CHANNEL_MASK); packet.data[1] = control; packet.data[2] = value; d->sendShortMessage(packet); } void WinMIDIOutput::sendKeyPressure(int chan, int note, int value) { WinMIDIPacket packet; packet.data[0] = MIDI_STATUS_KEYPRESURE | (chan & MIDI_CHANNEL_MASK); packet.data[1] = note; packet.data[2] = value; d->sendShortMessage(packet); } void WinMIDIOutput::sendProgram(int chan, int program) { WinMIDIPacket packet; packet.data[0] = MIDI_STATUS_PROGRAMCHANGE | (chan & MIDI_CHANNEL_MASK); packet.data[1] = program; d->sendShortMessage(packet); } void WinMIDIOutput::sendChannelPressure(int chan, int value) { WinMIDIPacket packet; packet.data[0] = MIDI_STATUS_CHANNELPRESSURE | (chan & MIDI_CHANNEL_MASK); packet.data[1] = value; d->sendShortMessage(packet); } void WinMIDIOutput::sendPitchBend(int chan, int v) { WinMIDIPacket packet; // -8192 <= v <= 8191; 0 <= value <= 16384 int value = 8192 + v; packet.data[0] = MIDI_STATUS_PITCHBEND | (chan & MIDI_CHANNEL_MASK); packet.data[1] = MIDI_LSB(value); packet.data[2] = MIDI_MSB(value); d->sendShortMessage(packet); } void WinMIDIOutput::sendSystemMsg(const int status) { WinMIDIPacket packet; packet.data[0] = status; d->sendShortMessage(packet); } void WinMIDIOutput::sendSysex(const QByteArray &data) { d->sendSysexEvent(data); } }} drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/macsynth0000644000000000000000000000013213532747316020705 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/macsynth/0000755000175000001440000000000013532747316021553 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/macsynth/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316023522 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/macsynth/CMakeLists.txt0000644000175000001440000000441013532747316024312 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(CMAKE_INCLUDE_CURRENT_DIR ON) #include_directories(../common) set(drumstick-rt-macsynth_QTOBJ_SRCS ../../include/drumstick/rtmidioutput.h macsynth.h ) set(drumstick-rt-macsynth_SRCS macsynth.cpp ) qt5_wrap_cpp(drumstick-rt-macsynth_MOC_SRCS ${drumstick-rt-macsynth_QTOBJ_SRCS} OPTIONS -I ${DRUMSTICK_SOURCE_DIR}/library/include ) if(STATIC_DRUMSTICK) add_library(drumstick-rt-macsynth STATIC ${drumstick-rt-macsynth_MOC_SRCS} ${drumstick-rt-macsynth_SRCS}) target_compile_definitions(drumstick-rt-macsynth PRIVATE QT_STATICPLUGIN) set_target_properties(drumstick-rt-macsynth PROPERTIES STATIC_LIB "libdrumstick-rt-macsynth") else() add_library(drumstick-rt-macsynth MODULE ${drumstick-rt-macsynth_MOC_SRCS} ${drumstick-rt-macsynth_SRCS}) target_compile_definitions(drumstick-rt-macsynth PRIVATE QT_PLUGIN) endif() target_link_libraries(drumstick-rt-macsynth Qt5::Core "-framework CoreMIDI -framework CoreFoundation -framework CoreServices" "-framework CoreAudio -framework AudioToolbox -framework AudioUnit" ) target_include_directories(drumstick-rt-macsynth PRIVATE ${DRUMSTICK_SOURCE_DIR}/library/include ../common ) set_target_properties(drumstick-rt-macsynth PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/drumstick) install(TARGETS drumstick-rt-macsynth RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick) drumstick-1.1.3/library/rt-backends/macsynth/PaxHeaders.32572/macsynth.h0000644000000000000000000000013213532747316022761 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/macsynth/macsynth.h0000644000175000001440000000456013532747316023557 0ustar00pedrousers00000000000000/* Drumstick RT Mac OSX Backend Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DLSSOFTSYNTH_H #define DLSSOFTSYNTH_H #include #include #include namespace drumstick { namespace rt { class MacSynthOutput : public MIDIOutput { Q_OBJECT #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) Q_PLUGIN_METADATA(IID "net.sourceforge.drumstick.rt.MIDIOutput") #endif Q_INTERFACES(drumstick::rt::MIDIOutput) public: MacSynthOutput(QObject *parent = 0); virtual ~MacSynthOutput(); // MIDIOutput interface public: virtual void initialize(QSettings* settings); virtual QString backendName(); virtual QString publicName(); virtual void setPublicName(QString name); virtual QStringList connections(bool advanced); virtual void setExcludedConnections(QStringList conns); virtual void open(QString name); virtual void close(); virtual QString currentConnection(); public slots: virtual void sendNoteOff(int chan, int note, int vel); virtual void sendNoteOn(int chan, int note, int vel); virtual void sendKeyPressure(int chan, int note, int value); virtual void sendController(int chan, int control, int value); virtual void sendProgram(int chan, int program); virtual void sendChannelPressure(int chan, int value); virtual void sendPitchBend(int chan, int value); virtual void sendSysex(const QByteArray &data); virtual void sendSystemMsg(const int status); private: class MacSynthOutputPrivate; MacSynthOutputPrivate* const d; }; }} #endif // MACSYNTH_H drumstick-1.1.3/library/rt-backends/macsynth/PaxHeaders.32572/macsynth.pro0000644000000000000000000000013213532747316023332 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/macsynth/macsynth.pro0000644000175000001440000000076613532747316024134 0ustar00pedrousers00000000000000TEMPLATE = lib CONFIG += plugin static { CONFIG += staticlib create_prl } TARGET = drumstick-rt-macsynth DESTDIR = ../../../build/lib/drumstick DEPENDPATH += . ../../include INCLUDEPATH += . ../../include include (../../../global.pri) QT -= gui HEADERS += ../../include/drumstick/rtmidioutput.h \ macsynth.h SOURCES += macsynth.cpp LIBS += -framework CoreMIDI -framework CoreFoundation -framework CoreServices LIBS += -framework CoreAudio -framework AudioToolbox -framework AudioUnit drumstick-1.1.3/library/rt-backends/macsynth/PaxHeaders.32572/macsynth.cpp0000644000000000000000000000013213532747316023314 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/macsynth/macsynth.cpp0000644000175000001440000003105313532747316024107 0ustar00pedrousers00000000000000/* Drumstick RT Mac OSX Backend Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include "macsynth.h" #include #include #include #define PRETTY_NAME "DLS Synth" namespace drumstick { namespace rt { class MacSynthOutput::MacSynthOutputPrivate { private: AUGraph m_graph; AudioUnit m_synthUnit; QString m_connection; QString m_soundfont_dls; bool m_default_dls; bool m_reverb_dls; public: explicit MacSynthOutputPrivate(): m_graph(nullptr), m_synthUnit(nullptr) { //qDebug() << Q_FUNC_INFO; m_connection.clear(); } ~MacSynthOutputPrivate() { //qDebug() << Q_FUNC_INFO; stop(); } bool useDefaultDls() const { return m_default_dls; } void setDefaultDlsFlag(const bool f) { if (f != m_default_dls) { m_default_dls = f; } } bool useReverb() const { return m_reverb_dls; } void setReverbFlag(const bool f) { if (f != m_reverb_dls) { m_reverb_dls = f; } } QString soundFontDls() const { return m_soundfont_dls; } void setSoundFontDls(const QString& sf) { if (sf != m_soundfont_dls) { m_soundfont_dls = sf; } } QString currentConnection() { return m_connection; } void start () { OSStatus result; AudioComponentDescription cd; UInt32 usesReverb; AUNode synthNode = 0; AUNode outputNode = 0; AUNode limiterNode = 0; //qDebug() << Q_FUNC_INFO; if (m_graph == nullptr) { cd.componentManufacturer = kAudioUnitManufacturer_Apple; cd.componentFlags = 0; cd.componentFlagsMask = 0; result = NewAUGraph (&m_graph); registerStatus("NewAUGraph", result); if (result != noErr) return; cd.componentType = kAudioUnitType_MusicDevice; cd.componentSubType = kAudioUnitSubType_DLSSynth; result = AUGraphAddNode (m_graph, &cd, &synthNode); registerStatus( "AUGraphAddNode", result); cd.componentType = kAudioUnitType_Effect; cd.componentSubType = kAudioUnitSubType_PeakLimiter; result = AUGraphAddNode(m_graph, &cd, &limiterNode); registerStatus( "AUGraphAddNode", result); cd.componentType = kAudioUnitType_Output; cd.componentSubType = kAudioUnitSubType_DefaultOutput; result = AUGraphAddNode (m_graph, &cd, &outputNode); registerStatus( "AUGraphAddNode", result); result = AUGraphOpen (m_graph); registerStatus( "AUGraphOpen", result); if (result != noErr) return; result = AUGraphConnectNodeInput (m_graph, synthNode, 0, limiterNode, 0); registerStatus( "AUGraphConnectNodeInput", result); result = AUGraphConnectNodeInput (m_graph, limiterNode, 0, outputNode, 0); registerStatus( "AUGraphConnectNodeInput", result); result = AUGraphNodeInfo (m_graph, synthNode, nullptr, &m_synthUnit); registerStatus( "AUGraphNodeInfo", result); if (!m_default_dls && !m_soundfont_dls.isEmpty()) { QByteArray utf8file = m_soundfont_dls.toUtf8(); CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, reinterpret_cast(utf8file.data()), utf8file.length(), false); if (url) { // kMusicDeviceProperty_SoundBankURL since 10.5 result = AudioUnitSetProperty(m_synthUnit, kMusicDeviceProperty_SoundBankURL, kAudioUnitScope_Global, 0, &url, sizeof(url)); registerStatus( "AudioUnitSetProperty(SoundBankURL)", result); CFRelease(url); } } usesReverb = (m_reverb_dls ? 1 : 0); //qDebug() << "usesReverb =" << usesReverb; result = AudioUnitSetProperty ( m_synthUnit, kMusicDeviceProperty_UsesInternalReverb, kAudioUnitScope_Global, 0, &usesReverb, sizeof (usesReverb) ); registerStatus( "AudioUnitSetProperty(UsesInternalReverb)", result); result = AUGraphInitialize (m_graph); registerStatus( "AUGraphInitialize", result); if (result != noErr) { return; } for (uint i = 0; i < 16; ++i) { result = MusicDeviceMIDIEvent(m_synthUnit, MIDI_STATUS_CONTROLCHANGE+i, MIDI_CTL_MSB_MAIN_VOLUME,100,0); registerStatus( "MusicDeviceMIDIEvent", result ); result = MusicDeviceMIDIEvent(m_synthUnit, MIDI_STATUS_CONTROLCHANGE+i, MIDI_CTL_REVERB_SEND,100,0); registerStatus( "MusicDeviceMIDIEvent", result ); result = MusicDeviceMIDIEvent(m_synthUnit, MIDI_STATUS_CONTROLCHANGE+i, MIDI_CTL_MSB_BANK_SELECT,0,0); registerStatus( "MusicDeviceMIDIEvent", result ); result = MusicDeviceMIDIEvent(m_synthUnit, MIDI_STATUS_CONTROLCHANGE+i, MIDI_CTL_LSB_BANK_SELECT,0,0); registerStatus( "MusicDeviceMIDIEvent", result ); result = MusicDeviceMIDIEvent(m_synthUnit, MIDI_STATUS_PROGRAMCHANGE+i, 0,0,0); registerStatus( "MusicDeviceMIDIEvent", result ); } result = AUGraphStart (m_graph); registerStatus( "AUGraphStart", result); if (result != noErr) { return; } } m_connection = QString(QLatin1String(PRETTY_NAME)); } void stop () { OSStatus result; //qDebug() << Q_FUNC_INFO; if (m_graph != nullptr) { result = AUGraphStop(m_graph); if (result != noErr) qWarning() << "AUGraphStop() err:" << result; result = AUGraphClose(m_graph); if (result != noErr) qWarning() << "AUGraphClose() err:" << result; result = DisposeAUGraph(m_graph); if (result != noErr) qWarning() << "DisposeAUGraph() err:" << result; m_graph = nullptr; } m_connection.clear(); } void initialize ( QSettings *settings ) { //qDebug() << Q_FUNC_INFO; settings->beginGroup(PRETTY_NAME); m_default_dls = settings->value("default_dls", true).toBool(); m_reverb_dls = settings->value("reverb_dls", false).toBool(); m_soundfont_dls = settings->value("soundfont_dls").toString(); //qDebug() << "default_dls:" << m_default_dls; //qDebug() << "reverb_dls:" << m_reverb_dls; //qDebug() << "soundfont_dls" << m_soundfont_dls; settings->endGroup(); } void registerStatus(const QString& context, const long status) { if (status != noErr) { qWarning() << context << "err:" << status; } //else { // qDebug() << context; //} } void sendStatusEvent(uint status, uint data1, uint data2) { MusicDeviceMIDIEvent ( m_synthUnit, status, data1, data2, 0 ); } void sendSysexEvent(Byte *msg, uint msglen) { MusicDeviceSysEx ( m_synthUnit, msg, msglen ); } }; MacSynthOutput::MacSynthOutput(QObject *parent): MIDIOutput(parent), d(new MacSynthOutputPrivate) { } MacSynthOutput::~MacSynthOutput() { delete d; } void MacSynthOutput::initialize(QSettings* settings) { d->initialize(settings); } QString MacSynthOutput::backendName() { return QLatin1String(PRETTY_NAME); } QString MacSynthOutput::publicName() { return QLatin1String(PRETTY_NAME); } void MacSynthOutput::setPublicName(QString name) { Q_UNUSED(name) } QStringList MacSynthOutput::connections(bool advanced) { Q_UNUSED(advanced) return QStringList(QLatin1String(PRETTY_NAME)); } void MacSynthOutput::setExcludedConnections(QStringList conns) { Q_UNUSED(conns) } void MacSynthOutput::open(QString name) { Q_UNUSED(name) //qDebug() << Q_FUNC_INFO; d->start(); } void MacSynthOutput::close() { //qDebug() << Q_FUNC_INFO; d->stop(); } QString MacSynthOutput::currentConnection() { return d->currentConnection(); } void MacSynthOutput::sendNoteOn(int chan, int note, int vel) { uint status, data1, data2; status = MIDI_STATUS_NOTEON | (chan & 0x0f); data1 = static_cast(note); data2 = static_cast(vel); d->sendStatusEvent(status, data1, data2); } void MacSynthOutput::sendNoteOff(int chan, int note, int vel) { uint status, data1, data2; status = MIDI_STATUS_NOTEOFF | (chan & 0x0f); data1 = static_cast(note); data2 = static_cast(vel); d->sendStatusEvent(status, data1, data2); } void MacSynthOutput::sendController(int chan, int control, int value) { uint status, data1, data2; status = MIDI_STATUS_CONTROLCHANGE | (chan & 0x0f); data1 = static_cast(control); data2 = static_cast(value); d->sendStatusEvent(status, data1, data2); } void MacSynthOutput::sendKeyPressure(int chan, int note, int value) { uint status, data1, data2; status = MIDI_STATUS_KEYPRESURE | (chan & 0x0f); data1 = static_cast(note); data2 = static_cast(value); d->sendStatusEvent(status, data1, data2); } void MacSynthOutput::sendProgram(int chan, int program) { uint status, data1, data2; status = MIDI_STATUS_PROGRAMCHANGE | (chan & 0x0f); data1 = static_cast(program); data2 = 0; d->sendStatusEvent(status, data1, data2); } void MacSynthOutput::sendChannelPressure(int chan, int value) { uint status, data1, data2; status = MIDI_STATUS_CHANNELPRESSURE | (chan & 0x0f); data1 = static_cast(value); data2 = 0; d->sendStatusEvent(status, data1, data2); } void MacSynthOutput::sendPitchBend(int chan, int value) { uint status, data1, data2; quint16 val = static_cast(value + 8192); // value between -8192 and +8191 status = MIDI_STATUS_PITCHBEND | (chan & 0x0f); data1 = MIDI_LSB(val); // LSB data2 = MIDI_MSB(val); // MSB d->sendStatusEvent(status, data1, data2); } void MacSynthOutput::sendSysex(const QByteArray& data) { d->sendSysexEvent(reinterpret_cast(const_cast(data.data())), static_cast(data.length())); } void MacSynthOutput::sendSystemMsg(const int status) { d->sendStatusEvent(static_cast(status), 0, 0); } }} drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/alsa-in0000644000000000000000000000013213532747316020403 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.930000148 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/alsa-in/0000755000175000001440000000000013532747316021251 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/alsa-in/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316023220 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.930000148 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/alsa-in/CMakeLists.txt0000644000175000001440000000402113532747316024006 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(CMAKE_INCLUDE_CURRENT_DIR ON) set(drumstick-rt-alsa-in_QTOBJ_SRCS ../../include/drumstick/rtmidiinput.h ../../include/drumstick/rtmidioutput.h alsamidiinput.h ) set(drumstick-rt-alsa-in_SRCS alsamidiinput.cpp ) qt5_wrap_cpp(drumstick-rt-alsa-in_MOC_SRCS ${drumstick-rt-alsa-in_QTOBJ_SRCS} OPTIONS -I ${DRUMSTICK_SOURCE_DIR}/library/include ) if(STATIC_DRUMSTICK) add_library(drumstick-rt-alsa-in STATIC ${drumstick-rt-alsa-in_MOC_SRCS} ${drumstick-rt-alsa-in_SRCS}) target_compile_definitions(drumstick-rt-alsa-in PRIVATE QT_STATICPLUGIN) set_target_properties(drumstick-rt-alsa-in PROPERTIES STATIC_LIB "libdrumstick-rt-alsa-in") else() add_library(drumstick-rt-alsa-in MODULE ${drumstick-rt-alsa-in_MOC_SRCS} ${drumstick-rt-alsa-in_SRCS}) target_compile_definitions(drumstick-rt-alsa-in PRIVATE QT_PLUGIN) endif() target_link_libraries(drumstick-rt-alsa-in drumstick-alsa Qt5::Core) set_target_properties(drumstick-rt-alsa-in PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/drumstick) install(TARGETS drumstick-rt-alsa-in RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick) drumstick-1.1.3/library/rt-backends/alsa-in/PaxHeaders.32572/alsa-in.pro0000644000000000000000000000013213532747316022526 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.930000148 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/alsa-in/alsa-in.pro0000644000175000001440000000074413532747316023324 0ustar00pedrousers00000000000000TEMPLATE = lib CONFIG += plugin static { CONFIG += staticlib create_prl } TARGET = drumstick-rt-alsa-in DESTDIR = ../../../build/lib/drumstick DEPENDPATH += . ../../include INCLUDEPATH += . ../../include include (../../../global.pri) QT -= gui HEADERS += ../../include/drumstick/rtmidiinput.h \ ../../include/drumstick/rtmidioutput.h \ alsamidiinput.h SOURCES += alsamidiinput.cpp LIBS += -L../../../build/lib \ -ldrumstick-alsa \ -lasound drumstick-1.1.3/library/rt-backends/alsa-in/PaxHeaders.32572/alsamidiinput.h0000644000000000000000000000013213532747316023474 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.930000148 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/alsa-in/alsamidiinput.h0000644000175000001440000000372013532747316024267 0ustar00pedrousers00000000000000/* Drumstick RT Backend using the ALSA Sequencer Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef ALSAMIDIInput_H #define ALSAMIDIInput_H #include #include #include namespace drumstick { namespace rt { class ALSAMIDIInput: public MIDIInput { Q_OBJECT #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) Q_PLUGIN_METADATA(IID "net.sourceforge.drumstick.rt.MIDIInput") #endif Q_INTERFACES(drumstick::rt::MIDIInput) public: ALSAMIDIInput(QObject *parent = 0); virtual ~ALSAMIDIInput(); // MIDIInput interface virtual void initialize(QSettings* settings); virtual QString backendName(); virtual QString publicName(); virtual void setPublicName(QString name); virtual QStringList connections(bool advanced); virtual void setExcludedConnections(QStringList conns); virtual void open(QString name); virtual void close(); virtual QString currentConnection(); virtual void setMIDIThruDevice(MIDIOutput *device); virtual void enableMIDIThru(bool enable); virtual bool isEnabledMIDIThru(); private: class ALSAMIDIInputPrivate; ALSAMIDIInputPrivate * const d; }; }} #endif /* ALSAMIDIInput_H */ drumstick-1.1.3/library/rt-backends/alsa-in/PaxHeaders.32572/alsamidiinput.cpp0000644000000000000000000000013213532747316024027 xustar0030 mtime=1567346382.693999845 30 atime=1567346382.930000148 30 ctime=1567346382.693999845 drumstick-1.1.3/library/rt-backends/alsa-in/alsamidiinput.cpp0000644000175000001440000002571513532747316024632 0ustar00pedrousers00000000000000/* Drumstick RT Backend using the ALSA Sequencer Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include "alsamidiinput.h" namespace drumstick { namespace rt { static QString DEFAULT_PUBLIC_NAME(QLatin1String("MIDI In")); class ALSAMIDIInput::ALSAMIDIInputPrivate : public SequencerEventHandler { public: ALSAMIDIInput *m_inp; MIDIOutput *m_out; MidiClient *m_client; MidiPort *m_port; int m_portId; int m_clientId; bool m_thruEnabled; bool m_clientFilter; int m_runtimeAlsaNum; QString m_publicName; QString m_currentInput; QStringList m_inputDevices; QStringList m_excludedNames; QMutex m_openMutex; ALSAMIDIInputPrivate(ALSAMIDIInput *inp) : m_inp(inp), m_out(0), m_client(0), m_port(0), m_portId(-1), m_clientId(-1), m_thruEnabled(false), m_publicName(DEFAULT_PUBLIC_NAME) { m_runtimeAlsaNum = getRuntimeALSALibraryNumber(); m_client = new MidiClient(m_inp); m_client->open(); m_client->setClientName(m_publicName); m_port = m_client->createPort(); m_port->setPortName("in"); m_port->setCapability( SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE ); m_port->setPortType( SND_SEQ_PORT_TYPE_APPLICATION | SND_SEQ_PORT_TYPE_MIDI_GENERIC ); m_clientId = m_client->getClientId(); m_portId = m_port->getPortId(); m_port->setTimestamping(false); m_port->setTimestampReal(false); m_client->setHandler(this); } virtual ~ALSAMIDIInputPrivate() { if (m_client != NULL) { clearSubscription(); if (m_port != NULL) m_port->detach(); m_client->close(); delete m_client; } } bool clientIsAdvanced(int clientId) { // asking for runtime version instead of SND_LIB_VERSION if (m_runtimeAlsaNum < 0x01000B) // ALSA <= 1.0.10 return (clientId < 64); else // ALSA >= 1.0.11 return (clientId < 16); } void reloadDeviceList(bool advanced) { m_clientFilter = !advanced; m_inputDevices.clear(); QListIterator it(m_client->getAvailableInputs()); while(it.hasNext()) { bool excluded = false; PortInfo p = it.next(); QString name = QString("%1:%2").arg(p.getClientName()).arg(p.getPort()); if (m_clientFilter && clientIsAdvanced(p.getClient())) continue; if ( m_clientFilter && name.startsWith(QLatin1String("Virtual Raw MIDI")) ) continue; if ( name.startsWith(m_publicName) ) continue; foreach(const QString& n, m_excludedNames) { if (name.startsWith(n)) { excluded = true; break; } } if (!excluded) m_inputDevices << name; } if (!m_currentInput.isEmpty() && !m_inputDevices.contains(m_currentInput)) { m_currentInput.clear(); } } bool setSubscription(const QString &newDevice) { //qDebug() << Q_FUNC_INFO << newDevice; if (m_inputDevices.contains(newDevice)) { m_currentInput = newDevice; m_port->unsubscribeAll(); m_port->subscribeFrom(newDevice); m_client->startSequencerInput(); return true; } return false; } void clearSubscription() { if (!m_currentInput.isEmpty()) { m_client->stopSequencerInput(); m_port->unsubscribeAll(); m_currentInput.clear(); } } void setPublicName(QString newName) { if (newName != m_publicName) { m_client->setClientName(newName); m_publicName = newName; } } void handleSequencerEvent(SequencerEvent* ev) { if ( !SequencerEvent::isConnectionChange(ev) ) switch(ev->getSequencerType()) { case SND_SEQ_EVENT_NOTEOFF: { const NoteOffEvent* n = static_cast(ev); if(m_out != 0 && m_thruEnabled) { m_out->sendNoteOff(n->getChannel(), n->getKey(), n->getVelocity()); } emit m_inp->midiNoteOff(n->getChannel(), n->getKey(), n->getVelocity()); } break; case SND_SEQ_EVENT_NOTEON: { const NoteOnEvent* n = static_cast(ev); if(m_out != 0 && m_thruEnabled) { m_out->sendNoteOn(n->getChannel(), n->getKey(), n->getVelocity()); } emit m_inp->midiNoteOn(n->getChannel(), n->getKey(), n->getVelocity()); } break; case SND_SEQ_EVENT_KEYPRESS: { const KeyPressEvent* n = static_cast(ev); if(m_out != 0 && m_thruEnabled) { m_out->sendKeyPressure(n->getChannel(), n->getKey(), n->getVelocity()); } emit m_inp->midiKeyPressure(n->getChannel(), n->getKey(), n->getVelocity()); } break; case SND_SEQ_EVENT_CONTROLLER: case SND_SEQ_EVENT_CONTROL14: { const ControllerEvent* n = static_cast(ev); if(m_out != 0 && m_thruEnabled) { m_out->sendController(n->getChannel(), n->getParam(), n->getValue()); } emit m_inp->midiController(n->getChannel(), n->getParam(), n->getValue()); } break; case SND_SEQ_EVENT_PGMCHANGE: { const ProgramChangeEvent* p = static_cast(ev); if(m_out != 0 && m_thruEnabled) { m_out->sendProgram(p->getChannel(), p->getValue()); } emit m_inp->midiProgram(p->getChannel(), p->getValue()); } break; case SND_SEQ_EVENT_CHANPRESS: { const ChanPressEvent* n = static_cast(ev); if(m_out != 0 && m_thruEnabled) { m_out->sendChannelPressure(n->getChannel(), n->getValue()); } emit m_inp->midiChannelPressure(n->getChannel(), n->getValue()); } break; case SND_SEQ_EVENT_PITCHBEND: { const PitchBendEvent* n = static_cast(ev); if(m_out != 0 && m_thruEnabled) { m_out->sendPitchBend(n->getChannel(), n->getValue()); } emit m_inp->midiPitchBend(n->getChannel(), n->getValue()); } break; case SND_SEQ_EVENT_SYSEX: { const SysExEvent* n = static_cast(ev); QByteArray data(n->getData(), n->getLength()); if(m_out != 0 && m_thruEnabled) { m_out->sendSysex(data); } emit m_inp->midiSysex(data); } break; case SND_SEQ_EVENT_SYSTEM: { const SystemEvent* n = static_cast(ev); int status = (int) n->getRaw8(0); if(m_out != 0 && m_thruEnabled) { m_out->sendSystemMsg(status); } if (status < 0xF7) emit m_inp->midiSystemCommon(status); else if (status > 0xF7) emit m_inp->midiSystemRealtime(status); } break; default: break; } delete ev; } }; ALSAMIDIInput::ALSAMIDIInput(QObject *parent) : MIDIInput(parent), d(new ALSAMIDIInputPrivate(this)) { } ALSAMIDIInput::~ALSAMIDIInput() { delete d; } void ALSAMIDIInput::initialize(QSettings* settings) { Q_UNUSED(settings) } QString ALSAMIDIInput::backendName() { return QLatin1String("ALSA"); } QString ALSAMIDIInput::publicName() { return d->m_publicName; } void ALSAMIDIInput::setPublicName(QString name) { d->setPublicName(name); } QStringList ALSAMIDIInput::connections(bool advanced) { d->reloadDeviceList(advanced); return d->m_inputDevices; } void ALSAMIDIInput::setExcludedConnections(QStringList conns) { d->m_excludedNames = conns; } void ALSAMIDIInput::open(QString name) { d->setSubscription(name); } void ALSAMIDIInput::close() { d->clearSubscription(); } QString ALSAMIDIInput::currentConnection() { return d->m_currentInput; } void ALSAMIDIInput::setMIDIThruDevice(MIDIOutput *device) { d->m_out = device; } void ALSAMIDIInput::enableMIDIThru(bool enable) { d->m_thruEnabled = enable; } bool ALSAMIDIInput::isEnabledMIDIThru() { return d->m_thruEnabled && (d->m_out != 0); } }} drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/oss-in0000644000000000000000000000013013532747316020265 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/oss-in/0000755000175000001440000000000013532747316021135 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/oss-in/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013013532747316023102 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/oss-in/CMakeLists.txt0000644000175000001440000000432513532747316023701 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(CMAKE_INCLUDE_CURRENT_DIR ON) #include_directories(../common) set(drumstick-rt-oss-in_QTOBJ_SRCS ../../include/drumstick/rtmidiinput.h ../../include/drumstick/rtmidioutput.h ../common/midiparser.h ossinput_p.h ossinput.h ) set(drumstick-rt-oss-in_SRCS ../common/midiparser.cpp ossinput_p.cpp ossinput.cpp ) qt5_wrap_cpp(drumstick-rt-oss-in_MOC_SRCS ${drumstick-rt-oss-in_QTOBJ_SRCS} OPTIONS -I ${DRUMSTICK_SOURCE_DIR}/library/include ) if(STATIC_DRUMSTICK) add_library(drumstick-rt-oss-in STATIC ${drumstick-rt-oss-in_MOC_SRCS} ${drumstick-rt-oss-in_SRCS}) target_compile_definitions(drumstick-rt-oss-in PRIVATE QT_STATICPLUGIN) set_target_properties(drumstick-rt-oss-in PROPERTIES STATIC_LIB "libdrumstick-rt-oss-in") else() add_library(drumstick-rt-oss-in MODULE ${drumstick-rt-oss-in_MOC_SRCS} ${drumstick-rt-oss-in_SRCS}) target_compile_definitions(drumstick-rt-oss-in PRIVATE QT_PLUGIN) endif() target_include_directories(drumstick-rt-oss-in PRIVATE ${DRUMSTICK_SOURCE_DIR}/library/include ../common ) target_link_libraries(drumstick-rt-oss-in Qt5::Core) set_target_properties(drumstick-rt-oss-in PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/drumstick) install(TARGETS drumstick-rt-oss-in RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick) drumstick-1.1.3/library/rt-backends/oss-in/PaxHeaders.32572/ossinput.cpp0000644000000000000000000000013013532747316022732 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/oss-in/ossinput.cpp0000644000175000001440000000355413532747316023534 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "ossinput.h" namespace drumstick { namespace rt { OSSInput::OSSInput(QObject *parent) : MIDIInput(parent), d(new OSSInputPrivate(this)) { } OSSInput::~OSSInput() { delete d; } void OSSInput::initialize(QSettings *settings) { Q_UNUSED(settings) } QString OSSInput::backendName() { return "OSS"; } QString OSSInput::publicName() { return d->m_publicName; } void OSSInput::setPublicName(QString name) { d->m_publicName = name; } QStringList OSSInput::connections(bool advanced) { d->reloadDeviceList(advanced); return d->m_inputDevices; } void OSSInput::setExcludedConnections(QStringList conns) { Q_UNUSED(conns) } QString OSSInput::currentConnection() { return d->m_currentInput; } void OSSInput::open(QString name) { d->open(name); } void OSSInput::close() { d->close(); } void OSSInput::setMIDIThruDevice(MIDIOutput *device) { d->setMIDIThruDevice(device); //d->m_out = device; } void OSSInput::enableMIDIThru(bool enable) { d->m_thruEnabled = enable; } bool OSSInput::isEnabledMIDIThru() { return d->m_thruEnabled && (d->m_out != 0); } }} drumstick-1.1.3/library/rt-backends/oss-in/PaxHeaders.32572/ossinput_p.cpp0000644000000000000000000000013013532747316023251 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/oss-in/ossinput_p.cpp0000644000175000001440000000550613532747316024052 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include "ossinput_p.h" #include "ossinput.h" namespace drumstick { namespace rt { static QString DEFAULT_PUBLIC_NAME(QLatin1String("MIDI In")); OSSInputPrivate::OSSInputPrivate(QObject *parent) : QObject(parent), m_inp(qobject_cast(parent)), m_out(0), m_device(0), m_notifier(0), m_parser(0), m_thruEnabled(false), m_advanced(false), m_publicName(DEFAULT_PUBLIC_NAME) { reloadDeviceList(); } void OSSInputPrivate::reloadDeviceList(bool advanced) { QDir dir("/dev"); QStringList filters; m_advanced = advanced; filters << "dmmidi*" << "admmidi*"; if (advanced) { filters << "midi*" << "amidi*"; } dir.setNameFilters(filters); dir.setFilter(QDir::System); dir.setSorting(QDir::Name); m_inputDevices.clear(); QFileInfoList listInfo = dir.entryInfoList(); foreach(const QFileInfo &info, listInfo) { m_inputDevices << info.absoluteFilePath(); } } void OSSInputPrivate::open(QString portName) { QFile *f = new QFile(portName); m_currentInput = portName; m_device = f; m_device->open( QIODevice::ReadOnly | QIODevice::Unbuffered ); m_notifier = new QSocketNotifier(f->handle(), QSocketNotifier::Read); m_parser = new MIDIParser(m_inp); m_buffer.clear(); connect(m_notifier, SIGNAL(activated(int)), this, SLOT(processIncomingMessages(int))); //qDebug() << Q_FUNC_INFO << portName; } void OSSInputPrivate::close() { if (m_device != 0) { m_device->close(); delete m_notifier; delete m_device; delete m_parser; m_device = 0; m_parser = 0; } m_currentInput.clear(); } void OSSInputPrivate::setMIDIThruDevice(MIDIOutput* device) { m_out = device; if (m_parser != 0) { m_parser->setMIDIThruDevice(device); } } void OSSInputPrivate::processIncomingMessages(int) { char ch; m_device->getChar(&ch); if (m_parser != 0) { uchar uch = static_cast(ch); m_parser->parse(uch); } } }} drumstick-1.1.3/library/rt-backends/oss-in/PaxHeaders.32572/oss-in.pro0000644000000000000000000000013013532747316022274 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/oss-in/oss-in.pro0000644000175000001440000000104013532747316023062 0ustar00pedrousers00000000000000TEMPLATE = lib TARGET = drumstick-rt-oss-in DESTDIR = ../../../build/lib/drumstick include (../../../global.pri) CONFIG += plugin static { CONFIG += staticlib create_prl } DEPENDPATH += ../../include ../common INCLUDEPATH += ../../include ../common QT -= gui HEADERS += ../../include/drumstick/rtmidiinput.h \ ../../include/drumstick/rtmidioutput.h \ ../common/midiparser.h \ ossinput_p.h \ ossinput.h SOURCES += ossinput.cpp \ ossinput_p.cpp \ ../common/midiparser.cpp drumstick-1.1.3/library/rt-backends/oss-in/PaxHeaders.32572/ossinput_p.h0000644000000000000000000000013013532747316022716 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/oss-in/ossinput_p.h0000644000175000001440000000324213532747316023512 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef OSSINPUT_P_H #define OSSINPUT_P_H #include #include #include #include #include #include "midiparser.h" namespace drumstick { namespace rt { class MIDIOutput; class OSSInput; class OSSInputPrivate : public QObject { Q_OBJECT public: OSSInput *m_inp; MIDIOutput *m_out; QIODevice *m_device; QSocketNotifier *m_notifier; MIDIParser *m_parser; bool m_thruEnabled; bool m_advanced; QString m_publicName; QString m_currentInput; QStringList m_inputDevices; QStringList m_excludedNames; QByteArray m_buffer; OSSInputPrivate(QObject *parent = 0); void reloadDeviceList(bool advanced = false); void open(QString portName); void close(); //void parse(); void setMIDIThruDevice(MIDIOutput* device); public slots: void processIncomingMessages(int); }; }} #endif // OSSINPUT_P_H drumstick-1.1.3/library/rt-backends/oss-in/PaxHeaders.32572/ossinput.h0000644000000000000000000000013013532747316022377 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt-backends/oss-in/ossinput.h0000644000175000001440000000362713532747316023202 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef ossINPUT_H #define ossINPUT_H #include #include #include #include "ossinput_p.h" namespace drumstick { namespace rt { class OSSInput : public MIDIInput { Q_OBJECT #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) Q_PLUGIN_METADATA(IID "net.sourceforge.drumstick.rt.MIDIInput") #endif Q_INTERFACES(drumstick::rt::MIDIInput) public: OSSInput(QObject *parent = 0); virtual ~OSSInput(); // MIDIInput interface public: virtual void initialize(QSettings* settings); virtual QString backendName(); virtual QString publicName(); virtual void setPublicName(QString name); virtual QStringList connections(bool advanced); virtual void setExcludedConnections(QStringList conns); virtual void open(QString name); virtual void close(); virtual QString currentConnection(); virtual void setMIDIThruDevice(MIDIOutput *device); virtual void enableMIDIThru(bool enable); virtual bool isEnabledMIDIThru(); private: OSSInputPrivate *d; }; }} #endif // ossINPUT_H drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/mac-out0000644000000000000000000000013213532747316020424 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/mac-out/0000755000175000001440000000000013532747316021272 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/mac-out/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316023241 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/mac-out/CMakeLists.txt0000644000175000001440000000426513532747316024041 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(CMAKE_INCLUDE_CURRENT_DIR ON) set(drumstick-rt-mac-out_QTOBJ_SRCS ../../include/drumstick/rtmidioutput.h macmidioutput.h ) set(drumstick-rt-mac-out_SRCS ../common/maccommon.h ../common/maccommon.cpp macmidioutput.cpp ) qt5_wrap_cpp(drumstick-rt-mac-out_MOC_SRCS ${drumstick-rt-mac-out_QTOBJ_SRCS} OPTIONS -I ${DRUMSTICK_SOURCE_DIR}/library/include ) if(STATIC_DRUMSTICK) add_library(drumstick-rt-mac-out STATIC ${drumstick-rt-mac-out_MOC_SRCS} ${drumstick-rt-mac-out_SRCS}) target_compile_definitions(drumstick-rt-mac-out PRIVATE QT_STATICPLUGIN) set_target_properties(drumstick-rt-mac-out PROPERTIES STATIC_LIB "libdrumstick-rt-mac-out") else() add_library(drumstick-rt-mac-out MODULE ${drumstick-rt-mac-out_MOC_SRCS} ${drumstick-rt-mac-out_SRCS}) target_compile_definitions(drumstick-rt-mac-out PRIVATE QT_PLUGIN) endif() target_link_libraries(drumstick-rt-mac-out Qt5::Core "-framework CoreMIDI -framework CoreFoundation" ) target_include_directories(drumstick-rt-mac-out PRIVATE ${DRUMSTICK_SOURCE_DIR}/library/include ../common ) set_target_properties(drumstick-rt-mac-out PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/drumstick) install(TARGETS drumstick-rt-mac-out RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/drumstick) drumstick-1.1.3/library/rt-backends/mac-out/PaxHeaders.32572/macmidioutput.h0000644000000000000000000000013213532747316023536 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/mac-out/macmidioutput.h0000644000175000001440000000447313532747316024337 0ustar00pedrousers00000000000000/* Drumstick RT Backend Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef MACMIDIOUTPUT_H #define MACMIDIOUTPUT_H #include namespace drumstick { namespace rt { class MacMIDIOutput : public MIDIOutput { Q_OBJECT #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) Q_PLUGIN_METADATA(IID "net.sourceforge.drumstick.rt.MIDIOutput") #endif Q_INTERFACES(drumstick::rt::MIDIOutput) public: explicit MacMIDIOutput(QObject *parent = 0); virtual ~MacMIDIOutput(); // MIDIOutput interface virtual void initialize(QSettings* settings); virtual QString backendName(); virtual QString publicName(); virtual void setPublicName(QString name); virtual QStringList connections(bool advanced); virtual void setExcludedConnections(QStringList conns); virtual void open(QString name); virtual void close(); virtual QString currentConnection(); public slots: virtual void sendNoteOff(int chan, int note, int vel); virtual void sendNoteOn(int chan, int note, int vel); virtual void sendKeyPressure(int chan, int note, int value); virtual void sendController(int chan, int control, int value); virtual void sendProgram(int chan, int program); virtual void sendChannelPressure(int chan, int value); virtual void sendPitchBend(int chan, int value); virtual void sendSysex(const QByteArray &data); virtual void sendSystemMsg(const int status); private: class MacMIDIOutputPrivate; MacMIDIOutputPrivate* const d; }; }} #endif // MACMIDIOUTPUT_H drumstick-1.1.3/library/rt-backends/mac-out/PaxHeaders.32572/mac-out.pro0000644000000000000000000000013213532747316022570 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/mac-out/mac-out.pro0000644000175000001440000000117513532747316023365 0ustar00pedrousers00000000000000TEMPLATE = lib CONFIG += plugin static { CONFIG += staticlib create_prl } TARGET = drumstick-rt-mac-out DESTDIR = ../../../build/lib/drumstick DEPENDPATH += . ../../include ../common INCLUDEPATH += . ../../include ../common include (../../../global.pri) QT -= gui HEADERS += ../../include/drumstick/rtmidiinput.h \ ../../include/drumstick/rtmidioutput.h \ macmidioutput.h \ ../common/maccommon.h SOURCES += \ macmidioutput.cpp \ ../common/maccommon.cpp LIBS += -framework CoreMIDI -framework CoreFoundation #-framework CoreAudio -framework AudioToolbox -framework AudioUnit drumstick-1.1.3/library/rt-backends/mac-out/PaxHeaders.32572/macmidioutput.cpp0000644000000000000000000000013213532747316024071 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/mac-out/macmidioutput.cpp0000644000175000001440000003132713532747316024670 0ustar00pedrousers00000000000000/* Drumstick RT Backend Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "macmidioutput.h" #include "maccommon.h" #include #include #include #include #include #include #include #include namespace drumstick { namespace rt { static CFStringRef DEFAULT_PUBLIC_NAME CFSTR("MIDI Out"); class MacMIDIOutput::MacMIDIOutputPrivate { public: MIDIClientRef m_client; MIDIPortRef m_port; MIDIEndpointRef m_endpoint; MIDIEndpointRef m_destination; bool m_clientFilter; QString m_currentOutput; QString m_publicName; QStringList m_excludedNames; QStringList m_outputDevices; MacMIDIOutputPrivate(): m_client(0), m_port(0), m_endpoint(0), m_destination(0), m_clientFilter(true), m_publicName(QString::fromCFString(DEFAULT_PUBLIC_NAME)) { internalCreate(DEFAULT_PUBLIC_NAME); } void internalCreate(CFStringRef name) { OSStatus result = noErr; result = MIDIClientCreate( name, NULL, NULL, &m_client ); if ( result != noErr ) { qDebug() << "MIDIClientCreate() error:" << result; return; } result = MIDISourceCreate( m_client, name, &m_endpoint ); if ( result != noErr ) { qDebug() << "MIDISourceCreate() error:" << result; return; } result = MIDIOutputPortCreate( m_client, name, &m_port ); if (result != noErr) { qDebug() << "MIDIOutputPortCreate() error:" << result; return; } reloadDeviceList(true); } virtual ~MacMIDIOutputPrivate() { internalDispose(); } void internalDispose() { OSStatus result = noErr; if (m_port != 0) { result = MIDIPortDispose( m_port ); if (result != noErr) { qDebug() << "MIDIPortDispose() error:" << result; m_port = 0; } } if (m_endpoint != 0) { result = MIDIEndpointDispose( m_endpoint ); if (result != noErr) { qDebug() << "MIDIEndpointDispose() err:" << result; m_endpoint = 0; } } if (m_client != 0) { result = MIDIClientDispose( m_client ); if (result != noErr) { qDebug() << "MIDIClientDispose() error:" << result; m_client = 0; } } } void setPublicName(QString name) { if (m_publicName != name) { internalDispose(); internalCreate(name.toCFString()); m_publicName = name; } } void reloadDeviceList(bool advanced) { int num = MIDIGetNumberOfDestinations(); m_clientFilter = !advanced; m_outputDevices.clear(); for (int i = 0; i < num; ++i) { bool excluded = false; MIDIEndpointRef dest = MIDIGetDestination( i ); if (dest != 0) { QString name = getEndpointName(dest); if ( m_clientFilter && name.contains(QLatin1String("IAC"), Qt::CaseSensitive) ) continue; if ( name.contains (m_publicName) ) continue; foreach ( const QString& n, m_excludedNames ) { if ( name.contains(n) ) { excluded = true; break; } } if (!excluded) m_outputDevices << name; } } if (!m_currentOutput.isEmpty() && m_destination != 0 && !m_outputDevices.contains(m_currentOutput)) { m_currentOutput.clear(); m_destination = 0; } } void sendEvents( const MIDIPacketList* events ) { MIDIReceived(m_endpoint, events); if (m_destination != 0) MIDISend(m_port, m_destination, events); } bool open(const QString &name) { int index; QStringList allOutputDevices; int num = MIDIGetNumberOfDestinations(); for (int i = 0; i < num; ++i) { MIDIEndpointRef dest = MIDIGetDestination( i ); if (dest != 0) allOutputDevices << getEndpointName( dest ); } index = allOutputDevices.indexOf(name); if (index < 0) return false; m_destination = MIDIGetDestination( index ); m_currentOutput = name; return true; } void close() { m_destination = 0; m_currentOutput.clear(); } }; MacMIDIOutput::MacMIDIOutput(QObject *parent) : MIDIOutput(parent), d(new MacMIDIOutputPrivate) { } MacMIDIOutput::~MacMIDIOutput() { delete d; } void MacMIDIOutput::initialize(QSettings *settings) { Q_UNUSED(settings) } QString MacMIDIOutput::backendName() { return QLatin1Literal("CoreMIDI"); } QString MacMIDIOutput::publicName() { return d->m_publicName; } void MacMIDIOutput::setPublicName(QString name) { d->setPublicName(name); } QStringList MacMIDIOutput::connections(bool advanced) { d->reloadDeviceList(advanced); return d->m_outputDevices; } void MacMIDIOutput::setExcludedConnections(QStringList conns) { d->m_excludedNames = conns; } void MacMIDIOutput::open(QString name) { d->open(name); } void MacMIDIOutput::close() { d->close(); } QString MacMIDIOutput::currentConnection() { return d->m_currentOutput; } /* Realtime MIDI slots */ /*void MacMIDIOutput::allNotesOff() { quint8 data[3]; quint8 buf[2048]; MIDIPacketList* pktlist = (MIDIPacketList*) &buf; MIDIPacket* packet = MIDIPacketListInit(pktlist); for(int chan = 0; chan < MIDI_CHANNELS && packet != NULL; ++chan) { data[0] = MIDI_STATUS_CONTROLCHANGE | (chan & 0x0f); data[1] = MIDI_CTL_ALL_NOTES_OFF; data[2] = 0; packet = MIDIPacketListAdd(pktlist, sizeof(buf), packet, 0, sizeof(data), data); if (packet != NULL) { data[1] = MIDI_CTL_ALL_SOUNDS_OFF; packet = MIDIPacketListAdd(pktlist, sizeof(buf), packet, 0, sizeof(data), data); } } if (packet != NULL) d->sendEvents(pktlist); }*/ /*void MacMIDIOutput::resetControllers() { quint8 data[3]; quint8 buf[2048]; MIDIPacketList* pktlist = (MIDIPacketList*) &buf; MIDIPacket* packet = MIDIPacketListInit(pktlist); for(int chan = 0; chan < MIDI_CHANNELS && packet != NULL; ++chan) { data[0] = MIDI_STATUS_CONTROLCHANGE | (chan & 0x0f); data[1] = MIDI_CTL_RESET_CONTROLLERS; data[2] = 0; packet = MIDIPacketListAdd(pktlist, sizeof(buf), packet, 0, sizeof(data), data); if (packet != NULL) { data[1] = MIDI_CTL_MSB_MAIN_VOLUME; data[2] = 100; packet = MIDIPacketListAdd(pktlist, sizeof(buf), packet, 0, sizeof(data), data); } } if (packet != NULL) d->sendEvents(pktlist); }*/ void MacMIDIOutput::sendNoteOn(int chan, int note, int vel) { quint8 data[3]; MIDIPacketList pktlist ; MIDIPacket* packet = MIDIPacketListInit(&pktlist); data[0] = MIDI_STATUS_NOTEON | (chan & 0x0f); data[1] = note; data[2] = vel; packet = MIDIPacketListAdd(&pktlist, sizeof(pktlist), packet, 0, sizeof(data), data); if (packet != NULL) d->sendEvents(&pktlist); } void MacMIDIOutput::sendNoteOff(int chan, int note, int vel) { quint8 data[3]; MIDIPacketList pktlist ; MIDIPacket* packet = MIDIPacketListInit(&pktlist); data[0] = MIDI_STATUS_NOTEOFF | (chan & 0x0f); data[1] = note; data[2] = vel; packet = MIDIPacketListAdd(&pktlist, sizeof(pktlist), packet, 0, sizeof(data), data); if (packet != NULL) d->sendEvents(&pktlist); } void MacMIDIOutput::sendController(int chan, int control, int value) { quint8 data[3]; MIDIPacketList pktlist ; MIDIPacket* packet = MIDIPacketListInit(&pktlist); data[0] = MIDI_STATUS_CONTROLCHANGE | (chan & 0x0f); data[1] = control; data[2] = value; packet = MIDIPacketListAdd(&pktlist, sizeof(pktlist), packet, 0, sizeof(data), data); if (packet != NULL) d->sendEvents(&pktlist); } void MacMIDIOutput::sendKeyPressure(int chan, int note, int value) { quint8 data[3]; MIDIPacketList pktlist ; MIDIPacket* packet = MIDIPacketListInit(&pktlist); data[0] = MIDI_STATUS_KEYPRESURE | (chan & 0x0f); data[1] = note; data[2] = value; packet = MIDIPacketListAdd(&pktlist, sizeof(pktlist), packet, 0, sizeof(data), data); if (packet != NULL) d->sendEvents(&pktlist); } void MacMIDIOutput::sendProgram(int chan, int program) { quint8 data[2]; MIDIPacketList pktlist ; MIDIPacket* packet = MIDIPacketListInit(&pktlist); data[0] = MIDI_STATUS_PROGRAMCHANGE | (chan & 0x0f); data[1] = program; packet = MIDIPacketListAdd(&pktlist, sizeof(pktlist), packet, 0, sizeof(data), data); if (packet != NULL) d->sendEvents(&pktlist); } void MacMIDIOutput::sendChannelPressure(int chan, int value) { quint8 data[2]; MIDIPacketList pktlist ; MIDIPacket* packet = MIDIPacketListInit(&pktlist); data[0] = MIDI_STATUS_CHANNELPRESSURE | (chan & 0x0f); data[1] = value; packet = MIDIPacketListAdd(&pktlist, sizeof(pktlist), packet, 0, sizeof(data), data); if (packet != NULL) d->sendEvents(&pktlist); } void MacMIDIOutput::sendPitchBend(int chan, int value) { quint16 val = value + 8192; // value between -8192 and +8191 quint8 data[3]; MIDIPacketList pktlist ; MIDIPacket* packet = MIDIPacketListInit(&pktlist); data[0] = MIDI_STATUS_PITCHBEND | (chan & 0x0f); data[1] = MIDI_LSB(val); // LSB data[2] = MIDI_MSB(val); // MSB packet = MIDIPacketListAdd(&pktlist, sizeof(pktlist), packet, 0, sizeof(data), data); if (packet != NULL) d->sendEvents(&pktlist); } void MacMIDIOutput::sendSysex(const QByteArray& data) { quint8 buf[4096]; if (data.size() > 4096) return; MIDIPacketList* pktlist = (MIDIPacketList*) &buf; MIDIPacket* packet = MIDIPacketListInit(pktlist); packet = MIDIPacketListAdd(pktlist, sizeof(buf), packet, 0, data.size(), (const Byte*)data.data()); if (packet != NULL) d->sendEvents(pktlist); } void MacMIDIOutput::sendSystemMsg(const int status) { quint8 data; MIDIPacketList pktlist; MIDIPacket* packet = MIDIPacketListInit(&pktlist); data = status; packet = MIDIPacketListAdd(&pktlist, sizeof(pktlist), packet, 0, sizeof(data), &data); if (packet != NULL) d->sendEvents(&pktlist); } }} drumstick-1.1.3/library/rt-backends/PaxHeaders.32572/common0000644000000000000000000000013213532747316020347 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/common/0000755000175000001440000000000013532747316021215 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt-backends/common/PaxHeaders.32572/maccommon.cpp0000644000000000000000000000013213532747316023101 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/common/maccommon.cpp0000644000175000001440000000457513532747316023705 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "maccommon.h" #if QT_VERSION < QT_VERSION_CHECK(5,2,0) QString CFStringToQString(CFStringRef str) { if (!str) return QString(); CFIndex length = CFStringGetLength(str); const UniChar *chars = CFStringGetCharactersPtr(str); if (chars) return QString(reinterpret_cast(chars), length); QVarLengthArray buffer(length); CFStringGetCharacters(str, CFRangeMake(0, length), buffer.data()); return QString(reinterpret_cast(buffer.constData()), length); } #endif QString getEndpointName(MIDIEndpointRef endpoint) { QString result; CFStringRef str = 0; MIDIObjectGetStringProperty (endpoint, kMIDIPropertyName, &str); if (str != 0) { result = QString::fromCFString(str); CFRelease(str); str = 0; } MIDIEntityRef entity = 0; MIDIEndpointGetEntity(endpoint, &entity); if (entity == 0) return result; if (result.isEmpty()) { MIDIObjectGetStringProperty (entity, kMIDIPropertyName, &str); if (str != 0) { result = QString::fromCFString(str); CFRelease(str); str = 0; } } MIDIDeviceRef device = 0; MIDIEntityGetDevice (entity, &device); if (device == 0) return result; MIDIObjectGetStringProperty (device, kMIDIPropertyName, &str); if (str != 0) { QString s = QString::fromCFString(str); CFRelease (str); str = 0; if (!result.startsWith(s, Qt::CaseInsensitive) ) result = (s + ' ' + result).trimmed(); } return result; } drumstick-1.1.3/library/rt-backends/common/PaxHeaders.32572/maccommon.h0000644000000000000000000000013213532747316022546 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/common/maccommon.h0000644000175000001440000000201113532747316023331 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef MACCOMMON_H #define MACCOMMON_H #include #include #if QT_VERSION < QT_VERSION_CHECK(5,2,0) QString CFStringToQString(CFStringRef str); #endif QString getEndpointName(MIDIEndpointRef endpoint); #endif // MACCOMMON_H drumstick-1.1.3/library/rt-backends/common/PaxHeaders.32572/midiparser.h0000644000000000000000000000013213532747316022734 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/common/midiparser.h0000644000175000001440000000240513532747316023526 0ustar00pedrousers00000000000000/* Drumstick MIDI realtime input-output Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef MIDIPARSER_H #define MIDIPARSER_H #include #include namespace drumstick { namespace rt { class MIDIParser : public QObject { Q_OBJECT public: explicit MIDIParser(MIDIInput *in = 0, QObject *parent = 0); virtual ~MIDIParser(); void setMIDIThruDevice(MIDIOutput* device); public slots: void parse(unsigned char byte); void parse(QByteArray bytes); private: class MIDIParserPrivate; MIDIParserPrivate *d; }; }} #endif // MIDIPARSER_H drumstick-1.1.3/library/rt-backends/common/PaxHeaders.32572/midiparser.cpp0000644000000000000000000000013213532747316023267 xustar0030 mtime=1567346382.709999865 30 atime=1567346382.930000148 30 ctime=1567346382.709999865 drumstick-1.1.3/library/rt-backends/common/midiparser.cpp0000644000175000001440000002046713532747316024071 0ustar00pedrousers00000000000000/* Drumstick MIDI realtime input-output Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include "midiparser.h" namespace drumstick { namespace rt { class MIDIParser::MIDIParserPrivate { public: MIDIParserPrivate(): m_in(0), m_out(0), m_running_status(0) { } MIDIInput *m_in; MIDIOutput *m_out; unsigned char m_running_status; QByteArray m_buffer; void processNoteOff(const int chan, const int note, const int vel) { //qDebug() << "NoteOff(" << hex << chan << "," << note << "," << vel << ")"; if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { m_out->sendNoteOff(chan, note, vel); } if (m_in != 0) { m_in->emit midiNoteOff(chan, note, vel); } } void processNoteOn(const int chan, const int note, const int vel) { //qDebug() << "NoteOn(" << hex << chan << "," << note << "," << vel << ")"; if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { m_out->sendNoteOn(chan, note, vel); } if (m_in != 0) { m_in->emit midiNoteOn(chan, note, vel); } } void processKeyPressure(const int chan, const int note, const int value) { //qDebug() << "KeyPressure(" << hex << chan << "," << note << "," << value << ")"; if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { m_out->sendKeyPressure(chan, note, value); } if (m_in != 0) { m_in->emit midiKeyPressure(chan, note, value); } } void processController(const int chan, const int control, const int value) { //qDebug() << "Controller(" << chan << "," << control << "," << value << ")"; if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { m_out->sendController(chan, control, value); } if (m_in != 0) { m_in->emit midiController(chan, control, value); } } void processProgram(const int chan, const int program) { //qDebug() << "Program(" << hex << chan << "," << program << ")"; if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { m_out->sendProgram(chan, program); } if (m_in != 0) { m_in->emit midiProgram(chan, program); } } void processChannelPressure(const int chan, const int value) { //qDebug() << "ChannelPressure(" << chan << "," << value << ")"; if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { m_out->sendChannelPressure(chan, value); } if (m_in != 0) { m_in->emit midiChannelPressure(chan, value); } } void processPitchBend(const int chan, const int value) { //qDebug() << "PitchBend(" << chan << "," << value << ")"; if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { m_out->sendPitchBend(chan, value); } if (m_in != 0) { m_in->emit midiPitchBend(chan, value); } } void processSysex(const QByteArray &data) { //qDebug() << "Sysex(" << data.toHex() << ")"; if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { m_out->sendSysex(data); } if (m_in != 0) { m_in->emit midiSysex(data); } } void processSystemCommon(const int status) { //qDebug() << "common SystemMsg(" << hex << status << ")"; if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { m_out->sendSystemMsg(status); } if (m_in != 0) { m_in->emit midiSystemCommon(status); } } void processSystemRealtime(unsigned char byte) { //qDebug() << "realtime SystemMsg(" << hex << byte << ")"; if (m_in != 0 && m_in->isEnabledMIDIThru() && m_out != 0) { m_out->sendSystemMsg(byte); } if (m_in != 0) { m_in->emit midiSystemRealtime(byte); } } }; MIDIParser::MIDIParser(MIDIInput *in, QObject *parent) : QObject(parent), d(new MIDIParser::MIDIParserPrivate) { d->m_buffer.clear(); d->m_in = in; } MIDIParser::~MIDIParser() { delete d; } void MIDIParser::setMIDIThruDevice(MIDIOutput *device) { d->m_out = device; } void MIDIParser::parse(unsigned char byte) { unsigned char status; int chan, m1, m2, v; if (byte >= MIDI_STATUS_REALTIME) { // system realtime d->processSystemRealtime(byte); return; } else d->m_buffer.append(byte); while(d->m_buffer.length() > 0) { status = static_cast(d->m_buffer.at(0)); if (status == MIDI_STATUS_SYSEX) { // system exclusive if (byte == MIDI_STATUS_ENDSYSEX) { d->processSysex(d->m_buffer); d->m_buffer.clear(); } else return; } else if (status > MIDI_STATUS_SYSEX && status < MIDI_STATUS_ENDSYSEX) { // system common d->processSystemCommon(status); d->m_buffer.clear(); } else if (status < MIDI_STATUS_SYSEX && status >= MIDI_STATUS_NOTEOFF) { // channel message d->m_running_status = status; chan = status & MIDI_CHANNEL_MASK; status = status & MIDI_STATUS_MASK; switch(status) { case MIDI_STATUS_NOTEOFF: if (d->m_buffer.length() < 3) return; m1 = static_cast(d->m_buffer.at(1)); m2 = static_cast(d->m_buffer.at(2)); d->processNoteOff(chan, m1, m2); break; case MIDI_STATUS_NOTEON: if (d->m_buffer.length() < 3) return; m1 = static_cast(d->m_buffer.at(1)); m2 = static_cast(d->m_buffer.at(2)); d->processNoteOn(chan, m1, m2); break; case MIDI_STATUS_KEYPRESURE: if (d->m_buffer.length() < 3) return; m1 = static_cast(d->m_buffer.at(1)); m2 = static_cast(d->m_buffer.at(2)); d->processKeyPressure(chan, m1, m2); break; case MIDI_STATUS_CONTROLCHANGE: if (d->m_buffer.length() < 3) return; m1 = static_cast(d->m_buffer.at(1)); m2 = static_cast(d->m_buffer.at(2)); d->processController(chan, m1, m2); break; case MIDI_STATUS_PROGRAMCHANGE: if (d->m_buffer.length() < 2) return; m1 = static_cast(d->m_buffer.at(1)); d->processProgram(chan, m1); break; case MIDI_STATUS_CHANNELPRESSURE: if (d->m_buffer.length() < 2) return; m1 = static_cast(d->m_buffer.at(1)); d->processChannelPressure(chan, m1); break; case MIDI_STATUS_PITCHBEND: if (d->m_buffer.length() < 3) return; m1 = static_cast(d->m_buffer.at(1)); m2 = static_cast(d->m_buffer.at(2)); v = m1 + m2 * 0x80 - 0x2000; d->processPitchBend(chan, v); break; } d->m_buffer.clear(); } else { // running status d->m_buffer.insert(0, d->m_running_status); } } } void MIDIParser::parse(QByteArray bytes) { foreach(unsigned char byte, bytes) { parse(byte); } } }} drumstick-1.1.3/library/PaxHeaders.32572/alsa0000644000000000000000000000013013532747316015600 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/alsa/0000755000175000001440000000000013532747316016450 5ustar00pedrousers00000000000000drumstick-1.1.3/library/alsa/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013013532747316020415 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/alsa/CMakeLists.txt0000644000175000001440000000576213532747316021222 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(CMAKE_INCLUDE_CURRENT_DIR ON) #include_directories(${ALSA_INC_DIR}) link_directories(${ALSA_LIB_DIR}) set(drumstick-alsa_QTOBJ_SRCS ../include/drumstick/alsaclient.h ../include/drumstick/alsaevent.h ../include/drumstick/alsaport.h ../include/drumstick/alsaqueue.h ../include/drumstick/alsatimer.h ../include/drumstick/playthread.h ) set(drumstick-alsa_HEADERS ../include/drumstick/alsaclient.h ../include/drumstick/alsaevent.h ../include/drumstick/alsaport.h ../include/drumstick/alsaqueue.h ../include/drumstick/alsatimer.h ../include/drumstick/drumstickcommon.h ../include/drumstick/playthread.h ../include/drumstick/subscription.h ) SET(drumstick-alsa_SRCS alsaclient.cpp alsaevent.cpp alsaport.cpp alsaqueue.cpp alsatimer.cpp playthread.cpp subscription.cpp ) qt5_wrap_cpp(drumstick-alsa_MOC_SRCS ${drumstick-alsa_QTOBJ_SRCS}) add_library(drumstick-alsa ${drumstick-alsa_MOC_SRCS} ${drumstick-alsa_SRCS} ${drumstick-alsa_HEADERS} ) add_library(Drumstick::ALSA ALIAS drumstick-alsa) target_include_directories(drumstick-alsa PUBLIC $ $ PRIVATE ${ALSA_INC_DIR} ) target_link_libraries(drumstick-alsa ${ALSA_LIBS} Qt5::Core ) if(USE_DBUS) target_link_libraries(drumstick-alsa Qt5::DBus ) endif() if(STATIC_DRUMSTICK) set_target_properties(drumstick-alsa PROPERTIES STATIC_LIB "libdrumstick-alsa") else() set_target_properties(drumstick-alsa PROPERTIES VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} SOVERSION ${VERSION_MAJOR} ) endif() install(TARGETS drumstick-alsa EXPORT drumstick-alsa-config RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(FILES ${drumstick-alsa_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/drumstick) install(FILES ../include/drumstick.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install(EXPORT drumstick-alsa-config DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/drumstick/cmake) export(TARGETS drumstick-alsa FILE drumstick-alsa-config.cmake) drumstick-1.1.3/library/alsa/PaxHeaders.32572/alsaqueue.cpp0000644000000000000000000000013013532747316020346 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/alsa/alsaqueue.cpp0000644000175000001440000005034013532747316021143 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include /** * @file alsaqueue.cpp * Implementation of classes managing ALSA Sequencer queues */ namespace drumstick { /** * @addtogroup ALSAQueue * @{ * * ALSA events can be delivered to the output ports at scheduled times using the * queues. There is a small amount of available queues in the system, so this is * a limited resource. Queues are also used to time-stamp incoming events. * * Classes: * * QueueInfo holds several properties about the queue object. * * QueueStatus is used to retrieve the status of the queue object. * * QueueTempo holds properties to get and set the tempo in the queue object. * * QueueTimer holds properties about the Timer used in the queue object. * * MidiQueue represents the queue object. * * @see http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_queue.html * @} */ /** * Default constructor */ QueueInfo::QueueInfo() { snd_seq_queue_info_malloc(&m_Info); } /** * Constructor. * @param other ALSA queue info object pointer */ QueueInfo::QueueInfo(snd_seq_queue_info_t* other) { snd_seq_queue_info_malloc(&m_Info); snd_seq_queue_info_copy(m_Info, other); } /** * Copy constructor. * @param other An existing QueueInfo object reference. */ QueueInfo::QueueInfo(const QueueInfo& other) { snd_seq_queue_info_malloc(&m_Info); snd_seq_queue_info_copy(m_Info, other.m_Info); } /** * Destructor */ QueueInfo::~QueueInfo() { snd_seq_queue_info_free(m_Info); } /** * Copy the current object and return the copy. * @return The pointer to the new object. */ QueueInfo* QueueInfo::clone() { return new QueueInfo(m_Info); } /** * Assignment operator. * @param other An existing QueueInfo object reference. * @return This object. */ QueueInfo& QueueInfo::operator=(const QueueInfo& other) { snd_seq_queue_info_copy(m_Info, other.m_Info); return *this; } /** * Gets the queue's numeric identifier. * @return The numeric identifier. */ int QueueInfo::getId() { return snd_seq_queue_info_get_queue(m_Info); } /** * Gets the queue name * @return The queue name. */ QString QueueInfo::getName() { return QString(snd_seq_queue_info_get_name(m_Info)); } /** * Gets the owner's client id of the queue. * @return the owner's client id. */ int QueueInfo::getOwner() { return snd_seq_queue_info_get_owner(m_Info); } /** * Returns the locking status of the queue * @return The locking status. */ bool QueueInfo::isLocked() { return (snd_seq_queue_info_get_locked(m_Info) != 0); } /** * Gets the flags of the queue. * @return The flags of the queue. */ unsigned int QueueInfo::getFlags() { return snd_seq_queue_info_get_flags(m_Info); } /** * Sets the queue name * @param value The queue name */ void QueueInfo::setName(QString value) { snd_seq_queue_info_set_name(m_Info, value.toLocal8Bit().data()); } /** * Sets the client ID of the owner * @param value The client ID of the owner */ void QueueInfo::setOwner(int value) { snd_seq_queue_info_set_owner(m_Info, value); } /** * Sets the bit flags of the queue * @param value The bit flags */ void QueueInfo::setFlags(unsigned int value) { snd_seq_queue_info_set_flags(m_Info, value); } /** * Sets the locked status of the queue * @param locked The locked status */ void QueueInfo::setLocked(bool locked) { snd_seq_queue_info_set_locked(m_Info, locked ? 1 : 0); } /** * Gets the size of the ALSA queue info object. * @return The size of the ALSA object. */ int QueueInfo::getInfoSize() const { return snd_seq_queue_info_sizeof(); } /** * Default constructor */ QueueStatus::QueueStatus() { snd_seq_queue_status_malloc(&m_Info); } /** * Constructor * @param other ALSA queue status object pointer */ QueueStatus::QueueStatus(snd_seq_queue_status_t* other) { snd_seq_queue_status_malloc(&m_Info); snd_seq_queue_status_copy(m_Info, other); } /** * Copy constructor * @param other An existing QueueStatus object reference */ QueueStatus::QueueStatus(const QueueStatus& other) { snd_seq_queue_status_malloc(&m_Info); snd_seq_queue_status_copy(m_Info, other.m_Info); } /** * Destructor */ QueueStatus::~QueueStatus() { snd_seq_queue_status_free(m_Info); } /** * Copy the current object and return the copy * @return The pointer to the new object */ QueueStatus* QueueStatus::clone() { return new QueueStatus(m_Info); } /** * Assignment operator * @param other An existing QueueStatus object reference * @return This object */ QueueStatus& QueueStatus::operator=(const QueueStatus& other) { snd_seq_queue_status_copy(m_Info, other.m_Info); return *this; } /** * Gets the queue's numeric identifier * @return The queue's numeric identifier. */ int QueueStatus::getId() { return snd_seq_queue_status_get_queue(m_Info); } /** * Gets the number of queued events * @return The number of queued events */ int QueueStatus::getEvents() { return snd_seq_queue_status_get_events(m_Info); } /** * Gets the real time (secods and nanoseconds) of the queue * @return The queue's real time. */ const snd_seq_real_time_t* QueueStatus::getRealtime() { return snd_seq_queue_status_get_real_time(m_Info); } /** * Gets the running status bits * @return The running status bits */ unsigned int QueueStatus::getStatusBits() { return snd_seq_queue_status_get_status(m_Info); } /** * Gets the musical time (ticks) of the queue * @return The musical time */ snd_seq_tick_time_t QueueStatus::getTickTime() { return snd_seq_queue_status_get_tick_time(m_Info); } /** * Gets the size of the ALSA status object * @return The size of the ALSA object */ int QueueStatus::getInfoSize() const { return snd_seq_queue_status_sizeof(); } /** * Gets the queue's running state * @return True if the queue is running */ bool QueueStatus::isRunning() { return (snd_seq_queue_status_get_status(m_Info) != 0); } /** * Gets the clock time in seconds of the queue * @return The queue time in seconds */ double QueueStatus::getClockTime() { const snd_seq_real_time_t* time = snd_seq_queue_status_get_real_time(m_Info); return (time->tv_sec * 1.0) + (time->tv_nsec * 1.0e-9); } /** * Default constructor */ QueueTempo::QueueTempo() { snd_seq_queue_tempo_malloc(&m_Info); } /** * Constructor * @param other An ALSA queue tempo object pointer */ QueueTempo::QueueTempo(snd_seq_queue_tempo_t* other) { snd_seq_queue_tempo_malloc(&m_Info); snd_seq_queue_tempo_copy(m_Info, other); } /** * Copy constructor * @param other An existing QueueTempo object reference */ QueueTempo::QueueTempo(const QueueTempo& other) { snd_seq_queue_tempo_malloc(&m_Info); snd_seq_queue_tempo_copy(m_Info, other.m_Info); } /** * Destructor */ QueueTempo::~QueueTempo() { snd_seq_queue_tempo_free(m_Info); } /** * Copy the current object returning the copied object * @return The pointer to the new object */ QueueTempo* QueueTempo::clone() { return new QueueTempo(m_Info); } /** * Assignment operator * @param other An existing QueueTempo object reference * @return This object */ QueueTempo& QueueTempo::operator=(const QueueTempo& other) { snd_seq_queue_tempo_copy(m_Info, other.m_Info); return *this; } /** * Gets the queue's numeric identifier * @return The queue's numeric identifier */ int QueueTempo::getId() { return snd_seq_queue_tempo_get_queue(m_Info); } /** * Gets the PPQ (parts per quarter note) resolution of the queue * @return The PPQ (parts per quarter note) resolution */ int QueueTempo::getPPQ() { return snd_seq_queue_tempo_get_ppq(m_Info); } /** * Gets the tempo skew numerator. The real skew factor is the quotient of this * value divided by the skew base. * @return The tempo skew numerator. * @see getSkewBase(), setSkewValue(), setTempoFactor() */ unsigned int QueueTempo::getSkewValue() { return snd_seq_queue_tempo_get_skew(m_Info); } /** * Gets the tempo skew base. The real skew factor is the quotient of the skew * value divided by the skew base. * @return The tempo skew base. * @see getSkewValue(), setSkewValue(), setTempoFactor() */ unsigned int QueueTempo::getSkewBase() { return snd_seq_queue_tempo_get_skew_base(m_Info); } /** * Gets the queue's tempo in microseconds per beat. * @return The queue's tempo in microseconds per beat. */ unsigned int QueueTempo::getTempo() { return snd_seq_queue_tempo_get_tempo(m_Info); } /** * Sets the queue resolution in parts per quarter note. * @param value The queue resolution in PPQ. */ void QueueTempo::setPPQ(int value) { snd_seq_queue_tempo_set_ppq(m_Info, value); } /** * Sets the tempo skew numerator. The real skew factor is the quotient of this * value divided by the skew base. * @param value The tempo skew numerator. * @see getSkewBase(), getSkewValue(), setTempoFactor() */ void QueueTempo::setSkewValue(unsigned int value) { snd_seq_queue_tempo_set_skew(m_Info, value); } /** * Sets the tempo skew base. The real skew factor is the quotient of the skew * value divided by the skew base. * @bug Protected because ALSA only accepts as argument a constant SKEW_BASE * @param value The tempo skew base. * @see getSkewBase(), getSkewValue(), setTempoFactor() */ void QueueTempo::setSkewBase(unsigned int value) { snd_seq_queue_tempo_set_skew_base(m_Info, value); } /** * Sets the queue tempo in microseconds per beat * @param value The tempo in microseconds per beat */ void QueueTempo::setTempo(unsigned int value) { snd_seq_queue_tempo_set_tempo(m_Info, value); } /** * Gets the queue's nominal BPM tempo (in beats per minute) * @return The queue's nominal BPM tempo (in beats per minute) */ float QueueTempo::getNominalBPM() { int itempo = getTempo(); if (itempo != 0) return 6.0e7f / itempo; return 0.0f; } /** * Gets the queue's real BPM tempo in beats per minute. The result is equal to * the nominal BPM tempo multiplied by the skew factor. * @return */ float QueueTempo::getRealBPM() { float tempo = getNominalBPM(); return tempo * getSkewValue() / SKEW_BASE; } /** * Sets the queue's tempo skew factor * @param value The tempo skew factor. */ void QueueTempo::setTempoFactor(float value) { setSkewValue(floor(SKEW_BASE * value)); setSkewBase(SKEW_BASE); } /** * Sets the queue's nominal tempo in BPM (beats per minute). * @param value The nominal tempo in BPM (beats per minute). */ void QueueTempo::setNominalBPM(float value) { setTempo(floor(6.0e7f / value)); } /** * Gets the size of the ALSA queue tempo object * @return The size of the ALSA object */ int QueueTempo::getInfoSize() const { return snd_seq_queue_tempo_sizeof(); } /** * Default constructor */ QueueTimer::QueueTimer() { snd_seq_queue_timer_malloc(&m_Info); } /** * Constructor * @param other An ALSA queue timer object pointer */ QueueTimer::QueueTimer(snd_seq_queue_timer_t* other) { snd_seq_queue_timer_malloc(&m_Info); snd_seq_queue_timer_copy(m_Info, other); } /** * Copy constructor * @param other An existing QueueTimer object reference */ QueueTimer::QueueTimer(const QueueTimer& other) { snd_seq_queue_timer_malloc(&m_Info); snd_seq_queue_timer_copy(m_Info, other.m_Info); } /** * Destructor */ QueueTimer::~QueueTimer() { snd_seq_queue_timer_free(m_Info); } /** * Copy the current object and return the copy * @return The pointer to the new object */ QueueTimer* QueueTimer::clone() { return new QueueTimer(m_Info); } /** * Assignment operator * @param other An existing QueueTimer object reference * @return This object */ QueueTimer& QueueTimer::operator=(const QueueTimer& other) { snd_seq_queue_timer_copy(m_Info, other.m_Info); return *this; } /** * The queue's numeric identifier * @return The queue's numeric identifier */ int QueueTimer::getQueueId() { return snd_seq_queue_timer_get_queue(m_Info); } /** * Gets the timer type. * * The timer type can be one of the following constants: *

    *
  • SND_SEQ_TIMER_ALSA: ALSA timer
  • *
  • SND_SEQ_TIMER_MIDI_CLOCK: MIDI Clock (CLOCK event)
  • *
  • SND_SEQ_TIMER_MIDI_TICK: MIDI Timer Tick (TICK event)
  • *
* @return the timer type. * @see setType() */ snd_seq_queue_timer_type_t QueueTimer::getType() { return snd_seq_queue_timer_get_type(m_Info); } /** * Gets the timer identifier record * @return The timer identifier record pointer */ const snd_timer_id_t* QueueTimer::getId() { return snd_seq_queue_timer_get_id(m_Info); } /** * Gets the timer resolution * @return The timer resolution */ unsigned int QueueTimer::getResolution() { return snd_seq_queue_timer_get_resolution(m_Info); } /** * Sets the timer type. * The timer type can be one of the following constants: *
    *
  • SND_SEQ_TIMER_ALSA: ALSA timer
  • *
  • SND_SEQ_TIMER_MIDI_CLOCK: MIDI Clock (CLOCK event)
  • *
  • SND_SEQ_TIMER_MIDI_TICK: MIDI Timer Tick (TICK event)
  • *
* @param value The timer type * @see getType() */ void QueueTimer::setType(snd_seq_queue_timer_type_t value) { snd_seq_queue_timer_set_type(m_Info, value); } /** * Sets the timer identifier record * @param value The timer identifier record pointer */ void QueueTimer::setId(snd_timer_id_t* value) { snd_seq_queue_timer_set_id(m_Info, value); } /** * Sets the timer identifier * @param id Timer identifier object * @since 0.3.0 */ void QueueTimer::setId(const TimerId& id) { setId(id.m_Info); } /** * Sets the timer resolution * @param value The timer resolution */ void QueueTimer::setResolution(unsigned int value) { snd_seq_queue_timer_set_resolution(m_Info, value); } /** * Gets the size of the ALSA queue timer object * @return The size of the ALSA object */ int QueueTimer::getInfoSize() const { return snd_seq_queue_timer_sizeof(); } /** * Constructor * @param seq An existing MidiClient instance * @param parent An optional parent object */ MidiQueue::MidiQueue(MidiClient* seq, QObject* parent) : QObject(parent) { m_MidiClient = seq; m_Id = CHECK_ERROR(snd_seq_alloc_queue(m_MidiClient->getHandle())); m_allocated = !(m_Id < 0); } /** * Constructor * @param seq An existing MidiClient instance * @param info A QueueInfo object reference * @param parent An optional parent object */ MidiQueue::MidiQueue(MidiClient* seq, const QueueInfo& info, QObject* parent) : QObject(parent) { m_MidiClient = seq; m_Info = info; m_Id = CHECK_ERROR(snd_seq_create_queue(m_MidiClient->getHandle(), m_Info.m_Info)); m_allocated = !(m_Id < 0); } /** * Constructor * @param seq An existing MidiClient instance * @param name The name for the new queue * @param parent An optional parent object */ MidiQueue::MidiQueue(MidiClient* seq, const QString name, QObject* parent) : QObject(parent) { m_MidiClient = seq; m_Id = CHECK_ERROR(snd_seq_alloc_named_queue(m_MidiClient->getHandle(), name.toLocal8Bit().data())); m_allocated = !(m_Id < 0); } /** * Constructor. * * Note: this constructor doesn't allocate a new queue, it uses an existing one. * @param seq An existing MidiClient instance * @param queue_id An existing queue numeric identifier * @param parent An optional parent object */ MidiQueue::MidiQueue(MidiClient* seq, const int queue_id, QObject* parent) : QObject(parent) { m_MidiClient = seq; m_Id = queue_id; m_allocated = false; } /** * Destructor */ MidiQueue::~MidiQueue() { if ( m_allocated && (m_MidiClient->getHandle() != NULL) ) { CHECK_ERROR(snd_seq_free_queue(m_MidiClient->getHandle(), m_Id)); } } /** * Gets a QueueInfo object reference * @return A QueueInfo object reference */ QueueInfo& MidiQueue::getInfo() { CHECK_WARNING(snd_seq_get_queue_info(m_MidiClient->getHandle(), m_Id, m_Info.m_Info)); return m_Info; } /** * Gets a QueueStatus object reference * @return A QueueStatus object reference */ QueueStatus& MidiQueue::getStatus() { CHECK_WARNING(snd_seq_get_queue_status(m_MidiClient->getHandle(), m_Id, m_Status.m_Info)); return m_Status; } /** * Gets a QueueTempo object reference * @return A QueueTempo object reference */ QueueTempo& MidiQueue::getTempo() { CHECK_WARNING(snd_seq_get_queue_tempo(m_MidiClient->getHandle(), m_Id, m_Tempo.m_Info)); return m_Tempo; } /** * Gets a QueueTimer object reference * @return A QueueTimer object reference */ QueueTimer& MidiQueue::getTimer() { CHECK_WARNING(snd_seq_get_queue_timer(m_MidiClient->getHandle(), m_Id, m_Timer.m_Info)); return m_Timer; } /** * Applies a QueueInfo object to the queue * @param value A QueueInfo object reference */ void MidiQueue::setInfo(const QueueInfo& value) { m_Info = value; CHECK_WARNING(snd_seq_set_queue_info(m_MidiClient->getHandle(), m_Id, m_Info.m_Info)); } /** * Applies a QueueTempo object to the queue * @param value A QueueTempo object reference */ void MidiQueue::setTempo(const QueueTempo& value) { m_Tempo = value; CHECK_WARNING(snd_seq_set_queue_tempo(m_MidiClient->getHandle(), m_Id, m_Tempo.m_Info)); } /** * Applies q QueueTimer object to the queue * @param value A QueueTimer object reference */ void MidiQueue::setTimer(const QueueTimer& value) { m_Timer = value; CHECK_WARNING(snd_seq_set_queue_timer(m_MidiClient->getHandle(), m_Id, m_Timer.m_Info)); } /** * Gets the queue usage flag. * * @return 1 = client is allowed to access the queue, 0 = not allowed. */ int MidiQueue::getUsage() { return CHECK_WARNING(snd_seq_get_queue_usage(m_MidiClient->getHandle(), m_Id)); } /** * Sets the queue usage flag. * * @param used 1 = client is allowed to access the queue, 0 = not allowed. */ void MidiQueue::setUsage(int used) { CHECK_WARNING(snd_seq_set_queue_usage(m_MidiClient->getHandle(), m_Id, used)); } /** * Start the queue. * * This method should start running the queue from the initial position. */ void MidiQueue::start() { CHECK_WARNING(snd_seq_start_queue(m_MidiClient->getHandle(), m_Id, NULL)); CHECK_WARNING(snd_seq_drain_output(m_MidiClient->getHandle())); } /** * Stop the queue. * * This method should stop running the queue. */ void MidiQueue::stop() { if (m_MidiClient != NULL && m_MidiClient->getHandle() != NULL) { CHECK_WARNING(snd_seq_stop_queue(m_MidiClient->getHandle(), m_Id, NULL)); CHECK_WARNING(snd_seq_drain_output(m_MidiClient->getHandle())); } } /** * Start the queue without resetting the last position. * * This method should start running the queue from the last position set. */ void MidiQueue::continueRunning() { CHECK_WARNING(snd_seq_continue_queue(m_MidiClient->getHandle(), m_Id, NULL)); CHECK_WARNING(snd_seq_drain_output(m_MidiClient->getHandle())); } /** * Clear the queue, dropping any scheduled events. */ void MidiQueue::clear() { if (m_MidiClient != NULL && m_MidiClient->getHandle() != NULL) snd_seq_drop_output(m_MidiClient->getHandle()); } /** * Sets the queue position in musical time (ticks). * @param pos Musical time in ticks. */ void MidiQueue::setTickPosition(snd_seq_tick_time_t pos) { SystemEvent event(SND_SEQ_EVENT_SETPOS_TICK); snd_seq_ev_set_queue_pos_tick(event.getHandle(), m_Id, pos); event.setDirect(); m_MidiClient->outputDirect(&event); } /** * Sets the queue position in real time (clock) units: seconds and nanoseconds. * @param pos Real time (clock) position in seconds/nanoseconds. */ void MidiQueue::setRealTimePosition(snd_seq_real_time_t* pos) { SystemEvent event(SND_SEQ_EVENT_SETPOS_TIME); snd_seq_ev_set_queue_pos_real(event.getHandle(), m_Id, pos); event.setDirect(); m_MidiClient->outputDirect(&event); } } /* namespace drumstick */ drumstick-1.1.3/library/alsa/PaxHeaders.32572/alsa.pro0000644000000000000000000000013013532747316017317 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/alsa/alsa.pro0000644000175000001440000000200313532747316020105 0ustar00pedrousers00000000000000TEMPLATE = lib TARGET = drumstick-alsa DESTDIR = ../../build/lib DEPENDPATH += . ../include INCLUDEPATH += . ../include include (../../global.pri) QT -= gui #QT += dbus CONFIG += qt thread link_pkgconfig static { CONFIG += staticlib create_prl } DEFINES += drumstick_alsa_EXPORTS #RTKIT_SUPPORT QMAKE_CXXFLAGS += $$QMAKE_CXXFLAGS_HIDESYMS # Input HEADERS += ../include/drumstick/alsaclient.h \ ../include/drumstick/alsaevent.h \ ../include/drumstick/alsaport.h \ ../include/drumstick/alsaqueue.h \ ../include/drumstick/alsatimer.h \ ../include/drumstick/drumstick.h \ ../include/drumstick/drumstickcommon.h \ ../include/drumstick/macros.h \ ../include/drumstick/playthread.h \ ../include/drumstick/subscription.h SOURCES += alsaclient.cpp \ alsaevent.cpp \ alsaport.cpp \ alsaqueue.cpp \ alsatimer.cpp \ playthread.cpp \ subscription.cpp PKGCONFIG += alsa drumstick-1.1.3/library/alsa/PaxHeaders.32572/playthread.cpp0000644000000000000000000000013013532747316020516 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/alsa/playthread.cpp0000644000175000001440000001366013532747316021317 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include /** * @file playthread.cpp * Implementation of a sequencer output thread */ namespace drumstick { /** * @addtogroup PlayThread * @{ * * SequencerOutputThread provides MIDI sequence playback. * * This is an abstract class that must be extended providing * an implementation for the pure virtual methods: * SequencerOutputThread::hasNext() and SequencerOutputThread::nextEvent() * before using it for MIDI sequence playback. You can use any structure or * class you prefer to store the SequencerEvent objects, but they must be * provided ordered by time. A simplistic Song definition may be: * * @code * typedef QList Song; * @endcode * * Using this class is optional. You may prefer another mechanism to * manage playback actions. This class uses a thread to manage the * sequence playback as a background task. * @} */ const int TIMEOUT = 100; /** * Constructor * @param seq Existing MidiClient object pointer * @param portId Numeric input/output port identifier */ SequencerOutputThread::SequencerOutputThread(MidiClient *seq, int portId) : QThread(), m_MidiClient(seq), m_Queue(0), m_PortId(portId), m_Stopped(false), m_QueueId(0), m_npfds(0), m_pfds(0) { if (m_MidiClient != NULL) { m_Queue = m_MidiClient->getQueue(); m_QueueId = m_Queue->getId(); } } /** * Checks if stop has been requested * @return True if stop has been requested * @since 0.2.0 */ bool SequencerOutputThread::stopRequested() { QReadLocker locker(&m_mutex); return m_Stopped; } /** * Stops the playback task */ void SequencerOutputThread::stop() { QWriteLocker locker(&m_mutex); m_Stopped = true; locker.unlock(); while (isRunning()) wait(TIMEOUT); } /** * Sends an echo event, with the same PortId as sender and destination. * @param tick Event schedule time in ticks. */ void SequencerOutputThread::sendEchoEvent(int tick) { if (!stopRequested() && m_MidiClient != NULL) { SystemEvent ev(SND_SEQ_EVENT_ECHO); ev.setSource(m_PortId); ev.setDestination(m_MidiClient->getClientId(), m_PortId); ev.scheduleTick(m_QueueId, tick, false); sendSongEvent(&ev); } } /** * Sends a SequencerEvent * @param ev SequencerEvent object pointer */ void SequencerOutputThread::sendSongEvent(SequencerEvent* ev) { if (m_MidiClient != NULL) { while (!stopRequested() && (snd_seq_event_output_direct(m_MidiClient->getHandle(), ev->getHandle()) < 0)) poll(m_pfds, m_npfds, TIMEOUT); } } /** * Flush the ALSA output buffer. */ void SequencerOutputThread::drainOutput() { if (m_MidiClient != NULL) { while (!stopRequested() && (snd_seq_drain_output(m_MidiClient->getHandle()) < 0)) poll(m_pfds, m_npfds, TIMEOUT); } } /** * Waits until the ALSA output queue is empty (all the events have been played.) */ void SequencerOutputThread::syncOutput() { if (!stopRequested() && m_MidiClient != NULL) { QueueStatus status = m_Queue->getStatus(); while (!stopRequested() && (status.getEvents() > 0)) { usleep(TIMEOUT); status = m_Queue->getStatus(); } } } /** * Thread process loop */ void SequencerOutputThread::run() { unsigned int last_tick; if (m_MidiClient != NULL) { try { m_npfds = snd_seq_poll_descriptors_count(m_MidiClient->getHandle(), POLLOUT); m_pfds = (pollfd*) alloca(m_npfds * sizeof(pollfd)); snd_seq_poll_descriptors(m_MidiClient->getHandle(), m_pfds, m_npfds, POLLOUT); last_tick = getInitialPosition(); if (last_tick == 0) { m_Queue->start(); } else { m_Queue->setTickPosition(last_tick); m_Queue->continueRunning(); } while (!stopRequested() && hasNext()) { SequencerEvent* ev = nextEvent(); if (getEchoResolution() > 0) { while (!stopRequested() && (last_tick < ev->getTick())) { last_tick += getEchoResolution(); sendEchoEvent(last_tick); } } if (!stopRequested() && !SequencerEvent::isConnectionChange(ev)) sendSongEvent(ev); } if (stopRequested()) { m_Queue->clear(); emit stopped(); } else { drainOutput(); syncOutput(); if (stopRequested()) emit stopped(); else emit finished(); } m_Queue->stop(); } catch (...) { qWarning("exception in output thread"); } m_npfds = 0; m_pfds = 0; } } /** * Starts the playback thread * @param priority Thread priority, default is InheritPriority */ void SequencerOutputThread::start( Priority priority ) { QWriteLocker locker(&m_mutex); m_Stopped = false; QThread::start( priority ); } } /* namespace drumstick */ drumstick-1.1.3/library/alsa/PaxHeaders.32572/subscription.cpp0000644000000000000000000000013013532747316021105 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/alsa/subscription.cpp0000644000175000001440000002620413532747316021704 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include /** * @file subscription.cpp * Implementation of classes managing ALSA sequencer subscriptions */ namespace drumstick { /** * @addtogroup ALSASubscription * @{ * * Subscriptions are virtual MIDI cables between readable and writable ports. * * The ALSA sequencer readable ports are equivalent to the MIDI OUT ports in the * real world. Similarly, the writable ports are equivalent to the MIDI IN ones. * Subscriptions, like real MIDI cables, always involve a readable port (source) * and a writable port (destination). * * Classes: * * Subscriber: This class is used to enumerate the subscribers of a given (root) port. * * Subscription: This class represents a connection between two ports. * * @see http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_subscribe.html * @} */ /** * Default constructor */ Subscriber::Subscriber() { snd_seq_query_subscribe_malloc(&m_Info); } /** * Copy constructor * @param other Existing Subscriber object reference */ Subscriber::Subscriber(const Subscriber& other) { snd_seq_query_subscribe_malloc(&m_Info); snd_seq_query_subscribe_copy(m_Info, other.m_Info); } /** * Constructor * @param other Pointer to an ALSA query subscribe object */ Subscriber::Subscriber(snd_seq_query_subscribe_t* other) { snd_seq_query_subscribe_malloc(&m_Info); snd_seq_query_subscribe_copy(m_Info, other); } /** * Destructor */ Subscriber::~Subscriber() { snd_seq_query_subscribe_free(m_Info); } /** * Copy the current object * @return Pointer to the new object */ Subscriber* Subscriber::clone() { return new Subscriber(m_Info); } /** * Assignment operator * @param other Existing Subscriber object reference * @return This object */ Subscriber& Subscriber::operator=(const Subscriber& other) { snd_seq_query_subscribe_copy(m_Info, other.m_Info); return *this; } /** * Gets the subscriber's client number * @return Client number */ int Subscriber::getClient() { return snd_seq_query_subscribe_get_client(m_Info); } /** * Gets the subscriober's port number * @return Port number */ int Subscriber::getPort() { return snd_seq_query_subscribe_get_port(m_Info); } /** * Gets the subscriber's root address * @return Pointer to the ALSA client/port address */ const snd_seq_addr_t* Subscriber::getRoot() { return snd_seq_query_subscribe_get_root(m_Info); } /** * Gets the subscription type (read or write). *
    *
  • SND_SEQ_QUERY_SUBS_READ: read subscriptions
  • *
  • SND_SEQ_QUERY_SUBS_WRITE: write subscriptions
  • *
* @return Subscription type */ snd_seq_query_subs_type_t Subscriber::getType() { return snd_seq_query_subscribe_get_type(m_Info); } /** * Gets the index of the subscriber container * @return Index of the subscriber */ int Subscriber::getIndex() { return snd_seq_query_subscribe_get_index(m_Info); } /** * Gets the number of subscribers returned by a query operation * @return Number of subscribers */ int Subscriber::getNumSubs() { return snd_seq_query_subscribe_get_num_subs(m_Info); } /** * Gets the subscriber's address * @return Pointer to the ALSA address record */ const snd_seq_addr_t* Subscriber::getAddr() { return snd_seq_query_subscribe_get_addr(m_Info); } /** * Gets the subscriber's queue number * @return Queue number */ int Subscriber::getQueue() { return snd_seq_query_subscribe_get_queue(m_Info); } /** * Gets the subscriber's exclusive flag * @return Exclusive flag */ bool Subscriber::getExclusive() { return (snd_seq_query_subscribe_get_exclusive(m_Info) != 0); } /** * Gets the susbcriber's time-update flag * @return Time update flag */ bool Subscriber::getTimeUpdate() { return (snd_seq_query_subscribe_get_time_update(m_Info) != 0); } /** * Gets the subscriber's time real time-stamp flag * @return Time real flag */ bool Subscriber::getTimeReal() { return (snd_seq_query_subscribe_get_time_real(m_Info) != 0); } /** * Sets the subscriber's client number * @param client Client number */ void Subscriber::setClient(int client) { snd_seq_query_subscribe_set_client(m_Info, client); } /** * Sets the subscriber's port number * @param port Port number */ void Subscriber::setPort(int port) { snd_seq_query_subscribe_set_port(m_Info, port); } /** * Sets the subscriber's root address * @param addr Pointer to the root ALSA address record */ void Subscriber::setRoot(snd_seq_addr_t* addr) { snd_seq_query_subscribe_set_root(m_Info, addr); } /** * Sets the subscription type *
    *
  • SND_SEQ_QUERY_SUBS_READ: read subscriptions
  • *
  • SND_SEQ_QUERY_SUBS_WRITE: write subscriptions
  • *
* @param type Subscription type */ void Subscriber::setType(snd_seq_query_subs_type_t type) { snd_seq_query_subscribe_set_type(m_Info, type); } /** * Sets the index of the subscriber * @param index Subscriber index */ void Subscriber::setIndex(int index) { snd_seq_query_subscribe_set_index(m_Info, index); } /** * Gets the size of the ALSA query subscriber object * @return Size of the ALSA object */ int Subscriber::getSizeOfInfo() const { return snd_seq_query_subscribe_sizeof(); } /** * Default constructor */ Subscription::Subscription() { snd_seq_port_subscribe_malloc(&m_Info); } /** * Copy constructor * @param other Existing Subscription object reference */ Subscription::Subscription(const Subscription& other) { snd_seq_port_subscribe_malloc(&m_Info); snd_seq_port_subscribe_copy(m_Info, other.m_Info); } /** * Constructor * @param other Pointer to an ALSA subscription object */ Subscription::Subscription(snd_seq_port_subscribe_t* other) { snd_seq_port_subscribe_malloc(&m_Info); snd_seq_port_subscribe_copy(m_Info, other); } /** * Constructor * @param seq Pointer to a MIDI Client object */ Subscription::Subscription(MidiClient* seq) { snd_seq_port_subscribe_malloc(&m_Info); CHECK_WARNING(snd_seq_get_port_subscription(seq->getHandle(), m_Info)); } /** * Destructor * @return */ Subscription::~Subscription() { snd_seq_port_subscribe_free(m_Info); } /** * Copy the current object * @return Pointer to the new object */ Subscription* Subscription::clone() { return new Subscription(m_Info); } /** * Assignment operator * @param other Existing subscription object reference * @return This object */ Subscription& Subscription::operator=(const Subscription& other) { snd_seq_port_subscribe_copy(m_Info, other.m_Info); return *this; } /** * Gets the sender address of the subscription (MIDI OUT port) * @return Pointer to the sender ALSA address record */ const snd_seq_addr_t* Subscription::getSender() { return snd_seq_port_subscribe_get_sender(m_Info); } /** * Gets the destination address of the subscription (MIDI IN port) * @return Pointer to the destination ALSA address record */ const snd_seq_addr_t* Subscription::getDest() { return snd_seq_port_subscribe_get_dest(m_Info); } /** * Gets the susbcription's queue number * @return Queue number */ int Subscription::getQueue() { return snd_seq_port_subscribe_get_queue(m_Info); } /** * Gets the subscription's exclusive flag * @return Exclusive flag */ bool Subscription::getExclusive() { return (snd_seq_port_subscribe_get_exclusive(m_Info) != 0); } /** * Gets the susbcription's time-update flag * @return Time-update flag */ bool Subscription::getTimeUpdate() { return (snd_seq_port_subscribe_get_time_update(m_Info) != 0); } /** * Gets the susbcription's time-real (time-stamping) flag * @return Time real flag */ bool Subscription::getTimeReal() { return (snd_seq_port_subscribe_get_time_real(m_Info) != 0); } /** * Sets the Subscription's sender (MIDI OUT) port * @param addr Pointer to the sender ALSA address record */ void Subscription::setSender(const snd_seq_addr_t* addr) { snd_seq_port_subscribe_set_sender(m_Info, addr); } /** * Sets the Subscription's destination (MIDI IN) port * @param addr Pointer to the destination ALSA address record */ void Subscription::setDest(const snd_seq_addr_t* addr) { snd_seq_port_subscribe_set_dest(m_Info, addr); } /** * Sets the Subscription's Queue number * @param q Queue number */ void Subscription::setQueue(int q) { snd_seq_port_subscribe_set_queue(m_Info, q); } /** * Sets the subscription's exclusive flag * @param val Exclusive flag */ void Subscription::setExclusive(bool val) { snd_seq_port_subscribe_set_exclusive(m_Info, val?1:0); } /** * Sets the susbcription's time-update flag * @param val Time update flag */ void Subscription::setTimeUpdate(bool val) { snd_seq_port_subscribe_set_time_update(m_Info, val?1:0); } /** * Sets the subscription's time real (time-stamping) flag * @param val Time real flag */ void Subscription::setTimeReal(bool val) { snd_seq_port_subscribe_set_time_real(m_Info, val?1:0); } /** * Sets the Subscription's sender (MIDI OUT) port * @param client Client number * @param port Port number */ void Subscription::setSender(unsigned char client, unsigned char port) { snd_seq_addr_t addr; addr.client = client; addr.port = port; setSender(&addr); } /** * Sets the Subscription's destination (MIDI IN) port * @param client Client number * @param port Port number */ void Subscription::setDest(unsigned char client, unsigned char port) { snd_seq_addr_t addr; addr.client = client; addr.port = port; setDest(&addr); } /** * Performs the subscription in the ALSA sequencer subsystem. * Neither the sender nor the destination ports need to belong to the * same MidiClient instance performing the subscription. * @param seq MidiClient instance pointer */ void Subscription::subscribe(MidiClient* seq) { if ((m_Info == NULL) || (seq == NULL) || !(seq->isOpened())) { return; } CHECK_WARNING(snd_seq_subscribe_port(seq->getHandle(), m_Info)); } /** * Breaks the subscription in the ALSA sequencer subsystem. * Neither the sender nor the destination ports need to belong to the * same MidiClient instance breaking the subscription. * @param seq MidiClient instance pointer */ void Subscription::unsubscribe(MidiClient* seq) { if ((m_Info == NULL) || (seq == NULL) || !(seq->isOpened())) { return; } CHECK_WARNING(snd_seq_unsubscribe_port(seq->getHandle(), m_Info)); } /** * Gets the size of the ALSA subscription object * @return Size of the ALSA object */ int Subscription::getSizeOfInfo() const { return snd_seq_port_subscribe_sizeof(); } } /* namespace drumstick */ drumstick-1.1.3/library/alsa/PaxHeaders.32572/alsaport.cpp0000644000000000000000000000013013532747316020206 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/alsa/alsaport.cpp0000644000175000001440000006323613532747316021013 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include /** * @file alsaport.cpp * Implementation of classes managing ALSA Sequencer ports. */ namespace drumstick { /** * @addtogroup ALSAPort * @{ * * Ports are the endpoints of the MIDI connections. * * Ports can be readable, writable, or both. They can be private for the owner * application, or can be subscribed by a third application. * * The ALSA sequencer readable ports are equivalent to the MIDI OUT ports in the * real world. Similarly, the writable ports are equivalent to the MIDI IN ones. * * Classes: * * PortInfo is a container to retrieve and change some properties about the ALSA * MIDI ports. * * MidiPort represents an ALSA MIDI port. * * @see http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_port.html * @} */ /** * Default constructor. */ PortInfo::PortInfo() { snd_seq_port_info_malloc(&m_Info); } /** * Copy constructor * @param other Another PortInfo object reference */ PortInfo::PortInfo(const PortInfo& other) { snd_seq_port_info_malloc(&m_Info); snd_seq_port_info_copy(m_Info, other.m_Info); m_ReadSubscribers = other.m_ReadSubscribers; m_WriteSubscribers = other.m_WriteSubscribers; m_ClientName = other.m_ClientName; } /** * Constructor * @param other An ALSA port info object pointer */ PortInfo::PortInfo(snd_seq_port_info_t* other) { snd_seq_port_info_malloc(&m_Info); snd_seq_port_info_copy(m_Info, other); } /** * Constructor * @param seq A MidiClient instance * @param client An existing client number * @param port An existing port number */ PortInfo::PortInfo(MidiClient* seq, const int client, const int port) { snd_seq_port_info_malloc(&m_Info); CHECK_WARNING(snd_seq_get_any_port_info(seq->getHandle(), client, port, m_Info)); } /** * Constructor * @param seq A MidiClient instance * @param port An existing port number */ PortInfo::PortInfo(MidiClient* seq, const int port) { snd_seq_port_info_malloc(&m_Info); CHECK_WARNING(snd_seq_get_port_info(seq->getHandle(), port, m_Info)); } /** * Destructor */ PortInfo::~PortInfo() { snd_seq_port_info_free(m_Info); freeSubscribers(); } /** * Copy the current object * @return A pointer to the new object */ PortInfo* PortInfo::clone() { return new PortInfo(m_Info); } /** * Assignment operator * @param other Another PortInfo object reference * @return This object */ PortInfo& PortInfo::operator=(const PortInfo& other) { snd_seq_port_info_copy(m_Info, other.m_Info); m_ReadSubscribers = other.m_ReadSubscribers; m_WriteSubscribers = other.m_WriteSubscribers; m_ClientName = other.m_ClientName; return *this; } /** * Gets the client number * @return The client number * @see setClient() */ int PortInfo::getClient() { return snd_seq_port_info_get_client(m_Info); } /** * Gets the port number * @return The port number * @see setPort() */ int PortInfo::getPort() { return snd_seq_port_info_get_port(m_Info); } /** * Gets the address record for this port * @return A pointer to the address record * @see setAddr() */ const snd_seq_addr_t* PortInfo::getAddr() { return snd_seq_port_info_get_addr(m_Info); } /** * Gets the port name * @return The port name * @see setName() */ QString PortInfo::getName() { return QString(snd_seq_port_info_get_name(m_Info)); } /** * Gets the capabilities bitmap * @return The capabilities bitmap * @see setCapability() */ unsigned int PortInfo::getCapability() { return snd_seq_port_info_get_capability(m_Info); } /** * Gets the port type * @return The port type * @see setType() */ unsigned int PortInfo::getType() { return snd_seq_port_info_get_type(m_Info); } /** * Gets the MIDI channels * @return The MIDI channels * @see setMidiChannels() */ int PortInfo::getMidiChannels() { return snd_seq_port_info_get_midi_channels(m_Info); } /** * Gets the MIDI voices * @return The MIDI voices * @see setMidiVoices() */ int PortInfo::getMidiVoices() { return snd_seq_port_info_get_midi_voices(m_Info); } /** * Gets the synth voices * @return The synth voices * @see setSynthVoices() */ int PortInfo::getSynthVoices() { return snd_seq_port_info_get_synth_voices(m_Info); } /** * Get the number of read subscriptions. * @return The number of read subscriptions. */ int PortInfo::getReadUse() { return snd_seq_port_info_get_read_use(m_Info); } /** * Gets the number of write subscriptions. * @return The number of write subscriptions. */ int PortInfo::getWriteUse() { return snd_seq_port_info_get_write_use(m_Info); } /** * Gets the port-specified mode. * @return The port-specified mode. * @see setPortSpecified() */ int PortInfo::getPortSpecified() { return snd_seq_port_info_get_port_specified(m_Info); } /** * Sets the client number * @param client The client number * @see getClient() */ void PortInfo::setClient(int client) { snd_seq_port_info_set_client(m_Info, client); } /** * Set the port number * @param port The port number * @see getPort() */ void PortInfo::setPort(int port) { snd_seq_port_info_set_port(m_Info, port); } /** * Sets the address record * @param addr An address record pointer * @see getAddr() */ void PortInfo::setAddr(const snd_seq_addr_t* addr) { snd_seq_port_info_set_addr(m_Info, addr); } /** * Sets the port name * @param name The port name * @see getName() */ void PortInfo::setName(QString const& name) { snd_seq_port_info_set_name(m_Info, name.toLocal8Bit().data()); } /** * Sets the capability bitmap. * * Each port has the capability bitmaps to specify the access of * the port from other clients. The capability bit flags are: *
    *
  • SND_SEQ_PORT_CAP_READ Readable from this port
  • *
  • SND_SEQ_PORT_CAP_WRITE Writable to this port
  • *
  • SND_SEQ_PORT_CAP_DUPLEX Read/write duplex access is supported
  • *
  • SND_SEQ_PORT_CAP_SUBS_READ Read subscription is allowed
  • *
  • SND_SEQ_PORT_CAP_SUBS_WRITE Write subscription is allowed
  • *
  • SND_SEQ_PORT_CAP_NO_EXPORT Subscription management from 3rd clients is disallowed
  • *
* @param capability The capability bitmap. * @see getCapability() */ void PortInfo::setCapability(unsigned int capability) { snd_seq_port_info_set_capability(m_Info, capability); } /** * Sets the port type. * * The port type is defined combining some of the type bit flags: *
    *
  • SND_SEQ_PORT_TYPE_SPECIFIC Hardware specific port
  • *
  • SND_SEQ_PORT_TYPE_MIDI_GENERIC Generic MIDI device
  • *
  • SND_SEQ_PORT_TYPE_MIDI_GM General MIDI compatible device
  • *
  • SND_SEQ_PORT_TYPE_MIDI_GM2 General MIDI 2 compatible device
  • *
  • SND_SEQ_PORT_TYPE_MIDI_GS GS compatible device
  • *
  • SND_SEQ_PORT_TYPE_MIDI_XG XG compatible device
  • *
  • SND_SEQ_PORT_TYPE_MIDI_MT32 MT-32 compatible device
  • *
  • SND_SEQ_PORT_TYPE_HARDWARE Implemented in hardware
  • *
  • SND_SEQ_PORT_TYPE_SOFTWARE Implemented in software
  • *
  • SND_SEQ_PORT_TYPE_SYNTHESIZER Generates sound
  • *
  • SND_SEQ_PORT_TYPE_PORT Connects to other device(s)
  • *
  • SND_SEQ_PORT_TYPE_APPLICATION Application (sequencer/editor)
  • *
* @param type The port type bitmap * @see getType() */ void PortInfo::setType(unsigned int type) { snd_seq_port_info_set_type(m_Info, type); } /** * Set the MIDI channels * @param channels The MIDI channels * @see getMidiChannels() */ void PortInfo::setMidiChannels(int channels) { snd_seq_port_info_set_midi_channels(m_Info, channels); } /** * Sets the MIDI voices * @param voices The MIDI voices * @see getMidiVoices() */ void PortInfo::setMidiVoices(int voices) { snd_seq_port_info_set_midi_voices(m_Info, voices); } /** * Sets the synth voices * @param voices The synth voices * @see getSynthVoices() */ void PortInfo::setSynthVoices(int voices) { snd_seq_port_info_set_synth_voices(m_Info, voices); } /** * Sets the port-specified mode * @param val The port-specified mode. * @see getPortSpecified() */ void PortInfo::setPortSpecified(int val) { snd_seq_port_info_set_port_specified(m_Info, val); } /** * Gets the list of read subscribers * @return The list of read subscribers */ SubscribersList PortInfo::getReadSubscribers() const { return m_ReadSubscribers; // copy } /** * Gets the list of write subscribers * @return The list of write subscribers */ SubscribersList PortInfo::getWriteSubscribers() const { return m_WriteSubscribers; // copy } /** * Obtains the port subscribers lists * @param seq An opened MidiClient instance */ void PortInfo::readSubscribers(MidiClient* seq) { Subscriber subs; snd_seq_addr_t tmp; freeSubscribers(); tmp.client = getClient(); tmp.port = getPort(); // Read subs subs.setType(SND_SEQ_QUERY_SUBS_READ); subs.setIndex(0); subs.setRoot(&tmp); while (snd_seq_query_port_subscribers(seq->getHandle(), subs.m_Info) >= 0) { m_ReadSubscribers.append(subs); subs.setIndex(subs.getIndex() + 1); } // Write subs subs.setType(SND_SEQ_QUERY_SUBS_WRITE); subs.setIndex(0); subs.setRoot(&tmp); while (snd_seq_query_port_subscribers(seq->getHandle(), subs.m_Info) >= 0) { m_WriteSubscribers.append(subs); subs.setIndex(subs.getIndex() + 1); } } /** * Releases the subscribers lists */ void PortInfo::freeSubscribers() { m_ReadSubscribers.clear(); m_WriteSubscribers.clear(); } /** * Gets the size of the ALSA info object * @return The size of the object */ int PortInfo::getSizeOfInfo() const { return snd_seq_port_info_sizeof(); } /** * Gets the timestamping mode * @return The timestamping mode * @see setTimestamping() */ bool PortInfo::getTimestamping() { return (snd_seq_port_info_get_timestamping(m_Info) == 1); } /** * Gets the timestamping real mode * @return The timestamping real mode * @see setTimestampReal() */ bool PortInfo::getTimestampReal() { return (snd_seq_port_info_get_timestamp_real(m_Info) == 1); } /** * Gets the timestamping queue number * @return The timestamping queue number * @see setTimestampQueue() */ int PortInfo::getTimestampQueue() { return snd_seq_port_info_get_timestamp_queue(m_Info); } /** * Sets the timestamping mode * @param value The timestamping mode * @see getTimestamping() */ void PortInfo::setTimestamping(bool value) { snd_seq_port_info_set_timestamping(m_Info, value?1:0); } /** * Sets the timestamping real mode * @param value The timestamping real mode * @see getTimestampReal() */ void PortInfo::setTimestampReal(bool value) { snd_seq_port_info_set_timestamp_real(m_Info, value?1:0); } /** * Sets the timestamp queue number * @param queueId The timestamp queue number * @see getTimestampQueue() */ void PortInfo::setTimestampQueue(int queueId) { snd_seq_port_info_set_timestamp_queue(m_Info, queueId); } /** * Constructor * @param parent An optional parent object */ MidiPort::MidiPort( QObject* parent ) : QObject( parent ), m_MidiClient( NULL ), m_Attached( false ) {} /** * Destructor. * * All subscriptions are released. */ MidiPort::~MidiPort() { unsubscribeAll(); detach(); freeSubscriptions(); } /** * Gets the PortInfo object pointer */ PortInfo* MidiPort::getPortInfo() { return &m_Info; } /** * Gets the list of susbcriptions * @return The list of susbcriptions */ SubscriptionsList MidiPort::getSubscriptions() const { return m_Subscriptions; } /** * Releases the lists of subscriptions. */ void MidiPort::freeSubscriptions() { m_Subscriptions.clear(); } /** * Sets the MidiClient * @param seq A MidiClient object pointer */ void MidiPort::setMidiClient( MidiClient* seq ) { if (m_MidiClient != seq) { m_MidiClient = seq; emit midiClientChanged( this, m_MidiClient ); applyPortInfo(); } } /** * Subscribe a Subscription object * @param subs A Subscription object pointer */ void MidiPort::subscribe(Subscription* subs) { subs->subscribe(m_MidiClient); m_Subscriptions.append(*subs); emit subscribed(this, subs); } /** * Unsubscribe a Subscription object * @param subs A Subscription object pointer */ void MidiPort::unsubscribe( Subscription* subs ) { Subscription subs2; if (m_MidiClient == NULL) { return; } subs->unsubscribe(m_MidiClient); SubscriptionsList::iterator it; for(it = m_Subscriptions.begin(); it != m_Subscriptions.end(); ++it) { subs2 = (*it); if ((subs2.getSender()->client == subs->getSender()->client) && (subs2.getSender()->port == subs->getSender()->port) && (subs2.getDest()->client == subs->getDest()->client) && (subs2.getDest()->port == subs->getDest()->port)) { m_Subscriptions.erase(it); break; } } } /** * Subscribe to another port destination * @param info A PortInfo object pointer */ void MidiPort::subscribeTo( PortInfo* info ) { Subscription subs; subs.setSender(m_Info.getAddr()); subs.setDest(info->getAddr()); subscribe(&subs); } /** * Susbcribe to another port destination * @param client ALSA client number * @param port ALSA port number */ void MidiPort::subscribeTo( int client, int port ) { Subscription subs; snd_seq_addr addr; addr.client = client; addr.port = port; subs.setSender(m_Info.getAddr()); subs.setDest(&addr); subscribe(&subs); } /** * Subscribe to another port destination * @param name A string representing a client:port pair */ void MidiPort::subscribeTo( QString const& name ) { Subscription subs; snd_seq_addr addr; if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL)) { subs.setSender(m_Info.getAddr()); if (m_MidiClient->parseAddress(name, addr)) { subs.setDest(&addr); subscribe(&subs); } } } /** * Unsubscribe a destination port * @param name A string representing a client:port pair */ void MidiPort::unsubscribeTo( QString const& name ) { Subscription subs; snd_seq_addr addr; if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL)) { subs.setSender(m_Info.getAddr()); if (m_MidiClient->parseAddress(name, addr)) { subs.setDest(&addr); unsubscribe(&subs); } } } /** * Unsubscribe a destination port * @param port A PortInfo object pointer */ void MidiPort::unsubscribeTo( PortInfo* port ) { Subscription subs; if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL)) { subs.setSender(m_Info.getAddr()); subs.setDest(port->getAddr()); unsubscribe(&subs); } } /** * Unsubscribe a destination port * @param addr An ALSA address record pointer */ void MidiPort::unsubscribeTo( const snd_seq_addr_t* addr ) { Subscription subs; if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL)) { subs.setSender(m_Info.getAddr()); subs.setDest(addr); unsubscribe(&subs); } } /** * Subscribe a source port * @param port A PortInfo object pointer */ void MidiPort::subscribeFrom( PortInfo* port ) { Subscription subs; subs.setSender( port->getAddr() ); subs.setDest( m_Info.getAddr() ); subscribe(&subs); } /** * Subscribe a source port * @param client ALSA client number * @param port ALSA port number */ void MidiPort::subscribeFrom( int client, int port ) { Subscription subs; snd_seq_addr addr; addr.client = client; addr.port = port; subs.setSender(&addr); subs.setDest(m_Info.getAddr()); subscribe(&subs); } /** * Subscribe a source port * @param name A string representing a client:port pair */ void MidiPort::subscribeFrom( QString const& name ) { Subscription subs; snd_seq_addr addr; if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL)) { if (m_MidiClient->parseAddress(name, addr)) { subs.setSender(&addr); subs.setDest(m_Info.getAddr()); subscribe(&subs); } } } /** * Unsubscribe a source port * @param name A string representing a client:port pair */ void MidiPort::unsubscribeFrom( QString const& name ) { Subscription subs; snd_seq_addr addr; if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL)) { if (m_MidiClient->parseAddress(name, addr)) { subs.setSender(&addr); subs.setDest(m_Info.getAddr()); unsubscribe(&subs); } } } /** * Unsubscribe a source port * @param port A PortInfo object pointer */ void MidiPort::unsubscribeFrom( PortInfo* port ) { Subscription subs; if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL)) { subs.setSender(port->getAddr()); subs.setDest(m_Info.getAddr()); unsubscribe(&subs); } } /** * Unsubscribe a source port * @param addr An ALSA address record pointer */ void MidiPort::unsubscribeFrom( const snd_seq_addr_t* addr ) { Subscription subs; if ((m_MidiClient != NULL) && (m_MidiClient->getHandle() != NULL)) { subs.setSender(addr); subs.setDest(m_Info.getAddr()); unsubscribe(&subs); } } /** * Subscribe from the System:announce port */ void MidiPort::subscribeFromAnnounce() { subscribeFrom(SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE); } /** * Unsubscribe all subscriptions */ void MidiPort::unsubscribeAll() { if (m_MidiClient == NULL) { return; } SubscriptionsList::Iterator it; for( it = m_Subscriptions.begin(); it != m_Subscriptions.end(); ++it) { Subscription s = (*it); s.unsubscribe(m_MidiClient); } m_Subscriptions.clear(); } /** * Applies all the the delayed PortInfo changes to the MIDI port object */ void MidiPort::applyPortInfo() { if (m_Attached && (m_MidiClient != NULL) && (m_MidiClient->isOpened())) { CHECK_WARNING(snd_seq_set_port_info( m_MidiClient->getHandle(), m_Info.getPort(), m_Info.m_Info )); } } /** * Gets the port name * @return The port name */ QString MidiPort::getPortName() { return m_Info.getName(); } /** * Sets the port name * @param newName The new port name */ void MidiPort::setPortName( QString const& newName ) { m_Info.setName(newName); applyPortInfo(); } /** * Gets the port number * @return The port number */ int MidiPort::getPortId() { return m_Info.getPort(); } /** * Gets the port capabilities * @return The capabilities bitmap * @see PortInfo::getCapability() */ unsigned int MidiPort::getCapability() { return m_Info.getCapability(); } /** * Sets the port capabilities * @param newValue The capabilities bitmap * @see PortInfo::setCapability() */ void MidiPort::setCapability(unsigned int newValue) { m_Info.setCapability(newValue); applyPortInfo(); } /** * Gets the port type * @return The port type bitmap * @see PortInfo::getType() */ unsigned int MidiPort::getPortType() { return m_Info.getType(); } /** * Sets the port type bitmap * @param newValue The port type flags bitmap * @see PortInfo::setType() */ void MidiPort::setPortType( unsigned int newValue) { m_Info.setType( newValue ); applyPortInfo(); } /** * Gets the MIDI channels * @return The MIDI channels */ int MidiPort::getMidiChannels() { return m_Info.getMidiChannels(); } /** * Sets the MIDI channels * @param newValue The MIDI channels */ void MidiPort::setMidiChannels(int newValue) { m_Info.setMidiChannels( newValue ); applyPortInfo(); } /** * Gets the MIDI voices * @return The MIDI voices */ int MidiPort::getMidiVoices() { return m_Info.getMidiVoices(); } /** * Sets the MIDI voices * @param newValue The MIDI voices */ void MidiPort::setMidiVoices(int newValue) { m_Info.setMidiVoices( newValue ); applyPortInfo(); } /** * Gets the synth voices * @return The synth voices */ int MidiPort::getSynthVoices() { return m_Info.getSynthVoices(); } /** * Sets the synth voices * @param newValue The synth voices */ void MidiPort::setSynthVoices(int newValue) { m_Info.setSynthVoices( newValue ); applyPortInfo(); } /** * Gets the timestamping mode * @return The timestamping mode */ bool MidiPort::getTimestamping() { return m_Info.getTimestamping(); } /** * Gets the timestamp real mode * @return The timestamp real mode */ bool MidiPort::getTimestampReal() { return m_Info.getTimestampReal(); } /** * Gets the timestamp queue number * @return The timestamp queue number */ int MidiPort::getTimestampQueue() { return m_Info.getTimestampQueue(); } /** * Sets the timestamping mode * @param value The timestamping mode */ void MidiPort::setTimestamping(bool value) { m_Info.setTimestamping(value); applyPortInfo(); } /** * Sets the timestamp real mode * @param value The timestamp real mode */ void MidiPort::setTimestampReal(bool value) { m_Info.setTimestampReal(value); applyPortInfo(); } /** * Sets the timestamp queue number * @param queueId The queue number */ void MidiPort::setTimestampQueue(int queueId) { m_Info.setTimestampQueue(queueId); applyPortInfo(); } /** * Attach the port to a MidiClient instance * @param seq A MidiClient object pointer */ void MidiPort::attach( MidiClient* seq ) { if (!m_Attached && (seq != NULL)) { m_MidiClient = seq; m_MidiClient->portAttach(this); m_Attached = true; emit attached(this); } } /** * Detach the port from any MidiClient instance previously attached */ void MidiPort::detach() { if (m_Attached && (m_MidiClient != NULL)) { m_MidiClient->portDetach(this); m_Attached = false; emit detached(this); } } /** * Update the subscribers list in the PortInfo member */ void MidiPort::updateSubscribers() { m_Info.readSubscribers(m_MidiClient); } /** * Gets the list of read subscribers * @return The list of read subscribers */ PortInfoList MidiPort::getReadSubscribers() { const SubscribersList subs(m_Info.getReadSubscribers()); PortInfoList lst; SubscribersList::ConstIterator it; for(it = subs.constBegin(); it != subs.constEnd(); ++it) { Subscriber s = *it; int client = s.getAddr()->client; if ((client != SND_SEQ_CLIENT_SYSTEM) && (client != m_Info.getClient())) { int port = s.getAddr()->port; PortInfo p(m_MidiClient, client, port); if ((p.getCapability() & SND_SEQ_PORT_CAP_NO_EXPORT) == 0) { p.setClientName(m_MidiClient->getClientName(client)); lst << p; } } } return lst; } /** * Gets the list of write subscribers * @return The list of write subscribers */ PortInfoList MidiPort::getWriteSubscribers() { const SubscribersList subs(m_Info.getWriteSubscribers()); PortInfoList lst; SubscribersList::ConstIterator it; for(it = subs.constBegin(); it != subs.constEnd(); ++it) { Subscriber s = *it; int client = s.getAddr()->client; if ((client != SND_SEQ_CLIENT_SYSTEM) && (client != m_Info.getClient())) { int port = s.getAddr()->port; PortInfo p(m_MidiClient, client, port); if ((p.getCapability() & SND_SEQ_PORT_CAP_NO_EXPORT) == 0) { p.setClientName(m_MidiClient->getClientName(client)); lst << p; } } } return lst; } /** * Checks if the provided address is included in the port list * @param addr ALSA address record pointer * @param lst List of port information containers * @return True if the address is found */ bool MidiPort::containsAddress(const snd_seq_addr_t* addr, const PortInfoList& lst) { PortInfoList::ConstIterator i; for( i = lst.begin(); i != lst.end(); ++i) { PortInfo p = *i; if ((p.getAddr()->client == addr->client) && (p.getAddr()->port == addr->port)) { return true; } } return false; } /** * Update the write subscriptions * @param ports List of writable ports to be subscribed */ void MidiPort::updateConnectionsTo(const PortInfoList& ports) { PortInfoList subs(getReadSubscribers()); PortInfoList::ConstIterator i; for (i = subs.constBegin(); i != subs.constEnd(); ++i) { PortInfo s = *i; if (!containsAddress(s.getAddr(), ports)) { unsubscribeTo(s.getAddr()); } } for (i = ports.constBegin(); i != ports.constEnd(); ++i) { PortInfo p = *i; if (!containsAddress(p.getAddr(), subs)) { subscribeTo(&p); } } } /** * Update the read susbcriptions * @param ports List of readable ports to be subscribed */ void MidiPort::updateConnectionsFrom(const PortInfoList& ports) { PortInfoList subs(getWriteSubscribers()); PortInfoList::ConstIterator i; for (i = subs.constBegin(); i != subs.constEnd(); ++i) { PortInfo s = *i; if (!containsAddress(s.getAddr(), ports)) { unsubscribeFrom(s.getAddr()); } } for (i = ports.constBegin(); i != ports.constEnd(); ++i) { PortInfo p = *i; if (!containsAddress(p.getAddr(), subs)) { subscribeFrom(&p); } } } } /* namespace drumstick; */ drumstick-1.1.3/library/alsa/PaxHeaders.32572/alsaevent.cpp0000644000000000000000000000013013532747316020343 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/alsa/alsaevent.cpp0000644000175000001440000006071213532747316021144 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include /** * @file alsaevent.cpp * Implementation of classes managing ALSA Sequencer events. */ /** * @class QEvent * The QEvent class is the base class of all event classes. * @see http://qt-project.org/doc/qt-5/qevent.html */ namespace drumstick { /** * @addtogroup ALSAEvent * @{ * * MIDI Events are messages transmitted between MIDI devices or applications. * * Classes: * * SequencerEvent: Base class for the event's hierarchy. * * ChannelEvent: Base class for the events having a Channel property. * * KeyEvent: Base class for the events having Key and Velocity properties. * * NoteEvent: Class representing a note event with duration. * * NoteOnEvent: Event representing a note-on MIDI event. * * NoteOffEvent: Event representing a note-off MIDI event. * * KeyPressEvent: Event representing a MIDI key pressure, or polyphonic after-touch event. * * ControllerEvent: Event representing a MIDI control change event. * * ProgramChangeEvent: Event representing a MIDI program change event. * * PitchBendEvent: Event representing a MIDI bender, or pitch wheel event. * * ChanPressEvent: Event representing a MIDI channel pressure or after-touch event. * * VariableEvent: Base class for variable length events. * * SysExEvent: Event representing a MIDI system exclusive event. * * TextEvent: Event representing a SMF text event. * * SystemEvent: Generic event. * * QueueControlEvent: ALSA Event representing a queue control command. * * ValueEvent: Generic event having a value property. * * TempoEvent: ALSA Event representing a tempo change for an ALSA queue. * * SubscriptionEvent: ALSA Event representing a subscription between two ALSA clients and ports. * * ClientEvent: ALSA Event representing a change on some ALSA sequencer client. * * PortEvent: ALSA Event representing a change on some ALSA sequencer port. * * RemoveEvents: Auxiliary class to remove events from an ALSA queue. * * MidiCodec: Auxiliary class to translate between raw MIDI streams and ALSA events. * * @see http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_event.html * @see http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_events.html * @see http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_ev_type.html * @see http://www.alsa-project.org/alsa-doc/alsa-lib/group___m_i_d_i___event.html * @} */ /** * Default constructor. */ SequencerEvent::SequencerEvent() : QEvent(SequencerEventType) { snd_seq_ev_clear( &m_event ); } /** * Constructor from an ALSA event record * @param event ALSA event record */ SequencerEvent::SequencerEvent(snd_seq_event_t* event) : QEvent(SequencerEventType) { snd_seq_ev_clear( &m_event ); m_event = *event; } /** * Copy constructor * @param other A SequencerEvent object reference */ SequencerEvent::SequencerEvent(const SequencerEvent& other) : QEvent(SequencerEventType) { snd_seq_ev_clear( &m_event ); m_event = other.m_event; } /** * Assignment operator * @param other A SequencerEvent object reference * @return This object */ SequencerEvent& SequencerEvent::operator=(const SequencerEvent& other) { m_event = other.m_event; return *this; } /** * Checks if the event's type is a subscription. * @param event A SequencerEvent object pointer * @return True if the event has a subscribe/unsubscribe type. */ bool SequencerEvent::isSubscription(const SequencerEvent* event) { snd_seq_event_type_t te = event->getSequencerType(); return ( te == SND_SEQ_EVENT_PORT_SUBSCRIBED || te == SND_SEQ_EVENT_PORT_UNSUBSCRIBED ); } /** * Checks if the event's type is of type port. * @param event A SequencerEvent object pointer * @return True if the event has a port start/exit/change type. */ bool SequencerEvent::isPort(const SequencerEvent* event) { snd_seq_event_type_t te = event->getSequencerType(); return ( te == SND_SEQ_EVENT_PORT_START || te == SND_SEQ_EVENT_PORT_EXIT || te == SND_SEQ_EVENT_PORT_CHANGE ); } /** * Checks if the event's type is of type client. * @param event A SequencerEvent object pointer * @return True if the event has a client start/exit/change type. */ bool SequencerEvent::isClient(const SequencerEvent* event) { snd_seq_event_type_t te = event->getSequencerType(); return ( te == SND_SEQ_EVENT_CLIENT_START || te == SND_SEQ_EVENT_CLIENT_EXIT || te == SND_SEQ_EVENT_CLIENT_CHANGE ); } /** * Checks if the event's type is of type connection change. * @param event A SequencerEvent object pointer * @return True if the event has a client/port/subscription type. */ bool SequencerEvent::isConnectionChange(const SequencerEvent* event) { snd_seq_event_type_t te = event->getSequencerType(); return ( te == SND_SEQ_EVENT_PORT_START || te == SND_SEQ_EVENT_PORT_EXIT || te == SND_SEQ_EVENT_PORT_CHANGE || te == SND_SEQ_EVENT_CLIENT_START || te == SND_SEQ_EVENT_CLIENT_EXIT || te == SND_SEQ_EVENT_CLIENT_CHANGE || te == SND_SEQ_EVENT_PORT_SUBSCRIBED || te == SND_SEQ_EVENT_PORT_UNSUBSCRIBED ); } /** * Checks if the event's type is a Channel Voice message. * @param event A SequencerEvent object pointer * @return True if the event is a channel voice message. * @since 0.2.0 */ bool SequencerEvent::isChannel(const SequencerEvent* event) { snd_seq_event_type_t te = event->getSequencerType(); return ( te == SND_SEQ_EVENT_NOTEOFF || te == SND_SEQ_EVENT_NOTEON || te == SND_SEQ_EVENT_NOTE || te == SND_SEQ_EVENT_KEYPRESS || te == SND_SEQ_EVENT_CONTROLLER || te == SND_SEQ_EVENT_CONTROL14 || te == SND_SEQ_EVENT_PGMCHANGE || te == SND_SEQ_EVENT_CHANPRESS || te == SND_SEQ_EVENT_PITCHBEND ); } /** * Sets the event's ALSA sequencer type * @param eventType The ALSA sequencer type */ void SequencerEvent::setSequencerType(const snd_seq_event_type_t eventType) { m_event.type = eventType; } /** * Sets the client:port destination of the event. * @param client The destination's client ID * @param port The destination port ID * @see setSubscribers() */ void SequencerEvent::setDestination(const unsigned char client, const unsigned char port) { snd_seq_ev_set_dest(&m_event, client, port); } /** * Sets the event's source port ID * @param port The source port ID * @see getSourceClient(), getSourcePort() */ void SequencerEvent::setSource(const unsigned char port) { snd_seq_ev_set_source(&m_event, port); } /** * Sets the event's destination to be all the subscribers of the source port. */ void SequencerEvent::setSubscribers() { snd_seq_ev_set_subs(&m_event); } /** * Sets the event's destination to be all queues/clients/ports/channels. */ void SequencerEvent::setBroadcast() { snd_seq_ev_set_broadcast(&m_event); } /** * Sets the event to be immediately delivered, not queued/scheduled. * @see scheduleTick(), scheduleReal() */ void SequencerEvent::setDirect() { snd_seq_ev_set_direct(&m_event); } /** * Sets the event to be scheduled in musical time (ticks) units. * @param queue The queue number to be used. * @param tick The time in ticks. * @param relative Use relative (to the current) time instead of absolute time. */ void SequencerEvent::scheduleTick(int queue, int tick, bool relative) { snd_seq_ev_schedule_tick(&m_event, queue, relative, tick); } /** * Sets the event to be scheduled in real (clock) time units. * @param queue The queue number to be used. * @param secs The time in whole seconds. * @param nanos The nanoseconds to be added. * @param relative Use relative (to the current) time instead of absolute time. */ void SequencerEvent::scheduleReal(int queue, ulong secs, ulong nanos, bool relative) { snd_seq_real_time_t rtime; rtime.tv_sec = secs; rtime.tv_nsec = nanos; snd_seq_ev_schedule_real(&m_event, queue, relative, &rtime); } /** * Sets the priority of the event. This is used in case of several events share * the same scheduling time. * * @param high Mark the event as a high priority one. */ void SequencerEvent::setPriority(const bool high) { snd_seq_ev_set_priority(&m_event, high); } /** * Sets the event's tag. This attribute is any arbitrary number, not used by * the ALSA library. Range limited to 0 thru 255. * @param aTag A tag number. */ void SequencerEvent::setTag(const unsigned char aTag) { #if SND_LIB_VERSION > 0x010008 snd_seq_ev_set_tag(&m_event, aTag); #else m_event.tag = aTag; #endif } /** * Gets an event's raw 32 bits parameter. * @param n The parameter index, between 0 and 2. * @return The parameter's value. * @see setRaw32() */ unsigned int SequencerEvent::getRaw32(const unsigned int n) const { if (n < 3) return m_event.data.raw32.d[n]; return 0; } /** * Sets an event's raw 32 bits parameter. * @param n The parameter index, between 0 and 2. * @param value The parameter's value. */ void SequencerEvent::setRaw32(const unsigned int n, const unsigned int value) { if (n < 3) m_event.data.raw32.d[n] = value; } /** * Gets an event's raw 8 bits parameter. * @param n The parameter index, between 0 and 11. * @return The parameter's value. * @see setRaw8() */ unsigned char SequencerEvent::getRaw8(const unsigned int n) const { if (n < 12) return m_event.data.raw8.d[n]; return 0; } /** * Sets an event's raw 8 bits parameter. * @param n The parameter index, between 0 and 11. * @param value The parameter's value. */ void SequencerEvent::setRaw8(const unsigned int n, const unsigned char value) { if (n < 12) m_event.data.raw8.d[n] = value; } /** * Releases the event record. * @deprecated */ void SequencerEvent::free() { snd_seq_free_event(&m_event); } /** * Gets the encoded length of the event record. * @return The encoded length. */ int SequencerEvent::getEncodedLength() { return snd_seq_event_length(&m_event); } /** * Constructor using proper attribute values. * @param ch MIDI Channel. * @param key MIDI note. * @param vel Note velocity. * @param dur Note duration. */ NoteEvent::NoteEvent(int ch, int key, int vel, int dur) : KeyEvent() { snd_seq_ev_set_note(&m_event, ch, key, vel, dur); } /** * Constructor using proper attribute values. * @param ch MIDI Channel. * @param key MIDI note. * @param vel Note velocity. */ NoteOnEvent::NoteOnEvent(int ch, int key, int vel) : KeyEvent() { snd_seq_ev_set_noteon(&m_event, ch, key, vel); } /** * Constructor using proper attribute values. * @param ch MIDI Channel. * @param key MIDI note. * @param vel Note velocity. */ NoteOffEvent::NoteOffEvent(int ch, int key, int vel) : KeyEvent() { snd_seq_ev_set_noteoff(&m_event, ch, key, vel); } /** * Constructor using proper attribute values. * @param ch MIDI Channel. * @param key MIDI note. * @param vel Note velocity. */ KeyPressEvent::KeyPressEvent(int ch, int key, int vel) : KeyEvent() { snd_seq_ev_set_keypress(&m_event, ch, key, vel); } /** * Constructor using proper attribute values. * @param ch MIDI Channel. * @param cc MIDI Controller number. * @param val Controller value. */ ControllerEvent::ControllerEvent(int ch, int cc, int val) : ChannelEvent() { snd_seq_ev_set_controller(&m_event, ch, cc, val); } /** * Constructor using proper attribute values. * @param ch MIDI Channel. * @param val MIDI Program number. */ ProgramChangeEvent::ProgramChangeEvent(int ch, int val) : ChannelEvent() { snd_seq_ev_set_pgmchange(&m_event, ch, val); } /** * Constructor using proper attribute values. * @param ch MIDI Channel. * @param val Pitch Bend value. Zero centered from -8192 to 8191. */ PitchBendEvent::PitchBendEvent(int ch, int val) : ChannelEvent() { snd_seq_ev_set_pitchbend(&m_event, ch, val); } /** * Constructor using proper attribute values. * @param ch MIDI Channel. * @param val Aftertouch value. */ ChanPressEvent::ChanPressEvent(int ch, int val) : ChannelEvent() { snd_seq_ev_set_chanpress(&m_event, ch, val); } /** * Default constructor. */ VariableEvent::VariableEvent() : SequencerEvent() { m_data.clear(); snd_seq_ev_set_variable ( &m_event, m_data.size(), m_data.data() ); } /** * Constructor from an ALSA event record. * @param event ALSA event record. */ VariableEvent::VariableEvent(snd_seq_event_t* event) : SequencerEvent(event) { m_data = QByteArray((char *) event->data.ext.ptr, event->data.ext.len); snd_seq_ev_set_variable ( &m_event, m_data.size(), m_data.data() ); } /** * Constructor from an arbitrary data array. * @param data A data byte array. */ VariableEvent::VariableEvent(const QByteArray& data) : SequencerEvent() { m_data = data; snd_seq_ev_set_variable ( &m_event, m_data.size(), m_data.data() ); } /** * Copy constructor. * @param other Another VariableEvent instance. s */ VariableEvent::VariableEvent(const VariableEvent& other) : SequencerEvent() { m_data = other.m_data; snd_seq_ev_set_variable ( &m_event, m_data.size(), m_data.data() ); } /** * Constructor from a data pointer. * @param datalen Length of the data. * @param dataptr Pointer the data. */ VariableEvent::VariableEvent(const unsigned int datalen, char* dataptr) : SequencerEvent() { m_data = QByteArray(dataptr, datalen); snd_seq_ev_set_variable( &m_event, m_data.size(), m_data.data() ); } /** * Assignment operator. * @param other Another VariableEvent object reference * @return Pointer to this object */ VariableEvent& VariableEvent::operator=(const VariableEvent& other) { m_event = other.m_event; m_data = other.m_data; snd_seq_ev_set_variable ( &m_event, m_data.size(), m_data.data() ); return *this; } /** * Default constructor. */ SysExEvent::SysExEvent() : VariableEvent() { snd_seq_ev_set_sysex( &m_event, m_data.size(), m_data.data() ); } /** * Constructor from an ALSA event record. * @param event ALSA event record. */ SysExEvent::SysExEvent(snd_seq_event_t* event) : VariableEvent(event) { snd_seq_ev_set_sysex( &m_event, m_data.size(), m_data.data() ); } /** * Constructor from a data array. * @param data A data byte array. */ SysExEvent::SysExEvent(const QByteArray& data) : VariableEvent(data) { snd_seq_ev_set_sysex( &m_event, m_data.size(), m_data.data() ); } /** * Copy constructor. * @param other Another SysExEvent object reference. */ SysExEvent::SysExEvent(const SysExEvent& other) : VariableEvent(other) { snd_seq_ev_set_sysex( &m_event, m_data.size(), m_data.data() ); } /** * Constructor taking a data pointer and length * @param datalen Data length * @param dataptr Data pointer */ SysExEvent::SysExEvent(const unsigned int datalen, char* dataptr) : VariableEvent( datalen, dataptr ) { snd_seq_ev_set_sysex( &m_event, m_data.size(), m_data.data() ); } /** * Default constructor */ TextEvent::TextEvent() : VariableEvent(), m_textType(1) { setSequencerType(SND_SEQ_EVENT_USR_VAR0); } /** * Constructor from an ALSA sequencer record. * @param event ALSA sequencer record. */ TextEvent::TextEvent(snd_seq_event_t* event) : VariableEvent(event), m_textType(1) { setSequencerType(SND_SEQ_EVENT_USR_VAR0); } /** * Constructor from a given string * @param text The event's text * @param textType The SMF text type */ TextEvent::TextEvent(const QString& text, const int textType) : VariableEvent(text.toUtf8()), m_textType(textType) { setSequencerType(SND_SEQ_EVENT_USR_VAR0); } /** * Copy constructor * @param other An existing TextEvent object reference */ TextEvent::TextEvent(const TextEvent& other) : VariableEvent(other) { setSequencerType(SND_SEQ_EVENT_USR_VAR0); m_textType = other.getTextType(); } /** * Constructor from a data pointer and length * @param datalen Data length * @param dataptr Data pointer */ TextEvent::TextEvent(const unsigned int datalen, char* dataptr) : VariableEvent(datalen, dataptr), m_textType(1) { setSequencerType(SND_SEQ_EVENT_USR_VAR0); } /** * Gets the event's text content. * @return The text content. */ QString TextEvent::getText() const { return QString::fromUtf8(m_data.data(), m_data.size()); } /** * Gets the event's SMF text type. * @return The SMF text type. */ int TextEvent::getTextType() const { return m_textType; } /** * Constructor * @param type The event's type */ SystemEvent::SystemEvent(const snd_seq_event_type_t type) : SequencerEvent() { snd_seq_ev_set_fixed(&m_event); setSequencerType(type); } /** * Constructor * @param type Event type * @param queue Queue number * @param value Value */ QueueControlEvent::QueueControlEvent(snd_seq_event_type_t type, int queue, int value) : SequencerEvent() { snd_seq_ev_set_queue_control(&m_event, type, queue, value); } /** * Constructor * @param type The event's type * @param val Value */ ValueEvent::ValueEvent(const snd_seq_event_type_t type, int val) : SequencerEvent() { snd_seq_ev_set_fixed(&m_event); setSequencerType(type); setValue(val); } /** * Constructor * @param queue Queue number. * @param tempo Tempo value in microseconds per quarter note. */ TempoEvent::TempoEvent(int queue, int tempo) : QueueControlEvent() { snd_seq_ev_set_queue_tempo(&m_event, queue, tempo); } /** * Default constructor. */ RemoveEvents::RemoveEvents() { snd_seq_remove_events_malloc(&m_Info); } /** * Copy constructor. * @param other An existing RemoveEvents object reference. */ RemoveEvents::RemoveEvents(const RemoveEvents& other) { snd_seq_remove_events_malloc(&m_Info); snd_seq_remove_events_copy(m_Info, other.m_Info); } /** * Constructor from an ALSA remove events object pointer. * @param other An ALSA remove events object pointer. */ RemoveEvents::RemoveEvents(snd_seq_remove_events_t* other) { snd_seq_remove_events_malloc(&m_Info); snd_seq_remove_events_copy(m_Info, other); } /** * Destructor. */ RemoveEvents::~RemoveEvents() { snd_seq_remove_events_free(m_Info); } /** * Create a new object copied from this object and return a pointer to the copy. * @return A pointer to the new object. */ RemoveEvents* RemoveEvents::clone() { return new RemoveEvents(m_Info); } /** * Assignment operator. * @param other An existing RemoveEvents object reference. * @return This object. */ RemoveEvents& RemoveEvents::operator=(const RemoveEvents& other) { snd_seq_remove_events_copy(m_Info, other.m_Info); return *this; } /** * Gets the allocated size of the ALSA remove events object. * @return The size of the ALSA remove events object. */ int RemoveEvents::getSizeOfInfo() const { return snd_seq_remove_events_sizeof(); } /** * Gets the MIDI channel. * @return The MIDI channel. * @see setChannel() */ int RemoveEvents::getChannel() { return snd_seq_remove_events_get_channel(m_Info); } /** * Gets the condition. * @return The condition. * @see setCondition() */ unsigned int RemoveEvents::getCondition() { return snd_seq_remove_events_get_condition(m_Info); } /** * Gets the destination. * @return The destination record pointer. * @see setDest() */ const snd_seq_addr_t* RemoveEvents::getDest() { return snd_seq_remove_events_get_dest(m_Info); } /** * Gets the event type. * @return The event type. * @see setEventType() */ int RemoveEvents::getEventType() { return snd_seq_remove_events_get_event_type(m_Info); } /** * Gets the queue number. * @return The queue number. * @see setQueue() */ int RemoveEvents::getQueue() { return snd_seq_remove_events_get_queue(m_Info); } /** * Gets the numeric tag. * @return The numeric tag. * @see setTag() */ int RemoveEvents::getTag() { return snd_seq_remove_events_get_tag(m_Info); } /** * Gets the timestamp. * @return The timestamp. * @see setTime() */ const snd_seq_timestamp_t* RemoveEvents::getTime() { return snd_seq_remove_events_get_time(m_Info); } /** * Gets the MIDI channel. * @param chan The MIDI channel. * @see getChannel() */ void RemoveEvents::setChannel(int chan) { snd_seq_remove_events_set_channel(m_Info, chan); } /** * Sets the flags of the conditional event's removal. This condition is a * bitmap of the combination (OR) the following auto-described flags: *
    *
  • SND_SEQ_REMOVE_INPUT
  • *
  • SND_SEQ_REMOVE_OUTPUT
  • *
  • SND_SEQ_REMOVE_DEST
  • *
  • SND_SEQ_REMOVE_DEST_CHANNEL
  • *
  • SND_SEQ_REMOVE_TIME_BEFORE
  • *
  • SND_SEQ_REMOVE_TIME_AFTER
  • *
  • SND_SEQ_REMOVE_TIME_TICK
  • *
  • SND_SEQ_REMOVE_EVENT_TYPE
  • *
  • SND_SEQ_REMOVE_IGNORE_OFF
  • *
  • SND_SEQ_REMOVE_TAG_MATCH
  • *
* @param cond The condition bitmap. * @see getCondition() */ void RemoveEvents::setCondition(unsigned int cond) { snd_seq_remove_events_set_condition(m_Info, cond); } /** * Set the destination address. * @param dest A pointer to the destination address record. * @see getDest() */ void RemoveEvents::setDest(const snd_seq_addr_t* dest) { snd_seq_remove_events_set_dest(m_Info, dest); } /** * Sets the event type. * @param type The event type. * @see getEventType() */ void RemoveEvents::setEventType(int type) { snd_seq_remove_events_set_event_type(m_Info, type); } /** * Sets the queue number. * @param queue The queue number. * @see getQueue() */ void RemoveEvents::setQueue(int queue) { snd_seq_remove_events_set_queue(m_Info, queue); } /** * Sets the numeric tag. * @param tag The numeric tag. * @see getTag() */ void RemoveEvents::setTag(int tag) { snd_seq_remove_events_set_tag(m_Info, tag); } /** * Sets the timestamp. * @param time A pointer to the timestamp record. * @see getTime() */ void RemoveEvents::setTime(const snd_seq_timestamp_t* time) { snd_seq_remove_events_set_time(m_Info, time); } /** * MidiCodec constructor * @param bufsize The buffer size of the CODEC * @param parent The optional parent object */ MidiCodec::MidiCodec( int bufsize, QObject* parent ) : QObject(parent) { CHECK_ERROR(snd_midi_event_new(bufsize, &m_Info)); } /** * Destructor */ MidiCodec::~MidiCodec() { snd_midi_event_free(m_Info); } /** * CODEC initialization. */ void MidiCodec::init() { snd_midi_event_init(m_Info); } /** * Decode from event to bytes. * @param buf A buffer to get the results * @param count Available bytes in MIDI byte stream * @param ev The input event * @return The number of written bytes if success. */ long MidiCodec::decode(unsigned char *buf, long count, const snd_seq_event_t *ev) { return CHECK_WARNING(snd_midi_event_decode(m_Info, buf, count, ev)); } /** * Encode from byte stream. * @param buf MIDI byte stream * @param count Bytes of MIDI byte stream to encode * @param ev Result - sequencer event * @return Number of written bytes if success. */ long MidiCodec::encode(const unsigned char *buf, long count, snd_seq_event_t *ev) { return CHECK_WARNING(snd_midi_event_encode(m_Info, buf, count, ev)); } /** * Read one byte and encode to sequencer event if finished. * @param c A byte of MIDI stream * @param ev Result - sequencer event * @return 1 - sequencer event is completed, 0 - next byte is required for completion, otherwise a negative error code */ long MidiCodec::encode(int c, snd_seq_event_t *ev) { return CHECK_WARNING(snd_midi_event_encode_byte(m_Info, c, ev)); } /** * Enable MIDI running status (command merge) * @param enable True to enable, false to disable. */ void MidiCodec::enableRunningStatus(bool enable) { snd_midi_event_no_status(m_Info, enable ? 0 : 1); } /** * Reset MIDI decode parser. */ void MidiCodec::resetDecoder() { snd_midi_event_reset_decode(m_Info); } /** * Reset MIDI encode parser. */ void MidiCodec::resetEncoder() { snd_midi_event_reset_encode(m_Info); } /** * Resize the CODEC buffer * @param bufsize New buffer size. */ void MidiCodec::resizeBuffer(int bufsize) { CHECK_WARNING(snd_midi_event_resize_buffer(m_Info, bufsize)); } } /* namespace drumstick */ drumstick-1.1.3/library/alsa/PaxHeaders.32572/alsatimer.cpp0000644000000000000000000000013013532747316020342 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/alsa/alsatimer.cpp0000644000175000001440000007226613532747316021152 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include /** * @file alsatimer.cpp * Implementation of classes managing ALSA Timers */ namespace drumstick { /** * @addtogroup ALSATimer * @{ * * Timers provide periodic time events to applications, and also to the ALSA * sequencer. * * There are two mechanisms to deliver the timer events. To use the callback * mechanism, a class must be derived from TimerEventHandler, and a instance * of the derived class must be assigned to the Timer instance using * Timer::setHandler(). If the handler is not assigned, then the Timer instance * will generate the signal Timer::timerExpired(). * * Classes: * * TimerInfo: ALSA Timer information container. * * This class is used to hold properties about ALSA Timers. * * TimerId: ALSA Timer identifier container. * * This class provides an unique identifier for a Timer. * * TimerGlobalInfo: Global timer information container. * * This class provides global timer parameters. * * TimerQuery: ALSA Timer inquiry helper. * * This class provides a mechanism to enumerate the available system timers. * * TimerParams: ALSA Timer parameters container. * * This class provides several parameters about a Timer. * * TimerStatus: ALSA Timer status container. * * This class provides some status information about a Timer. * * TimerEventHandler: ALSA Timer events handler. * * This abstract class is used to define an interface that other class can * implement to receive timer events. * * Timer: ALSA Timer management. * * This class represents an ALSA timer object. * * @see http://www.alsa-project.org/alsa-doc/alsa-lib/group___timer.html * @} */ /** * Constructor */ TimerInfo::TimerInfo() { snd_timer_info_malloc(&m_Info); } /** * Cosntructor * @param other ALSA timer info object pointer */ TimerInfo::TimerInfo(const snd_timer_info_t *other) { snd_timer_info_malloc(&m_Info); snd_timer_info_copy(m_Info, other); } /** * Copy constructor * @param other Existing TimerInfo object reference */ TimerInfo::TimerInfo(const TimerInfo& other) { snd_timer_info_malloc(&m_Info); snd_timer_info_copy(m_Info, other.m_Info); } /** * Destructor */ TimerInfo::~TimerInfo() { snd_timer_info_free(m_Info); } /** * Copy the current object * @return Pointer to the new object */ TimerInfo* TimerInfo::clone() { return new TimerInfo(m_Info); } /** * Assignment operator * @param other Existing TimerInfo object reference */ TimerInfo& TimerInfo::operator=(const TimerInfo& other) { snd_timer_info_copy(m_Info, other.m_Info); return *this; } /** * Check if the timer is slave (depends on another device) * @return True if the timer is slave */ bool TimerInfo::isSlave() { return (snd_timer_info_is_slave(m_Info) != 0); } /** * Gets the card number * @return Card number */ int TimerInfo::getCard() { return snd_timer_info_get_card(m_Info); } /** * Gets the string identifier * @return String identifier */ QString TimerInfo::getId() { return QString(snd_timer_info_get_id(m_Info)); } /** * Gets the timer name * @return Timer name */ QString TimerInfo::getName() { return QString(snd_timer_info_get_name(m_Info)); } /** * Gets the timer resolution (timer period in nanoseconds) * @return Timer resolution in nanos */ long TimerInfo::getResolution() { return snd_timer_info_get_resolution(m_Info); } /** * Gets the timer frequency in Hz * @return Timer frequency in Hz */ long TimerInfo::getFrequency() { long res = getResolution(); if (res > 0) { return 1000000000L / res; } return 0; } /** * Gets the size of the ALSA timer info object * @return Size of the ALSA object */ int TimerInfo::getSizeOfInfo() const { return snd_timer_info_sizeof(); } /** * Gets the maximum timer ticks * @deprecated * @return Maximum timer ticks */ long TimerInfo::getTicks() { return snd_timer_info_get_ticks(m_Info); } /** * Constructor */ TimerId::TimerId() { snd_timer_id_malloc(&m_Info); } /** * Constructor * @param other ALSA timer ID object pointer */ TimerId::TimerId(const snd_timer_id_t *other) { snd_timer_id_malloc(&m_Info); snd_timer_id_copy(m_Info, other); if (getCard() < 0) setCard(0); if (getDevice() < 0) setDevice(0); if (getSubdevice() < 0) setSubdevice(0); } /** * Copy constructor * @param other Existing TimerId object reference */ TimerId::TimerId(const TimerId& other) { snd_timer_id_malloc(&m_Info); snd_timer_id_copy(m_Info, other.m_Info); if (getCard() < 0) setCard(0); if (getDevice() < 0) setDevice(0); if (getSubdevice() < 0) setSubdevice(0); } /** * Constructor * @param cls Class * @param scls Subclass * @param card Card * @param dev Device * @param sdev Subdevice */ TimerId::TimerId(int cls, int scls, int card, int dev, int sdev) { snd_timer_id_malloc(&m_Info); setClass(cls); setSlaveClass(scls); setCard(card); setDevice(dev); setSubdevice(sdev); } /** * Destructor */ TimerId::~TimerId() { snd_timer_id_free(m_Info); } /** * Copy the object * @return Pointer to the new object */ TimerId* TimerId::clone() { return new TimerId(m_Info); } /** * Assignment operator * @param other Existing TimerId object reference * @return This object */ TimerId& TimerId::operator=(const TimerId& other) { snd_timer_id_copy(m_Info, other.m_Info); if (getCard() < 0) setCard(0); if (getDevice() < 0) setDevice(0); if (getSubdevice() < 0) setSubdevice(0); return *this; } /** * Set the class identifier. Existing classes: *
    *
  • SND_TIMER_CLASS_SLAVE: slave timer
  • *
  • SND_TIMER_CLASS_GLOBAL: global timer
  • *
  • SND_TIMER_CLASS_CARD: card timer
  • *
  • SND_TIMER_CLASS_PCM: PCM timer
  • *
* @param devclass Class identifier. */ void TimerId::setClass(int devclass) { snd_timer_id_set_class(m_Info, devclass); } /** * Gets the class identifier. * @return Class identifier * @see setClass() */ int TimerId::getClass() { return snd_timer_id_get_class(m_Info); } /** * Sets the Slave class * @param devsclass Slave class */ void TimerId::setSlaveClass(int devsclass) { snd_timer_id_set_sclass(m_Info, devsclass); } /** * Gets the slave class * @return Slave class */ int TimerId::getSlaveClass() { return snd_timer_id_get_sclass(m_Info); } /** * Sets the card number * @param card Card number */ void TimerId::setCard(int card) { snd_timer_id_set_card(m_Info, card); } /** * Gets the card number * @return Card number */ int TimerId::getCard() { return snd_timer_id_get_card(m_Info); } /** * Sets the device number * @param device Device number */ void TimerId::setDevice(int device) { snd_timer_id_set_device(m_Info, device); } /** * Gets the device number * @return Device number */ int TimerId::getDevice() { return snd_timer_id_get_device(m_Info); } /** * Sets the subdevice number * @param subdevice Subdevice number */ void TimerId::setSubdevice(int subdevice) { snd_timer_id_set_subdevice (m_Info, subdevice); } /** * Gets the subdevice number * @return Subdevice number */ int TimerId::getSubdevice() { return snd_timer_id_get_subdevice(m_Info); } /** * Gets the size of the ALSA timer ID object * @return Size of the ALSA object */ int TimerId::getSizeOfInfo() const { return snd_timer_id_sizeof(); } /** * Constructor * @param deviceName Device name, usually "hw" * @param openMode Open mode (unknown values) */ TimerQuery::TimerQuery(const QString& deviceName, int openMode) { CHECK_WARNING( snd_timer_query_open( &m_Info, deviceName.toLocal8Bit().data(), openMode )); readTimers(); } /** * Constructor * @param deviceName Device name, usually "hw" * @param openMode Open mode (unknown values) * @param conf ALSA configuration object pointer */ TimerQuery::TimerQuery( const QString& deviceName, int openMode, snd_config_t* conf ) { CHECK_WARNING( snd_timer_query_open_lconf( &m_Info, deviceName.toLocal8Bit().data(), openMode, conf )); readTimers(); } /** * Destructor */ TimerQuery::~TimerQuery() { freeTimers(); snd_timer_query_close(m_Info); } /** * Enumerate the available timers storing the results into an internal list */ void TimerQuery::readTimers() { TimerId tid; snd_timer_id_set_class(tid.m_Info, SND_TIMER_CLASS_NONE); for(;;) { int rc = snd_timer_query_next_device(m_Info, tid.m_Info); if ((rc < 0) || (tid.getClass() < 0)) { break; } m_timers.append(tid); } } /** * Release the internal list of timers */ void TimerQuery::freeTimers() { m_timers.clear(); } /** * Get a TimerGlobalInfo object * @return TimerGlobalInfo object reference */ TimerGlobalInfo& TimerQuery::getGlobalInfo() { snd_timer_query_info(m_Info, m_GlobalInfo.m_Info); return m_GlobalInfo; } /** * Sets the global parameters * @param params Pointer to an ALSA timer global parameters object */ void TimerQuery::setGlobalParams(snd_timer_gparams_t* params) { snd_timer_query_params(m_Info, params); } /** * Gets the global timer parameters * @param params Pointer to an ALSA timer global parameters object */ void TimerQuery::getGlobalParams(snd_timer_gparams_t* params) { snd_timer_query_params(m_Info, params); } /** * Gets the global timer status * @param status Pointer to an ALSA timer global status object */ void TimerQuery::getGlobalStatus(snd_timer_gstatus_t *status) { snd_timer_query_status(m_Info, status); } /** * Default constructor */ TimerGlobalInfo::TimerGlobalInfo() { snd_timer_ginfo_malloc(&m_Info); } /** * Constructor * @param other ALSA global info object pointer */ TimerGlobalInfo::TimerGlobalInfo(const snd_timer_ginfo_t* other) { snd_timer_ginfo_malloc(&m_Info); snd_timer_ginfo_copy(m_Info, other); } /** * Copy constructor * @param other Existing TimerGlobalInfo object reference */ TimerGlobalInfo::TimerGlobalInfo(const TimerGlobalInfo& other) { snd_timer_ginfo_malloc(&m_Info); snd_timer_ginfo_copy(m_Info, other.m_Info); } /** * Destructor */ TimerGlobalInfo::~TimerGlobalInfo() { snd_timer_ginfo_free(m_Info); } /** * Copy the current object * @return Pointer to the new object */ TimerGlobalInfo* TimerGlobalInfo::clone() { return new TimerGlobalInfo(m_Info); } /** * Assignment operator * @param other Existing TimerGlobalInfo object reference * @return This object */ TimerGlobalInfo& TimerGlobalInfo::operator=(const TimerGlobalInfo& other) { snd_timer_ginfo_copy(m_Info, other.m_Info); return *this; } /** * Sets the timer identifier * @param tid TimerId object reference */ void TimerGlobalInfo::setTimerId(const TimerId& tid) { m_Id = tid; snd_timer_ginfo_set_tid (m_Info, m_Id.m_Info); } /** * Gets the timer identifier * @return TimerId object reference */ TimerId& TimerGlobalInfo::getTimerId() { m_Id = TimerId(snd_timer_ginfo_get_tid (m_Info)); return m_Id; } /** * Gets the flags * @return Undocumented flags */ unsigned int TimerGlobalInfo::getFlags() { return snd_timer_ginfo_get_flags (m_Info); } /** * Gets the card number * @return Card number */ int TimerGlobalInfo::getCard() { return snd_timer_ginfo_get_card (m_Info); } /** * Gets the timer ID string * @return Timer ID string */ QString TimerGlobalInfo::getId() { return QString(snd_timer_ginfo_get_id (m_Info)); } /** * Gets the timer name * @return Timer name */ QString TimerGlobalInfo::getName() { return QString(snd_timer_ginfo_get_name (m_Info)); } /** * Gets the timer resolution in ns * @return Timer resolution in ns */ unsigned long TimerGlobalInfo::getResolution() { return snd_timer_ginfo_get_resolution (m_Info); } /** * Gets timer minimal resolution in ns * @return Minimal resolution in ns */ unsigned long TimerGlobalInfo::getMinResolution() { return snd_timer_ginfo_get_resolution_min (m_Info); } /** * Gets timer maximal resolution in ns * @return Maximal resolution in ns */ unsigned long TimerGlobalInfo::getMaxResolution() { return snd_timer_ginfo_get_resolution_max(m_Info); } /** * Gets current timer clients * @return Current clients */ unsigned int TimerGlobalInfo::getClients() { return snd_timer_ginfo_get_clients(m_Info); } /** * Gets the size of the ALSA timer global info object * @return Size of the ALSA object */ int TimerGlobalInfo::getSizeOfInfo() const { return snd_timer_ginfo_sizeof(); } /** * Default constructor */ TimerParams::TimerParams() { snd_timer_params_malloc (&m_Info); } /** * Constructor * @param other Pointer to an ALSA timer parameters object */ TimerParams::TimerParams(const snd_timer_params_t *other) { snd_timer_params_malloc (&m_Info); snd_timer_params_copy (m_Info, other); } /** * Copy constructor * @param other Existing TimerParams object reference */ TimerParams::TimerParams(const TimerParams& other) { snd_timer_params_malloc (&m_Info); snd_timer_params_copy (m_Info, other.m_Info); } /** * Destructor * @return */ TimerParams::~TimerParams() { snd_timer_params_free (m_Info); } /** * Copy the current object * @return Pointer to the new object */ TimerParams* TimerParams::clone() { return new TimerParams(m_Info); } /** * Assignment operator * @param other Existing TimerParams object reference * @return This object */ TimerParams& TimerParams::operator=(const TimerParams& other) { snd_timer_params_copy (m_Info, other.m_Info); return *this; } /** * Sets the automatic start flag * @param auto_start Value for the automatic start flag */ void TimerParams::setAutoStart(bool auto_start) { snd_timer_params_set_auto_start (m_Info, auto_start ? 1 : 0); } /** * Gets the automatic start flag * @return True if the timer starts automatically */ bool TimerParams::getAutoStart() { return (snd_timer_params_get_auto_start (m_Info) != 0); } /** * Sets the exclusive flag * @param exclusive True if the timer has the exclusive flag */ void TimerParams::setExclusive(bool exclusive) { snd_timer_params_set_exclusive (m_Info, exclusive ? 1 : 0); } /** * Gets the timer's exclusive flag * @return True if the timer has the exclusive flag */ bool TimerParams::getExclusive() { return (snd_timer_params_get_exclusive (m_Info) != 0); } /** * Sets the timer early event * @param early_event Timer early event */ void TimerParams::setEarlyEvent(bool early_event) { snd_timer_params_set_early_event (m_Info, early_event ? 1 : 0); } /** * Gets the timer early event * @return Timer early event */ bool TimerParams::getEarlyEvent() { return (snd_timer_params_get_early_event (m_Info) != 0); } /** * Sets the timer ticks * @param ticks Timer ticks */ void TimerParams::setTicks(long ticks) { snd_timer_params_set_ticks (m_Info, ticks); } /** * Gets the timer ticks * @return Timer ticks */ long TimerParams::getTicks() { return snd_timer_params_get_ticks (m_Info); } /** * Sets the queue size (32-1024) * @param queue_size Queue size */ void TimerParams::setQueueSize(long queue_size) { snd_timer_params_set_queue_size (m_Info, queue_size); } /** * Gets the queue size * @return Queue size */ long TimerParams::getQueueSize() { return snd_timer_params_get_queue_size (m_Info); } /** * Sets the event filter * @param filter Event filter */ void TimerParams::setFilter(unsigned int filter) { snd_timer_params_set_filter (m_Info, filter); } /** * Gets the event filter * @return Event filter */ unsigned int TimerParams::getFilter() { return snd_timer_params_get_filter (m_Info); } /** * Gets the size of the ALSA timer parameters object * @return Size of the ALSA object */ int TimerParams::getSizeOfInfo() const { return snd_timer_params_sizeof(); } /** * Default constructor */ TimerStatus::TimerStatus() { snd_timer_status_malloc (&m_Info); } /** * Constructor * @param other Pointer to an existing ALSA timer status object */ TimerStatus::TimerStatus(const snd_timer_status_t *other) { snd_timer_status_malloc (&m_Info); snd_timer_status_copy (m_Info, other); } /** * Copy constructor * @param other Existing TimerStatus object reference */ TimerStatus::TimerStatus(const TimerStatus& other) { snd_timer_status_malloc (&m_Info); snd_timer_status_copy (m_Info, other.m_Info); } /** * Destructor */ TimerStatus::~TimerStatus() { snd_timer_status_free (m_Info); } /** * Copy the current object * @return Pointer to the new object */ TimerStatus* TimerStatus::clone() { return new TimerStatus(m_Info); } /** * Assignment operator * @param other Existing TimerStatus object reference * @return This object */ TimerStatus& TimerStatus::operator=(const TimerStatus& other) { snd_timer_status_copy (m_Info, other.m_Info); return *this; } /** * Gets the high resolution time-stamp * @return High resolution time-stamp */ snd_htimestamp_t TimerStatus::getTimestamp() { return snd_timer_status_get_timestamp (m_Info); } /** * Gets the resolution in us * @return Resolution in us */ long TimerStatus::getResolution() { return snd_timer_status_get_resolution (m_Info); } /** * Gets the master tick lost count * @return Master tick lost count */ long TimerStatus::getLost() { return snd_timer_status_get_lost (m_Info); } /** * Gets the overrun count * @return Overrun count */ long TimerStatus::getOverrun() { return snd_timer_status_get_overrun (m_Info); } /** * Gets the count of used queue elements * @return Count of used queue elements */ long TimerStatus::getQueue() { return snd_timer_status_get_queue (m_Info); } /** * Gets the size of the ALSA timer status object * @return Size of the ALSA object */ int TimerStatus::getSizeOfInfo() const { return snd_timer_status_sizeof(); } /** * Constructor. * Open flags can be a combination of the following constants: *
    *
  • SND_TIMER_OPEN_NONBLOCK: non-blocking behavior
  • *
  • SND_TIMER_OPEN_TREAD: enhanced read, use time-stamps and event notification
  • *
* @param deviceName Name of the device * @param openMode Open mode flags bitmap * @param parent Optional parent object */ Timer::Timer( const QString& deviceName, int openMode, QObject* parent ) : QObject(parent), m_asyncHandler(NULL), m_handler(NULL), m_thread(NULL), m_deviceName(deviceName) { CHECK_ERROR( snd_timer_open( &m_Info, m_deviceName.toLocal8Bit().data(), openMode )); } /** * Constructor. * Open flags can be a combination of the following constants: *
    *
  • SND_TIMER_OPEN_NONBLOCK: non-blocking behavior
  • *
  • SND_TIMER_OPEN_TREAD: enhanced read, use time-stamps and event notification
  • *
* @param deviceName Name of the device * @param openMode Open mode flags bitmap * @param conf ALSA configuration object pointer * @param parent Optional parent object */ Timer::Timer( const QString& deviceName, int openMode, snd_config_t* conf, QObject* parent ) : QObject(parent), m_asyncHandler(NULL), m_handler(NULL), m_thread(NULL), m_deviceName(deviceName) { CHECK_ERROR( snd_timer_open_lconf( &m_Info, m_deviceName.toLocal8Bit().data(), openMode, conf )); } /** * Constructor * Open flags can be a combination of the following constants: *
    *
  • SND_TIMER_OPEN_NONBLOCK: non-blocking behavior
  • *
  • SND_TIMER_OPEN_TREAD: enhanced read, use time-stamps and event notification
  • *
* @param id TimerId object reference * @param openMode Open mode flags bitmap * @param parent Optional parent object */ Timer::Timer( TimerId& id, int openMode, QObject* parent ) : QObject(parent), m_asyncHandler(NULL), m_handler(NULL), m_thread(NULL) { m_deviceName = QString("hw:CLASS=%1,SCLASS=%2,CARD=%3,DEV=%4,SUBDEV=%5") .arg(id.getClass()) .arg(id.getSlaveClass()) .arg(id.getCard()) .arg(id.getDevice()) .arg(id.getSubdevice()); CHECK_ERROR( snd_timer_open( &m_Info, m_deviceName.toLocal8Bit().data(), openMode )); } /** * Constructor. * Open flags can be a combination of the following constants: *
    *
  • SND_TIMER_OPEN_NONBLOCK: non-blocking behavior
  • *
  • SND_TIMER_OPEN_TREAD: enhanced read, use time-stamps and event notification
  • *
* @param cls Class * @param scls Subclass * @param card Card * @param dev Device * @param sdev Subdevice * @param openMode Open mode flags bitmap * @param parent Optional parent object */ Timer::Timer( int cls, int scls, int card, int dev, int sdev, int openMode, QObject* parent ) : QObject(parent), m_asyncHandler(NULL), m_handler(NULL), m_thread(NULL) { m_deviceName = QString("hw:CLASS=%1,SCLASS=%2,CARD=%3,DEV=%4,SUBDEV=%5") .arg(cls) .arg(scls) .arg(card) .arg(dev) .arg(sdev); CHECK_ERROR( snd_timer_open( &m_Info, m_deviceName.toLocal8Bit().data(), openMode )); } /** * Destructor. */ Timer::~Timer() { stopEvents(); if (m_thread != NULL) delete m_thread; CHECK_WARNING(snd_timer_close(m_Info)); } /** * Adds an asynchronous timer handler function. * @param callback Function handler * @param private_data Any data that will be passed to the callback */ void Timer::addAsyncTimerHandler(snd_async_callback_t callback, void *private_data) { CHECK_WARNING(snd_async_add_timer_handler(&m_asyncHandler, m_Info, callback, private_data)); } /** * Gets the ALSA timer handle * @return ALSA timer handle */ snd_timer_t* Timer::getTimerHandle() { return snd_async_handler_get_timer(m_asyncHandler); } /** * Gets the count of poll descriptors * @return Count of poll descriptors */ int Timer::getPollDescriptorsCount() { return snd_timer_poll_descriptors_count(m_Info); } /** * Gets poll descriptors * @param pfds Pointer to a pollfd array * @param space Number of pollfd elements available */ void Timer::pollDescriptors(struct pollfd *pfds, unsigned int space) { CHECK_WARNING(snd_timer_poll_descriptors(m_Info, pfds, space)); } /** * Gets returned events from poll descriptors * @param pfds Pointer to a pollfd array * @param nfds Number of pollfd elements available * @param revents Returned events */ void Timer::pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds, unsigned short *revents) { CHECK_WARNING(snd_timer_poll_descriptors_revents(m_Info, pfds, nfds, revents)); } /** * Gets the timer info object * @return TimerInfo object reference */ TimerInfo& Timer::getTimerInfo() { snd_timer_info (m_Info, m_TimerInfo.m_Info); return m_TimerInfo; } /** * Sets the timer parameters * @param params TimerParams object reference */ void Timer::setTimerParams(const TimerParams& params) { CHECK_WARNING( snd_timer_params(m_Info, params.m_Info) ); } /** * Gets the timer status * @return TimerStatus object reference */ TimerStatus& Timer::getTimerStatus() { CHECK_WARNING( snd_timer_status(m_Info, m_TimerStatus.m_Info) ); return m_TimerStatus; } /** * Start rolling the timer */ void Timer::start() { CHECK_WARNING(snd_timer_start(m_Info)); } /** * Stop rolling the timer */ void Timer::stop() { CHECK_WARNING(snd_timer_stop(m_Info)); } /** * Continue rolling the timer */ void Timer::continueRunning() { CHECK_WARNING(snd_timer_continue(m_Info)); } /** * Read bytes from the timer handle * @param buffer Buffer to store the input bytes * @param size Input buffer size in bytes * @return Bytes read from the timer */ ssize_t Timer::read(void *buffer, size_t size) { return snd_timer_read(m_Info, buffer, size); } /** * Internal function to deliver the timer events using one of the two available * methods: *
    *
  • TimerEventHandler instance pointer provided in Timer::setHandler()
  • *
  • A signal Timer::timerExpired() is emitted, otherwise
  • *
*/ void Timer::doEvents() { snd_timer_tread_t tr; while ( read(&tr, sizeof(tr)) == sizeof(tr) ) { int msecs = ((tr.tstamp.tv_sec - m_last_time.tv_sec) * 1000) + round((tr.tstamp.tv_nsec - m_last_time.tv_nsec) / 1000000.0); m_last_time = tr.tstamp; if ( m_handler != NULL ) m_handler->handleTimerEvent(tr.val, msecs); else emit timerExpired(tr.val, msecs); } } /** * Starts the events dispatching thread */ void Timer::startEvents() { m_last_time = getTimerStatus().getTimestamp(); if (m_thread == NULL) { m_thread = new TimerInputThread(this, 500); m_thread->start(); } } /** * Stops the events dispatching thread */ void Timer::stopEvents() { int counter = 0; if (m_thread != NULL) { m_thread->stop(); while (!m_thread->wait(500) && (counter < 10)) { counter++; } if (!m_thread->isFinished()) { m_thread->terminate(); } delete m_thread; } } /** * Check and return the best available global TimerId in the system, meaning * the timer with higher frequency (or lesser period, resolution). * @return A TimerId object * @since 0.3.0 */ TimerId Timer::bestGlobalTimerId() { TimerId id; snd_timer_t* timer; snd_timer_info_t* info; long res, best_res = LONG_MAX; char timername[64]; int test_devs[] = { SND_TIMER_GLOBAL_SYSTEM , SND_TIMER_GLOBAL_RTC #ifdef SND_TIMER_GLOBAL_HPET , SND_TIMER_GLOBAL_HPET #endif #ifdef SND_TIMER_GLOBAL_HRTIMER , SND_TIMER_GLOBAL_HRTIMER #endif }; int max_global_timers = sizeof(test_devs)/sizeof(int); int clas = SND_TIMER_CLASS_GLOBAL; int scls = SND_TIMER_SCLASS_NONE; int card = 0; int dev = SND_TIMER_GLOBAL_SYSTEM; int sdev = 0; int err = 0; int is_slave = 0; int i; snd_timer_info_alloca(&info); // default system timer id.setClass(clas); id.setSlaveClass(scls); id.setCard(card); id.setDevice(dev); id.setSubdevice(sdev); // select a non slave timer with the lowest resolution value for( i = 0; i < max_global_timers; ++i ) { dev = test_devs[i]; sprintf( timername, "hw:CLASS=%i,SCLASS=%i,CARD=%i,DEV=%i,SUBDEV=%i", clas, scls, card, dev, sdev ); err = snd_timer_open(&timer, timername, SND_TIMER_OPEN_NONBLOCK); if (err < 0) continue; err = snd_timer_info(timer, info); if (err == 0) { is_slave = snd_timer_info_is_slave(info); res = snd_timer_info_get_resolution(info); if ((is_slave == 0) && (best_res > res)) { best_res = res; id.setDevice(dev); } } snd_timer_close(timer); } return id; } /** * Check and return the best available global Timer in the system, meaning * the timer with higher frequency (or lesser period, resolution). * @param openMode Open mode flags * @param parent Optional parent object * @return A new Timer instance pointer */ Timer* Timer::bestGlobalTimer(int openMode, QObject* parent) { TimerId id = bestGlobalTimerId(); return new Timer(id, openMode, parent); } /** * Loop reading and dispatching timer events. */ void Timer::TimerInputThread::run() { int err, count; struct pollfd *fds; if (m_timer == NULL) return; count = m_timer->getPollDescriptorsCount(); fds = (pollfd *) calloc(count, sizeof(struct pollfd)); if (fds == NULL) { qWarning() << "allocation error!"; return; } fds->events = POLLIN; fds->revents = 0; try { while (!stopped() && (m_timer != NULL)) { m_timer->pollDescriptors(fds, count); if ((err = poll(fds, count, m_Wait)) < 0) { qWarning() << "poll error " << err << "(" << strerror(err) << ")"; return; } if (err == 0) { qWarning() << "timer time out"; return; } m_timer->doEvents(); } } catch (...) { qWarning() << "exception in input thread"; } free(fds); } /** * Returns the rolling state of the timer thread * @return The stopped state */ bool Timer::TimerInputThread::stopped() { QReadLocker locker(&m_mutex); return m_Stopped; } /** * Stop the thread */ void Timer::TimerInputThread::stop() { QWriteLocker locker(&m_mutex); m_Stopped = true; } } /* namespace drumstick */ drumstick-1.1.3/library/alsa/PaxHeaders.32572/alsaclient.cpp0000644000000000000000000000013013532747316020500 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.930000148 29 ctime=1567346382.71399987 drumstick-1.1.3/library/alsa/alsaclient.cpp0000644000175000001440000017613713532747316021312 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #if defined(RTKIT_SUPPORT) #include #include #include #include #include #endif #include #ifndef RLIMIT_RTTIME #define RLIMIT_RTTIME 15 #endif #ifndef SCHED_RESET_ON_FORK #define SCHED_RESET_ON_FORK 0x40000000 #endif #ifndef DEFAULT_INPUT_TIMEOUT #define DEFAULT_INPUT_TIMEOUT 500 #endif /** * @file alsaclient.cpp * Implementation of classes managing ALSA Sequencer clients */ /** * @class QObject * The QObject class is the base class of all Qt objects. * @see http://qt-project.org/doc/qt-5/qobject.html */ /** * @class QThread * The QThread class provides platform-independent threads. * @see http://qt-project.org/doc/qt-5/qthread.html */ namespace drumstick { /** * @addtogroup ALSAClient * @{ * * ALSA clients are any entities using ALSA sequencer services. A client * may be an application or a device driver for an external MIDI port, like * USB MIDI devices or the MIDI/game ports of some sound cards. This library * allows to easily create applications managing ALSA clients. * * ALSA clients are also file descriptors representing a sequencer device, * that must be opened before reading or writing MIDI events. When the client * is opened, it is given some handle and a number identifying it to other * clients in the system. You can also provide a name for it. * * Each ALSA sequencer client can have several ports attached. The ports can be * readable or writable, and can be subscribed in pairs: one readable port to * one writable port. The subscriptions can be made and queried by external * applications, like "aconnect" or "qjackctl". * * SystemInfo is an auxiliary class to query several system capabilities. * * The PoolInfo class represents a container to query and change some values * for the kernel memory pool assigned to an ALSA client. * * The ClientInfo class is another container to query and change properties of * the MidiClient itself. * * The SequencerEventHandler abstract class is used to define an interface * that other class can implement to receive sequencer events. It is one of the * three methods of delivering input events offered by the library. * * @section EventInput Input * MidiClient uses a separate thread to receive events from the ALSA sequencer. * The input thread can be started and stopped using the methods * MidiClient::startSequencerInput() and MidiClient::stopSequencerInput(). * It is necessary to have this thread in mind when using this library to read * events. There are three delivering methods of input events: *
    *
  • A Callback method. To use this method, you must derive a class from * SequencerEventHandler, overriding the method * SequencerEventHandler::handleSequencerEvent() to provide your own event * processing code. You must give a handler instance pointer to * the client using MidiClient::setHandler().
  • *
  • Using QEvent listeners. To use this method, you must have one or more * classes derived from QObject overriding the method QObject::customEvent(). * You must also use the method MidiClient::addListener() to add such objects * to the client's listeners list, and MidiClient::setEventsEnabled().
  • *
  • The third method involves signals and slots. Whenever a sequencer event * is received, a signal MidiClient::eventReceived() is emitted, that can be * connected to your own supplied slot(s) to process it. *
* The selected method depends only on your requirements and your preferences. *
    *
  • The Callback method is preferred for real-time usage because the handler * receives the events without any delay, but at the same time you must * avoid calling methods of any GUI widgets within the handler. Instead, * you can create QEvents and call QObject::postEvent() to notify the GUI.
  • *
  • Inside QObject::eventReceiver() you can collect QEvents and call * any method you want, but the events are not delivered in real-time. Instead, * they are enqueued and dispatched by the main application's event loop.
  • *
  • The signals/slots method can be real-time or queued, depending on the * last parameter of QObject::connect(). If it is Qt::DirectConnection, the signal * is delivered in real-time, and the same rule about avoiding calls to any * GUI widgets methods apply. If it is Qt::QueuedConnection, then the signal is * enqueued using the application's event loop, and it is safe to call any GUI * methods in this case.
  • *
* Whichever method you select, it excludes the other methods for the same * program. A callback takes precedence over the others. If it is not set, then * the events are sent if MidiClient::setEventsEnabled() is called. * If neither a callback handler is set nor events are enabled, then the signal * is emitted. In any case, the event pointer must be deleted by the receiver * method. * * @see http://qt-project.org/doc/qt-5/threads-reentrancy.html * * @section EventOutput Output * * The methods to send a single event to the ALSA sequencer are: *
    *
  • MidiClient::output() using the library buffer, automatically flushed.
  • *
  • MidiClient::outputBuffer() using the library buffer. Not flushed automatically.
  • *
  • MidiClient::outputDirect() not using the library buffer.
  • *
* The two first methods usually require a call to MidiClient::drainOutput() to * flush the ALSA library output buffer. The third one bypasses the buffer, and * doesn't require the call to MidiClient::drainOutput(). Note that the buffer * can be automatically drained by the first method when it becomes full. * * After being dispatched to the ALSA Sequencer, the events can be scheduled at * some time in the future, or immediately. This depends on the following * methods of the SequencerEvent class: *
    *
  • SequencerEvent::setDirect() not scheduled
  • *
  • SequencerEvent::scheduleTick() scheduled in musical time (ticks)
  • *
  • SequencerEvent::scheduleReal() scheduled in clock time (seconds)
  • *
* * When you need to schedule a lot of events, for instance reproducing * a Standard MIDI File (SMF) or a MIDI sequence, you may want to use the * abstract class SequencerOutputThread. * * @section Memory * * There are two memory issues: the memory pool belongs to the kernel sequencer, * and can be managed by the class PoolInfo and the methods * MidiClient::getPoolInfo() and MidiClient::setPoolInfo(). The library buffer * can be controlled using the methods MidiClient::getOutputBufferSize() and * MidiClient::setOutputBufferSize() as well as MidiClient::getInputBufferSize() * and MidiClient::setInputBufferSize(). * * @see http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_client.html * @} */ /** * This class manages event input from the ALSA sequencer. */ class MidiClient::SequencerInputThread: public QThread { public: SequencerInputThread(MidiClient *seq, int timeout) : QThread(), m_MidiClient(seq), m_Wait(timeout), m_Stopped(false), m_RealTime(true) {} virtual ~SequencerInputThread() {} virtual void run(); bool stopped(); void stop(); void setRealtimePriority(); MidiClient *m_MidiClient; int m_Wait; bool m_Stopped; bool m_RealTime; QReadWriteLock m_mutex; }; class MidiClient::MidiClientPrivate { public: MidiClientPrivate() : m_eventsEnabled(false), m_BlockMode(false), m_NeedRefreshClientList(true), m_OpenMode(SND_SEQ_OPEN_DUPLEX), m_DeviceName("default"), m_SeqHandle(0), m_Thread(0), m_Queue(0), m_handler(0) { } bool m_eventsEnabled; bool m_BlockMode; bool m_NeedRefreshClientList; int m_OpenMode; QString m_DeviceName; snd_seq_t* m_SeqHandle; QPointer m_Thread; QPointer m_Queue; SequencerEventHandler* m_handler; ClientInfo m_Info; ClientInfoList m_ClientList; MidiPortList m_Ports; PortInfoList m_OutputsAvail; PortInfoList m_InputsAvail; QObjectList m_listeners; SystemInfo m_sysInfo; PoolInfo m_poolInfo; }; /** * Constructor. * * This constructor optionally gets a QObject parent. When you create a * MidiClient with another object as parent, the MidiClient object will * automatically add itself to the parent's children() list. The parent takes * ownership of the object i.e. it will automatically delete its children in * its destructor. * * It is necessary to invoke open() later to get the sequencer client handler * from the ALSA sequencer subsystem. * * @param parent The optional parent object * @return a MidiClient instance */ MidiClient::MidiClient( QObject* parent ) : QObject(parent), d(new MidiClientPrivate) { } /** * Destructor. * * The ports and queue associated to this client are automatically released. */ MidiClient::~MidiClient() { stopSequencerInput(); detachAllPorts(); if (d->m_Queue != 0) delete d->m_Queue; close(); freeClients(); if (d->m_Thread != 0) delete d->m_Thread; delete d; } /** * Returns the sequencer handler managed by ALSA */ snd_seq_t* MidiClient::getHandle() { return d->m_SeqHandle; } /** * Returns true if the sequencer is opened */ bool MidiClient::isOpened() { return (d->m_SeqHandle != NULL); } /** * Returns the name of the sequencer device */ QString MidiClient::getDeviceName() { return d->m_DeviceName; } /** * Returns the last open mode used in open() */ int MidiClient::getOpenMode() { return d->m_OpenMode; } /** * Returns the last block mode used in open() */ bool MidiClient::getBlockMode() { return d->m_BlockMode; } /** * Returns true if the events mode of delivery has been enabled */ bool MidiClient::getEventsEnabled() const { return d->m_eventsEnabled; } /** * Sets a sequencer event handler enabling the callback delivery mode */ void MidiClient::setHandler(SequencerEventHandler* handler) { d->m_handler = handler; } /** * Enables real-time priority for the MIDI input thread. The system needs either * RLIMIT_RTPRIO or RealtimeKit. First RLIMIT_RTPRIO is tried, and if this * method fails, RealtimeKit is used. * * @param enable real-time priority enabled * @since 0.5.0 */ void MidiClient::setRealTimeInput(bool enable) { if (d->m_Thread == 0) { d->m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT); d->m_Thread->m_RealTime = enable; } } /** * Return the real-time priority setting for the MIDI input thread. * @return true if the real-time priority is enabled * @since 0.5.0 */ bool MidiClient::realTimeInputEnabled() { if (d->m_Thread == 0) return true; return d->m_Thread->m_RealTime; } /** * Open the sequencer device. * * When opening the MidiClient instance, several properties may optionally * be set as the device name, the open mode and block mode. Default values * are provided for them. After a successful open, an event with * SND_SEQ_EVENT_CLIENT_START is broadcast to the announce port. * * @param deviceName the sequencer device name, default value = "default". * This is not a name you make up for your own purposes; it has special * significance to the ALSA library. Usually you need to pass "default" here. * @param openMode the open mode, default value = SND_SEQ_OPEN_DUPLEX. * The read/write mode of the sequencer. Can be one of these three values: *
    *
  • SND_SEQ_OPEN_OUTPUT - open the sequencer for output only
  • *
  • SND_SEQ_OPEN_INPUT - open the sequencer for input only
  • *
  • SND_SEQ_OPEN_DUPLEX - open the sequencer for output and input
  • *
* @param blockMode open in blocking mode, default value = false. */ void MidiClient::open( const QString deviceName, const int openMode, const bool blockMode) { CHECK_ERROR( snd_seq_open( &d->m_SeqHandle, deviceName.toLocal8Bit().data(), openMode, blockMode ? 0 : SND_SEQ_NONBLOCK ) ); CHECK_WARNING( snd_seq_get_client_info( d->m_SeqHandle, d->m_Info.m_Info ) ); d->m_DeviceName = deviceName; d->m_OpenMode = openMode; d->m_BlockMode = blockMode; } /** * Open the sequencer device, providing a configuration object pointer. * * This method is like open() except that a configuration is explicitly * provided. After a successful open, an event with SND_SEQ_EVENT_CLIENT_START * type is broadcasted from the announce port. * * @param conf a configuration object pointer. * @param deviceName the sequencer device name, default value = "default". * This is not a name you make up for your own purposes; it has special * significance to the ALSA library. Usually you need to pass "default" here. * @param openMode the open mode, default value = SND_SEQ_OPEN_DUPLEX. * The read/write mode of the sequencer. Can be one of these three values: *
    *
  • SND_SEQ_OPEN_OUTPUT - open the sequencer for output only
  • *
  • SND_SEQ_OPEN_INPUT - open the sequencer for input only
  • *
  • SND_SEQ_OPEN_DUPLEX - open the sequencer for output and input
  • *
* @param blockMode open in blocking mode, default value = false. */ void MidiClient::open( snd_config_t* conf, const QString deviceName, const int openMode, const bool blockMode ) { CHECK_ERROR( snd_seq_open_lconf( &d->m_SeqHandle, deviceName.toLocal8Bit().data(), openMode, blockMode ? 0 : SND_SEQ_NONBLOCK, conf )); CHECK_WARNING( snd_seq_get_client_info(d->m_SeqHandle, d->m_Info.m_Info)); d->m_DeviceName = deviceName; d->m_OpenMode = openMode; d->m_BlockMode = blockMode; } /** * Close the sequencer device. * * After a client is closed, an event with SND_SEQ_EVENT_CLIENT_EXIT is * broadcast to the announce port. The connection between other clients are * disconnected. Call this just before exiting your program. */ void MidiClient::close() { if (d->m_SeqHandle != NULL) { stopSequencerInput(); CHECK_WARNING(snd_seq_close(d->m_SeqHandle)); d->m_SeqHandle = NULL; } } /** * Gets the size of the library output buffer for the ALSA client. * * This buffer is used to store the decoded byte-stream of output events before * transferring to the sequencer. * * @return the size of the library output buffer */ size_t MidiClient::getOutputBufferSize() { return snd_seq_get_output_buffer_size(d->m_SeqHandle); } /** * Sets the size of the library output buffer for the ALSA client. * * This buffer is used to store the decoded byte-stream of output events before * transferring to the sequencer. * * @param newSize the size of the library output buffer */ void MidiClient::setOutputBufferSize(size_t newSize) { if (getOutputBufferSize() != newSize) { CHECK_WARNING(snd_seq_set_output_buffer_size(d->m_SeqHandle, newSize)); } } /** * Gets the size of the library input buffer for the ALSA client. * * This buffer is used to read a byte-stream of input events before * transferring from the sequencer. * * @return the size of the library input buffer */ size_t MidiClient::getInputBufferSize() { return snd_seq_get_input_buffer_size(d->m_SeqHandle); } /** * Sets the size of the library input buffer for the ALSA client. * * This buffer is used to read a byte-stream of input events before * transferring from the sequencer. * * @param newSize the size of the library input buffer */ void MidiClient::setInputBufferSize(size_t newSize) { if (getInputBufferSize() != newSize) { CHECK_WARNING(snd_seq_set_input_buffer_size(d->m_SeqHandle, newSize)); } } /** * Change the blocking mode of the client. * * In block mode, the client falls into sleep when it fills the output memory * pool with full events. The client will be woken up after a certain amount * of free space becomes available. * * @param newValue the blocking mode */ void MidiClient::setBlockMode(bool newValue) { if (d->m_BlockMode != newValue) { d->m_BlockMode = newValue; if (d->m_SeqHandle != NULL) { CHECK_WARNING(snd_seq_nonblock(d->m_SeqHandle, d->m_BlockMode ? 0 : 1)); } } } /** * Gets the client ID. * * Returns the ID of the client. A client ID is necessary to inquiry or to set * the client information. A user client ID is assigned from 128 to 191. * * @return the client ID. */ int MidiClient::getClientId() { return CHECK_WARNING(snd_seq_client_id(d->m_SeqHandle)); } /** * Returns the type snd_seq_type_t of the given sequencer handle. * @return the type snd_seq_type_t of the given sequencer handle. */ snd_seq_type_t MidiClient::getSequencerType() { return snd_seq_type(d->m_SeqHandle); } /** * Dispatch the events received from the Sequencer. * * There are three methods of events delivering: *
    *
  • A Callback method. To use this method, you must derive a class from * SequencerEventHandler, overriding the method * SequencerEventHandler::handleSequencerEvent() to * provide your own event processing. You must provide the handler instance to * the client using setHandler().
  • *
  • Using QEvent listeners. To use this method, you must use one or more * classes derived from QObject overriding the method QObject::customEvent(). * You must also use the method addListener() to add such objects to the * client's listeners list.
  • *
  • The third method involves signals and slots. Whenever a sequencer event * is received, a signal eventReceived() is emitted, that can be connected to * your own supplied slot(s) to process it. *
* @see ALSAClient */ void MidiClient::doEvents() { do { int err = 0; snd_seq_event_t* evp = NULL; SequencerEvent* event = NULL; err = snd_seq_event_input(d->m_SeqHandle, &evp); if ((err >= 0) && (evp != NULL)) { switch (evp->type) { case SND_SEQ_EVENT_NOTE: event = new NoteEvent(evp); break; case SND_SEQ_EVENT_NOTEON: event = new NoteOnEvent(evp); break; case SND_SEQ_EVENT_NOTEOFF: event = new NoteOffEvent(evp); break; case SND_SEQ_EVENT_KEYPRESS: event = new KeyPressEvent(evp); break; case SND_SEQ_EVENT_CONTROLLER: case SND_SEQ_EVENT_CONTROL14: case SND_SEQ_EVENT_REGPARAM: case SND_SEQ_EVENT_NONREGPARAM: event = new ControllerEvent(evp); break; case SND_SEQ_EVENT_PGMCHANGE: event = new ProgramChangeEvent(evp); break; case SND_SEQ_EVENT_CHANPRESS: event = new ChanPressEvent(evp); break; case SND_SEQ_EVENT_PITCHBEND: event = new PitchBendEvent(evp); break; case SND_SEQ_EVENT_SYSEX: event = new SysExEvent(evp); break; case SND_SEQ_EVENT_PORT_SUBSCRIBED: case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: event = new SubscriptionEvent(evp); break; case SND_SEQ_EVENT_PORT_CHANGE: case SND_SEQ_EVENT_PORT_EXIT: case SND_SEQ_EVENT_PORT_START: event = new PortEvent(evp); d->m_NeedRefreshClientList = true; break; case SND_SEQ_EVENT_CLIENT_CHANGE: case SND_SEQ_EVENT_CLIENT_EXIT: case SND_SEQ_EVENT_CLIENT_START: event = new ClientEvent(evp); d->m_NeedRefreshClientList = true; break; case SND_SEQ_EVENT_SONGPOS: case SND_SEQ_EVENT_SONGSEL: case SND_SEQ_EVENT_QFRAME: case SND_SEQ_EVENT_TIMESIGN: case SND_SEQ_EVENT_KEYSIGN: event = new ValueEvent(evp); break; case SND_SEQ_EVENT_SETPOS_TICK: case SND_SEQ_EVENT_SETPOS_TIME: case SND_SEQ_EVENT_QUEUE_SKEW: event = new QueueControlEvent(evp); break; case SND_SEQ_EVENT_TEMPO: event = new TempoEvent(evp); break; default: event = new SequencerEvent(evp); break; } // first, process the callback (if any) if (d->m_handler != NULL) { d->m_handler->handleSequencerEvent(event->clone()); } else { // second, process the event listeners if (d->m_eventsEnabled) { QObjectList::Iterator it; for(it=d->m_listeners.begin(); it!=d->m_listeners.end(); ++it) { QObject* sub = (*it); QCoreApplication::postEvent(sub, event->clone()); } } else { // finally, process signals emit eventReceived(event->clone()); } } delete event; } } while (snd_seq_event_input_pending(d->m_SeqHandle, 0) > 0); } /** * Starts reading events from the ALSA sequencer. */ void MidiClient::startSequencerInput() { if (d->m_Thread == 0) { d->m_Thread = new SequencerInputThread(this, DEFAULT_INPUT_TIMEOUT); } d->m_Thread->start( d->m_Thread->m_RealTime ? QThread::TimeCriticalPriority : QThread::InheritPriority ); } /** * Stops reading events from the ALSA sequencer. */ void MidiClient::stopSequencerInput() { int counter = 0; if (d->m_Thread != 0) { if (d->m_Thread->isRunning()) { d->m_Thread->stop(); while (!d->m_Thread->wait(500) && (counter < 10)) { counter++; } if (!d->m_Thread->isFinished()) { d->m_Thread->terminate(); } } delete d->m_Thread; } } /** * Reads the ALSA sequencer's clients list. */ void MidiClient::readClients() { ClientInfo cInfo; freeClients(); cInfo.setClient(-1); while (snd_seq_query_next_client(d->m_SeqHandle, cInfo.m_Info) >= 0) { cInfo.readPorts(this); d->m_ClientList.append(cInfo); } d->m_NeedRefreshClientList = false; } /** * Releases the list of ALSA sequencer's clients. */ void MidiClient::freeClients() { d->m_ClientList.clear(); } /** * Gets the list of clients from the ALSA sequencer. * @return the list of clients. */ ClientInfoList MidiClient::getAvailableClients() { if (d->m_NeedRefreshClientList) readClients(); ClientInfoList lst = d->m_ClientList; // copy return lst; } /** * Gets the ClientInfo object holding data about this client. * @return the ClientInfo object representing this client. */ ClientInfo& MidiClient::getThisClientInfo() { snd_seq_get_client_info(d->m_SeqHandle, d->m_Info.m_Info); return d->m_Info; } /** * Sets the data supplied by the ClientInfo object into the ALSA sequencer * client. This allows to change the name, capabilities, type and other data * in a single step. * * @param val a ClientInfo object reference */ void MidiClient::setThisClientInfo(const ClientInfo& val) { d->m_Info = val; snd_seq_set_client_info(d->m_SeqHandle, d->m_Info.m_Info); } /** * This internal method applies the ClientInfo data to the ALSA sequencer client */ void MidiClient::applyClientInfo() { if (d->m_SeqHandle != NULL) { snd_seq_set_client_info(d->m_SeqHandle, d->m_Info.m_Info); } } /** * Gets the client's public name * @return The client's name */ QString MidiClient::getClientName() { return d->m_Info.getName(); } /** * Gets the public name corresponding to the given Client ID. * @param clientId The ID of any existing sequencer client * @return The client's name */ QString MidiClient::getClientName(const int clientId) { ClientInfoList::Iterator it; if (d->m_NeedRefreshClientList) readClients(); for (it = d->m_ClientList.begin(); it != d->m_ClientList.end(); ++it) { if ((*it).getClientId() == clientId) { return (*it).getName(); } } return QString(); } /** * Changes the public name of the ALSA sequencer client. * @param newName A new public name */ void MidiClient::setClientName(QString const& newName) { if (newName != d->m_Info.getName()) { d->m_Info.setName(newName); applyClientInfo(); } } /** * Gets the list of MidiPort instances belonging to this client. * @return The list of MidiPort instances. */ MidiPortList MidiClient::getMidiPorts() const { return d->m_Ports; } /** * Create and attach a new MidiPort instance to this client. * @return The pointer to the new MidiPort instance. */ MidiPort* MidiClient::createPort() { MidiPort* port = new MidiPort(this); port->attach(this); return port; } /** * Attach a MidiPort instance to this client * @param port The MidiPort to be attached */ void MidiClient::portAttach(MidiPort* port) { if (d->m_SeqHandle != NULL) { CHECK_ERROR(snd_seq_create_port(d->m_SeqHandle, port->m_Info.m_Info)); d->m_Ports.push_back(port); } } /** * Detach a MidiPort instance from this client * @param port The MidiPort to be detached */ void MidiClient::portDetach(MidiPort* port) { if (d->m_SeqHandle != NULL) { if(port->getPortInfo()->getClient() == getClientId()) { return; } CHECK_ERROR(snd_seq_delete_port(d->m_SeqHandle, port->getPortInfo()->getPort())); port->setMidiClient(NULL); MidiPortList::iterator it; for(it = d->m_Ports.begin(); it != d->m_Ports.end(); ++it) { if ((*it)->getPortInfo()->getPort() == port->getPortInfo()->getPort()) { d->m_Ports.erase(it); break; } } } } /** * Detach all the ports belonging to this client. */ void MidiClient::detachAllPorts() { if (d->m_SeqHandle != NULL) { MidiPortList::iterator it; for (it = d->m_Ports.begin(); it != d->m_Ports.end(); ++it) { CHECK_ERROR(snd_seq_delete_port(d->m_SeqHandle, (*it)->getPortInfo()->getPort())); (*it)->setMidiClient(NULL); d->m_Ports.erase(it); } } } /** * Add an event filter to the client. * @param evtype An event filter to be added. */ void MidiClient::addEventFilter(int evtype) { snd_seq_set_client_event_filter(d->m_SeqHandle, evtype); } /** * Gets the broadcast filter usage of the client. * * @return The broadcast filter. */ bool MidiClient::getBroadcastFilter() { return d->m_Info.getBroadcastFilter(); } /** * Sets the broadcast filter usage of the client. * * @param newValue The broadcast filter. */ void MidiClient::setBroadcastFilter(bool newValue) { d->m_Info.setBroadcastFilter(newValue); applyClientInfo(); } /** * Get the error-bounce usage of the client. * * @return The error-bounce usage. */ bool MidiClient::getErrorBounce() { return d->m_Info.getErrorBounce(); } /** * Sets the error-bounce usage of the client. * * @param newValue The error-bounce usage. */ void MidiClient::setErrorBounce(bool newValue) { d->m_Info.setErrorBounce(newValue); applyClientInfo(); } /** * Output an event using the library output buffer. * * An event is once expanded on the output buffer. The output buffer will be * drained automatically if it becomes full. * * @param ev The event to be sent. * @param async Use asynchronous mode. If false, this call will block until the * event can be delivered. * @param timeout The maximum time to wait in synchronous mode. */ void MidiClient::output(SequencerEvent* ev, bool async, int timeout) { int npfds; pollfd* pfds; if (async) { CHECK_WARNING(snd_seq_event_output(d->m_SeqHandle, ev->getHandle())); } else { npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT); pfds = (pollfd*) alloca(npfds * sizeof(pollfd)); snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT); while (snd_seq_event_output(d->m_SeqHandle, ev->getHandle()) < 0) { poll(pfds, npfds, timeout); } } } /** * Output an event directly to the sequencer * * This function sends an event to the sequencer directly not using the library * output buffer. * * @param ev The event to be sent. * @param async Use asynchronous mode. If false, this call will block until the * event is delivered to the sequencer. * @param timeout The maximum time to wait in synchronous mode. */ void MidiClient::outputDirect(SequencerEvent* ev, bool async, int timeout) { int npfds; pollfd* pfds; if (async) { CHECK_WARNING(snd_seq_event_output_direct(d->m_SeqHandle, ev->getHandle())); } else { npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT); pfds = (pollfd*) alloca(npfds * sizeof(pollfd)); snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT); while (snd_seq_event_output_direct(d->m_SeqHandle, ev->getHandle()) < 0) { poll(pfds, npfds, timeout); } } } /** * Output an event using the library output buffer, without draining the buffer. * * An event is once expanded on the output buffer. The output buffer will NOT be * drained automatically if it becomes full. * * @param ev The event to be sent. */ void MidiClient::outputBuffer(SequencerEvent* ev) { CHECK_WARNING(snd_seq_event_output_buffer(d->m_SeqHandle, ev->getHandle())); } /** * Drain the library output buffer. * * This function drains all pending events on the output buffer. The function * returns immediately after the events are sent to the queues regardless * whether the events are processed or not. * * @param async Use asynchronous mode. If false, this call will block until the * buffer can be flushed. * @param timeout The maximum time to wait in synchronous mode. */ void MidiClient::drainOutput(bool async, int timeout) { int npfds; pollfd* pfds; if (async) { CHECK_WARNING(snd_seq_drain_output(d->m_SeqHandle)); } else { npfds = snd_seq_poll_descriptors_count(d->m_SeqHandle, POLLOUT); pfds = (pollfd*) alloca(npfds * sizeof(pollfd)); snd_seq_poll_descriptors(d->m_SeqHandle, pfds, npfds, POLLOUT); while (snd_seq_drain_output(d->m_SeqHandle) < 0) { poll(pfds, npfds, timeout); } } } /** * Wait until all sent events are processed. * * This function waits until all events of this client are processed. */ void MidiClient::synchronizeOutput() { snd_seq_sync_output_queue(d->m_SeqHandle); } /** * Get the MidiQueue instance associated to this client. * If the client is not associated to a MidiQueue, one is created. * @return A MidiQueue instance pointer */ MidiQueue* MidiClient::getQueue() { if (d->m_Queue == NULL) { createQueue(); } return d->m_Queue; } /** * Create and return a new MidiQueue associated to this client. * @return A new MidiQueue instance. */ MidiQueue* MidiClient::createQueue() { if (d->m_Queue != NULL) { delete d->m_Queue; } d->m_Queue = new MidiQueue(this, this); return d->m_Queue; } /** * Create and return a new MidiQueue with the given name, associated to this * client. * @param queueName The name for the new queue. * @return A new MidiQueue instance. */ MidiQueue* MidiClient::createQueue(QString const& queueName ) { if (d->m_Queue != NULL) { delete d->m_Queue; } d->m_Queue = new MidiQueue(this, queueName, this); return d->m_Queue; } /** * Create a new MidiQueue instance using a queue already existing in the * system, associating it to the client. * * @param queue_id An existing queue identifier. * @return A new MidiQueue instance. */ MidiQueue* MidiClient::useQueue(int queue_id) { if (d->m_Queue != NULL) { delete d->m_Queue; } d->m_Queue = new MidiQueue(this, queue_id, this); return d->m_Queue; } /** * Create a new MidiQueue instance using a queue already existing in the * system, associating it to the client. * * @param name An existing queue name. * @return A new MidiQueue instance. */ MidiQueue* MidiClient::useQueue(const QString& name) { if (d->m_Queue != NULL) { delete d->m_Queue; } int queue_id = getQueueId(name); if ( queue_id >= 0) { d->m_Queue = new MidiQueue(this, queue_id, this); } return d->m_Queue; } /** * Associate an existing MidiQueue instance to the client. * * @param queue An existing MidiQueue. * @return The provided MidiQueue instance. */ MidiQueue* MidiClient::useQueue(MidiQueue* queue) { if (d->m_Queue != NULL) { delete d->m_Queue; } queue->setParent(this); d->m_Queue = queue; return d->m_Queue; } /** * Get a list of the existing queues * @return a list of existing queues */ QList MidiClient::getAvailableQueues() { int q, err, max; QList queues; snd_seq_queue_info_t* qinfo; snd_seq_queue_info_alloca(&qinfo); max = getSystemInfo().getMaxQueues(); for ( q = 0; q < max; ++q ) { err = snd_seq_get_queue_info(d->m_SeqHandle, q, qinfo); if (err == 0) { queues.append(q); } } return queues; } /** * Gets a list of the available user ports in the system, filtered by the given * bitmap of desired capabilities. * * @param filter A bitmap of capabilities. * @return A filtered list of the available ports in the system. */ PortInfoList MidiClient::filterPorts(unsigned int filter) { PortInfoList result; ClientInfoList::ConstIterator itc; PortInfoList::ConstIterator itp; if (d->m_NeedRefreshClientList) readClients(); for (itc = d->m_ClientList.constBegin(); itc != d->m_ClientList.constEnd(); ++itc) { ClientInfo ci = (*itc); if ((ci.getClientId() == SND_SEQ_CLIENT_SYSTEM) || (ci.getClientId() == d->m_Info.getClientId())) continue; PortInfoList lstPorts = ci.getPorts(); for(itp = lstPorts.constBegin(); itp != lstPorts.constEnd(); ++itp) { PortInfo pi = (*itp); unsigned int cap = pi.getCapability(); if ( ((filter & cap) != 0) && ((SND_SEQ_PORT_CAP_NO_EXPORT & cap) == 0) ) { result.append(pi); } } } return result; } /** * Update the internal lists of user ports. */ void MidiClient::updateAvailablePorts() { d->m_InputsAvail.clear(); d->m_OutputsAvail.clear(); d->m_InputsAvail = filterPorts( SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ ); d->m_OutputsAvail = filterPorts( SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE ); } /** * Gets the available user input ports in the system. * @return The list of available input ports. */ PortInfoList MidiClient::getAvailableInputs() { d->m_NeedRefreshClientList = true; updateAvailablePorts(); return d->m_InputsAvail; } /** * Gets the available user output ports in the system. * @return The list of available output ports. */ PortInfoList MidiClient::getAvailableOutputs() { d->m_NeedRefreshClientList = true; updateAvailablePorts(); return d->m_OutputsAvail; } /** * Adds a QObject to the listeners list. This object should override the method * QObject::customEvent() to receive SequencerEvent instances. * @param listener A QObject listener to be notified of received events. * @see removeListener(), setEventsEnabled() */ void MidiClient::addListener(QObject* listener) { d->m_listeners.append(listener); } /** * Removes a QObject listener from the listeners list. * @param listener listener A QObject listener to be removed of received events. * @see addListener(), setEventsEnabled() */ void MidiClient::removeListener(QObject* listener) { d->m_listeners.removeAll(listener); } /** * Enables the notification of received SequencerEvent instances to the listeners * registered with addListener() * @param bEnabled The new state of the events delivering mode. * @see addListener(), removeListener(), setEventsEnabled() */ void MidiClient::setEventsEnabled(bool bEnabled) { if (bEnabled != d->m_eventsEnabled) { d->m_eventsEnabled = bEnabled; } } /** * Gets a SystemInfo instance with the updated state of the system. * @return The updated system info. */ SystemInfo& MidiClient::getSystemInfo() { snd_seq_system_info(d->m_SeqHandle, d->m_sysInfo.m_Info); return d->m_sysInfo; } /** * Gets a PoolInfo instance with an updated state of the client memory pool * @return The updated memory pool state. */ PoolInfo& MidiClient::getPoolInfo() { snd_seq_get_client_pool(d->m_SeqHandle, d->m_poolInfo.m_Info); return d->m_poolInfo; } /** * Applies (updates) the client's PoolInfo data into the system. * @param info The PoolInfo reference to be applied to the client. */ void MidiClient::setPoolInfo(const PoolInfo& info) { d->m_poolInfo = info; CHECK_WARNING(snd_seq_set_client_pool(d->m_SeqHandle, d->m_poolInfo.m_Info)); } /** * Resets the client input pool. * @see dropInput() */ void MidiClient::resetPoolInput() { CHECK_WARNING(snd_seq_reset_pool_input(d->m_SeqHandle)); } /** * Resets the client output pool. * @see dropOutput() */ void MidiClient::resetPoolOutput() { CHECK_WARNING(snd_seq_reset_pool_output(d->m_SeqHandle)); } /** * Sets the size of the client's input pool. * @param size The new size */ void MidiClient::setPoolInput(int size) { CHECK_WARNING(snd_seq_set_client_pool_input(d->m_SeqHandle, size)); } /** * Sets the size of the client's output pool. * @param size The new size */ void MidiClient::setPoolOutput(int size) { CHECK_WARNING(snd_seq_set_client_pool_output(d->m_SeqHandle, size)); } /** * Sets the room size of the client's output pool. * @param size The new size */ void MidiClient::setPoolOutputRoom(int size) { CHECK_WARNING(snd_seq_set_client_pool_output_room(d->m_SeqHandle, size)); } /** * Clears the client's input buffer and and remove events in sequencer queue. * @see resetPoolInput() */ void MidiClient::dropInput() { CHECK_WARNING(snd_seq_drop_input(d->m_SeqHandle)); } /** * Remove all events on user-space input buffer. * @see dropInput() */ void MidiClient::dropInputBuffer() { CHECK_WARNING(snd_seq_drop_input_buffer(d->m_SeqHandle)); } /** * Clears the client's output buffer and and remove events in sequencer queue. * * This method removes all events on both user-space output buffer and output * memory pool on kernel. * @see resetPoolOutput() */ void MidiClient::dropOutput() { CHECK_WARNING(snd_seq_drop_output(d->m_SeqHandle)); } /** * Removes all events on the library output buffer. * * Removes all events on the user-space output buffer. Unlike dropOutput(), this * method doesn't remove events on the client's output memory pool. * @see dropOutput() */ void MidiClient::dropOutputBuffer() { CHECK_WARNING(snd_seq_drop_output_buffer(d->m_SeqHandle)); } /** * Removes events on input/output buffers and pools. * Removes matching events with the given condition from input/output buffers * and pools. The removal condition is specified in the spec argument. * @param spec A RemoveEvents instance specifying the removal condition. */ void MidiClient::removeEvents(const RemoveEvents* spec) { CHECK_WARNING(snd_seq_remove_events(d->m_SeqHandle, spec->m_Info)); } /** * Extracts (and removes) the first event in the output buffer. * @return The extracted event. */ SequencerEvent* MidiClient::extractOutput() { snd_seq_event_t* ev; if (CHECK_WARNING(snd_seq_extract_output(d->m_SeqHandle, &ev) == 0)) { return new SequencerEvent(ev); } return NULL; } /** * Returns the size of pending events on the output buffer. * * @return The size of pending events. */ int MidiClient::outputPending() { return snd_seq_event_output_pending(d->m_SeqHandle); } /** * Gets the size of the events on the input buffer. * * If there are events remaining on the user-space input buffer, this method * returns the total size of events on it. If the argument is true, this method * checks the presence of events on the sequencer FIFO, and when events exist * they are transferred to the input buffer, and the number of received events * are returned. If the argument is false and no events remain on the input * buffer, this method simply returns zero. * * @param fetch Check and fetch the sequencer input pool. * @return The size in bytes of the remaining input events on the buffer. */ int MidiClient::inputPending(bool fetch) { return snd_seq_event_input_pending(d->m_SeqHandle, fetch ? 1 : 0); } /** * Gets the queue's numeric identifier corresponding to the provided name. * * @param name The name string to query. * @return The number of the matching queue. */ int MidiClient::getQueueId(const QString& name) { return snd_seq_query_named_queue(d->m_SeqHandle, name.toLocal8Bit().data()); } /** * Returns the number of poll descriptors. * @param events Poll events to be checked (POLLIN and POLLOUT). * @return The number of poll descriptors. */ int MidiClient::getPollDescriptorsCount(short events) { return snd_seq_poll_descriptors_count(d->m_SeqHandle, events); } /** * Get poll descriptors. * * Get poll descriptors assigned to the sequencer handle. Since a sequencer * handle can duplex streams, you need to set which direction(s) is/are polled * in events argument. When POLLIN bit is specified, the incoming events to the * ports are checked. * * @param pfds Array of poll descriptors * @param space Space in the poll descriptor array * @param events Polling events to be checked (POLLIN and POLLOUT) * @return Count of filled descriptors */ int MidiClient::pollDescriptors( struct pollfd *pfds, unsigned int space, short events ) { return snd_seq_poll_descriptors(d->m_SeqHandle, pfds, space, events); } /** * Gets the number of returned events from poll descriptors * @param pfds Array of poll descriptors. * @param nfds Count of poll descriptors. * @return Number of returned events. */ unsigned short MidiClient::pollDescriptorsRevents(struct pollfd *pfds, unsigned int nfds) { unsigned short revents; CHECK_WARNING( snd_seq_poll_descriptors_revents( d->m_SeqHandle, pfds, nfds, &revents )); return revents; } /** * Gets the internal sequencer device name * @return The device name. */ const char * MidiClient::_getDeviceName() { return snd_seq_name(d->m_SeqHandle); } /** * Sets the client name * @param name The new client name. */ void MidiClient::_setClientName(const char *name) { CHECK_WARNING(snd_seq_set_client_name(d->m_SeqHandle, name)); } /** * Create an ALSA sequencer port, without using MidiPort. * @param name The name of the new port. * @param caps The new port capabilities. * @param type The type of the new port. * @return The port numeric identifier. */ int MidiClient::createSimplePort( const char *name, unsigned int caps, unsigned int type ) { return CHECK_WARNING( snd_seq_create_simple_port( d->m_SeqHandle, name, caps, type )); } /** * Remove an ALSA sequencer port. * @param port The numeric identifier of the port. */ void MidiClient::deleteSimplePort(int port) { CHECK_WARNING( snd_seq_delete_simple_port( d->m_SeqHandle, port )); } /** * Subscribe one port from another arbitrary sequencer client:port. * @param myport The number of the internal port. * @param client The external client's identifier. * @param port The external port's identifier. */ void MidiClient::connectFrom(int myport, int client, int port) { CHECK_WARNING( snd_seq_connect_from(d->m_SeqHandle, myport, client, port )); } /** * Subscribe one port to another arbitrary sequencer client:port. * @param myport The number of the internal port. * @param client The external client's identifier. * @param port The external port's identifier. */ void MidiClient::connectTo(int myport, int client, int port) { CHECK_WARNING( snd_seq_connect_to(d->m_SeqHandle, myport, client, port )); } /** * Unsubscribe one port from another arbitrary sequencer client:port. * @param myport The number of the internal port. * @param client The external client's identifier. * @param port The external port's identifier. */ void MidiClient::disconnectFrom(int myport, int client, int port) { CHECK_WARNING( snd_seq_disconnect_from(d->m_SeqHandle, myport, client, port )); } /** * Unsubscribe one port to another arbitrary sequencer client:port. * @param myport The number of the internal port. * @param client The external client's identifier. * @param port The external port's identifier. */ void MidiClient::disconnectTo(int myport, int client, int port) { CHECK_WARNING( snd_seq_disconnect_to(d->m_SeqHandle, myport, client, port )); } /** * Parse a text address representation, returning an ALSA address record. * * This function can be used as a replacement of the standard ALSA function * snd_seq_parse_address(). * * @param straddr source text address representation * @param addr returned ALSA address record * @return true if the text address was successfully parsed * @since 0.3.1 */ bool MidiClient::parseAddress( const QString& straddr, snd_seq_addr& addr ) { bool ok(false); QString testClient, testPort; ClientInfoList::ConstIterator cit; int pos = straddr.indexOf(':'); if (pos > -1) { testClient = straddr.left(pos); testPort = straddr.mid(pos+1); } else { testClient = straddr; testPort = '0'; } addr.client = testClient.toInt(&ok); if (ok) addr.port = testPort.toInt(&ok); if (!ok) { if (d->m_NeedRefreshClientList) readClients(); for ( cit = d->m_ClientList.constBegin(); cit != d->m_ClientList.constEnd(); ++cit ) { ClientInfo ci = *cit; if (testClient.compare(ci.getName(), Qt::CaseInsensitive) == 0) { addr.client = ci.getClientId(); addr.port = testPort.toInt(&ok); return ok; } } } return ok; } /** * Returns true or false depending on the input thread state. * @return true if the input thread is stopped. */ bool MidiClient::SequencerInputThread::stopped() { QReadLocker locker(&m_mutex); return m_Stopped; } /** * Stops the input thread. */ void MidiClient::SequencerInputThread::stop() { QWriteLocker locker(&m_mutex); m_Stopped = true; } #if defined(RTKIT_SUPPORT) static pid_t _gettid(void) { return (pid_t) ::syscall(SYS_gettid); } #endif void MidiClient::SequencerInputThread::setRealtimePriority() { struct sched_param p; int rt, policy = SCHED_RR | SCHED_RESET_ON_FORK; quint32 priority = 6; #if defined(RTKIT_SUPPORT) bool ok; quint32 max_prio; quint64 thread; struct rlimit old_limit, new_limit; long long max_rttime; #endif ::memset(&p, 0, sizeof(p)); p.sched_priority = priority; rt = ::pthread_setschedparam(::pthread_self(), policy, &p); if (rt != 0) { #if defined(RTKIT_SUPPORT) const QString rtkit_service = QLatin1String("org.freedesktop.RealtimeKit1"); const QString rtkit_path = QLatin1String("/org/freedesktop/RealtimeKit1"); const QString rtkit_iface = rtkit_service; thread = _gettid(); QDBusConnection bus = QDBusConnection::systemBus(); QDBusInterface realtimeKit(rtkit_service, rtkit_path, rtkit_iface, bus); QVariant maxRTPrio = realtimeKit.property("MaxRealtimePriority"); max_prio = maxRTPrio.toUInt(&ok); if (!ok) { qWarning() << "invalid property RealtimeKit.MaxRealtimePriority"; return; } if (priority > max_prio) priority = max_prio; QVariant maxRTNSec = realtimeKit.property("RTTimeNSecMax"); max_rttime = maxRTNSec.toLongLong(&ok); if (!ok || max_rttime < 0) { qWarning() << "invalid property RealtimeKit.RTTimeNSecMax"; return; } new_limit.rlim_cur = new_limit.rlim_max = max_rttime; rt = ::getrlimit(RLIMIT_RTTIME, &old_limit); if (rt < 0) { qWarning() << "getrlimit() failed. err=" << rt << ::strerror(rt); return; } rt = ::setrlimit(RLIMIT_RTTIME, &new_limit); if ( rt < 0) { qWarning() << "setrlimit() failed, err=" << rt << ::strerror(rt); return; } QDBusMessage reply = realtimeKit.call("MakeThreadRealtime", thread, priority); if (reply.type() == QDBusMessage::ErrorMessage ) qWarning() << "error returned by RealtimeKit.MakeThreadRealtime:" << reply.errorMessage(); #endif } else { qWarning() << "pthread_setschedparam() failed, err=" << rt << ::strerror(rt); } } /** * Main input thread process loop. */ void MidiClient::SequencerInputThread::run() { unsigned long npfd; pollfd* pfd; if ( priority() == TimeCriticalPriority ) setRealtimePriority(); if (m_MidiClient != NULL) { npfd = snd_seq_poll_descriptors_count(m_MidiClient->getHandle(), POLLIN); pfd = (pollfd *) alloca(npfd * sizeof(pollfd)); try { snd_seq_poll_descriptors(m_MidiClient->getHandle(), pfd, npfd, POLLIN); while (!stopped() && (m_MidiClient != NULL)) { int rt = poll(pfd, npfd, m_Wait); if (rt > 0) { m_MidiClient->doEvents(); } } } catch (...) { qWarning() << "exception in input thread"; } } } /** * Default constructor */ ClientInfo::ClientInfo() { snd_seq_client_info_malloc(&m_Info); } /** * Copy constructor * @param other Another ClientInfo reference to be copied */ ClientInfo::ClientInfo(const ClientInfo& other) { snd_seq_client_info_malloc(&m_Info); snd_seq_client_info_copy(m_Info, other.m_Info); m_Ports = other.m_Ports; } /** * Copy constructor * @param other An existing ALSA client info object */ ClientInfo::ClientInfo(snd_seq_client_info_t* other) { snd_seq_client_info_malloc(&m_Info); snd_seq_client_info_copy(m_Info, other); } /** * Constructor * @param seq A MidiClient object * @param id A numeric client id */ ClientInfo::ClientInfo(MidiClient* seq, int id) { snd_seq_client_info_malloc(&m_Info); snd_seq_get_any_client_info(seq->getHandle(), id, m_Info); } /** * Destructor */ ClientInfo::~ClientInfo() { freePorts(); snd_seq_client_info_free(m_Info); } /** * Clone the client info object. * @return A pointer to the new object. */ ClientInfo* ClientInfo::clone() { return new ClientInfo(m_Info); } /** * Assignment operator * @param other Another ClientInfo object * @return This object */ ClientInfo& ClientInfo::operator=(const ClientInfo& other) { snd_seq_client_info_copy(m_Info, other.m_Info); m_Ports = other.m_Ports; return *this; } /** * Gets the client's numeric identifier. * @return The client's numeric identifier. */ int ClientInfo::getClientId() { return snd_seq_client_info_get_client(m_Info); } /** * Gets the client's type * @return The client's type. */ snd_seq_client_type_t ClientInfo::getClientType() { return snd_seq_client_info_get_type(m_Info); } /** * Gets the client's name * @return The client's name. */ QString ClientInfo::getName() { return QString(snd_seq_client_info_get_name(m_Info)); } /** * Gets the client's broadcast filter * @return The client's broadcast filter. */ bool ClientInfo::getBroadcastFilter() { return (snd_seq_client_info_get_broadcast_filter(m_Info) != 0); } /** * Gets the client's error bounce * @return The client's error bounce. */ bool ClientInfo::getErrorBounce() { return (snd_seq_client_info_get_error_bounce(m_Info) != 0); } /** * Gets the client's event filter. * @return The client's event filter. * @deprecated */ const unsigned char* ClientInfo::getEventFilter() { return snd_seq_client_info_get_event_filter(m_Info); } /** * Gets the client's port count. * @return The client's port count. */ int ClientInfo::getNumPorts() { return snd_seq_client_info_get_num_ports(m_Info); } /** * Gets the number of lost events. * @return The number of lost events. */ int ClientInfo::getEventLost() { return snd_seq_client_info_get_event_lost(m_Info); } /** * Sets the client identifier number. * @param client The client identifier number. */ void ClientInfo::setClient(int client) { snd_seq_client_info_set_client(m_Info, client); } /** * Sets the client name. * @param name The client name. */ void ClientInfo::setName(QString name) { snd_seq_client_info_set_name(m_Info, name.toLocal8Bit().data()); } /** * Sets the broadcast filter. * @param val The broadcast filter. */ void ClientInfo::setBroadcastFilter(bool val) { snd_seq_client_info_set_broadcast_filter(m_Info, val ? 1 : 0); } /** * Sets the error bounce. * @param val The error bounce. */ void ClientInfo::setErrorBounce(bool val) { snd_seq_client_info_set_error_bounce(m_Info, val ? 1 : 0); } /** * Sets the event filter. * @param filter The event filter. * @deprecated */ void ClientInfo::setEventFilter(unsigned char *filter) { snd_seq_client_info_set_event_filter(m_Info, filter); } /** * Read the client ports. * @param seq The client instance. */ void ClientInfo::readPorts(MidiClient* seq) { PortInfo info; freePorts(); info.setClient(getClientId()); info.setClientName(getName()); info.setPort(-1); while (snd_seq_query_next_port(seq->getHandle(), info.m_Info) >= 0) { info.readSubscribers(seq); m_Ports.append(info); } } /** * Release the ports list. */ void ClientInfo::freePorts() { m_Ports.clear(); } /** * Gets the ports list. * @return The ports list. */ PortInfoList ClientInfo::getPorts() const { PortInfoList lst = m_Ports; // copy return lst; } /** * Gets the size of the internal object. * @return The size of the internal object. */ int ClientInfo::getSizeOfInfo() const { return snd_seq_client_info_sizeof(); } #if SND_LIB_VERSION > 0x010010 /** * Adds an event type to the client's filter. * * @param eventType The new event's type. */ void ClientInfo::addFilter(int eventType) { snd_seq_client_info_event_filter_add(m_Info, eventType); } /** * Checks id the given event's type is filtered. * @param eventType The event's type. * @return true if the event type is filtered */ bool ClientInfo::isFiltered(int eventType) { return (snd_seq_client_info_event_filter_check(m_Info, eventType) != 0); } /** * Clear the client's event filter */ void ClientInfo::clearFilter() { snd_seq_client_info_event_filter_clear(m_Info); } /** * Removes the event type from the client's filter. * @param eventType The event's type. */ void ClientInfo::removeFilter(int eventType) { snd_seq_client_info_event_filter_del(m_Info, eventType); } #endif /** * Default constructor */ SystemInfo::SystemInfo() { snd_seq_system_info_malloc(&m_Info); } /** * Copy constructor * @param other Another SystemInfo object reference to be copied */ SystemInfo::SystemInfo(const SystemInfo& other) { snd_seq_system_info_malloc(&m_Info); snd_seq_system_info_copy(m_Info, other.m_Info); } /** * Copy constructor * @param other Another ALSA system info object to be copied */ SystemInfo::SystemInfo(snd_seq_system_info_t* other) { snd_seq_system_info_malloc(&m_Info); snd_seq_system_info_copy(m_Info, other); } /** * Constructor * @param seq A MidiClient object */ SystemInfo::SystemInfo(MidiClient* seq) { snd_seq_system_info_malloc(&m_Info); snd_seq_system_info(seq->getHandle(), m_Info); } /** * Destructor */ SystemInfo::~SystemInfo() { snd_seq_system_info_free(m_Info); } /** * Clone the system info object * @return A pointer to the new object */ SystemInfo* SystemInfo::clone() { return new SystemInfo(m_Info); } /** * Assignment operator * @param other Another SystemInfo object * @return This object */ SystemInfo& SystemInfo::operator=(const SystemInfo& other) { snd_seq_system_info_copy(m_Info, other.m_Info); return *this; } /** * Get the system's maximum number of clients. * @return The maximum number of clients. */ int SystemInfo::getMaxClients() { return snd_seq_system_info_get_clients(m_Info); } /** * Get the system's maximum number of ports. * @return The maximum number of ports. */ int SystemInfo::getMaxPorts() { return snd_seq_system_info_get_ports(m_Info); } /** * Get the system's maximum number of queues. * @return The system's maximum number of queues. */ int SystemInfo::getMaxQueues() { return snd_seq_system_info_get_queues(m_Info); } /** * Get the system's maximum number of channels. * @return The system's maximum number of channels. */ int SystemInfo::getMaxChannels() { return snd_seq_system_info_get_channels(m_Info); } /** * Get the system's current number of queues. * @return The system's current number of queues. */ int SystemInfo::getCurrentQueues() { return snd_seq_system_info_get_cur_queues(m_Info); } /** * Get the system's current number of clients. * @return The system's current number of clients. */ int SystemInfo::getCurrentClients() { return snd_seq_system_info_get_cur_clients(m_Info); } /** * Get the system's info object size. * @return The system's info object size. */ int SystemInfo::getSizeOfInfo() const { return snd_seq_system_info_sizeof(); } /** * Default constructor */ PoolInfo::PoolInfo() { snd_seq_client_pool_malloc(&m_Info); } /** * Copy constructor * @param other Another PoolInfo object reference to be copied */ PoolInfo::PoolInfo(const PoolInfo& other) { snd_seq_client_pool_malloc(&m_Info); snd_seq_client_pool_copy(m_Info, other.m_Info); } /** * Copy constructor * @param other An ALSA pool info object to be copied */ PoolInfo::PoolInfo(snd_seq_client_pool_t* other) { snd_seq_client_pool_malloc(&m_Info); snd_seq_client_pool_copy(m_Info, other); } /** * Constructor * @param seq A MidiClient object */ PoolInfo::PoolInfo(MidiClient* seq) { snd_seq_client_pool_malloc(&m_Info); snd_seq_get_client_pool(seq->getHandle(), m_Info); } /** * Destructor */ PoolInfo::~PoolInfo() { snd_seq_client_pool_free(m_Info); } /** * Clone the pool info obeject * @return A pointer to the new object */ PoolInfo* PoolInfo::clone() { return new PoolInfo(m_Info); } /** * Assignment operator * @param other Another PoolInfo object reference to be copied * @return This object */ PoolInfo& PoolInfo::operator=(const PoolInfo& other) { snd_seq_client_pool_copy(m_Info, other.m_Info); return *this; } /** * Gets the client ID for this object. * @return The client ID. */ int PoolInfo::getClientId() { return snd_seq_client_pool_get_client(m_Info); } /** * Gets the available size on input pool. * @return The available size on input pool. */ int PoolInfo::getInputFree() { return snd_seq_client_pool_get_input_free(m_Info); } /** * Gets the input pool size. * @return The input pool size. */ int PoolInfo::getInputPool() { return snd_seq_client_pool_get_input_pool(m_Info); } /** * Gets the available size on output pool. * @return The available size on output pool. */ int PoolInfo::getOutputFree() { return snd_seq_client_pool_get_output_free(m_Info); } /** * Gets the output pool size. * @return The output pool size. */ int PoolInfo::getOutputPool() { return snd_seq_client_pool_get_output_pool(m_Info); } /** * Gets the output room size. * The output room is the minimum pool size for select/blocking mode. * @return The output room size. */ int PoolInfo::getOutputRoom() { return snd_seq_client_pool_get_output_room(m_Info); } /** * Set the input pool size. * @param size The input pool size. */ void PoolInfo::setInputPool(int size) { snd_seq_client_pool_set_input_pool(m_Info, size); } /** * Sets the output pool size. * @param size The output pool size. */ void PoolInfo::setOutputPool(int size) { snd_seq_client_pool_set_output_pool(m_Info, size); } /** * Sets the output room size. * The output room is the minimum pool size for select/blocking mode. * * @param size Output room size */ void PoolInfo::setOutputRoom(int size) { snd_seq_client_pool_set_output_room(m_Info, size); } /** * Gets the size of the client pool object. * @return The size of the client pool object. */ int PoolInfo::getSizeOfInfo() const { return snd_seq_client_pool_sizeof(); } #if SND_LIB_VERSION > 0x010004 /** * Gets the runtime ALSA library version string * @return string representing the runtime ALSA library version * @since 0.3.0 */ QString getRuntimeALSALibraryVersion() { return QString(snd_asoundlib_version()); } /** * Gets the runtime ALSA library version number * @return integer representing the runtime ALSA library version * @since 0.3.0 */ int getRuntimeALSALibraryNumber() { QRegExp rx("(\\d+)"); QString str = getRuntimeALSALibraryVersion(); bool ok; int pos = 0, result = 0, j = 0; while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) { int v = rx.cap(1).toInt(&ok); if (ok) { result <<= 8; result += v; } pos += rx.matchedLength(); j++; } return result; } #endif // SND_LIB_VERSION > 0x010004 /** * Gets the runtime ALSA drivers version string * @return string representing the runtime ALSA drivers version * @since 0.3.0 */ QString getRuntimeALSADriverVersion() { QRegExp rx(".*Driver Version.*([\\d\\.]+).*"); QString s; QFile f("/proc/asound/version"); if (f.open(QFile::ReadOnly)) { QTextStream str(&f); if (rx.exactMatch(str.readLine().trimmed())) s = rx.cap(1); } return s; } /** * Gets the runtime ALSA drivers version number * @return integer representing the runtime ALSA drivers version * @since 0.3.0 */ int getRuntimeALSADriverNumber() { QRegExp rx("(\\d+)"); QString str = getRuntimeALSADriverVersion(); bool ok; int pos = 0, result = 0, j = 0; while ((pos = rx.indexIn(str, pos)) != -1 && j < 3) { int v = rx.cap(1).toInt(&ok); if (ok) { result <<= 8; result += v; } pos += rx.matchedLength(); j++; } return result; } } /* namespace drumstick */ drumstick-1.1.3/library/PaxHeaders.32572/rt0000644000000000000000000000013013532747316015305 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.934000152 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt/0000755000175000001440000000000013532747316016155 5ustar00pedrousers00000000000000drumstick-1.1.3/library/rt/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013013532747316020122 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.934000152 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt/CMakeLists.txt0000644000175000001440000001067513532747316020726 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(CMAKE_INCLUDE_CURRENT_DIR ON) if (APPLE) set(CMAKE_MACOSX_RPATH 1) set(MACOSX_FRAMEWORK_IDENTIFIER “net.sourceforge”) set(MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(MACOSX_FRAMEWORK_BUNDLE_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) endif() set(drumstick-rt_QOBJ_SRCS ../include/drumstick/rtmidiinput.h ../include/drumstick/rtmidioutput.h ) set(drumstick-rt_HEADERS ../include/drumstick/macros.h ../include/drumstick/rtmidiinput.h ../include/drumstick/rtmidioutput.h ../include/drumstick/backendmanager.h ) set(drumstick-rt_SRCS backendmanager.cpp ) qt5_wrap_cpp(drumstick-rt_MOC_SRCS ${drumstick-rt_QOBJ_SRCS}) add_library(drumstick-rt ${drumstick-rt_MOC_SRCS} ${drumstick-rt_SRCS} ${drumstick-rt_HEADERS} ) add_library(Drumstick::RT ALIAS drumstick-rt) target_include_directories(drumstick-rt PUBLIC $ $ ) target_compile_definitions(drumstick-rt PRIVATE LIBSUFFIX=${CMAKE_INSTALL_LIBDIR}) target_link_libraries(drumstick-rt Qt5::Core) if(STATIC_DRUMSTICK) set_target_properties(drumstick-rt PROPERTIES STATIC_LIB "libdrumstick-rt") # # target_compile_definitions(drumstick-rt DUMMY_BACKEND) # target_link_libraries(drumstick-rt drumstick-rt-dummy-in) # target_link_libraries(drumstick-rt drumstick-rt-dummy-out) # if(ALSA_FOUND) target_compile_definitions(drumstick-rt LINUX_BACKEND) target_link_libraries(drumstick-rt drumstick-rt-alsa-in drumstick-rt-alsa-out drumstick-rt-eassynth drumstick-alsa) endif() if(UNIX AND NOT APPLE) target_compile_definitions(drumstick-rt OSS_BACKEND) target_link_libraries(drumstick-rt drumstick-rt-oss-in drumstick-rt-oss-out) endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_compile_definitions(drumstick-rt MAC_BACKEND) target_link_libraries(drumstick-rt drumstick-rt-mac-in drumstick-rt-mac-out drumstick-rt-macsynth "-framework CoreMIDI -framework CoreFoundation") endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") target_compile_definitions(drumstick-rt WIN_BACKEND) target_link_libraries(drumstick-rt drumstick-rt-win-in drumstick-rt-win-out winmm) endif() find_package(Qt5Network) if(Qt5Network_FOUND) target_compile_definitions(drumstick-rt NET_BACKEND) target_link_libraries(drumstick-rt drumstick-rt-net-in drumstick-rt-net-out) endif() if(PKG_CONFIG_FOUND) pkg_check_modules(FLUIDSYNTH fluidsynth>=1.1.1) if(FLUIDSYNTH_FOUND) target_compile_definitions(drumstick-rt SYNTH_BACKEND) target_link_libraries(drumstick-rt drumstick-rt-synth) endif() endif() else() # STATIC_DRUMSTICK set_target_properties(drumstick-rt PROPERTIES FRAMEWORK TRUE VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} SOVERSION ${VERSION_MAJOR}) endif() install(TARGETS drumstick-rt EXPORT drumstick-rt-config RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} ) install(FILES ${drumstick-rt_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/drumstick) install(EXPORT drumstick-rt-config DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/drumstick/cmake) export(TARGETS drumstick-rt FILE drumstick-rt-config.cmake) drumstick-1.1.3/library/rt/PaxHeaders.32572/backendmanager.cpp0000644000000000000000000000013013532747316021010 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.934000152 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt/backendmanager.cpp0000644000175000001440000002073213532747316021607 0ustar00pedrousers00000000000000/* Drumstick RT (realtime MIDI In/Out) Copyright (C) 2009-2019 Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #if defined(LINUX_BACKEND) Q_IMPORT_PLUGIN(ALSAMIDIInput) Q_IMPORT_PLUGIN(ALSAMIDIOutput) Q_IMPORT_PLUGIN(SynthController) #endif #if defined(MAC_BACKEND) Q_IMPORT_PLUGIN(MacMIDIInput) Q_IMPORT_PLUGIN(MacMIDIOutput) Q_IMPORT_PLUGIN(MacSynthOutput) #endif #if defined(WIN_BACKEND) Q_IMPORT_PLUGIN(WinMIDIInput) Q_IMPORT_PLUGIN(WinMIDIOutput) #endif #if defined(NET_BACKEND) Q_IMPORT_PLUGIN(NetMIDIInput) Q_IMPORT_PLUGIN(NetMIDIOutput) #endif #if defined(DUMMY_BACKEND) Q_IMPORT_PLUGIN(DummyInput) Q_IMPORT_PLUGIN(DummyOutput) #endif #if defined(SYNTH_BACKEND) Q_IMPORT_PLUGIN(SynthOutput) #endif #if defined(OSS_BACKEND) Q_IMPORT_PLUGIN(OSSInput) Q_IMPORT_PLUGIN(OSSOutput) #endif #define MKSTR_A(x) #x #define MKSTR(x) MKSTR_A(x) /** * @file backendmanager.cpp * Implementation of a class managing realtime MIDI input/output backends */ namespace drumstick { namespace rt { /** * @addtogroup RT * @{ * * BackendManager provides a mechanism to find and enumerate backends (plugins) * to manage realtime MIDI input/output * * This class and plugins are multiplatform. The backends implement one of these * interfaces: * * MIDIInput: for plugins that can receive MIDI events * * MIDIOutput: for plugins that can consume MIDI events * * @} */ class BackendManager::BackendManagerPrivate { public: QList m_inputsList; QList m_outputsList; ~BackendManagerPrivate() { clearLists(); } void clearLists() { m_inputsList.clear(); m_outputsList.clear(); } void appendDir(const QString& candidate, QStringList& result) { QDir checked(candidate); if (checked.exists() && !result.contains(checked.absolutePath())) { result << checked.absolutePath(); } } }; /** * @brief Constructor */ BackendManager::BackendManager(): d(new BackendManagerPrivate) { refresh(); } /** * @brief Destructor */ BackendManager::~BackendManager() { delete d; } /** * @brief returns the paths where backends are searched * @return list of paths */ QStringList BackendManager::defaultPaths() { QStringList result; QString appPath = QCoreApplication::applicationDirPath() + QDir::separator(); #if defined(Q_OS_WIN) d->appendDir( appPath + QSTR_DRUMSTICK, result ); d->appendDir( appPath + "../lib/" + QSTR_DRUMSTICK, result ); #else #if defined(Q_OS_MAC) d->appendDir( appPath + QStringLiteral("../PlugIns/") + QSTR_DRUMSTICK, result ); #endif // Linux, Unix... QStringList libs; libs << "../lib/"; #if defined(LIBSUFFIX) libs << QString("../%1/").arg(MKSTR(LIBSUFFIX)); #endif foreach(const QString& lib, libs) { d->appendDir( appPath + lib + QSTR_DRUMSTICK, result ); } #endif d->appendDir( appPath + ".." + QDir::separator() + QSTR_DRUMSTICK, result ); QByteArray envdir = qgetenv(QSTR_DRUMSTICKRT.toLatin1()); if(!envdir.isEmpty()) { d->appendDir(QString(envdir), result ); } d->appendDir( QDir::homePath() + QDir::separator() + QSTR_DRUMSTICK, result ); d->appendDir( QLibraryInfo::location(QLibraryInfo::PluginsPath) + QDir::separator() + QSTR_DRUMSTICK, result ); foreach(const QString& path, QCoreApplication::libraryPaths()) { d->appendDir( path + QDir::separator() + QSTR_DRUMSTICK, result ); } return result; } /** * @brief BackendManager::refresh finds the installed backends searching the list of paths * provided by the function defaultPaths() applying the optional settings as well. * @param settings (optional) */ void BackendManager::refresh(QSettings *settings) { QString name_in; QString name_out; QStringList names; QStringList paths; if (settings != nullptr) { settings->beginGroup(QSTR_DRUMSTICKRT_GROUP); d->appendDir(settings->value(QSTR_DRUMSTICKRT_PATH).toString(), paths); name_in = settings->value(QSTR_DRUMSTICKRT_PUBLICNAMEIN).toString(); name_out = settings->value(QSTR_DRUMSTICKRT_PUBLICNAMEOUT).toString(); names << settings->value(QSTR_DRUMSTICKRT_EXCLUDED).toStringList(); names << (name_in.isEmpty() ? QLatin1String("MIDI In") : name_in); names << (name_out.isEmpty() ? QLatin1String("MIDI Out") : name_out); settings->endGroup(); } paths << defaultPaths(); d->clearLists(); // Dynamic backends foreach(const QString& dir, paths) { QDir pluginsDir(dir); foreach (QString fileName, pluginsDir.entryList(QDir::Files)) { if (QLibrary::isLibrary(fileName)) { QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); QObject *obj = loader.instance(); if (obj != nullptr) { MIDIInput *input = qobject_cast(obj); if (input != nullptr && !d->m_inputsList.contains(input)) { if (!name_in.isEmpty()) { input->setPublicName(name_in); } input->setExcludedConnections(names); d->m_inputsList << input; } else { MIDIOutput *output = qobject_cast(obj); if (output != nullptr && !d->m_outputsList.contains(output)) { if (!name_out.isEmpty()) { output->setPublicName(name_out); } output->setExcludedConnections(names); d->m_outputsList << output; } } } } } } // Static backends foreach(QObject* obj, QPluginLoader::staticInstances()) { if (obj != nullptr) { MIDIInput *input = qobject_cast(obj); if (input != nullptr && !d->m_inputsList.contains(input)) { input->setPublicName(name_in); input->setExcludedConnections(names); d->m_inputsList << input; } else { MIDIOutput *output = qobject_cast(obj); if (output != nullptr && !d->m_outputsList.contains(output)) { output->setPublicName(name_out); output->setExcludedConnections(names); d->m_outputsList << output; } } } } } QList BackendManager::availableInputs() { return d->m_inputsList; } QList BackendManager::availableOutputs() { return d->m_outputsList; } MIDIInput* BackendManager::inputBackendByName(const QString name) { foreach (MIDIInput* i, d->m_inputsList) { if (i->backendName() == name) { return i; } } return nullptr; } MIDIOutput* BackendManager::outputBackendByName(const QString name) { foreach (MIDIOutput* i, d->m_outputsList) { if (i->backendName() == name) { return i; } } return nullptr; } }} drumstick-1.1.3/library/rt/PaxHeaders.32572/rt.pro0000644000000000000000000000013013532747316016531 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.934000152 29 ctime=1567346382.71399987 drumstick-1.1.3/library/rt/rt.pro0000644000175000001440000000516613532747316017334 0ustar00pedrousers00000000000000TEMPLATE = lib TARGET = drumstick-rt DESTDIR = ../../build/lib DEPENDPATH += . ../include INCLUDEPATH += . ../include include (../../global.pri) CONFIG += qt static { CONFIG += staticlib create_prl } DEFINES += drumstick_rt_EXPORTS QMAKE_CXXFLAGS += $$QMAKE_CXXFLAGS_HIDESYMS QT -= gui # Input HEADERS += \ ../include/drumstick/rtmidiinput.h \ ../include/drumstick/rtmidioutput.h \ ../include/drumstick/backendmanager.h \ ../include/drumstick/macros.h SOURCES += \ backendmanager.cpp macx:!static { TARGET = drumstick-rt CONFIG += lib_bundle FRAMEWORK_HEADERS.version = Versions FRAMEWORK_HEADERS.files = $$HEADERS FRAMEWORK_HEADERS.path = Headers/drumstick QMAKE_BUNDLE_DATA += FRAMEWORK_HEADERS #QMAKE_LFLAGS_SONAME = -Wl,-install_name,@executable_path/../Frameworks/ QMAKE_SONAME_PREFIX = @rpath QMAKE_TARGET_BUNDLE_PREFIX = net.sourceforge QMAKE_BUNDLE = drumstick-rt QMAKE_INFO_PLIST = ../Info.plist.lib } static { LIBS += -L$$OUT_PWD/../../build/lib/drumstick LIBS += -L$$OUT_PWD/../../build/lib #dummy { # DEFINES += DUMMY_BACKEND # LIBS += -ldrumstick-rt-dummy-in \ # -ldrumstick-rt-dummy-out #} linux* { DEFINES += LINUX_BACKEND LIBS += -ldrumstick-rt-alsa-in \ -ldrumstick-rt-alsa-out \ -ldrumstick-alsa \ -lasound packagesExist(libpulse-simple) { LIBS += -ldrumstick-rt-eassynth CONFIG += link_pkgconfig PKGCONFIG += libpulse-simple } } unix:!macx { DEFINES += OSS_BACKEND LIBS += -ldrumstick-rt-oss-in \ -ldrumstick-rt-oss-out } macx { DEFINES += MAC_BACKEND LIBS += -ldrumstick-rt-mac-in \ -ldrumstick-rt-mac-out \ -ldrumstick-rt-macsynth \ -framework CoreMIDI \ -framework CoreFoundation \ -framework CoreServices \ -framework CoreAudio \ -framework AudioToolbox \ -framework AudioUnit } win32 { DEFINES += WIN_BACKEND LIBS += -ldrumstick-rt-win-in \ -ldrumstick-rt-win-out \ -lwinmm } DEFINES += NET_BACKEND QT += network LIBS += -ldrumstick-rt-net-in \ -ldrumstick-rt-net-out packagesExist(fluidsynth) { DEFINES += SYNTH_BACKEND LIBS += -ldrumstick-rt-synth macx { LIBS += -framework FluidSynth } else { CONFIG += link_pkgconfig PKGCONFIG += fluidsynth } } } drumstick-1.1.3/library/PaxHeaders.32572/file0000644000000000000000000000013013532747316015577 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.934000152 29 ctime=1567346382.71399987 drumstick-1.1.3/library/file/0000755000175000001440000000000013532747316016447 5ustar00pedrousers00000000000000drumstick-1.1.3/library/file/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013013532747316020414 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.934000152 29 ctime=1567346382.71399987 drumstick-1.1.3/library/file/CMakeLists.txt0000644000175000001440000000525113532747316021212 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(CMAKE_INCLUDE_CURRENT_DIR ON) if (APPLE) set(CMAKE_MACOSX_RPATH 1) set(MACOSX_FRAMEWORK_IDENTIFIER “net.sourceforge”) set(MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(MACOSX_FRAMEWORK_BUNDLE_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) endif() set(drumstick-file_QTOBJ_SRCS ../include/drumstick/qsmf.h ../include/drumstick/qwrk.h ../include/drumstick/qove.h ) set(drumstick-file_HEADERS ../include/drumstick/macros.h ../include/drumstick/qsmf.h ../include/drumstick/qwrk.h ../include/drumstick/qove.h ) set(drumstick-file_SRCS qsmf.cpp qwrk.cpp qove.cpp ) qt5_wrap_cpp(drumstick-file_MOC_SRCS ${drumstick-file_QTOBJ_SRCS}) add_library(drumstick-file ${drumstick-file_MOC_SRCS} ${drumstick-file_SRCS} ${drumstick-file_HEADERS} ) add_library(Drumstick::File ALIAS drumstick-file) target_include_directories(drumstick-file PUBLIC $ $ ) target_link_libraries(drumstick-file Qt5::Core) if(STATIC_DRUMSTICK) set_target_properties(drumstick-file PROPERTIES STATIC_LIB "libdrumstick-file") else() set_target_properties(drumstick-file PROPERTIES FRAMEWORK TRUE VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH} SOVERSION ${VERSION_MAJOR}) endif() install(TARGETS drumstick-file EXPORT drumstick-file-config RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} ) install(FILES ${drumstick-file_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/drumstick) install(EXPORT drumstick-file-config DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/drumstick/cmake) export(TARGETS drumstick-file FILE drumstick-file-config.cmake) drumstick-1.1.3/library/file/PaxHeaders.32572/file.pro0000644000000000000000000000013013532747316017315 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.934000152 29 ctime=1567346382.71399987 drumstick-1.1.3/library/file/file.pro0000644000175000001440000000201713532747316020110 0ustar00pedrousers00000000000000TEMPLATE = lib TARGET = drumstick-file DESTDIR = ../../build/lib DEPENDPATH += . ../include INCLUDEPATH += . ../include include (../../global.pri) CONFIG += qt DEFINES += drumstick_file_EXPORTS QMAKE_CXXFLAGS += $$QMAKE_CXXFLAGS_HIDESYMS QT -= gui # Input HEADERS += ../include/drumstick/macros.h \ ../include/drumstick/qsmf.h \ ../include/drumstick/qwrk.h \ ../include/drumstick/qove.h SOURCES += qsmf.cpp \ qwrk.cpp \ qove.cpp static { CONFIG += staticlib create_prl DEFINES += DRUMSTICK_STATIC } macx:!static { TARGET = drumstick-file CONFIG += lib_bundle FRAMEWORK_HEADERS.version = Versions FRAMEWORK_HEADERS.files = $$HEADERS FRAMEWORK_HEADERS.path = Headers/drumstick QMAKE_BUNDLE_DATA += FRAMEWORK_HEADERS #QMAKE_LFLAGS_SONAME = -Wl,-install_name,@executable_path/../Frameworks/ QMAKE_SONAME_PREFIX = @rpath QMAKE_TARGET_BUNDLE_PREFIX = net.sourceforge QMAKE_BUNDLE = drumstick-file QMAKE_INFO_PLIST = ../Info.plist.lib } drumstick-1.1.3/library/file/PaxHeaders.32572/qwrk.cpp0000644000000000000000000000013013532747316017344 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.934000152 29 ctime=1567346382.71399987 drumstick-1.1.3/library/file/qwrk.cpp0000644000175000001440000007301213532747316020142 0ustar00pedrousers00000000000000/* WRK File component Copyright (C) 2010-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include /** * @file qwrk.cpp * Implementation of a class managing Cakewalk WRK Files input */ namespace drumstick { /** * @addtogroup WRK * @{ * * QWrk provides a mechanism to parse Cakewalk WRK Files, without * the burden of a policy forcing to use some internal sequence representation. * * This class is not related or based on the ALSA library. * * @} */ class QWrk::QWrkPrivate { public: QWrkPrivate(): m_Now(0), m_From(0), m_Thru(11930), m_KeySig(0), m_Clock(0), m_AutoSave(0), m_PlayDelay(0), m_ZeroCtrls(false), m_SendSPP(true), m_SendCont(true), m_PatchSearch(false), m_AutoStop(false), m_StopTime(4294967295U), m_AutoRewind(false), m_RewindTime(0), m_MetroPlay(false), m_MetroRecord(true), m_MetroAccent(false), m_CountIn(1), m_ThruOn(true), m_AutoRestart(false), m_CurTempoOfs(1), m_TempoOfs1(32), m_TempoOfs2(64), m_TempoOfs3(128), m_PunchEnabled(false), m_PunchInTime(0), m_PunchOutTime(0), m_EndAllTime(0), m_division(120), m_codec(0), m_IOStream(0) { } quint32 m_Now; ///< Now marker time quint32 m_From; ///< From marker time quint32 m_Thru; ///< Thru marker time quint8 m_KeySig; ///< Key signature (0=C, 1=C#, ... 11=B) quint8 m_Clock; ///< Clock Source (0=Int, 1=MIDI, 2=FSK, 3=SMPTE) quint8 m_AutoSave; ///< Auto save (0=disabled, 1..256=minutes) quint8 m_PlayDelay; ///< Play Delay bool m_ZeroCtrls; ///< Zero continuous controllers? bool m_SendSPP; ///< Send Song Position Pointer? bool m_SendCont; ///< Send MIDI Continue? bool m_PatchSearch; ///< Patch/controller search-back? bool m_AutoStop; ///< Auto-stop? quint32 m_StopTime; ///< Auto-stop time bool m_AutoRewind; ///< Auto-rewind? quint32 m_RewindTime; ///< Auto-rewind time bool m_MetroPlay; ///< Metronome on during playback? bool m_MetroRecord; ///< Metronome on during recording? bool m_MetroAccent; ///< Metronome accents primary beats? quint8 m_CountIn; ///< Measures of count-in (0=no count-in) bool m_ThruOn; ///< MIDI Thru enabled? (only used if no THRU rec) bool m_AutoRestart; ///< Auto-restart? quint8 m_CurTempoOfs; ///< Which of the 3 tempo offsets is used: 0..2 quint8 m_TempoOfs1; ///< Fixed-point ratio value of offset 1 quint8 m_TempoOfs2; ///< Fixed-point ratio value of offset 2 quint8 m_TempoOfs3; ///< Fixed-point ratio value of offset 3 bool m_PunchEnabled; ///< Auto-Punch enabled? quint32 m_PunchInTime; ///< Punch-in time quint32 m_PunchOutTime; ///< Punch-out time quint32 m_EndAllTime; ///< Time of latest event (incl. all tracks) int m_division; QTextCodec *m_codec; QDataStream *m_IOStream; QByteArray m_lastChunkData; QList m_tempos; }; /** * Constructor */ QWrk::QWrk(QObject * parent) : QObject(parent), d(new QWrkPrivate) { } /** * Destructor */ QWrk::~QWrk() { delete d; } /** * Gets the text codec used for text meta-events I/O * @return QTextCodec pointer */ QTextCodec* QWrk::getTextCodec() { return d->m_codec; } /** * Sets the text codec for text meta-events. * The engine doesn't take ownership of the codec instance. * * @param codec QTextCodec pointer */ void QWrk::setTextCodec(QTextCodec *codec) { d->m_codec = codec; } /** * Gets the last chunk raw data (undecoded) * * @return last chunk raw data */ QByteArray QWrk::getLastChunkRawData() const { return d->m_lastChunkData; } /** * Read the chunk raw data (undecoded) */ void QWrk::readRawData(int size) { d->m_lastChunkData = d->m_IOStream->device()->read(size); } /** * Now marker time * @return Now marker time */ int QWrk::getNow() const { return d->m_Now; } /** * From marker time * @return From marker time */ int QWrk::getFrom() const { return d->m_From; } /** * Thru marker time * @return Thru marker time */ int QWrk::getThru() const { return d->m_Thru; } /** * Key signature (0=C, 1=C#, ... 11=B) * @return Key signature */ int QWrk::getKeySig() const { return d->m_KeySig; } /** * Clock Source (0=Int, 1=MIDI, 2=FSK, 3=SMPTE) * @return Clock Source */ int QWrk::getClock() const { return d->m_Clock; } /** * Auto save (0=disabled, 1..256=minutes) * @return Auto save */ int QWrk::getAutoSave() const { return d->m_AutoSave; } /** * Play Delay * @return Play Delay */ int QWrk::getPlayDelay() const { return d->m_PlayDelay; } /** * Zero continuous controllers? * @return Zero continuous controllers */ bool QWrk::getZeroCtrls() const { return d->m_ZeroCtrls; } /** * Send Song Position Pointer? * @return Send Song Position Pointer */ bool QWrk::getSendSPP() const { return d->m_SendSPP; } /** * Send MIDI Continue? * @return Send MIDI Continue */ bool QWrk::getSendCont() const { return d->m_SendCont; } /** * Patch/controller search-back? * @return Patch/controller search-back */ bool QWrk::getPatchSearch() const { return d->m_PatchSearch; } /** * Auto-stop? * @return Auto-stop */ bool QWrk::getAutoStop() const { return d->m_AutoStop; } /** * Auto-stop time * @return Auto-stop time */ unsigned int QWrk::getStopTime() const { return d->m_StopTime; } /** * Auto-rewind? * @return Auto-rewind */ bool QWrk::getAutoRewind() const { return d->m_AutoRewind; } /** * Auto-rewind time * @return Auto-rewind time */ int QWrk::getRewindTime() const { return d->m_RewindTime; } /** * Metronome on during playback? * @return Metronome on during playback */ bool QWrk::getMetroPlay() const { return d->m_MetroPlay; } /** * Metronome on during recording? * @return Metronome on during recording */ bool QWrk::getMetroRecord() const { return d->m_MetroRecord; } /** * Metronome accents primary beats? * @return Metronome accents primary beats */ bool QWrk::getMetroAccent() const { return d->m_MetroAccent; } /** * Measures of count-in (0=no count-in) * @return Measures of count-in */ int QWrk::getCountIn() const { return d->m_CountIn; } /** * MIDI Thru enabled? (only used if no THRU rec) * @return MIDI Thru enabled */ bool QWrk::getThruOn() const { return d->m_ThruOn; } /** * Auto-restart? * @return Auto-restart */ bool QWrk::getAutoRestart() const { return d->m_AutoRestart; } /** * Which of the 3 tempo offsets is used: 0..2 * @return tempo offset index */ int QWrk::getCurTempoOfs() const { return d->m_CurTempoOfs; } /** * Fixed-point ratio value of tempo offset 1 * * NOTE: The offset ratios are expressed as a numerator in the expression * n/64. To get a ratio from this number, divide the number by 64. To get * this number from a ratio, multiply the ratio by 64. * Examples: * 32 ==> 32/64 = 0.5 * 63 ==> 63/64 = 0.9 * 64 ==> 64/64 = 1.0 * 128 ==> 128/64 = 2.0 * * @return tempo offset 1 */ int QWrk::getTempoOfs1() const { return d->m_TempoOfs1; } /** * Fixed-point ratio value of tempo offset 2 * * NOTE: The offset ratios are expressed as a numerator in the expression * n/64. To get a ratio from this number, divide the number by 64. To get * this number from a ratio, multiply the ratio by 64. * Examples: * 32 ==> 32/64 = 0.5 * 63 ==> 63/64 = 0.9 * 64 ==> 64/64 = 1.0 * 128 ==> 128/64 = 2.0 * * @return tempo offset 2 */ int QWrk::getTempoOfs2() const { return d->m_TempoOfs2; } /** * Fixed-point ratio value of tempo offset 3 * * NOTE: The offset ratios are expressed as a numerator in the expression * n/64. To get a ratio from this number, divide the number by 64. To get * this number from a ratio, multiply the ratio by 64. * Examples: * 32 ==> 32/64 = 0.5 * 63 ==> 63/64 = 0.9 * 64 ==> 64/64 = 1.0 * 128 ==> 128/64 = 2.0 * * @return tempo offset 3 */ int QWrk::getTempoOfs3() const { return d->m_TempoOfs3; } /** * Auto-Punch enabled? * @return Auto-Punch enabled */ bool QWrk::getPunchEnabled() const { return d->m_PunchEnabled; } /** * Punch-in time * @return punch-in time */ int QWrk::getPunchInTime() const { return d->m_PunchInTime; } /** * Punch-out time * @return Punch-out time */ int QWrk::getPunchOutTime() const { return d->m_PunchOutTime; } /** * Time of latest event (incl. all tracks) * @return Time of latest event */ int QWrk::getEndAllTime() const { return d->m_EndAllTime; } /** * Gets a single byte from the stream * @return A Single byte */ quint8 QWrk::readByte() { quint8 b = 0xff; if (!d->m_IOStream->atEnd()) *d->m_IOStream >> b; return b; } /** * Converts two bytes into a single 16-bit value * @param c1 first byte * @param c2 second byte * @return 16-bit value */ quint16 QWrk::to16bit(quint8 c1, quint8 c2) { quint16 value = (c1 << 8); value += c2; return value; } /** * Converts four bytes into a single 32-bit value * @param c1 1st byte * @param c2 2nd byte * @param c3 3rd byte * @param c4 4th byte * @return 32-bit value */ quint32 QWrk::to32bit(quint8 c1, quint8 c2, quint8 c3, quint8 c4) { quint32 value = (c1 << 24); value += (c2 << 16); value += (c3 << 8); value += c4; return value; } /** * Reads a 16-bit value * @return 16-bit value */ quint16 QWrk::read16bit() { quint8 c1, c2; c1 = readByte(); c2 = readByte(); return to16bit(c2, c1); } /** * Reads a 24-bit value * @return 32-bit value */ quint32 QWrk::read24bit() { quint8 c1, c2, c3; c1 = readByte(); c2 = readByte(); c3 = readByte(); return to32bit(0, c3, c2, c1); } /** * Reads a 32-bit value * @return 32-bit value */ quint32 QWrk::read32bit() { quint8 c1, c2, c3, c4; c1 = readByte(); c2 = readByte(); c3 = readByte(); c4 = readByte(); return to32bit(c4, c3, c2, c1); } /** * Reads a string * @return a string */ QString QWrk::readString(int len) { QString s; if ( len > 0 ) { quint8 c = 0xff; QByteArray data; for ( int i = 0; i < len && c != 0 && !atEnd(); ++i ) { c = readByte(); if ( c != 0) data += c; } if (d->m_codec == NULL) s = QString(data); else s = d->m_codec->toUnicode(data); } return s; } /** * Reads a variable length string (C-style) * @return a string */ QString QWrk::readVarString() { QString s; QByteArray data; quint8 b; do { b = readByte(); if (b != 0) data += b; } while (b != 0 && !atEnd()); if (d->m_codec == NULL) s = QString(data); else s = d->m_codec->toUnicode(data); return s; } /** * Current position in the data stream * @return current position */ long QWrk::getFilePos() { return d->m_IOStream->device()->pos(); } /** * Seeks to a new position in the data stream * @param pos new position */ void QWrk::seek(qint64 pos) { d->m_IOStream->device()->seek(pos); } /** * Checks if the data stream pointer has reached the end position * @return true if the read pointer is at end */ bool QWrk::atEnd() { return d->m_IOStream->atEnd(); } /** * Jumps the given size in the data stream * @param size the gap size */ void QWrk::readGap(int size) { if ( size > 0) seek( getFilePos() + size ); } /** * Reads a stream. * @param stream Pointer to an existing and opened stream */ void QWrk::readFromStream(QDataStream *stream) { d->m_IOStream = stream; wrkRead(); } /** * Reads a stream from a disk file. * @param fileName Name of an existing file. */ void QWrk::readFromFile(const QString& fileName) { QFile file(fileName); file.open(QIODevice::ReadOnly); QDataStream ds(&file); readFromStream(&ds); file.close(); } void QWrk::processTrackChunk() { int namelen; QString name[2]; int trackno; int channel; int pitch; int velocity; int port; bool selected; bool muted; bool loop; trackno = read16bit(); for(int i=0; i<2; ++i) { namelen = readByte(); name[i] = readString(namelen); } channel = (qint8) readByte(); pitch = readByte(); velocity = readByte(); port = readByte(); quint8 flags = readByte(); selected = ((flags & 1) != 0); muted = ((flags & 2) != 0); loop = ((flags & 4) != 0); Q_EMIT signalWRKTrack( name[0], name[1], trackno, channel, pitch, velocity, port, selected, muted, loop ); } void QWrk::processVarsChunk() { d->m_Now = read32bit(); d->m_From = read32bit(); d->m_Thru = read32bit(); d->m_KeySig = readByte(); d->m_Clock = readByte(); d->m_AutoSave = readByte(); d->m_PlayDelay = readByte(); readGap(1); d->m_ZeroCtrls = (readByte() != 0); d->m_SendSPP = (readByte() != 0); d->m_SendCont = (readByte() != 0); d->m_PatchSearch = (readByte() != 0); d->m_AutoStop = (readByte() != 0); d->m_StopTime = read32bit(); d->m_AutoRewind = (readByte() != 0); d->m_RewindTime = read32bit(); d->m_MetroPlay = (readByte() != 0); d->m_MetroRecord = (readByte() != 0); d->m_MetroAccent = (readByte() != 0); d->m_CountIn = readByte(); readGap(2); d->m_ThruOn = (readByte() != 0); readGap(19); d->m_AutoRestart = (readByte() != 0); d->m_CurTempoOfs = readByte(); d->m_TempoOfs1 = readByte(); d->m_TempoOfs2 = readByte(); d->m_TempoOfs3 = readByte(); readGap(2); d->m_PunchEnabled = (readByte() != 0); d->m_PunchInTime = read32bit(); d->m_PunchOutTime = read32bit(); d->m_EndAllTime = read32bit(); Q_EMIT signalWRKGlobalVars(); } void QWrk::processTimebaseChunk() { quint16 timebase = read16bit(); d->m_division = timebase; Q_EMIT signalWRKTimeBase(timebase); } void QWrk::processNoteArray(int track, int events) { quint32 time = 0; quint8 status = 0, data1 = 0, data2 = 0, i = 0; quint16 dur = 0; int value = 0, type = 0, channel = 0, len = 0; QString text; QByteArray data; for ( i = 0; (i < events) && !atEnd(); ++i ) { time = read24bit(); status = readByte(); dur = 0; if (status >= 0x90) { type = status & 0xf0; channel = status & 0x0f; data1 = readByte(); if (type == 0x90 || type == 0xA0 || type == 0xB0 || type == 0xE0) data2 = readByte(); if (type == 0x90) dur = read16bit(); switch (type) { case 0x90: Q_EMIT signalWRKNote(track, time, channel, data1, data2, dur); break; case 0xA0: Q_EMIT signalWRKKeyPress(track, time, channel, data1, data2); break; case 0xB0: Q_EMIT signalWRKCtlChange(track, time, channel, data1, data2); break; case 0xC0: Q_EMIT signalWRKProgram(track, time, channel, data1); break; case 0xD0: Q_EMIT signalWRKChanPress(track, time, channel, data1); break; case 0xE0: value = (data2 << 7) + data1 - 8192; Q_EMIT signalWRKPitchBend(track, time, channel, value); break; case 0xF0: Q_EMIT signalWRKSysexEvent(track, time, data1); break; } } else if (status == 5) { int code = read16bit(); len = read32bit(); text = readString(len); Q_EMIT signalWRKExpression(track, time, code, text); } else if (status == 6) { int code = read16bit(); dur = read16bit(); readGap(4); Q_EMIT signalWRKHairpin(track, time, code, dur); } else if (status == 7) { len = read32bit(); text = readString(len); data.clear(); for(int j=0; j<13; ++j) { int byte = readByte(); data += byte; } Q_EMIT signalWRKChord(track, time, text, data); } else if (status == 8) { len = read16bit(); data.clear(); for(int j=0; jm_division; RecTempo last; last.time = 0; last.tempo = 100.0; last.seconds = 0.0; if (!d->m_tempos.isEmpty()) { foreach(const RecTempo& rec, d->m_tempos) { if (rec.time >= ticks) break; last = rec; } } return last.seconds + (((ticks - last.time) / division) * (60.0 / last.tempo)); } void QWrk::processTempoChunk(int factor) { double division = 1.0 * d->m_division; int count = read16bit(); RecTempo last, next; for (int i = 0; i < count; ++i) { long time = read32bit(); readGap(4); long tempo = read16bit() * factor; readGap(8); next.time = time; next.tempo = tempo / 100.0; next.seconds = 0.0; last.time = 0; last.tempo = next.tempo; last.seconds = 0.0; if (! d->m_tempos.isEmpty()) { foreach(const RecTempo& rec, d->m_tempos) { if (rec.time >= time) break; last = rec; } next.seconds = last.seconds + (((time - last.time) / division) * (60.0 / last.tempo)); } d->m_tempos.append(next); Q_EMIT signalWRKTempo(time, tempo); } } void QWrk::processSysexChunk() { int j; QString name; QByteArray data; int bank = readByte(); int length = read16bit(); bool autosend = (readByte() != 0); int namelen = readByte(); name = readString(namelen); for(j=0; j> 4; bool autosend = ( (b & 0x0f) != 0); int namelen = readByte(); name = readString(namelen); for(j=0; j127 qint8 channel = readByte(); // -1, 0->15 qint8 keyPlus = readByte(); // 0->127 qint8 velPlus = readByte(); // 0->127 qint8 localPort = readByte(); qint8 mode = readByte(); Q_EMIT signalWRKThru(mode, port, channel, keyPlus, velPlus, localPort); } void QWrk::processTrackOffset() { quint16 track = read16bit(); qint16 offset = read16bit(); Q_EMIT signalWRKTrackOffset(track, offset); } void QWrk::processTrackReps() { quint16 track = read16bit(); quint16 reps = read16bit(); Q_EMIT signalWRKTrackReps(track, reps); } void QWrk::processTrackPatch() { quint16 track = read16bit(); qint8 patch = readByte(); Q_EMIT signalWRKTrackPatch(track, patch); } void QWrk::processTimeFormat() { quint16 fmt = read16bit(); quint16 ofs = read16bit(); Q_EMIT signalWRKTimeFormat(fmt, ofs); } void QWrk::processComments() { int len = read16bit(); QString text = readString(len); Q_EMIT signalWRKComments(text); } void QWrk::processVariableRecord(int max) { int datalen = max - 32; QByteArray data; QString name = readVarString(); readGap(31 - name.length()); for ( int i = 0; i < datalen; ++i ) data += readByte(); Q_EMIT signalWRKVariableRecord(name, data); } void QWrk::processUnknown(int id) { Q_EMIT signalWRKUnknownChunk(id, d->m_lastChunkData); } void QWrk::processNewTrack() { qint16 bank = -1; qint16 patch = -1; //qint16 vol = -1; //qint16 pan = -1; qint8 key = -1; qint8 vel = 0; quint8 port = 0; qint8 channel = 0; bool selected = false; bool muted = false; bool loop = false; quint16 track = read16bit(); quint8 len = readByte(); QString name = readString(len); bank = read16bit(); patch = read16bit(); /*vol =*/ read16bit(); /*pan =*/ read16bit(); key = readByte(); vel = readByte(); readGap(7); port = readByte(); channel = readByte(); muted = (readByte() != 0); Q_EMIT signalWRKNewTrack(name, track, channel, key, vel, port, selected, muted, loop); if (bank > -1) Q_EMIT signalWRKTrackBank(track, bank); if (patch > -1) { if (channel > -1) Q_EMIT signalWRKProgram(track, 0, channel, patch); else Q_EMIT signalWRKTrackPatch(track, patch); } } void QWrk::processSoftVer() { int len = readByte(); QString vers = readString(len); Q_EMIT signalWRKSoftVer(vers); } void QWrk::processTrackName() { int track = read16bit(); int len = readByte(); QString name = readString(len); Q_EMIT signalWRKTrackName(track, name); } void QWrk::processStringTable() { QStringList table; int rows = read16bit(); for (int i = 0; i < rows; ++i) { int len = readByte(); QString name = readString(len); int idx = readByte(); table.insert(idx, name); } Q_EMIT signalWRKStringTable(table); } void QWrk::processLyricsStream() { quint16 track = read16bit(); int events = read32bit(); processNoteArray(track, events); } void QWrk::processTrackVol() { quint16 track = read16bit(); int vol = read16bit(); Q_EMIT signalWRKTrackVol(track, vol); } void QWrk::processNewTrackOffset() { quint16 track = read16bit(); int offset = read32bit(); Q_EMIT signalWRKTrackOffset(track, offset); } void QWrk::processTrackBank() { quint16 track = read16bit(); int bank = read16bit(); Q_EMIT signalWRKTrackBank(track, bank); } void QWrk::processSegmentChunk() { QString name; int track = read16bit(); int offset = read32bit(); readGap(8); int len = readByte(); name = readString(len); readGap(20); Q_EMIT signalWRKSegment(track, offset, name); int events = read32bit(); processNoteArray(track, events); } void QWrk::processNewStream() { QString name; int track = read16bit(); int len = readByte(); name = readString(len); Q_EMIT signalWRKSegment(track, 0, name); int events = read32bit(); processNoteArray(track, events); } void QWrk::processEndChunk() { emit signalWRKEnd(); } int QWrk::readChunk() { long start_pos, final_pos; int ck_len, ck = readByte(); if (ck != END_CHUNK) { ck_len = read32bit(); start_pos = getFilePos(); final_pos = start_pos + ck_len; readRawData(ck_len); seek(start_pos); switch (ck) { case TRACK_CHUNK: processTrackChunk(); break; case VARS_CHUNK: processVarsChunk(); break; case TIMEBASE_CHUNK: processTimebaseChunk(); break; case STREAM_CHUNK: processStreamChunk(); break; case METER_CHUNK: processMeterChunk(); break; case TEMPO_CHUNK: processTempoChunk(100); break; case NTEMPO_CHUNK: processTempoChunk(); break; case SYSEX_CHUNK: processSysexChunk(); break; case THRU_CHUNK: processThruChunk(); break; case TRKOFFS_CHUNK: processTrackOffset(); break; case TRKREPS_CHUNK: processTrackReps(); break; case TRKPATCH_CHUNK: processTrackPatch(); break; case TIMEFMT_CHUNK: processTimeFormat(); break; case COMMENTS_CHUNK: processComments(); break; case VARIABLE_CHUNK: processVariableRecord(ck_len); break; case NTRACK_CHUNK: processNewTrack(); break; case SOFTVER_CHUNK: processSoftVer(); break; case TRKNAME_CHUNK: processTrackName(); break; case STRTAB_CHUNK: processStringTable(); break; case LYRICS_CHUNK: processLyricsStream(); break; case TRKVOL_CHUNK: processTrackVol(); break; case NTRKOFS_CHUNK: processNewTrackOffset(); break; case TRKBANK_CHUNK: processTrackBank(); break; case METERKEY_CHUNK: processMeterKeyChunk(); break; case SYSEX2_CHUNK: processSysex2Chunk(); break; case NSYSEX_CHUNK: processNewSysexChunk(); break; case SGMNT_CHUNK: processSegmentChunk(); break; case NSTREAM_CHUNK: processNewStream(); break; default: processUnknown(ck); } seek(final_pos); } return ck; } void QWrk::wrkRead() { int vma, vme; int ck_id; QByteArray hdr(HEADER.length(), ' '); d->m_tempos.clear(); d->m_IOStream->device()->read(hdr.data(), HEADER.length()); if (hdr == HEADER) { readGap(1); vme = readByte(); vma = readByte(); Q_EMIT signalWRKHeader(vma, vme); do { ck_id = readChunk(); } while (ck_id != END_CHUNK); if (!atEnd()) Q_EMIT signalWRKError("Corrupted file"); else processEndChunk(); } else Q_EMIT signalWRKError("Invalid file format"); } } // namespace drumstick drumstick-1.1.3/library/file/PaxHeaders.32572/qove.cpp0000644000000000000000000000013013532747316017332 xustar0029 mtime=1567346382.71399987 30 atime=1567346382.934000152 29 ctime=1567346382.71399987 drumstick-1.1.3/library/file/qove.cpp0000644000175000001440000076503713532747316020147 0ustar00pedrousers00000000000000/* Overture OVE File component Copyright (C) 2006-2019, Rui Fan This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include /** * @file qove.cpp * Implementation of a class managing Overture OVE Files input */ namespace OVE { class OveSong; class Track; class Page; class Voice; class Line; class Staff; class Measure; class MeasureData; class MusicData; class OffsetElement; class LineElement; class PairEnds; class Note; class NoteContainer; class Beam; class Tie; class Tuplet; class Harmony; class Clef; class Lyric; class Slur; class MeasureText; class Articulation; class Glissando; class Decorator; class MeasureRepeat; class Dynamics; class Wedge; class WedgeEndPoint; class Pedal; class KuoHao; class Expressions; class HarpPedal; class MultiMeasureRest; class OctaveShift; class OctaveShiftEndPoint; class BarNumber; class Tempo; class Text; class TimeSignature; class Key; class RepeatSymbol; class NumericEnding; class MidiData; class MidiController; class MidiProgramChange; class MidiChannelPressure; class MidiPitchWheel; const int TWELVE_TONE = 12 ; const int INVALID_NOTE = -1 ; const int OCTAVE = 7 ; enum CondType { Cond_Time_Parameters = 0x09, // size - 7, TimeSignature Cond_Bar_Number = 0x0A, // size, compatible with previous version Cond_Decorator = 0x16, Cond_Tempo = 0x1C, // size - 7 Cond_Text = 0x1D, // size - 7, Rehearsal | SystemText Cond_Expression = 0x25, // size - 7, if set playback parameters in Expression, will store in COND Cond_Barline_Parameters = 0x30, // size - 7, include :|| repeat count Cond_Repeat = 0x31, // Cond_Numeric_Ending = 0x32, // Cond_None }; enum BdatType { Bdat_Raw_Note = 0x70, Bdat_Rest = 0x80, Bdat_Note = 0x90, Bdat_Beam = 0x10, Bdat_Harmony = 0x11, Bdat_Clef = 0x12, Bdat_Dynamics = 0x13, Bdat_Wedge = 0x14, // cresendo, decresendo Bdat_Glissando = 0x15, Bdat_Decorator = 0x16, // measure repeat | piano pedal | dotted barline Bdat_Key = 0x17, Bdat_Lyric = 0x18, Bdat_Octave_Shift = 0x19, Bdat_Slur = 0x1B, Bdat_Text = 0x1D, Bdat_Tie = 0x1E, Bdat_Tuplet = 0x1F, Bdat_Guitar_Bend = 0x21, // Bdat_Guitar_Barre = 0x22, // Bdat_Pedal = 0x23, Bdat_KuoHao = 0x24, // () [] {} Bdat_Expressions = 0x25, Bdat_Harp_Pedal = 0x26, Bdat_Multi_Measure_Rest = 0x27, Bdat_Harmony_GuitarFrame = 0x28, Bdat_Graphics_40 = 0x40, // unknown Bdat_Graphics_RoundRect = 0x41, Bdat_Graphics_Rect = 0x42, Bdat_Graphics_Round = 0x43, Bdat_Graphics_Line = 0x44, Bdat_Graphics_Curve = 0x45, Bdat_Graphics_WedgeSymbol = 0x46, Bdat_Midi_Controller = 0xAB, Bdat_Midi_Program_Change = 0xAC, Bdat_Midi_Channel_Pressure = 0xAD, Bdat_Midi_Pitch_Wheel = 0xAE, Bdat_Bar_End = 0xFF, Bdat_None }; //////////////////////////////////////// enum MusicDataType { // attributes MusicData_Clef, MusicData_Key, MusicData_Measure_Repeat, // sound MusicData_Tempo, // direction MusicData_Dynamics, MusicData_Wedge, MusicData_Wedge_EndPoint, MusicData_OctaveShift, MusicData_OctaveShift_EndPoint, MusicData_Expressions, MusicData_Repeat, MusicData_Text, MusicData_Harp_Pedal, MusicData_Pedal, // note & harmony MusicData_Note_Container, MusicData_Harmony, // note's children MusicData_Beam, MusicData_Glissando, MusicData_Lyric, MusicData_Slur, MusicData_Tie, MusicData_Tuplet, // barline MusicData_Numeric_Ending, MusicData_KuoHao, MusicData_Bar_End, MusicData_Decorator, MusicData_Multi_Measure_Rest, MusicData_None }; enum MidiType { Midi_Controller = 0, Midi_Program_Change, Midi_Channel_Pressure, Midi_Pitch_Wheel, Midi_None }; enum ClefType { Clef_Treble = 0x00, //0x00 Clef_Bass, //0x01 Clef_Alto, //0x02 Clef_UpAlto, //0x03 Clef_DownDownAlto, //0x04 Clef_DownAlto, //0x05 Clef_UpUpAlto, //0x06 Clef_Treble8va, //0x07 Clef_Bass8va, //0x08 Clef_Treble8vb, //0x09 Clef_Bass8vb, //0x0A Clef_Percussion1, //0x0B Clef_Percussion2, //0x0C Clef_TAB //0x0D }; enum GroupType { Group_None = 0, Group_Brace, Group_Bracket }; enum AccidentalType { Accidental_Normal = 0x0, Accidental_Sharp = 0x1, Accidental_Flat = 0x2, Accidental_Natural = 0x3, Accidental_DoubleSharp = 0x4, Accidental_DoubleFlat = 0x5, Accidental_Sharp_Caution = 0x9, Accidental_Flat_Caution = 0xA, Accidental_Natural_Caution = 0xB, Accidental_DoubleSharp_Caution = 0xC, Accidental_DoubleFlat_Caution = 0xD }; enum NoteHeadType { NoteHead_Standard = 0x00, NoteHead_Invisible, NoteHead_Rhythmic_Slash, NoteHead_Percussion, NoteHead_Closed_Rhythm, NoteHead_Open_Rhythm, NoteHead_Closed_Slash, NoteHead_Open_Slash, NoteHead_Closed_Do, NoteHead_Open_Do, NoteHead_Closed_Re, NoteHead_Open_Re, NoteHead_Closed_Mi, NoteHead_Open_Mi, NoteHead_Closed_Fa, NoteHead_Open_Fa, NoteHead_Closed_Sol, NoteHead_Open_Sol, NoteHead_Closed_La, NoteHead_Open_La, NoteHead_Closed_Ti, NoteHead_Open_Ti }; enum TiePos { Tie_None = 0x0, Tie_LeftEnd = 0x1, Tie_RightEnd = 0x2 }; enum ArticulationType { Articulation_Major_Trill = 0x00, Articulation_Minor_Trill = 0x01, Articulation_Trill_Section = 0x02, Articulation_Inverted_Short_Mordent = 0x03, Articulation_Inverted_Long_Mordent = 0x04, Articulation_Short_Mordent = 0x05, Articulation_Turn = 0x06, Articulation_Finger_1 = 0x07, Articulation_Finger_2 = 0x08, Articulation_Finger_3 = 0x09, Articulation_Finger_4 = 0x0A, Articulation_Finger_5 = 0x0B, Articulation_Flat_Accidental_For_Trill = 0x0C, Articulation_Sharp_Accidental_For_Trill = 0x0D, Articulation_Natural_Accidental_For_Trill = 0x0E, Articulation_Marcato = 0x0F, Articulation_Marcato_Dot = 0x10, Articulation_Heavy_Attack = 0x11, Articulation_SForzando = 0x12, Articulation_SForzando_Dot = 0x13, Articulation_Heavier_Attack = 0x14, Articulation_SForzando_Inverted = 0x15, Articulation_SForzando_Dot_Inverted = 0x16, Articulation_Staccatissimo = 0x17, Articulation_Staccato = 0x18, Articulation_Tenuto = 0x19, Articulation_Up_Bow = 0x1A, Articulation_Down_Bow = 0x1B, Articulation_Up_Bow_Inverted = 0x1C, Articulation_Down_Bow_Inverted = 0x1D, Articulation_Arpeggio = 0x1E, Articulation_Tremolo_Eighth = 0x1F, Articulation_Tremolo_Sixteenth = 0x20, Articulation_Tremolo_Thirty_Second = 0x21, Articulation_Tremolo_Sixty_Fourth = 0x22, Articulation_Natural_Harmonic = 0x23, Articulation_Artificial_Harmonic = 0x24, Articulation_Plus_Sign = 0x25, Articulation_Fermata = 0x26, Articulation_Fermata_Inverted = 0x27, Articulation_Pedal_Down = 0x28, Articulation_Pedal_Up = 0x29, Articulation_Pause = 0x2A, Articulation_Grand_Pause = 0x2B, Articulation_Toe_Pedal = 0x2C, Articulation_Heel_Pedal = 0x2D, Articulation_Toe_To_Heel_Pedal = 0x2E, Articulation_Heel_To_Toe_Pedal = 0x2F, Articulation_Open_String = 0x30, // finger 0 in guitar Articulation_Guitar_Lift = 0x46, Articulation_Guitar_Slide_Up = 0x47, Articulation_Guitar_Rip = 0x48, Articulation_Guitar_Fall_Off = 0x49, Articulation_Guitar_Slide_Down = 0x4A, Articulation_Guitar_Spill = 0x4B, Articulation_Guitar_Flip = 0x4C, Articulation_Guitar_Smear = 0x4D, Articulation_Guitar_Bend = 0x4E, Articulation_Guitar_Doit = 0x4F, Articulation_Guitar_Plop = 0x50, Articulation_Guitar_Wow_Wow = 0x51, Articulation_Guitar_Thumb = 0x64, Articulation_Guitar_Index_Finger = 0x65, Articulation_Guitar_Middle_Finger = 0x66, Articulation_Guitar_Ring_Finger = 0x67, Articulation_Guitar_Pinky_Finger = 0x68, Articulation_Guitar_Tap = 0x69, Articulation_Guitar_Hammer = 0x6A, Articulation_Guitar_Pluck = 0x6B, Articulation_None /* Articulation_Detached_Legato, Articulation_Spiccato, Articulation_Scoop, Articulation_Plop, Articulation_Doit, Articulation_Falloff, Articulation_Breath_Mark, Articulation_Caesura,*/ }; enum NoteType { Note_DoubleWhole= 0x0, Note_Whole = 0x1, Note_Half = 0x2, Note_Quarter = 0x3, Note_Eight = 0x4, Note_Sixteen = 0x5, Note_32 = 0x6, Note_64 = 0x7, Note_128 = 0x8, Note_256 = 0x9, Note_None }; inline int NoteTypeToTick(NoteType type, int quarter) { int c = int(pow(2.0, (int)type)) ; return quarter * 4 * 2 / c ; } enum HarmonyType { Harmony_maj = 0, Harmony_min, Harmony_aug, Harmony_dim, Harmony_dim7, Harmony_sus2, Harmony_sus4, Harmony_sus24, Harmony_add2, Harmony_add9, Harmony_omit3, Harmony_omit5, Harmony_2, Harmony_5, Harmony_6, Harmony_69, Harmony_7, Harmony_7b5, Harmony_7b9, Harmony_7s9, Harmony_7s11, Harmony_7b5s9, Harmony_7b5b9, Harmony_7b9s9, Harmony_7b9s11, Harmony_7sus4, Harmony_9, Harmony_9b5, Harmony_9s11, Harmony_9sus4, Harmony_11, Harmony_13, Harmony_13b5, Harmony_13b9, Harmony_13s9, Harmony_13s11, Harmony_13sus4, Harmony_min_add2, Harmony_min_add9, Harmony_min_maj7, Harmony_min6, Harmony_min6_add9, Harmony_min7, Harmony_min7b5, Harmony_min7_add4, Harmony_min7_add11, Harmony_min9, Harmony_min9_b5, Harmony_min9_maj7, Harmony_min11, Harmony_min13, Harmony_maj7, Harmony_maj7_b5, Harmony_maj7_s5, Harmony_maj7_69, Harmony_maj7_add9, Harmony_maj7_s11, Harmony_maj9, Harmony_maj9_sus4, Harmony_maj9_b5, Harmony_maj9_s5, Harmony_maj9_s11, Harmony_maj13, Harmony_maj13_b5, Harmony_maj13_b9, Harmony_maj13_b9b5, Harmony_maj13_s11, Harmony_aug7, Harmony_aug7_b9, Harmony_aug7_s9, Harmony_None }; enum DynamicsType { Dynamics_pppp = 0, Dynamics_ppp, Dynamics_pp, Dynamics_p, Dynamics_mp, Dynamics_mf, Dynamics_f, Dynamics_ff, Dynamics_fff, Dynamics_ffff, Dynamics_sf, Dynamics_fz, Dynamics_sfz, Dynamics_sffz, Dynamics_fp, Dynamics_sfp }; enum WedgeType { Wedge_Cres_Line = 0, // < Wedge_Double_Line, // <>, not appear in xml Wedge_Decresc_Line, // > Wedge_Cres, // cresc., not appear in xml, will create Expression Wedge_Decresc // decresc., not appear in xml, will create Expression }; enum KuoHaoType { KuoHao_Parentheses = 0, KuoHao_Brace, KuoHao_Bracket }; enum OctaveShiftType { OctaveShift_8 = 0, OctaveShift_Minus_8, OctaveShift_15, OctaveShift_Minus_15 }; enum OctaveShiftPosition { OctavePosition_Start = 0 , OctavePosition_Continue, OctavePosition_Stop }; enum RepeatType { Repeat_Segno = 0, Repeat_Coda, Repeat_ToCoda, Repeat_DSAlCoda, Repeat_DSAlFine, Repeat_DCAlCoda, Repeat_DCAlFine, Repeat_Fine, Repeat_Null }; enum BarlineType { Barline_Default = 0, //0x00 will be | or final (at last measure) Barline_Double, //0x01 || Barline_RepeatLeft, //0x02 ||: Barline_RepeatRight, //0x03 :|| Barline_Final, //0x04 Barline_Dashed, //0x05 Barline_Null //0x06 } ; enum NoteDuration { NoteDuration_256 = 15, NoteDuration_128 = NoteDuration_256 * 2, // 30 NoteDuration_64 = NoteDuration_128 * 2, // 60 NoteDuration_32 = NoteDuration_64 * 2, // 120 NoteDuration_16 = NoteDuration_32 * 2, // 240 NoteDuration_8 = NoteDuration_16 * 2, // 480 NoteDuration_4 = NoteDuration_8 * 2, // 960 NoteDuration_2 = NoteDuration_4 * 2, // 1920 NoteDuration_Whole = NoteDuration_2 * 2, // 3840 NoteDuration_Double_Whole = NoteDuration_Whole * 2 // 7680 }; enum ToneType { Tone_C = 0 , Tone_D, Tone_E, Tone_F, Tone_G, Tone_A, Tone_B }; enum KeyType { Key_C = 0, // C Key_Bass_1, // F Key_Bass_2, // Bb Key_Bass_3, // Eb Key_Bass_4, // Ab Key_Bass_5, // Db Key_Bass_6, // Gb Key_Bass_7, // Cb Key_Sharp_1, // G Key_Sharp_2, // D Key_Sharp_3, // A Key_Sharp_4, // E Key_Sharp_5, // B Key_Sharp_6, // F# Key_Sharp_7 // C# }; // IOveNotify.h class IOveNotify { public: IOveNotify() {} virtual ~IOveNotify() {} public: virtual void loadInfo(const QString& info) = 0; virtual void loadError() = 0; virtual void loadPosition(int currentMeasure, int totalMeasure, int currentTrack, int totalTrack) = 0; }; class IOVEStreamLoader { public: IOVEStreamLoader() {} virtual ~IOVEStreamLoader() {} public: virtual void setNotify(IOveNotify* notify) = 0; virtual void setFileStream(unsigned char* buffer, unsigned int size) = 0; virtual void setOve(OveSong* ove) = 0; // read stream, set readed data to setOve(ove) virtual bool load() = 0; virtual void release() = 0; }; IOVEStreamLoader* createOveStreamLoader(); ///////////////////////////////////////////////////////////////////////////// // basic element class TickElement { public: TickElement(); virtual ~TickElement() {} public: void setTick(int tick); int getTick(void) const; private: int tick_; }; class MeasurePos { public: MeasurePos(); virtual ~MeasurePos() {} public: void setMeasure(int measure); int getMeasure() const; void setOffset(int offset); int getOffset() const; MeasurePos shiftMeasure(int measure) const; MeasurePos shiftOffset(int offset) const; // ignore cross measure bool operator ==(const MeasurePos& mp) const; bool operator !=(const MeasurePos& mp) const; bool operator <(const MeasurePos& mp) const; bool operator <=(const MeasurePos& mp) const; bool operator >(const MeasurePos& mp) const; bool operator >=(const MeasurePos& mp) const; private: int measure_; int offset_; }; class PairElement { public: PairElement(); virtual ~PairElement(); public: MeasurePos* start() const; MeasurePos* stop() const; private: MeasurePos* start_; MeasurePos* stop_; }; class PairEnds { public: PairEnds(); virtual ~PairEnds(); public: LineElement* getLeftLine() const; LineElement* getRightLine() const; OffsetElement* getLeftShoulder() const; OffsetElement* getRightShoulder() const; private: LineElement* leftLine_; LineElement* rightLine_; OffsetElement* leftShoulder_; OffsetElement* rightShoulder_; }; class LineElement { public: LineElement(); virtual ~LineElement() {} public: virtual void setLine(int line); // middle line (3rd line of each clef) is set 0 virtual int getLine(void) const; private: int line_; }; class OffsetElement { public: OffsetElement(); virtual ~OffsetElement() {} public: virtual void setXOffset(int offset); virtual int getXOffset() const; virtual void setYOffset(int offset); virtual int getYOffset() const; private: int xOffset_; int yOffset_; }; class LengthElement { public: LengthElement(); virtual ~LengthElement() {} public: void setLength(int length); int getLength() const; private: int length_; // tick }; // base class of many ove music element class MusicData: public TickElement, public PairElement, public OffsetElement { public: MusicData(); virtual ~MusicData() {} public: MusicDataType getMusicDataType() const; enum XmlDataType { Attributes = 0, NoteBeam, Notations, Direction, None }; static XmlDataType getXmlDataType(MusicDataType type); // static bool get_is_pair_element(MusicDataType type) ; // show / hide void setShow(bool show); bool getShow() const; // color void setColor(unsigned int color); // not exists in ove 3 unsigned int getColor() const; void setVoice(unsigned int voice); unsigned int getVoice() const; void copyCommonBlock(const MusicData& source); protected: MusicDataType musicDataType_; private: bool show_; unsigned int color_; unsigned int voice_; }; class MidiData: public TickElement { public: MidiData(); virtual ~MidiData() {} public: MidiType getMidiType() const; protected: MidiType midiType_; }; //////////////////////////////////////////////////////////////////////////////// class OveSong { public: OveSong(); ~OveSong(); public: void setIsVersion4(bool version4 = true); bool getIsVersion4() const; void setQuarter(int tick); int getQuarter(void) const; void setShowPageMargin(bool show); bool getShowPageMargin() const; void setShowTransposeTrack(bool show); bool getShowTransposeTrack() const; void setShowLineBreak(bool show); bool getShowLineBreak() const; void setShowRuler(bool show); bool getShowRuler() const; void setShowColor(bool show); bool getShowColor() const; void setPlayRepeat(bool play); bool getPlayRepeat() const; enum PlayStyle{ Record, Swing, Notation }; void setPlayStyle(PlayStyle style); PlayStyle getPlayStyle() const; void addTitle(const QString& str); QList getTitles(void) const; void addAnnotate(const QString& str); QList getAnnotates(void) const; void addWriter(const QString& str); QList getWriters(void) const; void addCopyright(const QString& str); QList getCopyrights(void) const; void addHeader(const QString& str); QList getHeaders(void) const; void addFooter(const QString& str); QList getFooters(void) const; void addTrack(Track* ptr); int getTrackCount(void) const; QList getTracks() const; Track* getTrack(int part, int staff) const; void setTrackBarCount(int count); int getTrackBarCount() const; bool addPage(Page* page); int getPageCount() const; Page* getPage(int idx); void addLine(Line* ptr); int getLineCount() const; Line* getLine(int idx) const; void addMeasure(Measure* ptr); int getMeasureCount(void) const; Measure* getMeasure(int bar) const; void addMeasureData(MeasureData* ptr); int getMeasureDataCount(void) const; MeasureData* getMeasureData(int part, int staff/*=0*/, int bar) const; MeasureData* getMeasureData(int track, int bar) const; // tool void setPartStaffCounts(const QList& partStaffCounts); int getPartCount() const; int getStaffCount(int part) const; int getPartBarCount() const; void clear(void); QPair trackToPartStaff(int track) const; void setTextCodecName(const QString& codecName); QString getCodecString(const QByteArray& text); private: int partStaffToTrack(int part, int staff) const; private: bool version4_; int quarter_; bool showPageMargin_; bool showTransposeTrack; bool showLineBreak_; bool showRuler_; bool showColor_; bool playRepeat_; PlayStyle playStyle_; QList titles_; QList annotates_; QList writers_; QList copyrights_; QList headers_; QList footers_; QList tracks_; QList pages_; QList lines_; QList measures_; QList measureDatas_; int trackBarCount_; //equal to measures_.size() QList partStaffCounts_; QTextCodec* codec_; }; class Voice { public: Voice(); ~Voice(){} public: void setChannel(int channel); int getChannel() const; void setVolume(int volume); int getVolume() const; void setPitchShift(int pitchShift); int getPitchShift() const; void setPan(int pan); int getPan() const; void setPatch(int patch); int getPatch() const; void setStemType(int stemType); int getStemType() const; static int getDefaultPatch(); static int getDefaultVolume(); private: int channel_; // [0, 15] int volume_; // [-1, 127], -1 default int pitchShift_; // [-36, 36] int pan_; // [-64, 63] int patch_; // [0, 127] int stemType_; // 0, 1, 2 }; class Track { public: Track(); ~Track(); public: void setName(const QString& str); QString getName(void) const; void setBriefName(const QString& str); QString getBriefName(void) const; void setPatch(unsigned int patch); // -1: percussion unsigned int getPatch() const; void setChannel(int channel); int getChannel() const; void setShowName(bool show); bool getShowName() const; void setShowBriefName(bool show); bool getShowBriefName() const; void setMute(bool mute); bool getMute() const; void setSolo(bool solo); bool getSolo() const; void setShowKeyEachLine(bool show); bool getShowKeyEachLine() const; void setVoiceCount(int voices); int getVoiceCount() const; void addVoice(Voice* voice); QList getVoices() const; void setShowTranspose(bool show); bool getShowTranspose() const; void setTranspose(int transpose); int getTranspose() const; void setNoteShift(int shift); int getNoteShift() const; void setStartClef(int clef/*in ClefType*/); ClefType getStartClef() const; void setTransposeClef(int clef); int getTansposeClef() const; void setStartKey(int key/*in KeyType*/); int getStartKey() const; void setDisplayPercent(unsigned int percent/*25~100*/); unsigned int getDisplayPercent() const; void setShowLegerLine(bool show); bool getShowLegerLine() const; void setShowClef(bool show); bool getShowClef() const; void setShowTimeSignature(bool show); bool getShowTimeSignature() const; void setShowKeySignature(bool show); bool getShowKeySignature() const; void setShowBarline(bool show); bool getShowBarline() const; void setFillWithRest(bool fill); bool getFillWithRest() const; void setFlatTail(bool flat); bool getFlatTail() const; void setShowClefEachLine(bool show); bool getShowClefEachLine() const; struct DrumNode { int line_; int headType_; int pitch_; int voice_; public: DrumNode():line_(0), headType_(0), pitch_(0), voice_(0){} }; void addDrum(const DrumNode& node); QList getDrumKit() const; void clear(void); ///////////////////////////////////////////////// void setPart(int part); int getPart() const; private: int number_; QString name_; QString briefName_; unsigned int patch_; int channel_; int transpose_; bool showTranspose_; int noteShift_; int startClef_; int transposeClef_; unsigned int displayPercent_; int startKey_; int voiceCount_; QList voices_; bool showName_; bool showBriefName_; bool showKeyEachLine_; bool showLegerLine_; bool showClef_; bool showTimeSignature_; bool showKeySignature_; bool showBarline_; bool showClefEachLine_; bool fillWithRest_; bool flatTail_; bool mute_; bool solo_; QList drumKit_; ////////////////////////////// int part_; }; class Page { public: Page(); ~Page(){} public: void setBeginLine(int line); int getBeginLine() const; void setLineCount(int count); int getLineCount() const; void setLineInterval(int interval); // between system int getLineInterval() const; void setStaffInterval(int interval); int getStaffInterval() const; void setStaffInlineInterval(int interval); // between treble-bass staff int getStaffInlineInterval() const; void setLineBarCount(int count); int getLineBarCount() const; void setPageLineCount(int count); int getPageLineCount() const; void setLeftMargin(int margin); int getLeftMargin() const; void setTopMargin(int margin); int getTopMargin() const; void setRightMargin(int margin); int getRightMargin() const; void setBottomMargin(int margin); int getBottomMargin() const; void setPageWidth(int width); int getPageWidth() const; void setPageHeight(int height); int getPageHeight() const; private: int beginLine_; int lineCount_; int lineInterval_; int staffInterval_; int staffInlineInterval_; int lineBarCount_; int pageLineCount_; int leftMargin_; int topMargin_; int rightMargin_; int bottomMargin_; int pageWidth_; int pageHeight_; }; class Line { public: Line(); ~Line(); public: void addStaff(Staff* staff); int getStaffCount() const; Staff* getStaff(int idx) const; void setBeginBar(unsigned int bar); unsigned int getBeginBar() const; void setBarCount(unsigned int count); unsigned int getBarCount() const; void setYOffset(int offset); int getYOffset() const; void setLeftXOffset(int offset); int getLeftXOffset() const; void setRightXOffset(int offset); int getRightXOffset() const; private: QList staffs_; unsigned int beginBar_; unsigned int barCount_; int yOffset_; int leftXOffset_; int rightXOffset_; }; class Staff : public OffsetElement { public: Staff(); virtual ~Staff(){} public: void setClefType(int clef); ClefType getClefType() const; void setKeyType(int key); int getKeyType() const; void setVisible(bool visible); bool setVisible() const; void setGroupType(GroupType type); GroupType getGroupType() const; void setGroupStaffCount(int count); int getGroupStaffCount() const; private: ClefType clef_; int key_; bool visible_; GroupType groupType_; int groupStaffCount_; }; /////////////////////////////////////////////////////////////////////////////// class Note : public LineElement { public: Note(); virtual ~Note(){} public: void setIsRest(bool rest); bool getIsRest() const; void setNote(unsigned int note); unsigned int getNote() const; void setAccidental(int type); //AccidentalType AccidentalType getAccidental() const; void setShowAccidental(bool show); bool getShowAccidental() const; void setOnVelocity(unsigned int velocity); unsigned int getOnVelocity() const; void setOffVelocity(unsigned int velocity); unsigned int getOffVelocity() const; void setHeadType(int type); //NoteHeadType NoteHeadType getHeadType() const; void setTiePos(int tiePos); TiePos getTiePos() const; void setOffsetStaff(int offset); // cross staff notes int getOffsetStaff() const; void setShow(bool show); bool getShow() const; void setOffsetTick(int offset); int getOffsetTick() const; private: bool rest_; unsigned int note_; AccidentalType accidental_; bool showAccidental_; unsigned int onVelocity_; unsigned int offVelocity_; NoteHeadType headType_; TiePos tiePos_; int offsetStaff_; bool show_; int offsetTick_;//for playback }; class Articulation : public OffsetElement { public: Articulation(); virtual ~Articulation(){} public: void setArtType(int type);//ArticulationType ArticulationType getArtType() const; void setPlacementAbove(bool above); bool getPlacementAbove() const; // for midi bool willAffectNotes() const; static bool isTrill(ArticulationType type); // for xml enum XmlType { Xml_Articulation, Xml_Technical, Xml_Arpeggiate, Xml_Ornament, Xml_Fermata, Xml_Direction, Xml_Unknown }; XmlType getXmlType() const; // sound setting bool getChangeSoundEffect() const; void setSoundEffect(int soundFrom, int soundTo); QPair getSoundEffect() const; bool getChangeLength() const; void setLengthPercentage(int percentage); int getLengthPercentage() const; bool getChangeVelocity() const; enum VelocityType { Velocity_Offset, Velocity_SetValue, Velocity_Percentage }; void setVelocityType(VelocityType type); VelocityType getVelocityType() const; void setVelocityValue(int value); int getVelocityValue() const; bool getChangeExtraLength() const; void setExtraLength(int length); int getExtraLength() const; // trill enum TrillInterval { TrillInterval_Diatonic = 0, TrillInterval_Chromatic, TrillInterval_Whole }; void setTrillInterval(int interval); TrillInterval getTrillInterval() const; void setAuxiliaryFirst(bool first); bool getAuxiliaryFirst() const; void setTrillRate(NoteType rate); NoteType getTrillRate() const; void setTrillNoteLength(int length); int getTrillNoteLength() const; enum AccelerateType { Accelerate_None = 0 , Accelerate_Slow, Accelerate_Normal, Accelerate_Fast }; void setAccelerateType(int type); AccelerateType getAccelerateType() const; private: ArticulationType type_; bool above_; bool changeSoundEffect_; QPair soundEffect_; bool changeLength_; int lengthPercentage_; bool changeVelocity_; VelocityType velocityType_; int velocityValue_; bool changeExtraLength_; int extraLength_; // trill TrillInterval trillInterval_; bool auxiliaryFirst_; NoteType trillRate_; int trillNoteLength_; AccelerateType accelerateType_; }; class NoteContainer : public MusicData, public LengthElement { public: NoteContainer(); virtual ~NoteContainer(); public: void setIsGrace(bool grace); bool getIsGrace() const; void setIsCue(bool cue); bool getIsCue() const; void setIsRest(bool rest/*or note*/); bool getIsRest() const; void setIsRaw(bool raw); bool getIsRaw() const; void setNoteType(NoteType type); NoteType getNoteType() const; void setDot(int dot); int getDot() const; void setGraceNoteType(NoteType type); NoteType getGraceNoteType() const; void setInBeam(bool in); bool getInBeam() const; void setStemUp(bool up); bool getStemUp(void) const; void setShowStem(bool show); bool getShowStem() const; void setStemLength(int line); int getStemLength() const; void setTuplet(int tuplet); int getTuplet() const; void setSpace(int space); int getSpace() const; void addNoteRest(Note* note); QList getNotesRests() const; void addArticulation(Articulation* art); QList getArticulations() const; void setNoteShift(int octave); int getNoteShift() const; int getOffsetStaff() const; int getDuration() const; private: bool grace_; bool cue_; bool rest_; bool raw_; NoteType noteType_; int dot_; NoteType graceNoteType_; int tuplet_; int space_; bool inBeam_; bool stemUp_; bool showStem_; int stemLength_; // line count span int noteShift_; QList notes_; QList articulations_; }; class Beam : public MusicData, public PairEnds { public: Beam(); virtual ~Beam(){} public: void setIsGrace(bool grace); bool getIsGrace() const; void addLine(const MeasurePos& startMp, const MeasurePos& endMp); const QList > getLines() const; private: bool grace_; QList > lines_; }; class Tie : public MusicData, public PairEnds { public: Tie(); virtual ~Tie(){} public: void setShowOnTop(bool top); bool getShowOnTop() const; void setNote(int note);// note value tie point to int getNote() const; void setHeight(int height); int getHeight() const; private: bool showOnTop_; int note_; int height_; }; class Glissando : public MusicData, public PairEnds { public: Glissando(); virtual ~Glissando(){} public: void setStraightWavy(bool straight); bool getStraightWavy() const; void setText(const QString& text); QString getText() const; void setLineThick(int thick); int getLineThick() const; private: bool straight_; QString text_; int lineThick_; }; class Decorator : public MusicData { public: Decorator(); virtual ~Decorator(){} public: enum DecoratorType { Decorator_Dotted_Barline = 0, Decorator_Articulation }; void setDecoratorType(DecoratorType type); DecoratorType getDecoratorType() const; void setArticulationType(ArticulationType type); ArticulationType getArticulationType() const; private: DecoratorType decoratorType_; ArticulationType artType_; }; class MeasureRepeat : public MusicData { public: MeasureRepeat(); virtual ~MeasureRepeat(){} public: void setSingleRepeat(bool single); // false : double bool getSingleRepeat() const; private: bool singleRepeat_; }; class Tuplet : public MusicData, public PairEnds { public: Tuplet(); virtual ~Tuplet(); public: void setTuplet(int tuplet=3); int getTuplet() const; void setSpace(int space=2); int getSpace() const; void setHeight(int height); int getHeight() const; void setNoteType(NoteType type); NoteType getNoteType() const; OffsetElement* getMarkHandle() const; private: int tuplet_; int space_; int height_; NoteType noteType_; OffsetElement* mark_; }; class Harmony : public MusicData, public LengthElement { public: Harmony(); virtual ~Harmony(){} public: void setHarmonyType(HarmonyType type); HarmonyType getHarmonyType() const; void setRoot(int root=0);//C int getRoot() const; void setBass(int bass); int getBass() const; void setBassOnBottom(bool on); bool getBassOnBottom() const; void setAngle(int angle); int getAngle() const; private: HarmonyType harmonyType_; int root_; int bass_; bool bassOnBottom_; int angle_; }; class Clef : public MusicData, public LineElement { public: Clef(); virtual ~Clef(){} public: void setClefType(int type); // ClefType ClefType getClefType() const; private: ClefType clefType_; }; class Lyric : public MusicData { public: Lyric(); virtual ~Lyric(){} public: void setLyric(const QString& lyricText); QString getLyric() const; void setVerse(int verse); int getVerse() const; private: QString lyric_; int verse_; }; class Slur: public MusicData, public PairEnds { public: Slur(); virtual ~Slur(); public: void setContainerCount(int count); // span int getContainerCount() const; void setShowOnTop(bool top); bool getShowOnTop() const; OffsetElement* getHandle2() const; OffsetElement* getHandle3() const; void setNoteTimePercent(int percent); // 50% ~ 200% int getNoteTimePercent() const; private: int containerCount_; bool showOnTop_; int noteTimePercent_; OffsetElement* handle_2_; OffsetElement* handle_3_; }; class Dynamics: public MusicData { public: Dynamics(); virtual ~Dynamics() {} public: void setDynamicsType(int type);//DynamicsType DynamicsType getDynamicsType() const; void setIsPlayback(bool play); bool getIsPlayback() const; void setVelocity(int vel); int getVelocity() const; private: DynamicsType dynamicsType_; bool playback_; int velocity_; }; class WedgeEndPoint: public MusicData { public: WedgeEndPoint(); virtual ~WedgeEndPoint() {} public: void setWedgeType(WedgeType type); WedgeType getWedgeType() const; void setHeight(int height); int getHeight() const; void setWedgeStart(bool wedgeStart); bool getWedgeStart() const; private: int height_; WedgeType wedgeType_; bool wedgeStart_; }; class Wedge: public MusicData { public: Wedge(); virtual ~Wedge() {} public: void setWedgeType(WedgeType type); WedgeType getWedgeType() const; void setHeight(int height); int getHeight() const; private: int height_; WedgeType wedgeType_; }; class Pedal: public MusicData, public PairEnds { public: Pedal(); virtual ~Pedal(); public: void setHalf(bool half); bool getHalf() const; void setIsPlayback(bool playback); bool getIsPlayback() const; void setPlayOffset(int offset); // -127~127 int getPlayOffset() const; OffsetElement* getPedalHandle() const; //only on half pedal private: bool half_; bool playback_; int playOffset_; OffsetElement* pedalHandle_; }; class KuoHao: public MusicData, public PairEnds { public: KuoHao(); virtual ~KuoHao() {} public: void setHeight(int height); int getHeight() const; void setKuohaoType(int type);// KuoHaoType KuoHaoType getKuohaoType() const; private: int height_; KuoHaoType kuohaoType_; }; class Expressions: public MusicData { public: Expressions(); virtual ~Expressions() {} public: void setText(const QString& str); QString getText() const; private: QString text_; }; class HarpPedal: public MusicData { public: HarpPedal(); virtual ~HarpPedal() {} public: void setShowType(int type);//0:graph, 1:char, 2:char cut, 3:change int getShowType() const; void setShowCharFlag(int flag);//each bit is a bool, total 7 bools int getShowCharFlag() const; private: int showType_; int showCharFlag_; }; class OctaveShift: public MusicData, public LengthElement { public: OctaveShift(); virtual ~OctaveShift() {} public: void setOctaveShiftType(int type); OctaveShiftType getOctaveShiftType() const; int getNoteShift() const; void setEndTick(int tick); int getEndTick() const; private: OctaveShiftType octaveShiftType_; OctaveShiftPosition octaveShiftPosition_; int endTick_; }; class OctaveShiftEndPoint: public MusicData, public LengthElement { public: OctaveShiftEndPoint(); virtual ~OctaveShiftEndPoint() {} public: void setOctaveShiftType(int type); OctaveShiftType getOctaveShiftType() const; void setOctaveShiftPosition(int position); OctaveShiftPosition getOctaveShiftPosition() const; void setEndTick(int tick); int getEndTick() const; private: OctaveShiftType octaveShiftType_; OctaveShiftPosition octaveShiftPosition_; int endTick_; }; class MultiMeasureRest: public MusicData { public: MultiMeasureRest(); virtual ~MultiMeasureRest() {} public: void setMeasureCount(int count); int getMeasureCount() const; private: int measureCount_; }; class Tempo: public MusicData { public: Tempo(); virtual ~Tempo() {} public: void setLeftNoteType(int type);//NoteType NoteType getLeftNoteType() const; void setShowMark(bool show); bool getShowMark() const; void setShowBeforeText(bool show); bool getShowBeforeText() const; void setShowParenthesis(bool show); bool getShowParenthesis() const; void setTypeTempo(int tempo); //0x2580 = 96.00 int getTypeTempo() const; int getQuarterTempo() const; void setLeftText(const QString& str);// string at left of the mark QString getLeftText() const; void setRightText(const QString& str); QString getRightText() const; void setSwingEighth(bool swing); bool getSwingEighth() const; void setRightNoteType(int type); int getRightNoteType() const; private: int leftNoteType_; bool showMark_; bool showText_; bool showParenthesis_; int typeTempo_; QString leftText_; QString rightText_; bool swingEighth_; int rightNoteType_; }; class Text: public MusicData, public LengthElement { public: Text(); virtual ~Text() {} public: enum TextType { Text_Rehearsal, Text_SystemText, Text_MeasureText }; void setTextType(TextType type); TextType getTextType() const; void setHorizontalMargin(int margin); int getHorizontalMargin() const; void setVerticalMargin(int margin); int getVerticalMargin() const; void setLineThick(int thick); int getLineThick() const; void setText(const QString& text); QString getText() const; void setWidth(int width); int getWidth() const; void setHeight(int height); int getHeight() const; private: TextType textType_; int horiMargin_; int vertMargin_; int lineThick_; QString text_; int width_; int height_; }; /////////////////////////////////////////////////////////////////////////////// class TimeSignature: public MusicData { public: TimeSignature(); virtual ~TimeSignature() {} public: void setNumerator(int numerator); int getNumerator() const; void setDenominator(int denominator); int getDenominator() const; void setIsSymbol(bool symbol); //4/4:common, 2/2:cut bool getIsSymbol() const; void setBeatLength(int length); // tick int getBeatLength() const; void setBarLength(int length); // tick int getBarLength() const; void addBeat(int startUnit, int lengthUnit, int startTick); void endAddBeat(); int getUnits() const; void setReplaceFont(bool replace); bool getReplaceFont() const; void setShowBeatGroup(bool show); bool getShowBeatGroup() const; void setGroupNumerator1(int numerator); void setGroupNumerator2(int numerator); void setGroupNumerator3(int numerator); void setGroupDenominator1(int denominator); void setGroupDenominator2(int denominator); void setGroupDenominator3(int denominator); void setBeamGroup1(int count); void setBeamGroup2(int count); void setBeamGroup3(int count); void setBeamGroup4(int count); void set16thBeamCount(int count); void set32thBeamCount(int count); private: int numerator_; int denominator_; bool isSymbol_; int beatLength_; int barLength_; struct BeatNode { int startUnit_; int lengthUnit_; int startTick_; BeatNode() : startUnit_(0), lengthUnit_(0), startTick_(0) { } }; QList beats_; int barLengthUnits_; bool replaceFont_; bool showBeatGroup_; int groupNumerator1_; int groupNumerator2_; int groupNumerator3_; int groupDenominator1_; int groupDenominator2_; int groupDenominator3_; int beamGroup1_; int beamGroup2_; int beamGroup3_; int beamGroup4_; int beamCount16th_; int beamCount32th_; }; class Key: public MusicData { public: Key(); virtual ~Key() {} public: void setKey(int key); //C=0x0, G=0x8, C#=0xE, F=0x1, Db=0x7 int getKey() const; bool getSetKey() const; void setPreviousKey(int key); int getPreviousKey() const; void setSymbolCount(int count); int getSymbolCount() const; private: int key_; bool set_; int previousKey_; int symbolCount_; }; class RepeatSymbol: public MusicData { public: RepeatSymbol(); virtual ~RepeatSymbol() {} public: void setText(const QString& text); QString getText() const; void setRepeatType(int repeatType); RepeatType getRepeatType() const; private: QString text_; RepeatType repeatType_; }; class NumericEnding: public MusicData, public PairEnds { public: NumericEnding(); virtual ~NumericEnding(); public: OffsetElement* getNumericHandle() const; void setHeight(int height); int getHeight() const; void setText(const QString& text); QString getText() const; QList getNumbers() const; int getJumpCount() const; private: int height_; QString text_; OffsetElement* numericHandle_; }; class BarNumber: public MusicData { public: BarNumber(); virtual ~BarNumber() {} public: void setIndex(int index); int getIndex() const; void setShowOnParagraphStart(bool show); bool getShowOnParagraphStart() const; void setAlign(int align);// 0:left, 1:center, 2:right int getAlign() const; void setShowFlag(int flag); // 0:page, 1:staff, 2:bar, 3:none int getShowFlag() const; void setShowEveryBarCount(int count); int getShowEveryBarCount() const; void setPrefix(const QString& str); QString getPrefix() const; private: int index_; bool showOnParagraphStart_; int align_; int showFlag_; int barRange_; QString prefix_; }; /////////////////////////////////////////////////////////////////////////////// // MIDI class MidiController: public MidiData { public: MidiController(); virtual ~MidiController() {} public: void setController(int number); int getController() const; void setValue(int value); int getValue() const; private: int controller_; int value_; }; class MidiProgramChange: public MidiData { public: MidiProgramChange(); virtual ~MidiProgramChange() {} public: void setPatch(int patch); int getPatch() const; private: int patch_; }; class MidiChannelPressure: public MidiData { public: MidiChannelPressure(); virtual ~MidiChannelPressure() {} public: void setPressure(int pressure); int getPressure() const; private: int pressure_; }; class MidiPitchWheel: public MidiData { public: MidiPitchWheel(); virtual ~MidiPitchWheel() {} public: void setValue(int value); int getValue() const; private: int value_; }; /////////////////////////////////////////////////////////////////////////////// class Measure: public LengthElement { public: Measure(int index = 0); virtual ~Measure(); private: Measure(); public: BarNumber* getBarNumber() const; TimeSignature* getTime() const; void setLeftBarline(int barline/*in BarlineType*/); BarlineType getLeftBarline() const; void setRightBarline(int barline/*in BarlineType*/); BarlineType getRightBarline() const; // set when rightBarline == Baline_Backward void setBackwardRepeatCount(int repeatCount); int getBackwardRepeatCount() const; void setTypeTempo(double tempo); double getTypeTempo() const; void setIsPickup(bool pickup); bool getIsPickup() const; void setIsMultiMeasureRest(bool rest); bool getIsMultiMeasureRest() const; void setMultiMeasureRestCount(int count); int getMultiMeasureRestCount() const; private: void clear(); BarNumber* barNumber_; TimeSignature* time_; BarlineType leftBarline_; BarlineType rightBarline_; int repeatCount_; double typeTempo_; // based on some type bool pickup_; bool multiMeasureRest_; int multiMeasureRestCount_; }; class MeasureData { public: MeasureData(); ~MeasureData(); public: Clef* getClef() const; Key* getKey() const; void addNoteContainer(NoteContainer* ptr); QList getNoteContainers() const; // put Tempo, Text, RepeatSymbol to MeasureData at part=0 && staff=0 void addMusicData(MusicData* ptr); // if type==MusicData_None, return all QList getMusicDatas(MusicDataType type);//MusicXml: note|direction|harmony // put NumericEnding to MeasureData at part=0 && staff=0 void addCrossMeasureElement(MusicData* ptr, bool start); enum PairType { PairType_Start, PairType_Stop, PairType_All }; QList getCrossMeasureElements(MusicDataType type, PairType pairType); // for midi void addMidiData(MidiData* ptr); QList getMidiDatas(MidiType type); private: Key* key_; Clef* clef_; QList musicDatas_; QList noteContainers_; QList > crossMeasureElements_; QList midiDatas_; }; // StreamHandle class StreamHandle { public: StreamHandle(unsigned char* p, int size); virtual ~StreamHandle(); private: StreamHandle(); public: virtual bool read(char* buff, int size); virtual bool write(char* buff, int size); private: int size_; int curPos_; unsigned char* point_; }; // Block.h // base block, or resizable block in ove to store data class Block { public: Block(); explicit Block(unsigned int size); virtual ~Block() { } public: // size > 0, check this in use code virtual void resize(unsigned int count); const unsigned char* data() const; unsigned char* data(); unsigned int size() const; bool operator ==(const Block& block) const; bool operator !=(const Block& block) const; bool toBoolean() const; unsigned int toUnsignedInt() const; int toInt() const; QByteArray toStrByteArray() const; // string QByteArray fixedSizeBufferToStrByteArray() const; // string private: void doResize(unsigned int count); private: // char [-128, 127], unsigned char [0, 255] QList data_; }; class FixedBlock: public Block { public: explicit FixedBlock(unsigned int count); virtual ~FixedBlock() { } private: FixedBlock(); private: // can't resize virtual void resize(unsigned int count); }; /////////////////////////////////////////////////////////////////////////////// // 4 byte block in ove to store size class SizeBlock: public FixedBlock { public: SizeBlock(); virtual ~SizeBlock() { } public: // void fromUnsignedInt(unsigned int count) ; unsigned int toSize() const; }; // 4 bytes block in ove to store name class NameBlock: public FixedBlock { public: NameBlock(); virtual ~NameBlock() { } public: // ingore data more than 4 bytes bool isEqual(const QString& name) const; }; // 2 bytes block in ove to store count class CountBlock: public FixedBlock { public: CountBlock(); virtual ~CountBlock() { } public: // void setValue(unsigned short count) ; unsigned short toCount() const; }; // Chunk.h // content : name class Chunk { public: Chunk(); virtual ~Chunk() { } public: const static QString TrackName; const static QString PageName; const static QString LineName; const static QString StaffName; const static QString MeasureName; const static QString ConductName; const static QString BdatName; NameBlock getName() const; protected: NameBlock nameBlock_; }; // content : name / size / data class SizeChunk: public Chunk { public: SizeChunk(); virtual ~SizeChunk(); public: SizeBlock* getSizeBlock() const; Block* getDataBlock() const; const static unsigned int version3TrackSize; protected: SizeBlock* sizeBlock_; Block* dataBlock_; }; // content : name / count class GroupChunk: public Chunk { public: GroupChunk(); virtual ~GroupChunk(); public: CountBlock* getCountBlock() const; protected: CountBlock* childCount_; }; // ChunkParse.h class BasicParse { public: BasicParse(OveSong* ove); virtual ~BasicParse(); private: BasicParse(); public: void setNotify(IOveNotify* notify); virtual bool parse(); protected: bool readBuffer(Block& placeHolder, unsigned int size); bool jump(int offset); void messageOut(const QString& str); protected: OveSong* ove_; StreamHandle* handle_; IOveNotify* notify_; }; /////////////////////////////////////////////////////////////////////////////// class OvscParse: public BasicParse { public: OvscParse(OveSong* ove); virtual ~OvscParse(); public: void setOvsc(SizeChunk* chunk); virtual bool parse(); private: SizeChunk* chunk_; }; class TrackParse: public BasicParse { public: TrackParse(OveSong* ove); virtual ~TrackParse(); public: void setTrack(SizeChunk* chunk); virtual bool parse(); private: SizeChunk* chunk_; }; class GroupParse: BasicParse { public: GroupParse(OveSong* ove); virtual ~GroupParse(); public: void addSizeChunk(SizeChunk* sizeChunk); virtual bool parse(); private: QList sizeChunks_; }; class PageGroupParse: public BasicParse { public: PageGroupParse(OveSong* ove); virtual ~PageGroupParse(); public: void addPage(SizeChunk* chunk); virtual bool parse(); private: bool parsePage(SizeChunk* chunk, Page* page); private: QList pageChunks_; }; class StaffCountGetter: public BasicParse { public: StaffCountGetter(OveSong* ove); virtual ~StaffCountGetter() {} public: unsigned int getStaffCount(SizeChunk* chunk); }; class LineGroupParse: public BasicParse { public: LineGroupParse(OveSong* ove); virtual ~LineGroupParse(); public: void setLineGroup(GroupChunk* chunk); void addLine(SizeChunk* chunk); void addStaff(SizeChunk* chunk); virtual bool parse(); private: bool parseLine(SizeChunk* chunk, Line* line); bool parseStaff(SizeChunk* chunk, Staff* staff); private: GroupChunk* chunk_; QList lineChunks_; QList staffChunks_; }; class BarsParse: public BasicParse { public: BarsParse(OveSong* ove); virtual ~BarsParse(); public: void addMeasure(SizeChunk* chunk); void addConduct(SizeChunk* chunk); void addBdat(SizeChunk* chunk); virtual bool parse(); private: bool parseMeas(Measure* measure, SizeChunk* chunk); bool parseCond(Measure* measure, MeasureData* measureData, SizeChunk* chunk); bool parseBdat(Measure* measure, MeasureData* measureData, SizeChunk* chunk); bool getCondElementType(unsigned int byteData, CondType& type); bool getBdatElementType(unsigned int byteData, BdatType& type); // COND bool parseTimeSignature(Measure* measure, int length); bool parseTimeSignatureParameters(Measure* measure, int length); bool parseRepeatSymbol(MeasureData* measureData, int length); bool parseNumericEndings(MeasureData* measureData, int length); bool parseTempo(MeasureData* measureData, int length); bool parseBarNumber(Measure* measure, int length); bool parseText(MeasureData* measureData, int length); bool parseBarlineParameters(Measure* measure, int length); // BDAT bool parseNoteRest(MeasureData* measureData, int length, BdatType type); bool parseBeam(MeasureData* measureData, int length); bool parseTie(MeasureData* measureData, int length); bool parseTuplet(MeasureData* measureData, int length); bool parseHarmony(MeasureData* measureData, int length); bool parseClef(MeasureData* measureData, int length); bool parseLyric(MeasureData* measureData, int length); bool parseSlur(MeasureData* measureData, int length); bool parseGlissando(MeasureData* measureData, int length); bool parseDecorators(MeasureData* measureData, int length); bool parseDynamics(MeasureData* measureData, int length); bool parseWedge(MeasureData* measureData, int length); bool parseKey(MeasureData* measureData, int length); bool parsePedal(MeasureData* measureData, int length); bool parseKuohao(MeasureData* measureData, int length); bool parseExpressions(MeasureData* measureData, int length); bool parseHarpPedal(MeasureData* measureData, int length); bool parseMultiMeasureRest(MeasureData* measureData, int length); bool parseHarmonyGuitarFrame(MeasureData* measureData, int length); bool parseOctaveShift(MeasureData* measureData, int length); bool parseMidiController(MeasureData* measureData, int length); bool parseMidiProgramChange(MeasureData* measureData, int length); bool parseMidiChannelPressure(MeasureData* measureData, int length); bool parseMidiPitchWheel(MeasureData* measureData, int length); bool parseSizeBlock(int length); bool parseMidiCommon(MidiData* ptr); bool parseCommonBlock(MusicData* ptr); bool parseOffsetCommonBlock(MusicData* ptr); bool parsePairLinesBlock(PairEnds* ptr); //size==2 bool parseOffsetElement(OffsetElement* ptr);//size==2 private: QList measureChunks_; QList conductChunks_; QList bdatChunks_; }; class LyricChunkParse: public BasicParse { public: LyricChunkParse(OveSong* ove); virtual ~LyricChunkParse() {} public: void setLyricChunk(SizeChunk* chunk); virtual bool parse(); private: struct LyricInfo { int track_; int measure_; int verse_; int voice_; int wordCount_; int lyricSize_; QString name_; QString lyric_; int font_; int fontSize_; int fontStyle_; LyricInfo() : track_(0), measure_(0), verse_(0), voice_(0), wordCount_(0), lyricSize_(0), name_(QString()), lyric_(QString()), font_(0), fontSize_(12), fontStyle_(0) {} }; void processLyricInfo(const LyricInfo& info); private: SizeChunk* chunk_; }; class TitleChunkParse: public BasicParse { public: TitleChunkParse(OveSong* ove); virtual ~TitleChunkParse() {} public: void setTitleChunk(SizeChunk* chunk); virtual bool parse(); private: void addToOve(const QString& str, unsigned int titleType); private: unsigned int titleType_; unsigned int annotateType_; unsigned int writerType_; unsigned int copyrightType_; unsigned int headerType_; unsigned int footerType_; SizeChunk* chunk_; }; // OveOrganizer.h class OveOrganizer { public: OveOrganizer(OveSong* ove) ; virtual ~OveOrganizer(){} public: void organize() ; private: void organizeAttributes() ; void organizeTracks() ; void organizeMeasures() ; void organizeMeasure(int part, int track, Measure* measure, MeasureData* measureData) ; void organizeContainers(int part, int track, Measure* measure, MeasureData* measureData) ; void organizeMusicDatas(int part, int track, Measure* measure, MeasureData* measureData) ; void organizeCrossMeasureElements(int part, int track, Measure* measure, MeasureData* measureData) ; void organizePairElement(MusicData* data, int part, int track, Measure* measure, MeasureData* measureData) ; void organizeOctaveShift(OctaveShift* octave, Measure* measure, MeasureData* measureData) ; void organizeWedge(Wedge* wedge, int part, int track, Measure* measure, MeasureData* measureData) ; private: OveSong* ove_ ; }; // OveSerialize.h class StreamHandle; class Block; class NameBlock; class Chunk; class SizeChunk; class GroupChunk; class OveSerialize: public IOVEStreamLoader { public: OveSerialize(); virtual ~OveSerialize(); public: virtual void setOve(OveSong* ove); virtual void setFileStream(unsigned char* buffer, unsigned int size); virtual void setNotify(IOveNotify* notify); virtual bool load(void); virtual void release(); private: bool readNameBlock(NameBlock& nameBlock); bool readChunkName(Chunk* chunk, const QString& name); bool readSizeChunk(SizeChunk* sizeChunk); // contains a SizeChunk and data buffer bool readDataChunk(Block* block, unsigned int size); bool readGroupChunk(GroupChunk* groupChunk); bool readHeader(); bool readHeadData(SizeChunk* ovscChunk); bool readTracksData(); bool readPagesData(); bool readLinesData(); bool readBarsData(); bool readOveEnd(); void messageOutError(); void messageOut(const QString& str); private: OveSong* ove_; StreamHandle* streamHandle_; IOveNotify* notify_; }; /*template inline void deleteVector(QList& vec) { for (int i=0; i(const MeasurePos& mp) const { return !(*this <= mp); } bool MeasurePos::operator >=(const MeasurePos& mp) const { return !(*this < mp); } /////////////////////////////////////////////////////////////////////////////// PairElement::PairElement() { start_ = new MeasurePos(); stop_ = new MeasurePos(); } PairElement::~PairElement(){ delete start_; delete stop_; } MeasurePos* PairElement::start() const { return start_; } MeasurePos* PairElement::stop() const { return stop_; } /////////////////////////////////////////////////////////////////////////////// PairEnds::PairEnds() { leftLine_ = new LineElement(); rightLine_ = new LineElement(); leftShoulder_ = new OffsetElement(); rightShoulder_ = new OffsetElement(); } PairEnds::~PairEnds(){ delete leftLine_; delete rightLine_; delete leftShoulder_; delete rightShoulder_; } LineElement* PairEnds::getLeftLine() const { return leftLine_; } LineElement* PairEnds::getRightLine() const { return rightLine_; } OffsetElement* PairEnds::getLeftShoulder() const { return leftShoulder_; } OffsetElement* PairEnds::getRightShoulder() const { return rightShoulder_; } /////////////////////////////////////////////////////////////////////////////// LineElement::LineElement() { line_ = 0; } void LineElement::setLine(int line) { line_ = line; } int LineElement::getLine(void) const { return line_; } /////////////////////////////////////////////////////////////////////////////// OffsetElement::OffsetElement() { xOffset_ = 0; yOffset_ = 0; } void OffsetElement::setXOffset(int offset) { xOffset_ = offset; } int OffsetElement::getXOffset() const { return xOffset_; } void OffsetElement::setYOffset(int offset) { yOffset_ = offset; } int OffsetElement::getYOffset() const { return yOffset_; } /////////////////////////////////////////////////////////////////////////////// LengthElement::LengthElement() { length_ = 0; } void LengthElement::setLength(int length) { length_ = length; } int LengthElement::getLength() const { return length_; } /////////////////////////////////////////////////////////////////////////////// MusicData::MusicData() { musicDataType_ = MusicData_None; show_ = true; color_ = 0; voice_ = 0; } MusicDataType MusicData::getMusicDataType() const { return musicDataType_; } MusicData::XmlDataType MusicData::getXmlDataType(MusicDataType type) { XmlDataType xmlType = None; switch (type) { case MusicData_Measure_Repeat: { xmlType = Attributes; break; } case MusicData_Beam: { xmlType = NoteBeam; break; } case MusicData_Slur: case MusicData_Glissando: case MusicData_Tuplet: case MusicData_Tie: { xmlType = Notations; break; } case MusicData_Text: case MusicData_Repeat: case MusicData_Wedge: case MusicData_Dynamics: case MusicData_Pedal: case MusicData_OctaveShift_EndPoint: { xmlType = Direction; break; } default: { xmlType = None; break; } } return xmlType; } /*bool MusicData::get_is_pair_element(MusicDataType type) { bool pair = false; switch ( type ) { case MusicData_Numeric_Ending : case MusicData_Measure_Repeat : case MusicData_Wedge : case MusicData_OctaveShift : //case MusicData_OctaveShift_EndPoint : case MusicData_Pedal : case MusicData_Beam : case MusicData_Glissando : case MusicData_Slur : case MusicData_Tie : case MusicData_Tuplet : { pair = true; break; } default: break; } return pair; }*/ void MusicData::setShow(bool show) { show_ = show; } bool MusicData::getShow() const { return show_; } void MusicData::setColor(unsigned int color) { color_ = color; } unsigned int MusicData::getColor() const { return color_; } void MusicData::setVoice(unsigned int voice) { voice_ = voice; } unsigned int MusicData::getVoice() const { return voice_; } void MusicData::copyCommonBlock(const MusicData& source) { setTick(source.getTick()); start()->setOffset(source.start()->getOffset()); setColor(source.getColor()); } /////////////////////////////////////////////////////////////////////////////// MidiData::MidiData() { midiType_ = Midi_None; } MidiType MidiData::getMidiType() const { return midiType_; } /////////////////////////////////////////////////////////////////////////////// OveSong::OveSong() : codec_(0) { clear(); } OveSong::~OveSong() { clear(); } void OveSong::setIsVersion4(bool version4){ version4_ = version4; } bool OveSong::getIsVersion4() const { return version4_; } void OveSong::setQuarter(int tick) { quarter_ = tick; } int OveSong::getQuarter(void) const { return quarter_; } void OveSong::setShowPageMargin(bool show){ showPageMargin_ = show; } bool OveSong::getShowPageMargin() const { return showPageMargin_; } void OveSong::setShowTransposeTrack(bool show) { showTransposeTrack = show; } bool OveSong::getShowTransposeTrack() const { return showTransposeTrack; } void OveSong::setShowLineBreak(bool show) { showLineBreak_ = show; } bool OveSong::getShowLineBreak() const { return showLineBreak_; } void OveSong::setShowRuler(bool show) { showRuler_ = show; } bool OveSong::getShowRuler() const { return showRuler_; } void OveSong::setShowColor(bool show) { showColor_ = show; } bool OveSong::getShowColor() const { return showColor_; } void OveSong::setPlayRepeat(bool play) { playRepeat_ = play; } bool OveSong::getPlayRepeat() const { return playRepeat_; } void OveSong::setPlayStyle(PlayStyle style) { playStyle_ = style; } OveSong::PlayStyle OveSong::getPlayStyle() const { return playStyle_; } void OveSong::addTitle(const QString& str) { titles_.push_back(str); } QList OveSong::getTitles(void) const { return titles_; } void OveSong::addAnnotate(const QString& str) { annotates_.push_back(str); } QList OveSong::getAnnotates(void) const { return annotates_; } void OveSong::addWriter(const QString& str) { writers_.push_back(str); } QList OveSong::getWriters(void) const { return writers_; } void OveSong::addCopyright(const QString& str) { copyrights_.push_back(str); } QList OveSong::getCopyrights(void) const { return copyrights_; } void OveSong::addHeader(const QString& str) { headers_.push_back(str); } QList OveSong::getHeaders(void) const { return headers_; } void OveSong::addFooter(const QString& str) { footers_.push_back(str); } QList OveSong::getFooters(void) const { return footers_; } void OveSong::addTrack(Track* ptr) { tracks_.push_back(ptr); } int OveSong::getTrackCount(void) const { return tracks_.size(); } QList OveSong::getTracks() const { return tracks_; } void OveSong::setTrackBarCount(int count) { trackBarCount_ = count; } int OveSong::getTrackBarCount() const { return trackBarCount_; } Track* OveSong::getTrack(int part, int staff) const { int trackId = partStaffToTrack(part, staff); if( trackId >=0 && trackId < (int)tracks_.size() ) { return tracks_[trackId]; } return 0; } bool OveSong::addPage(Page* page) { pages_.push_back(page); return true; } int OveSong::getPageCount() const { return pages_.size(); } Page* OveSong::getPage(int idx) { if( idx>=0 && idx<(int)pages_.size() ) { return pages_[idx]; } return 0; } void OveSong::addLine(Line* ptr) { lines_.push_back(ptr); } int OveSong::getLineCount() const { return lines_.size(); } Line* OveSong::getLine(int idx) const { if( idx >=0 && idx<(int)lines_.size() ) { return lines_[idx]; } return 0; } void OveSong::addMeasure(Measure* ptr) { measures_.push_back(ptr); } int OveSong::getMeasureCount(void) const { return measures_.size(); } Measure* OveSong::getMeasure(int bar) const { if( bar >= 0 && bar < (int)measures_.size() ) { return measures_[bar]; } return 0; } void OveSong::addMeasureData(MeasureData* ptr) { measureDatas_.push_back(ptr); } int OveSong::getMeasureDataCount(void) const { return measureDatas_.size(); } MeasureData* OveSong::getMeasureData(int part, int staff/*=0*/, int bar) const { int trackId = partStaffToTrack(part, staff); int trackBarCount = getTrackBarCount(); if( bar >= 0 && bar < trackBarCount ) { int measureId = trackBarCount * trackId + bar; if( measureId >=0 && measureId < (int)measureDatas_.size() ) { return measureDatas_[measureId]; } } return 0; } MeasureData* OveSong::getMeasureData(int track, int bar) const { int id = trackBarCount_*track + bar; if( id >=0 && id < (int)measureDatas_.size() ) { return measureDatas_[id]; } return 0; } void OveSong::setPartStaffCounts(const QList& partStaffCounts) { //partStaffCounts_.assign(partStaffCounts.begin(), partStaffCounts.end()); for(int i=0; i=0 && part<(int)partStaffCounts_.size() ) { return partStaffCounts_[part]; } return 0; } int OveSong::getPartBarCount() const { return measureDatas_.size() / tracks_.size(); } QPair OveSong::trackToPartStaff(int track) const { QPair partStaff; int i; int staffCount = 0; for( i=0; i track ) { return qMakePair((int)i, track-staffCount); } staffCount += partStaffCounts_[i]; } return qMakePair((int)partStaffCounts_.size(), 0); } int OveSong::partStaffToTrack(int part, int staff) const { int i; unsigned int staffCount = 0; for( i=0; i=0 && staff<(int)partStaffCounts_[i] ) { int trackId = staffCount + staff; if( trackId >=0 && trackId < (int)tracks_.size() ) { return trackId; } } staffCount += partStaffCounts_[i]; } return tracks_.size(); } void OveSong::setTextCodecName(const QString& codecName) { codec_ = QTextCodec::codecForName(codecName.toLatin1()); } QString OveSong::getCodecString(const QByteArray& text) { QString s; if (codec_ == NULL) s = QString(text); else s = codec_->toUnicode(text); return s; } void OveSong::clear(void) { version4_ = true; quarter_ = 480; showPageMargin_ = false; showTransposeTrack = false; showLineBreak_ = false; showRuler_ = false; showColor_ = true; playRepeat_ = true; playStyle_ = Record; annotates_.clear(); copyrights_.clear(); footers_.clear(); headers_.clear(); titles_.clear(); writers_.clear(); // deleteVector(tracks_); for(int i=0; i Track::getVoices() const { return voices_; } void Track::setShowTranspose(bool show) { showTranspose_ = show; } bool Track::getShowTranspose() const { return showTranspose_; } void Track::setTranspose(int transpose) { transpose_ = transpose; } int Track::getTranspose() const { return transpose_; } void Track::setNoteShift(int shift) { noteShift_ = shift; } int Track::getNoteShift() const { return noteShift_; } void Track::setStartClef(int clef/*in Clef*/) { startClef_ = clef; } ClefType Track::getStartClef() const { return (ClefType)startClef_; } void Track::setTransposeClef(int clef) { transposeClef_ = clef; } int Track::getTansposeClef() const { return transposeClef_; } void Track::setStartKey(int key) { startKey_ = key; } int Track::getStartKey() const { return startKey_; } void Track::setDisplayPercent(unsigned int percent/*25~100?*/) { displayPercent_ = percent; } unsigned int Track::getDisplayPercent() const { return displayPercent_; } void Track::setShowLegerLine(bool show) { showLegerLine_ = show; } bool Track::getShowLegerLine() const { return showLegerLine_; } void Track::setShowClef(bool show) { showClef_ = show; } bool Track::getShowClef() const { return showClef_; } void Track::setShowTimeSignature(bool show) { showTimeSignature_ = show; } bool Track::getShowTimeSignature() const { return showTimeSignature_; } void Track::setShowKeySignature(bool show) { showKeySignature_ = show; } bool Track::getShowKeySignature() const { return showKeySignature_; } void Track::setShowBarline(bool show) { showBarline_ = show; } bool Track::getShowBarline() const { return showBarline_; } void Track::setFillWithRest(bool fill) { fillWithRest_ = fill; } bool Track::getFillWithRest() const { return fillWithRest_; } void Track::setFlatTail(bool flat) { flatTail_ = flat; } bool Track::getFlatTail() const { return flatTail_; } void Track::setShowClefEachLine(bool show) { showClefEachLine_ = show; } bool Track::getShowClefEachLine() const { return showClefEachLine_; } void Track::addDrum(const DrumNode& node) { /*DrumNode node; node.line_ = line; node.headType_ = headType; node.pitch_ = pitch; node.voice_ = voice;*/ drumKit_.push_back(node); } QList Track::getDrumKit() const { return drumKit_; } void Track::setPart(int part) { part_ = part; } int Track::getPart() const { return part_; } void Track::clear(void) { number_ = 0; name_ = QString(); patch_ = 0; channel_ = 0; transpose_ = 0; showTranspose_ = false; noteShift_ = 0; startClef_ = Clef_Treble; transposeClef_ = Clef_Treble; displayPercent_ = 100; startKey_ = 0; voiceCount_ = 8; showName_ = true; showBriefName_ = false; showKeyEachLine_ = false; showLegerLine_ = true; showClef_ = true; showTimeSignature_ = true; showKeySignature_ = true; showBarline_ = true; showClefEachLine_ = false; fillWithRest_ = true; flatTail_ = false; mute_ = false; solo_ = false; drumKit_.clear(); part_ = 0; for(int i=0; i= 0 && idx < (int) staffs_.size()) { return staffs_[idx]; } return 0; } void Line::setBeginBar(unsigned int bar) { beginBar_ = bar; } unsigned int Line::getBeginBar() const { return beginBar_; } void Line::setBarCount(unsigned int count) { barCount_ = count; } unsigned int Line::getBarCount() const { return barCount_; } void Line::setYOffset(int offset) { yOffset_ = offset; } int Line::getYOffset() const { return yOffset_; } void Line::setLeftXOffset(int offset) { leftXOffset_ = offset; } int Line::getLeftXOffset() const { return leftXOffset_; } void Line::setRightXOffset(int offset) { rightXOffset_ = offset; } int Line::getRightXOffset() const { return rightXOffset_; } /////////////////////////////////////////////////////////////////////////////// Staff::Staff() { clef_ = Clef_Treble; key_ = 0; visible_ = true; groupType_ = Group_None; groupStaffCount_ = 0; } void Staff::setClefType(int clef) { clef_ = (ClefType) clef; } ClefType Staff::getClefType() const { return clef_; } void Staff::setKeyType(int key) { key_ = key; } int Staff::getKeyType() const { return key_; } void Staff::setVisible(bool visible) { visible_ = visible; } bool Staff::setVisible() const { return visible_; } void Staff::setGroupType(GroupType type){ groupType_ = type; } GroupType Staff::getGroupType() const { return groupType_; } void Staff::setGroupStaffCount(int count) { groupStaffCount_ = count; } int Staff::getGroupStaffCount() const { return groupStaffCount_; } /////////////////////////////////////////////////////////////////////////////// Note::Note() { rest_ = false; note_ = 60; accidental_ = Accidental_Normal; showAccidental_ = false; offVelocity_ = 0x40; onVelocity_ = 0x50; headType_ = NoteHead_Standard; tiePos_ = Tie_None; offsetStaff_ = 0; show_ = true; offsetTick_ = 0; } void Note::setIsRest(bool rest) { rest_ = rest; } bool Note::getIsRest() const { return rest_; } void Note::setNote(unsigned int note) { note_ = note; } unsigned int Note::getNote() const { return note_; } void Note::setAccidental(int type) { accidental_ = (AccidentalType) type; } AccidentalType Note::getAccidental() const { return accidental_; } void Note::setShowAccidental(bool show) { showAccidental_ = show; } bool Note::getShowAccidental() const { return showAccidental_; } void Note::setOnVelocity(unsigned int velocity) { onVelocity_ = velocity; } unsigned int Note::getOnVelocity() const { return onVelocity_; } void Note::setOffVelocity(unsigned int velocity) { offVelocity_ = velocity; } unsigned int Note::getOffVelocity() const { return offVelocity_; } void Note::setHeadType(int type) { headType_ = (NoteHeadType) type; } NoteHeadType Note::getHeadType() const { return headType_; } void Note::setTiePos(int tiePos) { tiePos_ = (TiePos) tiePos; } TiePos Note::getTiePos() const { return tiePos_; } void Note::setOffsetStaff(int offset) { offsetStaff_ = offset; } int Note::getOffsetStaff() const { return offsetStaff_; } void Note::setShow(bool show) { show_ = show; } bool Note::getShow() const { return show_; } void Note::setOffsetTick(int offset) { offsetTick_ = offset; } int Note::getOffsetTick() const { return offsetTick_; } /////////////////////////////////////////////////////////////////////////////// Articulation::Articulation() { type_ = Articulation_Marcato; above_ = true; changeSoundEffect_ = false; changeLength_ = false; changeVelocity_ = false; changeExtraLength_ = false; soundEffect_ = qMakePair(0, 0); lengthPercentage_ = 100; velocityType_ = Velocity_Offset; velocityValue_ = 0; extraLength_ = 0; trillNoteLength_ = 60; trillRate_ = Note_Sixteen; accelerateType_ = Accelerate_None; auxiliaryFirst_ = false; trillInterval_ = TrillInterval_Chromatic; } void Articulation::setArtType(int type) { type_ = (ArticulationType) type; } ArticulationType Articulation::getArtType() const { return type_; } void Articulation::setPlacementAbove(bool above) { above_ = above; } bool Articulation::getPlacementAbove() const { return above_; } bool Articulation::getChangeSoundEffect() const { return changeSoundEffect_; } void Articulation::setSoundEffect(int soundFrom, int soundTo) { soundEffect_ = qMakePair(soundFrom, soundTo); changeSoundEffect_ = true; } QPair Articulation::getSoundEffect() const { return soundEffect_; } bool Articulation::getChangeLength() const { return changeLength_; } void Articulation::setLengthPercentage(int percentage) { lengthPercentage_ = percentage; changeLength_ = true; } int Articulation::getLengthPercentage() const { return lengthPercentage_; } bool Articulation::getChangeVelocity() const { return changeVelocity_; } void Articulation::setVelocityType(VelocityType type) { velocityType_ = type; changeVelocity_ = true; } Articulation::VelocityType Articulation::getVelocityType() const { return velocityType_; } void Articulation::setVelocityValue(int value) { velocityValue_ = value; } int Articulation::getVelocityValue() const { return velocityValue_; } bool Articulation::getChangeExtraLength() const { return changeExtraLength_; } void Articulation::setExtraLength(int length) { extraLength_ = length; changeExtraLength_ = true; } int Articulation::getExtraLength() const { return extraLength_; } void Articulation::setTrillNoteLength(int length) { trillNoteLength_ = length; } int Articulation::getTrillNoteLength() const { return trillNoteLength_; } void Articulation::setTrillRate(NoteType rate) { trillRate_ = rate; } NoteType Articulation::getTrillRate() const { return trillRate_; } void Articulation::setAccelerateType(int type) { accelerateType_ = (AccelerateType) type; } Articulation::AccelerateType Articulation::getAccelerateType() const { return accelerateType_; } void Articulation::setAuxiliaryFirst(bool first) { auxiliaryFirst_ = first; } bool Articulation::getAuxiliaryFirst() const { return auxiliaryFirst_; } void Articulation::setTrillInterval(int interval) { trillInterval_ = (TrillInterval) interval; } Articulation::TrillInterval Articulation::getTrillInterval() const { return trillInterval_; } bool Articulation::willAffectNotes() const { bool affect = false; switch (getArtType()) { case Articulation_Major_Trill: case Articulation_Minor_Trill: case Articulation_Trill_Section: case Articulation_Inverted_Short_Mordent: case Articulation_Inverted_Long_Mordent: case Articulation_Short_Mordent: case Articulation_Turn: case Articulation_Arpeggio: case Articulation_Tremolo_Eighth: case Articulation_Tremolo_Sixteenth: case Articulation_Tremolo_Thirty_Second: case Articulation_Tremolo_Sixty_Fourth: { affect = true; break; } case Articulation_Finger_1: case Articulation_Finger_2: case Articulation_Finger_3: case Articulation_Finger_4: case Articulation_Finger_5: case Articulation_Flat_Accidental_For_Trill: case Articulation_Sharp_Accidental_For_Trill: case Articulation_Natural_Accidental_For_Trill: case Articulation_Marcato: case Articulation_Marcato_Dot: case Articulation_Heavy_Attack: case Articulation_SForzando: case Articulation_SForzando_Dot: case Articulation_Heavier_Attack: case Articulation_SForzando_Inverted: case Articulation_SForzando_Dot_Inverted: case Articulation_Staccatissimo: case Articulation_Staccato: case Articulation_Tenuto: case Articulation_Up_Bow: case Articulation_Down_Bow: case Articulation_Up_Bow_Inverted: case Articulation_Down_Bow_Inverted: case Articulation_Natural_Harmonic: case Articulation_Artificial_Harmonic: case Articulation_Plus_Sign: case Articulation_Fermata: case Articulation_Fermata_Inverted: case Articulation_Pedal_Down: case Articulation_Pedal_Up: case Articulation_Pause: case Articulation_Grand_Pause: case Articulation_Toe_Pedal: case Articulation_Heel_Pedal: case Articulation_Toe_To_Heel_Pedal: case Articulation_Heel_To_Toe_Pedal: case Articulation_Open_String: case Articulation_Guitar_Lift: case Articulation_Guitar_Slide_Up: case Articulation_Guitar_Rip: case Articulation_Guitar_Fall_Off: case Articulation_Guitar_Slide_Down: case Articulation_Guitar_Spill: case Articulation_Guitar_Flip: case Articulation_Guitar_Smear: case Articulation_Guitar_Bend: case Articulation_Guitar_Doit: case Articulation_Guitar_Plop: case Articulation_Guitar_Wow_Wow: case Articulation_Guitar_Thumb: case Articulation_Guitar_Index_Finger: case Articulation_Guitar_Middle_Finger: case Articulation_Guitar_Ring_Finger: case Articulation_Guitar_Pinky_Finger: case Articulation_Guitar_Tap: case Articulation_Guitar_Hammer: case Articulation_Guitar_Pluck: { break; } default: break; } return affect; } bool Articulation::isTrill(ArticulationType type) { bool isTrill = false; switch (type) { case Articulation_Major_Trill: case Articulation_Minor_Trill: case Articulation_Trill_Section: { isTrill = true; break; } default: break; } return isTrill; } Articulation::XmlType Articulation::getXmlType() const { XmlType xmlType = Xml_Unknown; switch (type_) { case Articulation_Major_Trill: case Articulation_Minor_Trill: case Articulation_Trill_Section: case Articulation_Inverted_Short_Mordent: case Articulation_Inverted_Long_Mordent: case Articulation_Short_Mordent: case Articulation_Turn: // case Articulation_Flat_Accidental_For_Trill : // case Articulation_Sharp_Accidental_For_Trill : // case Articulation_Natural_Accidental_For_Trill : case Articulation_Tremolo_Eighth: case Articulation_Tremolo_Sixteenth: case Articulation_Tremolo_Thirty_Second: case Articulation_Tremolo_Sixty_Fourth: { xmlType = Xml_Ornament; break; } case Articulation_Marcato: case Articulation_Marcato_Dot: case Articulation_Heavy_Attack: case Articulation_SForzando: case Articulation_SForzando_Inverted: case Articulation_SForzando_Dot: case Articulation_SForzando_Dot_Inverted: case Articulation_Heavier_Attack: case Articulation_Staccatissimo: case Articulation_Staccato: case Articulation_Tenuto: case Articulation_Pause: case Articulation_Grand_Pause: { xmlType = Xml_Articulation; break; } case Articulation_Up_Bow: case Articulation_Down_Bow: case Articulation_Up_Bow_Inverted: case Articulation_Down_Bow_Inverted: case Articulation_Natural_Harmonic: case Articulation_Artificial_Harmonic: case Articulation_Finger_1: case Articulation_Finger_2: case Articulation_Finger_3: case Articulation_Finger_4: case Articulation_Finger_5: case Articulation_Plus_Sign: { xmlType = Xml_Technical; break; } case Articulation_Arpeggio: { xmlType = Xml_Arpeggiate; break; } case Articulation_Fermata: case Articulation_Fermata_Inverted: { xmlType = Xml_Fermata; break; } case Articulation_Pedal_Down: case Articulation_Pedal_Up: { xmlType = Xml_Direction; break; } // case Articulation_Toe_Pedal : // case Articulation_Heel_Pedal : // case Articulation_Toe_To_Heel_Pedal : // case Articulation_Heel_To_Toe_Pedal : // case Articulation_Open_String : default: break; } return xmlType; } /////////////////////////////////////////////////////////////////////////////// NoteContainer::NoteContainer() { musicDataType_ = MusicData_Note_Container; grace_ = false; cue_ = false; rest_ = false; raw_ = false; noteType_ = Note_Quarter; dot_ = 0; graceNoteType_ = Note_Eight; stemUp_ = true; showStem_ = true; stemLength_ = 7; inBeam_ = false; tuplet_ = 0; space_ = 2;//div by 0 noteShift_ = 0; } NoteContainer::~NoteContainer(){ for(int i=0; i NoteContainer::getNotesRests() const { return notes_; } void NoteContainer::addArticulation(Articulation* art) { articulations_.push_back(art); } QList NoteContainer::getArticulations() const { return articulations_; } void NoteContainer::setNoteShift(int octave) { noteShift_ = octave; } int NoteContainer::getNoteShift() const { return noteShift_; } int NoteContainer::getOffsetStaff() const { if(getIsRest()) return 0; int staffMove = 0; QList notes = getNotesRests(); for (int i = 0; i < notes.size(); ++i) { OVE::Note* notePtr = notes[i]; staffMove = notePtr->getOffsetStaff(); } return staffMove; } int NoteContainer::getDuration() const { int duration = (int) NoteDuration_4; switch (noteType_) { case Note_DoubleWhole: { duration = (int) NoteDuration_Double_Whole; break; } case Note_Whole: { duration = (int) NoteDuration_Whole; break; } case Note_Half: { duration = (int) NoteDuration_2; break; } case Note_Quarter: { duration = (int) NoteDuration_4; break; } case Note_Eight: { duration = (int) NoteDuration_8; break; } case Note_Sixteen: { duration = (int) NoteDuration_16; break; } case Note_32: { duration = (int) NoteDuration_32; break; } case Note_64: { duration = (int) NoteDuration_64; break; } case Note_128: { duration = (int) NoteDuration_128; break; } case Note_256: { duration = (int) NoteDuration_256; break; } default: break; } int dotLength = duration; for (int i = 0; i < dot_; ++i) { dotLength /= 2; } dotLength = duration - dotLength; duration += dotLength; return duration; } /////////////////////////////////////////////////////////////////////////////// Beam::Beam() { musicDataType_ = MusicData_Beam; grace_ = false; } void Beam::setIsGrace(bool grace) { grace_ = grace; } bool Beam::getIsGrace() const { return grace_; } void Beam::addLine(const MeasurePos& startMp, const MeasurePos& endMp) { lines_.push_back(qMakePair(startMp, endMp)); } const QList > Beam::getLines() const { return lines_; } /////////////////////////////////////////////////////////////////////////////// Tie::Tie() { musicDataType_ = MusicData_Tie; showOnTop_ = true; note_ = 72; height_ = 24; } void Tie::setShowOnTop(bool top) { showOnTop_ = top; } bool Tie::getShowOnTop() const { return showOnTop_; } void Tie::setNote(int note) { note_ = note; } int Tie::getNote() const { return note_; } void Tie::setHeight(int height) { height_ = height; } int Tie::getHeight() const { return height_; } /////////////////////////////////////////////////////////////////////////////// Glissando::Glissando() { musicDataType_ = MusicData_Glissando; straight_ = true; text_ = "gliss."; lineThick_ = 8; } void Glissando::setStraightWavy(bool straight) { straight_ = straight; } bool Glissando::getStraightWavy() const { return straight_; } void Glissando::setText(const QString& text) { text_ = text; } QString Glissando::getText() const { return text_; } void Glissando::setLineThick(int thick) { lineThick_ = thick; } int Glissando::getLineThick() const { return lineThick_; } /////////////////////////////////////////////////////////////////////////////// Decorator::Decorator() : decoratorType_(Decorator_Articulation), artType_(Articulation_Marcato) { musicDataType_ = MusicData_Decorator; } void Decorator::setDecoratorType(DecoratorType type) { decoratorType_ = type; } Decorator::DecoratorType Decorator::getDecoratorType() const { return decoratorType_; } void Decorator::setArticulationType(ArticulationType type) { artType_ = type; } ArticulationType Decorator::getArticulationType() const { return artType_; } /////////////////////////////////////////////////////////////////////////////// MeasureRepeat::MeasureRepeat() { musicDataType_ = MusicData_Measure_Repeat; singleRepeat_ = true; } void MeasureRepeat::setSingleRepeat(bool single) { singleRepeat_ = single; start()->setMeasure(0); start()->setOffset(0); stop()->setMeasure(single ? 1 : 2); stop()->setOffset(0); } bool MeasureRepeat::getSingleRepeat() const { return singleRepeat_; } /////////////////////////////////////////////////////////////////////////////// Tuplet::Tuplet() : tuplet_(3), space_(2), height_(0), noteType_(Note_Quarter){ musicDataType_ = MusicData_Tuplet; mark_ = new OffsetElement(); } Tuplet::~Tuplet(){ delete mark_; } void Tuplet::setTuplet(int tuplet) { tuplet_ = tuplet; } int Tuplet::getTuplet() const { return tuplet_; } void Tuplet::setSpace(int space) { space_ = space; } int Tuplet::getSpace() const { return space_; } OffsetElement* Tuplet::getMarkHandle() const { return mark_; } void Tuplet::setHeight(int height) { height_ = height; } int Tuplet::getHeight() const { return height_; } void Tuplet::setNoteType(NoteType type) { noteType_ = type; } NoteType Tuplet::getNoteType() const { return noteType_; } /////////////////////////////////////////////////////////////////////////////// Harmony::Harmony() { musicDataType_ = MusicData_Harmony; harmonyType_ = Harmony_maj; root_ = 0; bass_ = -1;//0xff bassOnBottom_ = false; angle_ = 0; } void Harmony::setHarmonyType(HarmonyType type) { harmonyType_ = type; } HarmonyType Harmony::getHarmonyType() const { return harmonyType_; } void Harmony::setRoot(int root) { root_ = root; } int Harmony::getRoot() const { return root_; } void Harmony::setBass(int bass) { bass_ = bass; } int Harmony::getBass() const { return bass_; } void Harmony::setBassOnBottom(bool on) { bassOnBottom_ = on; } bool Harmony::getBassOnBottom() const { return bassOnBottom_; } void Harmony::setAngle(int angle) { angle_ = angle; } int Harmony::getAngle() const { return angle_; } /////////////////////////////////////////////////////////////////////////////// Clef::Clef() { musicDataType_ = MusicData_Clef; clefType_ = Clef_Treble; } void Clef::setClefType(int type) { clefType_ = (ClefType) type; } ClefType Clef::getClefType() const { return clefType_; } /////////////////////////////////////////////////////////////////////////////// Lyric::Lyric() { musicDataType_ = MusicData_Lyric; lyric_ = QString(); verse_ = 0; } void Lyric::setLyric(const QString& lyricText) { lyric_ = lyricText; } QString Lyric::getLyric() const { return lyric_; } void Lyric::setVerse(int verse) { verse_ = verse; } int Lyric::getVerse() const { return verse_; } /////////////////////////////////////////////////////////////////////////////// Slur::Slur() { musicDataType_ = MusicData_Slur; containerCount_ = 1; showOnTop_ = true; noteTimePercent_ = 100; handle_2_ = new OffsetElement(); handle_3_ = new OffsetElement(); } Slur::~Slur() { delete handle_2_; delete handle_3_; } void Slur::setContainerCount(int count) { containerCount_ = count; } int Slur::getContainerCount() const { return containerCount_; } void Slur::setShowOnTop(bool top) { showOnTop_ = top; } bool Slur::getShowOnTop() const { return showOnTop_; } OffsetElement* Slur::getHandle2() const { return handle_2_; } OffsetElement* Slur::getHandle3() const { return handle_3_; } void Slur::setNoteTimePercent(int percent) { noteTimePercent_ = percent; } int Slur::getNoteTimePercent() const { return noteTimePercent_; } /////////////////////////////////////////////////////////////////////////////// Dynamics::Dynamics() { musicDataType_ = MusicData_Dynamics; dynamicsType_ = Dynamics_pppp; playback_ = true; velocity_ = 30; } void Dynamics::setDynamicsType(int type) { dynamicsType_ = (DynamicsType) type; } DynamicsType Dynamics::getDynamicsType() const { return dynamicsType_; } void Dynamics::setIsPlayback(bool play) { playback_ = play; } bool Dynamics::getIsPlayback() const { return playback_; } void Dynamics::setVelocity(int vel) { velocity_ = vel; } int Dynamics::getVelocity() const { return velocity_; } /////////////////////////////////////////////////////////////////////////////// WedgeEndPoint::WedgeEndPoint() { musicDataType_ = MusicData_Wedge_EndPoint; wedgeType_ = Wedge_Cres; height_ = 24; wedgeStart_ = true; } void WedgeEndPoint::setWedgeType(WedgeType type) { wedgeType_ = type; } WedgeType WedgeEndPoint::getWedgeType() const { return wedgeType_; } void WedgeEndPoint::setHeight(int height) { height_ = height; } int WedgeEndPoint::getHeight() const { return height_; } void WedgeEndPoint::setWedgeStart(bool wedgeStart) { wedgeStart_ = wedgeStart; } bool WedgeEndPoint::getWedgeStart() const { return wedgeStart_; } /////////////////////////////////////////////////////////////////////////////// Wedge::Wedge() { musicDataType_ = MusicData_Wedge; wedgeType_ = Wedge_Cres; height_ = 24; } void Wedge::setWedgeType(WedgeType type) { wedgeType_ = type; } WedgeType Wedge::getWedgeType() const { return wedgeType_; } void Wedge::setHeight(int height) { height_ = height; } int Wedge::getHeight() const { return height_; } /////////////////////////////////////////////////////////////////////////////// Pedal::Pedal() { musicDataType_ = MusicData_Pedal; half_ = false; playback_ = false; playOffset_ = 0; pedalHandle_ = new OffsetElement(); } Pedal::~Pedal() { delete pedalHandle_; } void Pedal::setHalf(bool half) { half_ = half; } bool Pedal::getHalf() const { return half_; } OffsetElement* Pedal::getPedalHandle() const { return pedalHandle_; } void Pedal::setIsPlayback(bool playback) { playback_ = playback; } bool Pedal::getIsPlayback() const { return playback_; } void Pedal::setPlayOffset(int offset) { playOffset_ = offset; } int Pedal::getPlayOffset() const { return playOffset_; } /////////////////////////////////////////////////////////////////////////////// KuoHao::KuoHao() { musicDataType_ = MusicData_KuoHao; kuohaoType_ = KuoHao_Parentheses; height_ = 0; } void KuoHao::setHeight(int height) { height_ = height; } int KuoHao::getHeight() const { return height_; } void KuoHao::setKuohaoType(int type) { kuohaoType_ = (KuoHaoType) type; } KuoHaoType KuoHao::getKuohaoType() const { return kuohaoType_; } /////////////////////////////////////////////////////////////////////////////// Expressions::Expressions() { musicDataType_ = MusicData_Expressions; text_ = QString(); } void Expressions::setText(const QString& str) { text_ = str; } QString Expressions::getText() const { return text_; } /////////////////////////////////////////////////////////////////////////////// HarpPedal::HarpPedal() : showType_(0), showCharFlag_(0) { musicDataType_ = MusicData_Harp_Pedal; } void HarpPedal::setShowType(int type) { showType_ = type; } int HarpPedal::getShowType() const { return showType_; } void HarpPedal::setShowCharFlag(int flag) { showCharFlag_ = flag; } int HarpPedal::getShowCharFlag() const { return showCharFlag_; } /////////////////////////////////////////////////////////////////////////////// OctaveShift::OctaveShift() : octaveShiftType_(OctaveShift_8), octaveShiftPosition_(OctavePosition_Start), endTick_(0) { musicDataType_ = MusicData_OctaveShift; } void OctaveShift::setOctaveShiftType(int type) { octaveShiftType_ = (OctaveShiftType) type; } OctaveShiftType OctaveShift::getOctaveShiftType() const { return octaveShiftType_; } int OctaveShift::getNoteShift() const { int shift = 12; switch (getOctaveShiftType()) { case OctaveShift_8: { shift = 12; break; } case OctaveShift_Minus_8: { shift = -12; break; } case OctaveShift_15: { shift = 24; break; } case OctaveShift_Minus_15: { shift = -24; break; } default: break; } return shift; } void OctaveShift::setEndTick(int tick) { endTick_ = tick; } int OctaveShift::getEndTick() const { return endTick_; } /////////////////////////////////////////////////////////////////////////////// OctaveShiftEndPoint::OctaveShiftEndPoint() { musicDataType_ = MusicData_OctaveShift_EndPoint; octaveShiftType_ = OctaveShift_8; octaveShiftPosition_ = OctavePosition_Start; endTick_ = 0; } void OctaveShiftEndPoint::setOctaveShiftType(int type) { octaveShiftType_ = (OctaveShiftType) type; } OctaveShiftType OctaveShiftEndPoint::getOctaveShiftType() const { return octaveShiftType_; } void OctaveShiftEndPoint::setOctaveShiftPosition(int position) { octaveShiftPosition_ = (OctaveShiftPosition) position; } OctaveShiftPosition OctaveShiftEndPoint::getOctaveShiftPosition() const { return octaveShiftPosition_; } void OctaveShiftEndPoint::setEndTick(int tick) { endTick_ = tick; } int OctaveShiftEndPoint::getEndTick() const { return endTick_; } /////////////////////////////////////////////////////////////////////////////// MultiMeasureRest::MultiMeasureRest() { musicDataType_ = MusicData_Multi_Measure_Rest; measureCount_ = 0; } void MultiMeasureRest::setMeasureCount(int count) { measureCount_ = count; } int MultiMeasureRest::getMeasureCount() const { return measureCount_; } /////////////////////////////////////////////////////////////////////////////// Tempo::Tempo() { musicDataType_ = MusicData_Tempo; leftNoteType_ = 3; showMark_ = false; showText_ = false; showParenthesis_ = false; typeTempo_ = 96; leftText_ = QString(); rightText_ = QString(); swingEighth_ = false; rightNoteType_ = 3; } void Tempo::setLeftNoteType(int type) { leftNoteType_ = type; } NoteType Tempo::getLeftNoteType() const { return (NoteType) leftNoteType_; } void Tempo::setShowMark(bool show) { showMark_ = show; } bool Tempo::getShowMark() const { return showMark_; } void Tempo::setShowBeforeText(bool show) { showText_ = show; } bool Tempo::getShowBeforeText() const { return showText_; } void Tempo::setShowParenthesis(bool show) { showParenthesis_ = show; } bool Tempo::getShowParenthesis() const { return showParenthesis_; } void Tempo::setTypeTempo(int tempo) { typeTempo_ = tempo; } int Tempo::getTypeTempo() const { return typeTempo_; } int Tempo::getQuarterTempo() const { double factor = pow(2.0, (int) Note_Quarter - (int) getLeftNoteType()); int tempo = int((double) getTypeTempo() * factor); return tempo; } void Tempo::setLeftText(const QString& str) { leftText_ = str; } QString Tempo::getLeftText() const { return leftText_; } void Tempo::setRightText(const QString& str) { rightText_ = str; } QString Tempo::getRightText() const { return rightText_; } void Tempo::setSwingEighth(bool swing) { swingEighth_ = swing; } bool Tempo::getSwingEighth() const { return swingEighth_; } void Tempo::setRightNoteType(int type) { rightNoteType_ = type; } int Tempo::getRightNoteType() const { return rightNoteType_; } /////////////////////////////////////////////////////////////////////////////// Text::Text() { musicDataType_ = MusicData_Text; textType_ = Text_Rehearsal; horiMargin_ = 8; vertMargin_ = 8; lineThick_ = 4; text_ = QString(); width_ = 0; height_ = 0; } void Text::setTextType(TextType type) { textType_ = type; } Text::TextType Text::getTextType() const { return textType_; } void Text::setHorizontalMargin(int margin) { horiMargin_ = margin; } int Text::getHorizontalMargin() const { return horiMargin_; } void Text::setVerticalMargin(int margin) { vertMargin_ = margin; } int Text::getVerticalMargin() const { return vertMargin_; } void Text::setLineThick(int thick) { lineThick_ = thick; } int Text::getLineThick() const { return lineThick_; } void Text::setText(const QString& text) { text_ = text; } QString Text::getText() const { return text_; } void Text::setWidth(int width) { width_ = width; } int Text::getWidth() const { return width_; } void Text::setHeight(int height) { height_ = height; } int Text::getHeight() const { return height_; } /////////////////////////////////////////////////////////////////////////////// TimeSignature::TimeSignature() { numerator_ = 4; denominator_ = 4; isSymbol_ = false; beatLength_ = 480; barLength_ = 1920; barLengthUnits_ = 0x400; replaceFont_ = false; showBeatGroup_ = false; groupNumerator1_ = 0; groupNumerator2_ = 0; groupNumerator3_ = 0; groupDenominator1_ = 4; groupDenominator2_ = 4; groupDenominator3_ = 4; beamGroup1_ = 4; beamGroup2_ = 0; beamGroup3_ = 0; beamGroup4_ = 0; beamCount16th_ = 4; beamCount32th_ = 1; } void TimeSignature::setNumerator(int numerator) { numerator_ = numerator; } int TimeSignature::getNumerator() const { return numerator_; } void TimeSignature::setDenominator(int denominator) { denominator_ = denominator; } int TimeSignature::getDenominator() const { return denominator_; } void TimeSignature::setIsSymbol(bool symbol) { isSymbol_ = symbol; } bool TimeSignature::getIsSymbol() const { if (numerator_ == 2 && denominator_ == 2) { return true; } return isSymbol_; } void TimeSignature::setBeatLength(int length) { beatLength_ = length; } int TimeSignature::getBeatLength() const { return beatLength_; } void TimeSignature::setBarLength(int length) { barLength_ = length; } int TimeSignature::getBarLength() const { return barLength_; } void TimeSignature::addBeat(int startUnit, int lengthUnit, int startTick) { BeatNode node; node.startUnit_ = startUnit; node.lengthUnit_ = lengthUnit; node.startTick_ = startTick; beats_.push_back(node); } void TimeSignature::endAddBeat() { int i; barLengthUnits_ = 0; for (i = 0; i < beats_.size(); ++i) { barLengthUnits_ += beats_[i].lengthUnit_; } } int TimeSignature::getUnits() const { return barLengthUnits_; } void TimeSignature::setReplaceFont(bool replace) { replaceFont_ = replace; } bool TimeSignature::getReplaceFont() const { return replaceFont_; } void TimeSignature::setShowBeatGroup(bool show) { showBeatGroup_ = show; } bool TimeSignature::getShowBeatGroup() const { return showBeatGroup_; } void TimeSignature::setGroupNumerator1(int numerator) { groupNumerator1_ = numerator; } void TimeSignature::setGroupNumerator2(int numerator) { groupNumerator2_ = numerator; } void TimeSignature::setGroupNumerator3(int numerator) { groupNumerator3_ = numerator; } void TimeSignature::setGroupDenominator1(int denominator) { groupDenominator1_ = denominator; } void TimeSignature::setGroupDenominator2(int denominator) { groupDenominator2_ = denominator; } void TimeSignature::setGroupDenominator3(int denominator) { groupDenominator3_ = denominator; } void TimeSignature::setBeamGroup1(int count) { beamGroup1_ = count; } void TimeSignature::setBeamGroup2(int count) { beamGroup2_ = count; } void TimeSignature::setBeamGroup3(int count) { beamGroup3_ = count; } void TimeSignature::setBeamGroup4(int count) { beamGroup4_ = count; } void TimeSignature::set16thBeamCount(int count) { beamCount16th_ = count; } void TimeSignature::set32thBeamCount(int count) { beamCount32th_ = count; } /////////////////////////////////////////////////////////////////////////////// Key::Key() { key_ = 0; set_ = false; previousKey_ = 0; symbolCount_ = 0; } void Key::setKey(int key) { key_ = key; set_ = true; } int Key::getKey() const { return key_; } bool Key::getSetKey() const { return set_; } void Key::setPreviousKey(int key) { previousKey_ = key; } int Key::getPreviousKey() const { return previousKey_; } void Key::setSymbolCount(int count) { symbolCount_ = count; } int Key::getSymbolCount() const { return symbolCount_; } /////////////////////////////////////////////////////////////////////////////// RepeatSymbol::RepeatSymbol() : text_("#1"), repeatType_(Repeat_Segno) { musicDataType_ = MusicData_Repeat; } void RepeatSymbol::setText(const QString& text) { text_ = text; } QString RepeatSymbol::getText() const { return text_; } void RepeatSymbol::setRepeatType(int repeatType) { repeatType_ = (RepeatType) repeatType; } RepeatType RepeatSymbol::getRepeatType() const { return repeatType_; } /////////////////////////////////////////////////////////////////////////////// NumericEnding::NumericEnding() { musicDataType_ = MusicData_Numeric_Ending; height_ = 0; text_ = QString(); numericHandle_ = new OffsetElement(); } NumericEnding::~NumericEnding() { delete numericHandle_; } OffsetElement* NumericEnding::getNumericHandle() const { return numericHandle_; } void NumericEnding::setHeight(int height) { height_ = height; } int NumericEnding::getHeight() const { return height_; } void NumericEnding::setText(const QString& text) { text_ = text; } QString NumericEnding::getText() const { return text_; } QList NumericEnding::getNumbers() const { int i; QStringList strs = text_.split(",", QString::SkipEmptyParts); QList endings; for (i = 0; i < strs.size(); ++i) { bool ok; int num = strs[i].toInt(&ok); endings.push_back(num); } return endings; } int NumericEnding::getJumpCount() const { QList numbers = getNumbers(); int count = 0; for (int i = 0; i < numbers.size(); ++i) { if ((int)i + 1 != numbers[i]) { break; } count = i + 1; } return count; } /////////////////////////////////////////////////////////////////////////////// BarNumber::BarNumber() { index_ = 0; showOnParagraphStart_ = false; align_ = 0; showFlag_ = 1; // staff barRange_ = 1; // can't be 0 prefix_ = QString(); } void BarNumber::setIndex(int index) { index_ = index; } int BarNumber::getIndex() const { return index_; } void BarNumber::setShowOnParagraphStart(bool show) { showOnParagraphStart_ = show; } bool BarNumber::getShowOnParagraphStart() const { return showOnParagraphStart_; } void BarNumber::setAlign(int align)// 0:left, 1:center, 2:right { align_ = align; } int BarNumber::getAlign() const { return align_; } void BarNumber::setShowFlag(int flag) { showFlag_ = flag; } int BarNumber::getShowFlag() const { return showFlag_; } void BarNumber::setShowEveryBarCount(int count) { barRange_ = count; } int BarNumber::getShowEveryBarCount() const { return barRange_; } void BarNumber::setPrefix(const QString& str) { prefix_ = str; } QString BarNumber::getPrefix() const { return prefix_; } /////////////////////////////////////////////////////////////////////////////// MidiController::MidiController() { midiType_ = Midi_Controller; controller_ = 64; // pedal value_ = 0; } void MidiController::setController(int number) { controller_ = number; } int MidiController::getController() const { return controller_; } void MidiController::setValue(int value) { value_ = value; } int MidiController::getValue() const { return value_; } /////////////////////////////////////////////////////////////////////////////// MidiProgramChange::MidiProgramChange() { midiType_ = Midi_Program_Change; patch_ = 0; // grand piano } void MidiProgramChange::setPatch(int patch) { patch_ = patch; } int MidiProgramChange::getPatch() const { return patch_; } /////////////////////////////////////////////////////////////////////////////// MidiChannelPressure::MidiChannelPressure() : pressure_(0) { midiType_ = Midi_Channel_Pressure; } void MidiChannelPressure::setPressure(int pressure) { pressure_ = pressure; } int MidiChannelPressure::getPressure() const { return pressure_; } /////////////////////////////////////////////////////////////////////////////// MidiPitchWheel::MidiPitchWheel() { midiType_ = Midi_Pitch_Wheel; value_ = 0; } void MidiPitchWheel::setValue(int value) { value_ = value; } int MidiPitchWheel::getValue() const { return value_; } /////////////////////////////////////////////////////////////////////////////// Measure::Measure(int index) { barNumber_ = new BarNumber(); barNumber_->setIndex(index); time_ = new TimeSignature(); clear(); } Measure::~Measure(){ clear(); delete barNumber_; delete time_; } BarNumber* Measure::getBarNumber() const { return barNumber_; } TimeSignature* Measure::getTime() const { return time_; } void Measure::setLeftBarline(int barline) { leftBarline_ = (BarlineType) barline; } BarlineType Measure::getLeftBarline() const { return leftBarline_; } void Measure::setRightBarline(int barline) { rightBarline_ = (BarlineType) barline; } BarlineType Measure::getRightBarline() const { return rightBarline_; } void Measure::setBackwardRepeatCount(int repeatCount) { repeatCount_ = repeatCount; } int Measure::getBackwardRepeatCount() const { return repeatCount_; } void Measure::setTypeTempo(double tempo) { typeTempo_ = tempo; } double Measure::getTypeTempo() const { return typeTempo_; } void Measure::setIsPickup(bool pickup) { pickup_ = pickup; } bool Measure::getIsPickup() const { return pickup_; } void Measure::setIsMultiMeasureRest(bool rest) { multiMeasureRest_ = rest; } bool Measure::getIsMultiMeasureRest() const { return multiMeasureRest_; } void Measure::setMultiMeasureRestCount(int count) { multiMeasureRestCount_ = count; } int Measure::getMultiMeasureRestCount() const { return multiMeasureRestCount_; } void Measure::clear() { leftBarline_ = Barline_Default; rightBarline_ = Barline_Default; repeatCount_ = 1; typeTempo_ = 96.00; setLength(0x780); //time = 4/4 pickup_ = false; multiMeasureRest_ = false; multiMeasureRestCount_ = 0; } /////////////////////////////////////////////////////////////////////////////// MeasureData::MeasureData() { key_ = new Key(); clef_ = new Clef(); } MeasureData::~MeasureData(){ int i; for(i=0; i MeasureData::getNoteContainers() const { return noteContainers_; } void MeasureData::addMusicData(MusicData* ptr) { musicDatas_.push_back(ptr); } QList MeasureData::getMusicDatas(MusicDataType type) { int i; QList notations; for (i = 0; i < musicDatas_.size(); ++i) { if (type == MusicData_None || musicDatas_[i]->getMusicDataType() == type) { notations.push_back(musicDatas_[i]); } } return notations; } void MeasureData::addCrossMeasureElement(MusicData* ptr, bool start) { crossMeasureElements_.push_back(qMakePair(ptr, start)); } QList MeasureData::getCrossMeasureElements( MusicDataType type, PairType pairType) { int i; QList pairs; for (i = 0; i < crossMeasureElements_.size(); ++i) { if ((type == MusicData_None || crossMeasureElements_[i].first->getMusicDataType() == type) && (pairType == PairType_All || ((crossMeasureElements_[i].second && pairType == PairType_Start) || (!crossMeasureElements_[i].second && pairType == PairType_Stop)))) { pairs.push_back(crossMeasureElements_[i].first); } } return pairs; } void MeasureData::addMidiData(MidiData* ptr) { midiDatas_.push_back(ptr); } QList MeasureData::getMidiDatas(MidiType type) { int i; QList datas; for (i = 0; i < midiDatas_.size(); ++i) { if (type == Midi_None || midiDatas_[i]->getMidiType() == type) { datas.push_back(midiDatas_[i]); } } return datas; } ////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////// StreamHandle::StreamHandle() : size_(0), curPos_(0), point_(NULL) { } StreamHandle::StreamHandle(unsigned char* p, int size) : size_(size), curPos_(0), point_(p) { } StreamHandle::~StreamHandle() { point_ = NULL; } bool StreamHandle::read(char* buff, int size) { if (point_ != NULL && curPos_ + size <= size_) { memcpy(buff, point_ + curPos_, size); curPos_ += size; return true; } return false; } bool StreamHandle::write(char* /*buff*/, int /*size*/) { return true; } // Block.cpp /////////////////////////////////////////////////////////////////////////////////////////////////// Block::Block() { doResize(0); } Block::Block(unsigned int count) { doResize(count); } void Block::resize(unsigned int count) { doResize(count); } void Block::doResize(unsigned int count) { data_.clear(); for(unsigned int i=0; i(&data_.front()); return &data_.front(); } unsigned char* Block::data() { return &data_.front(); } unsigned int Block::size() const { return data_.size(); } bool Block::toBoolean() const { if (data() == NULL) { return false; } return size() == 1 && data()[0] == 0x01; } unsigned int Block::toUnsignedInt() const { if (data() == NULL) { return 0; } unsigned int i; unsigned int num(0); for (i = 0; i < sizeof(unsigned int) && i < size(); ++i) { num = (num << 8) + *(data() + i); } return num; } int Block::toInt() const { if (data() == NULL) { return 0; } unsigned int i; int num = 0; for (i = 0; i < sizeof(unsigned int) && i < size(); ++i) { num = (num << 8) + (int) *(data() + i); } std::size_t minSize = sizeof(unsigned int); if (size() < minSize) { minSize = size(); } if ((*(data()) & 0x80) == 0x80) { int maxNum = int(pow(2.0, (int) minSize * 8)); num -= maxNum; //num *= -1; } return num; } QByteArray Block::toStrByteArray() const { if (data() == NULL) { return QByteArray(); } QByteArray arr((char*) data(), size()); return arr; } QByteArray Block::fixedSizeBufferToStrByteArray() const { unsigned int i; QByteArray str; for (i = 0; i < size(); ++i) { if (*(data() + i) == '\0') { break; } str += (char) *(data() + i); } return str; } bool Block::operator ==(const Block& block) const { unsigned int i; if (size() != block.size()) { return false; } for (i = 0; i < size() && i < block.size(); ++i) { if (*(data() + i) != *(block.data() + i)) { return false; } } return true; } bool Block::operator !=(const Block& block) const { return !(*this == block); } /////////////////////////////////////////////////////////////////////////////////////////////////// FixedBlock::FixedBlock() : Block() { } FixedBlock::FixedBlock(unsigned int count) : Block(count) { } void FixedBlock::resize(unsigned int /*count*/) { // Block::resize(size); } /////////////////////////////////////////////////////////////////////////////////////////////////// SizeBlock::SizeBlock() : FixedBlock(4) { } unsigned int SizeBlock::toSize() const { unsigned int i; unsigned int num(0); const unsigned int SIZE = 4; for (i = 0; i < SIZE; ++i) { num = (num << 8) + *(data() + i); } return num; } /*void SizeBlock::fromUnsignedInt(unsigned int count) { unsigned_int_to_char_buffer(count, data()); }*/ /////////////////////////////////////////////////////////////////////////////////////////////////// NameBlock::NameBlock() : FixedBlock(4) { } /*void NameBlock::setValue(const char* const name) { unsigned int i; for( i=0; i(name.size()); if (nsize != size()) { return false; } for (i = 0; i < size() && nsize; ++i) { if (data()[i] != name[i]) { return false; } } return true; } /////////////////////////////////////////////////////////////////////////////////////////////////// CountBlock::CountBlock() : FixedBlock(2) { } /*void CountBlock::setValue(unsigned short count) { unsigned int i; unsigned int SIZE = sizeof(unsigned short); for( i=0; i 7 ) { key = oveKey - 7; } else if( oveKey <= 7 ) { key = oveKey * (-1); } return key; } /////////////////////////////////////////////////////////////////////////////// BasicParse::BasicParse(OveSong* ove) : ove_(ove), handle_(NULL), notify_(NULL) { } BasicParse::BasicParse() : ove_(NULL), handle_(NULL), notify_(NULL) { } BasicParse::~BasicParse() { ove_ = NULL; handle_ = NULL; notify_ = NULL; } void BasicParse::setNotify(IOveNotify* notify) { notify_ = notify; } bool BasicParse::parse() { return false; } bool BasicParse::readBuffer(Block& placeHolder, unsigned int size) { if (handle_ == NULL) { return false; } if (placeHolder.size() != size) { placeHolder.resize(size); } if (size > 0) { return handle_->read((char*) placeHolder.data(), placeHolder.size()); } return true; } bool BasicParse::jump(int offset) { if (handle_ == NULL || offset < 0) { return false; } if (offset > 0) { Block placeHolder(offset); return handle_->read((char*) placeHolder.data(), placeHolder.size()); } return true; } void BasicParse::messageOut(const QString& str) { if (notify_ != NULL) { notify_->loadInfo(str); } } /////////////////////////////////////////////////////////////////////////////// OvscParse::OvscParse(OveSong* ove) : BasicParse(ove), chunk_(NULL) { } OvscParse::~OvscParse() { chunk_ = NULL; } void OvscParse::setOvsc(SizeChunk* chunk) { chunk_ = chunk; } bool OvscParse::parse() { Block* dataBlock = chunk_->getDataBlock(); unsigned int blockSize = chunk_->getSizeBlock()->toSize(); StreamHandle handle(dataBlock->data(), blockSize); Block placeHolder; handle_ = &handle; // version if (!readBuffer(placeHolder, 1)) { return false; } bool version4 = placeHolder.toUnsignedInt() == 4; ove_->setIsVersion4(version4); QString str = QString("This file is created by Overture ") + (version4 ? "4" : "3"); messageOut(str); if( !jump(6) ) { return false; } // show page margin if (!readBuffer(placeHolder, 1)) { return false; } ove_->setShowPageMargin(placeHolder.toBoolean()); if( !jump(1) ) { return false; } // transpose track if (!readBuffer(placeHolder, 1)) { return false; } ove_->setShowTransposeTrack(placeHolder.toBoolean()); // play repeat if (!readBuffer(placeHolder, 1)) { return false; } ove_->setPlayRepeat(placeHolder.toBoolean()); // play style if (!readBuffer(placeHolder, 1)) { return false; } OveSong::PlayStyle style = OveSong::Record; if(placeHolder.toUnsignedInt() == 1){ style = OveSong::Swing; } else if(placeHolder.toUnsignedInt() == 2){ style = OveSong::Notation; } ove_->setPlayStyle(style); // show line break if (!readBuffer(placeHolder, 1)) { return false; } ove_->setShowLineBreak(placeHolder.toBoolean()); // show ruler if (!readBuffer(placeHolder, 1)) { return false; } ove_->setShowRuler(placeHolder.toBoolean()); // show color if (!readBuffer(placeHolder, 1)) { return false; } ove_->setShowColor(placeHolder.toBoolean()); return true; } /////////////////////////////////////////////////////////////////////////////// TrackParse::TrackParse(OveSong* ove) :BasicParse(ove) { } TrackParse::~TrackParse() { } void TrackParse::setTrack(SizeChunk* chunk) { chunk_ = chunk; } bool TrackParse::parse() { Block* dataBlock = chunk_->getDataBlock(); unsigned int blockSize = ove_->getIsVersion4() ? chunk_->getSizeBlock()->toSize() : SizeChunk::version3TrackSize; StreamHandle handle(dataBlock->data(), blockSize); Block placeHolder; handle_ = &handle; Track* oveTrack = new Track(); ove_->addTrack(oveTrack); // 2 32bytes long track name buffer if( !readBuffer(placeHolder, 32) ) { return false; } oveTrack->setName(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray())); if( !readBuffer(placeHolder, 32) ) { return false; } oveTrack->setBriefName(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray())); if( !jump(8) ) { return false; } //0x fffa0012 fffa0012 if( !jump(1) ) { return false; } // patch if( !readBuffer(placeHolder, 1) ) { return false; } unsigned int thisByte = placeHolder.toInt(); oveTrack->setPatch(thisByte&0x7f); // show name if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setShowName(placeHolder.toBoolean()); // show brief name if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setShowBriefName(placeHolder.toBoolean()); if( !jump(1) ) { return false; } // show transpose if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setShowTranspose(placeHolder.toBoolean()); if( !jump(1) ) { return false; } // mute if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setMute(placeHolder.toBoolean()); // solo if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setSolo(placeHolder.toBoolean()); if( !jump(1) ) { return false; } // show key each line if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setShowKeyEachLine(placeHolder.toBoolean()); // voice count if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setVoiceCount(placeHolder.toUnsignedInt()); if( !jump(3) ) { return false; } // transpose value [-127, 127] if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setTranspose(placeHolder.toInt()); if( !jump(2) ) { return false; } // start clef if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setStartClef(placeHolder.toUnsignedInt()); // transpose celf if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setTransposeClef(placeHolder.toUnsignedInt()); // start key if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setStartKey(placeHolder.toUnsignedInt()); // display percent if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setDisplayPercent(placeHolder.toUnsignedInt()); // show leger line if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setShowLegerLine(placeHolder.toBoolean()); // show clef if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setShowClef(placeHolder.toBoolean()); // show time signature if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setShowTimeSignature(placeHolder.toBoolean()); // show key signature if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setShowKeySignature(placeHolder.toBoolean()); // show barline if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setShowBarline(placeHolder.toBoolean()); // fill with rest if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setFillWithRest(placeHolder.toBoolean()); // flat tail if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setFlatTail(placeHolder.toBoolean()); // show clef each line if( !readBuffer(placeHolder, 1) ) { return false; } oveTrack->setShowClefEachLine(placeHolder.toBoolean()); if( !jump(12) ) { return false; } // 8 voices int i; QList voices; for( i=0; i<8; ++i ) { Voice* voicePtr = new Voice(); if( !jump(5) ) { return false; } // channel if( !readBuffer(placeHolder, 1) ) { return false; } voicePtr->setChannel(placeHolder.toUnsignedInt()); // volume if( !readBuffer(placeHolder, 1) ) { return false; } voicePtr->setVolume(placeHolder.toInt()); // pitch shift if( !readBuffer(placeHolder, 1) ) { return false; } voicePtr->setPitchShift(placeHolder.toInt()); // pan if( !readBuffer(placeHolder, 1) ) { return false; } voicePtr->setPan(placeHolder.toInt()); if( !jump(6) ) { return false; } // patch if( !readBuffer(placeHolder, 1) ) { return false; } voicePtr->setPatch(placeHolder.toInt()); voices.push_back(voicePtr); } // stem type for( i=0; i<8; ++i ) { if( !readBuffer(placeHolder, 1) ) { return false; } voices[i]->setStemType(placeHolder.toUnsignedInt()); oveTrack->addVoice(voices[i]); } // percussion define QList nodes; for(i=0; i<16; ++i) { nodes.push_back(Track::DrumNode()); } // line for( i=0; i<16; ++i ) { if( !readBuffer(placeHolder, 1) ) { return false; } nodes[i].line_ = placeHolder.toInt(); } // head type for( i=0; i<16; ++i ) { if( !readBuffer(placeHolder, 1) ) { return false; } nodes[i].headType_ = placeHolder.toUnsignedInt(); } // pitch for( i=0; i<16; ++i ) { if( !readBuffer(placeHolder, 1) ) { return false; } nodes[i].pitch_ = placeHolder.toUnsignedInt(); } // voice for( i=0; i<16; ++i ) { if( !readBuffer(placeHolder, 1) ) { return false; } nodes[i].voice_ = placeHolder.toUnsignedInt(); } for( i=0; iaddDrum(nodes[i]); } /* if( !Jump(17) ) { return false; } // voice 0 channel if( !ReadBuffer(placeHolder, 1) ) { return false; } oveTrack->setChannel(placeHolder.toUnsignedInt()); // to be continued. if anything important...*/ return true; } /////////////////////////////////////////////////////////////////////////////// GroupParse::GroupParse(OveSong* ove) :BasicParse(ove) { } GroupParse::~GroupParse(){ sizeChunks_.clear(); } void GroupParse::addSizeChunk(SizeChunk* sizeChunk) { sizeChunks_.push_back(sizeChunk); } bool GroupParse::parse() { return false; } /////////////////////////////////////////////////////////////////////////////// PageGroupParse::PageGroupParse(OveSong* ove) :BasicParse(ove) { } PageGroupParse::~PageGroupParse(){ pageChunks_.clear(); } void PageGroupParse::addPage(SizeChunk* chunk) { pageChunks_.push_back(chunk); } bool PageGroupParse::parse() { if( pageChunks_.empty() ) { return false; } int i; for( i=0; iaddPage(page); if( !parsePage(pageChunks_[i], page) ) { return false; } } return true; } bool PageGroupParse::parsePage(SizeChunk* chunk, Page* page) { Block placeHolder(2); StreamHandle handle(chunk->getDataBlock()->data(), chunk->getSizeBlock()->toSize()); handle_ = &handle; // begin line if( !readBuffer(placeHolder, 2) ) { return false; } page->setBeginLine(placeHolder.toUnsignedInt()); // line count if( !readBuffer(placeHolder, 2) ) { return false; } page->setLineCount(placeHolder.toUnsignedInt()); if( !jump(4) ) { return false; } // staff interval if( !readBuffer(placeHolder, 2) ) { return false; } page->setStaffInterval(placeHolder.toUnsignedInt()); // line interval if( !readBuffer(placeHolder, 2) ) { return false; } page->setLineInterval(placeHolder.toUnsignedInt()); // staff inline interval if( !readBuffer(placeHolder, 2) ) { return false; } page->setStaffInlineInterval(placeHolder.toUnsignedInt()); // line bar count if( !readBuffer(placeHolder, 2) ) { return false; } page->setLineBarCount(placeHolder.toUnsignedInt()); // page line count if( !readBuffer(placeHolder, 2) ) { return false; } page->setPageLineCount(placeHolder.toUnsignedInt()); // left margin if( !readBuffer(placeHolder, 4) ) { return false; } page->setLeftMargin(placeHolder.toUnsignedInt()); // top margin if( !readBuffer(placeHolder, 4) ) { return false; } page->setTopMargin(placeHolder.toUnsignedInt()); // right margin if( !readBuffer(placeHolder, 4) ) { return false; } page->setRightMargin(placeHolder.toUnsignedInt()); // bottom margin if( !readBuffer(placeHolder, 4) ) { return false; } page->setBottomMargin(placeHolder.toUnsignedInt()); // page width if( !readBuffer(placeHolder, 4) ) { return false; } page->setPageWidth(placeHolder.toUnsignedInt()); // page height if( !readBuffer(placeHolder, 4) ) { return false; } page->setPageHeight(placeHolder.toUnsignedInt()); handle_ = NULL; return true; } /////////////////////////////////////////////////////////////////////////////// StaffCountGetter::StaffCountGetter(OveSong* ove) :BasicParse(ove) { } unsigned int StaffCountGetter::getStaffCount(SizeChunk* chunk) { StreamHandle handle(chunk->getDataBlock()->data(), chunk->getSizeBlock()->toSize()); Block placeHolder; handle_ = &handle; if( !jump(6) ) { return false; } // staff count if( !readBuffer(placeHolder, 2) ) { return false; } return placeHolder.toUnsignedInt(); } /////////////////////////////////////////////////////////////////////////////// LineGroupParse::LineGroupParse(OveSong* ove) : BasicParse(ove), chunk_(NULL) { } LineGroupParse::~LineGroupParse(){ chunk_ = NULL; lineChunks_.clear(); staffChunks_.clear(); } void LineGroupParse::setLineGroup(GroupChunk* chunk) { chunk_ = chunk; } void LineGroupParse::addLine(SizeChunk* chunk) { lineChunks_.push_back(chunk); } void LineGroupParse::addStaff(SizeChunk* chunk) { staffChunks_.push_back(chunk); } bool LineGroupParse::parse() { if( lineChunks_.empty() || staffChunks_.size() % lineChunks_.size() != 0 ) { return false; } int i; unsigned int j; unsigned int lineStaffCount = staffChunks_.size() / lineChunks_.size(); for( i=0; iaddLine(linePtr); if( !parseLine(lineChunks_[i], linePtr) ) { return false; } for( j=lineStaffCount*i; jaddStaff(staffPtr); if( !parseStaff(staffChunks_[j], staffPtr) ) { return false; } } } return true; } bool LineGroupParse::parseLine(SizeChunk* chunk, Line* line) { Block placeHolder; StreamHandle handle(chunk->getDataBlock()->data(), chunk->getSizeBlock()->toSize()); handle_ = &handle; if( !jump(2) ) { return false; } // begin bar if( !readBuffer(placeHolder, 2) ) { return false; } line->setBeginBar(placeHolder.toUnsignedInt()); // bar count if( !readBuffer(placeHolder, 2) ) { return false; } line->setBarCount(placeHolder.toUnsignedInt()); if( !jump(6) ) { return false; } // y offset if( !readBuffer(placeHolder, 2) ) { return false; } line->setYOffset(placeHolder.toInt()); // left x offset if( !readBuffer(placeHolder, 2) ) { return false; } line->setLeftXOffset(placeHolder.toInt()); // right x offset if( !readBuffer(placeHolder, 2) ) { return false; } line->setRightXOffset(placeHolder.toInt()); if( !jump(4) ) { return false; } handle_ = NULL; return true; } bool LineGroupParse::parseStaff(SizeChunk* chunk, Staff* staff) { Block placeHolder; StreamHandle handle(chunk->getDataBlock()->data(), chunk->getSizeBlock()->toSize()); handle_ = &handle; if( !jump(7) ) { return false; } // clef if( !readBuffer(placeHolder, 1) ) { return false; } staff->setClefType(placeHolder.toUnsignedInt()); // key if( !readBuffer(placeHolder, 1) ) { return false; } staff->setKeyType(oveKeyToKey(placeHolder.toUnsignedInt())); if( !jump(2) ) { return false; } // visible if( !readBuffer(placeHolder, 1) ) { return false; } staff->setVisible(placeHolder.toBoolean()); if( !jump(12) ) { return false; } // y offset if( !readBuffer(placeHolder, 2) ) { return false; } staff->setYOffset(placeHolder.toInt()); int jumpAmount = ove_->getIsVersion4() ? 26 : 18; if( !jump(jumpAmount) ) { return false; } // group type if( !readBuffer(placeHolder, 1) ) { return false; } GroupType groupType = Group_None; if(placeHolder.toUnsignedInt() == 1) { groupType = Group_Brace; } else if(placeHolder.toUnsignedInt() == 2) { groupType = Group_Bracket; } staff->setGroupType(groupType); // group staff count if( !readBuffer(placeHolder, 1) ) { return false; } staff->setGroupStaffCount(placeHolder.toUnsignedInt()); handle_ = NULL; return true; } /////////////////////////////////////////////////////////////////////////////// BarsParse::BarsParse(OveSong* ove) : BasicParse(ove) { } BarsParse::~BarsParse(){ measureChunks_.clear(); conductChunks_.clear(); bdatChunks_.clear(); } void BarsParse::addMeasure(SizeChunk* chunk) { measureChunks_.push_back(chunk); } void BarsParse::addConduct(SizeChunk* chunk) { conductChunks_.push_back(chunk); } void BarsParse::addBdat(SizeChunk* chunk) { bdatChunks_.push_back(chunk); } bool BarsParse::parse() { int i; int trackMeasureCount = ove_->getTrackBarCount(); int trackCount = ove_->getTrackCount(); int measureDataCount = trackCount * measureChunks_.size(); QList measures; QList measureDatas; if( measureChunks_.empty() || measureChunks_.size() != conductChunks_.size() || (int)bdatChunks_.size() != measureDataCount ) { return false; } // add to ove for ( i=0; i<(int)measureChunks_.size(); ++i ) { Measure* measure = new Measure(i); measures.push_back(measure); ove_->addMeasure(measure); } for ( i=0; iaddMeasureData(oveMeasureData); } for( i=0; i<(int)measureChunks_.size(); ++i ) { Measure* measure = measures[i]; // MEAS if( !parseMeas(measure, measureChunks_[i]) ) { QString ss = "failed in parse MEAS " + i; messageOut(ss); return false; } } for( i=0; i<(int)conductChunks_.size(); ++i ) { // COND if( !parseCond(measures[i], measureDatas[i], conductChunks_[i]) ) { QString ss = "failed in parse COND " + i; messageOut(ss); return false; } } for( i=0; i<(int)bdatChunks_.size(); ++i ) { int measId = i % trackMeasureCount; // BDAT if( !parseBdat(measures[measId], measureDatas[i], bdatChunks_[i]) ) { QString ss = "failed in parse BDAT " + i; messageOut(ss); return false; } if( notify_ != NULL ) { int measureID = i % trackMeasureCount; int trackID = i / trackMeasureCount; //msg.msg_ = OVE_IMPORT_POS; //msg.param1_ = (measureID<<16) + trackMeasureCount; //msg.param2_ = (trackID<<16) + trackCount; notify_->loadPosition(measureID, trackMeasureCount, trackID, trackCount); } } return true; } bool BarsParse::parseMeas(Measure* measure, SizeChunk* chunk) { Block placeHolder; StreamHandle measureHandle(chunk->getDataBlock()->data(), chunk->getSizeBlock()->toSize()); handle_ = &measureHandle; if( !jump(2) ) { return false; } // multi-measure rest if( !readBuffer(placeHolder, 1) ) { return false; } measure->setIsMultiMeasureRest(placeHolder.toBoolean()); // pickup if( !readBuffer(placeHolder, 1) ) { return false; } measure->setIsPickup(placeHolder.toBoolean()); if( !jump(4) ) { return false; } // left barline if( !readBuffer(placeHolder, 1) ) { return false; } measure->setLeftBarline(placeHolder.toUnsignedInt()); // right barline if( !readBuffer(placeHolder, 1) ) { return false; } measure->setRightBarline(placeHolder.toUnsignedInt()); // tempo if( !readBuffer(placeHolder, 2) ) { return false; } double tempo = ((double)placeHolder.toUnsignedInt()); if( ove_->getIsVersion4() ) { tempo /= 100.0; } measure->setTypeTempo(tempo); // bar length(tick) if( !readBuffer(placeHolder, 2) ) { return false; } measure->setLength(placeHolder.toUnsignedInt()); if( !jump(6) ) { return false; } // bar number offset if( !parseOffsetElement(measure->getBarNumber()) ) { return false; } if( !jump(2) ) { return false; } // multi-measure rest count if( !readBuffer(placeHolder, 2) ) { return false; } measure->setMultiMeasureRestCount(placeHolder.toUnsignedInt()); handle_ = NULL; return true; } bool BarsParse::parseCond(Measure* measure, MeasureData* measureData, SizeChunk* chunk) { Block placeHolder; StreamHandle handle(chunk->getDataBlock()->data(), chunk->getSizeBlock()->toSize()); handle_ = &handle; // item count if( !readBuffer(placeHolder, 2) ) { return false; } unsigned int cnt = placeHolder.toUnsignedInt(); if( !parseTimeSignature(measure, 36) ) { return false; } for( unsigned int i=0; igetTime(); // numerator if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setNumerator(placeHolder.toUnsignedInt()); // denominator if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setDenominator(placeHolder.toUnsignedInt()); if( !jump(2) ) { return false; } // beat length if( !readBuffer(placeHolder, 2) ) { return false; } timeSignature->setBeatLength(placeHolder.toUnsignedInt()); // bar length if( !readBuffer(placeHolder, 2) ) { return false; } timeSignature->setBarLength(placeHolder.toUnsignedInt()); if( !jump(4) ) { return false; } // is symbol if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setIsSymbol(placeHolder.toBoolean()); if( !jump(1) ) { return false; } // replace font if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setReplaceFont(placeHolder.toBoolean()); // color if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setColor(placeHolder.toUnsignedInt()); // show if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setShow(placeHolder.toBoolean()); // show beat group if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setShowBeatGroup(placeHolder.toBoolean()); if( !jump(6) ) { return false; } // numerator 1, 2, 3 if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setGroupNumerator1(placeHolder.toUnsignedInt()); if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setGroupNumerator2(placeHolder.toUnsignedInt()); if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setGroupNumerator3(placeHolder.toUnsignedInt()); // denominator if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setGroupDenominator1(placeHolder.toUnsignedInt()); if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setGroupDenominator2(placeHolder.toUnsignedInt()); if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setGroupDenominator3(placeHolder.toUnsignedInt()); // beam group 1~4 if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setBeamGroup1(placeHolder.toUnsignedInt()); if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setBeamGroup2(placeHolder.toUnsignedInt()); if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setBeamGroup3(placeHolder.toUnsignedInt()); if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->setBeamGroup4(placeHolder.toUnsignedInt()); // beam 16th if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->set16thBeamCount(placeHolder.toUnsignedInt()); // beam 32th if( !readBuffer(placeHolder, 1) ) { return false; } timeSignature->set32thBeamCount(placeHolder.toUnsignedInt()); return true; } bool BarsParse::parseTimeSignatureParameters(Measure* measure, int length) { Block placeHolder; TimeSignature* ts = measure->getTime(); int cursor = ove_->getIsVersion4() ? 10 : 8; if( !jump(cursor) ) { return false; } // numerator if( !readBuffer(placeHolder, 1) ) { return false; } unsigned int numerator = placeHolder.toUnsignedInt(); cursor = ove_->getIsVersion4() ? 11 : 9; if( ( length - cursor ) % 8 != 0 || (length - cursor) / 8 != (int)numerator ) { return false; } for( unsigned int i =0; iaddBeat(beatStart, beatLength, beatStartTick); } ts->endAddBeat(); return true; } bool BarsParse::parseBarlineParameters(Measure* measure, int /*length*/) { Block placeHolder; int cursor = ove_->getIsVersion4() ? 12 : 10; if( !jump(cursor) ) { return false; } // repeat count if( !readBuffer(placeHolder, 1) ) { return false; } int repeatCount = placeHolder.toUnsignedInt(); measure->setBackwardRepeatCount(repeatCount); if( !jump(6) ) { return false; } return true; } bool BarsParse::parseNumericEndings(MeasureData* measureData, int /*length*/) { Block placeHolder; NumericEnding* numeric = new NumericEnding(); measureData->addCrossMeasureElement(numeric, true); if( !jump(3) ) { return false; } // common if( !parseCommonBlock(numeric) ) { return false; } if( !jump(6) ) { return false; } // measure count if( !readBuffer(placeHolder, 2) ) { return false; } //int offsetMeasure = placeHolder.toUnsignedInt() - 1; int offsetMeasure = placeHolder.toUnsignedInt(); numeric->stop()->setMeasure(offsetMeasure); if( !jump(2) ) { return false; } // left x offset if( !readBuffer(placeHolder, 2) ) { return false; } numeric->getLeftShoulder()->setXOffset(placeHolder.toInt()); // height if( !readBuffer(placeHolder, 2) ) { return false; } numeric->setHeight(placeHolder.toUnsignedInt()); // left x offset if( !readBuffer(placeHolder, 2) ) { return false; } numeric->getRightShoulder()->setXOffset(placeHolder.toInt()); if( !jump(2) ) { return false; } // y offset if( !readBuffer(placeHolder, 2) ) { return false; } numeric->getLeftShoulder()->setYOffset(placeHolder.toInt()); numeric->getRightShoulder()->setYOffset(placeHolder.toInt()); // number offset if( !readBuffer(placeHolder, 2) ) { return false; } numeric->getNumericHandle()->setXOffset(placeHolder.toInt()); if( !readBuffer(placeHolder, 2) ) { return false; } numeric->getNumericHandle()->setYOffset(placeHolder.toInt()); if( !jump(6) ) { return false; } // text size if( !readBuffer(placeHolder, 1) ) { return false; } unsigned int size = placeHolder.toUnsignedInt(); // text : size maybe a huge value if( !readBuffer(placeHolder, size) ) { return false; } numeric->setText(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray())); // fix for wedding march.ove if( size % 2 == 0 ) { if( !jump(1) ) { return false; } } return true; } bool BarsParse::parseTempo(MeasureData* measureData, int /*length*/) { Block placeHolder; unsigned int thisByte; Tempo* tempo = new Tempo(); measureData->addMusicData(tempo); if( !jump(3) ) { return false; } // common if( !parseCommonBlock(tempo) ) { return false; } if( !readBuffer(placeHolder, 1) ) { return false; } thisByte = placeHolder.toUnsignedInt(); // show tempo tempo->setShowMark( (getHighNibble(thisByte) & 0x4) == 0x4 ); // show before text tempo->setShowBeforeText( (getHighNibble(thisByte) & 0x8 ) == 0x8 ) ; // show parenthesis tempo->setShowParenthesis( (getHighNibble(thisByte) & 0x1 ) == 0x1 ); // left note type tempo->setLeftNoteType( getLowNibble(thisByte) ); if( !jump(1) ) { return false; } if( ove_->getIsVersion4() ) { if( !jump(2) ) { return false; } // tempo if( !readBuffer(placeHolder, 2) ) { return false; } tempo->setTypeTempo(placeHolder.toUnsignedInt()/100); } else { // tempo if( !readBuffer(placeHolder, 2) ) { return false; } tempo->setTypeTempo(placeHolder.toUnsignedInt()); if( !jump(2) ) { return false; } } // offset if( !parseOffsetElement(tempo) ) { return false; } if( !jump(16) ) { return false; } // 31 bytes left text if( !readBuffer(placeHolder, 31) ) { return false; } tempo->setLeftText(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray())); if( !readBuffer(placeHolder, 1) ) { return false; } thisByte = placeHolder.toUnsignedInt(); // swing eighth tempo->setSwingEighth(getHighNibble(thisByte)!=8); // right note type tempo->setRightNoteType(getLowNibble(thisByte)); // right text if( ove_->getIsVersion4() ) { if( !readBuffer(placeHolder, 31) ) { return false; } tempo->setRightText(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray())); if( !jump(1) ) { return false; } } return true; } bool BarsParse::parseBarNumber(Measure* measure, int /*length*/) { Block placeHolder; BarNumber* barNumber = measure->getBarNumber(); if( !jump(2) ) { return false; } // show on paragraph start if( !readBuffer(placeHolder, 1) ) { return false; } barNumber->setShowOnParagraphStart(getLowNibble(placeHolder.toUnsignedInt())==8); unsigned int blankSize = ove_->getIsVersion4() ? 9 : 7; if( !jump(blankSize) ) { return false; } // text align if( !readBuffer(placeHolder, 1) ) { return false; } barNumber->setAlign(placeHolder.toUnsignedInt()); if( !jump(4) ) { return false; } // show flag if( !readBuffer(placeHolder, 1) ) { return false; } barNumber->setShowFlag(placeHolder.toUnsignedInt()); if( !jump(10) ) { return false; } // bar range if( !readBuffer(placeHolder, 1) ) { return false; } barNumber->setShowEveryBarCount(placeHolder.toUnsignedInt()); // prefix if( !readBuffer(placeHolder, 2) ) { return false; } barNumber->setPrefix(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray())); if( !jump(18) ) { return false; } return true; } bool BarsParse::parseText(MeasureData* measureData, int length) { Block placeHolder; Text* text = new Text(); measureData->addMusicData(text); if( !jump(3) ) { return false; } // common if( !parseCommonBlock(text) ) { return false; } // type if( !readBuffer(placeHolder, 1) ) { return false; } unsigned int thisByte = placeHolder.toUnsignedInt(); bool includeLineBreak = ( (getHighNibble(thisByte)&0x2) != 0x2 ); unsigned int id = getLowNibble(thisByte); Text::TextType textType = Text::Text_Rehearsal; if (id == 0) { textType = Text::Text_MeasureText; } else if (id == 1) { textType = Text::Text_SystemText; } else // id ==2 { textType = Text::Text_Rehearsal; } text->setTextType(textType); if( !jump(1) ) { return false; } // x offset if( !readBuffer(placeHolder, 4) ) { return false; } text->setXOffset(placeHolder.toInt()); // y offset if( !readBuffer(placeHolder, 4) ) { return false; } text->setYOffset(placeHolder.toInt()); // width if( !readBuffer(placeHolder, 4) ) { return false; } text->setWidth(placeHolder.toUnsignedInt()); // height if( !readBuffer(placeHolder, 4) ) { return false; } text->setHeight(placeHolder.toUnsignedInt()); if( !jump(7) ) { return false; } // horizontal margin if( !readBuffer(placeHolder, 1) ) { return false; } text->setHorizontalMargin(placeHolder.toUnsignedInt()); if( !jump(1) ) { return false; } // vertical margin if( !readBuffer(placeHolder, 1) ) { return false; } text->setVerticalMargin(placeHolder.toUnsignedInt()); if( !jump(1) ) { return false; } // line thick if( !readBuffer(placeHolder, 1) ) { return false; } text->setLineThick(placeHolder.toUnsignedInt()); if( !jump(2) ) { return false; } // text size if( !readBuffer(placeHolder, 2) ) { return false; } unsigned int size = placeHolder.toUnsignedInt(); // text string, maybe huge if( !readBuffer(placeHolder, size) ) { return false; } text->setText(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray())); if( !includeLineBreak ) { if( !jump(6) ) { return false; } } else { unsigned int cursor = ove_->getIsVersion4() ? 43 : 41; cursor += size; // multi lines of text for( unsigned int i=0; i<2; ++i ) { if( (int)cursor < length ) { // line parameters count if( !readBuffer(placeHolder, 2) ) { return false; } unsigned int lineCount = placeHolder.toUnsignedInt(); if( i==0 && int(cursor + 2 + 8*lineCount) > length ) { return false; } if( i==1 && int(cursor + 2 + 8*lineCount) != length ) { return false; } if( !jump(8*lineCount) ) { return false; } cursor += 2 + 8*lineCount; } } } return true; } bool BarsParse::parseRepeatSymbol(MeasureData* measureData, int /*length*/) { Block placeHolder; RepeatSymbol* repeat = new RepeatSymbol(); measureData->addMusicData(repeat); if( !jump(3) ) { return false; } // common if( !parseCommonBlock(repeat) ) { return false; } // RepeatType if( !readBuffer(placeHolder, 1) ) { return false; } repeat->setRepeatType(placeHolder.toUnsignedInt()); if( !jump(13) ) { return false; } // offset if( !parseOffsetElement(repeat) ) { return false; } if( !jump(15) ) { return false; } // size if( !readBuffer(placeHolder, 2) ) { return false; } unsigned int size = placeHolder.toUnsignedInt(); // text, maybe huge if( !readBuffer(placeHolder, size) ) { return false; } repeat->setText(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray())); // last 0 if( size % 2 == 0 ) { if( !jump(1) ) { return false; } } return true; } bool BarsParse::parseBdat(Measure* /*measure*/, MeasureData* measureData, SizeChunk* chunk) { Block placeHolder; StreamHandle handle(chunk->getDataBlock()->data(), chunk->getSizeBlock()->toSize()); handle_ = &handle; // parse here if( !readBuffer(placeHolder, 2) ) { return false; } unsigned int cnt = placeHolder.toUnsignedInt(); for( unsigned int i=0; i 0 ) { int factor = int(pow(2.0, bits-1)); num = (byte % (factor*2)); if ( (byte & factor) == factor ) { num -= factor*2; } } return num; } bool BarsParse::parseNoteRest(MeasureData* measureData, int length, BdatType type) { NoteContainer* container = new NoteContainer(); Block placeHolder; unsigned int thisByte; measureData->addNoteContainer(container); measureData->addMusicData(container); // note|rest & grace container->setIsRest(type==Bdat_Rest); container->setIsRaw(type==Bdat_Raw_Note); if( !readBuffer(placeHolder, 2) ) { return false; } thisByte = placeHolder.toUnsignedInt(); container->setIsGrace( thisByte == 0x3C00 ); container->setIsCue( thisByte == 0x4B40 || thisByte == 0x3240 ); // show / hide if( !readBuffer(placeHolder, 1) ) { return false; } thisByte = placeHolder.toUnsignedInt(); container->setShow(getLowNibble(thisByte)!=0x8); // voice container->setVoice(getLowNibble(thisByte)&0x7); // common if( !parseCommonBlock(container) ) { return false; } // tuplet if( !readBuffer(placeHolder, 1) ) { return false; } container->setTuplet(placeHolder.toUnsignedInt()); // space if( !readBuffer(placeHolder, 1) ) { return false; } container->setSpace(placeHolder.toUnsignedInt()); // in beam if( !readBuffer(placeHolder, 1) ) { return false; } thisByte = placeHolder.toUnsignedInt(); bool inBeam = ( getHighNibble(thisByte) & 0x1 ) == 0x1; container->setInBeam(inBeam); // grace NoteType container->setGraceNoteType((NoteType)getHighNibble(thisByte)); // dot container->setDot(getLowNibble(thisByte)&0x03); // NoteType if( !readBuffer(placeHolder, 1) ) { return false; } thisByte = placeHolder.toUnsignedInt(); container->setNoteType((NoteType)getLowNibble(thisByte)); int cursor = 0; if( type == Bdat_Rest ) { Note* restPtr = new Note(); container->addNoteRest(restPtr); restPtr->setIsRest(true); // line if( !readBuffer(placeHolder, 1) ) { return false; } restPtr->setLine(placeHolder.toInt()); if( !jump(1) ) { return false; } cursor = ove_->getIsVersion4() ? 16 : 14; } else // type == Bdat_Note || type == Bdat_Raw_Note { // stem up 0x80, stem down 0x00 if( !readBuffer(placeHolder, 1) ) { return false; } thisByte = placeHolder.toUnsignedInt(); container->setStemUp((getHighNibble(thisByte)&0x8)==0x8); // stem length int stemOffset = thisByte%0x80; container->setStemLength(getInt(stemOffset, 7)+7/*3.5 line span*/); // show stem 0x00, hide stem 0x40 if( !readBuffer(placeHolder, 1) ) { return false; } bool hideStem = getHighNibble(thisByte)==0x4; container->setShowStem(!hideStem); if( !jump(1) ) { return false; } // note count if( !readBuffer(placeHolder, 1) ) { return false; } unsigned int noteCount = placeHolder.toUnsignedInt(); unsigned int i; // each note 16 bytes for( i=0; isetIsRest(false); container->addNoteRest(notePtr); // note show / hide if( !readBuffer(placeHolder, 1) ) { return false; } thisByte = placeHolder.toUnsignedInt(); notePtr->setShow((thisByte&0x80) != 0x80); // note head type notePtr->setHeadType(thisByte&0x7f); // tie pos if( !readBuffer(placeHolder, 1) ) { return false; } thisByte = placeHolder.toUnsignedInt(); notePtr->setTiePos(getHighNibble(thisByte)); // offset staff, in {-1, 0, 1} if( !readBuffer(placeHolder, 1) ) { return false; } thisByte = getLowNibble(placeHolder.toUnsignedInt()); int offsetStaff = 0; if( thisByte == 1 ) { offsetStaff = 1; } if( thisByte == 7 ) { offsetStaff = -1; } notePtr->setOffsetStaff(offsetStaff); // accidental if( !readBuffer(placeHolder, 1) ) { return false; } thisByte = placeHolder.toUnsignedInt(); notePtr->setAccidental(getLowNibble(thisByte)); // accidental 0: influenced by key, 4: influenced by previous accidental in measure bool notShow = ( getHighNibble(thisByte) == 0 ) || ( getHighNibble(thisByte) == 4 ); notePtr->setShowAccidental(!notShow); if( !jump(1) ) { return false; } // line if( !readBuffer(placeHolder, 1) ) { return false; } notePtr->setLine(placeHolder.toInt()); if( !jump(1) ) { return false; } // note if( !readBuffer(placeHolder, 1) ) { return false; } unsigned int note = placeHolder.toUnsignedInt(); notePtr->setNote(note); // note on velocity if( !readBuffer(placeHolder, 1) ) { return false; } unsigned int onVelocity = placeHolder.toUnsignedInt(); notePtr->setOnVelocity(onVelocity); // note off velocity if( !readBuffer(placeHolder, 1) ) { return false; } unsigned int offVelocity = placeHolder.toUnsignedInt(); notePtr->setOffVelocity(offVelocity); if( !jump(2) ) { return false; } // length (tick) if( !readBuffer(placeHolder, 2) ) { return false; } container->setLength(placeHolder.toUnsignedInt()); // offset tick if( !readBuffer(placeHolder, 2) ) { return false; } notePtr->setOffsetTick(placeHolder.toInt()); } cursor = ove_->getIsVersion4() ? 18 : 16; cursor += noteCount * 16/*note size*/; } // articulation while ( cursor < length + 1/* 0x70 || 0x80 || 0x90 */ ) { Articulation* art = new Articulation(); container->addArticulation(art); // block size if( !readBuffer(placeHolder, 2) ) { return false; } int blockSize = placeHolder.toUnsignedInt(); // articulation type if( !readBuffer(placeHolder, 1) ) { return false; } art->setArtType(placeHolder.toUnsignedInt()); // placement if( !readBuffer(placeHolder, 1) ) { return false; } art->setPlacementAbove(placeHolder.toUnsignedInt()!=0x00); //0x00:below, 0x30:above // offset if( !parseOffsetElement(art) ) { return false; } if( !ove_->getIsVersion4() ) { if( blockSize - 8 > 0 ) { if( !jump(blockSize-8) ) { return false; } } } else { // setting if( !readBuffer(placeHolder, 1) ) { return false; } thisByte = placeHolder.toUnsignedInt(); const bool changeSoundEffect = ( ( thisByte & 0x1 ) == 0x1 ); const bool changeLength = ( ( thisByte & 0x2 ) == 0x2 ); const bool changeVelocity = ( ( thisByte & 0x4 ) == 0x4 ); //const bool changeExtraLength = ( ( thisByte & 0x20 ) == 0x20 ); if( !jump(8) ) { return false; } // velocity type if( !readBuffer(placeHolder, 1) ) { return false; } thisByte = placeHolder.toUnsignedInt(); if( changeVelocity ) { art->setVelocityType((Articulation::VelocityType)thisByte); } if( !jump(14) ) { return false; } // sound effect if( !readBuffer(placeHolder, 2) ) { return false; } int from = placeHolder.toInt(); if( !readBuffer(placeHolder, 2) ) { return false; } int to = placeHolder.toInt(); if( changeSoundEffect ) { art->setSoundEffect(from, to); } if( !jump(1) ) { return false; } // length percentage if( !readBuffer(placeHolder, 1) ) { return false; } if( changeLength ) { art->setLengthPercentage(placeHolder.toUnsignedInt()); } // velocity if( !readBuffer(placeHolder, 2) ) { return false; } if( changeVelocity ) { art->setVelocityValue(placeHolder.toInt()); } if( Articulation::isTrill(art->getArtType()) ) { if( !jump(8) ) { return false; } // trill note length if( !readBuffer(placeHolder, 1) ) { return false; } art->setTrillNoteLength(placeHolder.toUnsignedInt()); // trill rate if( !readBuffer(placeHolder, 1) ) { return false; } thisByte = placeHolder.toUnsignedInt(); NoteType trillNoteType = Note_Sixteen; switch ( getHighNibble(thisByte) ) { case 0: trillNoteType = Note_None; break; case 1: trillNoteType = Note_Sixteen; break; case 2: trillNoteType = Note_32; break; case 3: trillNoteType = Note_64; break; case 4: trillNoteType = Note_128; break; default: break; } art->setTrillRate(trillNoteType); // accelerate type art->setAccelerateType(thisByte&0xf); if( !jump(1) ) { return false; } // auxiliary first if( !readBuffer(placeHolder, 1) ) { return false; } art->setAuxiliaryFirst(placeHolder.toBoolean()); if( !jump(1) ) { return false; } // trill interval if( !readBuffer(placeHolder, 1) ) { return false; } art->setTrillInterval(placeHolder.toUnsignedInt()); } else { if( blockSize > 40 ) { if( !jump( blockSize - 40 ) ) { return false; } } } } cursor += blockSize; } return true; } int tupletToSpace(int tuplet) { int a(1); while( a*2 < tuplet ) { a *= 2; } return a; } bool BarsParse::parseBeam(MeasureData* measureData, int length) { int i; Block placeHolder; Beam* beam = new Beam(); measureData->addCrossMeasureElement(beam, true); // maybe create tuplet, for < quarter & tool 3( bool createTuplet = false; int maxEndUnit = 0; Tuplet* tuplet = new Tuplet(); // is grace if( !readBuffer(placeHolder, 1) ) { return false; } beam->setIsGrace(placeHolder.toBoolean()); if( !jump(1) ) { return false; } // voice if( !readBuffer(placeHolder, 1) ) { return false; } beam->setVoice(getLowNibble(placeHolder.toUnsignedInt())&0x7); // common if( !parseCommonBlock(beam) ) { return false; } if( !jump(2) ) { return false; } // beam count if( !readBuffer(placeHolder, 1) ) { return false; } int beamCount = placeHolder.toUnsignedInt(); if( !jump(1) ) { return false; } // left line if( !readBuffer(placeHolder, 1) ) { return false; } beam->getLeftLine()->setLine(placeHolder.toInt()); // right line if( !readBuffer(placeHolder, 1) ) { return false; } beam->getRightLine()->setLine(placeHolder.toInt()); if( ove_->getIsVersion4() ) { if( !jump(8) ) { return false; } } int currentCursor = ove_->getIsVersion4() ? 23 : 13; int count = (length - currentCursor)/16; if( count != beamCount ) { return false; } for( i=0; i 0 ) { createTuplet = true; tuplet->setTuplet(tupletCount); tuplet->setSpace(tupletToSpace(tupletCount)); } // start / stop measure // line i start end position MeasurePos startMp; MeasurePos stopMp; if( !readBuffer(placeHolder, 1) ) { return false; } startMp.setMeasure(placeHolder.toUnsignedInt()); if( !readBuffer(placeHolder, 1) ) { return false; } stopMp.setMeasure(placeHolder.toUnsignedInt()); if( !readBuffer(placeHolder, 2) ) { return false; } startMp.setOffset(placeHolder.toInt()); if( !readBuffer(placeHolder, 2) ) { return false; } stopMp.setOffset(placeHolder.toInt()); beam->addLine(startMp, stopMp); if( stopMp.getOffset() > maxEndUnit ) { maxEndUnit = stopMp.getOffset(); } if( i == 0 ) { if( !jump(4) ) { return false; } // left offset up+4, down-4 if( !readBuffer(placeHolder, 2) ) { return false; } beam->getLeftShoulder()->setYOffset(placeHolder.toInt()); // right offset up+4, down-4 if( !readBuffer(placeHolder, 2) ) { return false; } beam->getRightShoulder()->setYOffset(placeHolder.toInt()); } else { if( !jump(8) ) { return false; } } } const QList > lines = beam->getLines(); MeasurePos offsetMp; for( i=0; i offsetMp ) { offsetMp = lines[i].second; } } beam->stop()->setMeasure(offsetMp.getMeasure()); beam->stop()->setOffset(offsetMp.getOffset()); // a case that Tuplet block don't exist, and hide inside beam if( createTuplet ) { tuplet->copyCommonBlock(*beam); tuplet->getLeftLine()->setLine(beam->getLeftLine()->getLine()); tuplet->getRightLine()->setLine(beam->getRightLine()->getLine()); tuplet->stop()->setMeasure(beam->stop()->getMeasure()); tuplet->stop()->setOffset(maxEndUnit); measureData->addCrossMeasureElement(tuplet, true); } else { delete tuplet; } return true; } bool BarsParse::parseTie(MeasureData* measureData, int /*length*/) { Block placeHolder; Tie* tie = new Tie(); measureData->addCrossMeasureElement(tie, true); if( !jump(3) ) { return false; } // start common if( !parseCommonBlock(tie) ) { return false; } if( !jump(1) ) { return false; } // note if( !readBuffer(placeHolder, 1) ) { return false; } tie->setNote(placeHolder.toUnsignedInt()); // pair lines if( !parsePairLinesBlock(tie) ) { return false; } // offset common if( !parseOffsetCommonBlock(tie) ) { return false; } // left shoulder offset if( !parseOffsetElement(tie->getLeftShoulder()) ) { return false; } // right shoulder offset if( !parseOffsetElement(tie->getRightShoulder()) ) { return false; } // height if( !readBuffer(placeHolder, 2) ) { return false; } tie->setHeight(placeHolder.toUnsignedInt()); return true; } bool BarsParse::parseTuplet(MeasureData* measureData, int /*length*/) { Block placeHolder; Tuplet* tuplet = new Tuplet(); measureData->addCrossMeasureElement(tuplet, true); if( !jump(3) ) { return false; } // common if( !parseCommonBlock(tuplet) ) { return false; } if( !jump(2) ) { return false; } // pair lines if( !parsePairLinesBlock(tuplet) ) { return false; } // offset common if( !parseOffsetCommonBlock(tuplet) ) { return false; } // left shoulder offset if( !parseOffsetElement(tuplet->getLeftShoulder()) ) { return false; } // right shoulder offset if( !parseOffsetElement(tuplet->getRightShoulder()) ) { return false; } if( !jump(2) ) { return false; } // height if( !readBuffer(placeHolder, 2) ) { return false; } tuplet->setHeight(placeHolder.toUnsignedInt()); // tuplet if( !readBuffer(placeHolder, 1) ) { return false; } tuplet->setTuplet(placeHolder.toUnsignedInt()); // space if( !readBuffer(placeHolder, 1) ) { return false; } tuplet->setSpace(placeHolder.toUnsignedInt()); // mark offset if( !parseOffsetElement(tuplet->getMarkHandle()) ) { return false; } return true; } HarmonyType binaryToHarmonyType(int bin) { HarmonyType type = Harmony_maj; if( bin == 0x0091 ) { type = Harmony_maj; } else if( bin == 0x0089 ) { type = Harmony_min; } else if( bin == 0x0489 ) { type = Harmony_min7; } else if( bin == 0x0491 ) { type = Harmony_7; } else if( bin == 0x0495 ) { type = Harmony_9; } else if( bin == 0x0449 ) { type = Harmony_min7b5; } else if( bin == 0x04A1 ) { type = Harmony_7sus4; } else if( bin == 0x00A1 ) { type = Harmony_sus4; } else if( bin == 0x0049 ) { type = Harmony_dim; } else if( bin == 0x0249 ) { type = Harmony_dim7; } else if( bin == 0x0111 ) { type = Harmony_aug; } else if( bin == 0x0511 ) { type = Harmony_aug7; } else if( bin == 0x044D ) { type = Harmony_min9_b5; } else if( bin == 0x0499 ) { type = Harmony_7s9; } else if( bin == 0x0615 ) { type = Harmony_13; } else if( bin == 0x0289 ) { type = Harmony_min6; } else if( bin == 0x0291 ) { type = Harmony_6; } else if( bin == 0x0295 ) { type = Harmony_6; //6add9 } else if( bin == 0x0095 ) { type = Harmony_min; //minor add9 } else if( bin == 0x008D ) { type = Harmony_maj7; } else if( bin == 0x0891 ) { type = Harmony_maj7; } else if( bin == 0x0881 ) { type = Harmony_maj7_s5; //maj7#5 } else if( bin == 0x0911 ) { type = Harmony_maj7_s5; //maj7#5 } else if( bin == 0x0991 ) { type = Harmony_maj7_s11;//maj7#11 } else if( bin == 0x0851 ) { type = Harmony_maj7_s11;//maj7#11 } else if( bin == 0x08D1 ) { type = Harmony_maj9; } else if( bin == 0x0895 ) { type = Harmony_maj9_s5; //maj9#5 } else if( bin == 0x0995 ) { type = Harmony_maj13_s11;//maj9#11 } else if( bin == 0x0855 ) { type = Harmony_maj9_s11;//maj9#11 } else if( bin == 0x08D5 ) { type = Harmony_maj13; } else if( bin == 0x0A95 ) { type = Harmony_maj13_s11;//maj13#11 } else if( bin == 0x0A55 ) { type = Harmony_maj13; //maj13(no3) } else if( bin == 0x0A85 ) { type = Harmony_maj9_s5; //maj13#5#11(no4) } else if( bin == 0x0B45 ) { type = Harmony_7b9; } else if( bin == 0x0493 ) { type = Harmony_7b5; } else if( bin == 0x0451 ) { type = Harmony_9b5; } else if( bin == 0x0455 ) { type = Harmony_7s9; //7#5#9 } else if( bin == 0x0519 ) { type = Harmony_7b9; //7#5b9 } else if( bin == 0x0513 ) { type = Harmony_aug7; //aug9 } else if( bin == 0x0515 ) { type = Harmony_sus4; //sus9 } else if( bin == 0x04A5 ) { type = Harmony_13b9; } else if( bin == 0x0613 ) { type = Harmony_13b9; //13b9#11 } else if( bin == 0x0611 ) { type = Harmony_13; } else if( bin == 0x0653 ) { type = Harmony_min; //m(natural7) } else if( bin == 0x0889 ) { type = Harmony_min9; //m9(natural7) } else if( bin == 0x088D ) { type = Harmony_min11; } else if( bin == 0x04AD ) { type = Harmony_9s11; } else if( bin == 0x04D5 ) { type = Harmony_7sus4; //sus7 } else if( bin == 0x0421 ) { type = Harmony_min11; } else if( bin == 0x04A9 ) { type = Harmony_min9; } else if( bin == 0x048D ) { type = Harmony_7b5b9; } else if( bin == 0x0453 ) { type = Harmony_maj; //(no5) } else if( bin == 0x0011 ) { type = Harmony_maj7; //(no3) } else if( bin == 0x0081 ) { type = Harmony_7; //7(no3) } else if( bin == 0x0481 ) { type = Harmony_7; //7(no5) } else if( bin == 0x0411 ) { type = Harmony_6; } else if( bin == 0x0291 ) { type = Harmony_sus4; //sus(add9) } else if( bin == 0x00A5 ) { type = Harmony_13s9; //13#9b5 } else if( bin == 0x0659 ) { type = Harmony_sus4; //sus(no5) } else if( bin == 0x0021 ) { type = Harmony_7b5b9; //7b5b9#9 } else if( bin == 0x045B ) { type = Harmony_13b5; //13b5b9#9 } else if( bin == 0x065B ) { type = Harmony_13b9; //13b9#9 } else if( bin == 0x061B ) { type = Harmony_7b9s9; //7b9#9 } else if( bin == 0x04B5 ) { type = Harmony_7; } return type; } bool BarsParse::parseHarmony(MeasureData* measureData, int /*length*/) { Block placeHolder; Harmony* harmony = new Harmony(); measureData->addMusicData(harmony); if( !jump(3) ) { return false; } // common if( !parseCommonBlock(harmony) ) { return false; } // bass on bottom if( !readBuffer(placeHolder, 1) ) { return false; } harmony->setBassOnBottom((getHighNibble(placeHolder.toUnsignedInt())==0x4)); if( !jump(1) ) { return false; } // y offset if( !readBuffer(placeHolder, 2) ) { return false; } harmony->setYOffset(placeHolder.toInt()); // harmony type if( !readBuffer(placeHolder, 2) ) { return false; } harmony->setHarmonyType(binaryToHarmonyType(placeHolder.toUnsignedInt())); // root if( !readBuffer(placeHolder, 1) ) { return false; } harmony->setRoot(placeHolder.toInt()); // bass if( !readBuffer(placeHolder, 1) ) { return false; } harmony->setBass(placeHolder.toInt()); // angle if( !readBuffer(placeHolder, 2) ) { return false; } harmony->setAngle(placeHolder.toInt()); if( ove_->getIsVersion4() ) { // length (tick) if( !readBuffer(placeHolder, 2) ) { return false; } harmony->setLength(placeHolder.toUnsignedInt()); if( !jump(4) ) { return false; } } return true; } bool BarsParse::parseClef(MeasureData* measureData, int /*length*/) { Block placeHolder; Clef* clef = new Clef(); measureData->addMusicData(clef); if( !jump(3) ) { return false; } // common if( !parseCommonBlock(clef) ) { return false; } // clef type if( !readBuffer(placeHolder, 1) ) { return false; } clef->setClefType(placeHolder.toUnsignedInt()); // line if( !readBuffer(placeHolder, 1) ) { return false; } clef->setLine(placeHolder.toInt()); if( !jump(2) ) { return false; } return true; } bool BarsParse::parseLyric(MeasureData* measureData, int length) { Block placeHolder; Lyric* lyric = new Lyric(); measureData->addMusicData(lyric); if( !jump(3) ) { return false; } // common if( !parseCommonBlock(lyric) ) { return false; } if( !jump(2) ) { return false; } // offset if( !parseOffsetElement(lyric) ) { return false; } if( !jump(7) ) { return false; } // verse if( !readBuffer(placeHolder, 1) ) { return false; } lyric->setVerse(placeHolder.toUnsignedInt()); if( ove_->getIsVersion4() ) { if( !jump(6) ) { return false; } // lyric if( length > 29 ) { if( !readBuffer(placeHolder, length-29) ) { return false; } lyric->setLyric(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray())); } } return true; } bool BarsParse::parseSlur(MeasureData* measureData, int /*length*/) { Block placeHolder; Slur* slur = new Slur(); measureData->addCrossMeasureElement(slur, true); if( !jump(2) ) { return false; } // voice if( !readBuffer(placeHolder, 1) ) { return false; } slur->setVoice(getLowNibble(placeHolder.toUnsignedInt())&0x7); // common if( !parseCommonBlock(slur) ) { return false; } // show on top if( !readBuffer(placeHolder, 1) ) { return false; } slur->setShowOnTop(getHighNibble(placeHolder.toUnsignedInt())==0x8); if( !jump(1) ) { return false; } // pair lines if( !parsePairLinesBlock(slur) ) { return false; } // offset common if( !parseOffsetCommonBlock(slur) ) { return false; } // handle 1 if( !parseOffsetElement(slur->getLeftShoulder()) ) { return false; } // handle 4 if( !parseOffsetElement(slur->getRightShoulder()) ) { return false; } // handle 2 if( !parseOffsetElement(slur->getHandle2()) ) { return false; } // handle 3 if( !parseOffsetElement(slur->getHandle3()) ) { return false; } if( ove_->getIsVersion4() ) { if( !jump(3) ) { return false; } // note time percent if( !readBuffer(placeHolder, 1) ) { return false; } slur->setNoteTimePercent(placeHolder.toUnsignedInt()); if( !jump(36) ) { return false; } } return true; } bool BarsParse::parseGlissando(MeasureData* measureData, int /*length*/) { Block placeHolder; Glissando* glissando = new Glissando(); measureData->addCrossMeasureElement(glissando, true); if( !jump(3) ) { return false; } // common if( !parseCommonBlock(glissando) ) { return false; } // straight or wavy if( !readBuffer(placeHolder, 1) ) { return false; } unsigned int thisByte = placeHolder.toUnsignedInt(); glissando->setStraightWavy(getHighNibble(thisByte)==4); if( !jump(1) ) { return false; } // pair lines if( !parsePairLinesBlock(glissando) ) { return false; } // offset common if( !parseOffsetCommonBlock(glissando) ) { return false; } // left shoulder if( !parseOffsetElement(glissando->getLeftShoulder()) ) { return false; } // right shoulder if( !parseOffsetElement(glissando->getRightShoulder()) ) { return false; } if( ove_->getIsVersion4() ) { if( !jump(1) ) { return false; } // line thick if( !readBuffer(placeHolder, 1) ) { return false; } glissando->setLineThick(placeHolder.toUnsignedInt()); if( !jump(12) ) { return false; } // text 32 bytes if( !readBuffer(placeHolder, 32) ) { return false; } glissando->setText(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray())); if( !jump(6) ) { return false; } } return true; } bool getDecoratorType( unsigned int thisByte, bool& measureRepeat, Decorator::DecoratorType& decoratorType, bool& singleRepeat, ArticulationType& artType) { measureRepeat = false; decoratorType = Decorator::Decorator_Articulation; singleRepeat = true; artType = Articulation_None; switch (thisByte) { case 0x00: { decoratorType = Decorator::Decorator_Dotted_Barline; break; } case 0x30: { artType = Articulation_Open_String; break; } case 0x31: { artType = Articulation_Finger_1; break; } case 0x32: { artType = Articulation_Finger_2; break; } case 0x33: { artType = Articulation_Finger_3; break; } case 0x34: { artType = Articulation_Finger_4; break; } case 0x35: { artType = Articulation_Finger_5; break; } case 0x6B: { artType = Articulation_Flat_Accidental_For_Trill; break; } case 0x6C: { artType = Articulation_Sharp_Accidental_For_Trill; break; } case 0x6D: { artType = Articulation_Natural_Accidental_For_Trill; break; } case 0x8d: { measureRepeat = true; singleRepeat = true; break; } case 0x8e: { measureRepeat = true; singleRepeat = false; break; } case 0xA0: { artType = Articulation_Minor_Trill; break; } case 0xA1: { artType = Articulation_Major_Trill; break; } case 0xA2: { artType = Articulation_Trill_Section; break; } case 0xA6: { artType = Articulation_Turn; break; } case 0xA8: { artType = Articulation_Tremolo_Eighth; break; } case 0xA9: { artType = Articulation_Tremolo_Sixteenth; break; } case 0xAA: { artType = Articulation_Tremolo_Thirty_Second; break; } case 0xAB: { artType = Articulation_Tremolo_Sixty_Fourth; break; } case 0xB2: { artType = Articulation_Fermata; break; } case 0xB3: { artType = Articulation_Fermata_Inverted; break; } case 0xB9: { artType = Articulation_Pause; break; } case 0xBA: { artType = Articulation_Grand_Pause; break; } case 0xC0: { artType = Articulation_Marcato; break; } case 0xC1: { artType = Articulation_Marcato_Dot; break; } case 0xC2: { artType = Articulation_SForzando; break; } case 0xC3: { artType = Articulation_SForzando_Dot; break; } case 0xC4: { artType = Articulation_SForzando_Inverted; break; } case 0xC5: { artType = Articulation_SForzando_Dot_Inverted; break; } case 0xC6: { artType = Articulation_Staccatissimo; break; } case 0xC7: { artType = Articulation_Staccato; break; } case 0xC8: { artType = Articulation_Tenuto; break; } case 0xC9: { artType = Articulation_Natural_Harmonic; break; } case 0xCA: { artType = Articulation_Artificial_Harmonic; break; } case 0xCB: { artType = Articulation_Plus_Sign; break; } case 0xCC: { artType = Articulation_Up_Bow; break; } case 0xCD: { artType = Articulation_Down_Bow; break; } case 0xCE: { artType = Articulation_Up_Bow_Inverted; break; } case 0xCF: { artType = Articulation_Down_Bow_Inverted; break; } case 0xD0: { artType = Articulation_Pedal_Down; break; } case 0xD1: { artType = Articulation_Pedal_Up; break; } case 0xD6: { artType = Articulation_Heavy_Attack; break; } case 0xD7: { artType = Articulation_Heavier_Attack; break; } default: return false; break; } return true; } bool BarsParse::parseDecorators(MeasureData* measureData, int length) { Block placeHolder; MusicData* musicData = new MusicData(); if( !jump(3) ) { return false; } // common if( !parseCommonBlock(musicData) ) { return false; } if( !jump(2) ) { return false; } // y offset if( !readBuffer(placeHolder, 2) ) { return false; } musicData->setYOffset(placeHolder.toInt()); if( !jump(2) ) { return false; } // measure repeat | piano pedal | dotted barline | articulation if( !readBuffer(placeHolder, 1) ) { return false; } unsigned int thisByte = placeHolder.toUnsignedInt(); Decorator::DecoratorType decoratorType; bool isMeasureRepeat; bool isSingleRepeat = true; ArticulationType artType = Articulation_None; getDecoratorType(thisByte, isMeasureRepeat, decoratorType, isSingleRepeat, artType); if( isMeasureRepeat ) { MeasureRepeat* measureRepeat = new MeasureRepeat(); measureData->addCrossMeasureElement(measureRepeat, true); measureRepeat->copyCommonBlock(*musicData); measureRepeat->setYOffset(musicData->getYOffset()); measureRepeat->setSingleRepeat(isSingleRepeat); } else { Decorator* decorator = new Decorator(); measureData->addMusicData(decorator); decorator->copyCommonBlock(*musicData); decorator->setYOffset(musicData->getYOffset()); decorator->setDecoratorType(decoratorType); decorator->setArticulationType(artType); } int cursor = ove_->getIsVersion4() ? 16 : 14; if( !jump(length-cursor) ) { return false; } return true; } bool BarsParse::parseWedge(MeasureData* measureData, int length) { Block placeHolder; Wedge* wedge = new Wedge(); if( !jump(3) ) { return false; } // common if( !parseCommonBlock(wedge) ) { return false; } // wedge type if( !readBuffer(placeHolder, 1) ) { return false; } WedgeType wedgeType = Wedge_Cres_Line; bool wedgeOrExpression = true; unsigned int highHalfByte = getHighNibble(placeHolder.toUnsignedInt()); unsigned int lowHalfByte = getLowNibble(placeHolder.toUnsignedInt()); switch (highHalfByte) { case 0x0: { wedgeType = Wedge_Cres_Line; wedgeOrExpression = true; break; } case 0x4: { wedgeType = Wedge_Decresc_Line; wedgeOrExpression = true; break; } case 0x6: { wedgeType = Wedge_Decresc; wedgeOrExpression = false; break; } case 0x2: { wedgeType = Wedge_Cres; wedgeOrExpression = false; break; } default: break; } // 0xb | 0x8(ove3) , else 3, 0(ove3) if( (lowHalfByte & 0x8) == 0x8 ) { wedgeType = Wedge_Double_Line; wedgeOrExpression = true; } if( !jump(1) ) { return false; } // y offset if( !readBuffer(placeHolder, 2) ) { return false; } wedge->setYOffset(placeHolder.toInt()); // wedge if( wedgeOrExpression ) { measureData->addCrossMeasureElement(wedge, true); wedge->setWedgeType(wedgeType); if( !jump(2) ) { return false; } // height if( !readBuffer(placeHolder, 2) ) { return false; } wedge->setHeight(placeHolder.toUnsignedInt()); // offset common if( !parseOffsetCommonBlock(wedge) ) { return false; } int cursor = ove_->getIsVersion4() ? 21 : 19; if( !jump(length-cursor) ) { return false; } } // expression : cresc, decresc else { Expressions* express = new Expressions(); measureData->addMusicData(express); express->copyCommonBlock(*wedge); express->setYOffset(wedge->getYOffset()); if( !jump(4) ) { return false; } // offset common if( !parseOffsetCommonBlock(express) ) { return false; } if( ove_->getIsVersion4() ) { if( !jump(18) ) { return false; } // words if( length > 39 ) { if( !readBuffer(placeHolder, length-39) ) { return false; } express->setText(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray())); } } else { QString str = wedgeType==Wedge_Cres ? "cresc" : "decresc"; express->setText(str); if( !jump(8) ) { return false; } } } return true; } bool BarsParse::parseDynamics(MeasureData* measureData, int /*length*/) { Block placeHolder; Dynamics* dynamics = new Dynamics(); measureData->addMusicData(dynamics); if( !jump(1) ) { return false; } // is playback if( !readBuffer(placeHolder, 1) ) { return false; } dynamics->setIsPlayback(getHighNibble(placeHolder.toUnsignedInt())!=0x4); if( !jump(1) ) { return false; } // common if( !parseCommonBlock(dynamics) ) { return false; } // y offset if( !readBuffer(placeHolder, 2) ) { return false; } dynamics->setYOffset(placeHolder.toInt()); // dynamics type if( !readBuffer(placeHolder, 1) ) { return false; } dynamics->setDynamicsType(getLowNibble(placeHolder.toUnsignedInt())); // velocity if( !readBuffer(placeHolder, 1) ) { return false; } dynamics->setVelocity(placeHolder.toUnsignedInt()); int cursor = ove_->getIsVersion4() ? 4 : 2; if( !jump(cursor) ) { return false; } return true; } bool BarsParse::parseKey(MeasureData* measureData, int /*length*/) { Block placeHolder; Key* key = measureData->getKey(); int cursor = ove_->getIsVersion4() ? 9 : 7; if( !jump(cursor) ) { return false; } // key if( !readBuffer(placeHolder, 1) ) { return false; } key->setKey(oveKeyToKey(placeHolder.toUnsignedInt())); // previous key if( !readBuffer(placeHolder, 1) ) { return false; } key->setPreviousKey(oveKeyToKey(placeHolder.toUnsignedInt())); if( !jump(3) ) { return false; } // symbol count if( !readBuffer(placeHolder, 1) ) { return false; } key->setSymbolCount(placeHolder.toUnsignedInt()); if( !jump(4) ) { return false; } return true; } bool BarsParse::parsePedal(MeasureData* measureData, int length) { Block placeHolder; Pedal* pedal = new Pedal(); //measureData->addMusicData(pedal); //can't remember why measureData->addCrossMeasureElement(pedal, true); if( !jump(1) ) { return false; } // is playback if( !readBuffer(placeHolder, 1) ) { return false; } pedal->setIsPlayback(getHighNibble(placeHolder.toUnsignedInt())!=4); if( !jump(1) ) { return false; } // common if( !parseCommonBlock(pedal) ) { return false; } if( !jump(2) ) { return false; } // pair lines if( !parsePairLinesBlock(pedal) ) { return false; } // offset common if( !parseOffsetCommonBlock(pedal) ) { return false; } // left shoulder if( !parseOffsetElement(pedal->getLeftShoulder()) ) { return false; } // right shoulder if( !parseOffsetElement(pedal->getRightShoulder()) ) { return false; } int cursor = ove_->getIsVersion4() ? 0x45 : 0x23; int blankCount = ove_->getIsVersion4() ? 42 : 10; pedal->setHalf( length > cursor ); if( !jump(blankCount) ) { return false; } if( length > cursor ) { if( !jump(2) ) { return false; } // handle x offset if( !readBuffer(placeHolder, 2) ) { return false; } pedal->getPedalHandle()->setXOffset(placeHolder.toInt()); if( !jump(6) ) { return false; } } return true; } bool BarsParse::parseKuohao(MeasureData* measureData, int /*length*/) { Block placeHolder; KuoHao* kuoHao = new KuoHao(); measureData->addMusicData(kuoHao); if( !jump(3) ) { return false; } // common if( !parseCommonBlock(kuoHao) ) { return false; } if( !jump(2) ) { return false; } // pair lines if( !parsePairLinesBlock(kuoHao) ) { return false; } if( !jump(4) ) { return false; } // left shoulder if( !parseOffsetElement(kuoHao->getLeftShoulder()) ) { return false; } // right shoulder if( !parseOffsetElement(kuoHao->getRightShoulder()) ) { return false; } // kuohao type if( !readBuffer(placeHolder, 1) ) { return false; } kuoHao->setKuohaoType(placeHolder.toUnsignedInt()); // height if( !readBuffer(placeHolder, 1) ) { return false; } kuoHao->setHeight(placeHolder.toUnsignedInt()); int jumpAmount = ove_->getIsVersion4() ? 40 : 8; if( !jump(jumpAmount) ) { return false; } return true; } bool BarsParse::parseExpressions(MeasureData* measureData, int length) { Block placeHolder; Expressions* expressions = new Expressions(); measureData->addMusicData(expressions); if( !jump(3) ) { return false; } // common00 if( !parseCommonBlock(expressions) ) { return false; } if( !jump(2) ) { return false; } // y offset if( !readBuffer(placeHolder, 2) ) { return false; } expressions->setYOffset(placeHolder.toInt()); // range bar offset if( !readBuffer(placeHolder, 2) ) { return false; } //int barOffset = placeHolder.toUnsignedInt(); if( !jump(10) ) { return false; } // tempo 1 if( !readBuffer(placeHolder, 2) ) { return false; } //double tempo1 = ((double)placeHolder.toUnsignedInt()) / 100.0; // tempo 2 if( !readBuffer(placeHolder, 2) ) { return false; } //double tempo2 = ((double)placeHolder.toUnsignedInt()) / 100.0; if( !jump(6) ) { return false; } // text int cursor = ove_->getIsVersion4() ? 35 : 33; if( length > cursor ) { if( !readBuffer(placeHolder, length-cursor) ) { return false; } expressions->setText(ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray())); } return true; } bool BarsParse::parseHarpPedal(MeasureData* measureData, int /*length*/) { Block placeHolder; HarpPedal* harpPedal = new HarpPedal(); measureData->addMusicData(harpPedal); if( !jump(3) ) { return false; } // common if( !parseCommonBlock(harpPedal) ) { return false; } if( !jump(2) ) { return false; } // y offset if( !readBuffer(placeHolder, 2) ) { return false; } harpPedal->setYOffset(placeHolder.toInt()); // show type if( !readBuffer(placeHolder, 1) ) { return false; } harpPedal->setShowType(placeHolder.toUnsignedInt()); // show char flag if( !readBuffer(placeHolder, 1) ) { return false; } harpPedal->setShowCharFlag(placeHolder.toUnsignedInt()); if( !jump(8) ) { return false; } return true; } bool BarsParse::parseMultiMeasureRest(MeasureData* measureData, int /*length*/) { Block placeHolder(2); MultiMeasureRest* measureRest = new MultiMeasureRest(); measureData->addMusicData(measureRest); if( !jump(3) ) { return false; } // common if( !parseCommonBlock(measureRest) ) { return false; } if( !jump(6) ) { return false; } return true; } bool BarsParse::parseHarmonyGuitarFrame(MeasureData* measureData, int length) { Block placeHolder; Harmony* harmony = new Harmony(); measureData->addMusicData(harmony); if( !jump(3) ) { return false; } // common if( !parseCommonBlock(harmony) ) { return false; } // root if( !readBuffer(placeHolder, 1) ) { return false; } harmony->setRoot(placeHolder.toUnsignedInt()); // type if( !readBuffer(placeHolder, 1) ) { return false; } harmony->setHarmonyType((HarmonyType)placeHolder.toUnsignedInt()); // bass if( !readBuffer(placeHolder, 1) ) { return false; } harmony->setBass(placeHolder.toUnsignedInt()); int jumpAmount = ove_->getIsVersion4() ? length - 12 : length - 10; if( !jump(jumpAmount) ) { return false; } return true; } void extractOctave(unsigned int Bits, OctaveShiftType& octaveShiftType, QList& positions) { octaveShiftType = OctaveShift_8; positions.clear(); switch (Bits) { case 0x0: { octaveShiftType = OctaveShift_8; positions.push_back(OctavePosition_Continue); break; } case 0x1: { octaveShiftType = OctaveShift_Minus_8; positions.push_back(OctavePosition_Continue); break; } case 0x2: { octaveShiftType = OctaveShift_15; positions.push_back(OctavePosition_Continue); break; } case 0x3: { octaveShiftType = OctaveShift_Minus_15; positions.push_back(OctavePosition_Continue); break; } case 0x4: { octaveShiftType = OctaveShift_8; positions.push_back(OctavePosition_Stop); break; } case 0x5: { octaveShiftType = OctaveShift_Minus_8; positions.push_back(OctavePosition_Stop); break; } case 0x6: { octaveShiftType = OctaveShift_15; positions.push_back(OctavePosition_Stop); break; } case 0x7: { octaveShiftType = OctaveShift_Minus_15; positions.push_back(OctavePosition_Stop); break; } case 0x8: { octaveShiftType = OctaveShift_8; positions.push_back(OctavePosition_Start); break; } case 0x9: { octaveShiftType = OctaveShift_Minus_8; positions.push_back(OctavePosition_Start); break; } case 0xA: { octaveShiftType = OctaveShift_15; positions.push_back(OctavePosition_Start); break; } case 0xB: { octaveShiftType = OctaveShift_Minus_15; positions.push_back(OctavePosition_Start); ; break; } case 0xC: { octaveShiftType = OctaveShift_8; positions.push_back(OctavePosition_Start); positions.push_back(OctavePosition_Stop); break; } case 0xD: { octaveShiftType = OctaveShift_Minus_8; positions.push_back(OctavePosition_Start); positions.push_back(OctavePosition_Stop); break; } case 0xE: { octaveShiftType = OctaveShift_15; positions.push_back(OctavePosition_Start); positions.push_back(OctavePosition_Stop); break; } case 0xF: { octaveShiftType = OctaveShift_Minus_15; positions.push_back(OctavePosition_Start); positions.push_back(OctavePosition_Stop); break; } default: break; } } bool BarsParse::parseOctaveShift(MeasureData* measureData, int /*length*/) { Block placeHolder; OctaveShift* octave = new OctaveShift(); measureData->addCrossMeasureElement(octave, true); if( !jump(3) ) { return false; } // common if( !parseCommonBlock(octave) ) { return false; } // octave if( !readBuffer(placeHolder, 1) ) { return false; } unsigned int type = getLowNibble(placeHolder.toUnsignedInt()); OctaveShiftType octaveShiftType = OctaveShift_8; QList positions; extractOctave(type, octaveShiftType, positions); octave->setOctaveShiftType(octaveShiftType); if( !jump(1) ) { return false; } // y offset if( !readBuffer(placeHolder, 2) ) { return false; } octave->setYOffset(placeHolder.toInt()); if( !jump(4) ) { return false; } // length if( !readBuffer(placeHolder, 2) ) { return false; } octave->setLength(placeHolder.toUnsignedInt()); // end tick if( !readBuffer(placeHolder, 2) ) { return false; } octave->setEndTick(placeHolder.toUnsignedInt()); // start & stop maybe appear in same measure for (int i=0; iaddMusicData(octavePoint); octavePoint->copyCommonBlock(*octave); octavePoint->setOctaveShiftType(octaveShiftType); octavePoint->setOctaveShiftPosition(position); octavePoint->setEndTick(octave->getEndTick()); // stop if( i==0 && position == OctavePosition_Stop ) { octavePoint->start()->setOffset(octave->start()->getOffset()+octave->getLength()); } // end point if( i>0 ) { octavePoint->start()->setOffset(octave->start()->getOffset()+octave->getLength()); octavePoint->setTick(octave->getEndTick()); } } return true; } bool BarsParse::parseMidiController(MeasureData* measureData, int /*length*/) { Block placeHolder; MidiController* controller = new MidiController(); measureData->addMidiData(controller); parseMidiCommon(controller); // value [0, 128) if( !readBuffer(placeHolder, 1) ) { return false; } controller->setValue(placeHolder.toUnsignedInt()); // controller number if( !readBuffer(placeHolder, 1) ) { return false; } controller->setController(placeHolder.toUnsignedInt()); if( ove_->getIsVersion4() ) { if( !jump(2) ) { return false; } } return true; } bool BarsParse::parseMidiProgramChange(MeasureData* measureData, int /*length*/) { Block placeHolder; MidiProgramChange* program = new MidiProgramChange(); measureData->addMidiData(program); parseMidiCommon(program); if( !jump(1) ) { return false; } // patch if( !readBuffer(placeHolder, 1) ) { return false; } program->setPatch(placeHolder.toUnsignedInt()); if( ove_->getIsVersion4() ) { if( !jump(2) ) { return false; } } return true; } bool BarsParse::parseMidiChannelPressure(MeasureData* measureData, int /*length*/) { Block placeHolder; MidiChannelPressure* pressure = new MidiChannelPressure(); measureData->addMidiData(pressure); parseMidiCommon(pressure); if( !jump(1) ) { return false; } // pressure if( !readBuffer(placeHolder, 1) ) { return false; } pressure->setPressure(placeHolder.toUnsignedInt()); if( ove_->getIsVersion4() ) { if( !jump(2) ) { return false; } } return true; } bool BarsParse::parseMidiPitchWheel(MeasureData* measureData, int /*length*/) { Block placeHolder; MidiPitchWheel* wheel = new MidiPitchWheel(); measureData->addMidiData(wheel); parseMidiCommon(wheel); // pitch wheel if( !readBuffer(placeHolder, 2) ) { return false; } int value = placeHolder.toUnsignedInt(); wheel->setValue(value); if( ove_->getIsVersion4() ) { if( !jump(2) ) { return false; } } return true; } bool BarsParse::parseSizeBlock(int length) { if( !jump(length) ) { return false; } return true; } bool BarsParse::parseMidiCommon(MidiData* ptr) { Block placeHolder; if( !jump(3) ) { return false; } // start position if( !readBuffer(placeHolder, 2) ) { return false; } ptr->setTick(placeHolder.toUnsignedInt()); return true; } bool BarsParse::parseCommonBlock(MusicData* ptr) { Block placeHolder; // start tick if( !readBuffer(placeHolder, 2) ) { return false; } ptr->setTick(placeHolder.toInt()); // start unit if( !readBuffer(placeHolder, 2) ) { return false; } ptr->start()->setOffset(placeHolder.toInt()); if( ove_->getIsVersion4() ) { // color if( !readBuffer(placeHolder, 1) ) { return false; } ptr->setColor(placeHolder.toUnsignedInt()); if( !jump(1) ) { return false; } } return true; } bool BarsParse::parseOffsetCommonBlock(MusicData* ptr) { Block placeHolder; // offset measure if( !readBuffer(placeHolder, 2) ) { return false; } ptr->stop()->setMeasure(placeHolder.toUnsignedInt()); // end unit if( !readBuffer(placeHolder, 2) ) { return false; } ptr->stop()->setOffset(placeHolder.toInt()); return true; } bool BarsParse::parsePairLinesBlock(PairEnds* ptr) { Block placeHolder; // left line if( !readBuffer(placeHolder, 2) ) { return false; } ptr->getLeftLine()->setLine(placeHolder.toInt()); // right line if( !readBuffer(placeHolder, 2) ) { return false; } ptr->getRightLine()->setLine(placeHolder.toInt()); return true; } bool BarsParse::parseOffsetElement(OffsetElement* ptr) { Block placeHolder; // x offset if( !readBuffer(placeHolder, 2) ) { return false; } ptr->setXOffset(placeHolder.toInt()); // y offset if( !readBuffer(placeHolder, 2) ) { return false; } ptr->setYOffset(placeHolder.toInt()); return true; } bool BarsParse::getCondElementType(unsigned int byteData, CondType& type) { if( byteData == 0x09 ) { type = Cond_Time_Parameters; } else if (byteData == 0x0A) { type = Cond_Bar_Number; } else if (byteData == 0x16) { type = Cond_Decorator; } else if (byteData == 0x1C) { type = Cond_Tempo; } else if (byteData == 0x1D) { type = Cond_Text; } else if (byteData == 0x25) { type = Cond_Expression; } else if (byteData == 0x30) { type = Cond_Barline_Parameters; } else if (byteData == 0x31) { type = Cond_Repeat; } else if (byteData == 0x32) { type = Cond_Numeric_Ending; } else { return false; } return true; } bool BarsParse::getBdatElementType(unsigned int byteData, BdatType& type) { if (byteData == 0x70) { type = Bdat_Raw_Note; } else if (byteData == 0x80) { type = Bdat_Rest; } else if (byteData == 0x90) { type = Bdat_Note; } else if (byteData == 0x10) { type = Bdat_Beam; } else if (byteData == 0x11) { type = Bdat_Harmony; } else if (byteData == 0x12) { type = Bdat_Clef; } else if (byteData == 0x13) { type = Bdat_Wedge; } else if (byteData == 0x14) { type = Bdat_Dynamics; } else if (byteData == 0x15) { type = Bdat_Glissando; } else if (byteData == 0x16) { type = Bdat_Decorator; } else if (byteData == 0x17) { type = Bdat_Key; } else if (byteData == 0x18) { type = Bdat_Lyric; } else if (byteData == 0x19) { type = Bdat_Octave_Shift; } else if (byteData == 0x1B) { type = Bdat_Slur; } else if (byteData == 0x1D) { type = Bdat_Text; } else if (byteData == 0x1E) { type = Bdat_Tie; } else if (byteData == 0x1F) { type = Bdat_Tuplet; } else if (byteData == 0x21) { type = Bdat_Guitar_Bend; } else if (byteData == 0x22) { type = Bdat_Guitar_Barre; } else if (byteData == 0x23) { type = Bdat_Pedal; } else if (byteData == 0x24) { type = Bdat_KuoHao; } else if (byteData == 0x25) { type = Bdat_Expressions; } else if (byteData == 0x26) { type = Bdat_Harp_Pedal; } else if (byteData == 0x27) { type = Bdat_Multi_Measure_Rest; } else if (byteData == 0x28) { type = Bdat_Harmony_GuitarFrame; } else if (byteData == 0x40) { type = Bdat_Graphics_40; } else if (byteData == 0x41) { type = Bdat_Graphics_RoundRect; } else if (byteData == 0x42) { type = Bdat_Graphics_Rect; } else if (byteData == 0x43) { type = Bdat_Graphics_Round; } else if (byteData == 0x44) { type = Bdat_Graphics_Line; } else if (byteData == 0x45) { type = Bdat_Graphics_Curve; } else if (byteData == 0x46) { type = Bdat_Graphics_WedgeSymbol; } else if (byteData == 0xAB) { type = Bdat_Midi_Controller; } else if (byteData == 0xAC) { type = Bdat_Midi_Program_Change; } else if (byteData == 0xAD) { type = Bdat_Midi_Channel_Pressure; } else if (byteData == 0xAE) { type = Bdat_Midi_Pitch_Wheel; } else if (byteData == 0xFF) { type = Bdat_Bar_End; } else { return false; } return true; } /////////////////////////////////////////////////////////////////////////////// LyricChunkParse::LyricChunkParse(OveSong* ove) : BasicParse(ove) { } void LyricChunkParse::setLyricChunk(SizeChunk* chunk) { chunk_ = chunk; } // only ove3 has this chunk bool LyricChunkParse::parse() { unsigned int i; Block* dataBlock = chunk_->getDataBlock(); unsigned int blockSize = chunk_->getSizeBlock()->toSize(); StreamHandle handle(dataBlock->data(), blockSize); Block placeHolder; handle_ = &handle; if( !jump(4) ) { return false; } // Lyric count if( !readBuffer(placeHolder, 2) ) { return false; } unsigned int count = placeHolder.toUnsignedInt(); for( i=0; igetCodecString(placeHolder.fixedSizeBufferToStrByteArray()); if( info.lyricSize_ > 0 ) { // lyric if( info.lyricSize_ > 0 ) { if( !readBuffer(placeHolder, info.lyricSize_) ) { return false; } info.lyric_ = ove_->getCodecString(placeHolder.fixedSizeBufferToStrByteArray()); } if( !jump(4) ) { return false; } // font if( !readBuffer(placeHolder, 2) ) { return false; } info.font_ = placeHolder.toUnsignedInt(); if( !jump(1) ) { return false; } // font size if( !readBuffer(placeHolder, 1) ) { return false; } info.fontSize_ = placeHolder.toUnsignedInt(); // font style if( !readBuffer(placeHolder, 1) ) { return false; } info.fontStyle_ = placeHolder.toUnsignedInt(); if( !jump(1) ) { return false; } for( int j=0; jgetTrackBarCount(); QStringList words = info.lyric_.split(" ", QString::SkipEmptyParts); while ( index < words.size() && measureId+1 < trackMeasureCount ) { if( changeMeasure ) { ++measureId; measureData = ove_->getMeasureData(info.track_, measureId); changeMeasure = false; } if( measureData == 0 ) { return; } QList containers = measureData->getNoteContainers(); QList lyrics = measureData->getMusicDatas(MusicData_Lyric); for( i=0; igetIsRest() ) { continue; } for( j=0; j(lyrics[j]); if( containers[i]->start()->getOffset() == lyric->start()->getOffset() && (int)containers[i]->getVoice() == info.voice_ && lyric->getVerse() == info.verse_ ) { if(indexsetLyric(l); lyric->setVoice(info.voice_); } } ++index; } } } changeMeasure = true; } } /////////////////////////////////////////////////////////////////////////////// TitleChunkParse::TitleChunkParse(OveSong* ove) : BasicParse(ove) { titleType_ = 0x00000001; annotateType_ = 0x00010000; writerType_ = 0x00020002; copyrightType_ = 0x00030001; headerType_ = 0x00040000; footerType_ = 0x00050002; } void TitleChunkParse::setTitleChunk(SizeChunk* chunk) { chunk_ = chunk; } bool TitleChunkParse::parse() { Block* dataBlock = chunk_->getDataBlock(); unsigned int blockSize = chunk_->getSizeBlock()->toSize(); StreamHandle handle(dataBlock->data(), blockSize); Block typeBlock; unsigned int titleType; handle_ = &handle; if( !readBuffer(typeBlock, 4) ) { return false; } titleType = typeBlock.toUnsignedInt(); if( titleType == titleType_ || titleType == annotateType_ || titleType == writerType_ || titleType == copyrightType_ ) { Block offsetBlock; if( !readBuffer(offsetBlock, 4) ) { return false; } const unsigned int itemCount = 4; unsigned int i; for( i=0; i0 ) { //0x 00 AB 00 0C 00 00 if( !jump(6) ) { return false; } } Block countBlock; if( !readBuffer(countBlock, 2) ) { return false; } unsigned int titleSize = countBlock.toUnsignedInt(); Block dataBlock; if( !readBuffer(dataBlock, titleSize) ) { return false; } QByteArray array((char*)dataBlock.data(), dataBlock.size()); addToOve(ove_->getCodecString(array), titleType); } return true; } if( titleType == headerType_ || titleType == footerType_ ) { if( !jump(10) ) { return false; } Block countBlock; if( !readBuffer(countBlock, 2) ) { return false; } unsigned int titleSize = countBlock.toUnsignedInt(); Block dataBlock; if( !readBuffer(dataBlock, titleSize) ) { return false; } QByteArray array((char*)dataBlock.data(), dataBlock.size()); addToOve(ove_->getCodecString(array), titleType); //0x 00 AB 00 0C 00 00 if( !jump(6) ) { return false; } return true; } return false; } void TitleChunkParse::addToOve(const QString& str, unsigned int titleType) { if( str.isEmpty() ) { return; } if (titleType == titleType_) { ove_->addTitle(str); } if (titleType == annotateType_) { ove_->addAnnotate(str); } if (titleType == writerType_) { ove_->addWriter(str); } if (titleType == copyrightType_) { ove_->addCopyright(str); } if (titleType == headerType_) { ove_->addHeader(str); } if (titleType == footerType_) { ove_->addFooter(str); } } // OveOrganize.cpp OveOrganizer::OveOrganizer(OveSong* ove) { ove_ = ove; } void OveOrganizer::organize() { if(ove_ == NULL) { return; } organizeTracks(); organizeAttributes(); organizeMeasures(); } void OveOrganizer::organizeAttributes() { int i; int j; int k; // key if(ove_->getLineCount() > 0) { Line* line = ove_->getLine(0); int partBarCount = ove_->getPartBarCount(); int lastKey = 0; if(line != 0){ for(i=0; igetStaffCount(); ++i) { QPair partStaff = ove_->trackToPartStaff(i); Staff* staff = line->getStaff(i); lastKey = staff->getKeyType(); for(j=0; jgetMeasureData(partStaff.first, partStaff.second, j); if(measureData != 0) { Key* key = measureData->getKey(); if( j==0 ) { key->setKey(lastKey); key->setPreviousKey(lastKey); } if( !key->getSetKey() ) { key->setKey(lastKey); key->setPreviousKey(lastKey); } else { if( key->getKey() != lastKey ) { lastKey = key->getKey(); } } } } } } } // clef if( ove_->getLineCount() > 0 ) { Line* line = ove_->getLine(0); int partBarCount = ove_->getPartBarCount(); ClefType lastClefType = Clef_Treble; if(line != 0){ for( i=0; igetStaffCount(); ++i ) { QPair partStaff = ove_->trackToPartStaff(i); Staff* staff = line->getStaff(i); lastClefType = staff->getClefType(); for( j=0; jgetMeasureData(partStaff.first, partStaff.second, j); if(measureData != 0) { Clef* clefPtr = measureData->getClef(); clefPtr->setClefType((int)lastClefType); const QList& clefs = measureData->getMusicDatas(MusicData_Clef); for( k=0; k(clefs[k]); lastClefType = clef->getClefType(); } } } } } } } Staff* getStaff(OveSong* ove, int track) { if (ove->getLineCount() > 0) { Line* line = ove->getLine(0); if(line != 0 && line->getStaffCount() > 0) { Staff* staff = line->getStaff(track); return staff; } } return 0; } void OveOrganizer::organizeTracks() { int i; //QList > trackChannels; QList tracks = ove_->getTracks(); QList comboStaveStarts; for( i=0; igetGroupType() == Group_Brace && staff->getGroupStaffCount() == 1 ) { comboStaveStarts[i] = true; } } /*if( i < tracks.size() - 1 ) { if( tracks[i]->getStartClef() == Clef_Treble && tracks[i+1]->getStartClef() == Clef_Bass && tracks[i]->getChannel() == tracks[i+1]->get_channel() ) { } }*/ } int trackId = 0; QList partStaffCounts; while( trackId < (int)tracks.size() ) { int partTrackCount = 1; if( comboStaveStarts[trackId] ) { partTrackCount = 2; } partStaffCounts.push_back(partTrackCount); trackId += partTrackCount; } ove_->setPartStaffCounts(partStaffCounts); } void OveOrganizer::organizeMeasures() { int trackBarCount = ove_->getTrackBarCount(); for( int i=0; igetPartCount(); ++i ) { int partStaffCount = ove_->getStaffCount(i); for( int j=0; jgetMeasure(k); MeasureData* measureData = ove_->getMeasureData(i, j, k); organizeMeasure(i, j, measure, measureData); } } } } void OveOrganizer::organizeMeasure(int part, int track, Measure* measure, MeasureData* measureData) { // note containers organizeContainers(part, track, measure, measureData); // single end data organizeMusicDatas(part, track, measure, measureData); // cross measure elements organizeCrossMeasureElements(part, track, measure, measureData); } void addToList(QList& list, int number) { for(int i=0; i containers = measureData->getNoteContainers(); int barUnits = measure->getTime()->getUnits(); QList voices; for(i=0; istart()->getOffset(); } containers[i]->stop()->setOffset(endUnit); addToList(voices, containers[i]->getVoice()); } // shift voices qSort(voices.begin(), voices.end()); for (i = 0; i < voices.size(); ++i) { int voice = voices[i]; // voice -> i for(int j=0; j<(int)containers.size(); ++j) { int avoice = containers[j]->getVoice(); if ( avoice == voice && avoice != i ) { containers[j]->setVoice(i); } } } } void OveOrganizer::organizeMusicDatas(int /*part*/, int /*track*/, Measure* measure, MeasureData* measureData) { int i; int barIndex = measure->getBarNumber()->getIndex(); QList datas = measureData->getMusicDatas(MusicData_None); for(i=0; istart()->setMeasure(barIndex); } } void OveOrganizer::organizeCrossMeasureElements(int part, int track, Measure* measure, MeasureData* measureData) { int i; QList pairs = measureData->getCrossMeasureElements(MusicData_None, MeasureData::PairType_Start); for(i=0; igetMusicDataType() ) { case MusicData_Beam : case MusicData_Glissando : case MusicData_Slur : case MusicData_Tie : case MusicData_Tuplet : case MusicData_Pedal : case MusicData_Numeric_Ending : //case MusicData_OctaveShift_EndPoint : case MusicData_Measure_Repeat : { organizePairElement(pair, part, track, measure, measureData); break; } case MusicData_OctaveShift : { OctaveShift* octave = static_cast(pair); organizeOctaveShift(octave, measure, measureData); break; } case MusicData_Wedge : { Wedge* wedge = static_cast(pair); organizeWedge(wedge, part, track, measure, measureData); break; } default: break; } } } void OveOrganizer::organizePairElement( MusicData* data, int part, int track, Measure* measure, MeasureData* measureData) { int bar1Index = measure->getBarNumber()->getIndex(); int bar2Index = bar1Index + data->stop()->getMeasure(); MeasureData* measureData2 = ove_->getMeasureData(part, track, bar2Index); data->start()->setMeasure(bar1Index); if(measureData2 != 0 && measureData != measureData2) { measureData2->addCrossMeasureElement(data, false); } if( data->getMusicDataType() == MusicData_Tuplet ){ Tuplet* tuplet = static_cast(data); const QList containers = measureData->getNoteContainers(); for(int i=0; igetTick() > tuplet->getTick()){ break; } if(containers[i]->getTick() == tuplet->getTick()){ tuplet->setNoteType(containers[i]->getNoteType()); } } int tupletTick = NoteTypeToTick(tuplet->getNoteType(), ove_->getQuarter())*tuplet->getSpace(); if( tuplet->getTick() % tupletTick != 0 ) { int newStartTick = (tuplet->getTick() / tupletTick) * tupletTick; for(int i=0; igetTick() == newStartTick && containers[i]->getTuplet() == tuplet->getTuplet()) { tuplet->setTick(containers[i]->getTick()); tuplet->start()->setOffset(containers[i]->start()->getOffset()); } } } } } void OveOrganizer::organizeOctaveShift( OctaveShift* octave, Measure* measure, MeasureData* measureData) { // octave shift int i; const QList containers = measureData->getNoteContainers(); int barIndex = measure->getBarNumber()->getIndex(); octave->start()->setMeasure(barIndex); for(i=0; igetNoteShift(); int containerTick = containers[i]->getTick(); if( octave->getTick() <= containerTick && octave->getEndTick() > containerTick ) { containers[i]->setNoteShift(noteShift); } } } bool getMiddleUnit( OveSong* ove, int /*part*/, int /*track*/, Measure* measure1, Measure* measure2, int unit1, int /*unit2*/, Measure* middleMeasure, int& middleUnit) { QList barUnits; int i; int bar1Index = measure1->getBarNumber()->getIndex(); int bar2Index = measure2->getBarNumber()->getIndex(); int sumUnit = 0; for( int j=bar1Index; j<=bar2Index; ++j ) { Measure* measure = ove->getMeasure(j); barUnits.push_back(measure->getTime()->getUnits()); sumUnit += measure->getTime()->getUnits(); } int currentSumUnit = 0; for( i=0; igetMeasure(barMiddleIndex); middleUnit = sumUnit/2 - currentSumUnit; return true; } return false; } void OveOrganizer::organizeWedge(Wedge* wedge, int part, int track, Measure* measure, MeasureData* measureData) { int bar1Index = measure->getBarNumber()->getIndex(); int bar2Index = bar1Index + wedge->stop()->getMeasure(); MeasureData* measureData2 = ove_->getMeasureData(part, track, bar2Index); WedgeType wedgeType = wedge->getWedgeType(); if( wedge->getWedgeType() == Wedge_Double_Line ) { wedgeType = Wedge_Cres_Line; } wedge->start()->setMeasure(bar1Index); WedgeEndPoint* startPoint = new WedgeEndPoint(); measureData->addMusicData(startPoint); startPoint->setTick(wedge->getTick()); startPoint->start()->setOffset(wedge->start()->getOffset()); startPoint->setWedgeStart(true); startPoint->setWedgeType(wedgeType); startPoint->setHeight(wedge->getHeight()); WedgeEndPoint* stopPoint = new WedgeEndPoint(); stopPoint->setTick(wedge->getTick()); stopPoint->start()->setOffset(wedge->stop()->getOffset()); stopPoint->setWedgeStart(false); stopPoint->setWedgeType(wedgeType); stopPoint->setHeight(wedge->getHeight()); if(measureData2 != 0) { measureData2->addMusicData(stopPoint); } if( wedge->getWedgeType() == Wedge_Double_Line ) { Measure* middleMeasure = NULL; int middleUnit = 0; getMiddleUnit( ove_, part, track, measure, ove_->getMeasure(bar2Index), wedge->start()->getOffset(), wedge->stop()->getOffset(), middleMeasure, middleUnit); if( middleMeasure != 0 ) { WedgeEndPoint* midStopPoint = new WedgeEndPoint(); measureData->addMusicData(midStopPoint); midStopPoint->setTick(wedge->getTick()); midStopPoint->start()->setOffset(middleUnit); midStopPoint->setWedgeStart(false); midStopPoint->setWedgeType(Wedge_Cres_Line); midStopPoint->setHeight(wedge->getHeight()); WedgeEndPoint* midStartPoint = new WedgeEndPoint(); measureData->addMusicData(midStartPoint); midStartPoint->setTick(wedge->getTick()); midStartPoint->start()->setOffset(middleUnit); midStartPoint->setWedgeStart(true); midStartPoint->setWedgeType(Wedge_Decresc_Line); midStartPoint->setHeight(wedge->getHeight()); } } } // OveSerialize.cpp enum ChunkType { Chunk_OVSC = 00 , Chunk_TRKL, Chunk_TRAK, Chunk_PAGL, Chunk_PAGE, Chunk_LINL, Chunk_LINE, Chunk_STAF, Chunk_BARL, Chunk_MEAS, Chunk_COND, Chunk_BDAT, Chunk_PACH, Chunk_FNTS, Chunk_ODEV, Chunk_TITL, Chunk_ALOT, Chunk_ENGR, Chunk_FMAP, Chunk_PCPR, // Overture 3.6 Chunk_LYRC, Chunk_NONE }; ChunkType nameToChunkType(const NameBlock& name) { ChunkType type = Chunk_NONE; if (name.isEqual("OVSC")) { type = Chunk_OVSC; } else if (name.isEqual("TRKL")) { type = Chunk_TRKL; } else if (name.isEqual("TRAK")) { type = Chunk_TRAK; } else if (name.isEqual("PAGL")) { type = Chunk_PAGL; } else if (name.isEqual("PAGE")) { type = Chunk_PAGE; } else if (name.isEqual("LINL")) { type = Chunk_LINL; } else if (name.isEqual("LINE")) { type = Chunk_LINE; } else if (name.isEqual("STAF")) { type = Chunk_STAF; } else if (name.isEqual("BARL")) { type = Chunk_BARL; } else if (name.isEqual("MEAS")) { type = Chunk_MEAS; } else if (name.isEqual("COND")) { type = Chunk_COND; } else if (name.isEqual("BDAT")) { type = Chunk_BDAT; } else if (name.isEqual("PACH")) { type = Chunk_PACH; } else if (name.isEqual("FNTS")) { type = Chunk_FNTS; } else if (name.isEqual("ODEV")) { type = Chunk_ODEV; } else if (name.isEqual("TITL")) { type = Chunk_TITL; } else if (name.isEqual("ALOT")) { type = Chunk_ALOT; } else if (name.isEqual("ENGR")) { type = Chunk_ENGR; } else if (name.isEqual("FMAP")) { type = Chunk_FMAP; } else if (name.isEqual("PCPR")) { type = Chunk_PCPR; } else if (name.isEqual("LYRC")) { type = Chunk_LYRC; } return type; } int chunkTypeToMaxTimes(ChunkType type) { int maxTimes = -1; // no limit switch (type) { case Chunk_OVSC: { maxTimes = 1; break; } case Chunk_TRKL: {// case Chunk_TRAK : maxTimes = 1; break; } case Chunk_PAGL: {// case Chunk_PAGE : maxTimes = 1; break; } // case Chunk_LINE : // case Chunk_STAF : case Chunk_LINL: { maxTimes = 1; break; } // case Chunk_MEAS : // case Chunk_COND : // case Chunk_BDAT : case Chunk_BARL: { maxTimes = 1; break; } case Chunk_PACH: case Chunk_FNTS: case Chunk_ODEV: case Chunk_ALOT: case Chunk_ENGR: case Chunk_FMAP: case Chunk_PCPR: { maxTimes = 1; break; } case Chunk_TITL: { maxTimes = 8; break; } case Chunk_LYRC: { maxTimes = 1; break; } // case Chunk_NONE : default: break; } return maxTimes; } /////////////////////////////////////////////////////////////////////////////////////////// OveSerialize::OveSerialize() : ove_(0), streamHandle_(0), notify_(0) { } OveSerialize::~OveSerialize() { if(streamHandle_ != 0) { delete streamHandle_; streamHandle_ = 0; } } void OveSerialize::setOve(OveSong* ove) { ove_ = ove; } void OveSerialize::setFileStream(unsigned char* buffer, unsigned int size) { streamHandle_ = new StreamHandle(buffer, size); } void OveSerialize::setNotify(IOveNotify* notify) { notify_ = notify; } void OveSerialize::messageOutError() { if (notify_ != NULL) { notify_->loadError(); } } void OveSerialize::messageOut(const QString& str) { if (notify_ != NULL) { notify_->loadInfo(str); } } bool OveSerialize::load(void) { if(streamHandle_ == 0) return false; if( !readHeader() ) { messageOutError(); return false; } unsigned int i; QMap chunkTimes; //bool firstEnter = true; for( i=(int)Chunk_OVSC; i<(int)Chunk_NONE; ++i ) { chunkTimes[(ChunkType)i] = 0; } ChunkType chunkType = Chunk_NONE; do { NameBlock nameBlock; SizeChunk sizeChunk; if( !readNameBlock(nameBlock) ) { return false; } chunkType = nameToChunkType(nameBlock); ++chunkTimes[chunkType]; int maxTime = chunkTypeToMaxTimes(chunkType); if( maxTime > 0 && chunkTimes[chunkType] > maxTime ) { messageOut("format not support, chunk appear more than accept."); return false; } switch (chunkType) { /*case Chunk_OVSC : { if( !readHeadData(&sizeChunk) ) { messageOut_error(); return false; } break; }*/ case Chunk_TRKL: { if (!readTracksData()) { messageOutError(); return false; } break; } case Chunk_PAGL: { if (!readPagesData()) { messageOutError(); return false; } break; } case Chunk_LINL: { if (!readLinesData()) { messageOutError(); return false; } break; } case Chunk_BARL: { if (!readBarsData()) { messageOutError(); return false; } break; } case Chunk_TRAK: case Chunk_PAGE: case Chunk_LINE: case Chunk_STAF: case Chunk_MEAS: case Chunk_COND: case Chunk_BDAT: { return false; break; } case Chunk_LYRC: { SizeChunk lyricChunk; if (!readSizeChunk(&lyricChunk)) { messageOutError(); return false; } LyricChunkParse parse(ove_); parse.setLyricChunk(&lyricChunk); parse.parse(); break; } case Chunk_TITL: { SizeChunk titleChunk; if (!readSizeChunk(&titleChunk)) { messageOutError(); return false; } TitleChunkParse titleChunkParse(ove_); titleChunkParse.setTitleChunk(&titleChunk); titleChunkParse.parse(); break; } case Chunk_PACH: case Chunk_FNTS: case Chunk_ODEV: case Chunk_ALOT: case Chunk_ENGR: case Chunk_FMAP: case Chunk_PCPR: { if (!readSizeChunk(&sizeChunk)) { messageOutError(); return false; } break; } default: /*if( firstEnter ) { QString info = "Not compatible file, try to load and save with newer version, Overture 4 is recommended."; messageOut(info); messageOutError(); return false; }*/ break; } //firstEnter = false; } while ( chunkType != Chunk_NONE ); // if( !readOveEnd() ) { return false; } // organize OveData OVE::OveOrganizer organizer(ove_); organizer.organize(); return true; } void OveSerialize::release() { delete this; } bool OveSerialize::readHeader() { ChunkType chunkType = Chunk_NONE; NameBlock nameBlock; SizeChunk sizeChunk; if (!readNameBlock(nameBlock)) { return false; } chunkType = nameToChunkType(nameBlock); //int maxTime = chunkTypeToMaxTimes(chunkType); if (chunkType == Chunk_OVSC) { if (readHeadData(&sizeChunk)) { return true; } } QString info = "Not compatible file, try to load and save with newer version, Overture 4 is recommended."; messageOut(info); return false; } bool OveSerialize::readHeadData(SizeChunk* ovscChunk) { if (!readSizeChunk(ovscChunk)) return false; OvscParse ovscParse(ove_); ovscParse.setNotify(notify_); ovscParse.setOvsc(ovscChunk); return ovscParse.parse(); } bool OveSerialize::readTracksData() { GroupChunk trackGroupChunk; if (!readGroupChunk(&trackGroupChunk)) return false; unsigned int i; unsigned short trackCount = trackGroupChunk.getCountBlock()->toCount(); for (i = 0; i < trackCount; ++i) { SizeChunk* trackChunk = new SizeChunk(); if (ove_->getIsVersion4()) { if (!readChunkName(trackChunk, Chunk::TrackName)) { return false; } if (!readSizeChunk(trackChunk)) { return false; } } else { if (!readDataChunk(trackChunk->getDataBlock(), SizeChunk::version3TrackSize)) { return false; } } TrackParse trackParse(ove_); trackParse.setTrack(trackChunk); trackParse.parse(); } return true; } bool OveSerialize::readPagesData() { GroupChunk pageGroupChunk; if (!readGroupChunk(&pageGroupChunk)) return false; unsigned short pageCount = pageGroupChunk.getCountBlock()->toCount(); unsigned int i; PageGroupParse parse(ove_); for (i = 0; i < pageCount; ++i) { SizeChunk* pageChunk = new SizeChunk(); if (!readChunkName(pageChunk, Chunk::PageName)) { return false; } if (!readSizeChunk(pageChunk)) { return false; } parse.addPage(pageChunk); } if (!parse.parse()) { return false; } return true; } bool OveSerialize::readLinesData() { GroupChunk lineGroupChunk; if (!readGroupChunk(&lineGroupChunk)) return false; unsigned short lineCount = lineGroupChunk.getCountBlock()->toCount(); int i; unsigned int j; QList lineChunks; QList staffChunks; for (i = 0; i < lineCount; ++i) { SizeChunk* lineChunk = new SizeChunk(); if (!readChunkName(lineChunk, Chunk::LineName)) { return false; } if (!readSizeChunk(lineChunk)) { return false; } lineChunks.push_back(lineChunk); StaffCountGetter getter(ove_); unsigned int staffCount = getter.getStaffCount(lineChunk); for (j = 0; j < staffCount; ++j) { SizeChunk* staffChunk = new SizeChunk(); if (!readChunkName(staffChunk, Chunk::StaffName)) { return false; } if (!readSizeChunk(staffChunk)) { return false; } staffChunks.push_back(staffChunk); } } LineGroupParse parse(ove_); parse.setLineGroup(&lineGroupChunk); for (i = 0; i < lineChunks.size(); ++i) { parse.addLine(lineChunks[i]); } for (i = 0; i < staffChunks.size(); ++i) { parse.addStaff(staffChunks[i]); } if (!parse.parse()) { return false; } return true; } bool OveSerialize::readBarsData() { GroupChunk barGroupChunk; if (!readGroupChunk(&barGroupChunk)) return false; unsigned short measCount = barGroupChunk.getCountBlock()->toCount(); int i; QList measureChunks; QList conductChunks; QList bdatChunks; ove_->setTrackBarCount(measCount); // read chunks for (i = 0; i < measCount; ++i) { SizeChunk* measureChunkPtr = new SizeChunk(); if (!readChunkName(measureChunkPtr, Chunk::MeasureName)) { return false; } if (!readSizeChunk(measureChunkPtr)) { return false; } measureChunks.push_back(measureChunkPtr); } for (i = 0; i < measCount; ++i) { SizeChunk* conductChunkPtr = new SizeChunk(); if (!readChunkName(conductChunkPtr, Chunk::ConductName)) return false; if (!readSizeChunk(conductChunkPtr)) return false; conductChunks.push_back(conductChunkPtr); } int bdatCount = ove_->getTrackCount() * measCount; for (i = 0; i < bdatCount; ++i) { SizeChunk* batChunkPtr = new SizeChunk(); if (!readChunkName(batChunkPtr, Chunk::BdatName)) { return false; } if (!readSizeChunk(batChunkPtr)) { return false; } bdatChunks.push_back(batChunkPtr); } // parse bars BarsParse barsParse(ove_); for (i = 0; i < (int) measureChunks.size(); ++i) { barsParse.addMeasure(measureChunks[i]); } for (i = 0; i < (int) conductChunks.size(); ++i) { barsParse.addConduct(conductChunks[i]); } for (i = 0; i < (int) bdatChunks.size(); ++i) { barsParse.addBdat(bdatChunks[i]); } barsParse.setNotify(notify_); if (!barsParse.parse()) { return false; } return true; } bool OveSerialize::readOveEnd() { if (streamHandle_ == 0) return false; const unsigned int END_OVE1 = 0xffffffff; const unsigned int END_OVE2 = 0x00000000; unsigned int buffer; if (!streamHandle_->read((char*) &buffer, sizeof(unsigned int))) return false; if (buffer != END_OVE1) return false; if (!streamHandle_->read((char*) &buffer, sizeof(unsigned int))) return false; if (buffer != END_OVE2) return false; return true; } ///////////////////////////////////////////////////////////////////////////////////////// bool OveSerialize::readNameBlock(NameBlock& nameBlock) { if (streamHandle_ == 0) return false; if (!streamHandle_->read((char*) nameBlock.data(), nameBlock.size())) return false; return true; } bool OveSerialize::readChunkName(Chunk* /*chunk*/, const QString& name) { if (streamHandle_ == 0) return false; NameBlock nameBlock; if (!streamHandle_->read((char*) nameBlock.data(), nameBlock.size())) return false; if (!(nameBlock.toStrByteArray() == name)) return false; return true; } bool OveSerialize::readSizeChunk(SizeChunk* sizeChunk) { if (streamHandle_ == 0) return false; SizeBlock* sizeBlock = sizeChunk->getSizeBlock(); if (!streamHandle_->read((char*) sizeBlock->data(), sizeBlock->size())) return false; unsigned int blockSize = sizeBlock->toSize(); sizeChunk->getDataBlock()->resize(blockSize); Block* dataBlock = sizeChunk->getDataBlock(); if (!streamHandle_->read((char*) dataBlock->data(), blockSize)) return false; return true; } bool OveSerialize::readDataChunk(Block* block, unsigned int size) { if (streamHandle_ == 0) return false; block->resize(size); if (!streamHandle_->read((char*) block->data(), size)) return false; return true; } bool OveSerialize::readGroupChunk(GroupChunk* groupChunk) { if (streamHandle_ == 0) return false; CountBlock* countBlock = groupChunk->getCountBlock(); if (!streamHandle_->read((char*) countBlock->data(), countBlock->size())) return false; return true; } IOVEStreamLoader* createOveStreamLoader() { return new OveSerialize; } } // end of OVE namespace //////////////////////////////////////////////////////////////////////////////////////////////////// namespace drumstick { /** * @addtogroup OVE * @{ * * QOve provides a mechanism to parse Overture OVE Files, without * the burden of a policy forcing to use some internal sequence representation. * * This class is not related or based on the ALSA library. * * @} */ class MeasureToTick { public: MeasureToTick(); virtual ~MeasureToTick() { } public: void build(OVE::OveSong* ove, int quarter); struct TimeTick { int numerator_; int denominator_; int measure_; int tick_; TimeTick() : numerator_(4), denominator_(4), measure_(0), tick_(0) { } }; int getTick(int measure, int tickOffset); QList getTimeTicks() const; private: int quarter_; OVE::OveSong* ove_; QList tts_; }; int getMeasureTick(int quarter, int num, int den) { return quarter * 4 * num / den; } MeasureToTick::MeasureToTick() { quarter_ = 480; ove_ = NULL; } void MeasureToTick::build(OVE::OveSong* ove, int quarter) { unsigned int i; int currentTick = 0; unsigned int measureCount = ove->getMeasureCount(); quarter_ = quarter; ove_ = ove; tts_.clear(); for (i = 0; i < measureCount; ++i) { OVE::Measure* measure = ove_->getMeasure(i); OVE::TimeSignature* time = measure->getTime(); TimeTick tt; bool change = false; tt.tick_ = currentTick; tt.numerator_ = time->getNumerator(); tt.denominator_ = time->getDenominator(); tt.measure_ = i; if (i == 0) { change = true; } else { OVE::TimeSignature* previousTime = ove_->getMeasure(i - 1)->getTime(); if (time->getNumerator() != previousTime->getNumerator() || time->getDenominator() != previousTime->getDenominator()) { change = true; } } if (change) { tts_.push_back(tt); } currentTick += getMeasureTick(quarter_, tt.numerator_, tt.denominator_); } } int MeasureToTick::getTick(int measure, int tickOffset) { int i; TimeTick tt; for (i = 0; i < tts_.size(); ++i) { if (measure >= tts_[i].measure_ && (i == tts_.size() - 1 || measure < tts_[i + 1].measure_)) { int measuresTick = (measure - tts_[i].measure_) * getMeasureTick(quarter_, tts_[i].numerator_, tts_[i].denominator_); return tts_[i].tick_ + measuresTick + tickOffset; } } return 0; } QList MeasureToTick::getTimeTicks() const { return tts_; } ///////////////////////////////////////////////////////////////////////////////////////// class QOve::QOvePrivate { public: QOvePrivate() {} ~QOvePrivate() {} OVE::OveSong ove; MeasureToTick mtt; }; /** * Constructor */ QOve::QOve(QObject * parent) : QObject(parent), d(new QOvePrivate) { } /** * Destructor */ QOve::~QOve() { delete d; } /** * Sets the text codec for text meta-events. * * @param codec Name of the text codec */ void QOve::setTextCodecName(const QString& codec) { d->ove.setTextCodecName(codec); } /** * Reads an Overture file. * * @param fileName Name of an existing file. */ void QOve::readFromFile(const QString& fileName) { QFile oveFile(fileName); bool success = true; if (oveFile.open(QFile::ReadOnly)) { QByteArray buffer = oveFile.readAll(); oveFile.close(); d->ove.clear(); // ove -> OveSong OVE::IOVEStreamLoader* oveLoader = OVE::createOveStreamLoader(); oveLoader->setOve(&d->ove); oveLoader->setFileStream((unsigned char*) buffer.data(), buffer.size()); oveLoader->setNotify(0); bool result = oveLoader->load(); oveLoader->release(); if(!result) success = false; if (result) { convertSong(); } } if (!success) { Q_EMIT signalOVEError( "Cannot read this OVE file, " "probably because it has an incompatible format.\n" "Please, convert it using Overture 4 or a newer version."); } } void QOve::convertSong() { unsigned int i; int trackNo = 0; d->mtt.build(&d->ove, d->ove.getQuarter()); Q_EMIT signalOVEHeader(d->ove.getQuarter(), d->ove.getTrackCount()); convertSignatures(); for (i = 0; i < (unsigned int) d->ove.getPartCount(); ++i) { int partStaffCount = d->ove.getStaffCount(i); for (int j = 0; j < partStaffCount; ++j) { OVE::Track* trackPtr = d->ove.getTrack(i, j); int transpose = trackPtr->getShowTranspose() ? trackPtr->getTranspose() : 0; convertTrackHeader(trackPtr, trackNo); //int beginMeasure = 0; int endMeasure = d->ove.getMeasureCount(); int offsetTick = 0; for (int l = 0; l < endMeasure; ++l) { OVE::Measure* measure = d->ove.getMeasure(l); OVE::MeasureData* measureData = d->ove.getMeasureData(i, j, l); /* if (notify_ != NULL) { notify_->notify_convert_pos(l, endMeasure, trackID, d->ove_.getPartCount()); }*/ convertMeasure(trackPtr, trackNo, trackPtr->getVoices(), measure, measureData, transpose, offsetTick); } ++trackNo; } } Q_EMIT signalOVEEnd(); } void QOve::convertSignatures() { int i; int beginMeasure = 0; int endMeasure = d->ove.getMeasureCount(); // tempo QMap tempos; for (i = 0; i < d->ove.getPartCount(); ++i) { if(i>0) { break; } int partStaffCount = d->ove.getStaffCount(i); for (int j = 0; j < partStaffCount; ++j) { if(j>0) { break; } for (int k = beginMeasure; k < endMeasure; ++k) { OVE::Measure* measure = d->ove.getMeasure(k); OVE::MeasureData* measureData = d->ove.getMeasureData(i, j, k); QList tempoPtrs = measureData->getMusicDatas(OVE::MusicData_Tempo); if (k == 0 || (k > 0 && std::abs(measure->getTypeTempo() - d->ove.getMeasure(k - 1)->getTypeTempo()) > 0.01)) { int tick = d->mtt.getTick(k, 0); int tempo = (int) measure->getTypeTempo(); tempos[tick] = tempo; } for (int l = 0; l < tempoPtrs.size(); ++l) { OVE::Tempo* ptr = static_cast (tempoPtrs[l]); int tick = d->mtt.getTick(measure->getBarNumber()->getIndex(), ptr->getTick()); int tempo = ptr->getQuarterTempo() > 0 ? ptr->getQuarterTempo() : 1; tempos[tick] = tempo; } } } } QMap::iterator it; int lastTempo = 0; for (it = tempos.begin(); it != tempos.end(); ++it) { if (it == tempos.begin() || it.value() != lastTempo) { Q_EMIT signalOVETempo(it.key(), it.value()*100); } lastTempo = it.value(); } // time signature const QList tts = d->mtt.getTimeTicks(); for (i = 0; i < (int) tts.size(); ++i) { if (beginMeasure <= tts[i].measure_ && endMeasure > tts[i].measure_) { Q_EMIT signalOVETimeSig(tts[i].measure_, tts[i].tick_, tts[i].numerator_, tts[i].denominator_); } } // key signature bool createKey = false; for (i = beginMeasure; i < endMeasure; ++i) { OVE::MeasureData* measureData = d->ove.getMeasureData(0, 0, i); if (measureData != NULL) { OVE::Key* keyPtr = measureData->getKey(); if (i == 0 || keyPtr->getKey() != keyPtr->getPreviousKey()) { Q_EMIT signalOVEKeySig(i, d->mtt.getTick(i, 0), keyPtr->getKey()); createKey = true; } } } if (!createKey) { Q_EMIT signalOVEKeySig(0, 0, 0); } } void QOve::convertTrackHeader(OVE::Track* track, int trackNo) { int i; const QList voices = track->getVoices(); QMap patches; // channel, patch QMap pans; // channel, pan QMap volumes; // channel, volume QMap::iterator it; int ch = 0; int vol = 100; int patch = 0; // name QString trackName = track->getName(); // patch, pan(control 10), volume(control 7) for (i = 0; i < voices.size() && i < (unsigned int)track->getVoiceCount(); ++i) { int patch = voices[i]->getPatch(); int channel = voices[i]->getChannel(); int volume = voices[i]->getVolume(); if (patch != OVE::Voice::getDefaultPatch()) { patches[channel] = patch; } pans[channel] = voices[i]->getPan(); if (volume != OVE::Voice::getDefaultVolume()) { volumes[channel] = volume; } ch = channel; vol = volume; } // patch for (it = patches.begin(); it != patches.end(); ++it) { patch = it.value(); break; } // pan int lastPan = 64;//center for (it = pans.begin(); it != pans.end(); ++it) { if (it.value() != 0 && it.value() != lastPan) { Q_EMIT signalOVECtlChange(trackNo, 0, ch, 10, it.value()); } lastPan = it.value(); } // volume for (it = volumes.begin(); it != volumes.end(); ++it) { int volume = it.value(); if (volume != -1) { Q_EMIT signalOVECtlChange(trackNo, 0, ch, 7, it.value()); } } Q_EMIT signalOVENewTrack(track->getName(), trackNo, ch, 0, vol, 0, false, false, false); Q_EMIT signalOVETrackBank(trackNo, ch, 0); Q_EMIT signalOVETrackPatch(trackNo, ch, patch); } int getPitchShift(const QList& voices, int voice) { if (voice >= 0 && voice < (int) voices.size()) return voices[voice]->getPitchShift(); return 0; } int getChannel(const QList& voices, int voice) { if (voice >= 0 && voice < (int) voices.size()) return voices[voice]->getChannel(); return 0; } int getTick(int tick) { if(tick > 0) return tick; return 0; } void QOve::convertMeasure( OVE::Track* track, int trackNo, const QList& voices, OVE::Measure* measure, OVE::MeasureData* measureData, int transpose, int offsetTick) { Q_UNUSED(track) int i; int measureId = measure->getBarNumber()->getIndex(); QList containers = measureData->getNoteContainers(); // midi notes for (i = 0; i < containers.size(); ++i) { OVE::NoteContainer* container = containers[i]; int measureTick = d->mtt.getTick(measureId, 0); convertNotes( trackNo, measureTick, container, getChannel(voices, container->getVoice()), getPitchShift(voices, container->getVoice()) - transpose); } // midi events in graph window QList midiDatas = measureData->getMidiDatas(OVE::Midi_None); int channel = getChannel(voices, 0); for (i = 0; i < midiDatas.size(); ++i) { OVE::MidiType midiType = midiDatas[i]->getMidiType(); int midiTick = getTick(d->mtt.getTick(measureId, midiDatas[i]->getTick()) + offsetTick); switch (midiType) { case OVE::Midi_Controller: { OVE::MidiController* controller = static_cast (midiDatas[i]); Q_EMIT signalOVECtlChange(trackNo, midiTick, channel, controller->getController(), controller->getValue()); break; } case OVE::Midi_Program_Change: { OVE::MidiProgramChange* program = static_cast (midiDatas[i]); Q_EMIT signalOVEProgram(trackNo, midiTick, channel, program->getPatch()); break; } case OVE::Midi_Channel_Pressure: { OVE::MidiChannelPressure* pressure = static_cast (midiDatas[i]); Q_EMIT signalOVEChanPress(trackNo, midiTick, channel, pressure->getPressure()); break; } case OVE::Midi_Pitch_Wheel: { OVE::MidiPitchWheel* pitchWheel = static_cast (midiDatas[i]); Q_EMIT signalOVEPitchBend(trackNo, midiTick, channel, pitchWheel->getValue()); break; } default: break; } } // MusicData QList musicDatas = measureData->getMusicDatas(OVE::MusicData_None); for (i = 0; i < musicDatas.size(); ++i) { OVE::MusicDataType type = musicDatas[i]->getMusicDataType(); int musicDataTick = getTick(d->mtt.getTick(measureId, musicDatas[i]->getTick()) + offsetTick); switch (type) { case OVE::MusicData_Lyric: { OVE::Lyric* lyricPtr = static_cast (musicDatas[i]); Q_EMIT signalOVEText(trackNo, musicDataTick, lyricPtr->getLyric()); break; } case OVE::MusicData_Dynamics: { OVE::Dynamics* dynamicPtr = static_cast (musicDatas[i]); Q_EMIT signalOVECtlChange(trackNo, musicDataTick, channel, 7, dynamicPtr->getVelocity()); break; } case OVE::MusicData_Decorator: { OVE::Decorator* decorator = static_cast (musicDatas[i]); if (decorator->getDecoratorType() == OVE::Decorator::Decorator_Articulation) { OVE::ArticulationType artType = decorator->getArticulationType(); switch (artType) { case OVE::Articulation_Pedal_Down: { Q_EMIT signalOVECtlChange(trackNo, musicDataTick, channel, 64, 64); break; } case OVE::Articulation_Pedal_Up: { Q_EMIT signalOVECtlChange(trackNo, musicDataTick, channel, 64, 0); break; } default: break; } } break; } default: break; } } } bool hasNoteOn(int pos) { return (pos & OVE::Tie_RightEnd) != OVE::Tie_RightEnd; } bool hasNoteOff(int pos) { return (pos & OVE::Tie_LeftEnd) != OVE::Tie_LeftEnd; } int noteTypeToTick(OVE::NoteType type, int quarter = 480) { int c = int(pow(2.0, (int) type)); return quarter * 4 * 2 / c; } void QOve::convertNotes(int trackNo, int measureTick, OVE::NoteContainer* container, int channel, int pitchShift) { if (container->getIsRest()) { return; } int i; int j; int k; QList notes = container->getNotesRests(); QList articulations = container->getArticulations(); bool changeNoteCount = false; // for those who can change note numbers for (i = 0; i < articulations.size(); ++i) { OVE::Articulation* art = articulations[i]; OVE::ArticulationType type = art->getArtType(); for (j = 0; j < notes.size(); ++j) { OVE::Note* notePtr = notes[j]; unsigned int velocityValue = notePtr->getOnVelocity(); int noteValue = notePtr->getNote() + container->getNoteShift() + pitchShift; int startTick = measureTick + container->getTick() + notePtr->getOffsetTick(); // note on if (hasNoteOn(notePtr->getTiePos())) { switch (type) { // tremolo case OVE::Articulation_Tremolo_Eighth: case OVE::Articulation_Tremolo_Sixteenth: case OVE::Articulation_Tremolo_Thirty_Second: case OVE::Articulation_Tremolo_Sixty_Fourth: { int noteCount = (int) pow(2.0, ((int) type - (int) OVE::Articulation_Tremolo_Eighth) + 1); int noteTick = noteTypeToTick(container->getNoteType(), d->ove.getQuarter()) / noteCount; for (k = 0; k < noteCount; ++k) { // on int onTick = getTick(startTick + k * noteTick); Q_EMIT signalOVENoteOn(trackNo, onTick, channel, noteValue, velocityValue); if (k < noteCount - 1 || hasNoteOff((int) notePtr->getTiePos())) { // off int offTick = getTick(startTick + (k + 1) * noteTick); Q_EMIT signalOVENoteOff(trackNo, offTick, channel, noteValue, velocityValue); } } changeNoteCount = true; break; } default: break; } } } } if (changeNoteCount) { return; } // others who can change note properties for (i = 0; i < notes.size(); ++i) { OVE::Note* notePtr = notes[i]; unsigned int velocityValue = notePtr->getOnVelocity(); int noteValue = notePtr->getNote() + container->getNoteShift() + pitchShift; int startTick = getTick(measureTick + container->getTick() + notePtr->getOffsetTick()); int lengthTick = container->getLength(); // note on if (hasNoteOn((int) notePtr->getTiePos())) { for (j = 0; j < articulations.size(); ++j) { OVE::Articulation* art = articulations[j]; OVE::ArticulationType type = art->getArtType(); if (art->getChangeLength()) { lengthTick = noteTypeToTick(container->getNoteType(), d->ove.getQuarter()) * art->getLengthPercentage() / 100; } if (art->getChangeVelocity()) { switch (art->getVelocityType()) { case OVE::Articulation::Velocity_Offset: { velocityValue += art->getVelocityValue(); break; } case OVE::Articulation::Velocity_Percentage: { velocityValue *= (unsigned int) ((double) art->getVelocityValue() / (double) 100); break; } case OVE::Articulation::Velocity_SetValue: { velocityValue = art->getVelocityValue(); break; } default: break; } } if (art->getChangeExtraLength()) { } switch (type) { case OVE::Articulation_Pedal_Down: { Q_EMIT signalOVECtlChange(trackNo, startTick, channel, 64, 64); break; } case OVE::Articulation_Pedal_Up: { Q_EMIT signalOVECtlChange(trackNo, startTick, channel, 64, 0); break; } case OVE::Articulation_Arpeggio: { //if( art->getChangeSoundEffect() ) { unsigned int soundEffect = std::abs(art->getSoundEffect().first) + std::abs(art->getSoundEffect().second); int tickAmount = (soundEffect / notes.size()) * ((notes.size() - i) - 1); startTick -= tickAmount; //} break; } default: break; } } Q_EMIT signalOVENoteOn(trackNo, getTick(startTick), channel, noteValue, velocityValue); } // note off if (hasNoteOff(notePtr->getTiePos())) { Q_EMIT signalOVENoteOff(trackNo, getTick(startTick + lengthTick), channel, noteValue, velocityValue); } } return; } } // namespace drumstick drumstick-1.1.3/library/file/PaxHeaders.32572/qsmf.cpp0000644000000000000000000000013013532747316017326 xustar0029 mtime=1567346382.71399987 30 atime=1567346383.002000241 29 ctime=1567346382.71399987 drumstick-1.1.3/library/file/qsmf.cpp0000644000175000001440000007013513532747316020127 0ustar00pedrousers00000000000000/* Standard MIDI File component Copyright (C) 2006-2019, Pedro Lopez-Cabanillas Based on midifile.c by Tim Thompson, M.Czeiszperger and Greg Lee This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include /** * @file qsmf.cpp * Implementation of a class managing Standard MIDI Files input/output */ namespace drumstick { /** * @addtogroup SMF * @{ * * QSmf provides a mechanism to parse and encode Standard MIDI Files, without * the burden of a policy forcing to use some internal sequence representation. * * This class is not related or based on the ALSA library. * * @} */ class QSmf::QSmfPrivate { public: QSmfPrivate(): m_Interactive(false), m_CurrTime(0), m_RealTime(0), m_DblRealTime(0), m_DblOldRealtime(0), m_Division(96), m_CurrTempo(500000), m_OldCurrTempo(500000), m_OldRealTime(0), m_OldCurrTime(0), m_RevisedTime(0), m_TempoChangeTime(0), m_ToBeRead(0), m_NumBytesWritten(0), m_Tracks(0), m_fileFormat(0), m_LastStatus(0), m_codec(nullptr), m_IOStream(nullptr) { } bool m_Interactive; /**< file and track headers are not required */ quint64 m_CurrTime; /**< current time in delta-time units */ quint64 m_RealTime; /**< current time in 1/16 centisecond-time units */ double m_DblRealTime; /**< as above, floating */ double m_DblOldRealtime; int m_Division; /**< ticks per beat. Default = 96 */ quint64 m_CurrTempo; /**< microseconds per quarter note */ quint64 m_OldCurrTempo; quint64 m_OldRealTime; quint64 m_OldCurrTime; quint64 m_RevisedTime; quint64 m_TempoChangeTime; quint64 m_ToBeRead; quint64 m_NumBytesWritten; int m_Tracks; int m_fileFormat; int m_LastStatus; QTextCodec *m_codec; QDataStream *m_IOStream; QByteArray m_MsgBuff; QList m_TempoList; }; /** * Constructor * @param parent Optional parent object */ QSmf::QSmf(QObject * parent) : QObject(parent), d(new QSmfPrivate) { } /** * Destructor */ QSmf::~QSmf() { d->m_TempoList.clear(); delete d; } /** * Check if the SMF stream is positioned at the end. * @return True if the SMF stream is at the end */ bool QSmf::endOfSmf() { return d->m_IOStream->atEnd(); } /** * Gets a single byte from the SMF stream * @return A Single byte */ quint8 QSmf::getByte() { quint8 b = 0; if (!endOfSmf()) { *d->m_IOStream >> b; d->m_ToBeRead--; } return b; } /** * Puts a single byte to the SMF stream * @param value A Single byte */ void QSmf::putByte(quint8 value) { *d->m_IOStream << value; d->m_NumBytesWritten++; } /** * Adds a tempo change to the internal tempo list * @param tempo Tempo in microseconds per quarter * @param time Location in ticks */ void QSmf::addTempo(quint64 tempo, quint64 time) { QSmfRecTempo tempoRec; tempoRec.tempo = tempo; tempoRec.time = time; d->m_TempoList.append(tempoRec); } /** * Reads a SMF header */ void QSmf::readHeader() { d->m_CurrTime = 0; d->m_RealTime = 0; d->m_Division = 96; d->m_CurrTempo = 500000; d->m_OldCurrTempo = 500000; addTempo(d->m_CurrTempo, 0); if (d->m_Interactive) { d->m_fileFormat= 0; d->m_Tracks = 1; d->m_Division = 96; } else { readExpected("MThd"); d->m_ToBeRead = read32bit(); d->m_fileFormat = read16bit(); d->m_Tracks = read16bit(); d->m_Division = read16bit(); } emit signalSMFHeader(d->m_fileFormat, d->m_Tracks, d->m_Division); /* flush any extra stuff, in case the length of header is not */ while ((d->m_ToBeRead > 0) && !endOfSmf()) { getByte(); } if (d->m_ToBeRead > 0) { SMFError("Unexpected end of input"); } } /** * Reads a track chunk */ void QSmf::readTrack() { /* This array is indexed by the high half of a status byte. It's value is either the number of bytes needed (1 or 2) for a channel message, or 0 (meaning it's not a channel message). */ static const quint8 chantype[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 2, 0 }; quint64 lookfor; quint8 c, c1, type; bool sysexcontinue; // 1 if last message was an unfinished SysEx bool running; // 1 when running status used quint8 status; // status value (e.g. 0x90==note-on) int needed; double delta_secs; quint64 delta_ticks, save_time, save_tempo; sysexcontinue = false; status = 0; if (d->m_Interactive) { d->m_ToBeRead = std::numeric_limits::max(); } else { readExpected("MTrk"); d->m_ToBeRead = read32bit(); } d->m_CurrTime = 0; d->m_RealTime = 0; d->m_DblRealTime = 0; d->m_DblOldRealtime = 0; d->m_OldCurrTime = 0; d->m_OldRealTime = 0; d->m_CurrTempo = findTempo(); emit signalSMFTrackStart(); while (!endOfSmf() && (d->m_Interactive || d->m_ToBeRead > 0)) { lookfor = 0; if (d->m_Interactive) { d->m_CurrTime++; } else { delta_ticks = unsigned(readVarLen()); d->m_RevisedTime = d->m_CurrTime; d->m_CurrTime += delta_ticks; while (d->m_RevisedTime < d->m_CurrTime) { save_time = d->m_RevisedTime; save_tempo = d->m_CurrTempo; d->m_CurrTempo = findTempo(); if (d->m_CurrTempo != d->m_OldCurrTempo) { d->m_OldCurrTempo = d->m_CurrTempo; d->m_OldRealTime = d->m_RealTime; if (d->m_RevisedTime != d->m_TempoChangeTime) { d->m_DblOldRealtime = d->m_DblRealTime; d->m_OldCurrTime = save_time; } delta_secs = ticksToSecs(d->m_RevisedTime - d->m_OldCurrTime, quint16(d->m_Division), save_tempo); d->m_DblRealTime = d->m_DblOldRealtime + delta_secs * 1600.0; d->m_RealTime = quint64(0.5 + d->m_DblRealTime); if (d->m_RevisedTime == d->m_TempoChangeTime) { d->m_OldCurrTime = d->m_RevisedTime; d->m_DblOldRealtime = d->m_DblRealTime; } } else { delta_secs = ticksToSecs(d->m_RevisedTime - d->m_OldCurrTime, quint16(d->m_Division), d->m_CurrTempo); d->m_DblRealTime = d->m_DblOldRealtime + delta_secs * 1600.0; d->m_RealTime = quint64(0.5 + d->m_DblRealTime); } } } c = getByte(); if (sysexcontinue && (c != end_of_sysex)) { SMFError("didn't find expected continuation of a SysEx"); } if (c < 0xf8) { if ((c & 0x80) == 0) { if (status == 0) { SMFError("unexpected running status"); } running = true; } else { status = c; running = false; } needed = chantype[status >> 4 & 0x0f]; if (needed != 0) { if (running) { c1 = c; } else { c1 = getByte(); } if (needed > 1) { channelMessage(status, c1, getByte()); } else { channelMessage(status, c1, 0); } continue; } } switch (c) { case meta_event: type = getByte(); lookfor = quint64(readVarLen()); lookfor = d->m_ToBeRead - lookfor; msgInit(); while ((d->m_ToBeRead > lookfor) && !endOfSmf()) { msgAdd(getByte()); } metaEvent(type); break; case system_exclusive: lookfor = quint64(readVarLen()); lookfor = d->m_ToBeRead - lookfor; msgInit(); msgAdd(system_exclusive); while ((d->m_ToBeRead > lookfor) && !endOfSmf()) { c = getByte(); msgAdd(c); } if (c == end_of_sysex) { sysEx(); } else { sysexcontinue = true; } break; case end_of_sysex: lookfor = readVarLen(); lookfor = d->m_ToBeRead - lookfor; if (!sysexcontinue) { msgInit(); } while ((d->m_ToBeRead > lookfor) && !endOfSmf()) { c = getByte(); msgAdd(c); } if (sysexcontinue) { if (c == end_of_sysex) { sysEx(); sysexcontinue = false; } } break; default: badByte(c, d->m_IOStream->device()->pos() - 1); break; } if ((d->m_ToBeRead > lookfor) && endOfSmf()) { SMFError("Unexpected end of input"); } } emit signalSMFTrackEnd(); } /** * Reads a SMF stream. */ void QSmf::SMFRead() { int i; readHeader(); for ( i = d->m_Tracks; (i > 0) && !endOfSmf(); i--) { readTrack(); } } /** * Writes a SMF stream. * * Every MIDI file starts with a header. * In format 1 files, the first track is a tempo map. * The rest of the file is a series of tracks */ void QSmf::SMFWrite() { int i; d->m_LastStatus = 0; writeHeaderChunk(d->m_fileFormat, d->m_Tracks, d->m_Division); d->m_LastStatus = 0; if (d->m_fileFormat == 1) { emit signalSMFWriteTempoTrack(); } for (i = 0; i < d->m_Tracks; ++i) { writeTrackChunk(i); } } /** * Reads a SMF stream. * @param stream Pointer to an existing and opened stream */ void QSmf::readFromStream(QDataStream *stream) { d->m_IOStream = stream; SMFRead(); } /** * Reads a SMF stream from a disk file. * @param fileName Name of an existing file. */ void QSmf::readFromFile(const QString& fileName) { QFile file(fileName); file.open(QIODevice::ReadOnly); QDataStream ds(&file); readFromStream(&ds); file.close(); } /** * Writes a SMF stream * @param stream Pointer to an existing and opened stream */ void QSmf::writeToStream(QDataStream *stream) { d->m_IOStream = stream; SMFWrite(); } /** * Writes a SMF stream to a disk file * @param fileName File name */ void QSmf::writeToFile(const QString& fileName) { QFile file(fileName); file.open(QIODevice::WriteOnly); QDataStream ds(&file); writeToStream(&ds); file.close(); } /** * Writes a SMF header chuck * @param format SMF Format (0/1/2) * @param ntracks Number of tracks * @param division Resolution in ticks per quarter note */ void QSmf::writeHeaderChunk(int format, int ntracks, int division) { write32bit(MThd); write32bit(6); write16bit(quint16(format)); write16bit(quint16(ntracks)); write16bit(quint16(division)); } /** * Writes a track chuck * @param track Number of the track */ void QSmf::writeTrackChunk(int track) { quint32 trkhdr; quint32 trklength; qint64 offset; qint64 place_marker; d->m_LastStatus = 0; trkhdr = MTrk; trklength = 0; offset = d->m_IOStream->device()->pos(); write32bit(trkhdr); write32bit(trklength); d->m_NumBytesWritten = 0; emit signalSMFWriteTrack(track); place_marker = d->m_IOStream->device()->pos(); d->m_IOStream->device()->seek(offset); trklength = d->m_NumBytesWritten; write32bit(trkhdr); write32bit(trklength); d->m_IOStream->device()->seek(place_marker); } /** * Writes a variable length Meta Event * @param deltaTime Time offset in ticks * @param type Meta event type * @param data Message data */ void QSmf::writeMetaEvent(long deltaTime, int type, const QByteArray& data) { writeVarLen(deltaTime); d->m_LastStatus = meta_event; putByte(d->m_LastStatus); putByte(type); writeVarLen(data.size()); foreach(char byte, data) putByte(byte); } /** * Writes a Text Meta Event * @param deltaTime Time offset in ticks * @param type Meta event type * @param data Message text */ void QSmf::writeMetaEvent(long deltaTime, int type, const QString& data) { writeVarLen(deltaTime); putByte(d->m_LastStatus = meta_event); putByte(type); QByteArray lcldata; if (d->m_codec == nullptr) lcldata = data.toLatin1(); else lcldata = d->m_codec->fromUnicode(data); writeVarLen(lcldata.length()); foreach(char byte, lcldata) putByte(byte); } /** * Writes a simple Meta event * @param deltaTime Time offset in ticks * @param type Meta event type * @param data Meta event data * @since 0.2.0 */ void QSmf::writeMetaEvent(long deltaTime, int type, int data) { writeVarLen(deltaTime); putByte(d->m_LastStatus = meta_event); putByte(type); putByte(1); putByte(data); } /** * Writes a simple Meta event * @param deltaTime Time offset in ticks * @param type Meta event type */ void QSmf::writeMetaEvent(long deltaTime, int type) { writeVarLen(deltaTime); putByte(d->m_LastStatus = meta_event); putByte(type); putByte(0); } /** * Writes a variable length MIDI message * @param deltaTime Time offset in ticks * @param type MIDI event type * @param chan MIDI Channel * @param data Message data */ void QSmf::writeMidiEvent(long deltaTime, int type, int chan, const QByteArray& data) { int i, j, size; quint8 c; writeVarLen(deltaTime); if ((type == system_exclusive) || (type == end_of_sysex)) { c = type; d->m_LastStatus = 0; } else { if (chan > 15) { SMFError("error: MIDI channel greater than 16"); } c = type | chan; } if (d->m_LastStatus != c) { d->m_LastStatus = c; putByte(c); } if (type == system_exclusive || type == end_of_sysex) { size = data.size(); if (data[0] == type) --size; writeVarLen(size); } j = (data[0] == type ? 1 : 0); for (i = j; i < data.size(); ++i) { putByte(data[i]); } } /** * Writes a MIDI message with a single parameter * @param deltaTime Time offset in ticks * @param type MIDI event type * @param chan MIDI Channel * @param b1 Message parameter */ void QSmf::writeMidiEvent(long deltaTime, int type, int chan, int b1) { quint8 c; writeVarLen(deltaTime); if ((type == system_exclusive) || (type == end_of_sysex)) { SMFError("error: Wrong method for a system exclusive event"); } if (chan > 15) { SMFError("error: MIDI channel greater than 16"); } c = type | chan; if (d->m_LastStatus != c) { d->m_LastStatus = c; putByte(c); } putByte(b1); } /** * Writes a MIDI message with two parameters * @param deltaTime Time offset in ticks * @param type MIDI event type * @param chan MIDI Channel * @param b1 Message parameter 1 * @param b2 Message parameter 2 */ void QSmf::writeMidiEvent(long deltaTime, int type, int chan, int b1, int b2) { quint8 c; writeVarLen(deltaTime); if ((type == system_exclusive) || (type == end_of_sysex)) { SMFError("error: Wrong method for a system exclusive event"); } if (chan > 15) { SMFError("error: MIDI channel greater than 16"); } c = type | chan; if (d->m_LastStatus != c) { d->m_LastStatus = c; putByte(c); } putByte(b1); putByte(b2); } /** * Writes a variable length MIDI message * @param deltaTime Time offset in ticks * @param type MIDI event type * @param len Message length * @param data Message data */ void QSmf::writeMidiEvent(long deltaTime, int type, long len, char* data) { unsigned int i, j, size; quint8 c; writeVarLen(quint64(deltaTime)); if ((type != system_exclusive) && (type != end_of_sysex)) { SMFError("error: type should be system exclusive"); } d->m_LastStatus = 0; c = quint8(type); putByte(c); size = unsigned(len); c = quint8(data[0]); if (c == type) --size; writeVarLen(size); j = (c == type ? 1 : 0); for (i = j; i < unsigned(len); ++i) { putByte(quint8(data[i])); } } /** * Writes a MIDI Sequence number * @param deltaTime Time offset in ticks * @param seqnum Sequence number */ void QSmf::writeSequenceNumber(long deltaTime, int seqnum) { writeVarLen(deltaTime); d->m_LastStatus = meta_event; putByte(d->m_LastStatus); putByte(sequence_number); putByte(2); putByte((seqnum >> 8) & 0xff); putByte(seqnum & 0xff); } /** * Writes a Tempo change message * @param deltaTime Time offset in ticks * @param tempo Tempo in microseconds per quarter note */ void QSmf::writeTempo(long deltaTime, long tempo) { writeVarLen(deltaTime); putByte(d->m_LastStatus = meta_event); putByte(set_tempo); putByte(3); putByte((tempo >> 16) & 0xff); putByte((tempo >> 8) & 0xff); putByte(tempo & 0xff); } /** * Writes a Tempo change message * @param deltaTime Time offset in ticks * @param tempo Tempo expressed in quarter notes per minute */ void QSmf::writeBpmTempo(long deltaTime, int tempo) { long us_tempo = 60000000l / tempo; writeTempo(deltaTime, us_tempo); } /** * Writes a Time Signature message * @param deltaTime Time offset in ticks * @param num Numerator * @param den Denominator (exponent for a power of two) * @param cc Number of MIDI clocks in a metronome click * @param bb Number of notated 32nd notes in 24 MIDI clocks */ void QSmf::writeTimeSignature(long deltaTime, int num, int den, int cc, int bb) { writeVarLen(deltaTime); putByte(d->m_LastStatus = meta_event); putByte(time_signature); putByte(4); putByte(num & 0xff); putByte(den & 0xff); putByte(cc & 0xff); putByte(bb & 0xff); } /** * Writes a key Signature message * @param deltaTime Time offset in ticks * @param tone Number of alterations (positive=sharps, negative=flats) * @param mode Scale mode (0=major, 1=minor) */ void QSmf::writeKeySignature(long deltaTime, int tone, int mode) { writeVarLen(quint64(deltaTime)); putByte(d->m_LastStatus = meta_event); putByte(key_signature); putByte(2); putByte(quint8(tone)); putByte(mode & 0x01); } /** * Writes multi-length bytes * @param value Integer value */ void QSmf::writeVarLen(quint64 value) { quint64 buffer; buffer = value & 0x7f; while ((value >>= 7) > 0) { buffer <<= 8; buffer |= 0x80; buffer += (value & 0x7f); } while (true) { putByte(buffer & 0xff); if (buffer & 0x80) buffer >>= 8; else break; } } /* These routines are used to make sure that the byte order of the various data types remains constant between machines. */ void QSmf::write32bit(quint32 data) { putByte((data >> 24) & 0xff); putByte((data >> 16) & 0xff); putByte((data >> 8) & 0xff); putByte(data & 0xff); } void QSmf::write16bit(quint16 data) { putByte((data >> 8) & 0xff); putByte(data & 0xff); } quint16 QSmf::to16bit(quint8 c1, quint8 c2) { quint16 value; value = quint16(c1 << 8); value += c2; return value; } quint32 QSmf::to32bit(quint8 c1, quint8 c2, quint8 c3, quint8 c4) { quint32 value; value = unsigned(c1 << 24); value += unsigned(c2 << 16); value += unsigned(c3 << 8); value += c4; return value; } quint16 QSmf::read16bit() { quint8 c1, c2; c1 = getByte(); c2 = getByte(); return to16bit(c1, c2); } quint32 QSmf::read32bit() { quint8 c1, c2, c3, c4; c1 = getByte(); c2 = getByte(); c3 = getByte(); c4 = getByte(); return to32bit(c1, c2, c3, c4); } long QSmf::readVarLen() { quint64 value; quint8 c; c = getByte(); value = c; if ((c & 0x80) != 0) { value &= 0x7f; do { c = getByte(); value = (value << 7) + (c & 0x7f); } while ((c & 0x80) != 0); } return long(value); } void QSmf::readExpected(const QString& s) { int j; quint8 b; for (j = 0; j < s.length(); ++j) { b = getByte(); if (QChar(b) != s[j]) { SMFError(QString("Invalid (%1) SMF format at %2").arg(b, 0, 16).arg(d->m_IOStream->device()->pos())); break; } } } quint64 QSmf::findTempo() { quint64 result, old_tempo, new_tempo; QSmfRecTempo rec = d->m_TempoList.last(); old_tempo = d->m_CurrTempo; new_tempo = d->m_CurrTempo; QList::Iterator it; for( it = d->m_TempoList.begin(); it != d->m_TempoList.end(); ++it ) { rec = (*it); if (rec.time <= d->m_CurrTime) { old_tempo = rec.tempo; } new_tempo = rec.tempo; if (rec.time > d->m_RevisedTime) { break; } } if ((rec.time <= d->m_RevisedTime) || (rec.time > d->m_CurrTime)) { d->m_RevisedTime = d->m_CurrTime; result = old_tempo; } else { d->m_RevisedTime = rec.time; d->m_TempoChangeTime = d->m_RevisedTime; result = new_tempo; } return result; } /* This routine converts delta times in ticks into seconds. The else statement is needed because the formula is different for tracks based on notes and tracks based on SMPTE times. */ double QSmf::ticksToSecs(quint64 ticks, quint16 division, quint64 tempo) { double result; double smpte_format; double smpte_resolution; if (division > 0) { result = double(ticks * tempo)/(division * 1000000.0); } else { smpte_format = upperByte(division); smpte_resolution = lowerByte(division); result = double(ticks)/(smpte_format * smpte_resolution * 1000000.0); } return result; } void QSmf::SMFError(const QString& s) { emit signalSMFError(s); } void QSmf::channelMessage(quint8 status, quint8 c1, quint8 c2) { quint8 chan; int k; chan = status & midi_channel_mask; if (c1 > 127) { SMFError(QString("ChannelMessage with bad c1 = %1").arg(c1)); //c1 &= 127; } if (c2 > 127) { SMFError(QString("ChannelMessage with bad c2 = %1").arg(c2)); //c2 &= 127; } switch (status & midi_command_mask) { case note_off: emit signalSMFNoteOff(chan, c1, c2); break; case note_on: emit signalSMFNoteOn(chan, c1, c2); break; case poly_aftertouch: emit signalSMFKeyPress(chan, c1, c2); break; case control_change: emit signalSMFCtlChange(chan, c1, c2); break; case program_chng: emit signalSMFProgram(chan, c1); break; case channel_aftertouch: emit signalSMFChanPress(chan, c1); break; case pitch_wheel: k = c1 + (c2 << 7) - 8192; emit signalSMFPitchBend(chan, k); break; default: SMFError(QString("Invalid MIDI status %1. Unhandled event").arg(status)); break; } } void QSmf::metaEvent(quint8 b) { QSmfRecTempo rec; QByteArray m(d->m_MsgBuff); switch (b) { case sequence_number: emit signalSMFSequenceNum(to16bit(m[0], m[1])); break; case text_event: case copyright_notice: case sequence_name: case instrument_name: case lyric: case marker: case cue_point: { QString s; if (d->m_codec == nullptr) s = QString(m); else s = d->m_codec->toUnicode(m); emit signalSMFText(b, s); } break; case forced_channel: emit signalSMFforcedChannel(m[0]); break; case forced_port: emit signalSMFforcedPort(m[0]); break; case end_of_track: emit signalSMFendOfTrack(); break; case set_tempo: d->m_CurrTempo = to32bit(0, m[0], m[1], m[2]); emit signalSMFTempo(d->m_CurrTempo); rec = d->m_TempoList.last(); if (rec.tempo == d->m_CurrTempo) { return; } if (rec.time > d->m_CurrTime) { return; } addTempo(d->m_CurrTempo, d->m_CurrTime); break; case smpte_offset: emit signalSMFSmpte(m[0], m[1], m[2], m[3], m[4]); break; case time_signature: emit signalSMFTimeSig(m[0], m[1], m[2], m[3]); break; case key_signature: emit signalSMFKeySig(m[0], m[1]); break; case sequencer_specific: emit signalSMFSeqSpecific(m); break; default: emit signalSMFMetaUnregistered(b, m); break; } emit signalSMFMetaMisc(b, m); } void QSmf::sysEx() { QByteArray varr(d->m_MsgBuff); emit signalSMFSysex(varr); } void QSmf::badByte(quint8 b, int p) { SMFError(QString("Unexpected byte (%1) at %2").arg(b, 2, 16).arg(p)); } quint8 QSmf::lowerByte(quint16 x) { return (x & 0xff); } quint8 QSmf::upperByte(quint16 x) { return ((x >> 8) & 0xff); } void QSmf::msgInit() { d->m_MsgBuff.truncate(0); } void QSmf::msgAdd(quint8 b) { int s = d->m_MsgBuff.size(); d->m_MsgBuff.resize(s + 1); d->m_MsgBuff[s] = b; } /* public properties (accessors) */ /** * Gets the current time in ticks * @return Time in ticks */ long QSmf::getCurrentTime() { return d->m_CurrTime; } /** * Gets the current tempo * @return Tempo in us per quarter */ long QSmf::getCurrentTempo() { return d->m_CurrTempo; } /** * Gets the real time in seconds * @return Time in seconds */ long QSmf::getRealTime() { return d->m_RealTime; } /** * Gets the resolution * @return Resolution in ticks per quarter note */ int QSmf::getDivision() { return d->m_Division; } /** * Sets the resolution * @param division Resolution in ticks per quarter note */ void QSmf::setDivision(int division) { d->m_Division = division; } /** * Gets the number of tracks * @return Number of tracks */ int QSmf::getTracks() { return d->m_Tracks; } /** * Sets the number of tracks * @param tracks Number of tracks */ void QSmf::setTracks(int tracks) { d->m_Tracks = tracks; } /** * Gets the SMF file format * @return File format (0, 1, or 2) */ int QSmf::getFileFormat() { return d->m_fileFormat; } /** * Sets the SMF file format * @param fileFormat File format (0, 1, or 2) */ void QSmf::setFileFormat(int fileFormat) { d->m_fileFormat = fileFormat; } /** * Gets the position in the SMF stream * @return Position offset in the stream */ long QSmf::getFilePos() { return long(d->m_IOStream->device()->pos()); } /** * Gets the text codec used for text meta-events I/O * @return QTextCodec pointer * @since 0.2.0 */ QTextCodec* QSmf::getTextCodec() { return d->m_codec; } /** * Sets the text codec for text meta-events. * The engine doesn't take ownership of the codec instance. * * @param codec QTextCodec pointer * @since 0.2.0 */ void QSmf::setTextCodec(QTextCodec *codec) { d->m_codec = codec; } } drumstick-1.1.3/library/PaxHeaders.32572/Info.plist.lib0000644000000000000000000000013213532747316017454 xustar0030 mtime=1567346382.693999845 30 atime=1567346383.002000241 30 ctime=1567346382.693999845 drumstick-1.1.3/library/Info.plist.lib0000644000175000001440000000153313532747316020247 0ustar00pedrousers00000000000000 CFBundlePackageType FMWK CFBundleShortVersionString @FULL_VERSION@ CFBundleVersion @FULL_VERSION@ CFBundleGetInfoString Created by Qt/QMake CFBundleSignature @TYPEINFO@ CFBundleExecutable @LIBRARY@ CFBundleIdentifier @BUNDLEIDENTIFIER@ NSHumanReadableCopyright © 2006-2018, Pedro López-Cabanillas and others NOTE Please, do NOT change this file -- It was generated by Qt/QMake. drumstick-1.1.3/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316016033 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/CMakeLists.txt0000644000175000001440000001421013532747316016622 0ustar00pedrousers00000000000000# MIDI C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . cmake_minimum_required(VERSION 3.2 FATAL_ERROR) set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version") project(DRUMSTICK) set(CMAKE_COLOR_MAKEFILE ON) #set(CMAKE_VERBOSE_MAKEFILE ON) #set(CMAKE_CXX_VISIBILITY_PRESET hidden) #set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) set(CMAKE_INCLUDE_CURRENT_DIR TRUE) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib) # Additional CMake modules for 3rd party library checks reside here set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake_admin") set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) if(APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif() include(GNUInstallDirs) # DRUMSTICK version string set(VERSION_MAJOR "1") set(VERSION_MINOR "1") set(VERSION_PATCH "3") set(VERSION_SUFFIX "") set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}${VERSION_SUFFIX}) add_definitions(-DVERSION=${VERSION}) message(STATUS "drumstick ${VERSION} prefix ${CMAKE_INSTALL_PREFIX}") set(_DBUS_INIT OFF) # User options option(STATIC_DRUMSTICK "Build static libraries instead of dynamic" OFF) option(USE_DBUS "Include DBus support (required for RealtimeKit)" ${_DBUS_INIT}) message(STATUS "Build configuration: ${CMAKE_BUILD_TYPE}") if(STATIC_DRUMSTICK) set(BUILD_SHARED_LIBS OFF) add_definitions(-DDRUMSTICK_STATIC) message(STATUS "Building static libraries") else() set(BUILD_SHARED_LIBS ON) message(STATUS "Building dynamic libraries") endif() find_package(Qt5Core REQUIRED) message(STATUS "Found Qt5 version = ${Qt5Core_VERSION_STRING}") if(USE_DBUS) find_package(Qt5DBus REQUIRED) add_definitions(-DRTKIT_SUPPORT) endif() if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows") find_package(PkgConfig REQUIRED) if(PKG_CONFIG_FOUND) message(STATUS "Program pkg-config found (${PKG_CONFIG_EXECUTABLE})") else() message(FATAL_ERROR "Program pkg-config not found") endif() endif() if(${CMAKE_SYSTEM} MATCHES "Linux") pkg_check_modules(ALSA alsa>=1.0.0) if(ALSA_FOUND) set(ALSA_LIBS ${ALSA_LIBRARIES}) list(APPEND ALSA_LIB_DIR ${ALSA_LIBRARY_DIRS} ${ALSA_LIBDIR}) list(APPEND ALSA_INC_DIR ${ALSA_INCLUDE_DIRS} ${ALSA_INCLUDEDIR}) else() message(STATUS "Warning: ALSA library not found.") endif() endif() if(PKG_CONFIG_FOUND) pkg_check_modules(PULSE libpulse-simple) if(NOT PULSE_FOUND) message(STATUS "Warning: PulseAudio library not found.") endif() endif() if(${CMAKE_SYSTEM} MATCHES "Darwin") find_package(Qt5Concurrent REQUIRED) endif() link_directories(${DRUMSTICK_BINARY_DIR}/lib) add_subdirectory(library) add_subdirectory(utils) add_subdirectory(icons) include(CTest) if(BUILD_TESTING) add_subdirectory(tests) endif() if(${CMAKE_SYSTEM} MATCHES "Linux") find_package(Doxygen) if(DOXYGEN_FOUND) configure_file( "${CMAKE_SOURCE_DIR}/Doxyfile.in" "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile" IMMEDIATE @ONLY) add_custom_target(doxygen ${DOXYGEN} Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) endif() add_subdirectory(doc) configure_file(drumstick-alsa.pc.in drumstick-alsa.pc IMMEDIATE @ONLY) configure_file(drumstick.spec.in drumstick.spec IMMEDIATE @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/drumstick-alsa.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) # XML mime types set( SHARED_MIME_INFO_MINIMUM_VERSION "0.30" ) set( XDG_MIME_INSTALL_DIR "${CMAKE_INSTALL_DATAROOTDIR}/mime/packages" ) find_package( SharedMimeInfo ) if( SHARED_MIME_INFO_FOUND ) install( FILES drumstick.xml DESTINATION ${XDG_MIME_INSTALL_DIR} ) update_xdg_mimetypes( ${XDG_MIME_INSTALL_DIR} ) endif() endif() configure_file(drumstick-file.pc.in drumstick-file.pc IMMEDIATE @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/drumstick-file.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) configure_file(drumstick-rt.pc.in drumstick-rt.pc IMMEDIATE @ONLY) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/drumstick-rt.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) # uninstall custom target configure_file( "${CMAKE_SOURCE_DIR}/cmake_admin/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target( uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") if(UNIX) # tarball target add_custom_target( tarball COMMAND mkdir -p drumstick-${VERSION} COMMAND cp -r cmake_admin drumstick-${VERSION} COMMAND cp -r library drumstick-${VERSION} COMMAND cp -r utils drumstick-${VERSION} COMMAND cp -r doc drumstick-${VERSION} COMMAND cp -r icons drumstick-${VERSION} COMMAND cp -r tests drumstick-${VERSION} COMMAND cp CMakeLists.txt AUTHORS COPYING ChangeLog INSTALL NEWS README TODO drumstick*.in drumstick.pro drumstick.xml configure* Doxyfile.in chkcoverage global.pri drumstick-${VERSION} COMMAND tar -cj --exclude=.[a-z]* -f drumstick-${VERSION}.tar.bz2 drumstick-${VERSION} COMMAND tar -cz --exclude=.[a-z]* -f drumstick-${VERSION}.tar.gz drumstick-${VERSION} COMMAND zip -qr drumstick-${VERSION}.zip drumstick-${VERSION} -x '.[a-z]*' COMMAND rm -rf drumstick-${VERSION} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) endif() drumstick-1.1.3/PaxHeaders.32572/drumstick-alsa.pc.in0000644000000000000000000000013213532747316017147 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.002000241 30 ctime=1567346382.729999891 drumstick-1.1.3/drumstick-alsa.pc.in0000644000175000001440000000050713532747316017742 0ustar00pedrousers00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=${prefix}/lib@LIB_SUFFIX@ includedir=${prefix}/include Name: drumstick-alsa Version: @VERSION@ Description: MIDI Sequencer C++ Library Bindings for ALSA and Qt5 URL: http://sourceforge.net/projects/drumstick Libs: -L${libdir} -ldrumstick-alsa Cflags: -I${includedir} drumstick-1.1.3/PaxHeaders.32572/README0000644000000000000000000000013213532747316014153 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.002000241 30 ctime=1567346382.729999891 drumstick-1.1.3/README0000644000175000001440000000001313532747316014736 0ustar00pedrousers00000000000000See INSTALLdrumstick-1.1.3/PaxHeaders.32572/configure0000644000000000000000000000013213532747316015177 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.002000241 30 ctime=1567346382.729999891 drumstick-1.1.3/configure0000755000175000001440000000040013532747316015765 0ustar00pedrousers00000000000000#!/bin/bash # a typical configuration for production usage... mkdir -p build cd build cmake .. -DCMAKE_CXX_FLAGS="-W -Wall" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/usr/local \ -DSTATIC_DRUMSTICK=NO \ -DUSE_DBUS=YES \ -DENABLE_PCH=NO $* drumstick-1.1.3/PaxHeaders.32572/tests0000644000000000000000000000013213532747316014360 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/0000755000175000001440000000000013532747316015226 5ustar00pedrousers00000000000000drumstick-1.1.3/tests/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316017175 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/CMakeLists.txt0000644000175000001440000000167413532747316017776 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . find_package(Qt5Test REQUIRED) set (CMAKE_AUTOMOC ON) enable_testing() if (ALSA_FOUND) add_subdirectory(alsaTest1) add_subdirectory(alsaTest2) endif() add_subdirectory(fileTest) add_subdirectory(rtTest) drumstick-1.1.3/tests/PaxHeaders.32572/tests.pro0000644000000000000000000000013213532747316016321 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/tests.pro0000644000175000001440000000021013532747316017103 0ustar00pedrousers00000000000000TEMPLATE = subdirs CONFIG += ordered linux* { SUBDIRS += alsaTest1 SUBDIRS += alsaTest2 } SUBDIRS += fileTest SUBDIRS += rtTest drumstick-1.1.3/tests/PaxHeaders.32572/fileTest0000644000000000000000000000013213532747316016137 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/fileTest/0000755000175000001440000000000013532747316017005 5ustar00pedrousers00000000000000drumstick-1.1.3/tests/fileTest/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316020754 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/fileTest/CMakeLists.txt0000644000175000001440000000163413532747316021551 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . add_executable (fileTest filetest.cpp) target_link_libraries (fileTest drumstick-file Qt5::Core Qt5::Test ) add_test (fileTest ${PROJECT_BINARY_DIR}/bin/fileTest) drumstick-1.1.3/tests/fileTest/PaxHeaders.32572/fileTest.pro0000644000000000000000000000013213532747316020515 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/fileTest/fileTest.pro0000644000175000001440000000075113532747316021311 0ustar00pedrousers00000000000000QT += testlib QT -= gui TARGET = fileTest CONFIG += console CONFIG -= app_bundle TEMPLATE = app include (../../global.pri) SOURCES += filetest.cpp DEFINES += SRCDIR=\\\"$$PWD/\\\" INCLUDEPATH += . ../../library/include DESTDIR = ../../build/bin macx:!static { QMAKE_LFLAGS += -F$$OUT_PWD/../../build/lib -L$$OUT_PWD/../../build/lib LIBS += -framework drumstick-file } else { LIBS += -L$$OUT_PWD/../../build/lib \ -l$$drumstickLib(drumstick-file) } drumstick-1.1.3/tests/fileTest/PaxHeaders.32572/filetest.cpp0000644000000000000000000000013213532747316020537 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/fileTest/filetest.cpp0000644000175000001440000002126213532747316021333 0ustar00pedrousers00000000000000#include #include #include #include #include const unsigned char test_mid[] = { 0x4d, 0x54, 0x68, 0x64, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x78, 0x4d, 0x54, 0x72, 0x6b, 0x00, 0x00, 0x00, 0x99, 0x00, 0xff, 0x02, 0x2f, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x43, 0x29, 0x20, 0x32, 0x30, 0x30, 0x36, 0x2d, 0x32, 0x30, 0x31, 0x39, 0x20, 0x50, 0x65, 0x64, 0x72, 0x6f, 0x20, 0x4c, 0xc3, 0xb3, 0x70, 0x65, 0x7a, 0x2d, 0x43, 0x61, 0x62, 0x61, 0x6e, 0x69, 0x6c, 0x6c, 0x61, 0x73, 0x00, 0xff, 0x51, 0x03, 0x09, 0x27, 0xc0, 0x00, 0xff, 0x58, 0x04, 0x03, 0x02, 0x24, 0x08, 0x00, 0xff, 0x59, 0x02, 0x02, 0x00, 0x00, 0xf0, 0x0a, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7f, 0x00, 0x41, 0xf7, 0x00, 0x90, 0x3c, 0x78, 0x3c, 0x80, 0x3c, 0x00, 0x00, 0x90, 0x3e, 0x78, 0x3c, 0x80, 0x3e, 0x00, 0x00, 0x90, 0x40, 0x78, 0x3c, 0x80, 0x40, 0x00, 0x00, 0x90, 0x41, 0x78, 0x3c, 0x80, 0x41, 0x00, 0x00, 0x90, 0x43, 0x78, 0x3c, 0x80, 0x43, 0x00, 0x00, 0x90, 0x45, 0x78, 0x3c, 0x80, 0x45, 0x00, 0x00, 0x90, 0x47, 0x78, 0x3c, 0x80, 0x47, 0x00, 0x00, 0x90, 0x48, 0x78, 0x3c, 0x80, 0x48, 0x00, 0x00, 0xff, 0x2f, 0x00 }; const int test_mid_len = 175; const int FORMAT( 0 ); const int TRACKS( 1 ); const int DIVISION( 120 ); const int TEMPO( 100 ); const QString COPYRIGHT( "Copyright (C) 2006-2019 Pedro López-Cabanillas" ); const QByteArray GSRESET( "f04110421240007f0041f7" ); const QList NOTES({ 60, 62, 64, 65, 67, 69, 71, 72 }); using namespace drumstick; class FileTest : public QObject { Q_OBJECT public: FileTest(); public Q_SLOTS: void errorHandler(const QString& errorStr); void trackHandler(int track); void headerEvent(int format, int ntrks, int division); void trackStartEvent(); void trackEndEvent(); void endOfTrackEvent(); void noteOnEvent(int chan, int pitch, int vol); void noteOffEvent(int chan, int pitch, int vol); void keyPressEvent(int chan, int pitch, int press); void ctlChangeEvent(int chan, int ctl, int value); void pitchBendEvent(int chan, int value); void programEvent(int chan, int patch); void chanPressEvent(int chan, int press); void sysexEvent(const QByteArray& data); void textEvent(int typ, const QString& data); void timeSigEvent(int b0, int b1, int b2, int b3); void keySigEvent(int b0, int b1); void tempoEvent(int tempo); private Q_SLOTS: void testCaseWriteSmf(); void testCaseReadSmf(); private: QSmf *m_engine; QDataStream *m_stream; int m_numNoteOn; int m_lastNoteOn; int m_numNoteOff; int m_lastNoteOff; int m_lastKeyPress; int m_currentTrack; int m_endOfTrack; int m_lastCtl; int m_lastProgram; int m_lastChanPress; int m_lastPitchBend; int m_lastTempo; QByteArray m_data; QByteArray m_expected; QByteArray m_lastSysex; QString m_lastError; QString m_header; QString m_trackEnd; QString m_lastTextEvent; QString m_lastTimeSig; QString m_lastKeySig; }; FileTest::FileTest(): m_engine(nullptr), m_stream(nullptr), m_numNoteOn(0), m_lastNoteOn(0), m_numNoteOff(0), m_lastNoteOff(0), m_lastKeyPress(0), m_currentTrack(0), m_endOfTrack(0), m_lastCtl(0), m_lastProgram(0), m_lastChanPress(0), m_lastPitchBend(0), m_lastTempo(0) { m_engine = new QSmf(this); m_engine->setTextCodec(QTextCodec::codecForName("UTF-8")); m_stream = new QDataStream(&m_data, QIODevice::ReadWrite); m_expected = QByteArray::fromRawData(reinterpret_cast(test_mid), test_mid_len); connect(m_engine, SIGNAL(signalSMFError(const QString&)), this, SLOT(errorHandler(const QString&))); connect(m_engine, SIGNAL(signalSMFWriteTrack(int)), this, SLOT(trackHandler(int))); connect(m_engine, SIGNAL(signalSMFHeader(int,int,int)), this, SLOT(headerEvent(int,int,int))); connect(m_engine, SIGNAL(signalSMFTrackStart()), this, SLOT(trackStartEvent())); connect(m_engine, SIGNAL(signalSMFTrackEnd()), this, SLOT(trackEndEvent())); connect(m_engine, SIGNAL(signalSMFNoteOn(int,int,int)), this, SLOT(noteOnEvent(int,int,int))); connect(m_engine, SIGNAL(signalSMFNoteOff(int,int,int)), this, SLOT(noteOffEvent(int,int,int))); connect(m_engine, SIGNAL(signalSMFKeyPress(int,int,int)), this, SLOT(keyPressEvent(int,int,int))); connect(m_engine, SIGNAL(signalSMFCtlChange(int,int,int)), this, SLOT(ctlChangeEvent(int,int,int))); connect(m_engine, SIGNAL(signalSMFPitchBend(int,int)), this, SLOT(pitchBendEvent(int,int))); connect(m_engine, SIGNAL(signalSMFProgram(int,int)), this, SLOT(programEvent(int,int))); connect(m_engine, SIGNAL(signalSMFChanPress(int,int)), this, SLOT(chanPressEvent(int,int))); connect(m_engine, SIGNAL(signalSMFSysex(const QByteArray&)), this, SLOT(sysexEvent(const QByteArray&))); connect(m_engine, SIGNAL(signalSMFText(int,const QString&)), this, SLOT(textEvent(int,const QString&))); connect(m_engine, SIGNAL(signalSMFendOfTrack()), this, SLOT(endOfTrackEvent())); connect(m_engine, SIGNAL(signalSMFTimeSig(int,int,int,int)), this, SLOT(timeSigEvent(int,int,int,int))); connect(m_engine, SIGNAL(signalSMFKeySig(int,int)), this, SLOT(keySigEvent(int,int))); connect(m_engine, SIGNAL(signalSMFTempo(int)), this, SLOT(tempoEvent(int))); } void FileTest::errorHandler(const QString& errorStr) { m_lastError = errorStr; qWarning() << errorStr; } void FileTest::trackHandler(int ) { int i; // Text event m_engine->writeMetaEvent(0, copyright_notice, COPYRIGHT); m_engine->writeBpmTempo(0, TEMPO); m_engine->writeTimeSignature(0, 3, 2, 36, 8); // ts = 3/4 m_engine->writeKeySignature(0, 2, major_mode); // D major (2 sharps) // system exclusive event QByteArray gsreset = QByteArray::fromHex( GSRESET ); m_engine->writeMidiEvent(0, system_exclusive, long(gsreset.size()), gsreset.data()); // some note events for(i = 0; i < NOTES.length(); ++i) { m_engine->writeMidiEvent(0, note_on, 0, NOTES[i], 120); m_engine->writeMidiEvent(60, note_off, 0, NOTES[i], 0); } // final event m_engine->writeMetaEvent(0, end_of_track); } void FileTest::headerEvent(int format, int ntrks, int division) { m_header = QString("Format=%1, Tracks=%2, Division=%3") .arg(format).arg(ntrks).arg(division); } void FileTest::trackStartEvent() { m_currentTrack++; } void FileTest::trackEndEvent() { m_trackEnd = QString("End: %1").arg(m_currentTrack); } void FileTest::endOfTrackEvent() { m_endOfTrack++; } void FileTest::noteOnEvent(int , int pitch, int ) { m_numNoteOn++; m_lastNoteOn = pitch; } void FileTest::noteOffEvent(int , int pitch, int ) { m_numNoteOff++; m_lastNoteOff = pitch; } void FileTest::keyPressEvent(int , int pitch, int ) { m_lastKeyPress = pitch; } void FileTest::ctlChangeEvent(int , int ctl, int ) { m_lastCtl = ctl; } void FileTest::pitchBendEvent(int , int value) { m_lastPitchBend = value; } void FileTest::programEvent(int , int patch) { m_lastProgram = patch; } void FileTest::chanPressEvent(int , int press) { m_lastChanPress = press; } void FileTest::sysexEvent(const QByteArray& data) { m_lastSysex = data; } void FileTest::textEvent(int , const QString& data) { m_lastTextEvent = data; } void FileTest::timeSigEvent(int b0, int b1, int b2, int b3) { m_lastTimeSig = QString("%1, %2, %3, %4").arg(b0).arg(b1).arg(b2).arg(b3); } void FileTest::keySigEvent(int b0, int b1) { m_lastKeySig = QString("%1, %2").arg(b0).arg(b1); } void FileTest::tempoEvent(int tempo) { m_lastTempo = static_cast( 6e7 / tempo ); } void FileTest::testCaseWriteSmf() { m_data.clear(); m_engine->setDivision(DIVISION); m_engine->setFileFormat(FORMAT); m_engine->setTracks(TRACKS); m_engine->writeToStream(m_stream); if (!m_lastError.isEmpty()) { QFAIL(m_lastError.toLocal8Bit()); } QCOMPARE(m_data, m_expected); } void FileTest::testCaseReadSmf() { m_stream->device()->reset(); m_engine->readFromStream(m_stream); if (!m_lastError.isEmpty()) { QFAIL(m_lastError.toLocal8Bit()); } QCOMPARE(m_engine->getFileFormat(), FORMAT); QCOMPARE(m_engine->getDivision(), DIVISION); QCOMPARE(m_engine->getTracks(), TRACKS); QCOMPARE(m_lastTempo, TEMPO); QCOMPARE(m_lastTextEvent, COPYRIGHT); QCOMPARE(m_lastSysex, QByteArray::fromHex(GSRESET)); QCOMPARE(m_numNoteOn, NOTES.length()); QCOMPARE(m_numNoteOff, NOTES.length()); QCOMPARE(m_lastNoteOn, NOTES.last()); QCOMPARE(m_lastNoteOff, NOTES.last()); QCOMPARE(m_currentTrack, TRACKS); QCOMPARE(m_endOfTrack, TRACKS); } QTEST_APPLESS_MAIN(FileTest) #include "filetest.moc" drumstick-1.1.3/tests/PaxHeaders.32572/alsaTest20000644000000000000000000000013213532747316016222 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/alsaTest2/0000755000175000001440000000000013532747316017070 5ustar00pedrousers00000000000000drumstick-1.1.3/tests/alsaTest2/PaxHeaders.32572/alsaTest2.pro0000644000000000000000000000013213532747316020663 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/alsaTest2/alsaTest2.pro0000644000175000001440000000044513532747316021457 0ustar00pedrousers00000000000000QT += testlib QT -= gui TARGET = alsaTest2 CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += \ alsatest2.cpp DEFINES += SRCDIR=\\\"$$PWD/\\\" INCLUDEPATH += . ../../library/include LIBS = -L../../build/lib -ldrumstick-alsa -lasound DESTDIR = ../../build/bin drumstick-1.1.3/tests/alsaTest2/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316021037 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/alsaTest2/CMakeLists.txt0000644000175000001440000000163413532747316021634 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . add_executable (alsaTest2 alsatest2.cpp) target_link_libraries (alsaTest2 drumstick-alsa Qt5::Core Qt5::Test ) add_test (alsaTest2 ${PROJECT_BINARY_DIR}/bin/alsaTest2)drumstick-1.1.3/tests/alsaTest2/PaxHeaders.32572/alsatest2.cpp0000644000000000000000000000013213532747316020705 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/alsaTest2/alsatest2.cpp0000644000175000001440000000510113532747316021473 0ustar00pedrousers00000000000000#include #include #include using namespace drumstick; class AlsaTest2 : public QObject, public TimerEventHandler { Q_OBJECT public: AlsaTest2(); // TimerEventHandler implementation void handleTimerEvent(int ticks, int msecs); private Q_SLOTS: void testTimer(); void initTestCase(); void cleanupTestCase(); private: QPointer m_test_timer; int m_count; }; AlsaTest2::AlsaTest2(): m_test_timer(0), m_count(0) { } void AlsaTest2::handleTimerEvent(int , int ) { m_count++; } void AlsaTest2::initTestCase() { try { QFileInfo check_devsnd("/dev/snd/"); QVERIFY(check_devsnd.exists() && check_devsnd.isDir()); QFileInfo check_devsndseq("/dev/snd/seq"); QVERIFY(check_devsndseq.exists() && !check_devsndseq.isFile() && !check_devsndseq.isDir()); QFileInfo check_devsndtimer("/dev/snd/timer"); QVERIFY(check_devsndtimer.exists() && !check_devsndseq.isFile() && !check_devsndseq.isDir()); m_test_timer = Timer::bestGlobalTimer( SND_TIMER_OPEN_NONBLOCK | SND_TIMER_OPEN_TREAD ); } catch (...) { QWARN("Timer test initialization failed"); } } void AlsaTest2::cleanupTestCase() { delete m_test_timer; } void AlsaTest2::testTimer() { if (m_test_timer != 0) { m_count = 0; try { TimerParams tparams; TimerInfo tinfo = m_test_timer->getTimerInfo(); tparams.setAutoStart(true); if (!tinfo.isSlave()) { /* 50 Hz */ tparams.setTicks( 1000000000L / tinfo.getResolution() / 50); if (tparams.getTicks() < 1) { tparams.setTicks(1); } } else { tparams.setTicks(1); } tparams.setFilter(1 << SND_TIMER_EVENT_TICK); m_test_timer->setTimerParams(tparams); m_test_timer->setHandler(this); // Testing timer callback method m_test_timer->start(); m_test_timer->startEvents(); QTest::qWait(1000); m_test_timer->stopEvents(); m_test_timer->stop(); QVERIFY2(qAbs(50 - m_count) <= 1, "Timer results are wrong"); TimerStatus tstatus = m_test_timer->getTimerStatus(); QCOMPARE(tstatus.getLost(), 0L); QCOMPARE(tstatus.getOverrun(), 0L); } catch (...) { QFAIL("Timer test failed"); } } } QTEST_MAIN(AlsaTest2) #include "alsatest2.moc" drumstick-1.1.3/tests/PaxHeaders.32572/rtTest0000644000000000000000000000013213532747316015645 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/rtTest/0000755000175000001440000000000013532747316016513 5ustar00pedrousers00000000000000drumstick-1.1.3/tests/rtTest/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316020462 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/rtTest/CMakeLists.txt0000644000175000001440000000161413532747316021255 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . add_executable (rtTest rttest.cpp) target_link_libraries (rtTest drumstick-rt Qt5::Core Qt5::Test ) add_test (rtTest ${PROJECT_BINARY_DIR}/bin/rtTest) drumstick-1.1.3/tests/rtTest/PaxHeaders.32572/rtTest.pro0000644000000000000000000000013213532747316017731 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/rtTest/rtTest.pro0000644000175000001440000000074013532747316020523 0ustar00pedrousers00000000000000QT += testlib QT -= gui TARGET = rtTest CONFIG += console CONFIG -= app_bundle TEMPLATE = app include (../../global.pri) SOURCES += rttest.cpp DEFINES += SRCDIR=\\\"$$PWD/\\\" INCLUDEPATH += . ../../library/include DESTDIR = ../../build/bin macx:!static { QMAKE_LFLAGS += -F$$OUT_PWD/../../build/lib -L$$OUT_PWD/../../build/lib LIBS += -framework drumstick-rt } else { LIBS += -L$$OUT_PWD/../../build/lib \ -l$$drumstickLib(drumstick-rt) } drumstick-1.1.3/tests/rtTest/PaxHeaders.32572/rttest.cpp0000644000000000000000000000013213532747316017753 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/rtTest/rttest.cpp0000644000175000001440000000454213532747316020551 0ustar00pedrousers00000000000000#include #include #include #include #include #include using namespace drumstick::rt; class RtTest : public QObject { Q_OBJECT public: RtTest(); private Q_SLOTS: void testRT(); }; RtTest::RtTest() { } void RtTest::testRT() { QSettings settings; QList inputsList; QList outputsList; BackendManager man; man.refresh(&settings); QStringList paths = man.defaultPaths(); QVERIFY2(paths.length() > 0, "Plugins path is empty"); foreach(const QString& p, paths) { qDebug() << "path:" << p; } inputsList = man.availableInputs(); QVERIFY2(inputsList.length() > 0, "There aren't input backends"); foreach(MIDIInput* input, inputsList) { qDebug() << "input:" << input->backendName(); QCOMPARE(input->backendName().isEmpty(), false ); QCOMPARE(input->publicName().isEmpty(), false ); QStringList conns = input->connections(); //foreach(const QString& c, conns) { qDebug() << " connections:" << (conns.isEmpty() ? "none" : conns.join(", ")); //} /*QVERIFY2(conns.length() > 0, "Backend without any connection"); QStringList avconns = input->connections(true); QVERIFY2(avconns.length() > 0, "Backend without any advanced connection"); QVERIFY2(avconns.length() >= conns.length(), "unexpected connections number");*/ } outputsList = man.availableOutputs(); QVERIFY2(outputsList.length() > 0, "There aren't output backends"); foreach(MIDIOutput* output, outputsList) { qDebug() << "output:" << output->backendName(); QCOMPARE(output->backendName().isEmpty(), false ); QCOMPARE(output->publicName().isEmpty(), false ); QStringList conns = output->connections(); //foreach(const QString& c, conns) { qDebug() << " connections:" << (conns.isEmpty() ? "none" : conns.join(", ")); //} /*QVERIFY2(conns.length() > 0, "Backend without any connection"); QStringList avconns = output->connections(true); QVERIFY2(avconns.length() > 0, "Backend without any advanced connection"); QVERIFY2(avconns.length() >= conns.length(), "unexpected connections number");*/ } } QTEST_MAIN(RtTest) #include "rttest.moc" drumstick-1.1.3/tests/PaxHeaders.32572/alsaTest10000644000000000000000000000013213532747316016221 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/alsaTest1/0000755000175000001440000000000013532747316017067 5ustar00pedrousers00000000000000drumstick-1.1.3/tests/alsaTest1/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316021036 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/alsaTest1/CMakeLists.txt0000644000175000001440000000163413532747316021633 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . add_executable (alsaTest1 alsatest1.cpp) target_link_libraries (alsaTest1 drumstick-alsa Qt5::Core Qt5::Test ) add_test (alsaTest1 ${PROJECT_BINARY_DIR}/bin/alsaTest1)drumstick-1.1.3/tests/alsaTest1/PaxHeaders.32572/alsatest1.cpp0000644000000000000000000000013213532747316020703 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/alsaTest1/alsatest1.cpp0000644000175000001440000000360313532747316021476 0ustar00pedrousers00000000000000#include #include #include using namespace drumstick; class AlsaTest1 : public QObject { Q_OBJECT public: AlsaTest1(); private Q_SLOTS: void testEvents(); }; AlsaTest1::AlsaTest1() { } void AlsaTest1::testEvents() { NoteEvent note(0, 60, 100, 120); QCOMPARE(note.getChannel(), 0); QCOMPARE(note.getKey(), 60); QCOMPARE(note.getVelocity(), 100); QCOMPARE(note.getDuration(), 120uL); NoteOnEvent noteOn(1, 60, 100); QCOMPARE(noteOn.getChannel(), 1); QCOMPARE(noteOn.getKey(), 60); QCOMPARE(noteOn.getVelocity(), 100); NoteOffEvent noteOff(2, 60, 0); QCOMPARE(noteOff.getChannel(), 2); QCOMPARE(noteOff.getKey(), 60); QCOMPARE(noteOff.getVelocity(), 0); ControllerEvent ctl(3, 33, 66); QCOMPARE(ctl.getChannel(), 3); QCOMPARE(ctl.getParam(), 33u); QCOMPARE(ctl.getValue(), 66); ProgramChangeEvent pgm(4, 123); QCOMPARE(pgm.getChannel(), 4); QCOMPARE(pgm.getValue(), 123); KeyPressEvent keyPress(5, 60, 124); QCOMPARE(keyPress.getChannel(), 5); QCOMPARE(keyPress.getKey(), 60); QCOMPARE(keyPress.getVelocity(), 124); ChanPressEvent chanPress(6, 111); QCOMPARE(chanPress.getChannel(), 6); QCOMPARE(chanPress.getValue(), 111); PitchBendEvent bender(7, 1234); QCOMPARE(bender.getChannel(), 7); QCOMPARE(bender.getValue(), 1234); QByteArray sysexData = QByteArray::fromHex("f04110421240007f0041f7"); SysExEvent sysexEvent(sysexData); QCOMPARE(sysexEvent.getData(), sysexData.data()); QCOMPARE(sysexEvent.getLength(), (unsigned) sysexData.length()); QString text = "This can be a copyright, song name, instrument, lyric..."; TextEvent textEvent(text, 3); QCOMPARE(textEvent.getText(), text); QCOMPARE(textEvent.getLength(), (unsigned) text.length()); } QTEST_APPLESS_MAIN(AlsaTest1) #include "alsatest1.moc" drumstick-1.1.3/tests/alsaTest1/PaxHeaders.32572/alsaTest1.pro0000644000000000000000000000013213532747316020661 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.002000241 30 ctime=1567346382.725999886 drumstick-1.1.3/tests/alsaTest1/alsaTest1.pro0000644000175000001440000000044513532747316021455 0ustar00pedrousers00000000000000QT += testlib QT -= gui TARGET = alsatest1 CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += \ alsatest1.cpp DEFINES += SRCDIR=\\\"$$PWD/\\\" INCLUDEPATH += . ../../library/include LIBS = -L../../build/lib -ldrumstick-alsa -lasound DESTDIR = ../../build/bin drumstick-1.1.3/PaxHeaders.32572/AUTHORS0000644000000000000000000000013213532747316014343 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.002000241 30 ctime=1567346382.729999891 drumstick-1.1.3/AUTHORS0000644000175000001440000000011013532747316015124 0ustar00pedrousers00000000000000Pedro Lopez-Cabanillas Rui Fan drumstick-1.1.3/PaxHeaders.32572/drumstick.spec.in0000644000000000000000000000013213532747316016561 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.006000245 30 ctime=1567346382.729999891 drumstick-1.1.3/drumstick.spec.in0000644000175000001440000001151713532747316017357 0ustar00pedrousers00000000000000# spec file for package drumstick (Version @VERSION@) # # MIDI Sequencer C++ Library Bindings for Qt5 # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This file and all modifications and additions to the pristine # package are under the same license as the package itself. # # norootforbuild Name: drumstick Version: @VERSION@ Release: 1 License: GPL v2 or later Summary: MIDI Sequencer C++ Library Bindings Group: Productivity/Multimedia/Sound/Midi URL: http://drumstick.sourceforge.net Source: %{name}-%{version}.tar.bz2 BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: cmake BuildRequires: alsa-lib-devel BuildRequires: qt5-qtbase-devel BuildRequires: qt5-qtsvg-devel BuildRequires: doxygen BuildRequires: graphviz BuildRequires: libxslt BuildRequires: docbook-utils BuildRequires: docbook-style-xsl Requires: shared-mime-info %description This package includes test and example programs for drumstick libraries. Authors: -------- Pedro Lopez-Cabanillas %package -n libdrumstick-file1 Summary: MIDI Sequencer C++ Library Group: System/Libraries %description -n libdrumstick-file1 MIDI Sequencer C++ Library Bindings for Qt5 This library includes classes providing file input and output in formats commonly used by MIDI programs. Currently, SMF (standard MIDI file) read/write and WRK (Cakewalk) file read are supported. Authors: -------- Pedro Lopez-Cabanillas %package -n libdrumstick-alsa1 Summary: MIDI Sequencer C++ Library Group: System/Libraries %description -n libdrumstick-alsa1 MIDI Sequencer C++ Library Bindings for Qt5 and ALSA. This library includes the ALSA Sequencer library classes, providing MIDI recording and playback functionality to C++/Qt5 programs. Authors: -------- Pedro Lopez-Cabanillas %package -n libdrumstick-rt1 Summary: MIDI Realtime IO C++ Library Group: System/Libraries %description -n libdrumstick-rt1 MIDI Realtime IO C++ Library for Qt5 This library includes the RT library classes, providing MIDI realtime IO functionality to C++/Qt5 programs. Authors: -------- Pedro Lopez-Cabanillas %package -n libdrumstick-devel Summary: Development package for the libdrumstick library Group: Development/Libraries/C and C++ Requires: libdrumstick-file1 = %{version} Requires: libdrumstick-alsa1 = %{version} Requires: glibc-devel libstdc++-devel alsa-lib-devel qt5-qtbase-devel %description -n libdrumstick-devel This package contains the files needed to compile programs that use the libdrumstick libraries. Authors: -------- Pedro Lopez-Cabanillas %package -n libdrumstick-doc Summary: Development documentation package for the drumstick libraries Group: Documentation/Other %description -n libdrumstick-doc This package contains the developer's documentation of the drumstick libraries. Authors: -------- Pedro Lopez-Cabanillas %prep %setup -q %build CXXFLAGS="$RPM_OPT_FLAGS -g -fexceptions" \ cmake . -DSTATIC_DRUMSTICK=0 \ -DCMAKE_INSTALL_PREFIX=%{_prefix} \ -DLIB_SUFFIX=$(echo %_lib | cut -b4-) make %{?jobs:-j %jobs} VERBOSE=1 make doxygen %install make install DESTDIR=$RPM_BUILD_ROOT %post %{_bindir}/update-mime-database %{_datadir}/mime %postun %{_bindir}/update-mime-database %{_datadir}/mime %post -n libdrumstick-file1 -p /sbin/ldconfig %postun -n libdrumstick-file1 -p /sbin/ldconfig %post -n libdrumstick-alsa1 -p /sbin/ldconfig %postun -n libdrumstick-alsa1 -p /sbin/ldconfig %post -n libdrumstick-rt1 -p /sbin/ldconfig %postun -n libdrumstick-rt1 -p /sbin/ldconfig %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-, root, root) %doc AUTHORS COPYING NEWS README TODO ChangeLog %doc %{_mandir}/* %{_datadir}/icons/hicolor/*/*/* %{_datadir}/applications/* %{_bindir}/* %files -n libdrumstick-file1 %defattr(-,root,root) %{_libdir}/libdrumstick-file.so.* %{_datadir}/mime/packages/* %files -n libdrumstick-alsa1 %defattr(-,root,root) %{_libdir}/libdrumstick-alsa.so.* %files -n libdrumstick-rt1 %defattr(-,root,root) %{_libdir}/libdrumstick-rt.so.* %{_libdir}/drumstick/*.so %files -n libdrumstick-devel %defattr(-, root, root) %dir %{_includedir}/drumstick %{_libdir}/libdrumstick-file.so %{_libdir}/libdrumstick-alsa.so %{_libdir}/libdrumstick-rt.so %{_includedir}/drumstick.h %{_includedir}/drumstick/*.h %{_libdir}/pkgconfig/*.pc %files -n libdrumstick-doc %defattr(-, root, root) %doc doc/html/* %changelog * Sat Aug 30 2014 Pedro Lopez-Cabanillas 1.0.0 - New version * Thu Sep 9 2010 Pedro Lopez-Cabanillas 0.5.0 - New version drumstick-1.1.3/PaxHeaders.32572/Doxyfile.in0000644000000000000000000000013213532747316015406 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.006000245 30 ctime=1567346382.729999891 drumstick-1.1.3/Doxyfile.in0000644000175000001440000017313413532747316016210 0ustar00pedrousers00000000000000# Doxyfile 1.6.3 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = drumstick # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @VERSION@ # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = doc # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = YES # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it parses. # With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this tag. # The format is ext=language, where ext is a file extension, and language is one of # the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, # Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat # .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = YES # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = YES # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = YES # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = YES # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST = YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by # doxygen. The layout file controls the global structure of the generated output files # in an output format independent way. The create the layout file that represents # doxygen's defaults, run doxygen with the -l option. You can optionally specify a # file name after the option, if omitted DoxygenLayout.xml will be used as the name # of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = @CMAKE_SOURCE_DIR@/doc/drumstick-devel.doc.txt @CMAKE_SOURCE_DIR@/library # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = *.cpp *.h # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = @CMAKE_SOURCE_DIR@/library/rt-backends # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = @CMAKE_SOURCE_DIR@/utils/dumpmid @CMAKE_SOURCE_DIR@/utils/dumpwrk @CMAKE_SOURCE_DIR@/utils/dumpove @CMAKE_SOURCE_DIR@/utils/playsmf @CMAKE_SOURCE_DIR@/utils/dumpsmf @CMAKE_SOURCE_DIR@/utils/metronome @CMAKE_SOURCE_DIR@/utils/sysinfo @CMAKE_SOURCE_DIR@/utils/vpiano @CMAKE_SOURCE_DIR@/utils/drumgrid @CMAKE_SOURCE_DIR@/utils/guiplayer # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = YES # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # If the HTML_FOOTER_DESCRIPTION tag is set to YES, Doxygen will # add generated date, project name and doxygen version to HTML footer. HTML_FOOTER_DESCRIPTION = NO # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! # HTML_STYLESHEET = @CMAKE_SOURCE_DIR@/doc/doxygen.css HTML_STYLESHEET = # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER # are set, an additional index file will be generated that can be used as input for # Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated # HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. # For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see #
Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's # filter section matches. # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to FRAME, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. Other possible values # for this tag are: HIERARCHIES, which will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list; # ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which # disables this behavior completely. For backwards compatibility with previous # releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE # respectively. GENERATE_TREEVIEW = YES # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = /usr/include/QtCore /usr/include/QtGui # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = NO # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = YES # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = NO # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = NO # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Options related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO drumstick-1.1.3/PaxHeaders.32572/chkcoverage0000644000000000000000000000013213532747316015477 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.006000245 30 ctime=1567346382.729999891 drumstick-1.1.3/chkcoverage0000755000175000001440000000062013532747316016271 0ustar00pedrousers00000000000000#!/bin/bash echo "List of ALSA sequencer/midi/timer symbols not yet wrapped by drumstick" K=0 objdump -t -j *UND* build/library/libdrumstick.a | awk '{print $4}' | grep "^snd" > lib.txt nm --defined-only -D /usr/lib/libasound.so | awk '{print $3}'| egrep "^snd_(seq|midi|timer)" |\ while read W; do grep -q $W lib.txt if [ "$?" != "0" ]; then let K++ echo "$K $W" fi done rm -f lib.txt drumstick-1.1.3/PaxHeaders.32572/COPYING0000644000000000000000000000013213532747316014326 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.006000245 30 ctime=1567346382.729999891 drumstick-1.1.3/COPYING0000644000175000001440000004313613532747316015126 0ustar00pedrousers00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. drumstick-1.1.3/PaxHeaders.32572/drumstick.pro0000644000000000000000000000013213532747316016022 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.006000245 30 ctime=1567346382.729999891 drumstick-1.1.3/drumstick.pro0000644000175000001440000000013613532747316016613 0ustar00pedrousers00000000000000TEMPLATE = subdirs CONFIG += ordered SUBDIRS += library \ utils \ tests drumstick-1.1.3/PaxHeaders.32572/cmake_admin0000644000000000000000000000013213532747316015446 xustar0030 mtime=1567346382.693999845 30 atime=1567346383.006000245 30 ctime=1567346382.693999845 drumstick-1.1.3/cmake_admin/0000755000175000001440000000000013532747316016314 5ustar00pedrousers00000000000000drumstick-1.1.3/cmake_admin/PaxHeaders.32572/CreateLibtoolFile.cmake0000644000000000000000000000013213532747316022055 xustar0030 mtime=1567346382.693999845 30 atime=1567346383.006000245 30 ctime=1567346382.693999845 drumstick-1.1.3/cmake_admin/CreateLibtoolFile.cmake0000644000175000001440000000615613532747316022656 0ustar00pedrousers00000000000000# origin: http://www.cmake.org/Wiki/CMakeMacroLibtoolFile MACRO(GET_TARGET_PROPERTY_WITH_DEFAULT _variable _target _property _default_value) GET_TARGET_PROPERTY (${_variable} ${_target} ${_property}) IF (${_variable} MATCHES ".*NOTFOUND$") SET (${_variable} ${_default_value}) ENDIF (${_variable} MATCHES ".*NOTFOUND$") ENDMACRO (GET_TARGET_PROPERTY_WITH_DEFAULT) MACRO(CREATE_LIBTOOL_FILE _target _install_DIR) GET_TARGET_PROPERTY(_target_location ${_target} LOCATION) GET_TARGET_PROPERTY_WITH_DEFAULT(_target_static_lib ${_target} STATIC_LIB "") GET_TARGET_PROPERTY_WITH_DEFAULT(_target_dependency_libs ${_target} LT_DEPENDENCY_LIBS "") GET_TARGET_PROPERTY_WITH_DEFAULT(_target_current ${_target} LT_VERSION_CURRENT 0) GET_TARGET_PROPERTY_WITH_DEFAULT(_target_age ${_target} LT_VERSION_AGE 0) GET_TARGET_PROPERTY_WITH_DEFAULT(_target_revision ${_target} LT_VERSION_REVISION 0) GET_TARGET_PROPERTY_WITH_DEFAULT(_target_installed ${_target} LT_INSTALLED yes) GET_TARGET_PROPERTY_WITH_DEFAULT(_target_shouldnotlink ${_target} LT_SHOULDNOTLINK yes) GET_TARGET_PROPERTY_WITH_DEFAULT(_target_dlopen ${_target} LT_DLOPEN "") GET_TARGET_PROPERTY_WITH_DEFAULT(_target_dlpreopen ${_target} LT_DLPREOPEN "") GET_FILENAME_COMPONENT(_laname ${_target_location} NAME_WE) GET_FILENAME_COMPONENT(_soname ${_target_location} NAME) SET(_laname ${_laname}.la) SET(_laname_file "${CMAKE_CURRENT_BINARY_DIR}/${_laname}") FILE(WRITE ${_laname_file} "# ${_laname} - a libtool library file, generated by cmake \n") FILE(APPEND ${_laname_file} "# The name that we can dlopen(3).\n") FILE(APPEND ${_laname_file} "dlname='${_soname}'\n") FILE(APPEND ${_laname_file} "# Names of this library\n") FILE(APPEND ${_laname_file} "library_names='${_soname}.${_target_current}.${_target_age}.${_target_revision} ${_soname}.${_target_current} ${_soname}'\n") FILE(APPEND ${_laname_file} "# The name of the static archive\n") FILE(APPEND ${_laname_file} "old_library='${_target_static_lib}'\n") FILE(APPEND ${_laname_file} "# Libraries that this one depends upon.\n") FILE(APPEND ${_laname_file} "dependency_libs='${_target_dependency_libs}'\n") FILE(APPEND ${_laname_file} "# Version information.\n") FILE(APPEND ${_laname_file} "current=${_target_current}\n") FILE(APPEND ${_laname_file} "age=${_target_age}\n") FILE(APPEND ${_laname_file} "revision=${_target_revision}\n") FILE(APPEND ${_laname_file} "# Is this an already installed library?\n") FILE(APPEND ${_laname_file} "installed=${_target_installed}\n") FILE(APPEND ${_laname_file} "# Should we warn about portability when linking against -modules?\n") FILE(APPEND ${_laname_file} "shouldnotlink=${_target_shouldnotlink}\n") FILE(APPEND ${_laname_file} "# Files to dlopen/dlpreopen\n") FILE(APPEND ${_laname_file} "dlopen='${_target_dlopen}'\n") FILE(APPEND ${_laname_file} "dlpreopen='${_target_dlpreopen}'\n") FILE(APPEND ${_laname_file} "# Directory that this library needs to be installed in:\n") FILE(APPEND ${_laname_file} "libdir='${CMAKE_INSTALL_PREFIX}/${_install_DIR}'\n") INSTALL(FILES ${_laname_file} DESTINATION ${_install_DIR}) ENDMACRO(CREATE_LIBTOOL_FILE) drumstick-1.1.3/cmake_admin/PaxHeaders.32572/cmake_uninstall.cmake.in0000644000000000000000000000013213532747316022303 xustar0030 mtime=1567346382.689999838 30 atime=1567346383.006000245 30 ctime=1567346382.689999838 drumstick-1.1.3/cmake_admin/cmake_uninstall.cmake.in0000644000175000001440000000155513532747316023102 0ustar00pedrousers00000000000000IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) STRING(REGEX REPLACE "\n" ";" files "${files}") FOREACH(file ${files}) MESSAGE(STATUS "Uninstalling \"${file}\"") IF(EXISTS "${file}") EXEC_PROGRAM( "@CMAKE_COMMAND@" ARGS "-E remove \"${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) IF("${rm_retval}" STREQUAL 0) ELSE("${rm_retval}" STREQUAL 0) MESSAGE(FATAL_ERROR "Problem when removing \"${file}\"") ENDIF("${rm_retval}" STREQUAL 0) ELSE(EXISTS "${file}") MESSAGE(STATUS "File \"${file}\" does not exist.") ENDIF(EXISTS "${file}") ENDFOREACH(file) drumstick-1.1.3/cmake_admin/PaxHeaders.32572/MacroEnsureVersion.cmake0000644000000000000000000000013213532747316022316 xustar0030 mtime=1567346382.689999838 30 atime=1567346383.006000245 30 ctime=1567346382.689999838 drumstick-1.1.3/cmake_admin/MacroEnsureVersion.cmake0000644000175000001440000001173513532747316023116 0ustar00pedrousers00000000000000# This file defines the following macros for developers to use in ensuring # that installed software is of the right version: # # MACRO_ENSURE_VERSION - test that a version number is greater than # or equal to some minimum # MACRO_ENSURE_VERSION_RANGE - test that a version number is greater than # or equal to some minimum and less than some # maximum # MACRO_ENSURE_VERSION2 - deprecated, do not use in new code # # MACRO_ENSURE_VERSION # This macro compares version numbers of the form "x.y.z" or "x.y" # MACRO_ENSURE_VERSION( FOO_MIN_VERSION FOO_VERSION_FOUND FOO_VERSION_OK) # will set FOO_VERSION_OK to true if FOO_VERSION_FOUND >= FOO_MIN_VERSION # Leading and trailing text is ok, e.g. # MACRO_ENSURE_VERSION( "2.5.31" "flex 2.5.4a" VERSION_OK) # which means 2.5.31 is required and "flex 2.5.4a" is what was found on the system # Copyright (c) 2006, David Faure, # Copyright (c) 2007, Will Stephenson # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # MACRO_ENSURE_VERSION_RANGE # This macro ensures that a version number of the form # "x.y.z" or "x.y" falls within a range defined by # min_version <= found_version < max_version. # If this expression holds, FOO_VERSION_OK will be set TRUE # # Example: MACRO_ENSURE_VERSION_RANGE3( "0.1.0" ${FOOCODE_VERSION} "0.7.0" FOO_VERSION_OK ) # # This macro will break silently if any of x,y,z are greater than 100. # # Copyright (c) 2007, Will Stephenson # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # NORMALIZE_VERSION # Helper macro to convert version numbers of the form "x.y.z" # to an integer equal to 10^4 * x + 10^2 * y + z # # This macro will break silently if any of x,y,z are greater than 100. # # Copyright (c) 2006, David Faure, # Copyright (c) 2007, Will Stephenson # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # CHECK_RANGE_INCLUSIVE_LOWER # Helper macro to check whether x <= y < z # # Copyright (c) 2007, Will Stephenson # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. MACRO(NORMALIZE_VERSION _requested_version _normalized_version) STRING(REGEX MATCH "[^0-9]*[0-9]+\\.[0-9]+\\.[0-9]+.*" _threePartMatch "${_requested_version}") if (_threePartMatch) # parse the parts of the version string STRING(REGEX REPLACE "[^0-9]*([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" _major_vers "${_requested_version}") STRING(REGEX REPLACE "[^0-9]*[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" _minor_vers "${_requested_version}") STRING(REGEX REPLACE "[^0-9]*[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" _patch_vers "${_requested_version}") else (_threePartMatch) STRING(REGEX REPLACE "([0-9]+)\\.[0-9]+" "\\1" _major_vers "${_requested_version}") STRING(REGEX REPLACE "[0-9]+\\.([0-9]+)" "\\1" _minor_vers "${_requested_version}") set(_patch_vers "0") endif (_threePartMatch) # compute an overall version number which can be compared at once MATH(EXPR ${_normalized_version} "${_major_vers}*10000 + ${_minor_vers}*100 + ${_patch_vers}") ENDMACRO(NORMALIZE_VERSION) MACRO(MACRO_CHECK_RANGE_INCLUSIVE_LOWER _lower_limit _value _upper_limit _ok) if (${_value} LESS ${_lower_limit}) set( ${_ok} FALSE ) elseif (${_value} EQUAL ${_lower_limit}) set( ${_ok} TRUE ) elseif (${_value} EQUAL ${_upper_limit}) set( ${_ok} FALSE ) elseif (${_value} GREATER ${_upper_limit}) set( ${_ok} FALSE ) else (${_value} LESS ${_lower_limit}) set( ${_ok} TRUE ) endif (${_value} LESS ${_lower_limit}) ENDMACRO(MACRO_CHECK_RANGE_INCLUSIVE_LOWER) MACRO(MACRO_ENSURE_VERSION requested_version found_version var_too_old) NORMALIZE_VERSION( ${requested_version} req_vers_num ) NORMALIZE_VERSION( ${found_version} found_vers_num ) if (found_vers_num LESS req_vers_num) set( ${var_too_old} FALSE ) else (found_vers_num LESS req_vers_num) set( ${var_too_old} TRUE ) endif (found_vers_num LESS req_vers_num) ENDMACRO(MACRO_ENSURE_VERSION) MACRO(MACRO_ENSURE_VERSION2 requested_version2 found_version2 var_too_old2) MACRO_ENSURE_VERSION( ${requested_version2} ${found_version2} ${var_too_old2}) ENDMACRO(MACRO_ENSURE_VERSION2) MACRO(MACRO_ENSURE_VERSION_RANGE min_version found_version max_version var_ok) NORMALIZE_VERSION( ${min_version} req_vers_num ) NORMALIZE_VERSION( ${found_version} found_vers_num ) NORMALIZE_VERSION( ${max_version} max_vers_num ) MACRO_CHECK_RANGE_INCLUSIVE_LOWER( ${req_vers_num} ${found_vers_num} ${max_vers_num} ${var_ok}) ENDMACRO(MACRO_ENSURE_VERSION_RANGE) drumstick-1.1.3/cmake_admin/PaxHeaders.32572/FindPCHSupport.cmake0000644000000000000000000000013213532747316021335 xustar0030 mtime=1567346382.689999838 30 atime=1567346383.006000245 30 ctime=1567346382.689999838 drumstick-1.1.3/cmake_admin/FindPCHSupport.cmake0000644000175000001440000000675513532747316022143 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2008-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Try to find precompiled headers support for GCC 3.4 and 4.x # Once done this will define: # # Variable: # PCHSupport_FOUND # # Macro: # ADD_PRECOMPILED_HEADER IF(CMAKE_COMPILER_IS_GNUCXX) EXEC_PROGRAM(${CMAKE_CXX_COMPILER} ARGS -dumpversion OUTPUT_VARIABLE gcc_compiler_version) IF(gcc_compiler_version MATCHES "4\\.[0-9]\\.[0-9]") SET(PCHSupport_FOUND TRUE) ELSE(gcc_compiler_version MATCHES "4\\.[0-9]\\.[0-9]") IF(gcc_compiler_version MATCHES "3\\.4\\.[0-9]") SET(PCHSupport_FOUND TRUE) ENDIF(gcc_compiler_version MATCHES "3\\.4\\.[0-9]") ENDIF(gcc_compiler_version MATCHES "4\\.[0-9]\\.[0-9]") ENDIF(CMAKE_COMPILER_IS_GNUCXX) MACRO(ADD_PRECOMPILED_HEADER _targetName _input) GET_FILENAME_COMPONENT(_name ${_input} NAME) SET(_source "${CMAKE_CURRENT_SOURCE_DIR}/${_input}") SET(_outdir "${CMAKE_CURRENT_BINARY_DIR}/${_name}.gch") MAKE_DIRECTORY(${_outdir}) IF(NOT CMAKE_BUILD_TYPE) SET(_output "${_outdir}/Custom.c++") ELSE(NOT CMAKE_BUILD_TYPE) SET(_output "${_outdir}/${CMAKE_BUILD_TYPE}.c++") ENDIF(NOT CMAKE_BUILD_TYPE) STRING(TOUPPER "CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}" _flags_var_name) SET(_compiler_FLAGS ${CMAKE_CXX_FLAGS} ${${_flags_var_name}}) SEPARATE_ARGUMENTS(_compiler_FLAGS) #MESSAGE("_compiler_FLAGS: ${_compiler_FLAGS}") GET_DIRECTORY_PROPERTY(_dir_FLAGS INCLUDE_DIRECTORIES) FOREACH(item ${_dir_FLAGS}) LIST(APPEND _include_FLAGS "-I${item}") ENDFOREACH(item) #MESSAGE("_include_FLAGS: ${_include_FLAGS}") GET_DIRECTORY_PROPERTY(_definitions24 DEFINITIONS) GET_DIRECTORY_PROPERTY(_definitions26 COMPILE_DEFINITIONS) SET(_definitions ${_definitions24}) SEPARATE_ARGUMENTS(_definitions) FOREACH(def ${_definitions26}) LIST(APPEND _definitions "-D${def}") ENDFOREACH(def) STRING(TOUPPER "COMPILE_DEFINITIONS_${CMAKE_BUILD_TYPE}" _defs_var_name) GET_DIRECTORY_PROPERTY(_definitions_buildtype ${_defs_var_name}) FOREACH(def ${_definitions_buildtype}) LIST(APPEND _definitions "-D${def}") ENDFOREACH(def) LIST(REMOVE_DUPLICATES _definitions) #MESSAGE("_definitions: ${_definitions}") ADD_CUSTOM_COMMAND( OUTPUT ${_output} COMMAND ${CMAKE_CXX_COMPILER} ${_compiler_FLAGS} ${_include_FLAGS} ${_definitions} -x c++-header -o ${_output} ${_source} DEPENDS ${_source} ) ADD_CUSTOM_TARGET(${_targetName} DEPENDS ${_output}) #SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -include ${CMAKE_CURRENT_BINARY_DIR}/${_name} -Winvalid-pch -H") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -include ${CMAKE_CURRENT_BINARY_DIR}/${_name} -Winvalid-pch") ENDMACRO(ADD_PRECOMPILED_HEADER) drumstick-1.1.3/cmake_admin/PaxHeaders.32572/FindSharedMimeInfo.cmake0000644000000000000000000000013213532747316022160 xustar0030 mtime=1567346382.689999838 30 atime=1567346383.006000245 30 ctime=1567346382.689999838 drumstick-1.1.3/cmake_admin/FindSharedMimeInfo.cmake0000644000175000001440000000561513532747316022760 0ustar00pedrousers00000000000000# - Try to find the shared-mime-info package # # SHARED_MIME_INFO_MINIMUM_VERSION - Set this to the minimum version you need, default is 0.18 # # Once done this will define # # SHARED_MIME_INFO_FOUND - system has the shared-mime-info package # UPDATE_MIME_DATABASE_EXECUTABLE - the update-mime-database executable # Copyright (c) 2007, Pino Toscano, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # the minimum version of shared-mime-database we require if (NOT SHARED_MIME_INFO_MINIMUM_VERSION) set(SHARED_MIME_INFO_MINIMUM_VERSION "0.18") endif (NOT SHARED_MIME_INFO_MINIMUM_VERSION) if (UPDATE_MIME_DATABASE_EXECUTABLE) # in cache already set(SHARED_MIME_INFO_FOUND TRUE) else (UPDATE_MIME_DATABASE_EXECUTABLE) include (MacroEnsureVersion) find_program (UPDATE_MIME_DATABASE_EXECUTABLE NAMES update-mime-database) if (UPDATE_MIME_DATABASE_EXECUTABLE) exec_program (${UPDATE_MIME_DATABASE_EXECUTABLE} ARGS -v RETURN_VALUE _null OUTPUT_VARIABLE _smiVersionRaw) string(REGEX REPLACE "update-mime-database \\([a-zA-Z\\-]+\\) ([0-9]\\.[0-9]+).*" "\\1" smiVersion "${_smiVersionRaw}") set (SHARED_MIME_INFO_FOUND TRUE) endif (UPDATE_MIME_DATABASE_EXECUTABLE) if (SHARED_MIME_INFO_FOUND) if (NOT SharedMimeInfo_FIND_QUIETLY) message(STATUS "Found shared-mime-info version: ${smiVersion}") macro_ensure_version(${SHARED_MIME_INFO_MINIMUM_VERSION} ${smiVersion} _smiVersion_OK) if (NOT _smiVersion_OK) message(FATAL_ERROR "The found version of shared-mime-info (${smiVersion}) is below the minimum required (${SHARED_MIME_INFO_MINIMUM_VERSION})") endif (NOT _smiVersion_OK) endif (NOT SharedMimeInfo_FIND_QUIETLY) else (SHARED_MIME_INFO_FOUND) if (SharedMimeInfo_FIND_REQUIRED) message(FATAL_ERROR "Could NOT find shared-mime-info. See http://freedesktop.org/wiki/Software/shared-mime-info.") endif (SharedMimeInfo_FIND_REQUIRED) endif (SHARED_MIME_INFO_FOUND) endif (UPDATE_MIME_DATABASE_EXECUTABLE) mark_as_advanced(UPDATE_MIME_DATABASE_EXECUTABLE) macro(UPDATE_XDG_MIMETYPES _path) get_filename_component(_xdgmimeDir "${_path}" NAME) if("${_xdgmimeDir}" STREQUAL packages ) get_filename_component(_xdgmimeDir "${_path}" PATH) else("${_xdgmimeDir}" STREQUAL packages ) set(_xdgmimeDir "${_path}") endif("${_xdgmimeDir}" STREQUAL packages ) install(CODE " set(DESTDIR_VALUE \"\$ENV{DESTDIR}\") if (NOT DESTDIR_VALUE) # under Windows relative paths are used, that's why it runs from CMAKE_INSTALL_PREFIX execute_process(COMMAND ${UPDATE_MIME_DATABASE_EXECUTABLE} ${_xdgmimeDir} WORKING_DIRECTORY \"${CMAKE_INSTALL_PREFIX}\") endif (NOT DESTDIR_VALUE) ") endmacro (UPDATE_XDG_MIMETYPES) drumstick-1.1.3/cmake_admin/PaxHeaders.32572/COPYING-CMAKE-SCRIPTS0000644000000000000000000000013213532747316020521 xustar0030 mtime=1567346382.689999838 30 atime=1567346383.006000245 30 ctime=1567346382.689999838 drumstick-1.1.3/cmake_admin/COPYING-CMAKE-SCRIPTS0000644000175000001440000000245613532747316021321 0ustar00pedrousers00000000000000Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. drumstick-1.1.3/cmake_admin/PaxHeaders.32572/CreateManpages.cmake0000644000000000000000000000013213532747316021404 xustar0030 mtime=1567346382.693999845 30 atime=1567346383.006000245 30 ctime=1567346382.693999845 drumstick-1.1.3/cmake_admin/CreateManpages.cmake0000644000175000001440000000301013532747316022167 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2008-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; If not, see . MACRO(CREATE_MANPAGES) SET(outfiles) FOREACH (it ${ARGN}) GET_FILENAME_COMPONENT(outfile ${it} NAME_WE) GET_FILENAME_COMPONENT(infile ${it} ABSOLUTE) SET(outfile ${CMAKE_CURRENT_BINARY_DIR}/${outfile}.1) SET(outfiles ${outfiles} ${outfile}) ADD_CUSTOM_COMMAND( OUTPUT ${outfile} COMMAND ${XSLTPROC_EXECUTABLE} --nonet --xinclude --xincludestyle --output ${outfile} http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl ${infile} DEPENDS ${infile}) ENDFOREACH (it) ADD_CUSTOM_TARGET(manpages ALL DEPENDS ${outfiles}) INSTALL ( FILES ${outfiles} DESTINATION "${CMAKE_INSTALL_MANDIR}/man1" ) ENDMACRO(CREATE_MANPAGES) drumstick-1.1.3/PaxHeaders.32572/drumstick-file.pc.in0000644000000000000000000000013213532747316017146 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.006000245 30 ctime=1567346382.729999891 drumstick-1.1.3/drumstick-file.pc.in0000644000175000001440000000047613532747316017746 0ustar00pedrousers00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=${prefix}/lib@LIB_SUFFIX@ includedir=${prefix}/include Name: drumstick-file Version: @VERSION@ Description: MIDI Sequencer C++ Library Bindings for Qt5 URL: http://sourceforge.net/projects/drumstick Libs: -L${libdir} -ldrumstick-file Cflags: -I${includedir} drumstick-1.1.3/PaxHeaders.32572/drumstick.xml0000644000000000000000000000013213532747316016022 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.006000245 30 ctime=1567346382.729999891 drumstick-1.1.3/drumstick.xml0000644000175000001440000000176013532747316016617 0ustar00pedrousers00000000000000 Cakewalk project file Cakewalk project file Archivo de proyecto Cakewalk Overture project file Overture project file Archivo de proyecto Overture drumstick-1.1.3/PaxHeaders.32572/drumstick-rt.pc.in0000644000000000000000000000013213532747316016654 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.006000245 30 ctime=1567346382.729999891 drumstick-1.1.3/drumstick-rt.pc.in0000644000175000001440000000045413532747316017450 0ustar00pedrousers00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=${prefix} libdir=${prefix}/lib@LIB_SUFFIX@ includedir=${prefix}/include Name: drumstick-rt Version: @VERSION@ Description: MIDI Realtime Library for Qt5 URL: http://sourceforge.net/projects/drumstick Libs: -L${libdir} -ldrumstick-rt Cflags: -I${includedir} drumstick-1.1.3/PaxHeaders.32572/doc0000644000000000000000000000013013532747316013761 xustar0029 mtime=1567346382.72199988 30 atime=1567346383.006000245 29 ctime=1567346382.72199988 drumstick-1.1.3/doc/0000755000175000001440000000000013532747316014631 5ustar00pedrousers00000000000000drumstick-1.1.3/doc/PaxHeaders.32572/drumstick-metronome.xml.in0000644000000000000000000000013013532747316021175 xustar0029 mtime=1567346382.72199988 30 atime=1567346383.006000245 29 ctime=1567346382.72199988 drumstick-1.1.3/doc/drumstick-metronome.xml.in0000644000175000001440000001027013532747316021770 0ustar00pedrousers00000000000000 ]> &product; Pedro Lopez-Cabanillas plcl@users.sf.net 2010-2019 Pedro Lopez-Cabanillas Jan 13, 2019 &product; 1 @VERSION@ drumstick User Commands &product; A Drumstick command line utility for playing a metronome pattern. Synopsis &product; options Description This program is a Drumstick example and utility program. You can use it to play a MIDI metronome pattern. Arguments The following arguments are required: client:port An ALSA client:port specification that will be subscribed in order to send MIDI events to it. The client portion can be a number or a name, like in "20:0" or "KMidimon:0". The following arguments are optional: BPM Tempo in beats per minute. Default is 120 BPM. Prints a summary of the command-line options and exit. Prints the program version number and exit. License Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 or any later version published by the Free Software Foundation, considering as source code any files used for the production of this manpage. See also drumstick-dumpmid 1 , drumstick-playsmf 1 drumstick-1.1.3/doc/PaxHeaders.32572/drumstick-dumpmid.xml.in0000644000000000000000000000013013532747316020627 xustar0029 mtime=1567346382.72199988 30 atime=1567346383.006000245 29 ctime=1567346382.72199988 drumstick-1.1.3/doc/drumstick-dumpmid.xml.in0000644000175000001440000000762013532747316021427 0ustar00pedrousers00000000000000 ]> &product; Pedro Lopez-Cabanillas plcl@users.sf.net 2010-2019 Pedro Lopez-Cabanillas Jan 13, 2019 &product; 1 @VERSION@ drumstick User Commands &product; A Drumstick command line utility for decoding MIDI events. Synopsis &product; options Description This program is a Drumstick example and utility program. You can use it to decode standard MIDI events as text. Arguments The following argument is mandatory: client:port An ALSA client:port specification that will be subscribed in order to read MIDI events from it. The client portion can be a number or a name, like in "20:0" or "Virtual Piano:0". The following arguments are optional: Prints a summary of the command-line options and exit. Prints the program version number and exit. License Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 or any later version published by the Free Software Foundation, considering as source code any files used for the production of this manpage. See also drumstick-playsmf 1 , drumstick-vpiano 1 drumstick-1.1.3/doc/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013013532747316016576 xustar0029 mtime=1567346382.72199988 30 atime=1567346383.006000245 29 ctime=1567346382.72199988 drumstick-1.1.3/doc/CMakeLists.txt0000644000175000001440000000545013532747316017375 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2008-2019 Pedro Lopez-Cabanillas # # 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, see . FIND_PROGRAM(XSLTPROC_EXECUTABLE xsltproc) IF(XSLTPROC_EXECUTABLE) MESSAGE(STATUS "XSLTPROC Found: ${XSLTPROC_EXECUTABLE}") CONFIGURE_FILE(drumstick-drumgrid.xml.in ${CMAKE_CURRENT_BINARY_DIR}/drumstick-drumgrid.xml IMMEDIATE @ONLY) CONFIGURE_FILE(drumstick-dumpmid.xml.in ${CMAKE_CURRENT_BINARY_DIR}/drumstick-dumpmid.xml IMMEDIATE @ONLY) CONFIGURE_FILE(drumstick-dumpove.xml.in ${CMAKE_CURRENT_BINARY_DIR}/drumstick-dumpove.xml IMMEDIATE @ONLY) CONFIGURE_FILE(drumstick-dumpsmf.xml.in ${CMAKE_CURRENT_BINARY_DIR}/drumstick-dumpsmf.xml IMMEDIATE @ONLY) CONFIGURE_FILE(drumstick-dumpwrk.xml.in ${CMAKE_CURRENT_BINARY_DIR}/drumstick-dumpwrk.xml IMMEDIATE @ONLY) CONFIGURE_FILE(drumstick-metronome.xml.in ${CMAKE_CURRENT_BINARY_DIR}/drumstick-metronome.xml IMMEDIATE @ONLY) CONFIGURE_FILE(drumstick-playsmf.xml.in ${CMAKE_CURRENT_BINARY_DIR}/drumstick-playsmf.xml IMMEDIATE @ONLY) CONFIGURE_FILE(drumstick-guiplayer.xml.in ${CMAKE_CURRENT_BINARY_DIR}/drumstick-guiplayer.xml IMMEDIATE @ONLY) CONFIGURE_FILE(drumstick-sysinfo.xml.in ${CMAKE_CURRENT_BINARY_DIR}/drumstick-sysinfo.xml IMMEDIATE @ONLY) CONFIGURE_FILE(drumstick-vpiano.xml.in ${CMAKE_CURRENT_BINARY_DIR}/drumstick-vpiano.xml IMMEDIATE @ONLY) INCLUDE(CreateManpages) CREATE_MANPAGES ( ${CMAKE_CURRENT_BINARY_DIR}/drumstick-drumgrid.xml ${CMAKE_CURRENT_BINARY_DIR}/drumstick-dumpmid.xml ${CMAKE_CURRENT_BINARY_DIR}/drumstick-dumpove.xml ${CMAKE_CURRENT_BINARY_DIR}/drumstick-dumpsmf.xml ${CMAKE_CURRENT_BINARY_DIR}/drumstick-dumpwrk.xml ${CMAKE_CURRENT_BINARY_DIR}/drumstick-metronome.xml ${CMAKE_CURRENT_BINARY_DIR}/drumstick-playsmf.xml ${CMAKE_CURRENT_BINARY_DIR}/drumstick-guiplayer.xml ${CMAKE_CURRENT_BINARY_DIR}/drumstick-sysinfo.xml ${CMAKE_CURRENT_BINARY_DIR}/drumstick-vpiano.xml ) ELSE(XSLTPROC_EXECUTABLE) MESSAGE(STATUS "Warning: XSLTPROC NOT Found. Man pages won't be installed") ENDIF(XSLTPROC_EXECUTABLE) drumstick-1.1.3/doc/PaxHeaders.32572/drumstick-devel.doc.txt0000644000000000000000000000013013532747316020445 xustar0029 mtime=1567346382.72199988 30 atime=1567346383.006000245 29 ctime=1567346382.72199988 drumstick-1.1.3/doc/drumstick-devel.doc.txt0000644000175000001440000001727213532747316021251 0ustar00pedrousers00000000000000/** @mainpage drumstick Documentation @author Copyright © 2009-2017 Pedro López-Cabanillas <plcl AT users.sf.net> @date 2017-08-15 @version 1.1.1 This document is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ @section Abstract This is the reference documentation for drumstick. These libraries are a set of C++ MIDI related classes, using Qt5 objects, idioms and style. Currently, there are three libraries: - \b drumstick-alsa is a C++/Qt wrapper around the ALSA Sequencer API. ALSA sequencer provides software support for MIDI technology on Linux. - \b drumstick-file provides easy multiplatform file I/O for Standard MIDI Files (.mid), Cakewalk (.wrk) and Overture (.ove) file formats. - \b drumstick-rt is a realtime MIDI I/O library with pluggable backends. It uses drumstick-alsa on Linux, and other frameworks on Mac and Windows. @see http://qt-project.org/doc/qt-5/index.html @see http://www.alsa-project.org/alsa-doc/alsa-lib/seq.html @see http://www.ics.com/design-patterns @see http://www.midi.org/articles/tutorials @section Disclaimer This document is a work in progress, in a very early state. It will be always in development. Please visit the drumstick web site to read the latest version. @see http://drumstick.sourceforge.net @section Introduction For an introduction to design and programming with C++ and Qt, see the book "An Introduction to Design Patterns in C++ with Qt" by by Alan Ezust and Paul Ezust. It is available published on dead trees, and also online. Here is how a simple program playing notes using drumstick-alsa looks like: @code #include #include int main(int argc, char **argv) { QApplication app(argc, argv, false); // create a client object on the heap drumstick::MidiClient *client = new drumstick::MidiClient; client->open(); client->setClientName( "MyClient" ); // create the port. Pointer is owned by the client instance drumstick::MidiPort *port = client->createPort(); port->setPortName( "MyPort" ); port->setCapability( SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ ); port->setPortType( SND_SEQ_PORT_TYPE_MIDI_GENERIC ); // subscribe the port to some other client:port port->subscribeTo( "128:0" ); // or "name:port", like in "FluidSynth:0" QList notes = { 60, 62, 64, 65, 67, 69, 71, 72 }; for(int i = 0; i < notes.length(); ++i) { // create event objects on the stack, to send note on/off messages drumstick::NoteOnEvent ev1( 0, notes[i], 100 ); // (channel, note number, velocity) ev1.setSource( port->getPortId() ); ev1.setSubscribers(); // deliver to all the connected ports ev1.setDirect(); // not scheduled, deliver immediately client->output( &ev1 ); // or outputDirect() if you prefer not buffered client->drainOutput(); // flush the buffer QThread::msleep(250); // wait a quarter second drumstick::NoteOffEvent ev2( 0, notes[i], 0 ); // (channel, note number, velocity) ev2.setSource( port->getPortId() ); ev2.setSubscribers(); // deliver to all the connected ports ev2.setDirect(); // not scheduled, deliver immediately client->output( &ev2 ); // or outputDirect() if you prefer not buffered client->drainOutput(); // flush the buffer } // close and clean client->close(); delete client; return 0; } @endcode A similar example can also be implemented using the drumstick-rt library: @code #include #include int main(int argc, char **argv) { QApplication app(argc, argv, false); drumstick::rt::BackendManager man; drumstick::rt::MIDIOutput* output = man.outputBackendByName("ALSA"); if (output != 0) { qDebug() << "testing backend: " << output->backendName(); qDebug() << "public name " << output->publicName(); foreach(const QString& c, output->connections()) { qDebug() << "port " << c; } output->open("FLUID Synth (qsynth):0"); QList notes = { 60, 62, 64, 65, 67, 69, 71, 72 }; for(int i = 0; i < notes.length(); ++i) { output->sendNoteOn(0, notes[i], 100); QThread::msleep(250); // wait a quarter second output->sendNoteOff(0, notes[i], 0); } output->close(); } return 0; } @endcode A common pattern on both implementations is QThread::msleep(250) to do the rhythm. If you are targeting only Linux, you may be interested on another (better) way to do the same, using drumstick-alsa again, because ALSA Sequencer is capable of event sacheduling (that is why it is called a Sequencer). @code #include #include int main(int argc, char **argv) { QApplication app(argc, argv, false); drumstick::MidiClient *client = new drumstick::MidiClient; client->open(); client->setClientName( "MyClient" ); drumstick::MidiPort *port = client->createPort(); port->setPortName( "MyPort" ); port->setCapability( SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ ); port->setPortType( SND_SEQ_PORT_TYPE_MIDI_GENERIC ); port->subscribeTo( "FLUID Synth (qsynth):0" ); drumstick::MidiQueue *queue = client->createQueue( "MyQueue" ); drumstick::QueueTempo tempo = queue->getTempo(); tempo.setNominalBPM( 120 ); queue->setTempo(tempo); client->drainOutput(); queue->start(); int tick = 0; QList notes = { 60, 62, 64, 65, 67, 69, 71, 72 }; for(int i = 0; i < notes.length(); ++i) { drumstick::NoteOnEvent ev1( 0, notes[i], 100 ); ev1.setSource( port->getPortId() ); ev1.setSubscribers(); ev1.scheduleTick(queue->getId(), tick, false); client->output( &ev1 ); tick += 60; drumstick::NoteOffEvent ev2( 0, notes[i], 0 ); ev2.setSource( port->getPortId() ); ev2.setSubscribers(); ev2.scheduleTick(queue->getId(), tick, false); client->output( &ev2 ); } client->drainOutput(); client->synchronizeOutput(); queue->stop(); // close and clean client->close(); delete client; return 0; } @endcode There are more examples in the source tree, under the utils/ directory, and you can also see applications using this library, like kmetronome, kmidimon and VMPK. @see http://kmetronome.sourceforge.net @see http://kmidimon.sourceforge.net @see http://kmid2.sourceforge.net @see http://vmpk.sourceforge.net @section Acknowledgments Parts of this documentation are copied from the ALSA library documentation, whose authors are:
  • Jaroslav Kysela <perex AT perex.cz>
  • Abramo Bagnara <abramo AT alsa-project.org>
  • Takashi Iwai <tiwai AT suse.de>
  • Frank van de Pol <fvdpol AT coil.demon.nl>
@example drumgrid.cpp Simple drum patterns @include drumgrid.h @example dumpmid.cpp Print received sequencer events @include dumpmid.h @example playsmf.cpp SMF playback, command line interface program @include playsmf.h @example guiplayer.cpp SMF playback, graphic user interface program @include guiplayer.h @example dumpsmf.cpp SMF read and print @include dumpsmf.h @example dumpwrk.cpp Cakewalk WRK file parse and print @include dumpwrk.h @example dumpove.cpp Overture OVE file parse and print @include dumpove.h @example metronome.cpp Simple command line MIDI metronome @include metronome.h @example sysinfo.cpp Prints information about the ALSA sequencer subsystem @example vpiano.cpp A Virtual Piano Keyboard GUI application. See another one at http://vmpk.sf.net @include vpiano.h */ drumstick-1.1.3/doc/PaxHeaders.32572/drumstick-dumpwrk.xml.in0000644000000000000000000000013013532747316020661 xustar0029 mtime=1567346382.72199988 30 atime=1567346383.006000245 29 ctime=1567346382.72199988 drumstick-1.1.3/doc/drumstick-dumpwrk.xml.in0000644000175000001440000000771713532747316021470 0ustar00pedrousers00000000000000 ]> &product; Pedro Lopez-Cabanillas plcl@users.sf.net 2010-2019 Pedro Lopez-Cabanillas Jan 13, 2019 &product; 1 @VERSION@ drumstick User Commands &product; A Drumstick command line utility for decoding WRK (Cakewalk) files. Synopsis &product; options FILE Description This program is a Drumstick example and utility program. You can use it to decode as text your WRK files created with Cakewalk or Sonar. Arguments The following argument is required: The name of the input WRK file. The following arguments are optional: Prints a summary of the command-line options and exit. Prints the program version number and exit. Verbose output. License Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 or any later version published by the Free Software Foundation, considering as source code any files used for the production of this manpage. See also drumstick-dumpsmf 1 , drumstick-dumpove 1 drumstick-1.1.3/doc/PaxHeaders.32572/drumstick-vpiano.xml.in0000644000000000000000000000013013532747316020464 xustar0029 mtime=1567346382.72199988 30 atime=1567346383.006000245 29 ctime=1567346382.72199988 drumstick-1.1.3/doc/drumstick-vpiano.xml.in0000644000175000001440000002566513532747316021275 0ustar00pedrousers00000000000000 ]> &product; Pedro Lopez-Cabanillas plcl@users.sf.net 2010-2019 Pedro Lopez-Cabanillas Jan 13, 2019 &product; 1 @VERSION@ drumstick User Commands &product; A Drumstick GUI virtual piano utility. Synopsis &product; options... Description This program is a Drumstick example and utility program. You can use it to play and watch a virtual piano. Arguments The following arguments are optional: Prints a summary of the command-line options and exit. Prints the program version number and exit. style sets the application GUI style. Possible values are motif, windows, and platinum. If you compiled Qt with additional styles or have additional styles as plugins these will be available to the -style command line option stylesheet sets the application styleSheet. The value must be a path to a file that contains the Style Sheet. Note: Relative URLs in the Style Sheet file are relative to the Style Sheet file's path. session restores the application from an earlier session. prints debug message at the end about number of widgets left undestroyed and maximum number of widgets existed at the same time sets the application's layout direction to Qt::RightToLeft sets the backend to be used for on-screen widgets and QPixmaps. Available options are raster and opengl. display sets the X display (default is $DISPLAY). geometry sets the client geometry of the first window that is shown. font defines the application font. The font should be specified using an X logical font description. color sets the default background color and an application palette (light and dark shades are calculated). color sets the default foreground color. color sets the default button color. name sets the application name. title sets the application title. forces the application to use a TrueColor visual on an 8-bit display. count limits the number of colors allocated in the color cube on an 8-bit display, if the application is using the QApplication::ManyColor color specification. If count is 216 then a 6x6x6 color cube is used (i.e. 6 levels of red, 6 of green, and 6 of blue); for other values, a cube approximately proportional to a 2x3x1 cube is used. causes the application to install a private color map on an 8-bit display. sets the input method server (equivalent to setting the XMODIFIERS environment variable) defines how the input is inserted into the given widget, e.g., onTheSpot makes the input appear directly in the widget, while overTheSpot makes the input appear in a box floating over the widget and is not inserted until the editing is done. License Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 or any later version published by the Free Software Foundation, considering as source code any files used for the production of this manpage. See also drumstick-drumgrid 1 , drumstick-guiplayer 1 drumstick-1.1.3/doc/PaxHeaders.32572/drumstick-sysinfo.xml.in0000644000000000000000000000013013532747316020662 xustar0029 mtime=1567346382.72199988 30 atime=1567346383.006000245 29 ctime=1567346382.72199988 drumstick-1.1.3/doc/drumstick-sysinfo.xml.in0000644000175000001440000000567513532747316021472 0ustar00pedrousers00000000000000 ]> &product; Pedro Lopez-Cabanillas plcl@users.sf.net 2010-2019 Pedro Lopez-Cabanillas Jan 13, 2019 &product; 1 @VERSION@ drumstick User Commands &product; A Drumstick command line utility to get information about the ALSA sequencer. Synopsis &product; options... Description This program is a Drumstick example and utility program. You can use it to build a report containing useful information about the ALSA sequencer. Arguments The following arguments are optional: Prints a summary of the command-line options and exit. Prints the program version number and exit. License Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 or any later version published by the Free Software Foundation, considering as source code any files used for the production of this manpage. drumstick-1.1.3/doc/PaxHeaders.32572/drumstick-dumpsmf.xml.in0000644000000000000000000000013013532747316020643 xustar0029 mtime=1567346382.72199988 30 atime=1567346383.006000245 29 ctime=1567346382.72199988 drumstick-1.1.3/doc/drumstick-dumpsmf.xml.in0000644000175000001440000000750313532747316021443 0ustar00pedrousers00000000000000 ]> &product; Pedro Lopez-Cabanillas plcl@users.sf.net 2010-2019 Pedro Lopez-Cabanillas Jan 13, 2019 &product; 1 @VERSION@ drumstick User Commands &product; A Drumstick command line utility for decoding standard MIDI files. Synopsis &product; options FILE Description This program is a Drumstick example and utility program. You can use it to decode a standard MIDI file as text. Arguments The following argument is required: The name of the input SMF. The following arguments are optional: Prints a summary of the command-line options and exit. Prints the program version number and exit. License Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 or any later version published by the Free Software Foundation, considering as source code any files used for the production of this manpage. See also drumstick-playsmf 1 , drumstick-dumpwrk 1 , drumstick-dumpove 1 drumstick-1.1.3/doc/PaxHeaders.32572/drumstick-drumgrid.xml.in0000644000000000000000000000013013532747316021005 xustar0029 mtime=1567346382.72199988 30 atime=1567346383.006000245 29 ctime=1567346382.72199988 drumstick-1.1.3/doc/drumstick-drumgrid.xml.in0000644000175000001440000002634713532747316021614 0ustar00pedrousers00000000000000 ]> &product; Pedro Lopez-Cabanillas plcl@users.sf.net 2010-2019 Pedro Lopez-Cabanillas Jan 13, 2019 &product; 1 @VERSION@ drumstick User Commands &product; A Drumstick utility emulating a drum box. Synopsis &product; Standard options... Description This program is a Drumstick example and utility program. You can use it to create and play drum patterns. Arguments The following arguments are optional: client:port MIDI Destination Port. Prints a summary of the command-line options and exit. Prints the program version number and exit. style sets the application GUI style. Possible values are motif, windows, and platinum. If you compiled Qt with additional styles or have additional styles as plugins these will be available to the -style command line option stylesheet sets the application styleSheet. The value must be a path to a file that contains the Style Sheet. Note: Relative URLs in the Style Sheet file are relative to the Style Sheet file's path. session restores the application from an earlier session. prints debug message at the end about number of widgets left undestroyed and maximum number of widgets existed at the same time sets the application's layout direction to Qt::RightToLeft sets the backend to be used for on-screen widgets and QPixmaps. Available options are raster and opengl. display sets the X display (default is $DISPLAY). geometry sets the client geometry of the first window that is shown. font defines the application font. The font should be specified using an X logical font description. color sets the default background color and an application palette (light and dark shades are calculated). color sets the default foreground color. color sets the default button color. name sets the application name. title sets the application title. forces the application to use a TrueColor visual on an 8-bit display. count limits the number of colors allocated in the color cube on an 8-bit display, if the application is using the QApplication::ManyColor color specification. If count is 216 then a 6x6x6 color cube is used (i.e. 6 levels of red, 6 of green, and 6 of blue); for other values, a cube approximately proportional to a 2x3x1 cube is used. causes the application to install a private color map on an 8-bit display. sets the input method server (equivalent to setting the XMODIFIERS environment variable) defines how the input is inserted into the given widget, e.g., onTheSpot makes the input appear directly in the widget, while overTheSpot makes the input appear in a box floating over the widget and is not inserted until the editing is done. License Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 or any later version published by the Free Software Foundation, considering as source code any files used for the production of this manpage. See also drumstick-guiplayer 1 , drumstick-vpiano 1 drumstick-1.1.3/doc/PaxHeaders.32572/drumstick-playsmf.xml.in0000644000000000000000000000013013532747316020643 xustar0029 mtime=1567346382.72199988 30 atime=1567346383.006000245 29 ctime=1567346382.72199988 drumstick-1.1.3/doc/drumstick-playsmf.xml.in0000644000175000001440000001023013532747316021432 0ustar00pedrousers00000000000000 ]> &product; Pedro Lopez-Cabanillas plcl@users.sf.net 2010-2019 Pedro Lopez-Cabanillas Jan 13, 2019 &product; 1 @VERSION@ drumstick User Commands &product; A Drumstick command line utility for playing standard MIDI files. Synopsis &product; options FILE Description This program is a Drumstick example and utility program. You can use it to play standard MIDI files without GUI controls. Arguments The following arguments are required: client:port An ALSA client:port specification that will be subscribed in order to send MIDI events to it. The client portion can be a number or a name, like in "20:0" or "KMidimon:0". The name of the input SMF. The following arguments are optional: Prints a summary of the command-line options and exit. Prints the program version number and exit. License Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 or any later version published by the Free Software Foundation, considering as source code any files used for the production of this manpage. See also drumstick-dumpmid 1 , drumstick-guiplayer 1 drumstick-1.1.3/doc/PaxHeaders.32572/drumstick-dumpove.xml.in0000644000000000000000000000013013532747316020647 xustar0029 mtime=1567346382.72199988 30 atime=1567346383.006000245 29 ctime=1567346382.72199988 drumstick-1.1.3/doc/drumstick-dumpove.xml.in0000644000175000001440000000766113532747316021454 0ustar00pedrousers00000000000000 ]> &product; Rui Fan vanferry@gmail.com 2010-2019 Rui Fan Aug 31, 2010 &product; 1 @VERSION@ drumstick User Commands &product; A Drumstick command line utility for decoding OVE (Overture) files. Synopsis &product; options FILE Description This program is a Drumstick example and utility program. You can use it to decode as text your OVE files created with Overture. Arguments The following argument is mandatory: The name of the Overture file. The following arguments are optional: Prints a summary of the command-line options and exit. Prints the program version number and exit. Verbose output. License Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 or any later version published by the Free Software Foundation, considering as source code any files used for the production of this manpage. See also drumstick-dumpsmf 1 , drumstick-dumpwrk 1 drumstick-1.1.3/doc/PaxHeaders.32572/drumstick-guiplayer.xml.in0000644000000000000000000000013013532747316021171 xustar0029 mtime=1567346382.72199988 30 atime=1567346383.006000245 29 ctime=1567346382.72199988 drumstick-1.1.3/doc/drumstick-guiplayer.xml.in0000644000175000001440000002704513532747316021774 0ustar00pedrousers00000000000000 ]> &product; Pedro Lopez-Cabanillas plcl@users.sf.net 2010-2019 Pedro Lopez-Cabanillas Jan 13, 2019 &product; 1 @VERSION@ drumstick User Commands &product; A Drumstick GUI utility for playing MIDI files. Synopsis &product; options... FILE Description This program is a Drumstick example and utility program. You can use it to play Standard MIDI Files and Cakewalk WRK files with GUI controls. Arguments The following arguments are optional: The name of the input (mid/kar/wrk/ove) file. client:port MIDI Destination Port. Prints a summary of the command-line options and exit. Prints the program version number and exit. style sets the application GUI style. Possible values are motif, windows, and platinum. If you compiled Qt with additional styles or have additional styles as plugins these will be available to the -style command line option stylesheet sets the application styleSheet. The value must be a path to a file that contains the Style Sheet. Note: Relative URLs in the Style Sheet file are relative to the Style Sheet file's path. session restores the application from an earlier session. prints debug message at the end about number of widgets left undestroyed and maximum number of widgets existed at the same time sets the application's layout direction to Qt::RightToLeft sets the backend to be used for on-screen widgets and QPixmaps. Available options are raster and opengl. display sets the X display (default is $DISPLAY). geometry sets the client geometry of the first window that is shown. font defines the application font. The font should be specified using an X logical font description. color sets the default background color and an application palette (light and dark shades are calculated). color sets the default foreground color. color sets the default button color. name sets the application name. title sets the application title. forces the application to use a TrueColor visual on an 8-bit display. count limits the number of colors allocated in the color cube on an 8-bit display, if the application is using the QApplication::ManyColor color specification. If count is 216 then a 6x6x6 color cube is used (i.e. 6 levels of red, 6 of green, and 6 of blue); for other values, a cube approximately proportional to a 2x3x1 cube is used. causes the application to install a private color map on an 8-bit display. sets the input method server (equivalent to setting the XMODIFIERS environment variable) defines how the input is inserted into the given widget, e.g., onTheSpot makes the input appear directly in the widget, while overTheSpot makes the input appear in a box floating over the widget and is not inserted until the editing is done. License Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 or any later version published by the Free Software Foundation, considering as source code any files used for the production of this manpage. See also drumstick-drumgrid 1 , drumstick-vpiano 1 drumstick-1.1.3/PaxHeaders.32572/utils0000644000000000000000000000013213532747316014356 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/0000755000175000001440000000000013532747316015224 5ustar00pedrousers00000000000000drumstick-1.1.3/utils/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316017173 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/CMakeLists.txt0000644000175000001440000000224313532747316017765 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . #include_directories( # ${CMAKE_CURRENT_SOURCE_DIR} # ${CMAKE_CURRENT_BINARY_DIR} # ${CMAKE_CURRENT_SOURCE_DIR}/common #) add_subdirectory(dumpsmf) add_subdirectory(dumpwrk) add_subdirectory(dumpove) add_subdirectory(vpiano) if(ALSA_FOUND) add_subdirectory(dumpmid) add_subdirectory(playsmf) add_subdirectory(guiplayer) add_subdirectory(sysinfo) add_subdirectory(metronome) add_subdirectory(drumgrid) endif() drumstick-1.1.3/utils/PaxHeaders.32572/drumgrid0000644000000000000000000000013213532747316016173 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/drumgrid/0000755000175000001440000000000013532747316017041 5ustar00pedrousers00000000000000drumstick-1.1.3/utils/drumgrid/PaxHeaders.32572/drumgridabout.ui0000644000000000000000000000013213532747316021457 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/drumgrid/drumgridabout.ui0000644000175000001440000001172013532747316022251 0ustar00pedrousers00000000000000 AboutClass 0 0 487 334 About false true <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600;">Drumstick Drum Grid %VERSION%</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Sample application for the <a href="http://drumstick.sourceforge.net"><span style=" font-family:'DejaVu Sans'; text-decoration: underline; color:#0057ae;">Drumstick MIDI Sequencer C++ library</span></a></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copyright © 2006-2019, Pedro Lopez-Cabanillas &lt;<a href="mailto:plcl@users.sf.net"><span style=" font-family:'DejaVu Sans'; text-decoration: underline; color:#0057ae;">plcl@users.sf.net</span></a>&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">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.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You should have received a copy of the GNU General Public License along with this program. If not, see </span><a href="http://www.gnu.org/licenses/"><span style=" text-decoration: underline; color:#0057ae;">http://www.gnu.org/licenses/</span></a><span style=" font-size:8pt;">.</span></p></body></html> true QDialogButtonBox::Close buttonBox rejected() AboutClass close() 306 315 325 335 drumstick-1.1.3/utils/drumgrid/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316021010 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/drumgrid/CMakeLists.txt0000644000175000001440000000321713532747316021604 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . find_package(Qt5Widgets REQUIRED) set(drumgrid_forms_SRCS drumgridabout.ui drumgrid.ui ) set(drumgrid_SRCS drumgridabout.cpp drumgridabout.h drumgrid.cpp drumgrid.h drumgridmodel.cpp drumgridmodel.h drumgridmain.cpp ) set(drumgrid_qtobject_SRCS drumgridabout.h drumgridmodel.h drumgrid.h ) QT5_WRAP_UI(drumgrid_ui_SRCS ${drumgrid_forms_SRCS}) QT5_WRAP_CPP(drumgrid_moc_SRCS ${drumgrid_qtobject_SRCS}) ADD_EXECUTABLE(drumstick-drumgrid ${drumgrid_ui_SRCS} ${drumgrid_moc_SRCS} ${drumgrid_SRCS} ) target_include_directories(drumstick-drumgrid PRIVATE ../common ) TARGET_LINK_LIBRARIES(drumstick-drumgrid ${ALSA_LIBS} drumstick-alsa Qt5::Widgets ) INSTALL(TARGETS drumstick-drumgrid RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) INSTALL(FILES drumstick-drumgrid.desktop DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications") drumstick-1.1.3/utils/drumgrid/PaxHeaders.32572/drumgrid.cpp0000644000000000000000000000013213532747316020571 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/drumgrid/drumgrid.cpp0000644000175000001440000002735713532747316021400 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "drumgrid.h" #include "drumgridmodel.h" #include "ui_drumgrid.h" #include "drumgridabout.h" DrumGrid::DrumGrid(QWidget *parent) : QMainWindow(parent), m_ui(new Ui::DrumGrid), m_clientId(-1), m_portId(-1), m_queueId(-1), m_tick(0), m_weak_velocity(METRONOME_VELOCITY / 2), m_strong_velocity(METRONOME_VELOCITY), m_program(METRONOME_PROGRAM), m_channel(METRONOME_CHANNEL), m_volume(METRONOME_VOLUME), m_pan(METRONOME_PAN), m_resolution(METRONOME_RESOLUTION), m_bpm(TEMPO_DEFAULT), m_noteDuration(NOTE_DURATION), m_autoconnect(false), m_playing(false), m_useNoteOff(true) { m_ui->setupUi(this); m_ui->startButton->setIcon(style()->standardIcon(QStyle::StandardPixmap(QStyle::SP_MediaPlay))); m_ui->startButton->setShortcut(Qt::Key_MediaPlay); m_ui->stopButton->setIcon(style()->standardIcon(QStyle::StandardPixmap(QStyle::SP_MediaStop))); m_ui->stopButton->setShortcut(Qt::Key_MediaStop); m_ui->tempoSlider->setMaximum(TEMPO_MAX); m_ui->tempoSlider->setMinimum(TEMPO_MIN); m_ui->tempoSlider->setValue(m_bpm); connect( m_ui->actionAbout, SIGNAL(triggered()), SLOT(slotAbout())); connect( m_ui->actionAbout_Qt, SIGNAL(triggered()), SLOT(slotAboutQt())); connect( m_ui->actionQuit, SIGNAL(triggered()), SLOT(close())); connect( m_ui->actionConnect, SIGNAL(triggered()), SLOT(connectMidi())); connect( m_ui->startButton, SIGNAL(clicked()), SLOT(play())); connect( m_ui->stopButton, SIGNAL(clicked()), SLOT(stop())); connect( m_ui->tempoSlider, SIGNAL(valueChanged(int)), SLOT(tempoChange(int))); connect( m_ui->gridColumns, SIGNAL(valueChanged(int)), SLOT(gridColumns(int))); m_model = new DrumGridModel(this); m_model->fillSampleData(); m_ui->tableView->setModel(m_model); connect ( this, SIGNAL(signalUpdate(int,int)), SLOT(updateDisplay(int,int)) ); m_mapper = new QSignalMapper(this); addShortcut(QKeySequence("f"), "f"); addShortcut(QKeySequence("p"), "p"); addShortcut(QKeySequence("1"), "1"); addShortcut(QKeySequence("2"), "2"); addShortcut(QKeySequence("3"), "3"); addShortcut(QKeySequence("4"), "4"); addShortcut(QKeySequence("5"), "5"); addShortcut(QKeySequence("6"), "6"); addShortcut(QKeySequence("7"), "7"); addShortcut(QKeySequence("8"), "8"); addShortcut(QKeySequence("9"), "9"); addShortcut(QKeySequence("0"), QString()); addShortcut(QKeySequence::Delete, QString()); connect( m_mapper, SIGNAL(mapped(QString)), SLOT(shortcutPressed(QString))); connect ( m_ui->tableView, SIGNAL(doubleClicked(const QModelIndex&)), m_model, SLOT(changeCell(const QModelIndex &)) ); m_Client = new MidiClient(this); m_Client->open(); m_Client->setClientName("DrumGrid"); connect( m_Client, SIGNAL(eventReceived(SequencerEvent*)), SLOT(sequencerEvent(SequencerEvent*)), Qt::QueuedConnection ); m_Port = new MidiPort(this); m_Port->attach( m_Client ); m_Port->setPortName("DrumGrid Output Port"); m_Port->setCapability( SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_READ ); m_Port->setPortType( SND_SEQ_PORT_TYPE_APPLICATION | SND_SEQ_PORT_TYPE_MIDI_GENERIC ); m_Queue = m_Client->createQueue("DrumGrid"); m_queueId = m_Queue->getId(); m_portId = m_Port->getPortId(); m_clientId = m_Client->getClientId(); m_Client->setRealTimeInput(false); m_Client->startSequencerInput(); readSettings(); updateView(); } DrumGrid::~DrumGrid() { foreach(QShortcut* s, m_shortcuts) delete s; m_Port->detach(); m_Client->close(); delete m_ui; } void DrumGrid::updateView() { m_ui->tableView->resizeColumnsToContents(); m_ui->tableView->resizeRowsToContents(); } void DrumGrid::subscribe(const QString& portName) { try { if (!m_subscription.isEmpty()) { m_Port->unsubscribeTo(m_subscription); m_subscription.clear(); } m_Port->subscribeTo(portName); m_subscription = portName; } catch (const SequencerError& err) { qWarning() << "SequencerError exception. Error code: " << err.code() << " (" << err.qstrError() << ")"; qWarning() << "Location: " << err.location(); } } void DrumGrid::connectMidi() { bool ok; int current; QStringList items; QListIterator it(m_Client->getAvailableOutputs()); while(it.hasNext()) { PortInfo p = it.next(); items << QString("%1:%2").arg(p.getClientName()).arg(p.getPort()); } current = items.indexOf(m_subscription); QString item = QInputDialog::getItem(this, "MIDI port subscription", "Output port:", items, current, false, &ok); if (ok && !item.isEmpty()) subscribe(item); } void DrumGrid::sequencerEvent(SequencerEvent *ev) { switch (ev->getSequencerType()) { case SND_SEQ_EVENT_USR0: metronome_pattern(ev->getTick()); m_bar++; m_beat = 0; break; case SND_SEQ_EVENT_USR1: m_beat++; emit signalUpdate(m_bar, m_beat-1); break; } delete ev; } void DrumGrid::play() { metronome_set_tempo(); metronome_start(); } void DrumGrid::stop() { metronome_stop(); } void DrumGrid::tempoChange(int newTempo) { QString tip = QString::number(newTempo); m_bpm = newTempo; metronome_set_tempo(); m_ui->tempoSlider->setToolTip(tip); QToolTip::showText(QCursor::pos(), tip, this); } void DrumGrid::gridColumns(int columns) { m_model->updatePatternColumns(columns); updateView(); } void DrumGrid::shortcutPressed(const QString& value) { QModelIndex index = m_ui->tableView->currentIndex(); m_model->changeCell(index, value); } void DrumGrid::addShortcut(const QKeySequence& key, const QString& value) { QShortcut* shortcut = new QShortcut(key, m_ui->tableView); connect (shortcut, SIGNAL(activated()), m_mapper, SLOT(map())); m_mapper->setMapping(shortcut, value); m_shortcuts.append(shortcut); } void DrumGrid::readSettings() { QSettings settings; settings.beginGroup(QSTR_WINDOW); restoreGeometry(settings.value(QSTR_GEOMETRY).toByteArray()); restoreState(settings.value(QSTR_STATE).toByteArray()); settings.endGroup(); settings.beginGroup(QSTR_MIDI); QString midiConn = settings.value(QSTR_CONNECTION).toString(); m_bpm = settings.value(QSTR_TEMPO, TEMPO_DEFAULT).toInt(); settings.endGroup(); if (midiConn.length() > 0) { subscribe(midiConn); } settings.beginGroup(QSTR_PATTERN); QStringList keys = settings.allKeys(); if (!keys.empty()) { keys.sort(); m_model->clearPattern(); foreach(const QString& key, keys) { QStringList row = settings.value(key).toStringList(); m_model->addPatternData(key.toInt(), row); } m_model->endOfPattern(); } settings.endGroup(); } void DrumGrid::writeSettings() { QSettings settings; settings.clear(); settings.beginGroup(QSTR_WINDOW); settings.setValue(QSTR_GEOMETRY, saveGeometry()); settings.setValue(QSTR_STATE, saveState()); settings.endGroup(); settings.beginGroup(QSTR_MIDI); settings.setValue(QSTR_CONNECTION, m_subscription); settings.setValue(QSTR_TEMPO, m_bpm); settings.endGroup(); settings.beginGroup(QSTR_PATTERN); for(int r = 0; r < m_model->rowCount(); ++r) { settings.setValue( m_model->patternKey(r), m_model->patternData(r) ); } settings.endGroup(); settings.sync(); } void DrumGrid::closeEvent( QCloseEvent *event ) { writeSettings(); event->accept(); } void DrumGrid::metronome_event_output(SequencerEvent* ev) { ev->setSource(m_portId); ev->setSubscribers(); ev->setDirect(); m_Client->outputDirect(ev); } void DrumGrid::sendControlChange(int cc, int value) { ControllerEvent ev(m_channel, cc, value); metronome_event_output(&ev); } void DrumGrid::sendInitialControls() { metronome_set_program(); metronome_set_controls(); metronome_set_tempo(); } void DrumGrid::metronome_set_program() { ProgramChangeEvent ev(m_channel, m_program); metronome_event_output(&ev); } void DrumGrid::metronome_schedule_event(SequencerEvent* ev, int tick) { ev->setSource(m_portId); if (ev->getSequencerType() >= SND_SEQ_EVENT_USR0) ev->setDestination(m_clientId, m_portId); else ev->setSubscribers(); ev->scheduleTick(m_queueId, tick, false); m_Client->outputDirect(ev); } void DrumGrid::metronome_note(int note, int vel, int tick) { if (m_useNoteOff) { NoteEvent ev(m_channel, note, vel, m_noteDuration); metronome_schedule_event(&ev, tick); } else { NoteOnEvent ev(m_channel, note, vel); metronome_schedule_event(&ev, tick); } } void DrumGrid::metronome_echo(int tick, int ev_type) { SystemEvent ev(ev_type); metronome_schedule_event(&ev, tick); } int DrumGrid::decodeVelocity(const QString drumVel) { const qreal f = 127.0 / 9.0; int num = 0; bool isNum = false; if (drumVel.isEmpty()) return 0; if (drumVel == "f") return m_strong_velocity; else if (drumVel == "p") return m_weak_velocity; num = drumVel.toInt(&isNum); if (isNum) return qRound(f * num); return 0; } void DrumGrid::metronome_pattern(int tick) { int i, j, t, duration, key, vel; t = tick; duration = m_resolution / 4; for(i=0; icolumnCount(); ++i) { for(j=0; jrowCount(); ++j) { QString n = m_model->patternHit(j, i); if (!n.isEmpty()) { key = m_model->patternKey(j).toInt(); vel = decodeVelocity(n); metronome_note(key, vel, t); } } metronome_echo(t, SND_SEQ_EVENT_USR1); t += duration; } metronome_echo(t, SND_SEQ_EVENT_USR0); } void DrumGrid::metronome_set_tempo() { QueueTempo t = m_Queue->getTempo(); t.setPPQ(m_resolution); t.setNominalBPM(m_bpm); m_Queue->setTempo(t); m_Client->drainOutput(); } void DrumGrid::metronome_set_controls() { sendControlChange(VOLUME_CC, m_volume); sendControlChange(PAN_CC, m_pan); } void DrumGrid::metronome_start() { m_Queue->start(); m_patternDuration = m_resolution * m_model->columnCount() / 4; metronome_pattern(0); m_bar = 1; m_beat = 0; m_playing = true; } void DrumGrid::metronome_stop() { m_Queue->stop(); m_playing = false; } void DrumGrid::updateDisplay(int /*bar*/, int beat) { m_ui->tableView->selectColumn(beat); } void DrumGrid::slotAbout() { dlgAbout.exec(); } void DrumGrid::slotAboutQt() { qApp->aboutQt(); } drumstick-1.1.3/utils/drumgrid/PaxHeaders.32572/drumgrid.ui0000644000000000000000000000013213532747316020424 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/drumgrid/drumgrid.ui0000644000175000001440000000652313532747316021223 0ustar00pedrousers00000000000000 DrumGrid 0 0 596 396 Drumstick Drum Grid QFrame::StyledPanel QFrame::Raised 2 64 16 start stop 10 250 100 Qt::Horizontal 0 0 596 25 File Help Connect... Quit About About Qt drumstick-1.1.3/utils/drumgrid/PaxHeaders.32572/drumgrid.pro0000644000000000000000000000013213532747316020607 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/drumgrid/drumgrid.pro0000644000175000001440000000075413532747316021406 0ustar00pedrousers00000000000000TEMPLATE = app TARGET = drumstick-drumgrid QT += gui widgets #dbus CONFIG += qt thread exceptions static { CONFIG += link_prl } DESTDIR = ../../build/bin INCLUDEPATH += . ../../library/include ../common LIBS = -L../../build/lib -ldrumstick-alsa -lasound include (../../global.pri) SOURCES += drumgridabout.cpp \ drumgridmain.cpp \ drumgrid.cpp \ drumgridmodel.cpp HEADERS += drumgridabout.h \ drumgrid.h \ drumgridmodel.h FORMS += drumgridabout.ui \ drumgrid.ui drumstick-1.1.3/utils/drumgrid/PaxHeaders.32572/drumgrid.h0000644000000000000000000000013213532747316020236 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/drumgrid/drumgrid.h0000644000175000001440000000720013532747316021026 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DRUMGRID_H #define DRUMGRID_H #include "drumgridabout.h" #include #include #include #include const QString QSTR_WINDOW("Window"); const QString QSTR_GEOMETRY("Geometry"); const QString QSTR_STATE("State"); const QString QSTR_MIDI("MIDI"); const QString QSTR_CONNECTION("Connection"); const QString QSTR_TEMPO("Tempo"); const QString QSTR_PATTERN("Pattern"); const int TEMPO_MIN(25); const int TEMPO_MAX(250); const int TEMPO_DEFAULT(120); const int NOTE_DURATION(10); const int METRONOME_CHANNEL(9); const int METRONOME_VELOCITY(100); const int METRONOME_PROGRAM(0); const int METRONOME_RESOLUTION(120); const int METRONOME_VOLUME(100); const int METRONOME_PAN(64); const int VOLUME_CC(7); const int PAN_CC(10); namespace Ui { class DrumGrid; } namespace drumstick { class MidiClient; class MidiPort; class MidiQueue; class SequencerEvent; } class DrumGridModel; using namespace drumstick; class DrumGrid : public QMainWindow { Q_OBJECT public: DrumGrid(QWidget *parent = nullptr); ~DrumGrid(); void subscribe(const QString& portName); void addShortcut(const QKeySequence& key, const QString& value); void readSettings(); void writeSettings(); void closeEvent( QCloseEvent *event ); void metronome_start(); void metronome_stop(); void metronome_continue(); void sendControlChange(int cc, int value); void sendInitialControls(); void metronome_set_controls(); void metronome_set_program(); void metronome_set_tempo(); void metronome_pattern(int tick); void metronome_echo(int tick, int ev_type); void metronome_note(int note, int vel, int tick); void metronome_schedule_event(SequencerEvent* ev, int tick); void metronome_event_output(SequencerEvent* ev); int decodeVelocity(const QString drumVel); public slots: void slotAbout(); void slotAboutQt(); void updateView(); void sequencerEvent(SequencerEvent *ev); void connectMidi(); void play(); void stop(); void tempoChange(int newTempo); void gridColumns(int columns); void shortcutPressed(const QString& value); void updateDisplay(int bar, int beat); signals: void signalUpdate(int bar, int beat); private: Ui::DrumGrid *m_ui; int m_clientId; int m_portId; int m_queueId; unsigned long m_tick; MidiClient* m_Client; MidiPort* m_Port; MidiQueue* m_Queue; DrumGridModel* m_model; QString m_subscription; QSignalMapper* m_mapper; QVector m_shortcuts; About dlgAbout; int m_bar; int m_beat; int m_weak_velocity; int m_strong_velocity; int m_program; int m_channel; int m_volume; int m_pan; int m_resolution; int m_bpm; int m_noteDuration; int m_patternDuration; bool m_autoconnect; bool m_playing; bool m_useNoteOff; }; #endif // DRUMGRID_H drumstick-1.1.3/utils/drumgrid/PaxHeaders.32572/drumgridmodel.cpp0000644000000000000000000000013213532747316021612 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/drumgrid/drumgridmodel.cpp0000644000175000001440000001167713532747316022417 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "drumgridmodel.h" #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) #include #else #include #endif const QString DEFVAL("f"); DrumGridModel::DrumGridModel(QObject *parent) : QAbstractTableModel(parent), m_columns(16), m_lastValue(DEFVAL) { m_modelData.clear(); m_keys.clear(); loadKeyNames(); } void DrumGridModel::loadKeyNames() { m_keyNames.clear(); m_keyNames[46] = QLatin1String("Open HH"); m_keyNames[42] = QLatin1String("Closed HH"); m_keyNames[39] = QLatin1String("Hand Claps"); m_keyNames[38] = QLatin1String("Snare Drum"); m_keyNames[36] = QLatin1String("Bass Drum"); } void DrumGridModel::fillSampleData() { beginInsertRows(QModelIndex(), 0, 4); m_modelData.insert(0, QString(",p,,,,p,,,,p,,,,p,,").split(",")); m_modelData.insert(1, QString("f,,,p,f,,,p,f,,,p,f,,,p").split(",")); m_modelData.insert(2, QString(",,,,,,,,,,,,,4,4,").split(",")); m_modelData.insert(3, QString(",,,,f,,,,,,,,f,,,").split(",")); m_modelData.insert(4, QString("f,,,,p,,,,f,,,,p,,,").split(",")); m_keys.insert(0, 46); m_keys.insert(1, 42); m_keys.insert(2, 39); m_keys.insert(3, 38); m_keys.insert(4, 36); endInsertRows(); } int DrumGridModel::rowCount(const QModelIndex & /* parent */) const { return m_modelData.size(); } int DrumGridModel::columnCount(const QModelIndex & /* parent */) const { return m_columns; } QVariant DrumGridModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || role != Qt::DisplayRole) return QVariant(); return m_modelData[index.row()][index.column()].trimmed(); } QVariant DrumGridModel::headerData(int section , Qt::Orientation orientation, int role) const { if (role == Qt::DisplayRole) { if ( orientation == Qt::Horizontal ) { int m = section % 10; if (m == 9) m = 0; else m++; return QString::number(m); } else { int k = m_keys.value(section, 0); if (m_keyNames.contains(k)) return m_keyNames[k]; } } return QVariant(); } void DrumGridModel::changeCell(const QModelIndex &index) { QString after, before = m_modelData[index.row()][index.column()]; if (before.isEmpty()) after = m_lastValue; else after = QString(); changeCell(index, after); } void DrumGridModel::changeCell(const QModelIndex &index, const QString& newValue) { m_lastValue = m_modelData[index.row()][index.column()] = newValue; emit dataChanged(index, index); } QStringList DrumGridModel::patternData(int row) { return m_modelData.value(row, QStringList()); } QString DrumGridModel::patternKey(int row) { return QString::number(m_keys.value(row, 0)); } void DrumGridModel::clearPattern() { beginRemoveRows(QModelIndex(), 0, rowCount()); m_modelData.clear(); m_keys.clear(); m_tempData.clear(); m_tempKeys.clear(); endRemoveRows(); } void DrumGridModel::addPatternData(int key, const QStringList& row) { m_tempKeys.prepend(key); m_tempData.prepend(row); } void DrumGridModel::endOfPattern() { beginInsertRows(QModelIndex(), 0, m_tempData.size()); m_keys = m_tempKeys; m_modelData = m_tempData; endInsertRows(); } void DrumGridModel::updatePatternColumns(int columns) { int diff = m_columns - columns; if (diff == 0) return; if (diff > 0) { beginRemoveColumns(QModelIndex(), columns, m_columns-1); for(int i=0; i columns ) m_modelData[i].removeLast(); } else { beginInsertColumns(QModelIndex(), columns, columns-diff-1); for(int i=0; i 0) endRemoveColumns(); else endInsertColumns(); } QString DrumGridModel::patternHit(int row, int col) { if ((col < m_columns) && (row < m_modelData.size())) return m_modelData[row][col].trimmed(); return QString(); } drumstick-1.1.3/utils/drumgrid/PaxHeaders.32572/drumstick-drumgrid.desktop0000644000000000000000000000013213532747316023463 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/drumgrid/drumstick-drumgrid.desktop0000644000175000001440000000040613532747316024254 0ustar00pedrousers00000000000000[Desktop Entry] Name=Drumstick Drum Grid Exec=drumstick-drumgrid Icon=drumstick Terminal=false Type=Application Categories=AudioVideo;Audio;Midi;Education;Music; Keywords=Music;Midi;Drum;Grid; Comment=Drumstick Drum Grid Comment[es]=Caja de Ritmos de Drumstick drumstick-1.1.3/utils/drumgrid/PaxHeaders.32572/drumgridabout.h0000644000000000000000000000013213532747316021271 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/drumgrid/drumgridabout.h0000644000175000001440000000176113532747316022067 0ustar00pedrousers00000000000000/* Drumgrid test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef ABOUT_H #define ABOUT_H #include #include "ui_drumgridabout.h" class About : public QDialog { Q_OBJECT public: About(QWidget *parent = 0); private: Ui::AboutClass ui; }; #endif // ABOUT_H drumstick-1.1.3/utils/drumgrid/PaxHeaders.32572/drumgridmain.cpp0000644000000000000000000000013213532747316021436 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/drumgrid/drumgridmain.cpp0000644000175000001440000000474113532747316022235 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include "cmdversion.h" #include "drumgrid.h" const QString QSTR_APPNAME("DrumGrid"); const QString QSTR_DOMAIN("drumstick.sourceforge.net"); const QString PGM_DESCRIPTION("Drumstick Drum Grid"); const QString errorstr = "Fatal error from the ALSA sequencer. " "This usually happens when the kernel doesn't have ALSA support, " "or the device node (/dev/snd/seq) doesn't exists, " "or the kernel module (snd_seq) is not loaded. " "Please check your ALSA/MIDI configuration."; int main(int argc, char *argv[]) { QCoreApplication::setOrganizationName(QSTR_DOMAIN); QCoreApplication::setOrganizationDomain(QSTR_DOMAIN); QCoreApplication::setApplicationName(QSTR_APPNAME); QCoreApplication::setApplicationVersion(PGM_VERSION); QApplication app(argc, argv); QCommandLineParser parser; parser.setApplicationDescription(PGM_DESCRIPTION); auto helpOption = parser.addHelpOption(); auto versionOption = parser.addVersionOption(); QCommandLineOption portOption({"p", "port"}, "MIDI Out Port.", "client:port"); parser.addOption(portOption); parser.process(app); if (parser.isSet(versionOption) || parser.isSet(helpOption)) { return 0; } try { DrumGrid w; if (parser.isSet(portOption)) { QString port = parser.value(portOption); w.subscribe(port); } w.show(); return app.exec(); } catch (const SequencerError& ex) { QMessageBox::critical(nullptr, "Error", errorstr + " Returned error was: " + ex.qstrError() ); } catch (...) { qWarning() << errorstr; } return 0; } drumstick-1.1.3/utils/drumgrid/PaxHeaders.32572/drumgridabout.cpp0000644000000000000000000000013213532747316021624 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/drumgrid/drumgridabout.cpp0000644000175000001440000000204413532747316022415 0ustar00pedrousers00000000000000/* Drumgrid test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "drumgridabout.h" #include "cmdversion.h" About::About(QWidget *parent) : QDialog(parent) { ui.setupUi(this); QString aboutText = ui.AboutTextView->toHtml(); aboutText.replace("%VERSION%", PGM_VERSION); ui.AboutTextView->setHtml(aboutText); } drumstick-1.1.3/utils/drumgrid/PaxHeaders.32572/drumgridmodel.h0000644000000000000000000000013213532747316021257 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/drumgrid/drumgridmodel.h0000644000175000001440000000371113532747316022052 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DRUMGRIDMODEL_H #define DRUMGRIDMODEL_H #include #include class DrumGridModel : public QAbstractTableModel { Q_OBJECT public: DrumGridModel(QObject *parent = 0); int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; void loadKeyNames(); void fillSampleData(); void clearPattern(); void addPatternData(int key, const QStringList& row); void endOfPattern(); QStringList patternData(int row); QString patternKey(int row); QString patternHit(int row, int col); void updatePatternColumns(int columns); public slots: void changeCell(const QModelIndex &index); void changeCell(const QModelIndex &index, const QString& newValue); private: int m_columns; QString m_lastValue; QMap m_keyNames; QList m_modelData; QList m_tempData; QList m_keys; QList m_tempKeys; }; #endif /* DRUMGRIDMODEL_H */ drumstick-1.1.3/utils/PaxHeaders.32572/metronome0000644000000000000000000000013213532747316016363 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/metronome/0000755000175000001440000000000013532747316017231 5ustar00pedrousers00000000000000drumstick-1.1.3/utils/metronome/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316021200 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/metronome/CMakeLists.txt0000644000175000001440000000240413532747316021771 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . SET(metronome_SRCS metronome.cpp metronome.h ) SET(metronome_qtobject_SRCS metronome.h ) QT5_WRAP_CPP(metronome_moc_SRCS ${metronome_qtobject_SRCS}) ADD_EXECUTABLE(drumstick-metronome ${metronome_moc_SRCS} ${metronome_SRCS} ) target_include_directories(drumstick-metronome PRIVATE ../common ) TARGET_LINK_LIBRARIES(drumstick-metronome ${ALSA_LIBS} drumstick-alsa Qt5::Core ) # we should install some files... INSTALL(TARGETS drumstick-metronome RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) drumstick-1.1.3/utils/metronome/PaxHeaders.32572/metronome.h0000644000000000000000000000013213532747316020616 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/metronome/metronome.h0000644000175000001440000000540113532747316021407 0ustar00pedrousers00000000000000/* Standard MIDI simple metronome Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef METRONOME_H #define METRONOME_H #include #include #include #include #include #include #include #include const int TEMPO_DEFAULT(120); const int NOTE_DURATION(10); const int RHYTHM_TS_NUM(4); const int RHYTHM_TS_DEN(4); const int METRONOME_CHANNEL(9); const int METRONOME_STRONG_NOTE(34); const int METRONOME_WEAK_NOTE(33); const int METRONOME_VELOCITY(100); const int METRONOME_PROGRAM(0); const int METRONOME_RESOLUTION(240); const int METRONOME_VOLUME(100); const int METRONOME_PAN(64); using namespace drumstick; class Metronome : public QObject, public SequencerEventHandler { Q_OBJECT public: Metronome(QObject *parent = 0); virtual ~Metronome(); void play(QString tempo); bool stopped(); void stop(); void subscribe(const QString& portName); void shutupSound(); void sendControlChange( int cc, int value ); void sendInitialControls(); void metronome_note(int note, int tick); void metronome_echo(int tick); void metronome_pattern(int tick); void metronome_event_output(SequencerEvent* ev); void metronome_schedule_event(SequencerEvent* ev, int tick, bool lb); void metronome_set_program(); void metronome_set_tempo(); void metronome_set_controls(); // SequencerEventHandler interface void handleSequencerEvent( SequencerEvent* ev ); private: int m_weak_note; int m_strong_note; int m_weak_velocity; int m_strong_velocity; int m_program; int m_channel; int m_volume; int m_pan; int m_resolution; int m_bpm; int m_ts_num; /* time signature: numerator */ int m_ts_div; /* time signature: denominator */ int m_noteDuration; int m_patternDuration; int m_portId; int m_queueId; int m_clientId; bool m_Stopped; QReadWriteLock m_mutex; MidiClient* m_Client; MidiPort* m_Port; MidiQueue* m_Queue; }; #endif /*METRONOME_H*/ drumstick-1.1.3/utils/metronome/PaxHeaders.32572/metronome.pro0000644000000000000000000000013213532747316021167 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/metronome/metronome.pro0000644000175000001440000000052313532747316021760 0ustar00pedrousers00000000000000TEMPLATE = app TARGET = drumstick-metronome #QT += dbus CONFIG += qt console thread exceptions static { CONFIG += link_prl } DESTDIR = ../../build/bin INCLUDEPATH += . ../../library/include ../common LIBS = -L../../build/lib -ldrumstick-alsa -lasound include (../../global.pri) # Input HEADERS += metronome.h SOURCES += metronome.cpp drumstick-1.1.3/utils/metronome/PaxHeaders.32572/metronome.cpp0000644000000000000000000000013213532747316021151 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/metronome/metronome.cpp0000644000175000001440000002042413532747316021744 0ustar00pedrousers00000000000000/* Standard MIDI simple metronome Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include "metronome.h" #include "cmdversion.h" const QString PGM_NAME("drumstick-metronome"); const QString PGM_DESCRIPTION("ALSA based command line metronome"); static QTextStream cout(stdout, QIODevice::WriteOnly); static QTextStream cerr(stderr, QIODevice::WriteOnly); /* *************** * * Metronome class * * *************** */ Metronome::Metronome(QObject *parent) : QObject(parent), m_weak_note(METRONOME_WEAK_NOTE), m_strong_note(METRONOME_STRONG_NOTE), m_weak_velocity(METRONOME_VELOCITY), m_strong_velocity(METRONOME_VELOCITY), m_program(METRONOME_PROGRAM), m_channel(METRONOME_CHANNEL), m_volume(METRONOME_VOLUME), m_pan(METRONOME_PAN), m_resolution(METRONOME_RESOLUTION), m_bpm(TEMPO_DEFAULT), m_ts_num(RHYTHM_TS_NUM), m_ts_div(RHYTHM_TS_DEN), m_noteDuration(NOTE_DURATION), m_portId(-1), m_queueId(-1), m_clientId(-1), m_Stopped(true) { QLatin1String name("Metronome"); m_Client = new MidiClient(this); m_Client->open(); m_Client->setClientName(name); m_Client->setHandler(this); m_Port = new MidiPort(this); m_Port->attach( m_Client ); m_Port->setPortName(name); m_Port->setCapability( SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ | SND_SEQ_PORT_CAP_WRITE ); m_Port->setPortType( SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION ); m_Queue = m_Client->createQueue(name); m_clientId = m_Client->getClientId(); m_queueId = m_Queue->getId(); m_portId = m_Port->getPortId(); m_Port->setTimestamping(true); m_Port->setTimestampQueue(m_queueId); // Get and apply the best available timer TimerId best = Timer::bestGlobalTimerId(); QueueTimer qtimer; qtimer.setId(best); m_Queue->setTimer(qtimer); // Start sequencer input m_Client->setRealTimeInput(false); m_Client->startSequencerInput(); } Metronome::~Metronome() { m_Port->detach(); m_Client->close(); } void Metronome::handleSequencerEvent( SequencerEvent *ev ) { if (ev->getSequencerType() == SND_SEQ_EVENT_USR0) metronome_pattern(static_cast(ev->getTick()) + m_patternDuration); delete ev; } void Metronome::metronome_event_output(SequencerEvent* ev) { ev->setSource(static_cast(m_portId)); ev->setSubscribers(); ev->setDirect(); m_Client->outputDirect(ev); } void Metronome::sendControlChange(int cc, int value) { ControllerEvent ev(m_channel, cc, value); metronome_event_output(&ev); } void Metronome::sendInitialControls() { metronome_set_program(); metronome_set_controls(); metronome_set_tempo(); } void Metronome::metronome_set_program() { ProgramChangeEvent ev(m_channel, m_program); metronome_event_output(&ev); } void Metronome::metronome_schedule_event(SequencerEvent* ev, int tick, bool lb) { ev->setSource(static_cast(m_portId)); if (lb) // loop back ev->setDestination(static_cast(m_clientId), static_cast(m_portId)); else ev->setSubscribers(); ev->scheduleTick(m_queueId, tick, false); m_Client->outputDirect(ev); } void Metronome::metronome_note(int note, int tick) { NoteEvent ev(m_channel, note, METRONOME_VELOCITY, m_noteDuration); metronome_schedule_event(&ev, tick, false); } void Metronome::metronome_echo(int tick) { SystemEvent ev(SND_SEQ_EVENT_USR0); metronome_schedule_event(&ev, tick, true); } void Metronome::metronome_pattern(int tick) { int j, t, duration; t = tick; duration = m_resolution * 4 / m_ts_div; for (j = 0; j < m_ts_num; j++) { metronome_note(j ? m_weak_note : m_strong_note, t); t += duration; } metronome_echo(t); } void Metronome::metronome_set_tempo() { QueueTempo t = m_Queue->getTempo(); t.setPPQ(m_resolution); t.setNominalBPM(m_bpm); m_Queue->setTempo(t); m_Client->drainOutput(); } void Metronome::metronome_set_controls() { sendControlChange(MIDI_CTL_MSB_MAIN_VOLUME, m_volume); sendControlChange(MIDI_CTL_MSB_PAN, m_pan); } void Metronome::subscribe(const QString& portName) { m_Port->subscribeTo(portName); } bool Metronome::stopped() { QReadLocker locker(&m_mutex); return m_Stopped; } void Metronome::stop() { QWriteLocker locker(&m_mutex); m_Stopped = true; m_Client->dropOutput(); } void Metronome::shutupSound() { sendControlChange( MIDI_CTL_ALL_NOTES_OFF, 0 ); sendControlChange( MIDI_CTL_ALL_SOUNDS_OFF, 0 ); } void Metronome::play(QString tempo) { bool ok; m_Stopped = false; m_patternDuration = m_resolution * 4 / m_ts_div * m_ts_num; m_bpm = tempo.toInt(&ok); if (!ok) m_bpm = TEMPO_DEFAULT; cout << "Metronome playing. " << m_bpm << " bpm" << endl; cout << "Press Ctrl+C to exit" << endl; try { sendInitialControls(); m_Queue->start(); metronome_pattern(0); metronome_pattern(m_patternDuration); while (!stopped()) sleep(1); } catch (const SequencerError& err) { cerr << "SequencerError exception. Error code: " << err.code() << " (" << err.qstrError() << ")" << endl; cerr << "Location: " << err.location() << endl; } } static Metronome* metronome = nullptr; void signalHandler(int sig) { if (sig == SIGINT) qDebug() << "Caught a SIGINT. Exiting"; else if (sig == SIGTERM) qDebug() << "Caught a SIGTERM. Exiting"; if (metronome != nullptr) { metronome->stop(); metronome->shutupSound(); } } int main(int argc, char **argv) { const QString errorstr = "Fatal error from the ALSA sequencer. " "This usually happens when the kernel doesn't have ALSA support, " "or the device node (/dev/snd/seq) doesn't exists, " "or the kernel module (snd_seq) is not loaded. " "Please check your ALSA/MIDI configuration."; signal(SIGINT, signalHandler); signal(SIGTERM, signalHandler); QCoreApplication app(argc, argv); QCoreApplication::setApplicationName(PGM_NAME); QCoreApplication::setApplicationVersion(PGM_VERSION); QCommandLineParser parser; parser.setApplicationDescription(PGM_DESCRIPTION); auto helpOption = parser.addHelpOption(); auto versionOption = parser.addVersionOption(); QCommandLineOption portOption({"p","port"}, "Destination, MIDI port identifier.", "client:port"); parser.addOption(portOption); QCommandLineOption bpmOption({"b","bpm"}, "Tempo, in beats per minute (default=120).", "BPM", "120"); parser.addOption(bpmOption); parser.process(app); if (parser.isSet(versionOption) || parser.isSet(helpOption)) { return 0; } try { metronome = new Metronome(); if (parser.isSet(portOption)) { QString port = parser.value(portOption); metronome->subscribe(port); } else { cerr << "Destination Port is mandatory" << endl; parser.showHelp(); } QString bpm("120"); if (parser.isSet(bpmOption)) { bpm = parser.value(bpmOption); } metronome->play(bpm); } catch (const SequencerError& ex) { cerr << errorstr + " Returned error was: " + ex.qstrError() << endl; } catch (...) { cerr << errorstr << endl; } delete metronome; return 0; } drumstick-1.1.3/utils/PaxHeaders.32572/Info.plist.app0000644000000000000000000000013213532747316017162 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/Info.plist.app0000644000175000001440000000231313532747316017752 0ustar00pedrousers00000000000000 NSPrincipalClass NSApplication CFBundleIconFile @ICON@ CFBundlePackageType APPL CFBundleGetInfoString Created by Qt/QMake CFBundleInfoDictionaryVersion 6.0 CFBundleDisplayName Sample Drumstick Application CFBundleSignature @TYPEINFO@ CFBundleExecutable @EXECUTABLE@ CFBundleIdentifier @BUNDLEIDENTIFIER@ CFBundleVersion @FULL_VERSION@ CFBundleShortVersionString @FULL_VERSION@ NSHumanReadableCopyright © 2006-2018, Pedro López-Cabanillas and others NSHighResolutionCapable True NOTE This file was generated by Qt/QMake. drumstick-1.1.3/utils/PaxHeaders.32572/sysinfo0000644000000000000000000000013213532747316016050 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/sysinfo/0000755000175000001440000000000013532747316016716 5ustar00pedrousers00000000000000drumstick-1.1.3/utils/sysinfo/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316020665 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/sysinfo/CMakeLists.txt0000644000175000001440000000207713532747316021464 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . SET(sysinfo_SRCS sysinfo.cpp ) ADD_EXECUTABLE(drumstick-sysinfo ${sysinfo_SRCS} ) target_include_directories(drumstick-sysinfo PRIVATE ../common ) TARGET_LINK_LIBRARIES(drumstick-sysinfo ${ALSA_LIBS} drumstick-alsa Qt5::Core ) INSTALL(TARGETS drumstick-sysinfo RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) drumstick-1.1.3/utils/sysinfo/PaxHeaders.32572/sysinfo.cpp0000644000000000000000000000013213532747316020323 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/sysinfo/sysinfo.cpp0000644000175000001440000002170313532747316021117 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include "cmdversion.h" const QString PGM_NAME("drumstick-sysinfo"); const QString PGM_DESCRIPTION("ALSA Sequencer System Info"); static QTextStream cout(stdout, QIODevice::WriteOnly); static QTextStream cerr(stderr, QIODevice::WriteOnly); using namespace drumstick; void queryTimers() { cout << endl << "ALSA Timers" << endl; TimerQuery* query = new TimerQuery("hw", 0); cout << "type___ Name________________ c/s/C/D/S Freq." << endl; TimerIdList lst = query->getTimers(); TimerIdList::ConstIterator it; for( it = lst.constBegin(); it != lst.constEnd(); ++it ) { TimerId id = *it; try { Timer* timer = new Timer(id, SND_TIMER_OPEN_NONBLOCK); TimerInfo info = timer->getTimerInfo(); cout << qSetFieldWidth(8) << left << info.getId() << qSetFieldWidth(20) << left << info.getName().left(20) << qSetFieldWidth(0) << " " << id.getClass() << "/" << id.getSlaveClass() << "/" << id.getCard() << "/" << id.getDevice() << "/" << id.getSubdevice() << " "; if( info.isSlave() ) { cout << "SLAVE"; } else { long freq = info.getFrequency(); cout << freq << " Hz"; } cout << endl; delete timer; } catch (const SequencerError& err) { cerr << "Error opening timer:" << err.qstrError(); } } delete query; } void queryQueues(MidiClient* c) { cout << endl << "ALSA Queues" << endl; cout << "id Queue_Name__________ Timer_Name__________ owner status " << " state PPQ Tempo BPM Ticks Time" << endl; QList queues = c->getAvailableQueues(); foreach( int q, queues ) { MidiQueue* queue = new MidiQueue(c, q); if (queue != nullptr) { QueueInfo qinfo = queue->getInfo(); QueueStatus qsts = queue->getStatus(); QueueTempo qtmp = queue->getTempo(); QueueTimer qtmr = queue->getTimer(); TimerId tid(qtmr.getId()); QString tname; try { Timer* timer = new Timer(tid, SND_TIMER_OPEN_NONBLOCK); TimerInfo tinfo = timer->getTimerInfo(); tname = tinfo.getName(); delete timer; } catch (...) { tname = "inaccessible"; } cout << qSetFieldWidth(3) << left << qinfo.getId() << qSetFieldWidth(20) << qinfo.getName().left(20) << qSetFieldWidth(0) << " " << qSetFieldWidth(20) << tname.left(20) << qSetFieldWidth(6) << right << qinfo.getOwner() << qSetFieldWidth(7) << (qinfo.isLocked() ? "locked" : "free") << qSetFieldWidth(8) << (qsts.isRunning() ? "running" : "stopped") << qSetFieldWidth(4) << qtmp.getPPQ() << qSetFieldWidth(7) << qtmp.getRealBPM() << qSetFieldWidth(4) << qtmp.getNominalBPM() << qSetFieldWidth(8) << qsts.getTickTime() << qSetFieldWidth(0) << " " << qsts.getClockTime() << endl; delete queue; } } } QString clientTypeName(snd_seq_client_type_t ctype) { if (ctype == SND_SEQ_USER_CLIENT) return "User"; if (ctype == SND_SEQ_KERNEL_CLIENT) return "Kernel"; return "Unknown"; } QString portTypeNames(int ptype) { QStringList lst; if ((ptype & SND_SEQ_PORT_TYPE_HARDWARE) != 0) lst << "Hardware"; if ((ptype & SND_SEQ_PORT_TYPE_SOFTWARE) != 0) lst << "Software"; if ((ptype & SND_SEQ_PORT_TYPE_PORT) != 0) lst << "Port"; if ((ptype & SND_SEQ_PORT_TYPE_DIRECT_SAMPLE) != 0) lst << "Direct Sample"; if ((ptype & SND_SEQ_PORT_TYPE_MIDI_GENERIC) != 0) lst << "MIDI Generic"; if ((ptype & SND_SEQ_PORT_TYPE_MIDI_GM) != 0) lst << "GM"; if ((ptype & SND_SEQ_PORT_TYPE_MIDI_GM2) != 0) lst << "GM2"; if ((ptype & SND_SEQ_PORT_TYPE_MIDI_GS) != 0) lst << "GS"; if ((ptype & SND_SEQ_PORT_TYPE_MIDI_MT32) != 0) lst << "MT32"; if ((ptype & SND_SEQ_PORT_TYPE_MIDI_XG) != 0) lst << "XG"; if ((ptype & SND_SEQ_PORT_TYPE_SAMPLE) != 0) lst << "Sample"; if ((ptype & SND_SEQ_PORT_TYPE_SPECIFIC) != 0) lst << "Specific"; if ((ptype & SND_SEQ_PORT_TYPE_SYNTH) != 0) lst << "Synth"; if ((ptype & SND_SEQ_PORT_TYPE_APPLICATION) != 0) lst << "Application"; if ((ptype & SND_SEQ_PORT_TYPE_SYNTHESIZER) != 0) lst << "Synthesizer"; return " (" + lst.join(", ") + ")"; } QString subsNames(SubscribersList& subs) { QStringList lst; foreach( Subscriber s, subs ) { QString sname = QString("%1:%2").arg(static_cast(s.getAddr()->client)) .arg(static_cast(s.getAddr()->port)); lst << sname; } return lst.join(", "); } void queryClients(MidiClient* c) { cout << endl << "ALSA Sequencer clients" << endl; ClientInfoList clients = c->getAvailableClients(); foreach( ClientInfo cinfo, clients ) { PortInfoList plist = cinfo.getPorts(); cout << "Client " << qSetFieldWidth(4) << left << cinfo.getClientId() << qSetFieldWidth(0) << " : \"" << cinfo.getName() << "\" [" << clientTypeName(cinfo.getClientType()) << "]" << endl; foreach( PortInfo pinfo, plist ) { SubscribersList to = pinfo.getReadSubscribers(); SubscribersList from = pinfo.getWriteSubscribers(); cout << " Port " << qSetFieldWidth(4) << right << pinfo.getPort() << qSetFieldWidth(0) << " : \"" << pinfo.getName() << "\"" << (pinfo.getType() != 0 ? portTypeNames(pinfo.getType()) : "") << endl; if ( from.count() > 0 ) cout << " Connected From: " << subsNames(from) << endl; if ( to.count() > 0 ) cout << " Connecting To: " << subsNames(to) << endl; } } } void systemInfo() { MidiClient* client = new MidiClient(); client->open(); client->setClientName(PGM_NAME); SystemInfo info = client->getSystemInfo(); cout << PGM_DESCRIPTION << ", version: "<< PGM_VERSION << endl; cout << "Compiled ALSA library: " << LIBRARY_VERSION << endl; cout << "Runtime ALSA library: " << getRuntimeALSALibraryVersion() << endl; cout << "Runtime ALSA drivers: " << getRuntimeALSADriverVersion() << endl; cout << "Numeric ALSA compiled library: " << hex << SND_LIB_VERSION << endl; cout << "Numeric ALSA runtime library: " << getRuntimeALSALibraryNumber() << endl; cout << "Numeric ALSA runtime driver: " << getRuntimeALSADriverNumber() << endl; cout << "Max Clients: " << dec << info.getMaxClients() << endl; cout << "Max Ports: " << info.getMaxPorts() << endl; cout << "Max Queues: " << info.getMaxQueues() << endl; cout << "Max Channels: " << info.getMaxChannels() << endl; cout << "Current Queues: " << info.getCurrentQueues() << endl; cout << "Current Clients: " << info.getCurrentClients() << endl; queryTimers(); if (info.getCurrentQueues() > 0) queryQueues(client); if (info.getCurrentClients() > 0) queryClients(client); delete client; } int main(int argc, char **argv) { const QString errorstr = "Fatal error from the ALSA sequencer. " "This usually happens when the kernel doesn't have ALSA support, " "or the device node (/dev/snd/seq) doesn't exists, " "or the kernel module (snd_seq) is not loaded. " "Please check your ALSA/MIDI configuration."; QCoreApplication app(argc, argv); QCoreApplication::setApplicationName(PGM_NAME); QCoreApplication::setApplicationVersion(PGM_VERSION); QCommandLineParser parser; parser.setApplicationDescription(PGM_DESCRIPTION); auto helpOption = parser.addHelpOption(); auto versionOption = parser.addVersionOption(); parser.process(app); if (parser.isSet(versionOption) || parser.isSet(helpOption)) { return 0; } try { systemInfo(); } catch (const SequencerError& ex) { cerr << errorstr + " Returned error was: " + ex.qstrError() << endl; } catch (...) { cerr << errorstr << endl; } return 0; } drumstick-1.1.3/utils/sysinfo/PaxHeaders.32572/sysinfo.pro0000644000000000000000000000013213532747316020341 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/sysinfo/sysinfo.pro0000644000175000001440000000055413532747316021136 0ustar00pedrousers00000000000000TEMPLATE = app TARGET = drumstick-sysinfo #QT += dbus CONFIG += qt console thread exceptions static { CONFIG += link_prl } DESTDIR = ../../build/bin INCLUDEPATH += . ../../library/include ../common DEPENDPATH += . ../../library ../../library/include LIBS = -L../../build/lib -ldrumstick-alsa -lasound include (../../global.pri) # Input SOURCES += sysinfo.cpp drumstick-1.1.3/utils/PaxHeaders.32572/dumpove0000644000000000000000000000013213532747316016035 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpove/0000755000175000001440000000000013532747316016703 5ustar00pedrousers00000000000000drumstick-1.1.3/utils/dumpove/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316020652 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpove/CMakeLists.txt0000644000175000001440000000233213532747316021443 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . SET(dumpove_SRCS dumpove.cpp dumpove.h ) SET(dumpove_qtobject_SRCS dumpove.h ) QT5_WRAP_CPP(dumpove_moc_SRCS ${dumpove_qtobject_SRCS}) ADD_EXECUTABLE(drumstick-dumpove ${dumpove_moc_SRCS} ${dumpove_SRCS} ) target_include_directories(drumstick-dumpove PRIVATE ../common ) TARGET_LINK_LIBRARIES(drumstick-dumpove drumstick-file Qt5::Core ) # we should install some files... INSTALL(TARGETS drumstick-dumpove RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) drumstick-1.1.3/utils/dumpove/PaxHeaders.32572/dumpove.pro0000644000000000000000000000013213532747316020313 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpove/dumpove.pro0000644000175000001440000000073313532747316021107 0ustar00pedrousers00000000000000TEMPLATE = app TARGET = drumstick-dumpove CONFIG += qt console static { CONFIG += link_prl } DESTDIR = ../../build/bin INCLUDEPATH += . ../../library/include ../common include (../../global.pri) # Input HEADERS += dumpove.h SOURCES += dumpove.cpp macx:!static { QMAKE_LFLAGS += -F$$OUT_PWD/../../build/lib -L$$OUT_PWD/../../build/lib LIBS += -framework drumstick-file } else { LIBS = -L$$OUT_PWD/../../build/lib \ -l$$drumstickLib(drumstick-file) } drumstick-1.1.3/utils/dumpove/PaxHeaders.32572/dumpove.h0000644000000000000000000000013213532747316017742 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpove/dumpove.h0000644000175000001440000000650513532747316020541 0ustar00pedrousers00000000000000/* Overture OVE file dump program Copyright (C) 2006-2019, Fan Rui This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include using namespace drumstick; class QSpyOve : public QObject { Q_OBJECT public: QSpyOve(); void run(QString fileName); void dump(const long time, const int track, const QString& chan, const QString& event, const QString& data); void dumpStr(const long time, const QString& event, const QString& data); void dumpStr(const QString& event, const QString& data); void dumpHex(const QByteArray& data); void dumpVar(const QString& name, bool value); void dumpVar(const QString& name, int value); void dumpVar(const QString& name, unsigned int value); void setVerbosity(bool enable); bool verbosityEnabled() const; public slots: void errorHandler(const QString& errorStr); void fileHeader(int verh, int verl); void fileEnd(); /* void trackHeader(const QString& name1, const QString& name2, int track, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop); */ void newTrackHeader(const QString& name, int track, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop); void timeBase(int timebase); void noteOnEvent(int track, long tick, int channel, int pitch, int vol); void noteOffEvent(int track, long tick, int channel, int pitch, int vol); void keyPressEvent(int track, long tick, int channel, int pitch, int press); void ctlChangeEvent(int track, long tick, int channel, int ctl, int value); void pitchBendEvent(int track, long tick, int channel, int value); void programEvent(int track, long tick, int channel, int patch); void chanPressEvent(int track, long tick, int channel, int press); void sysexEvent(int track, long tick, int bank); void sysexEventBank(int bank, const QString& name, bool autosend, int port, const QByteArray& data); void forcedChannel(int channel); void forcedPort(int port); void textEvent(int track, long tick, const QString& data); void timeSigEvent(int bar, long tick, int num, int den); void keySigEvent(int bar, long tick, int alt); void tempoEvent(long tick, int tempo); void trackPatch(int track, int channel, int patch); void trackVol(int track, int channel, int vol); void trackBank(int track, int channel, int bank); void chord(int track, long tick, const QString& name, const QByteArray& data); void expression(int track, long tick, int code, const QString& text); private: bool m_verbosity; QOve *m_engine; }; drumstick-1.1.3/utils/dumpove/PaxHeaders.32572/dumpove.cpp0000644000000000000000000000013213532747316020275 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpove/dumpove.cpp0000644000175000001440000003022613532747316021071 0ustar00pedrousers00000000000000/* Overture OVE file dump program Copyright (C) 2006-2019, Fan Rui This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include "cmdversion.h" #include "dumpove.h" const QString NO_CHANNEL("--"); const QString PGM_NAME("drumstick-dumpove"); const QString PGM_DESCRIPTION("Drumstick command line utility for decoding OVE (Overture) files"); static QTextStream cout(stdout, QIODevice::WriteOnly); static QTextStream cerr(stderr, QIODevice::WriteOnly); QSpyOve::QSpyOve(): m_verbosity(false), m_engine(nullptr) { m_engine = new QOve(this); connect(m_engine, SIGNAL(signalOVEError(const QString&)), SLOT(errorHandler(const QString&))); connect(m_engine, SIGNAL(signalOVEHeader(int,int)), SLOT(fileHeader(int,int))); connect(m_engine, SIGNAL(signalOVEEnd()), SLOT(fileEnd())); connect(m_engine, SIGNAL(signalOVENoteOn(int, long, int, int, int)), SLOT(noteOnEvent(int, long, int, int, int))); connect(m_engine, SIGNAL(signalOVENoteOff(int, long, int, int, int)), SLOT(noteOffEvent(int, long, int, int, int))); connect(m_engine, SIGNAL(signalOVEKeyPress(int,long,int,int,int)), SLOT(keyPressEvent(int,long,int,int,int))); connect(m_engine, SIGNAL(signalOVECtlChange(int,long,int,int,int)), SLOT(ctlChangeEvent(int,long,int,int,int))); connect(m_engine, SIGNAL(signalOVEPitchBend(int,long,int,int)), SLOT(pitchBendEvent(int,long,int,int))); connect(m_engine, SIGNAL(signalOVEProgram(int,long,int,int)), SLOT(programEvent(int,long,int,int))); connect(m_engine, SIGNAL(signalOVEChanPress(int,long,int,int)), SLOT(chanPressEvent(int,long,int,int))); connect(m_engine, SIGNAL(signalOVESysexEvent(int,long,int)), SLOT(sysexEvent(int,long,int))); connect(m_engine, SIGNAL(signalOVESysex(int,const QString&,bool,int,const QByteArray&)), SLOT(sysexEventBank(int,const QString&,bool,int,const QByteArray&))); connect(m_engine, SIGNAL(signalOVEText(int,long,const QString&)), SLOT(textEvent(int,long,const QString&))); connect(m_engine, SIGNAL(signalOVETimeSig(int,long,int,int)), SLOT(timeSigEvent(int,long,int,int))); connect(m_engine, SIGNAL(signalOVEKeySig(int,long,int)), SLOT(keySigEvent(int,long,int))); connect(m_engine, SIGNAL(signalOVETempo(long,int)), SLOT(tempoEvent(long,int))); connect(m_engine, SIGNAL(signalOVETrackPatch(int,int,int)), SLOT(trackPatch(int,int,int))); connect(m_engine, SIGNAL(signalOVENewTrack(const QString&,int,int,int,int,int,bool,bool,bool)), SLOT(newTrackHeader(const QString&,int,int,int,int,int,bool,bool,bool))); connect(m_engine, SIGNAL(signalOVETrackVol(int,int,int)), SLOT(trackVol(int,int,int))); connect(m_engine, SIGNAL(signalOVETrackBank(int,int,int)), SLOT(trackBank(int,int,int))); connect(m_engine, SIGNAL(signalOVEChord(int,long,const QString&,const QByteArray&)), SLOT(chord(int,long,const QString&,const QByteArray&))); connect(m_engine, SIGNAL(signalOVEExpression(int,long,int,const QString&)), SLOT(expression(int,long,int,const QString&))); cout.setRealNumberNotation(QTextStream::FixedNotation); cout.setRealNumberPrecision(4); } void QSpyOve::dump(const long tick, const int track, const QString& chan, const QString& event, const QString& data) { cout << right << qSetFieldWidth(7) << tick; cout << qSetFieldWidth(0) << left << ' '; cout << qSetFieldWidth(5) << right << track; cout << qSetFieldWidth(3) << chan; cout << qSetFieldWidth(0) << left << ' '; cout << qSetFieldWidth(25) << event; cout << qSetFieldWidth(0) << ' ' << data << endl; } void QSpyOve::dumpStr(const long tick, const QString& event, const QString& data) { cout << right << qSetFieldWidth(7) << tick; cout << qSetFieldWidth(6) << NO_CHANNEL; cout << qSetFieldWidth(3) << NO_CHANNEL; cout << qSetFieldWidth(0) << left << ' '; cout << qSetFieldWidth(25) << event; cout << qSetFieldWidth(0) << ' ' << data << endl; } void QSpyOve::dumpStr(const QString& event, const QString& data) { cout << qSetFieldWidth(6) << NO_CHANNEL; cout << qSetFieldWidth(3) << NO_CHANNEL; cout << qSetFieldWidth(0) << left << ' '; cout << qSetFieldWidth(25) << event; cout << qSetFieldWidth(0) << ' ' << data << endl; } void QSpyOve::dumpHex(const QByteArray& data) { int i = 0, j = 0; QString s; if (m_verbosity) { while ( i < data.count() ) { s.clear(); for (j = 0; j < 16 && i < data.count(); ++j) { quint8 c = data[i++]; s += QString(" %1").arg(c & 0xff, 2, 16, QChar('0')); } cout << qSetFieldWidth(42) << ' ' << qSetFieldWidth(0) << s << endl; } } } void QSpyOve::dumpVar(const QString& name, int value) { cout << qSetFieldWidth(43) << ' ' << qSetFieldWidth(0) << name << " = " << value << endl; } void QSpyOve::dumpVar(const QString& name, unsigned int value) { cout << qSetFieldWidth(43) << ' ' << qSetFieldWidth(0) << name << " = " << value << endl; } void QSpyOve::dumpVar(const QString& name, bool value) { cout << qSetFieldWidth(43) << ' ' << qSetFieldWidth(0) << name << " = " << (value ? "true" : "false" ) << endl; } void QSpyOve::setVerbosity(bool enabled) { m_verbosity = enabled; } bool QSpyOve::verbosityEnabled() const { return m_verbosity; } void QSpyOve::errorHandler(const QString& errorStr) { cerr << "*** Warning! " << errorStr << endl; } void QSpyOve::fileHeader(int res, int tracks) { dumpStr(0, "OVE File Header", QString("Resolution=%1 Tracks=%2").arg(res).arg(tracks)); } void QSpyOve::fileEnd() { dumpStr(0, "Ove File End", QString()); } void QSpyOve::newTrackHeader( const QString& name, int track, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop ) { dump(0, track, QString::number(channel), "Track", name); if (m_verbosity) { dumpVar("pitch", pitch); dumpVar("velocity",velocity); dumpVar("port", port); dumpVar("selected", selected); dumpVar("muted", muted); dumpVar("loop", loop); } } void QSpyOve::timeBase(int timebase) { dumpStr(0, "Ticks per Quarter Note", QString::number(timebase)); } void QSpyOve::noteOnEvent(int track, long tick, int channel, int pitch, int vol) { dump(tick, track, QString::number(channel), "Note On", QString("key=%1 vel=%2").arg(pitch).arg(vol)); } void QSpyOve::noteOffEvent(int track, long tick, int channel, int pitch, int vol) { dump(tick, track, QString::number(channel), "Note Off", QString("key=%1 vel=%2").arg(pitch).arg(vol)); } void QSpyOve::keyPressEvent(int track, long tick, int channel, int pitch, int press) { dump(tick, track, QString::number(channel), "Key Pressure", QString("key=%1 press=%2").arg(pitch).arg(press)); } void QSpyOve::ctlChangeEvent(int track, long tick, int channel, int ctl, int value) { dump(tick, track, QString::number(channel), "Control Change", QString("ctl=%1 val=%2").arg(ctl).arg(value)); } void QSpyOve::pitchBendEvent(int track, long tick, int channel, int value) { dump(tick, track, QString::number(channel), "Pitch Bend", QString::number(value)); } void QSpyOve::programEvent(int track, long tick, int channel, int patch) { dump(tick, track, QString::number(channel), "Program Change", QString::number(patch)); } void QSpyOve::chanPressEvent(int track, long tick, int channel, int press) { dump(tick, track, QString::number(channel), "Channel Pressure", QString::number(press)); } void QSpyOve::sysexEvent(int track, long tick, int bank) { dump(tick, track, NO_CHANNEL, "System Exclusive", QString::number(bank)); } void QSpyOve::sysexEventBank(int bank, const QString& name, bool autosend, int port, const QByteArray& data) { dumpStr(0, "System Exclusive Bank", QString("bank=%1 name='%2' auto=%3 port=%4").arg(bank).arg(name).arg(autosend).arg(port)); dumpHex(data); } void QSpyOve::forcedChannel(int channel) { dump(0, 0, NO_CHANNEL, "Forced channel", QString::number(channel)); } void QSpyOve::forcedPort(int port) { dump(0, 0, NO_CHANNEL, "Forced port", QString::number(port)); } void QSpyOve::textEvent(int track, long tick, const QString& data) { dump(tick, track, NO_CHANNEL, QString("Text "), data); } void QSpyOve::timeSigEvent(int bar, long tick, int num, int den) { dumpStr(0, "Time Signature", QString("bar=%1, tick=%2, %3/%4").arg(bar).arg(tick).arg(num).arg(den)); } void QSpyOve::keySigEvent(int bar, long tick, int alt) { dumpStr(0, "Key Signature", QString("bar=%1, tick=%2, alt=%3").arg(bar).arg(tick).arg(alt)); } void QSpyOve::tempoEvent(long tick, int tempo) { double bpm = tempo / 100.0; dumpStr(tick, "Tempo", QString::number(bpm, 'f', 2)); } void QSpyOve::trackPatch(int track, int channel, int patch) { dump(0, track, QString::number(channel), "Track Patch", QString::number(patch)); } void QSpyOve::trackVol(int track, int channel, int vol) { Q_UNUSED(channel) dump(0, track, QString::number(channel), "Track Volume", QString::number(vol)); } void QSpyOve::trackBank(int track, int channel, int bank) { dump(0, track, QString::number(channel), "Track Bank", QString::number(bank)); } void QSpyOve::chord(int track, long tick, const QString& name, const QByteArray& data) { dump(tick, track, NO_CHANNEL, "Chord Diagram", name); dumpHex(data); } void QSpyOve::expression(int track, long tick, int code, const QString& text) { dump(tick, track, NO_CHANNEL, "Expression", QString("text=%1 code=%2").arg(text).arg(code)); } void QSpyOve::run(QString fileName) { cout << "__ticks track ch event____________________ data____" << endl; m_engine->readFromFile(fileName); } int main(int argc, char *argv[]) { QSpyOve spy; QCoreApplication app(argc, argv); QCoreApplication::setApplicationName(PGM_NAME); QCoreApplication::setApplicationVersion(PGM_VERSION); QCommandLineParser parser; parser.setApplicationDescription(PGM_DESCRIPTION); auto helpOption = parser.addHelpOption(); auto versionOption = parser.addVersionOption(); QCommandLineOption verboseOption("verbose", "Verbose output."); parser.addOption(verboseOption); parser.addPositionalArgument("file", "Input OVE file name.", "files..."); parser.process(app); if (parser.isSet(versionOption) || parser.isSet(helpOption)) { return 0; } if (parser.isSet(verboseOption)) { spy.setVerbosity(true); } QStringList fileNames, positionalArgs = parser.positionalArguments(); if (positionalArgs.isEmpty()) { cerr << "Inpout file name(s) missing" << endl; parser.showHelp(); } foreach(const QString& a, positionalArgs) { QFileInfo f(a); if (f.exists()) fileNames += f.canonicalFilePath(); else cerr << "File not found: " << a << endl; } foreach(const QString& file, fileNames) { spy.run(file); } return 0; } drumstick-1.1.3/utils/PaxHeaders.32572/dumpsmf0000644000000000000000000000013213532747316016031 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpsmf/0000755000175000001440000000000013532747316016677 5ustar00pedrousers00000000000000drumstick-1.1.3/utils/dumpsmf/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316020646 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpsmf/CMakeLists.txt0000644000175000001440000000233013532747316021435 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set(dumpsmf_SRCS dumpsmf.cpp dumpsmf.h ) set(dumpsmf_qtobject_SRCS dumpsmf.h ) qt5_wrap_cpp(dumpsmf_moc_SRCS ${dumpsmf_qtobject_SRCS}) add_executable(drumstick-dumpsmf ${dumpsmf_moc_SRCS} ${dumpsmf_SRCS} ) target_include_directories(drumstick-dumpsmf PRIVATE ../common ) target_link_libraries(drumstick-dumpsmf drumstick-file Qt5::Core ) # we should install some files... install(TARGETS drumstick-dumpsmf RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) drumstick-1.1.3/utils/dumpsmf/PaxHeaders.32572/dumpsmf.cpp0000644000000000000000000000013213532747316020265 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpsmf/dumpsmf.cpp0000644000175000001440000002303513532747316021061 0ustar00pedrousers00000000000000/* Standard MIDI File dump program Copyright (C) 2006-2019, Pedro Lopez-Cabanillas Based on midifile.c by Tim Thompson, M.Czeiszperger and Greg Lee This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include "cmdversion.h" #include "dumpsmf.h" const QString PGM_NAME("drumstick-dumpsmf"); const QString PGM_DESCRIPTION("Drumstick command line utility for decoding SMF (Standard MIDI) files"); static QTextStream cout(stdout, QIODevice::WriteOnly); static QTextStream cerr(stderr, QIODevice::WriteOnly); QSpySMF::QSpySMF(): m_currentTrack(0), m_engine(nullptr), m_rc(0) { QTextCodec *codec = QTextCodec::codecForName("UTF-8"); m_engine = new QSmf(this); m_engine->setTextCodec(codec); connect(m_engine, SIGNAL(signalSMFHeader(int,int,int)), this, SLOT(headerEvent(int,int,int))); connect(m_engine, SIGNAL(signalSMFTrackStart()), this, SLOT(trackStartEvent())); connect(m_engine, SIGNAL(signalSMFTrackEnd()), this, SLOT(trackEndEvent())); connect(m_engine, SIGNAL(signalSMFNoteOn(int,int,int)), this, SLOT(noteOnEvent(int,int,int))); connect(m_engine, SIGNAL(signalSMFNoteOff(int,int,int)), this, SLOT(noteOffEvent(int,int,int))); connect(m_engine, SIGNAL(signalSMFKeyPress(int,int,int)), this, SLOT(keyPressEvent(int,int,int))); connect(m_engine, SIGNAL(signalSMFCtlChange(int,int,int)), this, SLOT(ctlChangeEvent(int,int,int))); connect(m_engine, SIGNAL(signalSMFPitchBend(int,int)), this, SLOT(pitchBendEvent(int,int))); connect(m_engine, SIGNAL(signalSMFProgram(int,int)), this, SLOT(programEvent(int,int))); connect(m_engine, SIGNAL(signalSMFChanPress(int,int)), this, SLOT(chanPressEvent(int,int))); connect(m_engine, SIGNAL(signalSMFSysex(const QByteArray&)), this, SLOT(sysexEvent(const QByteArray&))); connect(m_engine, SIGNAL(signalSMFSeqSpecific(const QByteArray&)), this, SLOT(seqSpecificEvent(const QByteArray&))); connect(m_engine, SIGNAL(signalSMFMetaUnregistered(int, const QByteArray&)), this, SLOT(metaMiscEvent(int, const QByteArray&))); //connect(m_engine, SIGNAL(signalSMFVariable(const QByteArray&)), this, SLOT(variableEvent(const QByteArray&))); connect(m_engine, SIGNAL(signalSMFSequenceNum(int)), this, SLOT(seqNum(int))); connect(m_engine, SIGNAL(signalSMFforcedChannel(int)), this, SLOT(forcedChannel(int))); connect(m_engine, SIGNAL(signalSMFforcedPort(int)), this, SLOT(forcedPort(int))); connect(m_engine, SIGNAL(signalSMFText(int,const QString&)), this, SLOT(textEvent(int,const QString&))); connect(m_engine, SIGNAL(signalSMFendOfTrack()), this, SLOT(endOfTrackEvent())); connect(m_engine, SIGNAL(signalSMFTimeSig(int,int,int,int)), this, SLOT(timeSigEvent(int,int,int,int))); connect(m_engine, SIGNAL(signalSMFSmpte(int,int,int,int,int)), this, SLOT(smpteEvent(int,int,int,int,int))); connect(m_engine, SIGNAL(signalSMFKeySig(int,int)), this, SLOT(keySigEvent(int,int))); connect(m_engine, SIGNAL(signalSMFTempo(int)), this, SLOT(tempoEvent(int))); connect(m_engine, SIGNAL(signalSMFError(const QString&)), this, SLOT(errorHandler(const QString&))); cout.setRealNumberNotation(QTextStream::FixedNotation); cout.setRealNumberPrecision(4); cout.setCodec(codec); } void QSpySMF::dump(const QString& chan, const QString& event, const QString& data) { cout << right << qSetFieldWidth(7) << m_engine->getCurrentTime(); cout << right << qSetFieldWidth(10) << m_engine->getRealTime() / 1600.0; cout << qSetFieldWidth(3) << chan; cout << qSetFieldWidth(0) << left << " "; cout << qSetFieldWidth(15) << event; cout << qSetFieldWidth(0) << " " << data << endl; } void QSpySMF::dumpStr(const QString& event, const QString& data) { cout << right << qSetFieldWidth(7) << m_engine->getCurrentTime(); cout << right << qSetFieldWidth(10) << m_engine->getRealTime() / 1600.0; cout << qSetFieldWidth(3) << "--"; cout << qSetFieldWidth(0) << left << " "; cout << qSetFieldWidth(15) << event; cout << qSetFieldWidth(0) << " " << data << endl; } void QSpySMF::headerEvent(int format, int ntrks, int division) { dumpStr("SMF Header", QString("Format=%1, Tracks=%2, Division=%3") .arg(format).arg(ntrks).arg(division)); } void QSpySMF::trackStartEvent() { m_currentTrack++; dumpStr("Track", QString("Start: %1").arg(m_currentTrack)); } void QSpySMF::trackEndEvent() { dumpStr("Track", QString("End: %1").arg(m_currentTrack)); } void QSpySMF::endOfTrackEvent() { dumpStr("Meta Event", "End Of Track"); } void QSpySMF::noteOnEvent(int chan, int pitch, int vol) { dump(QString("%1").arg(chan, 2), "Note On", QString("%1, %2").arg(pitch).arg(vol)); } void QSpySMF::noteOffEvent(int chan, int pitch, int vol) { dump(QString("%1").arg(chan, 2), "Note Off", QString("%1, %2").arg(pitch).arg(vol)); } void QSpySMF::keyPressEvent(int chan, int pitch, int press) { dump(QString("%1").arg(chan, 2), "Key Pressure", QString("%1, %2").arg(pitch).arg(press)); } void QSpySMF::ctlChangeEvent(int chan, int ctl, int value) { dump(QString("%1").arg(chan, 2), "Control Change", QString("%1, %2").arg(ctl).arg(value)); } void QSpySMF::pitchBendEvent(int chan, int value) { dump(QString("%1").arg(chan, 2), "Pitch Bend", QString::number(value)); } void QSpySMF::programEvent(int chan, int patch) { dump(QString("%1").arg(chan, 2), "Program Change", QString::number(patch)); } void QSpySMF::chanPressEvent(int chan, int press) { dump(QString("%1").arg(chan, 2), "Chan.Pressure", QString::number(press)); } void QSpySMF::sysexEvent(const QByteArray& data) { int j; QString s; for (j = 0; j < data.count(); ++j) s.append(QString("%1 ").arg(data[j] & 0xff, 2, 16)); dumpStr("SysEx", s); } /*void QSpySMF::variableEvent(const QByteArray& data) { int j; QString s; for (j = 0; j < data.count(); ++j) s.append(QString("%1 ").arg(data[j] & 0xff, 2, 16)); dumpStr("Variable event", s); }*/ void QSpySMF::seqSpecificEvent(const QByteArray& data) { int j; QString s; for (j = 0; j < data.count(); ++j) s.append(QString("%1 ").arg(data[j] & 0xff, 2, 16)); dumpStr("Seq. specific", s); } void QSpySMF::metaMiscEvent(int typ, const QByteArray& data) { int j; QString s = QString("type=%1 ").arg(typ); for (j = 0; j < data.count(); ++j) s.append(QString("%1 ").arg(data[j] & 0xff, 2, 16)); dumpStr("Meta (unreg.)", s); } void QSpySMF::seqNum(int seq) { dump("--", "Sequence num.", QString::number(seq)); } void QSpySMF::forcedChannel(int channel) { dump("--", "Forced channel", QString::number(channel)); } void QSpySMF::forcedPort(int port) { dump("--", "Forced port", QString::number(port)); } void QSpySMF::textEvent(int typ, const QString& data) { dumpStr(QString("Text (%1)").arg(typ), data); } void QSpySMF::smpteEvent(int b0, int b1, int b2, int b3, int b4) { dump("--", "SMPTE", QString("%1, %2, %3, %4, %5").arg(b0).arg(b1).arg(b2).arg(b3).arg(b4)); } void QSpySMF::timeSigEvent(int b0, int b1, int b2, int b3) { dump("--", "Time Signature", QString("%1, %2, %3, %4").arg(b0).arg(b1).arg(b2).arg(b3)); } void QSpySMF::keySigEvent(int b0, int b1) { dump("--", "Key Signature", QString("%1, %2").arg(b0).arg(b1)); } void QSpySMF::tempoEvent(int tempo) { dump("--", "Tempo", QString::number(tempo)); } void QSpySMF::errorHandler(const QString& errorStr) { m_rc++; cerr << "*** Warning! " << errorStr << " at file offset " << m_engine->getFilePos() << endl; } void QSpySMF::run(QString fileName) { m_currentTrack = 0; cout << "__ticks __seconds ch event__________ data____" << endl; m_engine->readFromFile(fileName); } int QSpySMF::numErrors() { return m_rc; } int main(int argc, char **argv) { QSpySMF spy; QString file; QCoreApplication app(argc, argv); QCoreApplication::setApplicationName(PGM_NAME); QCoreApplication::setApplicationVersion(PGM_VERSION); QCommandLineParser parser; parser.setApplicationDescription(PGM_DESCRIPTION); auto helpOption = parser.addHelpOption(); auto versionOption = parser.addVersionOption(); parser.addPositionalArgument("file", "Input SMF file name.", "files..."); parser.process(app); if (parser.isSet(versionOption) || parser.isSet(helpOption)) { return 0; } QStringList fileNames, positionalArgs = parser.positionalArguments(); if (positionalArgs.isEmpty()) { cerr << "Input file name(s) missing" << endl; parser.showHelp(); } foreach(const QString& a, positionalArgs) { QFileInfo f(a); if (f.exists()) fileNames += f.canonicalFilePath(); else cerr << "File not found: " << a << endl; } foreach(const QString& file, fileNames) { spy.run(file); } return spy.numErrors(); } drumstick-1.1.3/utils/dumpsmf/PaxHeaders.32572/dumpsmf.pro0000644000000000000000000000013213532747316020303 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpsmf/dumpsmf.pro0000644000175000001440000000073313532747316021077 0ustar00pedrousers00000000000000TEMPLATE = app TARGET = drumstick-dumpsmf CONFIG += qt console static { CONFIG += link_prl } DESTDIR = ../../build/bin INCLUDEPATH += . ../../library/include ../common include (../../global.pri) # Input HEADERS += dumpsmf.h SOURCES += dumpsmf.cpp macx:!static { QMAKE_LFLAGS += -F$$OUT_PWD/../../build/lib -L$$OUT_PWD/../../build/lib LIBS += -framework drumstick-file } else { LIBS = -L$$OUT_PWD/../../build/lib \ -l$$drumstickLib(drumstick-file) } drumstick-1.1.3/utils/dumpsmf/PaxHeaders.32572/dumpsmf.h0000644000000000000000000000013213532747316017732 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpsmf/dumpsmf.h0000644000175000001440000000443213532747316020526 0ustar00pedrousers00000000000000/* Standard MIDI File dump program Copyright (C) 2006-2019, Pedro Lopez-Cabanillas Based on midifile.c by Tim Thompson, M.Czeiszperger and Greg Lee This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include using namespace drumstick; class QSpySMF : public QObject { Q_OBJECT public: QSpySMF(); void run(QString fileName); void dump(const QString& chan, const QString& event, const QString& data); void dumpStr(const QString& event, const QString& data); int numErrors(); public slots: void headerEvent(int format, int ntrks, int division); void trackStartEvent(); void trackEndEvent(); void endOfTrackEvent(); void noteOnEvent(int chan, int pitch, int vol); void noteOffEvent(int chan, int pitch, int vol); void keyPressEvent(int chan, int pitch, int press); void ctlChangeEvent(int chan, int ctl, int value); void pitchBendEvent(int chan, int value); void programEvent(int chan, int patch); void chanPressEvent(int chan, int press); void sysexEvent(const QByteArray& data); //void variableEvent(const QByteArray& data); void seqSpecificEvent(const QByteArray& data); void metaMiscEvent(int typ, const QByteArray& data); void seqNum(int seq); void forcedChannel(int channel); void forcedPort(int port); void textEvent(int typ, const QString& data); void smpteEvent(int b0, int b1, int b2, int b3, int b4); void timeSigEvent(int b0, int b1, int b2, int b3); void keySigEvent(int b0, int b1); void tempoEvent(int tempo); void errorHandler(const QString& errorStr); private: int m_currentTrack; QSmf *m_engine; int m_rc; }; drumstick-1.1.3/utils/PaxHeaders.32572/guiplayer0000644000000000000000000000013213532747316016357 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/0000755000175000001440000000000013532747316017225 5ustar00pedrousers00000000000000drumstick-1.1.3/utils/guiplayer/PaxHeaders.32572/guiplayer.pro0000644000000000000000000000013213532747316021157 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/guiplayer.pro0000644000175000001440000000102113532747316021742 0ustar00pedrousers00000000000000TEMPLATE = app TARGET = drumstick-guiplayer QT += gui widgets #dbus CONFIG += qt thread exceptions static { CONFIG += link_prl } DESTDIR = ../../build/bin INCLUDEPATH += . ../../library/include ../common LIBS = -L../../build/lib -ldrumstick-file -ldrumstick-alsa -lasound include (../../global.pri) # Input HEADERS += player.h guiplayer.h song.h playerabout.h FORMS += guiplayer.ui playerabout.ui SOURCES += playermain.cpp \ player.cpp \ guiplayer.cpp \ song.cpp \ playerabout.cpp RESOURCES += guiplayer.qrc drumstick-1.1.3/utils/guiplayer/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316021174 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/CMakeLists.txt0000644000175000001440000000336513532747316021774 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . find_package(Qt5Widgets REQUIRED) SET(guiplayer_forms_SRCS guiplayer.ui playerabout.ui ) SET(guiplayer_SRCS guiplayer.cpp guiplayer.h player.cpp player.h song.cpp song.h playerabout.cpp playerabout.h playermain.cpp ) SET(guiplayer_qtobject_SRCS player.h playerabout.h guiplayer.h ) QT5_WRAP_UI(guiplayer_ui_SRCS ${guiplayer_forms_SRCS}) QT5_WRAP_CPP(guiplayer_moc_SRCS ${guiplayer_qtobject_SRCS}) QT5_ADD_RESOURCES(guiplayer_resources guiplayer.qrc) ADD_EXECUTABLE(drumstick-guiplayer ${guiplayer_resources} ${guiplayer_ui_SRCS} ${guiplayer_moc_SRCS} ${guiplayer_SRCS} ) target_include_directories(drumstick-guiplayer PRIVATE ../common ) TARGET_LINK_LIBRARIES(drumstick-guiplayer ${ALSA_LIBS} drumstick-file drumstick-alsa Qt5::Widgets ) INSTALL(TARGETS drumstick-guiplayer RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) INSTALL(FILES drumstick-guiplayer.desktop DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications") drumstick-1.1.3/utils/guiplayer/PaxHeaders.32572/song.h0000644000000000000000000000013213532747316017553 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/song.h0000644000175000001440000000323713532747316020351 0ustar00pedrousers00000000000000/* SMF GUI Player test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef INCLUDED_SONG_H #define INCLUDED_SONG_H #include namespace drumstick { class SequencerEvent; } using namespace drumstick; class Song : public QList { public: Song() : QList(), m_format(0), m_ntrks(0), m_division(0) { } virtual ~Song(); void clear(); void sort(); void setHeader(int format, int ntrks, int division); void setDivision(int division); void setFileName(const QString& fileName); int getFormat() const { return m_format; } int getTracks() const { return m_ntrks; } int getDivision() const { return m_division; } QString getFileName() const { return m_fileName; } private: int m_format; int m_ntrks; int m_division; QString m_fileName; }; typedef QListIterator SongIterator; #endif /*INCLUDED_SONG_H*/ drumstick-1.1.3/utils/guiplayer/PaxHeaders.32572/playermain.cpp0000644000000000000000000000013213532747316021301 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/playermain.cpp0000644000175000001440000000565313532747316022103 0ustar00pedrousers00000000000000/* SMF GUI Player test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include "guiplayer.h" #include "cmdversion.h" const QString PGM_DESCRIPTION("ALSA Sequencer based MIDI file player"); const QString errorstr = "Fatal error from the ALSA sequencer. " "This usually happens when the kernel doesn't have ALSA support, " "or the device node (/dev/snd/seq) doesn't exists, " "or the kernel module (snd_seq) is not loaded. " "Please check your ALSA/MIDI configuration."; int main(int argc, char *argv[]) { QCoreApplication::setOrganizationName(QSTR_DOMAIN); QCoreApplication::setOrganizationDomain(QSTR_DOMAIN); QCoreApplication::setApplicationName(QSTR_APPNAME); QCoreApplication::setApplicationVersion(PGM_VERSION); QApplication app(argc, argv); QCommandLineParser parser; parser.setApplicationDescription(PGM_DESCRIPTION); auto helpOption = parser.addHelpOption(); auto versionOption = parser.addVersionOption(); QCommandLineOption portOption({"p", "port"}, "MIDI Out Connection.", "client:port"); parser.addOption(portOption); parser.addPositionalArgument("file", "Input SMF/KAR/OVE/WRK file name.", "file"); parser.process(app); if (parser.isSet(versionOption) || parser.isSet(helpOption)) { return 0; } QStringList fileNames, positionalArgs = parser.positionalArguments(); foreach(const QString& a, positionalArgs) { QFileInfo f(a); if (f.exists()) fileNames += f.canonicalFilePath(); else qWarning() << "File not found: " << a << endl; } try { GUIPlayer w; if(parser.isSet(portOption)) { QString port = parser.value(portOption); w.subscribe(port); } if (!fileNames.isEmpty()) { w.openFile(fileNames.first()); } w.show(); return app.exec(); } catch (const SequencerError& ex) { QMessageBox::critical(nullptr, "Error", errorstr + " Returned error was: " + ex.qstrError() ); } catch (...) { qWarning() << errorstr; } return 0; } drumstick-1.1.3/utils/guiplayer/PaxHeaders.32572/song.cpp0000644000000000000000000000013213532747316020106 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/song.cpp0000644000175000001440000000275513532747316020710 0ustar00pedrousers00000000000000/* SMF GUI Player test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include "song.h" static inline bool eventLessThan(const SequencerEvent* s1, const SequencerEvent* s2) { return s1->getTick() < s2->getTick(); } Song::~Song() { clear(); } void Song::sort() { qStableSort(begin(), end(), eventLessThan); } void Song::clear() { while (!isEmpty()) delete takeFirst(); m_fileName.clear(); m_format = 0; m_ntrks = 0; m_division = 0; } void Song::setHeader(int format, int ntrks, int division) { m_format = format; m_ntrks = ntrks; m_division = division; } void Song::setDivision(int division) { m_division = division; } void Song::setFileName(const QString& fileName) { m_fileName = fileName; } drumstick-1.1.3/utils/guiplayer/PaxHeaders.32572/guiplayer.h0000644000000000000000000000013213532747316020606 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/guiplayer.h0000644000175000001440000001400413532747316021376 0ustar00pedrousers00000000000000/* SMF GUI Player test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef INCLUDED_GUIPLAYER_H #define INCLUDED_GUIPLAYER_H #include #include #include #include #include #include #include namespace drumstick { class QSmf; class QWrk; class QOve; class MidiClient; class MidiPort; class MidiQueue; class SequencerEvent; } namespace Ui { class GUIPlayerClass; } class Player; class About; class Song; using namespace drumstick; const QString QSTR_DOMAIN("drumstick.sourceforge.net"); const QString QSTR_APPNAME("GUIPlayer"); enum PlayerState { InvalidState, EmptyState, PlayingState, PausedState, StoppedState }; class GUIPlayer : public QMainWindow { Q_OBJECT public: GUIPlayer(QWidget *parent = nullptr, Qt::WindowFlags flags = nullptr); ~GUIPlayer(); void appendSMFEvent(SequencerEvent* ev); void appendWRKEvent(unsigned long ticks, SequencerEvent* ev); void appendOVEEvent(unsigned long ticks, SequencerEvent* ev); void subscribe(const QString& portName); void updateTimeLabel(int mins, int secs, int cnts); void updateTempoLabel(float ftempo); void dragEnterEvent(QDragEnterEvent* event); void dropEvent(QDropEvent* event); void closeEvent(QCloseEvent* event); //bool event(QEvent* event); void openFile(const QString& fileName); void readSettings(); void writeSettings(); void updateState(PlayerState newState); void progressDialogInit(const QString& type, int max); void progressDialogUpdate(int pos); void progressDialogClose(); public slots: void about(); void aboutQt(); void play(); void pause(); void stop(); void open(); void setup(); void tempoReset(); void volumeReset(); void tempoSlider(int value); void volumeSlider(int value); void pitchShift(int value); void songFinished(); void playerStopped(); void sequencerEvent(SequencerEvent* ev); /* SMF slots */ void smfHeaderEvent(int format, int ntrks, int division); void smfNoteOnEvent(int chan, int pitch, int vol); void smfNoteOffEvent(int chan, int pitch, int vol); void smfKeyPressEvent(int chan, int pitch, int press); void smfCtlChangeEvent(int chan, int ctl, int value); void smfPitchBendEvent(int chan, int value); void smfProgramEvent(int chan, int patch); void smfChanPressEvent(int chan, int press); void smfSysexEvent(const QByteArray& data); void smfTempoEvent(int tempo); void smfErrorHandler(const QString& errorStr); void smfUpdateLoadProgress(); /* WRK slots */ void wrkUpdateLoadProgress(); void wrkErrorHandler(const QString& errorStr); void wrkFileHeader(int verh, int verl); void wrkEndOfFile(); void wrkStreamEndEvent(long time); void wrkTrackHeader(const QString& name1, const QString& name2, int trackno, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop); void wrkTimeBase(int timebase); void wrkNoteEvent(int track, long time, int chan, int pitch, int vol, int dur); void wrkKeyPressEvent(int track, long time, int chan, int pitch, int press); void wrkCtlChangeEvent(int track, long time, int chan, int ctl, int value); void wrkPitchBendEvent(int track, long time, int chan, int value); void wrkProgramEvent(int track, long time, int chan, int patch); void wrkChanPressEvent(int track, long time, int chan, int press); void wrkSysexEvent(int track, long time, int bank); void wrkSysexEventBank(int bank, const QString& name, bool autosend, int port, const QByteArray& data); void wrkTempoEvent(long time, int tempo); void wrkTrackPatch(int track, int patch); void wrkNewTrackHeader(const QString& name, int trackno, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop); void wrkTrackVol(int track, int vol); void wrkTrackBank(int track, int bank); /* OVE slots */ void oveErrorHandler(const QString& errorStr); void oveFileHeader(int quarter, int trackCount); void oveNoteOnEvent(int track, long tick, int channel, int pitch, int vol); void oveNoteOffEvent(int track, long tick, int channel, int pitch, int vol); void oveTrackPatch(int track, int channel, int patch); void oveTrackVol(int track, int channel, int vol); void oveTrackBank(int track, int channel, int bank); private: int m_portId; int m_queueId; int m_initialTempo; float m_tempoFactor; unsigned long m_tick; PlayerState m_state; QSmf* m_smf; QWrk* m_wrk; QOve* m_ove; MidiClient* m_Client; MidiPort* m_Port; MidiQueue* m_Queue; Player* m_player; Ui::GUIPlayerClass* m_ui; QPointer m_pd; QPointer m_aboutDlg; Song* m_song; QString m_subscription; QString m_lastDirectory; QString m_loadingMessages; struct SysexEventRec { int track; long time; int bank; }; QList m_savedSysexEvents; struct TrackMapRec { int channel; int pitch; int velocity; }; QHash m_trackMap; }; #endif // INCLUDED_GUIPLAYER_H drumstick-1.1.3/utils/guiplayer/PaxHeaders.32572/guiplayer.cpp0000644000000000000000000000013213532747316021141 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/guiplayer.cpp0000644000175000001440000010244713532747316021742 0ustar00pedrousers00000000000000/* SMF GUI Player test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "guiplayer.h" #include "ui_guiplayer.h" #include "playerabout.h" #include "player.h" #include "song.h" GUIPlayer::GUIPlayer(QWidget *parent, Qt::WindowFlags flags) : QMainWindow(parent, flags), m_portId(-1), m_queueId(-1), m_initialTempo(0), m_tempoFactor(1.0), m_tick(0), m_state(InvalidState), m_smf(0), m_wrk(0), m_ove(0), m_Client(0), m_Port(0), m_Queue(0), m_player(0), m_ui(new Ui::GUIPlayerClass), m_pd(0), m_aboutDlg(0), m_song(new Song) { m_ui->setupUi(this); setAcceptDrops(true); connect(m_ui->actionAbout, SIGNAL(triggered()), SLOT(about())); connect(m_ui->actionAboutQt, SIGNAL(triggered()), SLOT(aboutQt())); connect(m_ui->actionPlay, SIGNAL(triggered()), SLOT(play())); connect(m_ui->actionPause, SIGNAL(triggered()), SLOT(pause())); connect(m_ui->actionStop, SIGNAL(triggered()), SLOT(stop())); connect(m_ui->actionOpen, SIGNAL(triggered()), SLOT(open())); connect(m_ui->actionMIDISetup, SIGNAL(triggered()), SLOT(setup())); connect(m_ui->actionQuit, SIGNAL(triggered()), SLOT(close())); connect(m_ui->btnTempo, SIGNAL(clicked()), SLOT(tempoReset())); connect(m_ui->btnVolume, SIGNAL(clicked()), SLOT(volumeReset())); connect(m_ui->sliderTempo, SIGNAL(valueChanged(int)), SLOT(tempoSlider(int))); connect(m_ui->volumeSlider, SIGNAL(valueChanged(int)), SLOT(volumeSlider(int))); connect(m_ui->spinPitch, SIGNAL(valueChanged(int)), SLOT(pitchShift(int))); connect(m_ui->toolBar->toggleViewAction(), SIGNAL(toggled(bool)), m_ui->actionShowToolbar, SLOT(setChecked(bool))); m_ui->actionPlay->setShortcut( Qt::Key_MediaPlay ); m_ui->actionStop->setShortcut( Qt::Key_MediaStop ); m_Client = new MidiClient(this); m_Client->open(); m_Client->setPoolOutput(50); // small size, for near real-time pitchShift m_Client->setClientName("MIDI Player"); connect( m_Client, SIGNAL(eventReceived(SequencerEvent*)), SLOT(sequencerEvent(SequencerEvent*)), Qt::QueuedConnection ); m_Port = new MidiPort(this); m_Port->attach( m_Client ); m_Port->setPortName("MIDI Player Output Port"); m_Port->setCapability( SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ | SND_SEQ_PORT_CAP_WRITE ); m_Port->setPortType( SND_SEQ_PORT_TYPE_APPLICATION | SND_SEQ_PORT_TYPE_MIDI_GENERIC ); m_Queue = m_Client->createQueue(QSTR_APPNAME); m_queueId = m_Queue->getId(); m_portId = m_Port->getPortId(); m_smf = new QSmf(this); connect(m_smf, SIGNAL(signalSMFHeader(int,int,int)), SLOT(smfHeaderEvent(int,int,int))); connect(m_smf, SIGNAL(signalSMFNoteOn(int,int,int)), SLOT(smfNoteOnEvent(int,int,int))); connect(m_smf, SIGNAL(signalSMFNoteOff(int,int,int)), SLOT(smfNoteOffEvent(int,int,int))); connect(m_smf, SIGNAL(signalSMFKeyPress(int,int,int)), SLOT(smfKeyPressEvent(int,int,int))); connect(m_smf, SIGNAL(signalSMFCtlChange(int,int,int)), SLOT(smfCtlChangeEvent(int,int,int))); connect(m_smf, SIGNAL(signalSMFPitchBend(int,int)), SLOT(smfPitchBendEvent(int,int))); connect(m_smf, SIGNAL(signalSMFProgram(int,int)), SLOT(smfProgramEvent(int,int))); connect(m_smf, SIGNAL(signalSMFChanPress(int,int)), SLOT(smfChanPressEvent(int,int))); connect(m_smf, SIGNAL(signalSMFSysex(const QByteArray&)), SLOT(smfSysexEvent(const QByteArray&))); connect(m_smf, SIGNAL(signalSMFText(int,const QString&)), SLOT(smfUpdateLoadProgress())); connect(m_smf, SIGNAL(signalSMFTempo(int)), SLOT(smfTempoEvent(int))); connect(m_smf, SIGNAL(signalSMFTrackStart()), SLOT(smfUpdateLoadProgress())); connect(m_smf, SIGNAL(signalSMFTrackEnd()), SLOT(smfUpdateLoadProgress())); connect(m_smf, SIGNAL(signalSMFendOfTrack()), SLOT(smfUpdateLoadProgress())); connect(m_smf, SIGNAL(signalSMFError(const QString&)), SLOT(smfErrorHandler(const QString&))); m_wrk = new QWrk(this); connect(m_wrk, SIGNAL(signalWRKError(const QString&)), SLOT(wrkErrorHandler(const QString&))); connect(m_wrk, SIGNAL(signalWRKUnknownChunk(int,const QByteArray&)), SLOT(wrkUpdateLoadProgress())); connect(m_wrk, SIGNAL(signalWRKHeader(int,int)), SLOT(wrkFileHeader(int,int))); connect(m_wrk, SIGNAL(signalWRKEnd()), SLOT(wrkEndOfFile())); connect(m_wrk, SIGNAL(signalWRKStreamEnd(long)), SLOT(wrkStreamEndEvent(long))); connect(m_wrk, SIGNAL(signalWRKGlobalVars()), SLOT(wrkUpdateLoadProgress())); connect(m_wrk, SIGNAL(signalWRKTrack(const QString&, const QString&, int,int,int,int,int,bool,bool,bool)), SLOT(wrkTrackHeader(const QString&, const QString&, int,int,int,int,int,bool,bool,bool))); connect(m_wrk, SIGNAL(signalWRKTimeBase(int)), SLOT(wrkTimeBase(int))); connect(m_wrk, SIGNAL(signalWRKNote(int,long,int,int,int,int)), SLOT(wrkNoteEvent(int,long,int,int,int,int))); connect(m_wrk, SIGNAL(signalWRKKeyPress(int,long,int,int,int)), SLOT(wrkKeyPressEvent(int,long,int,int,int))); connect(m_wrk, SIGNAL(signalWRKCtlChange(int,long,int,int,int)), SLOT(wrkCtlChangeEvent(int,long,int,int,int))); connect(m_wrk, SIGNAL(signalWRKPitchBend(int,long,int,int)), SLOT(wrkPitchBendEvent(int,long,int,int))); connect(m_wrk, SIGNAL(signalWRKProgram(int,long,int,int)), SLOT(wrkProgramEvent(int,long,int,int))); connect(m_wrk, SIGNAL(signalWRKChanPress(int,long,int,int)), SLOT(wrkChanPressEvent(int,long,int,int))); connect(m_wrk, SIGNAL(signalWRKSysexEvent(int,long,int)), SLOT(wrkSysexEvent(int,long,int))); connect(m_wrk, SIGNAL(signalWRKSysex(int,const QString&,bool,int,const QByteArray&)), SLOT(wrkSysexEventBank(int,const QString&,bool,int,const QByteArray&))); connect(m_wrk, SIGNAL(signalWRKText(int,long,int,const QString&)), SLOT(wrkUpdateLoadProgress())); connect(m_wrk, SIGNAL(signalWRKTimeSig(int,int,int)), SLOT(wrkUpdateLoadProgress())); connect(m_wrk, SIGNAL(signalWRKKeySig(int,int)), SLOT(wrkUpdateLoadProgress())); connect(m_wrk, SIGNAL(signalWRKTempo(long,int)), SLOT(wrkTempoEvent(long,int))); connect(m_wrk, SIGNAL(signalWRKTrackPatch(int,int)), SLOT(wrkTrackPatch(int,int))); connect(m_wrk, SIGNAL(signalWRKComments(const QString&)), SLOT(wrkUpdateLoadProgress())); connect(m_wrk, SIGNAL(signalWRKVariableRecord(const QString&,const QByteArray&)), SLOT(wrkUpdateLoadProgress())); connect(m_wrk, SIGNAL(signalWRKNewTrack(const QString&,int,int,int,int,int,bool,bool,bool)), SLOT(wrkNewTrackHeader(const QString&,int,int,int,int,int,bool,bool,bool))); connect(m_wrk, SIGNAL(signalWRKTrackName(int,const QString&)), SLOT(wrkUpdateLoadProgress())); connect(m_wrk, SIGNAL(signalWRKTrackVol(int,int)), SLOT(wrkTrackVol(int,int))); connect(m_wrk, SIGNAL(signalWRKTrackBank(int,int)), SLOT(wrkTrackBank(int,int))); connect(m_wrk, SIGNAL(signalWRKSegment(int,long,const QString&)), SLOT(wrkUpdateLoadProgress())); connect(m_wrk, SIGNAL(signalWRKChord(int,long,const QString&,const QByteArray&)), SLOT(wrkUpdateLoadProgress())); connect(m_wrk, SIGNAL(signalWRKExpression(int,long,int,const QString&)), SLOT(wrkUpdateLoadProgress())); m_ove = new QOve(this); connect(m_ove, SIGNAL(signalOVEError(const QString&)), SLOT(oveErrorHandler(const QString&))); connect(m_ove, SIGNAL(signalOVEHeader(int,int)), SLOT(oveFileHeader(int,int))); connect(m_ove, SIGNAL(signalOVEEnd()), SLOT(wrkEndOfFile())); connect(m_ove, SIGNAL(signalOVENoteOn(int, long, int, int, int)), SLOT(oveNoteOnEvent(int, long, int, int, int))); connect(m_ove, SIGNAL(signalOVENoteOff(int, long, int, int, int)), SLOT(oveNoteOffEvent(int, long, int, int, int))); connect(m_ove, SIGNAL(signalOVEKeyPress(int,long,int,int,int)), SLOT(wrkKeyPressEvent(int,long,int,int,int))); connect(m_ove, SIGNAL(signalOVECtlChange(int,long,int,int,int)), SLOT(wrkCtlChangeEvent(int,long,int,int,int))); connect(m_ove, SIGNAL(signalOVEPitchBend(int,long,int,int)), SLOT(wrkPitchBendEvent(int,long,int,int))); connect(m_ove, SIGNAL(signalOVEProgram(int,long,int,int)), SLOT(wrkProgramEvent(int,long,int,int))); connect(m_ove, SIGNAL(signalOVEChanPress(int,long,int,int)), SLOT(wrkChanPressEvent(int,long,int,int))); connect(m_ove, SIGNAL(signalOVESysexEvent(int,long,int)), SLOT(wrkSysexEvent(int,long,int))); connect(m_ove, SIGNAL(signalOVESysex(int,const QString&,bool,int,const QByteArray&)), SLOT(wrkSysexEventBank(int,const QString&,bool,int,const QByteArray&))); connect(m_ove, SIGNAL(signalOVETempo(long,int)), SLOT(wrkTempoEvent(long,int))); connect(m_ove, SIGNAL(signalOVETrackPatch(int,int,int)), SLOT(oveTrackPatch(int,int,int))); connect(m_ove, SIGNAL(signalOVENewTrack(const QString&,int,int,int,int,int,bool,bool,bool)), SLOT(wrkNewTrackHeader(const QString&,int,int,int,int,int,bool,bool,bool))); connect(m_ove, SIGNAL(signalOVETrackVol(int,int,int)), SLOT(wrkTrackVol(int,int))); connect(m_ove, SIGNAL(signalOVETrackBank(int,int,int)), SLOT(oveTrackBank(int,int,int))); m_player = new Player(m_Client, m_portId); connect(m_player, SIGNAL(finished()), SLOT(songFinished())); connect(m_player, SIGNAL(stopped()), SLOT(playerStopped())); m_Client->setRealTimeInput(false); m_Client->startSequencerInput(); tempoReset(); volumeReset(); updateState(EmptyState); } GUIPlayer::~GUIPlayer() { m_Client->stopSequencerInput(); m_Port->detach(); m_Client->close(); delete m_player; } void GUIPlayer::subscribe(const QString& portName) { try { if (!m_subscription.isEmpty()) { m_Port->unsubscribeTo(m_subscription); } m_subscription = portName; m_Port->subscribeTo(m_subscription); } catch (const SequencerError& err) { qWarning() << "SequencerError exception. Error code: " << err.code() << " (" << err.qstrError() << ")"; qWarning() << "Location: " << err.location(); } } void GUIPlayer::updateTimeLabel(int mins, int secs, int cnts) { static QChar fill('0'); QString stime = QString("%1:%2.%3").arg(mins,2,10,fill) .arg(secs,2,10,fill) .arg(cnts,2,10,fill); m_ui->lblTime->setText(stime); } void GUIPlayer::updateState(PlayerState newState) { if (m_state == newState) return; switch (newState) { case EmptyState: m_ui->actionPlay->setEnabled(false); m_ui->actionPause->setEnabled(false); m_ui->actionStop->setEnabled(false); statusBar()->showMessage("Please, load a song"); break; case PlayingState: m_ui->actionPlay->setEnabled(false); m_ui->actionPause->setEnabled(true); m_ui->actionStop->setEnabled(true); statusBar()->showMessage("Playing"); break; case PausedState: m_ui->actionPlay->setEnabled(false); m_ui->actionStop->setEnabled(true); statusBar()->showMessage("Paused"); break; case StoppedState: m_ui->actionPause->setChecked(false); m_ui->actionPause->setEnabled(false); m_ui->actionStop->setEnabled(false); m_ui->actionPlay->setEnabled(true); statusBar()->showMessage("Stopped"); break; default: statusBar()->showMessage("Not initialized"); break; } m_state = newState; } void GUIPlayer::play() { if (!m_song->isEmpty()) { if (m_player->getInitialPosition() == 0) { if (m_initialTempo == 0) return; QueueTempo firstTempo = m_Queue->getTempo(); firstTempo.setPPQ(m_song->getDivision()); firstTempo.setTempo(m_initialTempo); firstTempo.setTempoFactor(m_tempoFactor); m_Queue->setTempo(firstTempo); m_Client->drainOutput(); m_player->sendVolumeEvents(); } m_player->start(); updateState(PlayingState); } } void GUIPlayer::pause() { if (m_state == PlayingState || m_player->isRunning()) { m_player->stop(); m_player->setPosition(m_Queue->getStatus().getTickTime()); updateState(PausedState); } else if (!m_song->isEmpty()) { m_player->start(); updateState(PlayingState); } } void GUIPlayer::stop() { if (m_state == PlayingState || m_state == PausedState || m_player->isRunning()) m_player->stop(); if (m_initialTempo != 0) songFinished(); else updateState(StoppedState); } void GUIPlayer::progressDialogInit(const QString& type, int max) { m_pd = new QProgressDialog(0, 0, 0, max, this); m_pd->setWindowTitle(QString("Loading %1 file...").arg(type)); m_pd->setMinimumDuration(1000); m_pd->setValue(0); } void GUIPlayer::progressDialogUpdate(int pos) { if (m_pd != 0) { m_pd->setValue(pos); qApp->processEvents(); } } void GUIPlayer::progressDialogClose() { delete m_pd; // set to 0 by QPointer<> } void GUIPlayer::openFile(const QString& fileName) { QFileInfo finfo(fileName); if (finfo.exists()) { m_song->clear(); m_loadingMessages.clear(); m_tick = 0; m_initialTempo = 0; try { QString ext = finfo.suffix().toLower(); if (ext == "wrk") { progressDialogInit("Cakewalk", finfo.size()); m_wrk->readFromFile(fileName); } else if (ext == "mid" || ext == "midi" || ext == "kar") { progressDialogInit("MIDI", finfo.size()); m_smf->readFromFile(fileName); } else if (ext == "ove") { m_ove->readFromFile(fileName); } progressDialogUpdate(finfo.size()); if (m_song->isEmpty()) { m_ui->lblName->clear(); } else { m_song->sort(); m_player->setSong(m_song); m_ui->lblName->setText(finfo.fileName()); m_lastDirectory = finfo.absolutePath(); } } catch (...) { m_song->clear(); m_ui->lblName->clear(); } progressDialogClose(); if (m_initialTempo == 0) { m_initialTempo = 500000; } updateTimeLabel(0,0,0); updateTempoLabel(6.0e7f / m_initialTempo); m_ui->progressBar->setValue(0); if (!m_loadingMessages.isEmpty()) { m_loadingMessages.insert(0, "Warning, this file may be non-standard or damaged.
"); QMessageBox::warning(this, QSTR_APPNAME, m_loadingMessages); } if (m_song->isEmpty()) updateState(EmptyState); else updateState(StoppedState); } } void GUIPlayer::open() { QString fileName = QFileDialog::getOpenFileName(this, "Open MIDI File", m_lastDirectory, "All files (*.kar *.mid *.midi *.ove *.wrk);;" "Karaoke files (*.kar);;" "MIDI Files (*.mid *.midi);;" "Overture Files (*.ove);;" "Cakewalk files (*.wrk)" ); if (! fileName.isEmpty() ) { stop(); openFile(fileName); } } void GUIPlayer::setup() { bool ok; int current; QStringList items; QListIterator it(m_Client->getAvailableOutputs()); while(it.hasNext()) { PortInfo p = it.next(); items << QString("%1:%2").arg(p.getClientName()).arg(p.getPort()); } current = items.indexOf(m_subscription); QString item = QInputDialog::getItem(this, "Player subscription", "Output port:", items, current, false, &ok); if (ok && !item.isEmpty()) subscribe(item); } void GUIPlayer::songFinished() { m_player->resetPosition(); updateState(StoppedState); } void GUIPlayer::playerStopped() { int portId = m_Port->getPortId(); for (int channel = 0; channel < 16; ++channel) { ControllerEvent ev1(channel, MIDI_CTL_ALL_NOTES_OFF, 0); ev1.setSource(portId); ev1.setSubscribers(); ev1.setDirect(); m_Client->outputDirect(&ev1); ControllerEvent ev2(channel, MIDI_CTL_ALL_SOUNDS_OFF, 0); ev2.setSource(portId); ev2.setSubscribers(); ev2.setDirect(); m_Client->outputDirect(&ev2); } m_Client->drainOutput(); } void GUIPlayer::updateTempoLabel(float ftempo) { QString stempo = QString("%1 bpm").arg(ftempo, 0, 'f', 2); m_ui->lblOther->setText(stempo); } void GUIPlayer::sequencerEvent(SequencerEvent *ev) { if ((ev->getSequencerType() == SND_SEQ_EVENT_ECHO) && (m_tick != 0)){ int pos = 100 * ev->getTick() / m_tick; const snd_seq_real_time_t* rt = m_Queue->getStatus().getRealtime(); int mins = rt->tv_sec / 60; int secs = rt->tv_sec % 60; int cnts = qFloor( rt->tv_nsec / 1.0e7 ); updateTempoLabel(m_Queue->getTempo().getRealBPM()); updateTimeLabel(mins, secs, cnts); m_ui->progressBar->setValue(pos); } delete ev; } void GUIPlayer::pitchShift(int value) { m_player->setPitchShift(value); } void GUIPlayer::tempoReset() { m_ui->sliderTempo->setValue(100); tempoSlider(100); } void GUIPlayer::volumeReset() { m_ui->volumeSlider->setValue(100); volumeSlider(100); } void GUIPlayer::tempoSlider(int value) { m_tempoFactor = (value*value + 100.0*value + 20000.0) / 40000.0; QueueTempo qtempo = m_Queue->getTempo(); qtempo.setTempoFactor(m_tempoFactor); m_Queue->setTempo(qtempo); m_Client->drainOutput(); if (!m_player->isRunning()) updateTempoLabel(qtempo.getRealBPM()); // Slider tooltip QString tip = QString("%1\%").arg(m_tempoFactor*100.0, 0, 'f', 0); m_ui->sliderTempo->setToolTip(tip); QToolTip::showText(QCursor::pos(), tip, this); } void GUIPlayer::volumeSlider(int value) { QString tip = QString::number(value)+'%'; m_ui->lblVolume->setText(tip); m_ui->volumeSlider->setToolTip(tip); m_player->setVolumeFactor(value); QToolTip::showText(QCursor::pos(), tip, this); } void GUIPlayer::dragEnterEvent( QDragEnterEvent * event ) { if (event->mimeData()->hasFormat("text/uri-list")) event->acceptProposedAction(); } void GUIPlayer::dropEvent( QDropEvent * event ) { QString data = event->mimeData()->text(); QString fileName = QUrl(data).path().trimmed(); while (fileName.endsWith(QChar::Null)) fileName.chop(1); if ( fileName.endsWith(".ove", Qt::CaseInsensitive) || fileName.endsWith(".mid", Qt::CaseInsensitive) || fileName.endsWith(".midi", Qt::CaseInsensitive) || fileName.endsWith(".kar", Qt::CaseInsensitive) || fileName.endsWith(".wrk", Qt::CaseInsensitive) ) { stop(); openFile(fileName); event->accept(); } else { QMessageBox::warning(this, QSTR_APPNAME, QString("Dropped file %1 is not supported").arg(fileName)); } } //bool GUIPlayer::event( QEvent * event ) //{ // if(event->type() == QEvent::Polish) { // readSettings(); // /* Process the command line arguments. // The first argument should be a MIDI file name */ // QStringList args = QCoreApplication::arguments(); // if (args.size() > 1) { // QString first = args.at(1); // openFile(first); // } // event->accept(); // } // return QMainWindow::event(event); //} void GUIPlayer::readSettings() { QSettings settings; settings.beginGroup("Window"); restoreGeometry(settings.value("Geometry").toByteArray()); restoreState(settings.value("State").toByteArray()); settings.endGroup(); settings.beginGroup("Preferences"); m_lastDirectory = settings.value("LastDirectory").toString(); QString midiConn = settings.value("MIDIConnection").toString(); settings.endGroup(); if (midiConn.length() > 0) subscribe(midiConn); } void GUIPlayer::writeSettings() { QSettings settings; settings.beginGroup("Window"); settings.setValue("Geometry", saveGeometry()); settings.setValue("State", saveState()); settings.endGroup(); settings.beginGroup("Preferences"); settings.setValue("LastDirectory", m_lastDirectory); settings.setValue("MIDIConnection", m_subscription); settings.endGroup(); } void GUIPlayer::closeEvent( QCloseEvent *event ) { stop(); m_player->wait(); writeSettings(); event->accept(); } void GUIPlayer::about() { if (m_aboutDlg == 0) m_aboutDlg = new About(this); m_aboutDlg->exec(); } void GUIPlayer::aboutQt() { qApp->aboutQt(); } /* **************************************** * * SMF (Standard MIDI file) format handling * **************************************** */ void GUIPlayer::smfUpdateLoadProgress() { progressDialogUpdate(m_smf->getFilePos()); } void GUIPlayer::appendSMFEvent(SequencerEvent* ev) { unsigned long tick = m_smf->getCurrentTime(); ev->setSource(m_portId); if (ev->getSequencerType() != SND_SEQ_EVENT_TEMPO) { ev->setSubscribers(); } ev->scheduleTick(m_queueId, tick, false); m_song->append(ev); if (tick > m_tick) m_tick = tick; smfUpdateLoadProgress(); } void GUIPlayer::smfHeaderEvent(int format, int ntrks, int division) { m_song->setHeader(format, ntrks, division); smfUpdateLoadProgress(); } void GUIPlayer::smfNoteOnEvent(int chan, int pitch, int vol) { SequencerEvent* ev = new NoteOnEvent (chan, pitch, vol); appendSMFEvent(ev); } void GUIPlayer::smfNoteOffEvent(int chan, int pitch, int vol) { SequencerEvent* ev = new NoteOffEvent (chan, pitch, vol); appendSMFEvent(ev); } void GUIPlayer::smfKeyPressEvent(int chan, int pitch, int press) { SequencerEvent* ev = new KeyPressEvent (chan, pitch, press); appendSMFEvent(ev); } void GUIPlayer::smfCtlChangeEvent(int chan, int ctl, int value) { SequencerEvent* ev = new ControllerEvent (chan, ctl, value); appendSMFEvent(ev); } void GUIPlayer::smfPitchBendEvent(int chan, int value) { SequencerEvent* ev = new PitchBendEvent (chan, value); appendSMFEvent(ev); } void GUIPlayer::smfProgramEvent(int chan, int patch) { SequencerEvent* ev = new ProgramChangeEvent (chan, patch); appendSMFEvent(ev); } void GUIPlayer::smfChanPressEvent(int chan, int press) { SequencerEvent* ev = new ChanPressEvent (chan, press); appendSMFEvent(ev); } void GUIPlayer::smfSysexEvent(const QByteArray& data) { SequencerEvent* ev = new SysExEvent (data); appendSMFEvent(ev); } void GUIPlayer::smfTempoEvent(int tempo) { if ( m_initialTempo == 0 ) { m_initialTempo = tempo; } SequencerEvent* ev = new TempoEvent (m_queueId, tempo); appendSMFEvent(ev); } void GUIPlayer::smfErrorHandler(const QString& errorStr) { if (m_loadingMessages.length() < 1024) m_loadingMessages.append(QString("%1 at file offset %2
") .arg(errorStr).arg(m_smf->getFilePos())); } /* ********************************* * * Cakewalk WRK file format handling * ********************************* */ void GUIPlayer::wrkUpdateLoadProgress() { if (m_pd != 0) progressDialogUpdate(m_wrk->getFilePos()); } void GUIPlayer::appendWRKEvent(unsigned long ticks, SequencerEvent* ev) { ev->setSource(m_portId); if (ev->getSequencerType() != SND_SEQ_EVENT_TEMPO) { ev->setSubscribers(); } ev->scheduleTick(m_queueId, ticks, false); m_song->append(ev); if (ticks > m_tick) m_tick = ticks; wrkUpdateLoadProgress(); } void GUIPlayer::wrkErrorHandler(const QString& errorStr) { if (m_loadingMessages.length() < 1024) m_loadingMessages.append(QString("%1 at file offset %2
") .arg(errorStr).arg(m_wrk->getFilePos())); } void GUIPlayer::wrkFileHeader(int /*verh*/, int /*verl*/) { m_song->setHeader(1, 0, 120); wrkUpdateLoadProgress(); } void GUIPlayer::wrkTimeBase(int timebase) { m_song->setDivision(timebase); wrkUpdateLoadProgress(); } void GUIPlayer::wrkStreamEndEvent(long time) { unsigned long ticks = time; if (ticks > m_tick) m_tick = ticks; wrkUpdateLoadProgress(); } void GUIPlayer::wrkTrackHeader( const QString& /*name1*/, const QString& /*name2*/, int trackno, int channel, int pitch, int velocity, int /*port*/, bool /*selected*/, bool /*muted*/, bool /*loop*/ ) { TrackMapRec rec; rec.channel = channel; rec.pitch = pitch; rec.velocity = velocity; m_trackMap[trackno] = rec; wrkUpdateLoadProgress(); } void GUIPlayer::wrkNoteEvent(int track, long time, int chan, int pitch, int vol, int dur) { int channel = chan; TrackMapRec rec = m_trackMap[track]; int key = pitch + rec.pitch; int velocity = vol + rec.velocity; if (rec.channel > -1) channel = rec.channel; SequencerEvent* ev = new NoteEvent(channel, key, velocity, dur); appendWRKEvent(time, ev); } void GUIPlayer::wrkKeyPressEvent(int track, long time, int chan, int pitch, int press) { int channel = chan; TrackMapRec rec = m_trackMap[track]; int key = pitch + rec.pitch; if (rec.channel > -1) channel = rec.channel; SequencerEvent* ev = new KeyPressEvent(channel, key, press); appendWRKEvent(time, ev); } void GUIPlayer::wrkCtlChangeEvent(int track, long time, int chan, int ctl, int value) { int channel = chan; TrackMapRec rec = m_trackMap[track]; if (rec.channel > -1) channel = rec.channel; SequencerEvent* ev = new ControllerEvent(channel, ctl, value); appendWRKEvent(time, ev); } void GUIPlayer::wrkPitchBendEvent(int track, long time, int chan, int value) { int channel = chan; TrackMapRec rec = m_trackMap[track]; if (rec.channel > -1) channel = rec.channel; SequencerEvent* ev = new PitchBendEvent(channel, value); appendWRKEvent(time, ev); } void GUIPlayer::wrkProgramEvent(int track, long time, int chan, int patch) { int channel = chan; TrackMapRec rec = m_trackMap[track]; if (rec.channel > -1) channel = rec.channel; SequencerEvent* ev = new ProgramChangeEvent(channel, patch); appendWRKEvent(time, ev); } void GUIPlayer::wrkChanPressEvent(int track, long time, int chan, int press) { int channel = chan; TrackMapRec rec = m_trackMap[track]; if (rec.channel > -1) channel = rec.channel; SequencerEvent* ev = new ChanPressEvent(channel, press); appendWRKEvent(time, ev); } void GUIPlayer::wrkSysexEvent(int track, long time, int bank) { SysexEventRec rec; rec.track = track; rec.time = time; rec.bank = bank; m_savedSysexEvents.append(rec); wrkUpdateLoadProgress(); } void GUIPlayer::wrkSysexEventBank(int bank, const QString& /*name*/, bool autosend, int /*port*/, const QByteArray& data) { SysExEvent* ev = new SysExEvent(data); if (autosend) appendWRKEvent(0, ev->clone()); foreach(const SysexEventRec& rec, m_savedSysexEvents) { if (rec.bank == bank) { appendWRKEvent(rec.time, ev->clone()); } } delete ev; wrkUpdateLoadProgress(); } void GUIPlayer::wrkTempoEvent(long time, int tempo) { double bpm = tempo / 100.0; if ( m_initialTempo < 0 ) m_initialTempo = qRound( bpm ); SequencerEvent* ev = new TempoEvent(m_queueId, qRound ( 6e7 / bpm ) ); appendWRKEvent(time, ev); } void GUIPlayer::wrkTrackPatch(int track, int patch) { int channel = 0; TrackMapRec rec = m_trackMap[track]; if (rec.channel > -1) channel = rec.channel; wrkProgramEvent(track, 0, channel, patch); } void GUIPlayer::wrkNewTrackHeader( const QString& /*name*/, int trackno, int channel, int pitch, int velocity, int /*port*/, bool /*selected*/, bool /*muted*/, bool /*loop*/ ) { TrackMapRec rec; rec.channel = channel; rec.pitch = pitch; rec.velocity = velocity; m_trackMap[trackno] = rec; wrkUpdateLoadProgress(); } void GUIPlayer::wrkTrackVol(int track, int vol) { int channel = 0; int lsb, msb; TrackMapRec rec = m_trackMap[track]; if (rec.channel > -1) channel = rec.channel; if (vol < 128) wrkCtlChangeEvent(track, 0, channel, MIDI_CTL_MSB_MAIN_VOLUME, vol); else { lsb = vol % 0x80; msb = vol / 0x80; wrkCtlChangeEvent(track, 0, channel, MIDI_CTL_LSB_MAIN_VOLUME, lsb); wrkCtlChangeEvent(track, 0, channel, MIDI_CTL_MSB_MAIN_VOLUME, msb); } } void GUIPlayer::wrkTrackBank(int track, int bank) { // assume GM/GS bank method int channel = 0; int lsb, msb; TrackMapRec rec = m_trackMap[track]; if (rec.channel > -1) channel = rec.channel; lsb = bank % 0x80; msb = bank / 0x80; wrkCtlChangeEvent(track, 0, channel, MIDI_CTL_MSB_BANK, msb); wrkCtlChangeEvent(track, 0, channel, MIDI_CTL_LSB_BANK, lsb); } void GUIPlayer::wrkEndOfFile() { if (m_initialTempo < 0) m_initialTempo = 120; SequencerEvent* ev = new SystemEvent(SND_SEQ_EVENT_ECHO); appendWRKEvent(m_tick, ev); } /* ********************************* * * Overture OVE file format handling * ********************************* */ void GUIPlayer::appendOVEEvent(unsigned long ticks, SequencerEvent* ev) { ev->setSource(m_portId); if (ev->getSequencerType() != SND_SEQ_EVENT_TEMPO) ev->setSubscribers(); ev->scheduleTick(m_queueId, ticks, false); m_song->append(ev); if (ticks > m_tick) m_tick = ticks; } void GUIPlayer::oveErrorHandler(const QString& errorStr) { if (m_loadingMessages.length() < 1024) m_loadingMessages.append(errorStr); } void GUIPlayer::oveFileHeader(int quarter, int trackCount) { m_song->setHeader(1, trackCount, quarter); } void GUIPlayer::oveNoteOnEvent(int /*track*/, long tick, int channel, int pitch, int vol) { SequencerEvent* ev = new NoteOnEvent(channel, pitch, vol); appendOVEEvent(tick, ev); } void GUIPlayer::oveNoteOffEvent(int /*track*/, long tick, int channel, int pitch, int vol) { SequencerEvent* ev = new NoteOffEvent(channel, pitch, vol); appendOVEEvent(tick, ev); } void GUIPlayer::oveTrackPatch(int track, int channel, int patch) { int ch = channel; TrackMapRec rec = m_trackMap[track]; if (rec.channel > -1) ch = rec.channel; wrkProgramEvent(track, 0, ch, patch); } void GUIPlayer::oveTrackVol(int track, int channel, int vol) { int ch = channel; int lsb, msb; TrackMapRec rec = m_trackMap[track]; if (rec.channel > -1) ch = rec.channel; if (vol < 128) wrkCtlChangeEvent(track, 0, ch, MIDI_CTL_MSB_MAIN_VOLUME, vol); else { lsb = vol % 0x80; msb = vol / 0x80; wrkCtlChangeEvent(track, 0, ch, MIDI_CTL_LSB_MAIN_VOLUME, lsb); wrkCtlChangeEvent(track, 0, ch, MIDI_CTL_MSB_MAIN_VOLUME, msb); } } void GUIPlayer::oveTrackBank(int track, int channel, int bank) { // assume GM/GS bank method int ch = channel; int lsb, msb; TrackMapRec rec = m_trackMap[track]; if (rec.channel > -1) ch = rec.channel; lsb = bank % 0x80; msb = bank / 0x80; wrkCtlChangeEvent(track, 0, ch, MIDI_CTL_MSB_BANK, msb); wrkCtlChangeEvent(track, 0, ch, MIDI_CTL_LSB_BANK, lsb); } drumstick-1.1.3/utils/guiplayer/PaxHeaders.32572/playerabout.ui0000644000000000000000000000013213532747316021322 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/playerabout.ui0000644000175000001440000001326313532747316022120 0ustar00pedrousers00000000000000 AboutClass 0 0 468 337 About :/resources/drumstick.png:/resources/drumstick.png false true <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600;">Drumstick MIDI Player %VERSION%</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Sample application for the <a href="http://drumstick.sourceforge.net"><span style=" font-family:'DejaVu Sans'; text-decoration: underline; color:#0057ae;">Drumstick MIDI Sequencer C++ library</span></a></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copyright © 2006-2019, Pedro Lopez-Cabanillas &lt;<a href="mailto:plcl@users.sf.net"><span style=" font-family:'DejaVu Sans'; text-decoration: underline; color:#0057ae;">plcl@users.sf.net</span></a>&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">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.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You should have received a copy of the GNU General Public License along with this program. If not, see </span><a href="http://www.gnu.org/licenses/"><span style=" text-decoration: underline; color:#0057ae;">http://www.gnu.org/licenses/</span></a><span style=" font-size:8pt;">.</span></p></body></html> true About Qt :/resources/qtlogo.png:/resources/qtlogo.png QDialogButtonBox::Close buttonBox rejected() AboutClass close() 306 315 325 335 drumstick-1.1.3/utils/guiplayer/PaxHeaders.32572/drumstick-guiplayer.desktop0000644000000000000000000000013213532747316024033 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/drumstick-guiplayer.desktop0000644000175000001440000000051613532747316024626 0ustar00pedrousers00000000000000[Desktop Entry] Name=Drumstick MIDI Player Exec=drumstick-guiplayer %f Icon=drumstick Terminal=false Type=Application Categories=AudioVideo;Audio;Midi;Education;Music; Keywords=Music;Midi;Player; MimeType=audio/midi;audio/x-midi;audio/cakewalk;audio/overture; Comment=Drumstick MIDI Player Comment[es]=Reproductor MIDI de Drumstick drumstick-1.1.3/utils/guiplayer/PaxHeaders.32572/playerabout.h0000644000000000000000000000013213532747316021134 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/playerabout.h0000644000175000001440000000203013532747316021720 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef ABOUT_H #define ABOUT_H #include #include "ui_playerabout.h" class About : public QDialog { Q_OBJECT public: About(QWidget *parent = 0); public slots: void aboutQt(); private: Ui::AboutClass ui; }; #endif // ABOUT_H drumstick-1.1.3/utils/guiplayer/PaxHeaders.32572/player.cpp0000644000000000000000000000013213532747316020434 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/player.cpp0000644000175000001440000001120613532747316021225 0ustar00pedrousers00000000000000/* SMF GUI Player test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include "player.h" #include "song.h" #include Player::Player(MidiClient *seq, int portId) : SequencerOutputThread(seq, portId), m_song(0), m_songIterator(0), m_lastEvent(0), m_songPosition(0), m_echoResolution(0), m_pitchShift(0), m_volumeFactor(100) { for (int chan = 0; chan < MIDI_CHANNELS; ++chan) m_volume[chan] = 100; } Player::~Player() { if (isRunning()) { stop(); } if (m_songIterator != 0) delete m_songIterator; if (m_lastEvent != 0) delete m_lastEvent; } void Player::setSong(Song* s) { m_song = s; if (m_song != NULL) { if (m_songIterator != NULL) { delete m_songIterator; } m_songIterator = new SongIterator(*m_song); m_echoResolution = m_song->getDivision() / 12; m_songPosition = 0; } } void Player::resetPosition() { if ((m_song != NULL) && (m_songIterator != NULL)) { m_songIterator->toFront(); m_songPosition = 0; } } void Player::setPosition(unsigned int pos) { m_songPosition = pos; m_songIterator->toFront(); while (m_songIterator->hasNext() && (m_songIterator->next()->getTick() < pos)) { }; if (m_songIterator->hasPrevious()) m_songIterator->previous(); } bool Player::hasNext() { return m_songIterator->hasNext(); } SequencerEvent* Player::nextEvent() { if (m_lastEvent != 0) delete m_lastEvent; m_lastEvent = m_songIterator->next()->clone(); switch (m_lastEvent->getSequencerType()) { case SND_SEQ_EVENT_NOTE: case SND_SEQ_EVENT_NOTEON: case SND_SEQ_EVENT_NOTEOFF: case SND_SEQ_EVENT_KEYPRESS: { KeyEvent* kev = static_cast(m_lastEvent); if (kev->getChannel() != MIDI_GM_DRUM_CHANNEL) kev->setKey(kev->getKey() + m_pitchShift); } break; case SND_SEQ_EVENT_CONTROLLER: { ControllerEvent *cev = static_cast(m_lastEvent); if (cev->getParam() == MIDI_CTL_MSB_MAIN_VOLUME) { int chan = cev->getChannel(); int value = cev->getValue(); m_volume[chan] = value; value = floor(value * m_volumeFactor / 100.0); if (value < 0) value = 0; if (value > 127) value = 127; cev->setValue(value); } } break; } return m_lastEvent; } void Player::setPitchShift(unsigned int pitch) { bool playing = isRunning(); if (playing) { stop(); unsigned int pos = m_Queue->getStatus().getTickTime(); m_Queue->clear(); allNotesOff(); setPosition(pos); } m_pitchShift = pitch; if (playing) start(); } void Player::setVolumeFactor(unsigned int vol) { m_volumeFactor = vol; for(int chan = 0; chan < MIDI_CHANNELS; ++chan) { int value = m_volume[chan]; value = floor(value * m_volumeFactor / 100.0); if (value < 0) value = 0; if (value > 127) value = 127; sendController(chan, MIDI_CTL_MSB_MAIN_VOLUME, value); } } void Player::sendController(int chan, int control, int value) { ControllerEvent ev(chan, control, value); ev.setSource(m_PortId); ev.setSubscribers(); ev.setDirect(); sendSongEvent(&ev); } void Player::allNotesOff() { for(int chan = 0; chan < MIDI_CHANNELS; ++chan) { sendController(chan, MIDI_CTL_ALL_NOTES_OFF, 0); sendController(chan, MIDI_CTL_ALL_SOUNDS_OFF, 0); } } void Player::sendVolumeEvents() { for(int chan = 0; chan < MIDI_CHANNELS; ++chan) { int value = m_volume[chan] = 100; value = floor(value * m_volumeFactor / 100.0); if (value < 0) value = 0; if (value > 127) value = 127; sendController(chan, MIDI_CTL_MSB_MAIN_VOLUME, value); } } drumstick-1.1.3/utils/guiplayer/PaxHeaders.32572/playerabout.cpp0000644000000000000000000000013213532747316021467 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/playerabout.cpp0000644000175000001440000000222513532747316022261 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "playerabout.h" #include "cmdversion.h" About::About(QWidget *parent) : QDialog(parent) { ui.setupUi(this); QString aboutText = ui.AboutTextView->toHtml(); aboutText.replace("%VERSION%", PGM_VERSION); ui.AboutTextView->setHtml(aboutText); connect (ui.aboutQt, SIGNAL(clicked()), SLOT(aboutQt())); } void About::aboutQt() { qApp->aboutQt(); } drumstick-1.1.3/utils/guiplayer/PaxHeaders.32572/resources0000644000000000000000000000013213532747316020371 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/resources/0000755000175000001440000000000013532747316021237 5ustar00pedrousers00000000000000drumstick-1.1.3/utils/guiplayer/resources/PaxHeaders.32572/qtlogo.png0000644000000000000000000000013213532747316022461 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/resources/qtlogo.png0000644000175000001440000000126113532747316023252 0ustar00pedrousers00000000000000PNG  IHDRabKGD pHYs@tIME %$#+>IDAT8}MHTaO3wqь! +haVAP-2lѢE?rYZHRJ!J_* ͟bi̽Zӌ/p2]GEN0)G!3#'҆26ȑX7SHJ,KT0" Jگ/ ;Waϑ;@*{IC" FOkd3q>ڛp.[:Mu12qǥϻ qxsG8;.q[6OKq0b1SySGPMRzS- @U[|wlͽeĎ&?``wh[Z[l 4(p> ðbG1*XNF>\į&„ٗ 4B a^T $!0#;^\H8UއyŽBt8Rm ^Z&u!m lAyh44'_j5XVbs -ùT3*!wzR_Nn,7 vvrpf dۏ^|mZp6cqSL`"PDJŹ_w[oߧB㑍|1E= 6޼y\r{Hatddd6slc.e T 4]5~bf=t`xLIENDB`drumstick-1.1.3/utils/guiplayer/resources/PaxHeaders.32572/stop.png0000644000000000000000000000013213532747316022141 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/resources/stop.png0000644000175000001440000000025613532747316022735 0ustar00pedrousers00000000000000PNG  IHDR%=m"gAMA aPLTEU~tRNS@6:bKGDH pHYs  #utIME IDATxc`@#$x[RIENDB`drumstick-1.1.3/utils/guiplayer/resources/PaxHeaders.32572/drumstick.png0000644000000000000000000000013213532747316023161 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/resources/drumstick.png0000644000175000001440000000103613532747316023752 0ustar00pedrousers00000000000000PNG  IHDRasBIT|d pHYsNtEXtSoftwarewww.inkscape.org<IDAT8Kﳭ{׻" H/bD!(b)LA֭i%:B)"QT(ba(fcctק"?DU$  "rǝuΝ>bqJ|MQUD|b 4,쨅mY彅 lRgwQZެVZ ˛t9>$#@:뗸8pNPcG#Hm#esG':AY#S]+nyKEWnTӞhR7VJ d2[᚜h G3'pA\>MWȆ ;ܕ?("zIQ-֙a3\&QoASZD$D+ȑ( x+~,TRHIENDB`drumstick-1.1.3/utils/guiplayer/resources/PaxHeaders.32572/play.png0000644000000000000000000000013213532747316022121 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/resources/play.png0000644000175000001440000000023713532747316022714 0ustar00pedrousers00000000000000PNG  IHDRagAMA a pHYs  ~AIDATxc`? (5DBc^C5!@ )1fb jNųIENDB`drumstick-1.1.3/utils/guiplayer/resources/PaxHeaders.32572/quit.png0000644000000000000000000000013213532747316022136 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/resources/quit.png0000644000175000001440000000032413532747316022726 0ustar00pedrousers00000000000000PNG  IHDRaIDATxڭ !FM7NTgq`\IH?boVڳ(tW ^re c4S,!jv* y;] d'yk-@7 &;h$X$l5P/%(Z&t>F¡IENDB`drumstick-1.1.3/utils/guiplayer/resources/PaxHeaders.32572/open.png0000644000000000000000000000013213532747316022115 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/resources/open.png0000644000175000001440000000040513532747316022705 0ustar00pedrousers00000000000000PNG  IHDRaIDATxڥS 0 sNlB l#AM:H!GR|e *}TՙfZavc4H)yK̢59#"rUO{ђv3;avM"O,0B"ԃeCm.1맃;|]хGl/C6`yEuEqpx# PL1GO*"ve+z_5:ǍIENDB`drumstick-1.1.3/utils/guiplayer/resources/PaxHeaders.32572/vol.png0000644000000000000000000000013213532747316021754 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/resources/vol.png0000644000175000001440000000142213532747316022544 0ustar00pedrousers00000000000000PNG  IHDRagAMA abKGD pHYs )ItIME 7Q}KIDATx}MHq3qsu 6PK`us3-n!," 7QF QE_Zm2;ҚTWW9pBhcwD&{ ?[<| * Ƴk϶>/@/<ՂP`!s*ȟ3wӶ'VZK8ض̠]2uYZKz7 ǏTfhhh@3f!Mf_4@dӞĪ'oz.=e|OYYRJ(X Mӈ$4ҪSGwdv_] ukb&ibYըJ$/ϣq?8V )xTA@׉c㠪*m:a-#)4@^nQPTf@A @UU|>IΎP )9F1MEQH&\Rs>p hYRRipoޡ>F:l'٪޻ZjrsH޹atxEq1ҔW*9xs34MCu222p32<'§n This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef INCLUDED_PLAYER_H #define INCLUDED_PLAYER_H #include #include "song.h" using namespace drumstick; class Player : public SequencerOutputThread { Q_OBJECT public: Player(MidiClient *seq, int portId); virtual ~Player(); virtual bool hasNext(); virtual SequencerEvent* nextEvent(); virtual unsigned int getInitialPosition() { return m_songPosition; } virtual unsigned int getEchoResolution() { return m_echoResolution; } unsigned int getPitchShift() { return m_pitchShift; } unsigned int getVolumeFactor() { return m_volumeFactor; } void setSong(Song* s); void resetPosition(); void setPosition(unsigned int pos); void setPitchShift(unsigned int pitch); void setVolumeFactor(unsigned int vol); void sendController(int chan, int control, int value); void allNotesOff(); void sendVolumeEvents(); private: Song* m_song; SongIterator* m_songIterator; SequencerEvent* m_lastEvent; unsigned int m_songPosition; unsigned int m_echoResolution; unsigned int m_pitchShift; unsigned int m_volumeFactor; int m_volume[MIDI_CHANNELS]; }; #endif /*INCLUDED_PLAYER_H*/ drumstick-1.1.3/utils/guiplayer/PaxHeaders.32572/guiplayer.ui0000644000000000000000000000013213532747316020774 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/guiplayer.ui0000644000175000001440000004654613532747316021604 0ustar00pedrousers00000000000000 GUIPlayerClass 0 0 437 266 Drumstick MIDI Player :/resources/drumstick.png:/resources/drumstick.png true Drumstick MIDI Player :/resources/drumstick.png:/resources/drumstick.png 0 0 255 255 255 255 255 255 0 0 0 0 0 0 255 255 255 255 255 255 0 0 0 0 0 0 146 145 144 165 164 164 0 0 0 0 0 0 Playback time and current levels true QFrame::NoFrame QFrame::Plain 4 0 0 210 62 210 62 34 00:00:00 Tempo: 0 0 100 0 Volume: Pitch: 50 16777215 Pitch Control Pitch transpose between -12 and +12 semitones -12 12 Reset Volume Reset Volume to 100% :/resources/vol.png:/resources/vol.png 0 0 Volume Slider 200 100 false Qt::Vertical QSlider::TicksAbove 0 0 Playback progress 0 Qt::AlignCenter true QProgressBar::TopToBottom QFormLayout::ExpandingFieldsGrow File Name: 0 0 Currently loaded MIDI file name true Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse 0 0 Tempo Slider 0 200 1 10 100 Qt::Horizontal QSlider::TicksAbove 5 0 0 Reset Tempo Reset Tempo to 100% tempo=100% 0 0 437 24 File Help Settings Tool Bar Qt::ToolButtonTextUnderIcon BottomToolBarArea false :/resources/open.png:/resources/open.png Open Open a MIDI file :/resources/quit.png:/resources/quit.png Quit Quit the application :/resources/play.png:/resources/play.png Play Start playing the current MIDI file false true true :/resources/pause.png:/resources/pause.png Pause Pause the playback false :/resources/stop.png:/resources/stop.png Stop Stop the playback false :/resources/about.png:/resources/about.png About Show the about box :/resources/qtlogo.png:/resources/qtlogo.png About Qt Show the about Qt dialog box :/resources/setup.png:/resources/setup.png MIDI Setup Select a connection for the MIDI output port true true Show Tool Bar Show Tool Bar Show or hide the tool bar true true Show Status Bar Show or hide the status bar spinPitch sliderTempo btnTempo volumeSlider actionShowStatusbar toggled(bool) myStatusBar setVisible(bool) -1 -1 216 296 actionShowToolbar toggled(bool) toolBar setVisible(bool) -1 -1 216 51 drumstick-1.1.3/utils/guiplayer/PaxHeaders.32572/guiplayer.qrc0000644000000000000000000000013213532747316021144 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/guiplayer/guiplayer.qrc0000644000175000001440000000064713532747316021744 0ustar00pedrousers00000000000000 resources/qtlogo.png resources/drumstick.png resources/about.png resources/open.png resources/pause.png resources/play.png resources/quit.png resources/setup.png resources/stop.png resources/vol.png drumstick-1.1.3/utils/PaxHeaders.32572/vpiano0000644000000000000000000000013213532747316015652 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/0000755000175000001440000000000013532747316016520 5ustar00pedrousers00000000000000drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/sonivoxsettingsdialog.h0000644000000000000000000000013213532747316022546 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/sonivoxsettingsdialog.h0000644000175000001440000000247413532747316023346 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef SonivoxSettingsDialog_H #define SonivoxSettingsDialog_H #include #include namespace Ui { class SonivoxSettingsDialog; } class SonivoxSettingsDialog : public QDialog { Q_OBJECT public: explicit SonivoxSettingsDialog(QWidget *parent = 0); ~SonivoxSettingsDialog(); void readSettings(); void writeSettings(); public slots: void accept(); void showEvent(QShowEvent *event); void restoreDefaults(); private: Ui::SonivoxSettingsDialog *ui; }; #endif // SonivoxSettingsDialog_H drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316020467 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/CMakeLists.txt0000644000175000001440000000476213532747316021271 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . find_package(Qt5Widgets REQUIRED) find_package(Qt5Svg REQUIRED) find_package(Qt5Network REQUIRED) if(STATIC_DRUMSTICK AND PKG_CONFIG_FOUND) pkg_check_modules(FLUIDSYNTH REQUIRED fluidsynth>=1.1.1) link_directories(${FLUIDSYNTH_LIBDIR}) endif() set(vpiano_forms_SRCS networksettingsdialog.ui fluidsettingsdialog.ui macsynthsettingsdialog.ui sonivoxsettingsdialog.ui vpianoabout.ui connections.ui preferences.ui vpiano.ui ) qt5_wrap_ui(vpiano_ui_SRCS ${vpiano_forms_SRCS}) set(vpiano_SRCS pianokey.cpp pianokey.h pianoscene.cpp pianoscene.h pianokeybd.cpp pianokeybd.h keylabel.cpp keylabel.h vpianoabout.cpp vpianoabout.h connections.cpp connections.h preferences.cpp preferences.h vpiano.cpp vpiano.h vpianomain.cpp networksettingsdialog.cpp fluidsettingsdialog.cpp macsynthsettingsdialog.cpp sonivoxsettingsdialog.cpp ) set(vpiano_qtobject_SRCS pianoscene.h pianokeybd.h vpianoabout.h connections.h preferences.h vpiano.h networksettingsdialog.h fluidsettingsdialog.h macsynthsettingsdialog.h sonivoxsettingsdialog.h ../../library/include/drumstick/rtmidiinput.h ) qt5_wrap_cpp(vpiano_moc_SRCS ${vpiano_qtobject_SRCS}) qt5_add_resources(vpiano_SRCS pianokeybd.qrc) add_executable(drumstick-vpiano ${vpiano_ui_SRCS} ${vpiano_moc_SRCS} ${vpiano_SRCS} ) target_include_directories(drumstick-vpiano PRIVATE ../common ) target_link_libraries(drumstick-vpiano drumstick-rt Qt5::Widgets Qt5::Svg Qt5::Network ) install(TARGETS drumstick-vpiano RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) install(FILES drumstick-vpiano.desktop DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications") drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/connections.cpp0000644000000000000000000000013213532747316020755 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/connections.cpp0000644000175000001440000001502213532747316021546 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "connections.h" #include "networksettingsdialog.h" #include "fluidsettingsdialog.h" #include "sonivoxsettingsdialog.h" #include "macsynthsettingsdialog.h" Connections::Connections(QWidget *parent) : QDialog(parent), m_advanced(false), m_thru(false), m_settingsChanged(false), m_midiIn(0), m_midiOut(0) { ui.setupUi(this); connect(ui.m_advanced, SIGNAL(clicked(bool)), SLOT(clickedAdvanced(bool))); connect(ui.m_inputBackends, SIGNAL(currentIndexChanged(QString)), SLOT(refreshInputs(QString))); connect(ui.m_outputBackends, SIGNAL(currentIndexChanged(QString)), SLOT(refreshOutputs(QString))); connect(ui.btnInputDriverCfg, &QToolButton::clicked, this, &Connections::configureInputDriver); connect(ui.btnOutputDriverCfg, &QToolButton::clicked, this, &Connections::configureOutputDriver); ui.m_advanced->setChecked(m_advanced); ui.m_thru->setChecked(m_thru); } void Connections::setInputs(QList ins) { ui.m_inputBackends->disconnect(); ui.m_inputBackends->clear(); foreach(MIDIInput *i, ins) { ui.m_inputBackends->addItem(i->backendName(), qVariantFromValue((void *) i)); } connect(ui.m_inputBackends, SIGNAL(currentIndexChanged(QString)), SLOT(refreshInputs(QString))); } void Connections::setOutputs(QList outs) { ui.m_outputBackends->disconnect(); foreach(MIDIOutput *o, outs) { ui.m_outputBackends->addItem(o->backendName(), qVariantFromValue((void *) o)); } connect(ui.m_outputBackends, SIGNAL(currentIndexChanged(QString)), SLOT(refreshOutputs(QString))); } void Connections::accept() { QString conn; QSettings settings; m_advanced = ui.m_advanced->isChecked(); m_thru = ui.m_thru->isChecked(); if (m_midiOut != 0) { conn = ui.m_outputPorts->currentText(); if (conn != m_midiOut->currentConnection() || m_settingsChanged) { m_midiOut->close(); if (!conn.isEmpty()) { m_midiOut->initialize(&settings); m_midiOut->open(conn); } } } if (m_midiIn != 0) { conn = ui.m_inputPorts->currentText(); if (conn != m_midiIn->currentConnection() || m_settingsChanged) { m_midiIn->close(); if (!conn.isEmpty()) { m_midiIn->initialize(&settings); m_midiIn->open(conn); } } if (m_midiOut != 0) { m_midiIn->setMIDIThruDevice(m_midiOut); m_midiIn->enableMIDIThru(m_thru); } } m_settingsChanged = false; QDialog::accept(); } void Connections::refresh() { m_advanced = ui.m_advanced->isChecked(); if (m_midiIn != 0) { ui.m_inputBackends->setCurrentText(m_midiIn->backendName()); refreshInputs(m_midiIn->backendName()); } if (m_midiOut != 0) { ui.m_outputBackends->setCurrentText(m_midiOut->backendName()); refreshOutputs(m_midiOut->backendName()); } } void Connections::refreshInputs(QString id) { ui.btnInputDriverCfg->setEnabled(id == "Network"); if (m_midiIn != 0 && m_midiIn->backendName() != id) { m_midiIn->close(); int idx = ui.m_inputBackends->findText(id, Qt::MatchStartsWith); if (idx > -1) { m_midiIn = (MIDIInput *) ui.m_inputBackends->itemData(idx).value(); } else { m_midiIn = 0; } } ui.m_inputPorts->clear(); if (m_midiIn != 0) { ui.m_inputPorts->addItem(QString()); ui.m_inputPorts->addItems(m_midiIn->connections(m_advanced)); ui.m_inputPorts->setCurrentText(m_midiIn->currentConnection()); } } void Connections::refreshOutputs(QString id) { ui.btnOutputDriverCfg->setEnabled(id == "Network" || id == "FluidSynth" || id == "DLS Synth" || id == "SonivoxEAS"); if (m_midiOut != 0 && m_midiOut->backendName() != id) { m_midiOut->close(); int idx = ui.m_outputBackends->findText(id, Qt::MatchStartsWith); if (idx > -1) { m_midiOut = (MIDIOutput *) ui.m_outputBackends->itemData(idx).value(); } else { m_midiOut = 0; } } ui.m_outputPorts->clear(); if (m_midiOut != 0) { ui.m_outputPorts->addItems(m_midiOut->connections(m_advanced)); ui.m_outputPorts->setCurrentText(m_midiOut->currentConnection()); } } void Connections::setAdvanced(bool value) { ui.m_advanced->setChecked(value); refresh(); } void Connections::clickedAdvanced(bool value) { m_advanced = value; refresh(); } void Connections::setMidiThru(bool value) { m_thru = value; ui.m_thru->setChecked(value); } bool Connections::advanced() { return ui.m_advanced->isChecked(); } bool Connections::midiThru() { return ui.m_thru->isChecked(); } void Connections::configureInputDriver() { QString driver = ui.m_inputBackends->currentText(); if (driver == "Network") { NetworkSettingsDialog dlg(this); m_settingsChanged |= (dlg.exec() == QDialog::Accepted); } } void Connections::configureOutputDriver() { QString driver = ui.m_outputBackends->currentText(); if (driver == "Network") { NetworkSettingsDialog dlg(this); m_settingsChanged |= (dlg.exec() == QDialog::Accepted); } else if (driver == "FluidSynth") { FluidSettingsDialog dlg(this); m_settingsChanged |= (dlg.exec() == QDialog::Accepted); } else if (driver == "SonivoxEAS") { SonivoxSettingsDialog dlg(this); m_settingsChanged |= (dlg.exec() == QDialog::Accepted); } else if (driver == "DLS Synth") { MacSynthSettingsDialog dlg(this); m_settingsChanged |= (dlg.exec() == QDialog::Accepted); } } drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/pianokeybd.qrc0000644000000000000000000000013213532747316020563 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/pianokeybd.qrc0000644000175000001440000000023713532747316021356 0ustar00pedrousers00000000000000 pianokeybd.png blkey.svg drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/pianokeybd.png0000644000000000000000000000013213532747316020562 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/pianokeybd.png0000644000175000001440000000111113532747316021345 0ustar00pedrousers00000000000000PNG  IHDR szzbKGD pHYs  tIME 8+93tEXtCommentCreated with The GIMPd%nIDATX헿@2BRDO#X +;V,|}_<QDD3[|!d90Ŝ{70Ey\.T^v|>Ǚal6h4G)yt:>. RȄ\וRZJJ< F1&'Iʛ繵J !UQ1~S{4AIyZ! 4@hmۙ!m4LnYַj\\.4zNrRl¶mZ-mPJ>APp8`0`! ø/!~?Cl6SEr<2N~@h%RYb~R"5#~=|*k+8c^˼q4MDQʌ`,ʌlޜsMG ULIENDB`drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/vpiano.cpp0000644000000000000000000000013213532747316017727 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/vpiano.cpp0000644000175000001440000002373113532747316020526 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include "vpiano.h" VPiano::VPiano( QWidget * parent, Qt::WindowFlags flags ) : QMainWindow(parent, flags), m_midiIn(nullptr), m_midiOut(nullptr) { m_nativeInput = QLatin1Literal("Network"); m_defaultInput = QLatin1Literal("21928"); #if defined(Q_OS_LINUX) m_nativeOutput = QLatin1Literal("SonivoxEAS"); m_defaultOutput = QLatin1Literal("SonivoxEAS"); #elif defined(Q_OS_OSX) m_nativeOutput = QLatin1Literal("DLS Synth"); m_defaultOutput = QLatin1Literal("DLS Synth"); #elif defined(Q_OS_WIN) m_nativeOutput = QLatin1Literal("Windows MM"); m_defaultOutput = QLatin1Literal("Microsoft GS Wavetable Synth"); #else m_nativeOutput = m_nativeInput; m_defaultOutput = m_defaultInput; #endif ui.setupUi(this); ui.statusBar->hide(); readSettings(); QSettings settings; BackendManager man; man.refresh(&settings); QList inputs = man.availableInputs(); QList outputs = man.availableOutputs(); findInput(m_lastInputBackend, inputs); if (m_midiIn == nullptr) { findInput(m_nativeInput, inputs); if (m_midiIn == nullptr) { qFatal("Unable to find a suitable input backend."); } } findOutput(m_lastOutputBackend, outputs); if (m_midiOut == nullptr) { findOutput(m_nativeOutput, outputs); if (m_midiOut == nullptr) { qFatal("Unable to find a suitable output backend"); } } connect(ui.actionExit, SIGNAL(triggered()), SLOT(close())); connect(ui.actionAbout, SIGNAL(triggered()), SLOT(slotAbout())); connect(ui.actionAbout_Qt, SIGNAL(triggered()), SLOT(slotAboutQt())); connect(ui.actionConnections, SIGNAL(triggered()), SLOT(slotConnections())); connect(ui.actionPreferences, SIGNAL(triggered()), SLOT(slotPreferences())); connect(ui.pianokeybd, SIGNAL(noteOn(int,int)), SLOT(slotNoteOn(int,int))); connect(ui.pianokeybd, SIGNAL(noteOff(int,int)), SLOT(slotNoteOff(int,int))); dlgConnections.setInputs(inputs); dlgConnections.setOutputs(outputs); dlgConnections.setInput(m_midiIn); dlgConnections.setOutput(m_midiOut); dlgConnections.setMidiThru(m_midiThru); dlgConnections.setAdvanced(m_advanced); if (m_midiIn != nullptr) { #if QT_VERSION < 0x050700 connect(m_midiIn, SIGNAL(midiNoteOn(int,int,int)), SLOT(slotNoteOn(int,int,int)), Qt::QueuedConnection); connect(m_midiIn, SIGNAL(midiNoteOff(int,int,int)), SLOT(slotNoteOff(int,int,int)), Qt::QueuedConnection); #else connect(m_midiIn, &MIDIInput::midiNoteOn, this, QOverload::of(&VPiano::slotNoteOn), Qt::QueuedConnection); connect(m_midiIn, &MIDIInput::midiNoteOff, this, QOverload::of(&VPiano::slotNoteOff), Qt::QueuedConnection); #endif if (!m_lastInputConnection.isEmpty()) { m_midiIn->initialize(&settings); m_midiIn->open(m_lastInputConnection); } } if (m_midiOut != nullptr && !m_lastOutputConnection.isEmpty()) { m_midiOut->initialize(&settings); m_midiOut->open(m_lastOutputConnection); if (m_midiIn != nullptr) { m_midiIn->setMIDIThruDevice(m_midiOut); m_midiIn->enableMIDIThru(m_midiThru); } } } VPiano::~VPiano() { //qDebug() << Q_FUNC_INFO; m_midiIn->close(); m_midiOut->close(); //qDebug() << "Cheers!"; } void VPiano::slotNoteOn(const int midiNote, const int vel) { int chan = dlgPreferences.getOutChannel(); m_midiOut->sendNoteOn(chan, midiNote, vel); } void VPiano::slotNoteOff(const int midiNote, const int vel) { int chan = dlgPreferences.getOutChannel(); m_midiOut->sendNoteOff(chan, midiNote, vel); } void VPiano::slotNoteOn(const int chan, const int note, const int vel) { if (dlgPreferences.getInChannel() == chan) { if (vel > 0) ui.pianokeybd->getPianoScene()->showNoteOn(note); else ui.pianokeybd->getPianoScene()->showNoteOff(note); } } void VPiano::slotNoteOff(const int chan, const int note, const int vel) { Q_UNUSED(vel) if (dlgPreferences.getInChannel() == chan) { ui.pianokeybd->getPianoScene()->showNoteOff(note); } } void VPiano::slotAbout() { dlgAbout.exec(); } void VPiano::slotAboutQt() { qApp->aboutQt(); } void VPiano::slotConnections() { dlgConnections.refresh(); if (dlgConnections.exec() == QDialog::Accepted) { if (m_midiIn != nullptr) { m_midiIn->disconnect(); } if (m_midiOut != nullptr) { m_midiOut->disconnect(); } m_midiIn = dlgConnections.getInput(); m_midiOut = dlgConnections.getOutput(); if (m_midiIn != nullptr) { connect(m_midiIn, SIGNAL(midiNoteOn(int,int,int)), SLOT(slotNoteOn(int,int,int))); connect(m_midiIn, SIGNAL(midiNoteOff(int,int,int)), SLOT(slotNoteOff(int,int,int))); } m_midiThru = dlgConnections.midiThru(); m_advanced = dlgConnections.advanced(); } } void VPiano::slotPreferences() { if (dlgPreferences.exec() == QDialog::Accepted) { if (ui.pianokeybd->baseOctave() != dlgPreferences.getBaseOctave()) { ui.pianokeybd->setBaseOctave(dlgPreferences.getBaseOctave()); } if (ui.pianokeybd->numKeys() != dlgPreferences.getNumKeys()) { ui.pianokeybd->setNumKeys(dlgPreferences.getNumKeys()); } if (ui.pianokeybd->startKey() != dlgPreferences.getStartingKey()) { ui.pianokeybd->setNumKeys(dlgPreferences.getNumKeys(), dlgPreferences.getStartingKey()); } } } void VPiano::closeEvent(QCloseEvent *event) { //qDebug() << Q_FUNC_INFO; writeSettings(); event->accept(); } void VPiano::writeSettings() { QSettings settings; settings.beginGroup("Window"); settings.setValue("Geometry", saveGeometry()); settings.setValue("State", saveState()); settings.endGroup(); settings.beginGroup("Connections"); settings.setValue("inputBackend", m_midiIn->backendName()); settings.setValue("outputBackend", m_midiOut->backendName()); settings.setValue("inputConnection", m_midiIn->currentConnection()); settings.setValue("outputConnection", m_midiOut->currentConnection()); settings.setValue("midiThru", m_midiThru); settings.setValue("advanced", m_advanced); settings.endGroup(); settings.beginGroup("Preferences"); settings.setValue("inputChannel", dlgPreferences.getInChannel()); settings.setValue("outputChannel",dlgPreferences.getOutChannel()); settings.setValue("velocity", dlgPreferences. getVelocity()); settings.setValue("baseOctave", dlgPreferences.getBaseOctave()); settings.setValue("numKeys", dlgPreferences.getNumKeys()); settings.setValue("startingKey", dlgPreferences.getStartingKey()); settings.endGroup(); settings.sync(); } void VPiano::readSettings() { QSettings settings; settings.beginGroup("Window"); restoreGeometry(settings.value("Geometry").toByteArray()); restoreState(settings.value("State").toByteArray()); settings.endGroup(); settings.beginGroup("Connections"); m_lastInputBackend = settings.value("inputBackend", m_nativeInput).toString(); m_lastOutputBackend = settings.value("outputBackend", m_nativeOutput).toString(); m_lastInputConnection = settings.value("inputConnection", m_defaultInput).toString(); m_lastOutputConnection = settings.value("outputConnection", m_defaultOutput).toString(); m_midiThru = settings.value("midiThru", false).toBool(); m_advanced = settings.value("advanced", false).toBool(); settings.endGroup(); settings.beginGroup("Preferences"); dlgPreferences.setInChannel(settings.value("inputChannel", 0).toInt()); dlgPreferences.setOutChannel(settings.value("outputChannel", 0).toInt()); dlgPreferences.setVelocity(settings.value("velocity", 100).toInt()); dlgPreferences.setBaseOctave(settings.value("baseOctave", 1).toInt()); dlgPreferences.setNumKeys(settings.value("numKeys", 88).toInt()); dlgPreferences.setStartingKey(settings.value("startingKey", 9).toInt()); ui.pianokeybd->setBaseOctave(settings.value("baseOctave", 1).toInt()); ui.pianokeybd->setNumKeys(settings.value("numKeys", 88).toInt(), settings.value("startingKey", 9).toInt()); settings.endGroup(); } void VPiano::findInput(QString name, QList &inputs) { if (name.isEmpty()) { return; } foreach(MIDIInput* input, inputs) { if (m_midiIn == nullptr && (input->backendName() == name)) { m_midiIn = input; break; } } if (m_midiIn == nullptr) { qWarning() << "Input backend not found: " << name; } } void VPiano::findOutput(QString name, QList &outputs) { if (name.isEmpty()) { return; } foreach(MIDIOutput* output, outputs) { if (m_midiOut == nullptr && (output->backendName() == name)) { m_midiOut = output; break; } } if (m_midiOut == nullptr) { qWarning() << "Output backend not found: " << name; } } drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/drumstick-vpiano.desktop0000644000000000000000000000013213532747316022621 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/drumstick-vpiano.desktop0000644000175000001440000000042013532747316023406 0ustar00pedrousers00000000000000[Desktop Entry] Name=Drumstick Virtual Piano Exec=drumstick-vpiano Icon=drumstick Terminal=false Type=Application Categories=AudioVideo;Audio;Midi;Education;Music; Keywords=Music;Midi;Piano;Virtual; Comment=Drumstick Virtual Piano Comment[es]=Piano virtual de Drumstick drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/vpianoabout.h0000644000000000000000000000013213532747316020427 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/vpianoabout.h0000644000175000001440000000176513532747316021231 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef ABOUT_H #define ABOUT_H #include #include "ui_vpianoabout.h" class About : public QDialog { Q_OBJECT public: About(QWidget *parent = 0); private: Ui::AboutClass ui; }; #endif // ABOUT_H drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/macsynthsettingsdialog.h0000644000000000000000000000013213532747316022667 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/macsynthsettingsdialog.h0000644000175000001440000000250413532747316023461 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef MacSynthSettingsDialog_H #define MacSynthSettingsDialog_H #include #include namespace Ui { class MacSynthSettingsDialog; } class MacSynthSettingsDialog : public QDialog { Q_OBJECT public: explicit MacSynthSettingsDialog(QWidget *parent = 0); ~MacSynthSettingsDialog(); void readSettings(); void writeSettings(); public slots: void accept(); void showEvent(QShowEvent *event); void restoreDefaults(); private: Ui::MacSynthSettingsDialog *ui; }; #endif // MacSynthSettingsDialog_H drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/fluidsettingsdialog.ui0000644000000000000000000000013213532747316022332 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/fluidsettingsdialog.ui0000644000175000001440000001246213532747316023130 0ustar00pedrousers00000000000000 FluidSettingsDialog 0 0 316 318 FluidSynth Driver Settings Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults QFrame::StyledPanel QFrame::Raised Sample Rate: sampleRate Period Size: periodSize # of Periods: periods Audio Driver: Polyphony: polyphony Sound Font: soundFont Gain: gain ... Chorus Reverb audioDriver periodSize periods sampleRate chorus reverb gain polyphony soundFont btnFile buttonBox accepted() FluidSettingsDialog accept() 248 254 157 274 buttonBox rejected() FluidSettingsDialog reject() 316 260 286 274 drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/keylabel.cpp0000644000000000000000000000013213532747316020223 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/keylabel.cpp0000644000175000001440000000216413532747316021017 0ustar00pedrousers00000000000000/* Virtual Piano Widget for Qt5 Copyright (C) 2008-2019, Pedro Lopez-Cabanillas 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, see . */ #include "keylabel.h" #include "pianokey.h" #include KeyLabel::KeyLabel(QGraphicsItem *parent) : QGraphicsTextItem(parent) { setAcceptedMouseButtons(Qt::NoButton); //rotate(270); setRotation(rotation() + 270); } QRectF KeyLabel::boundingRect() const { PianoKey* key = static_cast(parentItem()); return mapRectFromScene(key->rect()); } drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/networksettingsdialog.cpp0000644000000000000000000000013213532747316023065 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/networksettingsdialog.cpp0000644000175000001440000000726113532747316023664 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include "networksettingsdialog.h" #include "ui_networksettingsdialog.h" const QString QSTR_ADDRESS_IPV4(QLatin1Literal("225.0.0.37")); const QString QSTR_ADDRESS_IPV6(QLatin1Literal("ff12::37")); NetworkSettingsDialog::NetworkSettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::NetworkSettingsDialog) { ui->setupUi(this); connect(ui->buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::pressed, this, &NetworkSettingsDialog::restoreDefaults); connect(ui->checkIPv6, &QCheckBox::toggled, this, &NetworkSettingsDialog::toggledIPv6); } NetworkSettingsDialog::~NetworkSettingsDialog() { delete ui; } void NetworkSettingsDialog::accept() { writeSettings(); QDialog::accept(); } void NetworkSettingsDialog::showEvent(QShowEvent *event) { readSettings(); event->accept(); } void NetworkSettingsDialog::readSettings() { QSettings settings; settings.beginGroup("Network"); QString ifaceName = settings.value("interface", QString()).toString(); bool ipv6 = settings.value("ipv6", false).toBool(); QString address = settings.value("address", ipv6 ? QSTR_ADDRESS_IPV6 : QSTR_ADDRESS_IPV4).toString(); settings.endGroup(); ui->txtAddress->setText(address); ui->checkIPv6->setChecked(ipv6); ui->comboInterface->addItem(tr("Any"), ""); foreach( const QNetworkInterface& iface, QNetworkInterface::allInterfaces() ) { if ( iface.isValid() && iface.flags().testFlag(QNetworkInterface::CanMulticast) && iface.flags().testFlag(QNetworkInterface::IsUp) && iface.flags().testFlag(QNetworkInterface::IsRunning) && !iface.flags().testFlag(QNetworkInterface::IsLoopBack) ) { QString name = iface.name(); QString text = iface.humanReadableName(); ui->comboInterface->addItem(text, name); if (name == ifaceName) { ui->comboInterface->setCurrentText(text); } } } } void NetworkSettingsDialog::writeSettings() { QSettings settings; QString networkAddr = QSTR_ADDRESS_IPV4; QString networkIface; bool ipv6 = false; networkAddr = ui->txtAddress->text(); networkIface = ui->comboInterface->currentData().toString(); ipv6 = ui->checkIPv6->isChecked(); settings.beginGroup("Network"); settings.setValue("address", networkAddr); settings.setValue("interface", networkIface); settings.setValue("ipv6", ipv6); settings.endGroup(); settings.sync(); } void NetworkSettingsDialog::restoreDefaults() { ui->checkIPv6->setChecked(false); ui->txtAddress->setText(QSTR_ADDRESS_IPV4); ui->comboInterface->setCurrentText(tr("Any")); } void NetworkSettingsDialog::toggledIPv6(bool checked) { ui->txtAddress->setText(checked ? QSTR_ADDRESS_IPV6 : QSTR_ADDRESS_IPV4); } drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/preferences.ui0000644000000000000000000000013213532747316020567 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/preferences.ui0000644000175000001440000001601413532747316021362 0ustar00pedrousers00000000000000 PreferencesClass 0 0 270 213 Preferences 127 100 15 0 0 Output Channel spinOutChan 0 9 0 0 Number of keys spinNumKeys 0 0 Velocity spinVelocity 0 0 Input Channel spinInChan QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok 0 0 Base octave spinBaseOctave 15 12 120 88 0 0 Starting Key comboNotes 5 12 C C# D D# E F F# G G# A A# B spinInChan spinOutChan spinVelocity spinBaseOctave spinNumKeys comboNotes buttonBox buttonBox accepted() PreferencesClass accept() 237 412 263 11 buttonBox rejected() PreferencesClass reject() 127 412 155 14 drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/networksettingsdialog.ui0000644000000000000000000000013213532747316022720 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/networksettingsdialog.ui0000644000175000001440000000426613532747316023521 0ustar00pedrousers00000000000000 NetworkSettingsDialog 0 0 325 181 Network Driver Settings Use IPv6 Network Interface: comboInterface Address Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults buttonBox accepted() NetworkSettingsDialog accept() 236 126 157 87 buttonBox rejected() NetworkSettingsDialog reject() 292 126 286 87 drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/blkey.svg0000644000000000000000000000013213532747316017556 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/blkey.svg0000644000175000001440000001450513532747316020354 0ustar00pedrousers00000000000000 image/svg+xml drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/vpiano.pro0000644000000000000000000000013213532747316017745 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/vpiano.pro0000644000175000001440000000472613532747316020547 0ustar00pedrousers00000000000000TEMPLATE = app TARGET = drumstick-vpiano QT += gui widgets svg network CONFIG += qt thread exceptions DESTDIR = ../../build/bin include (../../global.pri) INCLUDEPATH += . ../../library/include ../common # Input FORMS += vpiano.ui connections.ui vpianoabout.ui preferences.ui fluidsettingsdialog.ui networksettingsdialog.ui \ sonivoxsettingsdialog.ui \ macsynthsettingsdialog.ui HEADERS += pianokey.h pianokeybd.h pianoscene.h vpiano.h \ keyboardmap.h keylabel.h pianodefs.h \ connections.h vpianoabout.h preferences.h \ fluidsettingsdialog.h networksettingsdialog.h \ macsynthsettingsdialog.h \ sonivoxsettingsdialog.h \ ../../library/include/drumstick/rtmidiinput.h SOURCES += pianokey.cpp pianokeybd.cpp pianoscene.cpp vpiano.cpp \ keylabel.cpp connections.cpp vpianoabout.cpp preferences.cpp vpianomain.cpp \ fluidsettingsdialog.cpp networksettingsdialog.cpp \ macsynthsettingsdialog.cpp \ sonivoxsettingsdialog.cpp RESOURCES += pianokeybd.qrc # libs macx:!static { QMAKE_LFLAGS += -F$$OUT_PWD/../../build/lib -L$$OUT_PWD/../../build/lib LIBS += -framework drumstick-rt ICON = ../../icons/drumstick.icns QMAKE_TARGET_BUNDLE_PREFIX = net.sourceforge QMAKE_BUNDLE = drumstick-vpiano QMAKE_INFO_PLIST = ../Info.plist.app } else { LIBS += -L$$OUT_PWD/../../build/lib/ LIBS += -l$$drumstickLib(drumstick-rt) } static { CONFIG += link_prl LIBS += -L$$OUT_PWD/../../build/lib/drumstick/ LIBS += -ldrumstick-rt-net-in \ -ldrumstick-rt-net-out packagesExist(fluidsynth) { DEFINES += SYNTH_BACKEND LIBS += -ldrumstick-rt-synth macx { QMAKE_LFLAGS += -F/Library/Frameworks LIBS += -framework FluidSynth } else { CONFIG += link_pkgconfig PKGCONFIG += fluidsynth } } linux* { LIBS += -ldrumstick-rt-alsa-in \ -ldrumstick-rt-alsa-out \ -ldrumstick-rt-eassynth \ -ldrumstick-alsa \ -lasound } unix:!macx { LIBS += -ldrumstick-rt-oss-in \ -ldrumstick-rt-oss-out } macx { LIBS += -ldrumstick-rt-mac-in \ -ldrumstick-rt-mac-out \ -ldrumstick-rt-macsynth \ -framework CoreMIDI \ -framework CoreFoundation } win32 { LIBS += -ldrumstick-rt-win-in \ -ldrumstick-rt-win-out \ -lwinmm } } drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/preferences.h0000644000000000000000000000013213532747316020401 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/preferences.h0000644000175000001440000000355013532747316021175 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef PREFERENCES_H #define PREFERENCES_H #include #include "ui_preferences.h" class Preferences : public QDialog { Q_OBJECT public: Preferences(QWidget *parent = 0); void setInChannel(const int chan); void setOutChannel(const int chan); void setVelocity(const int vel); void setBaseOctave(const int octave); void setNumKeys(const int keys); void setStartingKey(const int key); int getInChannel() const { return m_inChannel; } int getOutChannel() const { return m_outChannel; } int getVelocity() const { return m_velocity; } int getBaseOctave() const { return m_baseOctave; } int getNumKeys() const { return m_numKeys; } int getStartingKey() const { return m_startingKey; } void apply(); public slots: void slotButtonClicked(QAbstractButton *button); void accept(); protected: void showEvent ( QShowEvent *event ); private: Ui::PreferencesClass ui; int m_inChannel; int m_outChannel; int m_velocity; int m_baseOctave; int m_numKeys; int m_startingKey; }; #endif // PREFERENCES_H drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/fluidsettingsdialog.h0000644000000000000000000000013213532747316022144 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/fluidsettingsdialog.h0000644000175000001440000000255713532747316022746 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef FLUIDSETTINGSDIALOG_H #define FLUIDSETTINGSDIALOG_H #include #include namespace Ui { class FluidSettingsDialog; } class FluidSettingsDialog : public QDialog { Q_OBJECT public: explicit FluidSettingsDialog(QWidget *parent = 0); ~FluidSettingsDialog(); void readSettings(); void writeSettings(); public slots: void accept(); void showEvent(QShowEvent *event); void restoreDefaults(); void showFileDialog(); private: QString defaultAudioDriver() const; Ui::FluidSettingsDialog *ui; }; #endif // FLUIDSETTINGSDIALOG_H drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/keylabel.h0000644000000000000000000000013213532747316017670 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/keylabel.h0000644000175000001440000000204013532747316020455 0ustar00pedrousers00000000000000/* Virtual Piano Widget for Qt5 Copyright (C) 2008-2019, Pedro Lopez-Cabanillas 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, see . */ #ifndef KEYLABEL_H #define KEYLABEL_H #include "pianodefs.h" #include class VPIANO_EXPORT KeyLabel : public QGraphicsTextItem { public: KeyLabel(QGraphicsItem *parent = 0); virtual ~KeyLabel() {} virtual QRectF boundingRect() const; }; #endif // KEYLABEL_H drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/vpiano.ui0000644000000000000000000000013213532747316017562 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/vpiano.ui0000644000175000001440000000444613532747316020363 0ustar00pedrousers00000000000000 VPiano 0 0 664 139 Drumstick Virtual Piano 0 0 664 19 File Edit Help true &Exit &Preferences &Connections About About Qt PianoKeybd QGraphicsView
pianokeybd.h
drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/vpianomain.cpp0000644000000000000000000000013213532747316020574 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/vpianomain.cpp0000644000175000001440000000424713532747316021374 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include "cmdversion.h" #include "vpiano.h" const QString PGM_DESCRIPTION("Drumstick Simple Virtual Piano"); int main(int argc, char *argv[]) { QTextStream cerr(stderr, QIODevice::WriteOnly); QCoreApplication::setOrganizationName("drumstick.sourceforge.net"); QCoreApplication::setOrganizationDomain("drumstick.sourceforge.net"); QCoreApplication::setApplicationName("VPiano"); QCoreApplication::setApplicationVersion(PGM_VERSION); QApplication app(argc, argv); QCommandLineParser parser; parser.setApplicationDescription(PGM_DESCRIPTION); auto helpOption = parser.addHelpOption(); auto versionOption = parser.addVersionOption(); parser.process(app); if (parser.isSet(versionOption) || parser.isSet(helpOption)) { return 0; } QSettings settings; settings.beginGroup(QSTR_DRUMSTICKRT_GROUP); settings.setValue(QSTR_DRUMSTICKRT_PUBLICNAMEIN, QLatin1String("Virtual Piano IN")); settings.setValue(QSTR_DRUMSTICKRT_PUBLICNAMEOUT, QLatin1String("Virtual Piano OUT")); settings.endGroup(); settings.sync(); try { VPiano w; w.show(); return app.exec(); } catch (...) { cerr << "Fatal error from a MIDI backend." << endl; } return 0; } drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/pianokey.h0000644000000000000000000000013213532747316017717 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/pianokey.h0000644000175000001440000000335213532747316020513 0ustar00pedrousers00000000000000/* Virtual Piano Widget for Qt5 Copyright (C) 2008-2019, Pedro Lopez-Cabanillas 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, see . */ #ifndef PIANOKEY_H_ #define PIANOKEY_H_ #include "pianodefs.h" #include #include class VPIANO_EXPORT PianoKey : public QGraphicsRectItem { public: PianoKey(QGraphicsItem * parent = 0 ) : QGraphicsRectItem(parent), m_pressed(false) { } PianoKey(const QRectF &rect, const QBrush &brush, const int note); PianoKey(const QRectF &rect, const bool black, const int note); void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *); int getNote() const { return m_note; } void setBrush(const QBrush& b) { m_brush = b; } void setPressedBrush(const QBrush& b) { m_selectedBrush = b; } void resetBrush(); bool isPressed() const { return m_pressed; } void setPressed(bool p); int getDegree() const { return m_note % 12; } int getType() const { return (m_black ? 1 : 0); } private: bool m_pressed; QBrush m_selectedBrush; QBrush m_brush; int m_note; bool m_black; }; #endif /*PIANOKEY_H_*/ drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/connections.ui0000644000000000000000000000013213532747316020610 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/connections.ui0000644000175000001440000000664313532747316021412 0ustar00pedrousers00000000000000 ConnectionsClass 0 0 289 253 Connections MIDI IN Enable MIDI THRU MIDI OUT false ... Show advanced connections Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok false ... m_inputBackends btnInputDriverCfg m_inputPorts m_thru m_outputBackends btnOutputDriverCfg m_outputPorts m_advanced buttonBox accepted() ConnectionsClass accept() 264 303 283 112 buttonBox rejected() ConnectionsClass reject() 65 303 93 74 drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/vpiano.h0000644000000000000000000000013213532747316017374 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/vpiano.h0000644000175000001440000000435313532747316020172 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef VPIANO_H #define VPIANO_H #include #include #include #include #include "ui_vpiano.h" #include "vpianoabout.h" #include "connections.h" #include "preferences.h" using namespace drumstick::rt; class VPiano : public QMainWindow { Q_OBJECT public: VPiano( QWidget * parent = 0, Qt::WindowFlags flags = 0 ); virtual ~VPiano(); void closeEvent(QCloseEvent *event); void findInput(QString name, QList &inputs); void findOutput(QString name, QList &outputs); public slots: void readSettings(); void writeSettings(); void slotAbout(); void slotAboutQt(); void slotConnections(); void slotPreferences(); void slotNoteOn(const int midiNote, const int vel); void slotNoteOn(const int chan, const int note, const int vel); void slotNoteOff(const int midiNote, const int vel); void slotNoteOff(const int chan, const int note, const int vel); private: MIDIInput * m_midiIn; MIDIOutput* m_midiOut; QString m_lastInputBackend; QString m_lastOutputBackend; QString m_lastInputConnection; QString m_lastOutputConnection; bool m_midiThru; bool m_advanced; Ui::VPiano ui; About dlgAbout; Connections dlgConnections; Preferences dlgPreferences; QString m_nativeInput; QString m_nativeOutput; QString m_defaultInput; QString m_defaultOutput; }; #endif // VPIANO_H drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/sonivoxsettingsdialog.ui0000644000000000000000000000013213532747316022734 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/sonivoxsettingsdialog.ui0000644000175000001440000001072213532747316023527 0ustar00pedrousers00000000000000 SonivoxSettingsDialog 0 0 304 280 Sonivox EAS Synth :/icon.png:/icon.png Chorus Qt::AlignCenter Qt::Vertical 20 8 32765 Reverb Qt::AlignCenter 0 0 Buffer Time: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter ms 1 9999 60 32765 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults spnTime dial_Reverb dial_Chorus combo_Reverb combo_Chorus buttonBox accepted() SonivoxSettingsDialog accept() 145 260 148 288 buttonBox rejected() SonivoxSettingsDialog reject() 239 260 251 289 drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/vpianoabout.cpp0000644000000000000000000000013213532747316020762 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/vpianoabout.cpp0000644000175000001440000000205013532747316021550 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "vpianoabout.h" #include "cmdversion.h" About::About(QWidget *parent) : QDialog(parent) { ui.setupUi(this); QString aboutText = ui.AboutTextView->toHtml(); aboutText.replace("%VERSION%", PGM_VERSION); ui.AboutTextView->setHtml(aboutText); } drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/pianokey.cpp0000644000000000000000000000013213532747316020252 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/pianokey.cpp0000644000175000001440000000527113532747316021050 0ustar00pedrousers00000000000000/* Virtual Piano Widget for Qt5 Copyright (C) 2008-2019, Pedro Lopez-Cabanillas 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, see . */ #include "pianokey.h" #include #include #include #include static const QBrush blackBrush = QBrush(Qt::black); static const QBrush whiteBrush = QBrush(Qt::white); PianoKey::PianoKey(const QRectF &rect, const QBrush &brush, const int note) : QGraphicsRectItem(rect), m_pressed(false), m_brush(brush), m_note(note), m_black(brush == blackBrush) { setAcceptedMouseButtons(Qt::NoButton); } PianoKey::PianoKey(const QRectF &rect, const bool black, const int note) : QGraphicsRectItem(rect), m_pressed(false), m_brush( black ? blackBrush : whiteBrush ), m_note(note), m_black(black) { setAcceptedMouseButtons(Qt::NoButton); } void PianoKey::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { static QSvgRenderer keyRenderer(QString(":/vpiano/blkey.svg")); static const QPen blackPen(Qt::black, 1); static const QPen grayPen(QBrush(Qt::gray), 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); if (m_pressed) { if (m_selectedBrush.style() != Qt::NoBrush) { painter->setBrush(m_selectedBrush); } else { painter->setBrush(QApplication::palette().highlight()); } } else { painter->setBrush(m_brush); } painter->setPen(blackPen); painter->drawRoundRect(rect(), 15, 15); if (m_black) keyRenderer.render(painter, rect()); else { QPointF points[3] = { QPointF(rect().left()+1.5, rect().bottom()-1), QPointF(rect().right()-1, rect().bottom()-1), QPointF(rect().right()-1, rect().top()+1), }; painter->setPen(grayPen); painter->drawPolyline(points, 3); } } void PianoKey::setPressed(bool p) { if (p != m_pressed) { m_pressed = p; update(); } } void PianoKey::resetBrush() { if (m_black) m_brush = blackBrush; else m_brush = whiteBrush; } drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/pianoscene.cpp0000644000000000000000000000013213532747316020557 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/pianoscene.cpp0000644000175000001440000004217713532747316021363 0ustar00pedrousers00000000000000/* Virtual Piano Widget for Qt5 Copyright (C) 2008-2019, Pedro Lopez-Cabanillas 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, see . */ #include "pianoscene.h" #if defined(RAWKBD_SUPPORT) #include "nativefilter.h" #endif #include #include #include #include #include #include #define KEYWIDTH 18 #define KEYHEIGHT 72 static qreal sceneWidth(int keys) { return KEYWIDTH * qCeil( keys * 7.0 / 12.0 ); } PianoScene::PianoScene ( const int baseOctave, const int numKeys, const int startKey, const QColor& keyPressedColor, QObject * parent ) : QGraphicsScene( QRectF(0, 0, sceneWidth(numKeys), KEYHEIGHT), parent ), m_baseOctave( baseOctave ), m_numKeys( numKeys ), m_startKey( startKey ), m_minNote( 0 ), m_maxNote( 127 ), m_transpose( 0 ), m_showLabels( false ), m_useFlats( false ), m_rawkbd( false ), m_keyboardEnabled( true ), m_mouseEnabled( true ), m_touchEnabled( true ), m_keyPressedColor( keyPressedColor ), m_mousePressed( false ), m_velocity( 100 ), m_channel( 0 ), m_velocityTint( true ), m_handler( 0 ) #if defined(PALETTE_SUPPORT) ,m_showColorScale( false ) ,m_palette( 0 ) ,m_scalePalette( 0 ) #endif { QBrush hilightBrush(m_keyPressedColor.isValid() ? m_keyPressedColor : QApplication::palette().highlight()); QFont lblFont(QApplication::font()); lblFont.setPointSize(KEYLABELFONTSIZE); int upperLimit = m_numKeys + m_startKey; int adj = m_startKey % 12; if (adj >= 5) adj++; for(int i = m_startKey; i < upperLimit; ++i) { float x = 0; PianoKey* key = NULL; KeyLabel* lbl = NULL; int ocs = i / 12 * 7; int j = i % 12; if (j >= 5) j++; if ((j % 2) == 0) { x = (ocs + qFloor((j-adj) / 2.0)) * KEYWIDTH; key = new PianoKey( QRectF(x, 0, KEYWIDTH, KEYHEIGHT), false, i ); lbl = new KeyLabel(key); lbl->setDefaultTextColor(Qt::black); lbl->setPos(x, KEYHEIGHT); } else { x = (ocs + qFloor((j-adj) / 2.0)) * KEYWIDTH + KEYWIDTH * 6/10 + 1; key = new PianoKey( QRectF( x, 0, KEYWIDTH * 8/10 - 1, KEYHEIGHT * 6/10 ), true, i ); key->setZValue( 1 ); lbl = new KeyLabel(key); lbl->setDefaultTextColor(Qt::white); lbl->setPos(x - 3, KEYHEIGHT * 6/10 - 3); } //qDebug() << "i=" << i << "ocs=" << ocs << "j=" << j << "x=" << x; key->setAcceptTouchEvents(true); if (m_keyPressedColor.isValid()) key->setPressedBrush(hilightBrush); m_keys.insert(i, key); addItem( key ); lbl->setFont(lblFont); m_labels.insert(i, lbl); } hideOrShowKeys(); retranslate(); } QSize PianoScene::sizeHint() const { return QSize(sceneWidth(m_numKeys), KEYHEIGHT); } void PianoScene::showKeyOn( PianoKey* key, QColor color, int vel ) { if (m_velocityTint && vel >= 0 && color.isValid() ) { QBrush hilightBrush(color.lighter(200 - vel)); key->setPressedBrush(hilightBrush); } key->setPressed(true); } void PianoScene::showKeyOn( PianoKey* key, int vel ) { if (vel >= 0) { if (m_velocityTint && m_keyPressedColor.isValid()) { QBrush hilightBrush(m_keyPressedColor.lighter(200 - vel)); key->setPressedBrush(hilightBrush); } else { setColorFromPolicy(key, vel); } } key->setPressed(true); } void PianoScene::showKeyOff( PianoKey* key, int ) { key->setPressed(false); } void PianoScene::showNoteOn( const int note, QColor color, int vel ) { int n = note - m_baseOctave*12 - m_transpose; if ((note >= m_minNote) && (note <= m_maxNote) && m_keys.contains(n) && color.isValid()) showKeyOn(m_keys.value(n), color, vel); } void PianoScene::showNoteOn( const int note, int vel ) { int n = note - m_baseOctave*12 - m_transpose; if ((note >= m_minNote) && (note <= m_maxNote) && m_keys.contains(n)) showKeyOn(m_keys.value(n), vel); } void PianoScene::showNoteOff( const int note, int vel ) { int n = note - m_baseOctave*12 - m_transpose; if ((note >= m_minNote) && (note <= m_maxNote) && m_keys.contains(n)) showKeyOff(m_keys.value(n), vel); } void PianoScene::triggerNoteOn( const int note, const int vel ) { int n = m_baseOctave*12 + note + m_transpose; if ((n >= m_minNote) && (n <= m_maxNote)) { if (m_handler != NULL) { m_handler->noteOn(n, vel); } else { emit noteOn(n, vel); } } } void PianoScene::triggerNoteOff( const int note, const int vel ) { int n = m_baseOctave*12 + note + m_transpose; if ((n >= m_minNote) && (n <= m_maxNote)) { if (m_handler != NULL) { m_handler->noteOff(n, vel); } else { emit noteOff(n, vel); } } } void PianoScene::setColorFromPolicy(PianoKey* key, int vel) { QColor c; #if defined(PALETTE_SUPPORT) switch (m_palette->paletteId()) { case PAL_SINGLE: c = m_palette->getColor(0); break; case PAL_DOUBLE: c = m_palette->getColor(key->getType()); break; case PAL_CHANNELS: c = m_palette->getColor(m_channel); break; case PAL_SCALE: c = m_palette->getColor(key->getDegree()); } #else c = QApplication::palette().highlight().color(); #endif if (m_velocityTint && c.isValid()) { QBrush h(c.lighter(200 - vel)); key->setPressedBrush(h); } } void PianoScene::keyOn( PianoKey* key ) { triggerNoteOn(key->getNote(), m_velocity); showKeyOn(key, m_velocity); } void PianoScene::keyOff( PianoKey* key ) { triggerNoteOff(key->getNote(), 0); showKeyOff(key, 0); } void PianoScene::keyOn( PianoKey* key, qreal pressure ) { int vel = m_velocity * pressure; triggerNoteOn(key->getNote(), vel); showKeyOn(key, vel); } void PianoScene::keyOff( PianoKey* key, qreal pressure ) { int vel = m_velocity * pressure; triggerNoteOff(key->getNote(), vel); showKeyOff(key, vel); } void PianoScene::keyOn(const int note) { if (m_keys.contains(note)) keyOn(m_keys.value(note)); else triggerNoteOn(note, m_velocity); } void PianoScene::keyOff(const int note) { if (m_keys.contains(note)) keyOff(m_keys.value(note)); else triggerNoteOff(note, m_velocity); } PianoKey* PianoScene::getKeyForPos( const QPointF& p ) const { PianoKey* key = 0; QList ptitems = this->items(p, Qt::IntersectsItemShape, Qt::DescendingOrder); foreach(QGraphicsItem *itm, ptitems) { key = dynamic_cast(itm); if (key != 0) break; } return key; } void PianoScene::mouseMoveEvent ( QGraphicsSceneMouseEvent * mouseEvent ) { if (m_mouseEnabled) { if (m_mousePressed) { PianoKey* key = getKeyForPos(mouseEvent->scenePos()); PianoKey* lastkey = getKeyForPos(mouseEvent->lastScenePos()); if ((lastkey != NULL) && (lastkey != key) && lastkey->isPressed()) { keyOff(lastkey); } if ((key != NULL) && !key->isPressed()) { keyOn(key); } mouseEvent->accept(); return; } } } void PianoScene::mousePressEvent ( QGraphicsSceneMouseEvent * mouseEvent ) { if (m_mouseEnabled) { PianoKey* key = getKeyForPos(mouseEvent->scenePos()); if (key != NULL && !key->isPressed()) { keyOn(key); m_mousePressed = true; mouseEvent->accept(); return; } } } void PianoScene::mouseReleaseEvent ( QGraphicsSceneMouseEvent * mouseEvent ) { if (m_mouseEnabled) { m_mousePressed = false; PianoKey* key = getKeyForPos(mouseEvent->scenePos()); if (key != NULL && key->isPressed()) { keyOff(key); mouseEvent->accept(); return; } } } int PianoScene::getNoteFromKey( const int key ) const { if (m_keybdMap != NULL) { KeyboardMap::ConstIterator it = m_keybdMap->constFind(key); if ((it != m_keybdMap->constEnd()) && (it.key() == key)) { int note = it.value(); return note; } } return -1; } PianoKey* PianoScene::getPianoKey( const int key ) const { int note = getNoteFromKey(key); if (m_keys.contains(note)) return m_keys.value(note); return NULL; } void PianoScene::keyPressEvent ( QKeyEvent * keyEvent ) { if ( m_keyboardEnabled) { if ( !m_rawkbd && !keyEvent->isAutoRepeat() ) { // ignore auto-repeats int note = getNoteFromKey(keyEvent->key()); if (note > -1) keyOn(note); } keyEvent->accept(); return; } keyEvent->ignore(); } void PianoScene::keyReleaseEvent ( QKeyEvent * keyEvent ) { if (m_keyboardEnabled) { if ( !m_rawkbd && !keyEvent->isAutoRepeat() ) { // ignore auto-repeats int note = getNoteFromKey(keyEvent->key()); if (note > -1) keyOff(note); } keyEvent->accept(); return; } keyEvent->ignore(); } bool PianoScene::event(QEvent *event) { switch(event->type()) { case QEvent::TouchBegin: case QEvent::TouchEnd: case QEvent::TouchUpdate: { if (m_touchEnabled) { QTouchEvent *touchEvent = static_cast(event); QList touchPoints = touchEvent->touchPoints(); foreach(const QTouchEvent::TouchPoint& touchPoint, touchPoints) { switch (touchPoint.state()) { //case Qt::TouchPointPrimary: case Qt::TouchPointStationary: continue; case Qt::TouchPointReleased: { PianoKey* key = getKeyForPos(touchPoint.scenePos()); if (key != NULL && key->isPressed()) { keyOff(key, touchPoint.pressure()); } break; } case Qt::TouchPointPressed: { PianoKey* key = getKeyForPos(touchPoint.scenePos()); if (key != NULL && !key->isPressed()) { keyOn(key, touchPoint.pressure()); key->ensureVisible(); } break; } case Qt::TouchPointMoved: { PianoKey* key = getKeyForPos(touchPoint.scenePos()); PianoKey* lastkey = getKeyForPos(touchPoint.lastScenePos()); if ((lastkey != NULL) && (lastkey != key) && lastkey->isPressed()) { keyOff(lastkey, touchPoint.pressure()); } if ((key != NULL) && !key->isPressed()) { keyOn(key, touchPoint.pressure()); } break; } default: //qDebug() << "TouchPoint state: " << touchPoint.state(); break; } } //qDebug() << "accepted event: " << event; event->accept(); return true; } break; } default: break; } //qDebug() << "unprocessed event: " << event; return QGraphicsScene::event(event); } void PianoScene::allKeysOff() { foreach(PianoKey* key, m_keys) { key->setPressed(false); } } void PianoScene::setKeyPressedColor(const QColor& color) { if (color.isValid() && (color != m_keyPressedColor)) { m_keyPressedColor = color; QBrush hilightBrush(m_keyPressedColor); foreach(PianoKey* key, m_keys) { key->setPressedBrush(hilightBrush); } } } void PianoScene::resetKeyPressedColor() { QBrush hilightBrush(m_keyPressedColor.isValid() ? m_keyPressedColor : QApplication::palette().highlight()); foreach(PianoKey* key, m_keys) { key->setPressedBrush(hilightBrush); } } void PianoScene::hideOrShowKeys() { foreach(PianoKey* key, m_keys) { int n = m_baseOctave*12 + key->getNote() + m_transpose; bool b = !(n > m_maxNote) && !(n < m_minNote); key->setVisible(b); } } void PianoScene::setMinNote(const int note) { if (m_minNote != note) { m_minNote = note; hideOrShowKeys(); } } void PianoScene::setMaxNote(const int note) { if (m_maxNote != note) { m_maxNote = note; hideOrShowKeys(); } } void PianoScene::setBaseOctave(const int base) { if (m_baseOctave != base) { m_baseOctave = base; hideOrShowKeys(); refreshLabels(); } } QString PianoScene::noteName(const int note) { int num = (note + m_transpose + 12) % 12; int adj = (note + m_transpose < 0) ? 2 : 1; int oct = m_baseOctave + ((note + m_transpose) / 12) - adj; if (m_noteNames.isEmpty()) { QString name; if (!m_names_f.isEmpty() && !m_names_s.isEmpty()) name = m_useFlats ? m_names_f.value(num) : m_names_s.value(num); return QString("%1%2").arg(name).arg(oct); } else { int noteIndex = note + m_transpose + 12*m_baseOctave; #if defined(SMALL_SCREEN) return m_noteNames.value(noteIndex); #else return QString("%1").arg(m_noteNames.value(noteIndex)); #endif } } void PianoScene::refreshLabels() { foreach(KeyLabel* lbl, m_labels) { PianoKey* key = dynamic_cast(lbl->parentItem()); if(key != NULL) { lbl->setHtml(noteName(key->getNote())); lbl->setVisible(m_showLabels); } } } void PianoScene::refreshKeys() { foreach(PianoKey* key, m_keys) { #if defined(PALETTE_SUPPORT) if (m_showColorScale && m_scalePalette != 0) { int degree = key->getNote() % 12; key->setBrush(m_scalePalette->getColor(degree)); } else { key->resetBrush(); } #endif key->setPressed(false); } } void PianoScene::setShowLabels(bool show) { if (m_showLabels != show) { m_showLabels = show; refreshLabels(); } } void PianoScene::setUseFlats(bool use) { if (m_useFlats != use) { m_useFlats = use; refreshLabels(); } } void PianoScene::setTranspose(const int transpose) { if (m_transpose != transpose && transpose > -12 && transpose < 12) { m_transpose = transpose; hideOrShowKeys(); refreshLabels(); } } void PianoScene::setRawKeyboardMode(bool b) { if (m_rawkbd != b) { m_rawkbd = b; } } void PianoScene::useCustomNoteNames(const QStringList& names) { m_noteNames = names; refreshLabels(); } void PianoScene::useStandardNoteNames() { m_noteNames.clear(); refreshLabels(); } void PianoScene::setKeyboardEnabled(const bool enable) { if (enable != m_keyboardEnabled) { m_keyboardEnabled = enable; } } void PianoScene::setMouseEnabled(const bool enable) { if (enable != m_mouseEnabled) { m_mouseEnabled = enable; } } void PianoScene::setTouchEnabled(const bool enable) { if (enable != m_touchEnabled) { m_touchEnabled = enable; } } void PianoScene::retranslate() { m_names_s.clear(); m_names_f.clear(); m_names_s << trUtf8("C") << trUtf8("C♯") << trUtf8("D") << trUtf8("D♯") << trUtf8("E") << trUtf8("F") << trUtf8("F♯") << trUtf8("G") << trUtf8("G♯") << trUtf8("A") << trUtf8("A♯") << trUtf8("B"); m_names_f << trUtf8("C") << trUtf8("D♭") << trUtf8("D") << trUtf8("E♭") << trUtf8("E") << trUtf8("F") << trUtf8("G♭") << trUtf8("G") << trUtf8("A♭") << trUtf8("A") << trUtf8("B♭") << trUtf8("B"); refreshLabels(); } #if defined(PALETTE_SUPPORT) void PianoScene::setShowColorScale(const bool show) { if (m_showColorScale != show && m_scalePalette != 0 ) { m_showColorScale = show; refreshKeys(); invalidate(); } } void PianoScene::setPianoPalette(PianoPalette *p) { //qDebug() << Q_FUNC_INFO; resetKeyPressedColor(); m_palette = p; } #endif drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/sonivoxsettingsdialog.cpp0000644000000000000000000000013213532747316023101 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/sonivoxsettingsdialog.cpp0000644000175000001440000000771413532747316023703 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include "sonivoxsettingsdialog.h" #include "ui_sonivoxsettingsdialog.h" const QString QSTR_PREFERENCES("SonivoxEAS"); const QString QSTR_BUFFERTIME("BufferTime"); const QString QSTR_REVERBTYPE("ReverbType"); const QString QSTR_REVERBAMT("ReverbAmt"); const QString QSTR_CHORUSTYPE("ChorusType"); const QString QSTR_CHORUSAMT("ChorusAmt"); SonivoxSettingsDialog::SonivoxSettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::SonivoxSettingsDialog) { ui->setupUi(this); ui->combo_Reverb->addItem(QStringLiteral("Large Hall"), 0); ui->combo_Reverb->addItem(QStringLiteral("Hall"), 1); ui->combo_Reverb->addItem(QStringLiteral("Chamber"), 2); ui->combo_Reverb->addItem(QStringLiteral("Room"), 3); ui->combo_Reverb->addItem(QStringLiteral("None"), -1); ui->combo_Reverb->setCurrentIndex(4); ui->combo_Chorus->addItem(QStringLiteral("Preset 1"), 0); ui->combo_Chorus->addItem(QStringLiteral("Preset 2"), 1); ui->combo_Chorus->addItem(QStringLiteral("Preset 3"), 2); ui->combo_Chorus->addItem(QStringLiteral("Preset 4"), 3); ui->combo_Chorus->addItem(QStringLiteral("None"), -1); ui->combo_Chorus->setCurrentIndex(4); connect(ui->buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::pressed, this, &SonivoxSettingsDialog::restoreDefaults); } SonivoxSettingsDialog::~SonivoxSettingsDialog() { delete ui; } void SonivoxSettingsDialog::accept() { writeSettings(); QDialog::accept(); } void SonivoxSettingsDialog::showEvent(QShowEvent *event) { readSettings(); event->accept(); } void SonivoxSettingsDialog::readSettings() { QSettings settings; settings.beginGroup(QSTR_PREFERENCES); int bufferTime = settings.value(QSTR_BUFFERTIME, 60).toInt(); int reverbType = settings.value(QSTR_REVERBTYPE, 1).toInt(); int reverbAmt = settings.value(QSTR_REVERBAMT, 25800).toInt(); int chorusType = settings.value(QSTR_CHORUSTYPE, -1).toInt(); int chorusAmt = settings.value(QSTR_CHORUSAMT, 0).toInt(); settings.endGroup(); ui->spnTime->setValue(bufferTime); ui->dial_Reverb->setValue(reverbAmt); ui->dial_Chorus->setValue(chorusAmt); int reverbIndex = ui->combo_Reverb->findData(reverbType); int chorusIndex = ui->combo_Chorus->findData(chorusType); ui->combo_Reverb->setCurrentIndex(reverbIndex); ui->combo_Chorus->setCurrentIndex(chorusIndex); } void SonivoxSettingsDialog::writeSettings() { QSettings settings; settings.beginGroup(QSTR_PREFERENCES); settings.setValue(QSTR_BUFFERTIME, ui->spnTime->value()); settings.setValue(QSTR_REVERBTYPE, ui->combo_Reverb->currentData()); settings.setValue(QSTR_CHORUSTYPE, ui->combo_Chorus->currentData()); settings.setValue(QSTR_REVERBAMT, ui->dial_Reverb->value()); settings.setValue(QSTR_CHORUSAMT, ui->dial_Chorus->value()); settings.endGroup(); settings.sync(); } void SonivoxSettingsDialog::restoreDefaults() { ui->spnTime->setValue(60); ui->combo_Reverb->setCurrentIndex(1); ui->dial_Reverb->setValue(25800); ui->combo_Chorus->setCurrentIndex(4); ui->dial_Chorus->setValue(0); } drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/networksettingsdialog.h0000644000000000000000000000013213532747316022532 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/networksettingsdialog.h0000644000175000001440000000254613532747316023332 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef NETWORKSETTINGSDIALOG_H #define NETWORKSETTINGSDIALOG_H #include #include namespace Ui { class NetworkSettingsDialog; } class NetworkSettingsDialog : public QDialog { Q_OBJECT public: explicit NetworkSettingsDialog(QWidget *parent = nullptr); ~NetworkSettingsDialog(); void readSettings(); void writeSettings(); public slots: void accept(); void showEvent(QShowEvent *event); void restoreDefaults(); void toggledIPv6(bool checked); private: Ui::NetworkSettingsDialog *ui; }; #endif // NETWORKSETTINGSDIALOG_H drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/pianokeybd.h0000644000000000000000000000013213532747316020225 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/pianokeybd.h0000644000175000001440000000752313532747316021025 0ustar00pedrousers00000000000000/* Virtual Piano Widget for Qt5 Copyright (C) 2008-2019, Pedro Lopez-Cabanillas 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, see . */ #ifndef PIANOKEYBD_H #define PIANOKEYBD_H #include "pianoscene.h" #if defined(RAWKBD_SUPPORT) #include "nativefilter.h" #endif #include #if defined(VPIANO_PLUGIN) #include #else #define QDESIGNER_WIDGET_EXPORT #endif class QDESIGNER_WIDGET_EXPORT PianoKeybd : public QGraphicsView #if defined(RAWKBD_SUPPORT) , public RawKbdHandler #endif { Q_OBJECT Q_PROPERTY( int baseOctave READ baseOctave WRITE setBaseOctave ) Q_PROPERTY( int numKeys READ numKeys WRITE setNumKeys ) Q_PROPERTY( int rotation READ getRotation WRITE setRotation ) Q_PROPERTY( QColor keyPressedColor READ getKeyPressedColor WRITE setKeyPressedColor ) Q_PROPERTY( bool showLabels READ showLabels WRITE setShowLabels ) Q_PROPERTY( bool useFlats READ useFlats WRITE setUseFlats ) Q_PROPERTY( int transpose READ getTranspose WRITE setTranspose ) #if defined(VPIANO_PLUGIN) Q_CLASSINFO("Author", "Pedro Lopez-Cabanillas ") Q_CLASSINFO("URL", "http://sourceforge.net/projects/vmpk") Q_CLASSINFO("Version", "1.0") #endif public: PianoKeybd(QWidget *parent = 0); PianoKeybd(const int baseOctave, const int numKeys, const int startKey, QWidget *parent = 0); virtual ~PianoKeybd(); int baseOctave() const { return m_scene->baseOctave(); } void setBaseOctave(const int baseOctave) { m_scene->setBaseOctave(baseOctave); } int numKeys() const { return m_scene->numKeys(); } int startKey() const { return m_scene->startKey(); } void setNumKeys(const int numKeys, const int startKey = DEFAULTSTARTINGKEY); int getRotation() const { return m_rotation; } void setRotation(int r); QColor getKeyPressedColor() const { return m_scene->getKeyPressedColor(); } void setKeyPressedColor(const QColor& c) { m_scene->setKeyPressedColor(c); } bool showLabels() const { return m_scene->showLabels(); } void setShowLabels(bool show) { m_scene->setShowLabels(show); } bool useFlats() const { return m_scene->useFlats(); } void setUseFlats(bool use) { m_scene->setUseFlats(use); } int getTranspose() const { return m_scene->getTranspose(); } void setTranspose(int t) { m_scene->setTranspose(t); } QSize sizeHint() const; PianoScene* getPianoScene() { return m_scene; } void setRawKeyboardMap(KeyboardMap* m) { m_rawMap = m; } KeyboardMap* getRawKeyboardMap() { return m_rawMap; } void resetRawKeyboardMap() { m_rawMap = &m_defaultRawMap; } void resetKeyboardMap() { m_scene->setKeyboardMap(&m_defaultMap); } #if defined(RAWKBD_SUPPORT) // RawKbdHandler methods bool handleKeyPressed(int keycode); bool handleKeyReleased(int keycode); #endif signals: void noteOn( int midiNote, int vel ); void noteOff( int midiNote, int vel ); protected: void initialize(); void initDefaultMap(); void initScene(int base, int num, int ini, const QColor& c = QColor()); void resizeEvent(QResizeEvent *event); private: int m_rotation; PianoScene *m_scene; KeyboardMap *m_rawMap; KeyboardMap m_defaultMap; KeyboardMap m_defaultRawMap; }; #endif // PIANOKEYBD_H drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/fluidsettingsdialog.cpp0000644000000000000000000000013213532747316022477 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/fluidsettingsdialog.cpp0000644000175000001440000001642113532747316023274 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include "fluidsettingsdialog.h" #include "ui_fluidsettingsdialog.h" const QString QSTR_PREFERENCES("FluidSynth"); const QString QSTR_INSTRUMENTSDEFINITION("InstrumentsDefinition"); const QString QSTR_DATADIR("soundfonts"); const QString QSTR_DATADIR2("sounds/sf2"); const QString QSTR_SOUNDFONT("default.sf2"); const QString QSTR_AUDIODRIVER("AudioDriver"); const QString QSTR_PERIODSIZE("PeriodSize"); const QString QSTR_PERIODS("Periods"); const QString QSTR_SAMPLERATE("SampleRate"); const QString QSTR_CHORUS("Chorus"); const QString QSTR_REVERB("Reverb"); const QString QSTR_GAIN("Gain"); const QString QSTR_POLYPHONY("Polyphony"); const int DEFAULT_PERIODSIZE = 3072; const int DEFAULT_PERIODS = 1; const double DEFAULT_SAMPLERATE = 48000.0; const int DEFAULT_CHORUS = 0; const int DEFAULT_REVERB = 0; const double DEFAULT_GAIN = .5; const int DEFAULT_POLYPHONY = 32; FluidSettingsDialog::FluidSettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::FluidSettingsDialog) { ui->setupUi(this); connect(ui->btnFile, &QToolButton::clicked, this, &FluidSettingsDialog::showFileDialog); connect(ui->buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, this, &FluidSettingsDialog::restoreDefaults); ui->periodSize->setValidator(new QIntValidator(64, 8192, this)); ui->periods->setValidator(new QIntValidator(2, 64, this)); ui->sampleRate->setValidator(new QDoubleValidator(22050.0, 96000.0, 1, this)); ui->gain->setValidator(new QDoubleValidator(0.0, 10.0, 2, this)); ui->polyphony->setValidator(new QIntValidator(16, 4096, this)); } FluidSettingsDialog::~FluidSettingsDialog() { delete ui; } void FluidSettingsDialog::accept() { writeSettings(); QDialog::accept(); } void FluidSettingsDialog::showEvent(QShowEvent *event) { readSettings(); event->accept(); } QString FluidSettingsDialog::defaultAudioDriver() const { const QString QSTR_DEFAULT_AUDIODRIVER = #if defined(Q_OS_LINUX) QLatin1Literal("pulseaudio"); #elif defined(Q_OS_WIN) QLatin1Literal("dsound"); #elif defined(Q_OS_OSX) QLatin1Literal("coreaudio"); #else QLatin1Literal("oss"); #endif return QSTR_DEFAULT_AUDIODRIVER; } void FluidSettingsDialog::readSettings() { QSettings settings; QStringList drivers; QString fs_defSoundFont = QSTR_SOUNDFONT; #if defined(Q_OS_LINUX) drivers << "alsa" << "pulseaudio" << "oss"; #elif defined(Q_OS_WIN) drivers << "dsound"; #elif defined(Q_OS_OSX) drivers << "coreaudio"; #else drivers << "oss"; #endif QDir dir(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QSTR_DATADIR, QStandardPaths::LocateDirectory)); if (!dir.exists()) { dir = QDir(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QSTR_DATADIR2, QStandardPaths::LocateDirectory)); } QFileInfo sf2(dir, QSTR_SOUNDFONT); if (sf2.exists()) { fs_defSoundFont = sf2.absoluteFilePath(); } ui->audioDriver->addItems(drivers); settings.beginGroup(QSTR_PREFERENCES); ui->audioDriver->setCurrentText( settings.value(QSTR_AUDIODRIVER, defaultAudioDriver()).toString() ); ui->periodSize->setText( settings.value(QSTR_PERIODSIZE, DEFAULT_PERIODSIZE).toString() ); ui->periods->setText( settings.value(QSTR_PERIODS, DEFAULT_PERIODS).toString() ); ui->sampleRate->setText( settings.value(QSTR_SAMPLERATE, DEFAULT_SAMPLERATE).toString() ); ui->chorus->setChecked( settings.value(QSTR_CHORUS, DEFAULT_CHORUS).toInt() != 0 ); ui->reverb->setChecked( settings.value(QSTR_REVERB, DEFAULT_REVERB).toInt() != 0 ); ui->gain->setText( settings.value(QSTR_GAIN, DEFAULT_GAIN).toString() ); ui->polyphony->setText( settings.value(QSTR_POLYPHONY, DEFAULT_POLYPHONY).toString() ); ui->soundFont->setText( settings.value(QSTR_INSTRUMENTSDEFINITION, fs_defSoundFont).toString() ); settings.endGroup(); } void FluidSettingsDialog::writeSettings() { QSettings settings; QString audioDriver; QString soundFont(QSTR_SOUNDFONT); int periodSize(DEFAULT_PERIODSIZE); int periods(DEFAULT_PERIODS); double sampleRate(DEFAULT_SAMPLERATE); int chorus(DEFAULT_CHORUS); int reverb(DEFAULT_REVERB); double gain(DEFAULT_GAIN); int polyphony(DEFAULT_POLYPHONY); audioDriver = ui->audioDriver->currentText(); if (audioDriver.isEmpty()) { audioDriver = defaultAudioDriver(); } soundFont = ui->soundFont->text(); periodSize = ui->periodSize->text().toInt(); periods = ui->periods->text().toInt(); sampleRate = ui->sampleRate->text().toDouble(); chorus = (ui->chorus->isChecked() ? 1 : 0); reverb = (ui->reverb->isChecked() ? 1 : 0); gain = ui->gain->text().toDouble(); polyphony = ui->polyphony->text().toInt(); settings.beginGroup(QSTR_PREFERENCES); settings.setValue(QSTR_INSTRUMENTSDEFINITION, soundFont); settings.setValue(QSTR_AUDIODRIVER, audioDriver); settings.setValue(QSTR_PERIODSIZE, periodSize); settings.setValue(QSTR_PERIODS, periods); settings.setValue(QSTR_SAMPLERATE, sampleRate); settings.setValue(QSTR_CHORUS, chorus); settings.setValue(QSTR_REVERB, reverb); settings.setValue(QSTR_GAIN, gain); settings.setValue(QSTR_POLYPHONY, polyphony); settings.endGroup(); settings.sync(); } void FluidSettingsDialog::restoreDefaults() { ui->audioDriver->setCurrentText( defaultAudioDriver() ); ui->periodSize->setText( QString::number( DEFAULT_PERIODSIZE )); ui->periods->setText( QString::number( DEFAULT_PERIODS )); ui->sampleRate->setText( QString::number( DEFAULT_SAMPLERATE )); ui->chorus->setChecked( DEFAULT_CHORUS != 0 ); ui->reverb->setChecked( DEFAULT_REVERB != 0 ); ui->gain->setText( QString::number( DEFAULT_GAIN ) ); ui->polyphony->setText( QString::number( DEFAULT_POLYPHONY )); ui->soundFont->setText( QSTR_SOUNDFONT ); } void FluidSettingsDialog::showFileDialog() { QDir dir(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QSTR_DATADIR, QStandardPaths::LocateDirectory)); if (!dir.exists()) { dir = QDir(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QSTR_DATADIR2, QStandardPaths::LocateDirectory)); } QString fileName = QFileDialog::getOpenFileName(this, tr("Select SoundFont"), dir.absolutePath(), tr("SoundFont Files (*.sf2)")); if (!fileName.isEmpty()) { ui->soundFont->setText(fileName); } } drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/keyboardmap.h0000644000000000000000000000013213532747316020376 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/keyboardmap.h0000644000175000001440000000175713532747316021201 0ustar00pedrousers00000000000000/* Virtual Piano Widget for Qt5 Copyright (C) 2008-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; If not, see . */ #ifndef KEYBOARDMAP_H #define KEYBOARDMAP_H typedef QHash KeyboardMap; const int DEFAULTSTARTINGKEY = 9; const int DEFAULTBASEOCTAVE = 1; const int DEFAULTNUMBEROFKEYS = 88; const int KEYLABELFONTSIZE = 7; #endif // KEYBOARDMAP_H drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/macsynthsettingsdialog.cpp0000644000000000000000000000013213532747316023222 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/macsynthsettingsdialog.cpp0000644000175000001440000000504013532747316024012 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include "macsynthsettingsdialog.h" #include "ui_macsynthsettingsdialog.h" MacSynthSettingsDialog::MacSynthSettingsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::MacSynthSettingsDialog) { ui->setupUi(this); connect(ui->buttonBox->button(QDialogButtonBox::RestoreDefaults), &QPushButton::pressed, this, &MacSynthSettingsDialog::restoreDefaults); } MacSynthSettingsDialog::~MacSynthSettingsDialog() { delete ui; } void MacSynthSettingsDialog::accept() { writeSettings(); QDialog::accept(); } void MacSynthSettingsDialog::showEvent(QShowEvent *event) { readSettings(); event->accept(); } void MacSynthSettingsDialog::readSettings() { QSettings settings; settings.beginGroup("DLS Synth"); bool reverb = settings.value("reverb_dls", false).toBool(); bool def = settings.value("default_dls", true).toBool(); QString soundfont = settings.value("soundfont_dls").toString(); settings.endGroup(); ui->reverb_dls->setChecked(reverb); ui->default_dls->setChecked(def); ui->soundfont_dls->setText(soundfont); } void MacSynthSettingsDialog::writeSettings() { QSettings settings; QString soundfont = ui->soundfont_dls->text(); bool reverb = ui->reverb_dls->isChecked(); bool def = ui->default_dls->isChecked(); settings.beginGroup("DLS Synth"); settings.setValue("soundfont_dls", soundfont); settings.setValue("reverb_dls", reverb); settings.setValue("default_dls", def); settings.endGroup(); settings.sync(); } void MacSynthSettingsDialog::restoreDefaults() { ui->reverb_dls->setChecked(false); ui->default_dls->setChecked(true); ui->soundfont_dls->clear(); } drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/pianoscene.h0000644000000000000000000000013213532747316020224 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/pianoscene.h0000644000175000001440000001363213532747316021022 0ustar00pedrousers00000000000000/* Virtual Piano Widget for Qt5 Copyright (C) 2008-2019, Pedro Lopez-Cabanillas 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, see . */ #ifndef PIANOSCENE_H_ #define PIANOSCENE_H_ #include "pianokey.h" #include "keylabel.h" #include "keyboardmap.h" #if defined(PALETTE_SUPPORT) #include "pianopalette.h" #endif #include #include class PianoHandler { public: virtual ~PianoHandler() {} virtual void noteOn( const int note, const int vel ) = 0; virtual void noteOff( const int note, const int vel ) = 0; }; class VPIANO_EXPORT PianoScene : public QGraphicsScene { Q_OBJECT public: PianoScene ( const int baseOctave, const int numKeys, const int startKey, const QColor& keyPressedColor = QColor(), QObject * parent = 0 ); QSize sizeHint() const; void setKeyboardMap( KeyboardMap* map ) { m_keybdMap = map; } KeyboardMap* getKeyboardMap() const { return m_keybdMap; } PianoHandler* getPianoHandler() const { return m_handler; } void setPianoHandler(PianoHandler* handler) { m_handler = handler; } #if defined(PALETTE_SUPPORT) PianoPalette* getPianoPalette() const { return m_palette; } void setPianoPalette( PianoPalette* p ); void setColorScalePalette( PianoPalette* p ) { m_scalePalette = p; } bool showColorScale() const { return m_showColorScale; } void setShowColorScale(const bool show); #endif QColor getKeyPressedColor() const { return m_keyPressedColor; } void setKeyPressedColor(const QColor& color); void resetKeyPressedColor(); int getMinNote() const { return m_minNote; } void setMinNote(const int note); int getMaxNote() const { return m_maxNote; } void setMaxNote(const int note); int getTranspose() const { return m_transpose; } void setTranspose(const int transpose); bool showLabels() const { return m_showLabels; } void setShowLabels(const bool show); bool useFlats() const { return m_useFlats; } void setUseFlats(const bool use); bool isKeyboardEnabled() const { return m_keyboardEnabled; } void setKeyboardEnabled( const bool enable ); bool isMouseEnabled() const { return m_mouseEnabled; } void setMouseEnabled( const bool enable ); bool isTouchEnabled() const { return m_touchEnabled; } void setTouchEnabled( const bool enable ); bool velocityTint() const { return m_velocityTint; } void setVelocityTint( const bool enable ) { m_velocityTint = enable; } void showNoteOn( const int note, QColor color, int vel = -1 ); void showNoteOn( const int note, int vel = -1 ); void showNoteOff( const int note, int vel = -1 ); int baseOctave() const { return m_baseOctave; } void setBaseOctave( const int base ); int numKeys() const { return m_numKeys; } int startKey() const { return m_startKey; } void allKeysOff(); void keyOn( const int note ); void keyOff( const int note ); bool getRawKeyboardMode() const { return m_rawkbd; } void setRawKeyboardMode(const bool b); void useCustomNoteNames(const QStringList& names); void useStandardNoteNames(); int getVelocity() { return m_velocity; } void setVelocity(const int velocity) { m_velocity = velocity; } int getChannel() const { return m_channel; } void setChannel(const int channel) { m_channel = channel; } void retranslate(); QStringList noteNames() const { return m_names_s; } signals: void noteOn(int n, int v); void noteOff(int n, int v); protected: void showKeyOn( PianoKey* key, QColor color, int vel ); void showKeyOn( PianoKey* key, int vel ); void showKeyOff( PianoKey* key, int vel ); void keyOn( PianoKey* key ); void keyOff( PianoKey* key ); void keyOn( PianoKey* key, qreal pressure ); void keyOff( PianoKey* key, qreal pressure ); PianoKey* getKeyForPos( const QPointF& p ) const; PianoKey* getPianoKey( const int key ) const; QString noteName(const int note); void mouseMoveEvent ( QGraphicsSceneMouseEvent * mouseEvent ); void mousePressEvent ( QGraphicsSceneMouseEvent * mouseEvent ); void mouseReleaseEvent ( QGraphicsSceneMouseEvent * mouseEvent ); void keyPressEvent ( QKeyEvent * keyEvent ); void keyReleaseEvent ( QKeyEvent * keyEvent ); bool event(QEvent *event); private: void hideOrShowKeys(); void refreshLabels(); void refreshKeys(); void triggerNoteOn( const int note, const int vel ); void triggerNoteOff( const int note, const int vel ); int getNoteFromKey( const int key ) const; void setColorFromPolicy(PianoKey* key, const int vel); int m_baseOctave; int m_numKeys; int m_startKey; int m_minNote; int m_maxNote; int m_transpose; bool m_showLabels; bool m_useFlats; bool m_rawkbd; bool m_keyboardEnabled; bool m_mouseEnabled; bool m_touchEnabled; QColor m_keyPressedColor; bool m_mousePressed; int m_velocity; int m_channel; bool m_velocityTint; PianoHandler* m_handler; KeyboardMap* m_keybdMap; QHash m_keys; QMap m_labels; QStringList m_noteNames; QStringList m_names_s; QStringList m_names_f; #if defined(PALETTE_SUPPORT) bool m_showColorScale; PianoPalette* m_palette; PianoPalette* m_scalePalette; #endif }; #endif /*PIANOSCENE_H_*/ drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/macsynthsettingsdialog.ui0000644000000000000000000000013213532747316023055 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/macsynthsettingsdialog.ui0000644000175000001440000001033113532747316023644 0ustar00pedrousers00000000000000 MacSynthSettingsDialog 0 0 304 182 SoundFont: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter soundfont_dls true 0 0 ... Qt::Vertical 20 256 Use Internal Reverb Default Apple DLS Sound Set Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults soundfont_dls btn_soundfont default_dls reverb_dls default_dls toggled(bool) soundfont_dls setDisabled(bool) 136 58 260 31 default_dls toggled(bool) btn_soundfont setDisabled(bool) 294 58 294 30 default_dls toggled(bool) label_3 setDisabled(bool) 96 58 66 31 buttonBox accepted() MacSynthSettingsDialog accept() 170 158 192 184 buttonBox rejected() MacSynthSettingsDialog reject() 259 155 281 179 drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/vpianoabout.ui0000644000000000000000000000013213532747316020615 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/vpianoabout.ui0000644000175000001440000001172413532747316021413 0ustar00pedrousers00000000000000 AboutClass 0 0 487 334 About false true <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:16pt; font-weight:600;">Drumstick Virtual Piano %VERSION%</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:9pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Sample application for the <a href="http://drumstick.sourceforge.net"><span style=" font-family:'DejaVu Sans'; text-decoration: underline; color:#0057ae;">Drumstick MIDI Sequencer C++ library</span></a></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copyright © 2006-2019, Pedro Lopez-Cabanillas &lt;<a href="mailto:plcl@users.sf.net"><span style=" font-family:'DejaVu Sans'; text-decoration: underline; color:#0057ae;">plcl@users.sf.net</span></a>&gt;</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">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.</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">You should have received a copy of the GNU General Public License along with this program. If not, see </span><a href="http://www.gnu.org/licenses/"><span style=" text-decoration: underline; color:#0057ae;">http://www.gnu.org/licenses/</span></a><span style=" font-size:8pt;">.</span></p></body></html> true QDialogButtonBox::Close buttonBox rejected() AboutClass close() 306 315 325 335 drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/connections.h0000644000000000000000000000013213532747316020422 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/connections.h0000644000175000001440000000363613532747316021223 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef CONNECTIONS_H #define CONNECTIONS_H #include #include #include #include #include #include "ui_connections.h" using namespace drumstick::rt; class Connections : public QDialog { Q_OBJECT public: Connections(QWidget *parent = 0); void setInput(MIDIInput *in) { m_midiIn = in; } void setOutput(MIDIOutput *out) { m_midiOut = out; } void setInputs(QList ins); void setOutputs(QList outs); MIDIInput *getInput() { return m_midiIn; } MIDIOutput *getOutput() { return m_midiOut; } void setAdvanced(bool value); bool advanced(); bool midiThru(); public slots: void configureInputDriver(); void configureOutputDriver(); void clickedAdvanced(bool value); void setMidiThru(bool value); void refreshInputs(QString id); void refreshOutputs(QString id); void refresh(); void accept(); private: bool m_advanced; bool m_thru; bool m_settingsChanged; MIDIInput* m_midiIn; MIDIOutput* m_midiOut; Ui::ConnectionsClass ui; }; #endif // CONNECTIONS_H drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/preferences.cpp0000644000000000000000000000013213532747316020734 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/preferences.cpp0000644000175000001440000000546613532747316021540 0ustar00pedrousers00000000000000/* Virtual Piano test using the MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "preferences.h" #include #include Preferences::Preferences(QWidget *parent) : QDialog(parent), m_inChannel(0), m_outChannel(0), m_velocity(100), m_baseOctave(1), m_numKeys(88), m_startingKey(9) { ui.setupUi( this ); connect(ui.buttonBox, SIGNAL(clicked(QAbstractButton*)), SLOT(slotButtonClicked(QAbstractButton*))); } void Preferences::slotButtonClicked(QAbstractButton *button) { if (dynamic_cast(button) == ui.buttonBox->button(QDialogButtonBox::Apply)) { apply(); } } void Preferences::showEvent ( QShowEvent *event ) { if (event->type() == QEvent::Show) { ui.spinInChan->setValue( m_inChannel ); ui.spinOutChan->setValue( m_outChannel ); ui.spinVelocity->setValue( m_velocity ); ui.spinBaseOctave->setValue( m_baseOctave ); ui.spinNumKeys->setValue( m_numKeys ); ui.comboNotes->setCurrentIndex( m_startingKey ); } } void Preferences::apply() { m_inChannel = ui.spinInChan->value(); m_outChannel = ui.spinOutChan->value(); m_velocity = ui.spinVelocity->value(); m_baseOctave = ui.spinBaseOctave->value(); m_numKeys = ui.spinNumKeys->value(); m_startingKey = ui.comboNotes->currentIndex(); } void Preferences::accept() { apply(); QDialog::accept(); } void Preferences::setInChannel(const int chan) { m_inChannel = chan; ui.spinInChan->setValue(m_inChannel); } void Preferences::setOutChannel(const int chan) { m_outChannel = chan; ui.spinOutChan->setValue(m_outChannel); } void Preferences::setVelocity(const int vel) { m_velocity = vel; ui.spinVelocity->setValue(m_velocity); } void Preferences::setBaseOctave(const int octave) { m_baseOctave = octave; ui.spinBaseOctave->setValue(m_baseOctave); } void Preferences::setNumKeys(const int keys) { m_numKeys = keys; ui.spinNumKeys->setValue(m_numKeys); } void Preferences::setStartingKey(const int key) { m_startingKey = key; ui.comboNotes->setCurrentIndex(m_startingKey); } drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/pianokeybd.cpp0000644000000000000000000000013213532747316020560 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/pianokeybd.cpp0000644000175000001440000002307313532747316021356 0ustar00pedrousers00000000000000/* Virtual Piano Widget for Qt5 Copyright (C) 2008-2019, Pedro Lopez-Cabanillas 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, see . */ #include #include "pianokeybd.h" PianoKeybd::PianoKeybd(QWidget *parent) : QGraphicsView(parent), m_rotation(0), m_scene(NULL), m_rawMap(NULL) { initialize(); initScene(DEFAULTBASEOCTAVE, DEFAULTNUMBEROFKEYS, DEFAULTSTARTINGKEY); } PianoKeybd::PianoKeybd(const int baseOctave, const int numKeys, const int startKey, QWidget *parent) : QGraphicsView(parent), m_rotation(0), m_scene(NULL), m_rawMap(NULL) { initialize(); initScene(baseOctave, numKeys, startKey); } PianoKeybd::~PianoKeybd() { m_scene->setRawKeyboardMode(false); setRawKeyboardMap(0); } void PianoKeybd::initScene(int base, int num, int strt, const QColor& c) { m_scene = new PianoScene(base, num, strt, c, this); m_scene->setKeyboardMap(&m_defaultMap); connect(m_scene, SIGNAL(noteOn(int,int)), SIGNAL(noteOn(int,int))); connect(m_scene, SIGNAL(noteOff(int,int)), SIGNAL(noteOff(int,int))); setScene(m_scene); } void PianoKeybd::initialize() { setAttribute(Qt::WA_AcceptTouchEvents); setAttribute(Qt::WA_InputMethodEnabled, false); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setCacheMode(CacheBackground); setViewportUpdateMode(MinimalViewportUpdate); setRenderHints(QPainter::Antialiasing|QPainter::TextAntialiasing|QPainter::SmoothPixmapTransform); setOptimizationFlag(DontClipPainter, true); setOptimizationFlag(DontSavePainterState, true); setOptimizationFlag(DontAdjustForAntialiasing, true); setBackgroundBrush(QApplication::palette().background()); initDefaultMap(); } void PianoKeybd::resizeEvent(QResizeEvent *event) { QGraphicsView::resizeEvent(event); fitInView(m_scene->sceneRect(), Qt::KeepAspectRatio); } void PianoKeybd::initDefaultMap() { // Default translated Keyboard Map m_defaultMap.insert(Qt::Key_Z, 12); m_defaultMap.insert(Qt::Key_S, 13); m_defaultMap.insert(Qt::Key_X, 14); m_defaultMap.insert(Qt::Key_D, 15); m_defaultMap.insert(Qt::Key_C, 16); m_defaultMap.insert(Qt::Key_V, 17); m_defaultMap.insert(Qt::Key_G, 18); m_defaultMap.insert(Qt::Key_B, 19); m_defaultMap.insert(Qt::Key_H, 20); m_defaultMap.insert(Qt::Key_N, 21); m_defaultMap.insert(Qt::Key_J, 22); m_defaultMap.insert(Qt::Key_M, 23); m_defaultMap.insert(Qt::Key_Q, 24); m_defaultMap.insert(Qt::Key_2, 25); m_defaultMap.insert(Qt::Key_W, 26); m_defaultMap.insert(Qt::Key_3, 27); m_defaultMap.insert(Qt::Key_E, 28); m_defaultMap.insert(Qt::Key_R, 29); m_defaultMap.insert(Qt::Key_5, 30); m_defaultMap.insert(Qt::Key_T, 31); m_defaultMap.insert(Qt::Key_6, 32); m_defaultMap.insert(Qt::Key_Y, 33); m_defaultMap.insert(Qt::Key_7, 34); m_defaultMap.insert(Qt::Key_U, 35); m_defaultMap.insert(Qt::Key_I, 36); m_defaultMap.insert(Qt::Key_9, 37); m_defaultMap.insert(Qt::Key_O, 38); m_defaultMap.insert(Qt::Key_0, 39); m_defaultMap.insert(Qt::Key_P, 40); // Default Raw Keyboard Map #if defined(Q_OS_LINUX) m_defaultRawMap.insert(94, 11); m_defaultRawMap.insert(52, 12); m_defaultRawMap.insert(39, 13); m_defaultRawMap.insert(53, 14); m_defaultRawMap.insert(40, 15); m_defaultRawMap.insert(54, 16); m_defaultRawMap.insert(55, 17); m_defaultRawMap.insert(42, 18); m_defaultRawMap.insert(56, 19); m_defaultRawMap.insert(43, 20); m_defaultRawMap.insert(57, 21); m_defaultRawMap.insert(44, 22); m_defaultRawMap.insert(58, 23); m_defaultRawMap.insert(59, 24); m_defaultRawMap.insert(46, 25); m_defaultRawMap.insert(60, 26); m_defaultRawMap.insert(47, 27); m_defaultRawMap.insert(61, 28); m_defaultRawMap.insert(24, 29); m_defaultRawMap.insert(11, 30); m_defaultRawMap.insert(25, 31); m_defaultRawMap.insert(12, 32); m_defaultRawMap.insert(26, 33); m_defaultRawMap.insert(13, 34); m_defaultRawMap.insert(27, 35); m_defaultRawMap.insert(28, 36); m_defaultRawMap.insert(15, 37); m_defaultRawMap.insert(29, 38); m_defaultRawMap.insert(16, 39); m_defaultRawMap.insert(30, 40); m_defaultRawMap.insert(31, 41); m_defaultRawMap.insert(18, 42); m_defaultRawMap.insert(32, 43); m_defaultRawMap.insert(19, 44); m_defaultRawMap.insert(33, 45); m_defaultRawMap.insert(20, 46); m_defaultRawMap.insert(34, 47); m_defaultRawMap.insert(35, 48); #endif #if defined(Q_OS_WIN) m_defaultRawMap.insert(86, 11); m_defaultRawMap.insert(44, 12); m_defaultRawMap.insert(31, 13); m_defaultRawMap.insert(45, 14); m_defaultRawMap.insert(32, 15); m_defaultRawMap.insert(46, 16); m_defaultRawMap.insert(47, 17); m_defaultRawMap.insert(34, 18); m_defaultRawMap.insert(48, 19); m_defaultRawMap.insert(35, 20); m_defaultRawMap.insert(49, 21); m_defaultRawMap.insert(36, 22); m_defaultRawMap.insert(50, 23); m_defaultRawMap.insert(51, 24); m_defaultRawMap.insert(38, 25); m_defaultRawMap.insert(52, 26); m_defaultRawMap.insert(39, 27); m_defaultRawMap.insert(53, 28); m_defaultRawMap.insert(16, 29); m_defaultRawMap.insert(3, 30); m_defaultRawMap.insert(17, 31); m_defaultRawMap.insert(4, 32); m_defaultRawMap.insert(18, 33); m_defaultRawMap.insert(5, 34); m_defaultRawMap.insert(19, 35); m_defaultRawMap.insert(20, 36); m_defaultRawMap.insert(7, 37); m_defaultRawMap.insert(21, 38); m_defaultRawMap.insert(8, 39); m_defaultRawMap.insert(22, 40); m_defaultRawMap.insert(23, 41); m_defaultRawMap.insert(10, 42); m_defaultRawMap.insert(24, 43); m_defaultRawMap.insert(11, 44); m_defaultRawMap.insert(25, 45); m_defaultRawMap.insert(12, 46); m_defaultRawMap.insert(26, 47); m_defaultRawMap.insert(27, 48); #endif #if defined(Q_OS_MAC) m_defaultRawMap.insert(50, 11); m_defaultRawMap.insert(6, 12); m_defaultRawMap.insert(1, 13); m_defaultRawMap.insert(7, 14); m_defaultRawMap.insert(2, 15); m_defaultRawMap.insert(8, 16); m_defaultRawMap.insert(9, 17); m_defaultRawMap.insert(5, 18); m_defaultRawMap.insert(11, 19); m_defaultRawMap.insert(4, 20); m_defaultRawMap.insert(45, 21); m_defaultRawMap.insert(38, 22); m_defaultRawMap.insert(46, 23); m_defaultRawMap.insert(43, 24); m_defaultRawMap.insert(37, 25); m_defaultRawMap.insert(47, 26); m_defaultRawMap.insert(41, 27); m_defaultRawMap.insert(44, 28); m_defaultRawMap.insert(12, 29); m_defaultRawMap.insert(19, 30); m_defaultRawMap.insert(13, 31); m_defaultRawMap.insert(20, 32); m_defaultRawMap.insert(14, 33); m_defaultRawMap.insert(21, 34); m_defaultRawMap.insert(15, 35); m_defaultRawMap.insert(17, 36); m_defaultRawMap.insert(22, 37); m_defaultRawMap.insert(16, 38); m_defaultRawMap.insert(26, 39); m_defaultRawMap.insert(32, 40); m_defaultRawMap.insert(34, 41); m_defaultRawMap.insert(25, 42); m_defaultRawMap.insert(31, 43); m_defaultRawMap.insert(29, 44); m_defaultRawMap.insert(35, 45); m_defaultRawMap.insert(27, 46); m_defaultRawMap.insert(33, 47); m_defaultRawMap.insert(30, 48); #endif m_rawMap = &m_defaultRawMap; } void PianoKeybd::setNumKeys(const int numKeys, const int startKey) { if ( numKeys != m_scene->numKeys() || startKey != m_scene->startKey() ) { int baseOctave = m_scene->baseOctave(); QColor color = m_scene->getKeyPressedColor(); PianoHandler* handler = m_scene->getPianoHandler(); KeyboardMap* keyMap = m_scene->getKeyboardMap(); bool keyboardEnabled = m_scene->isKeyboardEnabled(); bool mouseEnabled = m_scene->isMouseEnabled(); bool touchEnabled = m_scene->isTouchEnabled(); delete m_scene; initScene(baseOctave, numKeys, startKey, color); m_scene->setPianoHandler(handler); m_scene->setKeyboardMap(keyMap); m_scene->setKeyboardEnabled(keyboardEnabled); m_scene->setMouseEnabled(mouseEnabled); m_scene->setTouchEnabled(touchEnabled); fitInView(m_scene->sceneRect(), Qt::KeepAspectRatio); } } void PianoKeybd::setRotation(int r) { if (r != m_rotation) { m_rotation = r; resetTransform(); rotate(m_rotation); fitInView(m_scene->sceneRect(), Qt::KeepAspectRatio); } } QSize PianoKeybd::sizeHint() const { return mapFromScene(sceneRect()).boundingRect().size(); } #if defined(RAWKBD_SUPPORT) bool PianoKeybd::handleKeyPressed(int keycode) { if (m_scene->isKeyboardEnabled() && m_rawMap != NULL && m_rawMap->contains(keycode)) { m_scene->keyOn(m_rawMap->value(keycode)); return true; } return false; } bool PianoKeybd::handleKeyReleased(int keycode) { if (m_scene->isKeyboardEnabled() && m_rawMap != NULL && m_rawMap->contains(keycode)) { m_scene->keyOff(m_rawMap->value(keycode)); return true; } return false; } #endif drumstick-1.1.3/utils/vpiano/PaxHeaders.32572/pianodefs.h0000644000000000000000000000013213532747316020050 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/vpiano/pianodefs.h0000644000175000001440000000171513532747316020645 0ustar00pedrousers00000000000000/* Virtual Piano Widget for Qt5 Copyright (C) 2008-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; If not, see . */ #ifndef PIANODEFS_H #define PIANODEFS_H //#if defined(VPIANO_PLUGIN) //#define VPIANO_EXPORT Q_DECL_EXPORT //#else //#define VPIANO_EXPORT Q_DECL_IMPORT //#endif #define VPIANO_EXPORT #endif // PIANODEFS_H drumstick-1.1.3/utils/PaxHeaders.32572/utils.pro0000644000000000000000000000013213532747316016315 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/utils.pro0000644000175000001440000000051213532747316017104 0ustar00pedrousers00000000000000TEMPLATE = subdirs CONFIG += ordered include (../global.pri) DEFINES += VERSION=$$VERSION SUBDIRS += \ dumpove \ dumpsmf \ dumpwrk \ vpiano linux* { SUBDIRS += \ drumgrid \ dumpmid \ guiplayer \ metronome \ playsmf \ sysinfo } macx { OTHER_FILES += Info.plist.app } drumstick-1.1.3/utils/PaxHeaders.32572/dumpmid0000644000000000000000000000013213532747316016015 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpmid/0000755000175000001440000000000013532747316016663 5ustar00pedrousers00000000000000drumstick-1.1.3/utils/dumpmid/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316020632 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpmid/CMakeLists.txt0000644000175000001440000000235313532747316021426 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . SET(dumpmid_SRCS dumpmid.cpp dumpmid.h ) SET(dumpmid_qtobject_SRCS dumpmid.h ) QT5_WRAP_CPP(dumpmid_moc_SRCS ${dumpmid_qtobject_SRCS}) ADD_EXECUTABLE(drumstick-dumpmid ${dumpmid_moc_SRCS} ${dumpmid_SRCS} ) target_include_directories(drumstick-dumpmid PRIVATE ../common ) TARGET_LINK_LIBRARIES(drumstick-dumpmid ${ALSA_LIBS} drumstick-alsa Qt5::Core ) # we should install some files... INSTALL(TARGETS drumstick-dumpmid RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) drumstick-1.1.3/utils/dumpmid/PaxHeaders.32572/dumpmid.cpp0000644000000000000000000000013213532747316020235 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpmid/dumpmid.cpp0000644000175000001440000003757213532747316021044 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include "dumpmid.h" #include "cmdversion.h" const QString PGM_NAME("drumstick-dumpmid"); const QString PGM_DESCRIPTION("Drumstick command line utility for decoding MIDI events"); static QTextStream cout(stdout, QIODevice::WriteOnly); static QTextStream cerr(stderr, QIODevice::WriteOnly); QDumpMIDI::QDumpMIDI() : QObject() { m_Client = new MidiClient(this); m_Client->open(); m_Client->setClientName("DumpMIDI"); #ifndef USE_QEVENTS // using signals instead connect( m_Client, SIGNAL(eventReceived(SequencerEvent*)), SLOT(sequencerEvent(SequencerEvent*)), Qt::DirectConnection ); #endif m_Port = new MidiPort(this); m_Port->attach( m_Client ); m_Port->setPortName("DumpMIDI port"); m_Port->setCapability( SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE ); m_Port->setPortType( SND_SEQ_PORT_TYPE_APPLICATION | SND_SEQ_PORT_TYPE_MIDI_GENERIC ); #ifdef WANT_TIMESTAMPS m_Queue = m_Client->createQueue("DumpMIDI"); m_Port->setTimestamping(true); //m_Port->setTimestampReal(true); m_Port->setTimestampQueue(m_Queue->getId()); #endif connect( m_Port, SIGNAL(subscribed(MidiPort*,Subscription*)), SLOT(subscription(MidiPort*,Subscription*))); qDebug() << "Trying to subscribe from Announce"; m_Port->subscribeFromAnnounce(); } QDumpMIDI::~QDumpMIDI() { m_Port->detach(); delete m_Port; m_Client->close(); delete m_Client; } bool QDumpMIDI::stopped() { QReadLocker locker(&m_mutex); return m_Stopped; } void QDumpMIDI::stop() { QWriteLocker locker(&m_mutex); m_Stopped = true; } void QDumpMIDI::subscription(MidiPort*, Subscription* subs) { qDebug() << "Subscription made from" << subs->getSender()->client << ":" << subs->getSender()->port; } void QDumpMIDI::subscribe(const QString& portName) { try { qDebug() << "Trying to subscribe" << portName.toLocal8Bit().data(); m_Port->subscribeFrom(portName); } catch (const SequencerError& err) { cerr << "SequencerError exception. Error code: " << err.code() << " (" << err.qstrError() << ")" << endl; cerr << "Location: " << err.location() << endl; throw err; } } void QDumpMIDI::run() { cout << "Press Ctrl+C to exit" << endl; #ifdef WANT_TIMESTAMPS cout << "___Ticks "; #endif cout << "Source_ Event_________________ Ch _Data__" << endl; try { #ifdef USE_QEVENTS m_Client->addListener(this); m_Client->setEventsEnabled(true); #endif m_Client->setRealTimeInput(false); m_Client->startSequencerInput(); #ifdef WANT_TIMESTAMPS m_Queue->start(); #endif m_Stopped = false; while (!stopped()) { #ifdef USE_QEVENTS QApplication::sendPostedEvents(); #endif sleep(1); } #ifdef WANT_TIMESTAMPS m_Queue->stop(); #endif m_Client->stopSequencerInput(); } catch (const SequencerError& err) { cerr << "SequencerError exception. Error code: " << err.code() << " (" << err.qstrError() << ")" << endl; cerr << "Location: " << err.location() << endl; throw err; } } #ifdef USE_QEVENTS void QDumpMIDI::customEvent(QEvent *ev) { if (ev->type() == SequencerEventType) { SequencerEvent* sev = static_cast(ev); if (sev != NULL) { dumpEvent(sev); } } } #else void QDumpMIDI::sequencerEvent(SequencerEvent *ev) { dumpEvent(ev); delete ev; } #endif void QDumpMIDI::dumpEvent(SequencerEvent* sev) { #ifdef WANT_TIMESTAMPS cout << qSetFieldWidth(8) << right << sev->getTick(); /* More timestamp options: cout << sev->getRealTimeSecs(); cout << sev->getRealTimeNanos(); */ /* Getting the time from the queue status object; QueueStatus sts = m_Queue->getStatus(); cout << qSetFieldWidth(8) << right << sts.getClockTime(); cout << sts.getTickTime(); */ cout << qSetFieldWidth(0) << " "; #endif cout << qSetFieldWidth(3) << right << sev->getSourceClient() << qSetFieldWidth(0) << ":"; cout << qSetFieldWidth(3) << left << sev->getSourcePort() << qSetFieldWidth(0) << " "; switch (sev->getSequencerType()) { case SND_SEQ_EVENT_NOTEON: { NoteOnEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(23) << left << "Note on"; cout << qSetFieldWidth(2) << right << e->getChannel() << " "; cout << qSetFieldWidth(3) << e->getKey() << " "; cout << qSetFieldWidth(3) << e->getVelocity(); } break; } case SND_SEQ_EVENT_NOTEOFF: { NoteOffEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(23) << left << "Note off"; cout << qSetFieldWidth(2) << right << e->getChannel() << " "; cout << qSetFieldWidth(3) << e->getKey() << " "; cout << qSetFieldWidth(3) << e->getVelocity(); } break; } case SND_SEQ_EVENT_KEYPRESS: { KeyPressEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(23) << left << "Polyphonic aftertouch"; cout << qSetFieldWidth(2) << right << e->getChannel() << " "; cout << qSetFieldWidth(3) << e->getKey() << " "; cout << qSetFieldWidth(3) << e->getVelocity(); } break; } case SND_SEQ_EVENT_CONTROL14: case SND_SEQ_EVENT_NONREGPARAM: case SND_SEQ_EVENT_REGPARAM: case SND_SEQ_EVENT_CONTROLLER: { ControllerEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(23) << left << "Control change"; cout << qSetFieldWidth(2) << right << e->getChannel() << " "; cout << qSetFieldWidth(3) << e->getParam() << " "; cout << qSetFieldWidth(3) << e->getValue(); } break; } case SND_SEQ_EVENT_PGMCHANGE: { ProgramChangeEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(23) << left << "Program change"; cout << qSetFieldWidth(2) << right << e->getChannel() << " "; cout << qSetFieldWidth(3) << e->getValue(); } break; } case SND_SEQ_EVENT_CHANPRESS: { ChanPressEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(23) << left << "Channel aftertouch"; cout << qSetFieldWidth(2) << right << e->getChannel() << " "; cout << qSetFieldWidth(3) << e->getValue(); } break; } case SND_SEQ_EVENT_PITCHBEND: { PitchBendEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(23) << left << "Pitch bend"; cout << qSetFieldWidth(2) << right << e->getChannel() << " "; cout << qSetFieldWidth(5) << e->getValue(); } break; } case SND_SEQ_EVENT_SONGPOS: { ValueEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "Song position pointer" << qSetFieldWidth(0); cout << e->getValue(); } break; } case SND_SEQ_EVENT_SONGSEL: { ValueEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "Song select" << qSetFieldWidth(0); cout << e->getValue(); } break; } case SND_SEQ_EVENT_QFRAME: { ValueEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "MTC quarter frame" << qSetFieldWidth(0); cout << e->getValue(); } break; } case SND_SEQ_EVENT_TIMESIGN: { ValueEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "SMF time signature" << qSetFieldWidth(0); cout << hex << e->getValue(); cout << dec; } break; } case SND_SEQ_EVENT_KEYSIGN: { ValueEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "SMF key signature" << qSetFieldWidth(0); cout << hex << e->getValue(); cout << dec; } break; } case SND_SEQ_EVENT_SETPOS_TICK: { QueueControlEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "Set tick queue pos." << qSetFieldWidth(0); cout << e->getQueue(); } break; } case SND_SEQ_EVENT_SETPOS_TIME: { QueueControlEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "Set rt queue pos." << qSetFieldWidth(0); cout << e->getQueue(); } break; } case SND_SEQ_EVENT_TEMPO: { TempoEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "Set queue tempo"; cout << qSetFieldWidth(3) << right << e->getQueue() << qSetFieldWidth(0) << " "; cout << e->getValue(); } break; } case SND_SEQ_EVENT_QUEUE_SKEW: { QueueControlEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "Queue timer skew" << qSetFieldWidth(0); cout << e->getQueue(); } break; } case SND_SEQ_EVENT_START: cout << left << "Start"; break; case SND_SEQ_EVENT_STOP: cout << left << "Stop"; break; case SND_SEQ_EVENT_CONTINUE: cout << left << "Continue"; break; case SND_SEQ_EVENT_CLOCK: cout << left << "Clock"; break; case SND_SEQ_EVENT_TICK: cout << left << "Tick"; break; case SND_SEQ_EVENT_TUNE_REQUEST: cout << left << "Tune request"; break; case SND_SEQ_EVENT_RESET: cout << left << "Reset"; break; case SND_SEQ_EVENT_SENSING: cout << left << "Active Sensing"; break; case SND_SEQ_EVENT_CLIENT_START: { ClientEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "Client start" << qSetFieldWidth(0) << e->getClient(); } break; } case SND_SEQ_EVENT_CLIENT_EXIT: { ClientEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "Client exit" << qSetFieldWidth(0) << e->getClient(); } break; } case SND_SEQ_EVENT_CLIENT_CHANGE: { ClientEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "Client changed" << qSetFieldWidth(0) << e->getClient(); } break; } case SND_SEQ_EVENT_PORT_START: { PortEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "Port start" << qSetFieldWidth(0); cout << e->getClient() << ":" << e->getPort(); } break; } case SND_SEQ_EVENT_PORT_EXIT: { PortEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "Port exit" << qSetFieldWidth(0); cout << e->getClient() << ":" << e->getPort(); } break; } case SND_SEQ_EVENT_PORT_CHANGE: { PortEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "Port changed" << qSetFieldWidth(0); cout << e->getClient() << ":" << e->getPort(); } break; } case SND_SEQ_EVENT_PORT_SUBSCRIBED: { SubscriptionEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "Port subscribed" << qSetFieldWidth(0); cout << e->getSenderClient() << ":" << e->getSenderPort() << " -> "; cout << e->getDestClient() << ":" << e->getDestPort(); } break; } case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: { SubscriptionEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "Port unsubscribed" << qSetFieldWidth(0); cout << e->getSenderClient() << ":" << e->getSenderPort() << " -> "; cout << e->getDestClient() << ":" << e->getDestPort(); } break; } case SND_SEQ_EVENT_SYSEX: { SysExEvent* e = static_cast(sev); if (e != NULL) { cout << qSetFieldWidth(26) << left << "System exclusive" << qSetFieldWidth(0); unsigned int i; for (i = 0; i < e->getLength(); ++i) { cout << hex << (unsigned char) e->getData()[i] << " "; } cout << dec; } break; } default: cout << qSetFieldWidth(26) << "Unknown event type" << qSetFieldWidth(0); cout << sev->getSequencerType(); }; cout << qSetFieldWidth(0) << endl; } QDumpMIDI* test; void signalHandler(int sig) { if (sig == SIGINT) qDebug() << "Caught a SIGINT. Exiting"; else if (sig == SIGTERM) qDebug() << "Caught a SIGTERM. Exiting"; test->stop(); } int main(int argc, char **argv) { const QString errorstr = "Fatal error from the ALSA sequencer. " "This usually happens when the kernel doesn't have ALSA support, " "or the device node (/dev/snd/seq) doesn't exists, " "or the kernel module (snd_seq) is not loaded. " "Please check your ALSA/MIDI configuration."; QCoreApplication app(argc, argv); QCoreApplication::setApplicationName(PGM_NAME); QCoreApplication::setApplicationVersion(PGM_VERSION); QCommandLineParser parser; parser.setApplicationDescription(PGM_DESCRIPTION); auto helpOption = parser.addHelpOption(); auto versionOption = parser.addVersionOption(); QCommandLineOption portOption({"p", "port"}, "Source MIDI Port.", "client:port"); parser.addOption(portOption); parser.process(app); if (parser.isSet(versionOption) || parser.isSet(helpOption)) { return 0; } try { test = new QDumpMIDI(); signal(SIGINT, signalHandler); signal(SIGTERM, signalHandler); if (parser.isSet(portOption)) { QString portName = parser.value(portOption); test->subscribe(portName); } else { cerr << "Port argument is mandatory" << endl; parser.showHelp(); } test->run(); } catch (const SequencerError& ex) { cerr << errorstr + " Returned error was: " + ex.qstrError() << endl; } catch (...) { cerr << errorstr << endl; } delete test; return 0; } drumstick-1.1.3/utils/dumpmid/PaxHeaders.32572/dumpmid.pro0000644000000000000000000000013213532747316020253 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpmid/dumpmid.pro0000644000175000001440000000065313532747316021050 0ustar00pedrousers00000000000000TEMPLATE = app TARGET = drumstick-dumpmid #QT += dbus CONFIG += qt console thread exceptions link_pkgconfig static { CONFIG += link_prl } DESTDIR = ../../build/bin INCLUDEPATH += . ../../library/include ../common DEPENDPATH += . ../../library ../../library/include include (../../global.pri) # Input HEADERS += dumpmid.h SOURCES += dumpmid.cpp LIBS = -L$$OUT_PWD/../../build/lib \ -ldrumstick-alsa PKGCONFIG += alsa drumstick-1.1.3/utils/dumpmid/PaxHeaders.32572/dumpmid.h0000644000000000000000000000013213532747316017702 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpmid/dumpmid.h0000644000175000001440000000363713532747316020504 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef DUMPMIDI_H_ #define DUMPMIDI_H_ /* MidiClient can deliver SequencerEvents with only * signals or posting QEvents to the QApplication loop */ #undef USE_QEVENTS //#define USE_QEVENTS /* To get timestamped events from ALSA, you need a running queue */ //#undef WANT_TIMESTAMPS #define WANT_TIMESTAMPS #include #include #include #include #include #include #include using namespace drumstick; class QDumpMIDI : public QObject { Q_OBJECT public: QDumpMIDI(); virtual ~QDumpMIDI(); void dumpEvent(SequencerEvent* ev); void subscribe(const QString& portName); void stop(); bool stopped(); void run(); public slots: void subscription(MidiPort* port, Subscription* subs); #ifdef USE_QEVENTS protected: virtual void customEvent( QEvent *ev ); #else void sequencerEvent( SequencerEvent* ev ); #endif private: MidiClient* m_Client; MidiPort* m_Port; #ifdef WANT_TIMESTAMPS MidiQueue* m_Queue; #endif bool m_Stopped; QReadWriteLock m_mutex; }; #endif /*DUMPMIDI_H_*/ drumstick-1.1.3/utils/PaxHeaders.32572/stableheaders.h0000644000000000000000000000013213532747316017412 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/stableheaders.h0000644000175000001440000000175613532747316020214 0ustar00pedrousers00000000000000/* MIDI Sequencer C++ Library Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef STABLEHEADERS_H_ #define STABLEHEADERS_H_ extern "C" { #include } #include #include #include #include #include #include #endif /*STABLEHEADERS_H_*/ drumstick-1.1.3/utils/PaxHeaders.32572/dumpwrk0000644000000000000000000000013213532747316016047 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpwrk/0000755000175000001440000000000013532747316016715 5ustar00pedrousers00000000000000drumstick-1.1.3/utils/dumpwrk/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316020664 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpwrk/CMakeLists.txt0000644000175000001440000000233213532747316021455 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . SET(dumpwrk_SRCS dumpwrk.cpp dumpwrk.h ) SET(dumpwrk_qtobject_SRCS dumpwrk.h ) QT5_WRAP_CPP(dumpwrk_moc_SRCS ${dumpwrk_qtobject_SRCS}) ADD_EXECUTABLE(drumstick-dumpwrk ${dumpwrk_moc_SRCS} ${dumpwrk_SRCS} ) target_include_directories(drumstick-dumpwrk PRIVATE ../common ) TARGET_LINK_LIBRARIES(drumstick-dumpwrk drumstick-file Qt5::Core ) # we should install some files... INSTALL(TARGETS drumstick-dumpwrk RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) drumstick-1.1.3/utils/dumpwrk/PaxHeaders.32572/dumpwrk.pro0000644000000000000000000000013213532747316020337 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpwrk/dumpwrk.pro0000644000175000001440000000073313532747316021133 0ustar00pedrousers00000000000000TEMPLATE = app TARGET = drumstick-dumpwrk CONFIG += qt console static { CONFIG += link_prl } DESTDIR = ../../build/bin INCLUDEPATH += . ../../library/include ../common include (../../global.pri) # Input HEADERS += dumpwrk.h SOURCES += dumpwrk.cpp macx:!static { QMAKE_LFLAGS += -F$$OUT_PWD/../../build/lib -L$$OUT_PWD/../../build/lib LIBS += -framework drumstick-file } else { LIBS = -L$$OUT_PWD/../../build/lib \ -l$$drumstickLib(drumstick-file) } drumstick-1.1.3/utils/dumpwrk/PaxHeaders.32572/dumpwrk.h0000644000000000000000000000013213532747316017766 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.006000245 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpwrk/dumpwrk.h0000644000175000001440000000762513532747316020571 0ustar00pedrousers00000000000000/* Cakewalk WRK file dump program Copyright (C) 2006-2019, Pedro Lopez-Cabanillas Based on midifile.c by Tim Thompson, M.Czeiszperger and Greg Lee This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include using namespace drumstick; class QSpyWrk : public QObject { Q_OBJECT public: QSpyWrk(); void run(QString fileName); void dump(const long time, const int track, const QString& chan, const QString& event, const QString& data); void dumpStr(const long time, const QString& event, const QString& data); void dumpHex(const QByteArray& data); void dumpVar(const QString& name, bool value); void dumpVar(const QString& name, int value); void dumpVar(const QString& name, unsigned int value); void setVerbosity(bool enable); bool verbosityEnabled() const; int returnCode() const { return m_rc; } public slots: void unknownChunk(int type, const QByteArray& data); void fileHeader(int verh, int verl); void trackHeader(const QString& name1, const QString& name2, int trackno, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop); void timeBase(int timebase); void globalVars(); void noteEvent(int track, long time, int chan, int pitch, int vol, int dur); void keyPressEvent(int track, long time, int chan, int pitch, int press); void ctlChangeEvent(int track, long time, int chan, int ctl, int value); void pitchBendEvent(int track, long time, int chan, int value); void programEvent(int track, long time, int chan, int patch); void chanPressEvent(int track, long time, int chan, int press); void sysexEvent(int track, long time, int bank); void sysexEventBank(int bank, const QString& name, bool autosend, int port, const QByteArray& data); void forcedChannel(int channel); void forcedPort(int port); void textEvent(int track, long time, int typ, const QString& data); void timeSigEvent(int bar, int num, int den); void keySigEvent(int bar, int alt); void tempoEvent(long time, int tempo); void errorHandler(const QString& errorStr); void thruMode(int mode, int port, int channel, int keyPlus, int velPlus, int localPort); void trackOffset(int track, int ofs); void trackReps(int track, int reps); void trackPatch(int track, int patch); void timeFormat(int frsec, int ofs); void comments(const QString& cmt); void variableRecord(const QString& name, const QByteArray& data); void newTrackHeader(const QString& name, int trackno, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop); void softVersion(const QString& version); void trackName(int trackno, const QString& name); void stringTable(const QStringList& table); void trackVol(int track, int vol); void trackBank(int track, int bank); void segment(int track, long time, const QString& name); void chord(int track, long time, const QString& name, const QByteArray& data); void expression(int track, long time, int code, const QString& text); void hairpin(int track, long time, int code, int dur); private: bool m_verbosity; QWrk *m_engine; int m_rc; }; drumstick-1.1.3/utils/dumpwrk/PaxHeaders.32572/dumpwrk.cpp0000644000000000000000000000013213532747316020321 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.010000251 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/dumpwrk/dumpwrk.cpp0000644000175000001440000004321113532747316021113 0ustar00pedrousers00000000000000/* Cakewalk WRK file dump program Copyright (C) 2006-2019, Pedro Lopez-Cabanillas Based on midifile.c by Tim Thompson, M.Czeiszperger and Greg Lee This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include "dumpwrk.h" #include "cmdversion.h" const QString NO_CHANNEL("--"); const QString PGM_NAME("drumstick-dumpwrk"); const QString PGM_DESCRIPTION("Drumstick command line utility for decoding WRK (Cakewalk) files"); static QTextStream cout(stdout, QIODevice::WriteOnly); static QTextStream cerr(stderr, QIODevice::WriteOnly); QSpyWrk::QSpyWrk(): m_verbosity(false), m_engine(nullptr), m_rc(0) { m_engine = new QWrk(this); m_engine->setTextCodec(QTextCodec::codecForName("Windows-1252")); connect(m_engine, SIGNAL(signalWRKError(const QString&)), SLOT(errorHandler(const QString&))); connect(m_engine, SIGNAL(signalWRKUnknownChunk(int,const QByteArray&)), SLOT(unknownChunk(int,const QByteArray&))); connect(m_engine, SIGNAL(signalWRKHeader(int,int)), SLOT(fileHeader(int,int))); connect(m_engine, SIGNAL(signalWRKGlobalVars()), SLOT(globalVars())); connect(m_engine, SIGNAL(signalWRKTrack(const QString&, const QString&, int,int,int,int,int,bool,bool,bool)), SLOT(trackHeader(const QString&, const QString&, int,int,int,int,int,bool,bool,bool))); connect(m_engine, SIGNAL(signalWRKTimeBase(int)), SLOT(timeBase(int))); connect(m_engine, SIGNAL(signalWRKNote(int,long,int,int,int,int)), SLOT(noteEvent(int,long,int,int,int,int))); connect(m_engine, SIGNAL(signalWRKKeyPress(int,long,int,int,int)), SLOT(keyPressEvent(int,long,int,int,int))); connect(m_engine, SIGNAL(signalWRKCtlChange(int,long,int,int,int)), SLOT(ctlChangeEvent(int,long,int,int,int))); connect(m_engine, SIGNAL(signalWRKPitchBend(int,long,int,int)), SLOT(pitchBendEvent(int,long,int,int))); connect(m_engine, SIGNAL(signalWRKProgram(int,long,int,int)), SLOT(programEvent(int,long,int,int))); connect(m_engine, SIGNAL(signalWRKChanPress(int,long,int,int)), SLOT(chanPressEvent(int,long,int,int))); connect(m_engine, SIGNAL(signalWRKSysexEvent(int,long,int)), SLOT(sysexEvent(int,long,int))); connect(m_engine, SIGNAL(signalWRKSysex(int,const QString&,bool,int,const QByteArray&)), SLOT(sysexEventBank(int,const QString&,bool,int,const QByteArray&))); connect(m_engine, SIGNAL(signalWRKText(int,long,int,const QString&)), SLOT(textEvent(int,long,int,const QString&))); connect(m_engine, SIGNAL(signalWRKTimeSig(int,int,int)), SLOT(timeSigEvent(int,int,int))); connect(m_engine, SIGNAL(signalWRKKeySig(int,int)), SLOT(keySigEvent(int,int))); connect(m_engine, SIGNAL(signalWRKTempo(long,int)), SLOT(tempoEvent(long,int))); connect(m_engine, SIGNAL(signalWRKThru(int,int,int,int,int,int)), SLOT(thruMode(int,int,int,int,int,int))); connect(m_engine, SIGNAL(signalWRKTrackOffset(int,int)), SLOT(trackOffset(int,int))); connect(m_engine, SIGNAL(signalWRKTrackReps(int,int)), SLOT(trackReps(int,int))); connect(m_engine, SIGNAL(signalWRKTrackPatch(int,int)), SLOT(trackPatch(int,int))); connect(m_engine, SIGNAL(signalWRKTimeFormat(int,int)), SLOT(timeFormat(int,int))); connect(m_engine, SIGNAL(signalWRKComments(const QString&)), SLOT(comments(const QString&))); connect(m_engine, SIGNAL(signalWRKVariableRecord(const QString&,const QByteArray&)), SLOT(variableRecord(const QString&,const QByteArray&))); connect(m_engine, SIGNAL(signalWRKNewTrack(const QString&,int,int,int,int,int,bool,bool,bool)), SLOT(newTrackHeader(const QString&,int,int,int,int,int,bool,bool,bool))); connect(m_engine, SIGNAL(signalWRKSoftVer(const QString&)), SLOT(softVersion(const QString&))); connect(m_engine, SIGNAL(signalWRKTrackName(int,const QString&)), SLOT(trackName(int,const QString&))); connect(m_engine, SIGNAL(signalWRKStringTable(const QStringList&)), SLOT(stringTable(const QStringList&))); connect(m_engine, SIGNAL(signalWRKTrackVol(int,int)), SLOT(trackVol(int,int))); connect(m_engine, SIGNAL(signalWRKTrackBank(int,int)), SLOT(trackBank(int,int))); connect(m_engine, SIGNAL(signalWRKSegment(int,long,const QString&)), SLOT(segment(int,long,const QString&))); connect(m_engine, SIGNAL(signalWRKChord(int,long,const QString&,const QByteArray&)), SLOT(chord(int,long,const QString&,const QByteArray&))); connect(m_engine, SIGNAL(signalWRKExpression(int,long,int,const QString&)), SLOT(expression(int,long,int,const QString&))); connect(m_engine, SIGNAL(signalWRKHairpin(int,long,int,int)), SLOT(hairpin(int,long,int,int))); cout.setRealNumberNotation(QTextStream::FixedNotation); cout.setRealNumberPrecision(4); cout.setCodec("UTF-8"); } void QSpyWrk::dump(const long time, const int track, const QString& chan, const QString& event, const QString& data) { cout << right << qSetFieldWidth(7) << time; cout << qSetFieldWidth(0) << left << ' '; cout << qSetFieldWidth(5) << right << track; cout << qSetFieldWidth(3) << chan; cout << qSetFieldWidth(0) << left << ' '; cout << qSetFieldWidth(25) << event; cout << qSetFieldWidth(0) << ' ' << data << endl; } void QSpyWrk::dumpStr(const long time, const QString& event, const QString& data) { cout << right << qSetFieldWidth(7) << time; cout << qSetFieldWidth(6) << NO_CHANNEL; cout << qSetFieldWidth(3) << NO_CHANNEL; cout << qSetFieldWidth(0) << left << ' '; cout << qSetFieldWidth(25) << event; cout << qSetFieldWidth(0) << ' ' << data << endl; } void QSpyWrk::dumpHex(const QByteArray& data) { int i = 0, j = 0; QString s; if (m_verbosity) { while ( i < data.count() ) { s.clear(); for (j = 0; j < 16 && i < data.count(); ++j) { quint8 c = static_cast(data[i++]); s += QString(" %1").arg(c & 0xff, 2, 16, QChar('0')); } cout << qSetFieldWidth(42) << ' ' << qSetFieldWidth(0) << s << endl; } } } void QSpyWrk::dumpVar(const QString& name, int value) { cout << qSetFieldWidth(43) << ' ' << qSetFieldWidth(0) << name << " = " << value << endl; } void QSpyWrk::dumpVar(const QString& name, unsigned int value) { cout << qSetFieldWidth(43) << ' ' << qSetFieldWidth(0) << name << " = " << value << endl; } void QSpyWrk::dumpVar(const QString& name, bool value) { cout << qSetFieldWidth(43) << ' ' << qSetFieldWidth(0) << name << " = " << (value ? "true" : "false" ) << endl; } void QSpyWrk::setVerbosity(bool enabled) { m_verbosity = enabled; } bool QSpyWrk::verbosityEnabled() const { return m_verbosity; } void QSpyWrk::errorHandler(const QString& errorStr) { m_rc++; cerr << "*** Warning! " << errorStr << endl; } void QSpyWrk::fileHeader(int verh, int verl) { dumpStr(0, "WRK File Version", QString("%1.%2").arg(verh).arg(verl)); } void QSpyWrk::globalVars() { dumpStr(0, "Global Vars", QString()); if (m_verbosity) { dumpVar("Now", m_engine->getNow()); dumpVar("From", m_engine->getFrom()); dumpVar("Thru", m_engine->getThru()); dumpVar("KeySig", m_engine->getKeySig()); dumpVar("Clock", m_engine->getClock()); dumpVar("AutoSave", m_engine->getAutoSave()); dumpVar("PlayDelay", m_engine->getPlayDelay()); dumpVar("ZeroCtrls", m_engine->getZeroCtrls()); dumpVar("SendSPP", m_engine->getSendSPP()); dumpVar("SendCont", m_engine->getSendCont()); dumpVar("PatchSearch", m_engine->getPatchSearch()); dumpVar("AutoStop", m_engine->getAutoStop()); dumpVar("StopTime", m_engine->getStopTime()); dumpVar("AutoRewind", m_engine->getAutoRewind()); dumpVar("RewindTime", m_engine->getRewindTime()); dumpVar("MetroPlay", m_engine->getMetroPlay()); dumpVar("MetroRecord", m_engine->getMetroRecord()); dumpVar("MetroAccent", m_engine->getMetroAccent()); dumpVar("CountIn", m_engine->getCountIn()); dumpVar("ThruOn", m_engine->getThruOn()); dumpVar("AutoRestart", m_engine->getAutoRestart()); dumpVar("CurTempoOfs", m_engine->getCurTempoOfs()); dumpVar("TempoOfs1", m_engine->getTempoOfs1()); dumpVar("TempoOfs2", m_engine->getTempoOfs2()); dumpVar("TempoOfs3", m_engine->getTempoOfs3()); dumpVar("PunchEnabled", m_engine->getPunchEnabled()); dumpVar("PunchInTime", m_engine->getPunchInTime()); dumpVar("PunchOutTime", m_engine->getPunchOutTime()); dumpVar("EndAllTime", m_engine->getEndAllTime()); } } void QSpyWrk::trackHeader( const QString& name1, const QString& name2, int trackno, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop ) { dump(0, trackno, QString::number(channel), "Track", QString("name1='%2' name2='%3'").arg(name1).arg(name2)); if (m_verbosity) { dumpVar("pitch", pitch); dumpVar("velocity",velocity); dumpVar("port", port); dumpVar("selected", selected); dumpVar("muted", muted); dumpVar("loop", loop); } } void QSpyWrk::timeBase(int timebase) { dumpStr(0, "Ticks per Quarter Note", QString::number(timebase)); } void QSpyWrk::noteEvent(int track, long time, int chan, int pitch, int vol, int dur) { dump(time, track, QString::number(chan), "Note", QString("key=%1 vel=%2 dur=%3").arg(pitch).arg(vol).arg(dur)); } void QSpyWrk::keyPressEvent(int track, long time, int chan, int pitch, int press) { dump(time, track, QString::number(chan), "Key Pressure", QString("key=%1 press=%2").arg(pitch).arg(press)); } void QSpyWrk::ctlChangeEvent(int track, long time, int chan, int ctl, int value) { dump(time, track, QString::number(chan), "Control Change", QString("ctl=%1 val=%2").arg(ctl).arg(value)); } void QSpyWrk::pitchBendEvent(int track, long time, int chan, int value) { dump(time, track, QString::number(chan), "Pitch Bend", QString::number(value)); } void QSpyWrk::programEvent(int track, long time, int chan, int patch) { dump(time, track, QString::number(chan), "Program Change", QString::number(patch)); } void QSpyWrk::chanPressEvent(int track, long time, int chan, int press) { dump(time, track, QString::number(chan), "Channel Pressure", QString::number(press)); } void QSpyWrk::sysexEvent(int track, long time, int bank) { dump(time, track, NO_CHANNEL, "System Exclusive", QString::number(bank)); } void QSpyWrk::sysexEventBank(int bank, const QString& name, bool autosend, int port, const QByteArray& data) { dumpStr(0, "System Exclusive Bank", QString("bank=%1 name='%2' auto=%3 port=%4").arg(bank).arg(name).arg(autosend).arg(port)); dumpHex(data); } void QSpyWrk::forcedChannel(int channel) { dump(0, 0, NO_CHANNEL, "Forced channel", QString::number(channel)); } void QSpyWrk::forcedPort(int port) { dump(0, 0, NO_CHANNEL, "Forced port", QString::number(port)); } void QSpyWrk::textEvent(int track, long time, int typ, const QString& data) { dump(time, track, NO_CHANNEL, QString("Text (%1)").arg(typ), data); } void QSpyWrk::timeSigEvent(int bar, int num, int den) { dumpStr(0, "Time Signature", QString("bar=%1, %2/%3").arg(bar).arg(num).arg(den)); } void QSpyWrk::keySigEvent(int bar, int alt) { dumpStr(0, "Key Signature", QString("bar=%1, alt=%2").arg(bar).arg(alt)); } void QSpyWrk::tempoEvent(long time, int tempo) { double bpm = tempo / 100.0; dumpStr(time, "Tempo", QString::number(bpm, 'f', 2)); } void QSpyWrk::thruMode(int mode, int port, int channel, int keyPlus, int velPlus, int localPort) { dumpStr(0, "Thru Mode", QString("mode=%1 port=%2 chan=%3 key+=%4 vel+=%5 port=%6").arg(mode).arg(port).arg(channel).arg(keyPlus).arg(velPlus).arg(localPort)); } void QSpyWrk::trackOffset(int track, int ofs) { dump(0, track, NO_CHANNEL, "Track Offset", QString::number(ofs)); } void QSpyWrk::trackReps(int track, int reps) { dump(0, track, NO_CHANNEL, "Track Repetitions", QString::number(reps)); } void QSpyWrk::trackPatch(int track, int patch) { dump(0, track, NO_CHANNEL, "Track Patch", QString::number(patch)); } void QSpyWrk::timeFormat(int frsec, int ofs) { dumpStr(0, "SMPTE Time Format", QString("%1 frames/second, offset=%2").arg(frsec).arg(ofs)); } void QSpyWrk::comments(const QString& cmt) { dumpStr(0, "Comment", cmt.trimmed()); } void QSpyWrk::variableRecord(const QString& name, const QByteArray& data) { QString s = name; bool isReadable = ( name == "Title" || name == "Author" || name == "Copyright" || name == "Subtitle" || name == "Instructions" || name == "Keywords" ); if (isReadable) { s += ": "; if (m_engine->getTextCodec() == nullptr) s += QString(data); else s += m_engine->getTextCodec()->toUnicode(data); } dumpStr(0, "Variable Record", s.trimmed()); if (!isReadable) dumpHex(data); } void QSpyWrk::newTrackHeader( const QString& name, int trackno, int channel, int pitch, int velocity, int port, bool selected, bool muted, bool loop ) { dump(0, trackno, QString::number(channel), "Track", name); if (m_verbosity) { dumpVar("pitch", pitch); dumpVar("velocity",velocity); dumpVar("port", port); dumpVar("selected", selected); dumpVar("muted", muted); dumpVar("loop", loop); } } void QSpyWrk::softVersion(const QString& version) { dumpStr(0, "Software Version", version); } void QSpyWrk::trackName(int trackno, const QString& name) { dump(0, trackno, NO_CHANNEL, "Track Name", name); } void QSpyWrk::stringTable(const QStringList& table) { dumpStr(0, "String Table", table.join(", ")); } void QSpyWrk::trackVol(int track, int vol) { dump(0, track, NO_CHANNEL, "Track Volume", QString::number(vol)); } void QSpyWrk::trackBank(int track, int bank) { dump(0, track, NO_CHANNEL, "Track Bank", QString::number(bank)); } void QSpyWrk::segment(int track, long time, const QString& name) { dump(time, track, NO_CHANNEL, "Track Segment", name); } void QSpyWrk::chord(int track, long time, const QString& name, const QByteArray& data) { dump(time, track, NO_CHANNEL, "Chord Diagram", name); dumpHex(data); } void QSpyWrk::expression(int track, long time, int code, const QString& text) { dump(time, track, NO_CHANNEL, "Expression", QString("text=%1 code=%2").arg(text).arg(code)); } void QSpyWrk::hairpin(int track, long time, int code, int dur) { dump(time, track, NO_CHANNEL, "Hairpin", QString("code=%1, dur=%2").arg(code).arg(dur)); } void QSpyWrk::unknownChunk(int type, const QByteArray& data) { QString name = QString("Unknown Chunk %1 (0x%2)").arg(type).arg(type, 2, 16, QChar('0')); dumpStr(0, name, QString("size=%2").arg(data.length())); dumpHex(data); } void QSpyWrk::run(QString fileName) { cout << "__ticks track ch event____________________ data____" << endl; m_engine->readFromFile(fileName); } int main(int argc, char *argv[]) { QSpyWrk spy; QCoreApplication app(argc, argv); QCoreApplication::setApplicationName(PGM_NAME); QCoreApplication::setApplicationVersion(PGM_VERSION); QCommandLineParser parser; parser.setApplicationDescription(PGM_DESCRIPTION); auto helpOption = parser.addHelpOption(); auto versionOption = parser.addVersionOption(); QCommandLineOption verboseOption("verbose", "Verbose output."); parser.addOption(verboseOption); parser.addPositionalArgument("file", "Input WRK File Name(s).", "files..."); parser.process(app); if (parser.isSet(versionOption) || parser.isSet(helpOption)) { return 0; } if (parser.isSet(verboseOption)) { spy.setVerbosity(true); } QStringList fileNames, positionalArgs = parser.positionalArguments(); foreach(const QVariant& a, positionalArgs) { QFileInfo f(a.toString()); if (f.exists()) fileNames += f.canonicalFilePath(); else cerr << "File not found: " << a.toString() << endl; } foreach(const QString& file, fileNames) { spy.run(file); } return spy.returnCode(); } drumstick-1.1.3/utils/PaxHeaders.32572/playsmf0000644000000000000000000000013213532747316016031 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.074000333 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/playsmf/0000755000175000001440000000000013532747316016677 5ustar00pedrousers00000000000000drumstick-1.1.3/utils/playsmf/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316020646 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.074000333 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/playsmf/CMakeLists.txt0000644000175000001440000000237513532747316021446 0ustar00pedrousers00000000000000# MIDI Sequencer C++ Library # Copyright (C) 2005-2019 Pedro Lopez-Cabanillas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . SET(playsmf_SRCS playsmf.cpp playsmf.h ) SET(playsmf_qtobject_SRCS playsmf.h ) QT5_WRAP_CPP(playsmf_moc_SRCS ${playsmf_qtobject_SRCS}) ADD_EXECUTABLE(drumstick-playsmf ${playsmf_moc_SRCS} ${playsmf_SRCS} ) target_include_directories(drumstick-playsmf PRIVATE ../common ) TARGET_LINK_LIBRARIES(drumstick-playsmf ${ALSA_LIBS} drumstick-alsa drumstick-file Qt5::Core ) # we should install some files... INSTALL(TARGETS drumstick-playsmf RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) drumstick-1.1.3/utils/playsmf/PaxHeaders.32572/playsmf.pro0000644000000000000000000000013213532747316020303 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.074000333 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/playsmf/playsmf.pro0000644000175000001440000000053613532747316021100 0ustar00pedrousers00000000000000TEMPLATE = app TARGET = drumstick-playsmf #QT += dbus CONFIG += qt console thread exceptions static { CONFIG += link_prl } DESTDIR = ../../build/bin INCLUDEPATH += . ../../library/include ../common LIBS = -L../../build/lib -ldrumstick-alsa -ldrumstick-file -lasound include (../../global.pri) # Input HEADERS += playsmf.h SOURCES += playsmf.cpp drumstick-1.1.3/utils/playsmf/PaxHeaders.32572/playsmf.cpp0000644000000000000000000000013213532747316020265 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.074000333 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/playsmf/playsmf.cpp0000644000175000001440000002567113532747316021071 0ustar00pedrousers00000000000000/* Standard MIDI File player program Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include "playsmf.h" #include "cmdversion.h" const QString PGM_NAME("drumstick-playsmf"); const QString PGM_DESCRIPTION("Drumstick command line MIDI file player"); static QTextStream cout(stdout, QIODevice::WriteOnly); static QTextStream cerr(stderr, QIODevice::WriteOnly); /* ********** * * Song class * ********** */ static inline bool eventLessThan(const SequencerEvent* s1, const SequencerEvent *s2) { return s1->getTick() < s2->getTick(); } void Song::sort() { qStableSort(begin(), end(), eventLessThan); } void Song::clear() { while (!isEmpty()) delete takeFirst(); } Song::~Song() { clear(); } /* ************* * * PlaySMF class * ************* */ PlaySMF::PlaySMF() : m_division(-1), m_portId(-1), m_queueId(-1), m_initialTempo(-1), m_Stopped(true) { m_Client = new MidiClient(this); m_Client->open(); m_Client->setClientName("MIDI Player"); m_Port = new MidiPort(this); m_Port->attach( m_Client ); m_Port->setPortName("MIDI Player port"); m_Port->setCapability(SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ); m_Port->setPortType(SND_SEQ_PORT_TYPE_APPLICATION); m_Queue = m_Client->createQueue(); m_queueId = m_Queue->getId(); m_portId = m_Port->getPortId(); m_engine = new QSmf(this); connect(m_engine, SIGNAL(signalSMFHeader(int,int,int)), SLOT(headerEvent(int,int,int))); connect(m_engine, SIGNAL(signalSMFNoteOn(int,int,int)), SLOT(noteOnEvent(int,int,int))); connect(m_engine, SIGNAL(signalSMFNoteOff(int,int,int)), SLOT(noteOffEvent(int,int,int))); connect(m_engine, SIGNAL(signalSMFKeyPress(int,int,int)), SLOT(keyPressEvent(int,int,int))); connect(m_engine, SIGNAL(signalSMFCtlChange(int,int,int)), SLOT(ctlChangeEvent(int,int,int))); connect(m_engine, SIGNAL(signalSMFPitchBend(int,int)), SLOT(pitchBendEvent(int,int))); connect(m_engine, SIGNAL(signalSMFProgram(int,int)), SLOT(programEvent(int,int))); connect(m_engine, SIGNAL(signalSMFChanPress(int,int)), SLOT(chanPressEvent(int,int))); connect(m_engine, SIGNAL(signalSMFSysex(const QByteArray&)), SLOT(sysexEvent(const QByteArray&))); connect(m_engine, SIGNAL(signalSMFText(int,const QString&)), SLOT(textEvent(int,const QString&))); connect(m_engine, SIGNAL(signalSMFTempo(int)), SLOT(tempoEvent(int))); connect(m_engine, SIGNAL(signalSMFTimeSig(int,int,int,int)), SLOT(timeSigEvent(int,int,int,int))); connect(m_engine, SIGNAL(signalSMFKeySig(int,int)), SLOT(keySigEvent(int,int))); connect(m_engine, SIGNAL(signalSMFError(const QString&)), SLOT(errorHandler(const QString&))); } PlaySMF::~PlaySMF() { m_Port->detach(); m_Client->close(); } void PlaySMF::subscribe(const QString& portName) { try { qDebug() << "Trying to subscribe to " << portName.toLocal8Bit().data(); m_Port->subscribeTo(portName); } catch (const SequencerError& err) { cerr << "SequencerError exception. Error code: " << err.code() << " (" << err.qstrError() << ")" << endl; cerr << "Location: " << err.location() << endl; throw err; } } bool PlaySMF::stopped() { QReadLocker locker(&m_mutex); return m_Stopped; } void PlaySMF::stop() { QWriteLocker locker(&m_mutex); m_Stopped = true; m_Client->dropOutput(); } void PlaySMF::shutupSound() { int channel; for (channel = 0; channel < 16; ++channel) { ControllerEvent ev(channel, MIDI_CTL_ALL_SOUNDS_OFF, 0); ev.setSource(static_cast(m_portId)); ev.setSubscribers(); ev.setDirect(); m_Client->outputDirect(&ev); } m_Client->drainOutput(); } void PlaySMF::appendEvent(SequencerEvent* ev) { long tick = m_engine->getCurrentTime(); ev->setSource(static_cast(m_portId)); if (ev->getSequencerType() != SND_SEQ_EVENT_TEMPO) { ev->setSubscribers(); } ev->scheduleTick(m_queueId, static_cast(tick), false); m_song.append(ev); } void PlaySMF::dump(const QString& chan, const QString& event, const QString& data) { cout << right << qSetFieldWidth(7) << m_engine->getCurrentTime(); cout << qSetFieldWidth(3) << chan; cout << qSetFieldWidth(0) << left << " "; cout << qSetFieldWidth(15) << event; cout << qSetFieldWidth(0) << " " << data << endl; } void PlaySMF::dumpStr(const QString& event, const QString& data) { cout << right << qSetFieldWidth(7) << m_engine->getCurrentTime(); cout << qSetFieldWidth(3) << "--"; cout << qSetFieldWidth(0) << left << " "; cout << qSetFieldWidth(15) << event; cout << qSetFieldWidth(0) << " " << data << endl; } void PlaySMF::headerEvent(int format, int ntrks, int division) { m_division = division; dumpStr("SMF Header", QString("Format=%1, Tracks=%2, Division=%3"). arg(format).arg(ntrks).arg(division)); } void PlaySMF::noteOnEvent(int chan, int pitch, int vol) { NoteOnEvent* ev = new NoteOnEvent (chan, pitch, vol); appendEvent(ev); } void PlaySMF::noteOffEvent(int chan, int pitch, int vol) { SequencerEvent* ev = new NoteOffEvent(chan, pitch, vol); appendEvent(ev); } void PlaySMF::keyPressEvent(int chan, int pitch, int press) { SequencerEvent* ev = new KeyPressEvent (chan, pitch, press); appendEvent(ev); } void PlaySMF::ctlChangeEvent(int chan, int ctl, int value) { SequencerEvent* ev = new ControllerEvent (chan, ctl, value); appendEvent(ev); } void PlaySMF::pitchBendEvent(int chan, int value) { SequencerEvent* ev = new PitchBendEvent (chan, value); appendEvent(ev); } void PlaySMF::programEvent(int chan, int patch) { SequencerEvent* ev = new ProgramChangeEvent (chan, patch); appendEvent(ev); } void PlaySMF::chanPressEvent(int chan, int press) { SequencerEvent* ev = new ChanPressEvent (chan, press); appendEvent(ev); } void PlaySMF::sysexEvent(const QByteArray& data) { SysExEvent* ev = new SysExEvent(data); appendEvent(ev); } void PlaySMF::textEvent(int typ, const QString& data) { dumpStr(QString("Text (%1)").arg(typ), data); } void PlaySMF::timeSigEvent(int b0, int b1, int b2, int b3) { dump("--", "Time Signature", QString("%1, %2, %3, %4").arg(b0).arg(b1).arg(b2).arg(b3)); } void PlaySMF::keySigEvent(int b0, int b1) { dump("--", "Key Signature", QString("%1, %2").arg(b0).arg(b1)); } void PlaySMF::tempoEvent(int tempo) { if ( m_initialTempo < 0 ) { m_initialTempo = tempo; } TempoEvent* ev = new TempoEvent(m_queueId, tempo); appendEvent(ev); } void PlaySMF::errorHandler(const QString& errorStr) { cout << "*** Warning! " << errorStr << " at file offset " << m_engine->getFilePos() << endl; } void PlaySMF::play(QString fileName) { cout << "Reading song: " << fileName << endl; cout << "___time ch event__________ data____" << endl; m_engine->readFromFile(fileName); m_song.sort(); m_Client->setPoolOutput(100); QueueTempo firstTempo = m_Queue->getTempo(); firstTempo.setPPQ(m_division); if (m_initialTempo > 0) firstTempo.setTempo(static_cast(m_initialTempo)); m_Queue->setTempo(firstTempo); m_Client->drainOutput(); cout << "Starting playback" << endl; cout << "Press Ctrl+C to exit" << endl; try { QListIterator i(m_song); m_Stopped = false; m_Queue->start(); while (!stopped() && i.hasNext()) { //m_Client->outputDirect(i.next()); m_Client->output(i.next()); } if (stopped()) { m_Queue->clear(); shutupSound(); } else { m_Client->drainOutput(); m_Client->synchronizeOutput(); } m_Queue->stop(); } catch (const SequencerError& err) { cerr << "SequencerError exception. Error code: " << err.code() << " (" << err.qstrError() << ")" << endl; cerr << "Location: " << err.location() << endl; throw err; } } static PlaySMF* player = nullptr; void signalHandler(int sig) { if (sig == SIGINT) qDebug() << "Caught a SIGINT. Exiting"; else if (sig == SIGTERM) qDebug() << "Caught a SIGTERM. Exiting"; if (player != nullptr) player->stop(); } int main(int argc, char **argv) { const QString errorstr = "Fatal error from the ALSA sequencer. " "This usually happens when the kernel doesn't have ALSA support, " "or the device node (/dev/snd/seq) doesn't exists, " "or the kernel module (snd_seq) is not loaded. " "Please check your ALSA/MIDI configuration."; signal(SIGINT, signalHandler); signal(SIGTERM, signalHandler); QCoreApplication app(argc, argv); QCoreApplication::setApplicationName(PGM_NAME); QCoreApplication::setApplicationVersion(PGM_VERSION); QCommandLineParser parser; parser.setApplicationDescription(PGM_DESCRIPTION); auto helpOption = parser.addHelpOption(); auto versionOption = parser.addVersionOption(); QCommandLineOption portOption({"p","port"}, "Destination, MIDI port.", "client:port"); parser.addOption(portOption); parser.addPositionalArgument("file", "Input SMF File(s).", "files..."); parser.process(app); if (parser.isSet(versionOption) || parser.isSet(helpOption)) { return 0; } try { player = new PlaySMF(); if (parser.isSet(portOption)) { QString port = parser.value(portOption); player->subscribe(port); } else { cerr << "Port argument is missing" << endl; parser.showHelp(); } QStringList files = parser.positionalArguments(); if (files.isEmpty()) { cerr << "No input files" << endl; parser.showHelp(); } foreach(const QString& f, files) { QFileInfo file(f); if (file.exists()) player->play(file.canonicalFilePath()); } } catch (const SequencerError& ex) { cerr << errorstr + " Returned error was: " + ex.qstrError() << endl; } catch (...) { cerr << errorstr << endl; } delete player; return 0; } drumstick-1.1.3/utils/playsmf/PaxHeaders.32572/playsmf.h0000644000000000000000000000013213532747316017732 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.074000333 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/playsmf/playsmf.h0000644000175000001440000000502313532747316020523 0ustar00pedrousers00000000000000/* Standard MIDI File player program Copyright (C) 2006-2019, Pedro Lopez-Cabanillas This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef PLAYSMF_H_ #define PLAYSMF_H_ #include #include #include #include #include #include #include #include #include using namespace drumstick; class Song : public QList { public: virtual ~Song(); void sort(); void clear(); }; class PlaySMF : public QObject { Q_OBJECT public: PlaySMF(); virtual ~PlaySMF(); void play(QString fileName); bool stopped(); void stop(); void appendEvent(SequencerEvent* ev); void subscribe(const QString& portName); void dump(const QString& chan, const QString& event, const QString& data); void dumpStr(const QString& event, const QString& data); void shutupSound(); public slots: void headerEvent(int format, int ntrks, int division); void noteOnEvent(int chan, int pitch, int vol); void noteOffEvent(int chan, int pitch, int vol); void keyPressEvent(int chan, int pitch, int press); void ctlChangeEvent(int chan, int ctl, int value); void pitchBendEvent(int chan, int value); void programEvent(int chan, int patch); void chanPressEvent(int chan, int press); void sysexEvent(const QByteArray& data); void textEvent(int typ, const QString& data); void tempoEvent(int tempo); void timeSigEvent(int b0, int b1, int b2, int b3); void keySigEvent(int b0, int b1); void errorHandler(const QString& errorStr); private: int m_division; int m_portId; int m_queueId; int m_initialTempo; bool m_Stopped; QReadWriteLock m_mutex; Song m_song; QSmf* m_engine; MidiClient* m_Client; MidiPort* m_Port; MidiQueue* m_Queue; }; #endif /*PLAYSMF_H_*/ drumstick-1.1.3/utils/PaxHeaders.32572/common0000644000000000000000000000013213532747316015646 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.074000333 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/common/0000755000175000001440000000000013532747316016514 5ustar00pedrousers00000000000000drumstick-1.1.3/utils/common/PaxHeaders.32572/cmdversion.h0000644000000000000000000000013213532747316020245 xustar0030 mtime=1567346382.717999876 30 atime=1567346383.074000333 30 ctime=1567346382.717999876 drumstick-1.1.3/utils/common/cmdversion.h0000644000175000001440000000030613532747316021035 0ustar00pedrousers00000000000000#ifndef CMDVERSION_H #define CMDVERSION_H #include #define LITERAL(s) #s #define STRINGIFY(s) LITERAL(s) const QString PGM_VERSION(STRINGIFY(VERSION)); #endif // CMDVERSION_H drumstick-1.1.3/PaxHeaders.32572/global.pri0000644000000000000000000000013213532747316015247 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.074000333 30 ctime=1567346382.729999891 drumstick-1.1.3/global.pri0000644000175000001440000000032613532747316016041 0ustar00pedrousers00000000000000VERSION = 1.1.3 DEFINES += VERSION=$$VERSION VER_MAJ = 1 VER_MIN = 1 VER_PAT = 3 defineReplace(drumstickLib) { LIBRARY_NAME = $$1 win32: LIBRARY_NAME = $$LIBRARY_NAME$$VER_MAJ return($$LIBRARY_NAME) } drumstick-1.1.3/PaxHeaders.32572/NEWS0000644000000000000000000000013213532747316013772 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.074000333 30 ctime=1567346382.729999891 drumstick-1.1.3/NEWS0000644000175000001440000000026313532747316014564 0ustar00pedrousers00000000000000Barcelona. Thursday, January 7, 2010 Project "aseqmm" has been renamed to "drumstick" RSS newsfeed available at: http://sourceforge.net/export/rss2_keepsake.php?group_id=296480 drumstick-1.1.3/PaxHeaders.32572/ChangeLog0000644000000000000000000000013213532747316015045 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.074000333 30 ctime=1567346382.729999891 drumstick-1.1.3/ChangeLog0000644000175000001440000001642313532747316015644 0ustar00pedrousers000000000000002019-09-01 * release 1.1.3 2019-08-29 * release preparations 2019-07-07 * Avoid endless loops on unexpected end of input. 2019-07-06 * Fix for ticket #17: CoreMIDI.framework using wrong name-case 2019-07-06 * Generate SMFError when the parser finds unexpected end of input. Fix for ticket #16 2019-07-05 * Fix for ticket #16: bad MIDI files (drumstick-file) 2019-07-02 * Fixed macOS deprecation warnings 2019-01-29 * general cleanups and bringing back the fluidsynth backend 2019-01-28 * Fix for ticket #14: migration to full GNUInstallDirs support 2019-01-27 * modernization started of the CMake build system 2019-01-26 * Library includes reorganization 2019-01-20 * Fixed drumstick-file unit test * Tweaks on qmake build system 2019-01-15 * Custom commandline parser replaced by standard Qt5 QCommandLineParser 2019-01-13 * Removed custom commanline parser class, replaced by standard Qt5 QCommandLineParser 2019-01-08 * fixed spurious error message for ALSA input 2019-01-07 * Fixed differences between unix and windows semantics 2019-01-06 * Network backend: support for IPv6 2018-11-25 * release 1.1.2 2018-11-24 * Fix for ticket #13 - some macOS input events lost * Added some bundle metadata for macOS * Solution for ticket #8: Path for plugins hardcoded 2018-02-24 * release 1.1.1 2018-01-07 * disabled fluidsynth output driver * Fixed build on macOS < 10.11, thanks to Andreas 2017-08-14 * fixed unit test for more tolerance * release preparations 2017-08-13 * fix for ticket #11: replaced assert() by Q_ASSERT() * fix for ticket #9: removed ALSA/Linux dependency where possible. 2017-05-10 * rt: fixed pitch bend events on several output backends 2017-04-16 * fixed tab order on forms 2017-04-03 * added keywords to the desktop files. Patch by Ross Gammon 2016-09-25 * release 1.1.0 2016-09-11 * reverted audio backend for sonivox eas to pulseaudio again * rt: settings for sonivox eas and mac native synth * vpiano: dialogs for synth settings 2016-08-18 * release 1.1.0 preparation * removed four utilities, now implemented as unit tests 2016-08-17 * drumstick-rt: fix backendmanager initialization, added two new methods to retrieve backends by name * documentation updated * copyright years updated 2016-07-03 * guiplayer accepts a single file argument in the command line: mid, kar, wrk, and ove * Missing cmake scripts license, patch by Maximiliano Curia 2016-05-22 * Fix for mac osx static builds 2016-05-21 * Fix for static build using the new backends 2016-05-16 * Fix for cmake/qmake builds on mac 2016-05-15 * new backend: Apple DLS Synth 2016-05-08 * version number changed provisionally to 1.0.99 * new backend: sonivox eas synthesizer for Linux 2016-02-17 * Fix build with GCC 6, patch by Robin Lee 2016-01-30 * guiplayer: there is no need for a quit() slot. Fix for hanging notes when closing the window with the corner icon. * Use GNUInstallDirs to install arch-independent data, patch by Heiko Becker 2015-12-29 * release 1.0.2 2015-10-10 * RT library: fixed ticket #6 - MIDI input connection on Mac OSX 2015-08-20 * release 1.0.1 2015-04-26 * RT library: fixed ticket #4: ALSA Midi Input not working 2014-11-22 * RT library: fixed windows midi input 2014-08-30 * release 1.0.0 2014-08-02 * vpiano using RT library 2014-07-26 * documentation updates 2014-04-27 * RT library: OSS backend 2014-04-13 * RT library: FluidSynth backend 2014-03-30 * RT library: Windows backend 2014-02-09 * RT library: Mac OSX backend 2014-02-09 * RT library: Network and ALSA backends 2013-12-31 * Qt5 compatibility 2010-09-13 * fixed dumpove: file header text 2010-09-08 * documentation updated * release 0.5.0 2010-09-08 * remaining warnings removed * guiplayer simplified, and optimizations * compile with -fvisibility=hidden if it is available * compile always with -fexceptions * fixes in both buildsystems, cmake and qmake 2010-09-02 * Use RealtimeKit support for the MIDI input thread. 2010-08-31 * OVE file format support, by Rui Fan * guiplayer adds OVE format playback 2010-07-24 * Fixed static build support 2010-07-12 * removed PCH build option * release 0.4.1 2010-07-11 * Fixed bug in class SequencerInputThread: realtime priority must be applied in run() instead of start() to avoid changing the scheduling policy of the parent. This is a problem when running FluidSynth in systems affected by a glib-2.22 bug that has not yet been fixed. Reference: https://bugzilla.gnome.org/show_bug.cgi?id=599079 2010-07-07 * smfplayer renamed as guiplayer, with a new windows layout and supporting Cakewalk WRK files playback * release 0.4.0 2010-07-03 * subdirectory "tests" renamed as "utils". * visibility attribute for public classes. 2010-06-10 * Compile fix for 0.3.2 * release 0.3.2a 2010-06-09 * Command line arguments for all the utilities/test programs. 2010-05-28 * fix a crash in drumstick-sysinfo when a timer module is not loaded. 2010-05-13 * Man pages for the utilities/test programs. 2010-05-10 * New test program: DrumGrid 2010-04-19 * Release 0.3.1 * Allow to build drumstick-file library under Windows * New method MidiClient::parseAddress() replacing the ALSA function snd_seq_parse_address() in MidiPort::subscribeTo() and similar methods. * Fixed MidiClient::getAvailableInputs() and getAvailableOutputs() forcing to always retrieve the clients list. 2010-03-09 * Release 0.3.0 * API changes: SequencerEvent::isChannel() returns true for SND_SEQ_EVENT_NOTE QueueTimer::setId(const TimerId& id) new method overload Timer::bestGlobalTimerId() new static function getRuntimeALSALibraryVersion() new global function getRuntimeALSALibraryNumber() new global function getRuntimeALSADriverVersion() new global function getRuntimeALSADriverNumber() new global function 2010-03-02 * New class QWrk, for reading Cakewalk files 2010-02-17 * Split: drumstick-file and drumstick-alsa 2010-01-07 * Renamed to 'drumstick' and moved to a new project repository 2009-12-27 * Release 0.2.0 * API changes: SequencerInputThread::start() added a priority parameter SequencerEvent::isChannel() new static method SequencerOutputThread::stopped() method removed, converted into a signal SequencerOutputThread::start() added a priority parameter SequencerOutputThread::shutupSound() method removed SequencerOutputThread::stopRequested() method added QSmfPrivate class added QSmf::writeMetaEvent() new method overload QSmf::getTextCodec() new method QSmf::setTextCodec() new method QSmf::signalSMFVariable() signal dropped QSmf::signalSMFMetaUnregistered() signal added Subscriber::operator==() removed unimplemented operator prototype 2009-08-27 * Public release 0.1.0 2008-12-29 0.0.2pre5 * Snapshot included in kmetronome-0.9.0 and kmidimon-0.6.0 2008-11-09 0.0.2pre1 * Initial pre-release 2008-05-12 0.0.1 * Development started drumstick-1.1.3/PaxHeaders.32572/INSTALL0000644000000000000000000000013213532747316014324 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.074000333 30 ctime=1567346382.729999891 drumstick-1.1.3/INSTALL0000644000175000001440000000413613532747316015121 0ustar00pedrousers00000000000000Basic build commands -------------------- $ cd drumstick-x.x.x $ mkdir -p build $ cd build $ cmake .. (or ccmake ..) (or cmake-gui ..) (or cmake .. -options, see below...) For simple test/development scenarios you can also use Qmake, but the Qmake- based build system provides only minimal functionality. $ make (or make VERBOSE=1) $ sudo make install $ sudo ldconfig (not needed if you only want STATIC_DRUMSTICK) Requirements ------------ Minimum supported versions: * CMake 2.8.11 * Qt5 * For Linux: ALSA 1.0 * shared-mime-info 0.30 See http://freedesktop.org/wiki/Software/shared-mime-info The utility "update-mime-database" must be executed after installing the library "drumstick-file" and the "drumstick.xml" file. This is automatically done by the cmake build system unless you defined DESTDIR. In this case, your package manager should perform it as a post-install step. * Doxygen 1.5 See http://www.doxygen.org If you want to generate the documentation for the libraries If you want to generate and install the man pages, the build system can do it if you have installed in your system the following packages: * xsltproc program. * docbook XSLT stylesheets. The package names depend on the Linux distribution. For Debian they are: xsltproc, docbook-xsl and docbook-xml. For openSUSE: libxslt, docbook_4, and docbook-xsl-stylesheets. RealtimeKit actions are called through DBus, so it is not a direct dependency. Optional CMake parameters ------------------------- -DSTATIC_DRUMSTICK=YES|ON|1 Build static libraries instead of a shared object -DSTATIC_DRUMSTICK=NO|OFF|0 Build dynamic libraries (default) -DCMAKE_BUILD_TYPE=Debug Compile with debug flags enabled -DCMAKE_BUILD_TYPE=Release Compile without debug flags, and optimization enabled -DCMAKE_CXX_FLAGS="-W -Wall" Specify custom compilation flags -DCMAKE_INSTALL_PREFIX=/usr/local Specify the desired install prefix -DUSE_DBUS=YES|ON|1 Build DBus support, required to use RealtimeKit (default) -DUSE_DBUS=NO|OFF|0 Don't include DBus support drumstick-1.1.3/PaxHeaders.32572/icons0000644000000000000000000000013213532747316014331 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.074000333 30 ctime=1567346382.725999886 drumstick-1.1.3/icons/0000755000175000001440000000000013532747316015177 5ustar00pedrousers00000000000000drumstick-1.1.3/icons/PaxHeaders.32572/CMakeLists.txt0000644000000000000000000000013213532747316017146 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.074000333 30 ctime=1567346382.725999886 drumstick-1.1.3/icons/CMakeLists.txt0000644000175000001440000000116513532747316017742 0ustar00pedrousers00000000000000INSTALL(FILES drumstick_16.png DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/16x16/apps" RENAME drumstick.png) INSTALL(FILES drumstick_32.png DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/32x32/apps" RENAME drumstick.png) INSTALL(FILES drumstick_48.png DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/48x48/apps" RENAME drumstick.png) INSTALL(FILES drumstick_64.png DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/64x64/apps" RENAME drumstick.png) INSTALL(FILES drumstick.svgz DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/apps") drumstick-1.1.3/icons/PaxHeaders.32572/drumstick.icns0000644000000000000000000000013013532747316017267 xustar0029 mtime=1567346382.72199988 30 atime=1567346383.074000333 29 ctime=1567346382.72199988 drumstick-1.1.3/icons/drumstick.icns0000644000175000001440000006646213532747316020100 0ustar00pedrousers00000000000000icnsm2is325t_YhߝoHE Sqxu^GD^eJ2]htkH1>),HS_jv}]\cdSR6;DJVamt~|=Fr^*'47FKDouG$M_T?92+4IF2]cwN Wn_RuwsoWJA;&De[$(/$"-82$/8 &1oT65 !ZXG5s8mk{j ܑ;󓐐[=Lk3eE9%1il32/mR /lp X0V70Up_,GzK TԌق6Eg~nI =n>  Y^X:* CRo{x^9C_ekpv|`< $OUZ`flqw}aC7"DJPV[agmsx~y^R'AND4 '#DDEKQW]bhnty~Rr|~zcKDc90DGLRX^ciouzhxjpxovvB'bI"3DHMSY_djpjƧi.@zt]<%?DINTZ`eZ4$Q|pZ>'",3@CBGA4)!BfWMIJoq`L:,"'1981(sko}L/6.!RJC@>?BGPZ``YL8+[]Pp|E1rmhfeRXkpuxxtk[F;<9<,SlkP6Z{}~q~{sgaD 9FH7Eq}qV58  +498+ $*/5:?-  %+06;?+  !&,17<6  "'-28: #(.39IG"5 $)4_y9 8)   .S~/bB FBl8mk ;na1  Aڂ Aވt 1Ks|fG U+˒)b} ͚i!I 'm{h-w%c2it32##BeiI A; ".I {/ #w%GI'$):,, .m0-1  -v.s3D21 ]0!1$O24 4'e OkQ*NחG -ۀ#$(>{-!%C] <$<А߄~!Mf b5ƚ0 )ۚ[ Vn}Y)KؔSͭ!   h ]Ʃ[ 6ȏ CqMQی} ! 'FD8 ADE*DcsrqqC-$[xz{X 2xtoiaXND:0&BD(FGHJKMNPQSTUWXZ[]^`abdeghjklnoqrtuwxy{|& j/3Kfk_vxy-\qkd[RI>5+#AD%FGIJLMOPQSTVWYZ[]^`acdfghjkmnpqrtuwx_4S |DEGHJKMNPQRTUWXZ[]^_abdeghikLGz~}|zwsnibZRJA91*#"ADFGIJLMNPQSTVWXZ[]^`acdegh7jW~~}{yurmg`YQIA91*$ $BDEFGIJLMOPQSTVWYZ\]^`acde@ ]~}|zxtpke_XPIA:2,&  !;DEFHIKLMOPRSUVXYZ\]_`R Y‘2:- l~}|zwtoke_XQIB;4.(#  %>D EGHIKLNOQRSUVXY[N+0q T`hn]2 !Z~}{yvsoje_XRKD=71+&"  -;DEGHJKMNOQRP@$  F m0_gmsxyY&(~|{yvsoke`ZSMGA:5/*&" !*18?DCA=:6-  !  _ ^fmswz|~t " e~~}{yvsokfa\VPJD>94/+'#  %  #%'()**)('%$"   ]emrwz|~<'v~~|{yvtplhc^YSNHC>950-)&#!!$'*,.124310.,*'%# \elrvz|~X&@y~|{ywtqnjea\WRMHC?;730-*'%#" & "#&(+.1469;=>?>=<:8630-*'$ ^$\elrvz|~"%/Pl{zxurokhd_[WRMIEA>:742/-+)('&%$$#"#$%&'(*+-0358;>ADFHIGEC@=:730,($"D[dlrwz|~@ #2AHGGFECBCEFGEB?=:864310//.-,--../013468;=@CFILOQSTSRPNKHEA>950+&"O$R\dlrvz|~ /PMJHECA@><<;:9887899:;<>?ACFHKMQSVY[]^]\ZXVROLHC?94/)$A%&HS]elrvz|~Z YZWURPNLKIHGFEDC@DDEFGIKLNPSUX[]`bdefgffeca_\YVRMIC>71,&!+AKU^fmrwz|~SBC*  _zyxwvvuttssrrqpT brssttuvwxyzz{{||}||{zyxwtrokgb]XSNJGEGK  >||{{zyyxxwv uuqG>vw xxyyz{{||}}~}}|{zxvtqmie`\WTQOQT f}|{zyj5tz{{|}}~~~}|{ywurokgc`]ZYXYZ\f~}{cE ;||}~~}|{zxvspmjgecbaabd8]qux{{bB  \~e;B~~}|zyvurpnljijk@   "F`lw xgUC+  -~ ~}|{zxvtsrpopo   $|~~}|{zxwvuthy ~}||{zyyx^4 I{~}|]2  3KL;'  (+($  !.0234678:;=>?@?@: #%&')*+-./1245689:<=>@/!"$%&()*,-.01245689;<=?@;" !"$%&()+,-/01345789;<>?@0   !#$%'()+,./0234678:;<>?@)#  "#$&'(*+,./0235679:;=>?@=$ "#%&')*+-./1235679:<=>@8' !"#%&')*,-.01245689:<=?@0 )  !"$%&()*,-/01345789;<=?@?%+  !#$%'()+,-/0134678:;<>?@9 -  !#$&'(*+,./0234678:;=>?@?-  "#$&'(*+-./1235679:;=>@-- !"#%&')*+-.01245689:<=>@: -  !"$%&()*,-.01245789;<=?@?.  !"$%'()+,-/01345789;<>?@02  !#$%'()+,./0234678:;<>?@@92  "#$&'(*+,./1235679:;=>?@:1 !"#%&')*+-./1235689:<=>@:0 !"#%&()*,-.01245689:<=?;1  !"$%&()*,-/01345789;<=: 2  !#$%'()+,-/0234678:;<: c' 4  "#$&'(*+,./0234679:;L ;Q=*  "#$&')*+-./123567*3q5"( !"#%&')*+-.01245\"  %  !"$%&()*,-.01(*~Em.$  !#$%'()+,-/l_!  !#$%'(*+ 1M  "#$&'($ !"#%< !"^   8s  N   (e  =w^ SR  C  8| t8mk@    !3)! 7 q1)! H{& V҈C K̀? ?q8[  DѨwR r }s #h 5\fK0icnV Bdrumstick-1.1.3/icons/PaxHeaders.32572/drumstick_48.png0000644000000000000000000000013213532747316017434 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.078000337 30 ctime=1567346382.725999886 drumstick-1.1.3/icons/drumstick_48.png0000644000175000001440000000361613532747316020233 0ustar00pedrousers00000000000000PNG  IHDR00WsBIT|d pHYsRR$JtEXtSoftwarewww.inkscape.org< IDATh[lsf/B@&'UP0 )BJiӛBHо J-U@7*I$n&ė^o=}3^46hgR_ oe2Pn([.yy>7 ! ܿܢ@]佉k>!K>\K $2+^qP?PwKsնuU*j+Hm?0:e{,>m S=o?MOYH)xC^~q[\]MWU7&!1)_)%':U]K `ûhzcd]EAth]H.['/g@ QRTPfR /"dm˖ג6LuW˃Xl .ڑ4!}'hB|zҌ0iR1N}wC*h im[bֻ)%5ױl,ȃ} ɻVZA q=N(QUq cL2i^Q/!AQ*;( 55ȇNW('gK)ͻ1&#Q05zhorVK[Obωw7xz,Bf6F$Mlf Ā3?`2iE?xRtYyi+>Ç/# c!^SJY%/fVs8I2ik]6Kܕu%ʯ-u2zG7RYԄyoϪ1F B>PwHr#%H8@h>'Ckn^Nl, Z$/Q._ݷȢa`n6Mj4/nd-'4PMH@ N&* 1aQV@}yL>ӊᔢ;k*_m¾-MW٥˸u m_\)M9ڞyg M^13[X 6L`g<ǔKQتY`Z= `.K{9G xb"t\L`$OUz@v|B6&Dab"DY=uO<Y^$U(SI@- S,{~3=zz.^F21I:8N'[udN s[Fcl ғàаrsP IYCVMpgb],!3]SXd$T8YcjDg@!aYXQ%eylOR 8`b7kI˸Y?aWj* BrRr!I"E | fnjiﱀz|L418{YSl`u;2d'JNtBh+ihz#I| /Q5I^BpjRu4rZ([-yr˿O)IENDB`drumstick-1.1.3/icons/PaxHeaders.32572/drumstick_64.png0000644000000000000000000000013213532747316017432 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.078000337 30 ctime=1567346382.725999886 drumstick-1.1.3/icons/drumstick_64.png0000644000175000001440000000532213532747316020225 0ustar00pedrousers00000000000000PNG  IHDR@@iqsBIT|d pHYsnnУhtEXtSoftwarewww.inkscape.org< OIDATxkpUgw+٤I)i -Bb,-**2LFȀ-|((*:AGALVQZH%mڐ6iڼwͦXgݽ_lh~+[e -Vo~<[b !ld)EO>">ߏP1\ Qlc*'o 1^k:*/6hʫ"rMhr0>=Hdu %[`&. pͺ2<7\em}d͖ -1t]1t93/LnͩDY Bhg; >R~ϺX\U꺆;v h󝆦مf_| IKH; Ӱa}λyϘu+ 0l8^dϱ-G?3[Cr X)쇀2&ۯ0G]hE5G{RYOk 1ģ$h] NPy@(4YR ô0u C, Ӳ0, 0, ˲0M C,LS}l!CW^mCfOsd3l crt*1;*} mAHX- ]mcϙδ0G~QFʹ1]:V$[XA먦abDI0ccb#$eA2arR{C@vR+xּŝ#Ҧga{*J9ձ9ǁ~8QΰXJ.쿀(cU\@5qo l^t Mۚ!Au?馛;).a˨c`/|%jgyf+Y ='9$JGU@\vkvK'<'oI%w:&H`wL;ݱr$C]CCXxR$y 27VrUj9" S& $ ag3~%%V6;3I2T 052pM3e1n~3ڿ8]S}Q0h'3Ktp'«j(cfWF "`^{W@me.+FyDq7((#B=h;B5/gϐif<+0g˓INTb髇ҋr]\ds/`-FrU@9 s4|Ύ9 )ha]%|rA&w?T)S$;O$Y PYKŬinbuiX4K9r$1qq%{`bV4]*,Y6Ix`>ez (sh.E%`Z` !4&%IZ i2HԩFDŽRQ²,_. 뉄C3 zC.zGJiz z\L&'ilot B•}VlwnXPlF6 [X1fb&#; 0˶ =N3˩&BQHZѫ?2-V3L49ÀogbrhI#ig2{ tV^q묛Bp \E5PKr$ALHXa93=( ))茕qk,ɞ/}Iu&Lw,r)ĹlN\|Z~&>sU^-n@=k!3AE1=a.m/ɇZ覃M͐R:krei`,2={y{W^&.!N϶(f E7 sAKzίƜB !:A'2֍Sg(QZŽuU8E'2brqZȲHY\ :L0HVpe~ &iZH.2T],ޢB&B~;U:^'k/G!WI5WzN N/b< >6e4-pL'r"{ ڻ:ht vz4ѷP\Okɒ`dx\]d^RŝӀd$& >.4D B¢0eVa,`ζxE4[XEe40q#f^@BPǭAҌ^~ p.˥߷9Ԙ#~<[2oy~+[e -[WPWIENDB`drumstick-1.1.3/icons/PaxHeaders.32572/drumstick.svgz0000644000000000000000000000013213532747316017326 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.078000337 30 ctime=1567346382.725999886 drumstick-1.1.3/icons/drumstick.svgz0000644000175000001440000000346113532747316020123 0ustar00pedrousers00000000000000Xێ7}W_<@"" 66X`y4h$疯a-&C6A0F:,u9uCմv3ύyVmnz?s͢\o7dYk7 _h#b-?Y~i+/ٚ_Ys G@Zbg6U7iqբ[9FyvYjwMNx, xl}D 4d TDr:+Q&-6rޣ~Tw^X}jM ٻweOB D1H$_YCIOphqn3 Tnq31[UcR:zz0Rl4"Y,L?]d45/fX>d:e ( '1+E"$lnDfm)=ȋ8ϦE v " )!ѶDŽ3E2b2q*x5!hb[Tk_tƹ"XgpQ(g" i7,0@h1BTL"r H@w98*4lZf0@5D2L`FmaHoF+K\Puq*N,TK{ JwB9T]Gd hR$)DRkTOL.Bt:Iڣг" AQ//8 q I2%](GN\_[j ߥ/üh?Wi59|?w5fƏ=bfO?Z̎Cm5tFpuQ b0A z=l} W8Ϝ>2%BO׋(&,i &yd}IOvGdNrDw$IXG; [0uxeؠYPON;%A}4.+xǹDM'q`D)w 2B2#11r?an ?b0F!Zx09"b/mSwF"@*D'OH:gq|)8a|cA9h.NK}mϑrPhLW[m4l_~ǽ(aS¡8N87t_Q7ꏖtNIGK6\g羉7qĹ7R.zqnK4þ\_կ|f{I?L߿sdrumstick-1.1.3/icons/PaxHeaders.32572/drumstick_32.png0000644000000000000000000000013213532747316017425 xustar0030 mtime=1567346382.725999886 30 atime=1567346383.078000337 30 ctime=1567346382.725999886 drumstick-1.1.3/icons/drumstick_32.png0000644000175000001440000000226213532747316020220 0ustar00pedrousers00000000000000PNG  IHDR szzsBIT|d pHYs77DtEXtSoftwarewww.inkscape.org</IDATX[lTEsvݶ.`[JTij"i,`4I|"!&ԄhbH0LD[Bl"`n/6>`Ce\}}sRlڜz?o CW殸і8H /Uc*O/SLbZ6.1mӒ,ۘvޜR`ʲ/w?]~^ԉ7(L$0#$HpR)5qSjUS =YUrsxFir_V B^gsbE ͪ4 8Y36Mf) CfC1 A1Rx C]čczh\E3X[tIg˶XS1m +`S)DJ$8[54װy׻_:" bqJ|MQUD|b 4,쨅mY彅 lRgwQZެVZ ˛t9>$#@:뗸8pNPcG#Hm#esG':AY#S]+nyKEWnTӞhR7VJ d2[᚜h G3'pA\>MWȆ ;ܕ?("zIQ-֙a3\&QoASZD$D+ȑ( x+~,TRHIENDB`drumstick-1.1.3/PaxHeaders.32572/TODO0000644000000000000000000000013213532747316013763 xustar0030 mtime=1567346382.729999891 30 atime=1567346383.078000337 30 ctime=1567346382.729999891 drumstick-1.1.3/TODO0000644000175000001440000000066213532747316014560 0ustar00pedrousers00000000000000Functions from ALSA library reported by chkcoverage. The following functions won't be used in drumstick. MISC (event filter) snd_seq_change_bit snd_seq_get_bit snd_seq_set_bit snd_seq_unset_bit CLIENT - private functions snd_seq_hw_open snd_seq_hw_ops snd_seq_create_event snd_seq_event_types TIMER - private functions snd_timer_async snd_timer_name snd_timer_hw_open snd_timer_nonblock snd_timer_query_hw_open snd_timer_type