changeset 0:5242703e91d3 tip

Initial checkin for AIM92 aimR8.2 (last updated May 1997).
author tomwalters
date Fri, 20 May 2011 15:19:45 +0100
parents
children
files docs/PAG95.doc docs/PAG95_F1.ps docs/ReadMe docs/ReadMe.First docs/aimBibliography docs/aimDemonstrations docs/aimDocList docs/aimDocumentation docs/aimFileFormats docs/aimInstructions docs/aimMailList docs/aimPaths docs/aimSilentOptions docs/aimStrobeCriterion docs/ftp.doc filter/all.c filter/formulae.c filter/formulae.h filter/gamma_tone.c filter/gamma_tone.h filter/generic.c filter/imb.c filter/makefile filter/phase.c filter/phase.h filter/recurse.c filter/recurse.h filter/scales.c filter/scales.h glib/X.c glib/axes.h glib/grey.c glib/grey.h glib/makefile glib/null.c glib/options.c glib/options.h glib/ps.c glib/windows.h makefile man/man1/acf.1 man/man1/acgram.1 man/man1/atob.1 man/man1/audim.1 man/man1/btoa.1 man/man1/bufframe.1 man/man1/bufwave.1 man/man1/chi.1 man/man1/conv.1 man/man1/convert.1 man/man1/cosine.1 man/man1/edframe.1 man/man1/edwave.1 man/man1/fbank.1 man/man1/fft.1 man/man1/filt1.1 man/man1/ftgram.1 man/man1/ftoa.1 man/man1/ftos.1 man/man1/gate.1 man/man1/gauss.1 man/man1/genasa.1 man/man1/genbmm.1 man/man1/gencgm.1 man/man1/genepn.1 man/man1/gennap.1 man/man1/gensai.1 man/man1/gensgm.1 man/man1/genspl.1 man/man1/genwav.1 man/man1/hdr.1 man/man1/integframe.1 man/man1/loudness.1 man/man1/manaim.1 man/man1/merge.1 man/man1/naptosai.1 man/man1/noise.1 man/man1/op.1 man/man1/options.1 man/man1/pitch_strength.1 man/man1/ptrain.1 man/man1/racf.1 man/man1/ramp.1 man/man1/saitonap.1 man/man1/scale.1 man/man1/smooth.1 man/man1/sp_weights.1 man/man1/stats.1 man/man1/step.1 man/man1/stof.1 man/man1/swab.1 man/man1/tone.1 man/man1/x11fonts.1 man/man1/x11gram.1 man/man1/x11play.1 man/man1/x11plot.1 man/man1/xreview.1 man/whatis model/atan.c model/bank.c model/bank.h model/calc.h model/corti.c model/corti.h model/defaults.c model/defaults.h model/faster.c model/gen.c model/image.c model/image.h model/integrate.c model/integrate.h model/interp.c model/makefile model/model.c model/model.h model/new.c model/review.c model/spiral.c model/spiral.h model/table.c model/units.c model/units.h model/version.c saitools/changeheader.c saitools/findintervals_nap.c saitools/findintervals_sai.c saitools/findpeaks.c saitools/header.c saitools/inout.c saitools/makefile saitools/matrix.c saitools/napgraph.c saitools/napheader.c saitools/removepeaks.c saitools/saicut.c saitools/saigraph.c saitools/saiinfo.c saitools/sairotate.c saitools/saisummary.c saitools/tip.h saitools/trigger.c stitch/buffer.c stitch/buffer.h stitch/draw.c stitch/draw.h stitch/fill.c stitch/fill.h stitch/fillable.c stitch/fillable.h stitch/funcs.c stitch/funcs.h stitch/io.c stitch/io.h stitch/makefile stitch/ops.c stitch/ops.h stitch/pullable.c stitch/pullable.h stitch/source.c stitch/source.h stitch/srcio.c stitch/srcio.h stitch/stitch.c stitch/stitch.h stitch/stypes.c stitch/stypes.h stitch/wrap.c stitch/wrap.h tools/acf.c tools/acgram.c tools/atob.c tools/audim.c tools/btoa.c tools/bufframe.c tools/bufwave.c tools/chi.c tools/conv.c tools/convert.c tools/cosine.c tools/edframe.c tools/edwave.c tools/fbank.c tools/fft.c tools/filt1.c tools/freqs.c tools/ftgram.c tools/ftoa.c tools/ftos.c tools/gate.c tools/gauss.c tools/hdr.c tools/header.c tools/header.h tools/integframe.c tools/loudness.c tools/makefile tools/merge.c tools/naptosai.c tools/noise.c tools/op.c tools/options.c tools/options.h tools/pitch_strength.c tools/ptrain.c tools/racf.c tools/ramp.c tools/saitonap.c tools/scale.c tools/sigproc.c tools/sigproc.h tools/smooth.c tools/sp_weights.c tools/stats.c tools/step.c tools/stof.c tools/strmatch.c tools/strmatch.h tools/swab.c tools/tone.c tools/units.c tools/units.h tools/x11coord.c tools/x11coord.h tools/x11fonts.c tools/x11gram.c tools/x11play.c tools/x11plot.c wdf/bank_tl.c wdf/bank_tl.h wdf/calc_tl.h wdf/ear.c wdf/ear.h wdf/fir.c wdf/fir.h wdf/formulae_tl.c wdf/formulae_tl.h wdf/makefile wdf/meddis.c wdf/meddis.h wdf/scales_tl.c wdf/scales_tl.h wdf/upsample.c wdf/upsample.h wdf/wdf_ear.c wdf/wdf_ear.h wdf/wdf_tl.c wdf/wdf_tl.h xaim/buttons.c xaim/cartoon.c xaim/disclaimer.text xaim/graphics.c xaim/initialise.c xaim/makefile xaim/releasenotes.text xaim/stipple_a xaim/switch_axes.c xaim/switch_buttons.c xaim/switch_control.c xaim/synthdramp.c xaim/synthirn.c xaim/xreview.bitmap xaim/xreview.c xaim/xreview.h
diffstat 264 files changed, 66521 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/PAG95.doc	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,476 @@
+Revised for JASA,  3 April 95		1
+
+
+Time-domain modelling of peripheral auditory processing:
+	A modular architecture and a software platform*
+
+Roy D. Patterson and Mike H. Allerhand
+MRC Applied Psychology Unit, 15 Chaucer Road, Cambridge  CB2 2EF, UK 
+
+Christian Gigure Laboratory of Experimental Audiology, University
+Hospital Utrecht, 3508 GA Utrecht, The Netherlands
+
+(Received		December, 1994)   (Revised 31 March 1995)
+
+A software package with a modular architecture has been developed to
+support perceptual modelling of the fine-grain spectro-temporal
+information observed in the auditory nerve. The package contains both
+functional and physiological modules to simulate auditory spectral
+analysis, neural encoding and temporal integration, including new
+forms of periodicity-sensitive temporal integration that generate
+stabilized auditory images. Combinations of the modules enable the
+user to approximate a wide variety of existing, time-domain, auditory
+models. Sequences of auditory images can be replayed to produce
+cartoons of auditory perceptions that illustrate the dynamic response
+of the auditory system to everyday sounds.
+
+PACS numbers: 43.64.Bt, 43.66.Ba, 43.71.An
+
+Running head: Auditory Image Model Software
+
+
+INTRODUCTION
+
+Several years ago, we developed a functional model of the cochlea to
+simulate the phase-locked activity that complex sounds produce in the
+auditory nerve. The purpose was to investigate the role of the
+fine-grain timing information in auditory perception generally
+(Patterson et al., 1992a; Patterson and Akeroyd, 1995), and in speech
+perception in particular (Patterson, Holdsworth and Allerhand, 1992b).
+The architecture of the resulting Auditory Image Model (AIM) is shown
+in the left-hand column of Fig. 1. The responses of the three modules
+to the vowel in 'hat' are shown in the three panels of Fig. 2.
+Briefly, the spectral analysis stage converts the sound wave into the
+model's representation of basilar membrane motion (BMM). For the vowel
+in 'hat', each glottal cycle generates a version of the basic vowel
+structure in the BMM (top panel).  The neural encoding stage
+stabilizes the BMM in level and sharpens features like vowel formants,
+to produce a simulation of the neural activity pattern (NAP) produced
+by the sound in the auditory nerve (middle panel).  The temporal
+integration stage stabilizes the repeating structure in the NAP and
+produces a simulation of our perception of the vowel (bottom panel),
+referred to as the auditory image.  Sequences of simulated images can
+be generated at regular intervals and replayed as an animated cartoon
+to show the dynamic behaviour of the auditory images produced by
+everyday sounds.  
+
+An earlier version of the AIM software was made available to
+collaborators via the Internet. From there it spread to the speech and
+music communities, indicating a more general interest in auditory
+models than we had originally anticipated. This has prompted us to
+prepare documentation and a formal release of the software (AIM R7).
+
+A number of users wanted to compare the outputs from the functional
+model, which is almost level independent, with those from
+physiological models of the cochlea, which are fundamentally level
+dependent. Others wanted to compare the auditory images produced by
+strobed temporal integration with correlograms. As a result, we have
+installed alternative modules for each of the three main stages as
+shown in the right-hand column of Fig. 1.  The alternative spectral
+analysis module is a non-linear, transmission line filterbank based on
+Gigure and Woodland (1994a). The neural encoding module is based on
+the inner haircell model of Meddis (1988).  The temporal integration
+module generates correlograms like those of Slaney and Lyon (1990) or
+Meddis and Hewitt (1991), using the algorithm proposed by Allerhand
+and Patterson (1992). The responses of the three modules to the vowel
+in 'hat' are shown in Fig. 3 for the case where the level of the vowel
+is 60 dB SPL. The patterns are broadly similar to those of the
+functional modules but the details differ, particularly at the output
+of the third stage. The differences grow more pronounced when the
+level of the vowel is reduced to 30 dB SPL or increased to 90 dB SPL.
+Figures 2 and 3 together illustrate how the software can be used to
+compare and contrast different auditory models.  The new modules also
+open the way to time-domain simulation of hearing impairment and
+distortion products of cochlear origin.
+
+Switches were installed to enable the user to shift from the
+functional to the physiological version of AIM at the output of each
+stage of the model. This architecture enables the system to implement
+other popular auditory models such as the gammatone- filterbank,
+Meddis-haircell, correlogram models proposed by Assmann and
+Summerfield (1990), Meddis and Hewitt (1991), and Brown and Cooke
+(1994). The remainder of this letter describes the integrated software
+package with emphasis on the functional and physiological routes, and
+on practical aspects of obtaining the software package.*
+
+
+
+I. THE AUDITORY IMAGE MODEL
+
+A. The spectral analysis stage 
+
+Spectral analysis is performed by a bank of auditory filters which
+converts a digitized wave into an array of filtered waves like those
+shown in the top panels of Figs 2 and 3.  The set of waves is AIM's
+representation of basilar membrane motion.  The software distributes
+the filters linearly along a frequency scale measured in Equivalent
+Rectangular Bandwidths (ERB's). The ERB scale was proposed by Glasberg
+and Moore (1990) based on physiological research summarized in
+Greenwood (1990) and psychoacoustic research summarized in Patterson
+and Moore (1986). The constants of the ERB function can also be set to
+produce a reasonable approximation to the Bark scale. Options enable
+the user to specify the number of channels in the filterbank and the
+minimum and maximum filter center frequencies.
+
+AIM provides both a functional auditory filter and a physiological
+auditory filter for generating the BMM: the former is a linear,
+gammatone filter (Patterson et al., 1992a); the latter is a
+non-linear, transmission-line filter (Gigure and Woodland, 1994a).
+The impulse response of the gammatone filter provides an excellent fit
+to the impulse response of primary auditory neurons in cats, and its
+amplitude characteristic is very similar to that of the 'roex' filter
+commonly used to represent the human auditory filter. The motivation
+for the gammatone filterbank and the available implementations are
+summarized in Patterson (1994a). The input wave is passed through an
+optional middle-ear filter adapted from Lutman and Martin (1979).
+
+In the physiological version, a 'wave digital filter' is used to
+implement the classical, one-dimensional, transmission-line
+approximation to cochlear hydrodynamics. A feedback circuit
+representing the fast motile response of the outer haircells generates
+level- dependent basilar membrane motion (Gigure and Woodland,
+1994a). The filterbank generates combination tones of the type
+f1-n(f2-f1) which propagate to the appropriate channel, and it has the
+potential to generate cochlear echoes. Options enable the user to
+customize the transmission line filter by specifying the feedback gain
+and saturation level of the outer haircell circuit. The middle ear
+filter forms an integral part of the simulation in this case.
+Together, it and the transmission line filterbank provide a
+bi-directional model of auditory spectral analysis.
+
+The upper panels of Figs 2 and 3 show the responses of the two
+filterbanks to the vowel in 'hat'. They have 75 channels covering the
+frequency range 100 to 6000 Hz (3.3 to 30.6 ERB's). In the
+high-frequency channels, the filters are broad and the glottal pulses
+generate impulse responses which decay relatively quickly. In the
+low-frequency channels, the filters are narrow and so they resolve
+individual continuous harmonics. The rightward skew in the
+low-frequency channels is the 'phase lag,' or 'propagation delay,' of
+the cochlea, which arises because the narrower low-frequency filters
+respond more slowly to input. The transmission line filterbank shows
+more ringing in the valleys than the gammatone filterbank because of
+its dynamic signal compression; as amplitude decreases the damping of
+the basilar membrane is reduced to increase sensitivity and frequency
+resolution.
+
+
+B. The neural encoding stage
+
+The second stage of AIM simulates the mechanical/neural transduction
+process performed by the inner haircells. It converts the BMM into a
+neural activity pattern (NAP), which is AIM's representation of the
+afferent activity in the auditory nerve. Two alternative simulations
+are provided for generating the NAP: a bank of two-dimensional
+adaptive- thresholding units (Holdsworth and Patterson, 1993), or a
+bank of inner haircell simulators (Meddis, 1988).
+
+The adaptive thresholding mechanism is a functional representation of
+neural encoding. It begins by rectifying and compressing the BMM; then
+it applies adaptation in time and suppression across frequency. The
+adaptation and suppression are coupled and they jointly sharpen
+features like vowel formants in the compressed BMM representation.
+Briefly, an adaptive threshold value is maintained for each channel
+and updated at the sampling rate. The new value is the largest of a)
+the previous value reduced by a fast-acting temporal decay factor, b)
+the previous value reduced by a longer-term temporal decay factor, c)
+the adapted level in the channel immediately above, reduced by a
+frequency spread factor, or d) the adapted level in the channel
+immediately below, reduced by the same frequency spread factor. The
+mechanism produces output whenever the input exceeds the adaptive
+threshold, and the output level is the difference between the input
+and the adaptive threshold. The parameters that control the spread of
+activity in time and frequency are options in AIM.
+
+The Meddis (1988) module simulates the operation of an individual
+inner haircell; specifically, it simulates the flow of
+neurotransmitter across three reservoirs that are postulated to exist
+in and around the haircell. The module reproduces important properties
+of single afferent fibres such as two-component time adaptation and
+phase-locking. The transmitter flow equations are solved using the
+wave-digital-filter algorithm described in Gigure and Woodland
+(1994a). There is one haircell simulator for each channel of the
+filterbank. Options allow the user to shift the entire rate-intensity
+function to a higher or lower level, and to specify the type of fibre
+(medium or high spontaneous-rate).
+
+The middle panels in Figures 2 and 3 show the NAPs obtained with
+adaptive thresholding and the Meddis module in response to BMMs from
+the gammatone and transmission line filterbanks of Figs 1 and 2,
+respectively. The phase lag of the BMM is preserved in the NAP. The
+positive half-cycles of the BMM waves have been sharpened in time, an
+effect which is more obvious in the adaptive thresholding NAP.
+Sharpening is also evident in the frequency dimension of the adaptive
+thresholding NAP. The individual 'haircells' are not coupled across
+channels in the Meddis module, and thus there is no frequency
+sharpening in this case. The physiological NAP reveals that the
+activity between glottal pulses in the high-frequency channels is due
+to the strong sixth harmonic in the first formant of the vowel.
+
+
+C. The temporal integration stage
+
+Periodic sounds give rise to static, rather than oscillating,
+perceptions indicating that temporal integration is applied to the NAP
+in the production of our initial perception of a sound -- our auditory
+image. Traditionally, auditory temporal integration is represented by
+a simple leaky integration process and AIM provides a bank of lowpass
+filters to enable the user to generate auditory spectra (Patterson,
+1994a) and auditory spectrograms (Patterson et al., 1992b). However,
+the leaky integrator removes the phase-locked fine structure observed
+in the NAP, and this conflicts with perceptual data indicating that
+the fine structure plays an important role in determining sound
+quality and source identification (Patterson, 1994b; Patterson and
+Akeroyd, 1995). As a result, AIM includes two modules which preserve
+much of the time-interval information in the NAP during temporal
+integration, and which produce a better representation of our auditory
+images. In the functional version of AIM, this is accomplished with
+strobed temporal integration (Patterson et al., 1992a,b); in the
+physiological version, it is accomplished with a bank of
+autocorrelators (Slaney and Lyon, 1990; Meddis and Hewitt, 1991).
+
+In the case of strobed temporal integration (STI), a bank of delay
+lines is used to form a buffer store for the NAP, one delay line per
+channel, and as the NAP proceeds along the buffer it decays linearly
+with time, at about 2.5 %/ms. Each channel of the buffer is assigned a
+strobe unit which monitors activity in that channel looking for local
+maxima in the stream of NAP pulses. When one is found, the unit
+initiates temporal integration in that channel; that is, it transfers
+a copy of the NAP at that instant to the corresponding channel of an
+image buffer and adds it point-for-point with whatever is already
+there. The local maximum itself is mapped to the 0-ms point in the
+image buffer. The multi-channel version of this STI process produces
+AIM's representation of our auditory image of a sound. Periodic and
+quasi-periodic sounds cause regular strobing which leads to simulated
+auditory images that are static, or nearly static, and which have the
+same temporal resolution as the NAP.  Dynamic sounds are represented
+as a sequence of auditory image frames. If the rate of change in a
+sound is not too rapid, as is diphthongs, features are seen to move
+smoothly as the sound proceeds, much as characters move smoothly in
+animated cartoons.
+
+An alternative form of temporal integration is provided by the
+correlogram (Slaney and Lyon, 1990; Meddis and Hewitt, 1991). It
+extracts periodicity information and preserves intra-period fine
+structure by autocorrelating each channel of the NAP. The correlogram
+is the multi-channel version of this process. It was originally
+introduced as a model of pitch perception (Licklider, 1951) with a
+neural wiring diagram to illustrate that it was physiologically
+plausible. To date, however, there is no physiological evidence for
+autocorrelation in the auditory system, and the installation of the
+module in the physiological route was a matter of convenience. The
+current implementation is a recursive, or running, autocorrelation. A
+functionally equivalent FFT-based method is also provided (Allerhand
+and Patterson, 1992). A comparison of the correlogram in the bottom
+panel of Fig. 3 with the auditory image in the bottom panel of Fig. 2
+shows that the vowel structure is more symmetric in the correlogram
+and there are larger level contrasts in the correlogram.  It is not
+yet known whether one of the representations is more realistic or more
+useful. The present purpose is to note that the software package can
+be used to compare auditory representations in a way not previously
+possible.
+
+
+
+II. THE SOFTWARE/HARDWARE PLATFORM
+
+i. The software package: The code is distributed as a compressed
+archive (in unix tar format), and can be obtained via ftp from the
+address: ftp.mrc-apu.cam.ac.uk (Name=anonymous; Password=<your email
+address>). All the software is contained in a single archive:
+pub/aim/aim.tar.Z. The associated text file pub/aim/ReadMe contains
+instructions for installing and compiling the software.  The AIM
+package consists of a makefile and several sub-directories.  Five of
+these (filter, glib, model, stitch and wdf) contain the C code for
+AIM. An aim/tools directory contains C code for ancillary software
+tools.  These software tools are provided for pre/post-processing of
+model input/output. A variety of functions are offered, including:
+stimulus generation, signal processing, and data manipulation.  An
+aim/man directory contains on-line manual pages describing AIM and the
+software tools.  An aim/scripts directory contains demonstration
+scripts for a guided tour through the model. Sounds used to test and
+demonstrate the model are provided in the aim/waves directory. These
+sounds were sampled at 20 kHz, and each sample is a 2-byte number in
+little-endian byte order; a tool is provided to swap byte order when
+necessary.
+
+ii. System requirements: The software is written in C. The code
+generated by the native C compilers included with Ultrix (version 4.3a
+and above) and SunOS (version 4.1.3 and above) has been extensively
+tested. The code from the GNU C compiler (version 2.5.7 and above) is
+also reliable.  The total disc usage of the AIM source code is about
+700 kbytes.  The package also includes 500 kbytes of sources for
+ancillary software tools, and 200 kbytes of documentation. The
+executable programs occupy about 1000 kbytes, and executable programs
+for ancillary tools occupy 7000 kbytes. About 800 Kbytes of temporary
+space are required for object files during compilation. The graphical
+interface uses X11 (R4 and above) with either the OpenWindows or Motif
+user interface. The programs can be compiled using the base Xlib
+library (libX11.a), and will run on both 1- bit (mono) and multi-plane
+(colour or greyscale) displays.
+
+iii. Compilation and operation: The makefile includes targets to
+compile the source code for AIM and the associated tools on a range of
+machines (DEC, SUN, SGI, HP); the targets differ only in the pathnames
+for the local X11 base library (libX11.a) and header files (X11/X.h
+and X11/Xlib.h).  AIM can be compiled without the display code if the
+graphics interface is not required or if X11 is not available (make
+noplot).  The executable for AIM is called gen. Compilation also
+generates symbolic links to gen, such as genbmm, gennap and gensai,
+which are used to select the desired output (BMM, NAP or SAI). The
+links and the executables for the aim/tools are installed in the
+aim/bin directory after compilation.  Options are specified as:
+name=value on the command line; unspecified options are assigned
+default values.  The model output takes the form of binary data routed
+by default to the model's graphical displays. Output can also be
+routed to plotting hardware, or other post- processing software.
+
+
+
+III. APPLICATIONS AND SUMMARY
+
+In hearing research, the functional version of AIM has been used to
+model phase perception (Patterson, 1987a), octave perception
+(Patterson et al., 1993), and timbre perception (Patterson, 1994b).
+The physiological version has been used to simulate cochlear hearing
+loss (Gigure, Woodland, and Robinson, 1993; Gigure and Woodland,
+1994b), and combination tones of cochlear origin (Gigure, Kunov, and
+Smoorenburg, 1995). In speech research, the functional version has
+been used to explain syllabic stress (Allerhand et al., 1992), and
+both versions have been used as preprocessors for speech recognition
+systems (e.g. Patterson, Anderson, and Allerhand, 1994; Gigure et
+al., 1993).  In summary, the AIM software package provides a modular
+architecture for time- domain computational studies of peripheral
+auditory processing.
+
+
+* Instructions for acquiring the software package electronically are
+presented in Section II.  This document refers to AIM R7 which is the
+first official release.
+
+
+ACKNOWLEDGEMENTS
+
+The gammatone filterbank, adaptive thresholding, and much of the
+software platform were written by John Holdsworth; the options handler
+is by Paul Manson, and the revised STI module by Jay Datta. Michael
+Akeroyd extended the postscript facilities and developed the xreview
+routine for auditory image cartoons. The software development was
+supported by grants from DRA Farnborough (U.K.), Esprit BR 3207 (EEC),
+and the Hearing Research Trust (U.K.). We thank Malcolm Slaney and
+Michael Akeroyd for helpful comments on an earlier version of the
+paper.
+
+
+Allerhand, M., and Patterson, R.D. (1992). "Correlograms and auditory
+images," Proc.  Inst. Acoust. 14, 281-288.
+
+Allerhand, M., Butterfield, S., Cutler, A., and Patterson, R.D.
+(1992). "Assessing syllable strength via an auditory model," Proc.
+Inst. Acoust. 14, 297-304.
+
+Assmann, P.F., and Summerfield, Q. (1990). "Modelling the perception
+of concurrent vowels: Vowels with different fundamental frequencies,"
+J. Acoust. Soc. Am., 88, 680- 697.
+
+Brown, G.J., and Cooke, M. (1994) "Computational auditory scene
+analysis," Computer Speech and Language 8, 297-336.
+
+Gigure, C., Woodland, P.C., and Robinson, A.J. (1993). "Application
+of an auditory model to the computer simulation of hearing impairment:
+Preliminary results," Can. Acoust.  21, 135-136.
+
+Gigure, C., and Woodland, P.C. (1994a). "A computational model of
+the auditory periphery for speech and hearing research. I. Ascending
+path," J. Acoust. Soc. Am. 95, 331-342.
+
+Gigure, C., and Woodland, P.C. (1994b). "A computational model of
+the auditory periphery for speech and hearing research. II: Descending
+paths,'' J. Acoust. Soc. Am.  95, 343-349.
+
+Gigure, C., Kunov, H., and Smoorenburg, G.F. (1995). "Computational
+modelling of psycho-acoustic combination tones and distortion-product
+otoacoustic emissions," 15th Int. Cong. on Acoustics, Trondheim
+(Norway), 26-30 June.
+
+Glasberg, B.R., and Moore, B.C.J. (1990). "Derivation of auditory
+filter shapes from notched-noise data," Hear. Res. 47, 103-38.
+
+Greenwood, D.D. (1990). "A cochlear frequency-position function for
+several species - 29 years later," J. Acoust. Soc. Am. 87, 2592-2605.
+
+Holdsworth, J.W., and Patterson, R.D. (1991).  "Analysis of
+waveforms," UK Patent No.  GB 2-234-078-A (23.1.91).  London: UK
+Patent Office.
+
+Licklider, J. C. R. (1951). "A duplex theory of pitch perception,"
+Experientia, 7, 128- 133.
+
+Lutman, M.E. and Martin, A.M. (1979). "Development of an
+electroacoustic analogue model of the middle ear and acoustic reflex,"
+J. Sound. Vib. 64, 133-157.
+
+Meddis, R. (1988). "Simulation of auditory-neural transduction:
+Further studies," J.  Acoust. Soc. Am. 83, 1056-1063.
+
+Meddis, R. and Hewitt, M.J. (1991). "Modelling the perception of
+concurrent vowels with different fundamental frequencies," J. Acoust.
+Soc. Am. 91, 233-45.
+
+Patterson, R.D. (1987). "A pulse ribbon model of monaural phase
+perception," J. Acoust.  Soc. Am., 82, 1560-1586.
+
+Patterson, R.D. (1994a). "The sound of a sinusoid: Spectral models,"
+J. Acoust. Soc. Am.  96, 1409-1418.
+
+Patterson, R.D. (1994b). "The sound of a sinusoid: Time-interval
+models." J. Acoust. Soc.  Am. 96, 1419-1428.
+
+Patterson, R.D. and Akeroyd, M. A. (1995). "Time-interval patterns and
+sound quality," in: Advances in Hearing Research: Proceedings of the
+10th International Symposium on Hearing, edited by G. Manley, G.
+Klump, C. Koppl, H. Fastl, & H. Oeckinghaus, World Scientific,
+Singapore, (in press).
+
+Patterson, R.D., Anderson, T., and Allerhand, M. (1994). "The auditory
+image model as a preprocessor for spoken language," in Proc. Third
+ICSLP, Yokohama, Japan 1395- 1398.
+
+Patterson, R.D., Milroy, R. and Allerhand, M. (1993). "What is the
+octave of a harmonically rich note?" In: Proc. 2nd Int. Conf. on Music
+and the Cognitive Sciences, edited by I. Cross and I Deliege (Harwood,
+Switzerland) 69-81.
+
+Patterson, R.D. and B.C.J. Moore (1986). "Auditory filters and
+excitation patterns as representations of frequency resolution," in
+Frequency Selectivity in Hearing, edited by B. C. J. Moore, (Academic,
+London) pp. 123-177.
+
+Patterson, R.D., Holdsworth, J. and Allerhand M. (1992) "Auditory
+Models as preprocessors for speech recognition," In: The Auditory
+Processing of Speech: From the auditory periphery to words, edited by
+M. E. H. Schouten (Mouton de Gruyter, Berlin) 67-83.
+
+Patterson, R.D., Robinson, K., Holdsworth, J., McKeown, D., Zhang, C.,
+and Allerhand M.  (1992) "Complex sounds and auditory images," In:
+Auditory physiology and perception, edited by Y Cazals, L. Demany, and
+K. Horner (Pergamon, Oxford) 429-446.
+
+Slaney, M. and Lyon, R.F. (1990).  "A perceptual pitch detector," in
+Proc. IEEE Int. Conf.  Acoust., Speech, Signal Processing,
+Albuquerque, New Mexico, April 1990.
+
+
+Figure 1. The three-stage structure of the AIM software package.
+Left-hand column: functional route, right-hand column: physiological
+route. For each module, the figure shows the function (bold type), the
+implementation (in the rectangle), and the simulation it produces
+(italics).
+
+Figure 2. Responses of the model to the vowel in 'hat' processed
+through the functional route: (top) basilar membrane motion, (middle)
+neural activity pattern, and (bottom) auditory image.
+
+Figure 3. Responses of the model to the vowel in 'hat' processed
+through the physiological route: (top) basilar membrane motion,
+(middle) neural activity pattern, and (bottom) autocorrelogram image.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/PAG95_F1.ps	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,2835 @@
+%!PS-Adobe-2.0
+%%Title: PAG95_F1-Layer#1
+%%Creator: PrintMonitor
+%%CreationDate: Tuesday, April 4, 1995
+%%Pages: (atend)
+%%BoundingBox: ? ? ? ?
+%%PageBoundingBox: 119 124 2354 3382
+%%For: roy
+%%DocumentProcSets: "(AppleDict md)" 71 0
+%% ) Copyright Apple Computer, Inc. 1989-92 All Rights Reserved.
+%%EndComments
+%%BeginProcSet: "(AppleDict md)" 71 0
+userdict/LW{save statusdict/product get(LaserWriter)anchorsearch
+exch pop{dup length 0 eq{pop 1}{( Plus)eq{2}{3}ifelse}ifelse}{0}ifelse exch restore}bind put
+userdict/patchOK known not{save LW dup 1 ne exch 2 ne and false<1861AEDAE118A9F95F1629C0137F8FE656811DD93DFBEA65E947502E78BA12284B8A58EF0A3
+2E272778DAA2ABEC72A84102D591E11D96BA61F57877B895A752D9BEAAC3DFD7D3220E2BDE7C036467464E0E836748F1DE7AB6216866F130CE7CFCEC8CE050B870C11881EE3E9D70919>{eexec}stopped{dup type/stringtype eq{pop}if}if and exch restore userdict/patchOK 3 -1 roll put} if
+userdict/downloadOK known not{userdict/downloadOK{ vmstatus exch sub exch pop 120000 gt patchOK and}bind put}if
+userdict/type42known known not{userdict/type42known systemdict/resourcestatus known{42/FontType resourcestatus{pop pop true}{false}ifelse }{false}ifelse put}if
+type42known not downloadOK and {userdict begin /*charpath /charpath load def/charpathflag false def/charpath{userdict/charpathflag true put userdict/*charpath get exec userdict/charpathflag false put}bind def end}if
+userdict/checkload known not{userdict/checkload{{pop exec} {save 3 dict begin/mystring 6050 string def
+exch/endstring exch def{currentfile mystring readline not{stop}if endstring eq{exit}if}loop end restore pop}ifelse}bind put}if
+userdict/LW+{LW 2 eq}bind put
+userdict/ok known not{userdict/ok{systemdict/statusdict known dup{LW 0 gt and}if}bind put}if
+systemdict/setobjectformat known{0 setobjectformat}if
+systemdict/currentpacking known{currentpacking true setpacking}if
+/md 270 dict def md begin
+/av 71 def
+/T true def/F false def/mtx matrix def/s75 75 string def/sa8 8 string def/sb8 8 string def
+/sc8 8 string def/sd8 8 string def/s1 ( ) def/pxs 1 def/pys 1 def
+/ns false def
+1 0 mtx defaultmatrix dtransform exch atan/pa exch def/nlw .24 def/ppr [-32 -29.52 762 582.48] def
+/pgr [0 0 0 0] def
+/pgs 1 def/por true def/xb 500 array def/so true def/tso true def/fillflag false def/pnm 1 def/fmv true def
+/sfl false def/ma 0 def/invertflag false def/dbinvertflag false def/xflip false def/yflip false def/noflips true def/scaleby96 false def/fNote true def/fBitStretch true def
+/4colors false def/fg (Rvd\001\001\000\000\177) def
+/bdf{bind def}bind def
+/xdf{exch def}bdf
+/xl{neg exch neg translate}bdf
+/fp{pnsh 0 ne pnsv 0 ne and}bdf
+/nop{}bdf/lnop[/nop load]cvx bdf
+/vrb[
+{fp{fg 6 get 0 ne{gsave stroke grestore}{gsave 1 setlinewidth pnsh pnsv scale stroke grestore}ifelse}if newpath}bind
+/eofill load
+dup
+/newpath load
+2 index
+dup
+{clip newpath}bind
+{}bind
+dup
+2 copy
+]def
+/sgd systemdict/setpagedevice known{{2 dict begin/PreRenderingEnhance exch def/Policies 1 dict dup/PreRenderingEnhance 1 put def currentdict end setpagedevice}}{{pop}}ifelse bdf
+/svsc systemdict/currentcolorscreen known{{currentcolorscreen/dkspf xdf/dkrot xdf/dkfreq xdf/dyspf xdf/dyrot xdf/dyfreq xdf/dmspf xdf/dmrot xdf/dmfreq xdf
+/dcspf xdf/dcrot xdf/dcfreq xdf}}{{currentscreen/spf xdf/rot xdf/freq xdf}}ifelse bdf
+/doop{vrb exch get exec}bdf
+/psu{/udf xdf/tso xdf /fNote xdf/fBitStretch xdf/scaleby96 xdf/yflip xdf/xflip xdf
+/invertflag xdf/dbinvertflag invertflag statusdict begin version cvr 47.0 ge product (LaserWriter) eq not and end invertflag and {not}if def
+xflip yflip or{/noflips false def}if
+/pgs xdf 2 index .72 mul exch div/pys xdf div .72 mul/pxs xdf ppr astore pop pgr astore pop/por xdf sn and/so xdf}bdf
+/tab{userdict /11x17 known{userdict begin /11x17 load exec end}{statusdict /setpage known{statusdict begin 792 1224 1 setpage end}{statusdict /setpageparams known{statusdict begin 792 1224 0 1 setpageparams end}if}ifelse}ifelse}bdf
+/a3Size{userdict /a3 known{userdict begin /a3 load exec end}{statusdict /setpageparams known{statusdict begin 842 1191 0 1 setpageparams end}if}ifelse}bdf
+/txpose{fNote{smalls}{bigs}ifelse pgs get exec pxs pys scale ppr aload pop por{noflips{pop exch neg exch translate pop 1 -1 scale}if
+xflip yflip and{pop exch neg exch translate 180 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg translate}if 
+xflip yflip not and{pop exch neg exch translate pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 translate}if yflip xflip not and{ppr 1 get neg ppr 0 get neg translate}if}
+{noflips{translate pop pop 270 rotate 1 -1 scale}if xflip yflip and{translate pop pop 90 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg translate}if
+xflip yflip not and{translate pop pop 90 rotate ppr 3 get ppr 1 get neg sub neg 0 translate}if yflip xflip not and{translate pop pop 270 rotate ppr 2 get ppr 0 get neg sub neg 0 exch translate}if}ifelse
+statusdict begin/waittimeout where{pop waittimeout 300 lt{statusdict/waittimeout 300 put}if}if end 
+scaleby96{ppr aload pop 4 -1 roll add 2 div 3 1 roll add 2 div 2 copy translate .96 dup scale neg exch neg exch translate}if}bdf
+/fr{4 copy pgr aload pop 3 -1 roll add 3 1 roll exch add 6 2 roll 3 -1 roll
+sub 3 1 roll exch sub 3 -1 roll exch div 3 1 roll div exch scale pop pop xl}bdf
+/obl{{0.212557 mul}{pop 0}ifelse}bdf
+/sfd{ps fg 5 -1 roll get mul 100 div 0 ps 5 -1 roll obl ps neg 0 0 6a astore makefont setfont}bdf
+/fnt{findfont sfd}bdf
+/bt{sa 3 1 roll 3 index and put}bdf
+/sa(\000\000\000\000\000\000\000\000\000\000)def
+/fs{0 1 bt 1 2 bt 2 4 bt 3 8 bt 4 16 bt 5 32 bt 6 64 bt 7 128 bt sa exch 8 exch put}bdf
+/mx1 matrix def
+/mx2 matrix def
+/mx3 matrix def
+/bu{currentpoint 4colors{currentcmykcolor}{currentrgbcolor}ifelse currentlinewidth currentlinecap currentlinejoin 
+currentdash exch aload length fg 5 sfl{1}{0}ifelse put pnsv pnsh 
+2t aload pop 3a aload pop mx2 aload pop mx1 aload pop mtx currentmatrix aload pop
+mx3 aload pop ps pm restore/ps xdf mx3 astore pop}bdf
+/bn{/pm save def mx3 setmatrix newpath 0 0 moveto ct dup 39 get 0 exch getinterval cvx exec mtx astore setmatrix mx1 astore pop mx2 astore pop 3a 
+astore pop 2t astore pop/pnsh xdf/pnsv xdf gw
+/sfl fg 5 get 0 ne def array astore exch setdash setlinejoin setlinecap 
+setlinewidth 4colors{mysetcmykcolor}{setrgbcolor}ifelse moveto}bdf
+/fc{save vmstatus exch sub 50000 lt
+{(%%[|0|]%%)=print flush}if pop restore}bdf
+/tc{32768 div add 3 1 roll 32768 div add 2t astore pop}bdf
+/3a [0 0 0] def
+/2t 2 array def
+/tp{3a astore pop}bdf
+/tt{mx2 currentmatrix pop currentpoint 2 copy 2t aload pop qa 2 copy translate 3a aload pop exch dup 0 eq
+{pop}{1 eq{-1 1}{1 -1}ifelse scale}ifelse rotate pop neg exch neg exch translate moveto}bdf
+/te{mx2 setmatrix}bdf
+/th{3 -1 roll div 3 1 roll exch div 2 copy mx1 scale pop scale/sfl true def}bdf
+/tu{1 1 mx1 itransform scale/sfl false def}bdf
+/ts{1 1 mx1 transform scale/sfl true def}bdf
+/fz{/ps xdf}bdf
+/dv{dup 0 ne{div}{pop}ifelse}bdf
+/pop4{pop pop pop pop}bdf
+/it{sfl{mx1 itransform}if}bdf
+/gm{exch it moveto}bdf/rm{it rmoveto}bdf
+/lm{currentpoint sfl{mx1 transform}if exch pop sub 0 exch it rmoveto}bdf
+/fm{statusdict/manualfeed known}bdf
+/se{statusdict exch/manualfeed exch put}bdf
+/mf{dup/ma exch def 0 gt{fm se/t1 5 st ok ma 1 gt and{/t2 0 st/t3 0 st
+statusdict/manualfeedtimeout 3600 put
+}if}if}bdf
+/jn{/statusdict where exch pop{statusdict exch /jobname exch put}if}bdf
+/pen{pnm mul/pnsh xdf pnm mul/pnsv xdf pnsh setlinewidth}bdf
+/min{2 copy gt{exch}if pop}bdf
+/max{2 copy lt{exch}if pop}bdf
+/dh{fg 6 1 put array astore dup {1 pxs div mul exch}forall astore exch pop exch pop exch setdash}bdf
+/ih[currentdash]def
+/rh{fg 6 0 put ih aload pop setdash}bdf
+/dl{gsave nlw pys div setlinewidth 0 setgray}bdf
+/dlin{exch currentpoint currentlinewidth 2 div dup
+translate newpath moveto lineto currentpoint stroke grestore moveto}bdf
+/lin{fg 6 get 0 ne{exch lineto currentpoint 0 doop moveto}
+{exch currentpoint/pnlv xdf/pnlh xdf gsave newpath/@1 xdf/@2 xdf fp{pnlh @2 lt{pnlv @1 ge
+{pnlh pnlv moveto @2 @1 lineto pnsh 0 rlineto
+0 pnsv rlineto pnlh pnsh add pnlv pnsv add lineto pnsh neg 0 rlineto}
+{pnlh pnlv moveto pnsh 0 rlineto @2 pnsh add @1 lineto 0 pnsv rlineto
+pnsh neg 0 rlineto pnlh pnlv pnsv add lineto}ifelse}{pnlv @1 gt
+{@2 @1 moveto pnsh 0 rlineto pnlh pnsh add pnlv lineto 0 pnsv rlineto
+pnsh neg 0 rlineto @2 @1 pnsv add lineto}{pnlh pnlv moveto pnsh 0 rlineto
+0 pnsv rlineto @2 pnsh add @1 pnsv add lineto pnsh neg 0 rlineto
+0 pnsv neg rlineto}ifelse}ifelse
+closepath fill}if @2 @1 grestore moveto}ifelse}bdf
+/gw{/pnm fg 3 get fg 4 get div def}bdf
+/lw{fg exch 4 exch put fg exch 3 exch put gw pnsv pnsh pen}bdf
+/barc{/@1 xdf/@2 xdf/@3 xdf/@4 xdf/@5 xdf
+/@6 xdf/@7 xdf/@8 xdf gsave
+@5 @7 add 2 div @6 @8 add 2 div translate newpath 0 0 moveto
+@5 @7 sub @6 @8 sub mtx currentmatrix pop scale @1{newpath}if
+0 0 0.5 @4 @3 arc @4 @3 sub abs 360 ge{closepath}if
+mtx setmatrix @2 doop grestore}bdf
+/ar{dup 0 eq barc}bdf
+/ov{0 exch 360 exch true barc}bdf
+/rc{dup/@t xdf 0 eq{4 copy 3 -1 roll eq 3 1 roll eq and{pnsv 2 div sub exch pnsh 2 div sub exch 4 2 roll pnsv 2 div add exch pnsh 2 div add exch
+/@t 1 def}if}if currentpoint 6 2 roll newpath 4 copy 4 2 roll exch moveto 6 -1 roll lineto lineto lineto closepath @t doop moveto}bdf
+/mup{dup pnsh 2 div le exch pnsv 2 div le or}bdf
+/rr{/@1 xdf 2. div/@2 xdf 2. div/@3 xdf
+/@4 xdf/@5 xdf/@6 xdf/@7 xdf
+@7 @5 eq @6 @4 eq @2 mup or or{@7 @6 @5 @4 @1 rc}
+{@4 @6 sub 2. div dup @2 lt{/@2 xdf}{pop}ifelse
+@5 @7 sub 2. div dup @2 lt{/@2 xdf}{pop}ifelse
+@1 0 eq{/@2 @2 pnsh 2 div 2 copy gt{sub def}{0 pop4}ifelse}if
+currentpoint newpath
+@4 @6 add 2. div @7 moveto
+@4 @7 @4 @5 @2 arcto pop4
+@4 @5 @6 @5 @2 arcto pop4
+@6 @5 @6 @7 @2 arcto pop4
+@6 @7 @4 @7 @2 arcto pop4
+closepath @1 doop moveto}ifelse}bdf
+/pr{gsave newpath/pl{exch moveto/pl{exch lineto}def}def}bdf
+/pl{exch lineto}bdf
+/ep{dup 0 eq{{moveto}{exch lin}{}{(%%[|1|]%%)= flush}pathforall
+pop grestore}{doop grestore}ifelse currentpoint newpath moveto}bdf
+/gr{64. div setgray}bdf
+/savescreen{ns not{/ns true def systemdict/currentcolorscreen known{currentcolorscreen/pkspf xdf/pkrot xdf/pkfreq xdf/pyspf xdf/pyrot xdf/pyfreq xdf/pmspf xdf/pmrot xdf/pmfreq xdf
+/pcspf xdf/pcrot xdf/pcfreq xdf}{currentscreen/sspf xdf/srot xdf/sfreq xdf}ifelse}if}bdf
+/restorescreen{/ns false def systemdict/setcolorscreen known{pcfreq pcrot/pcspf load pmfreq pmrot/pmspf load pyfreq pyrot/pyspf load
+pkfreq pkrot/pkspf load setcolorscreen}{sfreq srot/sspf load setscreen}ifelse}bdf
+/pat{savescreen sa8 
+copy pop 9.375 pa por not{90 add}if{1 add 4 mul cvi sa8 exch get exch 1 add 4 mul cvi 7 sub bitshift 1 and}setscreen exch not{gr}{pop}ifelse}bdf
+/sg{restorescreen gr}bdf
+/cpat{savescreen 10 2 roll 7 -1 roll sa8 copy pop 9.375 pa por not{90 add}if{1 add 4 mul cvi sa8 exch get exch 1 add 4 mul cvi 7 sub bitshift 1 and}8 -1 roll sb8 copy pop 9.375 pa por not{90 add}if{1 add 4 mul cvi sb8
+exch get exch 1 add 4 mul cvi 7 sub bitshift 1 and}9 -1 roll sc8 copy pop 9.375 pa por not{90 add}if{1 add 4 mul cvi sc8 exch get exch 1 add 4 mul cvi 7 sub bitshift 1 and}10 -1 roll sd8 copy pop 9.375 pa por not{90 add}if{1 add 4 mul cvi sd8
+exch get exch 1 add 4 mul cvi 7 sub bitshift 1 and}psuedo1 dsc 4{4 -1 roll 1 exch 64 div sub}repeat mysetcmykcolor pop pop}bdf
+systemdict/setcolorscreen known statusdict/processcolors known and{/psuedo1 lnop bdf/dsc/setcolorscreen load def}{/psuedo1{16{pop}repeat sa8 copy pop 9.375 pa por not{90 add}if{1 add 4 mul cvi sa8 exch get exch 1 add 4 mul cvi 7 sub bitshift 1 and}}bdf
+/bwsc{setscreen dup gr 0 exch 0 exch 64 exch 64 exch 64 exch}bdf/dsc/bwsc load def
+}ifelse
+systemdict/setcmykcolor known{/mysetcmykcolor /setcmykcolor load def}{/mysetcmykcolor{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf}ifelse
+/dc{transform round .5 sub exch round .5 sub exch itransform}bdf
+/sn{userdict/smooth4 known}bdf
+/x8{3 bitshift}bdf
+/x4{2 bitshift}bdf
+/d4{-2 bitshift}bdf
+/d8{-3 bitshift}bdf
+/rb{15 add -4 bitshift 1 bitshift}bdf
+/db{/@7 save def/@1 xdf/@2 xdf/@3 xdf/@4 xdf/@5 xdf/@6 @5 @3 4 add mul def
+dc translate scale/xdbit 1 1 idtransform abs/ydbit exch def abs def{0 0 1 ydbit add 1 10 rc clip}if
+@1 0 eq @1 4 eq or{currentrgbcolor 1 setgray ydbit 0 1 ydbit add 1 2 rc setrgbcolor}if
+@1 3 eq @1 7 eq or{1 setgray}{currentrgbcolor 2 index eq exch 2 index eq and exch pop{0 setgray}if}ifelse/@9 @1 0 eq @1 1 eq @1 3 eq or or dbinvertflag xor def/@13 @6 def
+@2 fBitStretch or{/@10 @4 x4 def/@11 @3 x4 def/@12 @10 rb def/@13 @12 @11 mul def/@15 1 1 dtransform abs/calcY 1 index def round cvi/@14 exch def
+abs/calcX 1 index def round cvi scaleby96 not{1 add}if def/@16 @15 rb def/@17 @16 @14 mul def}if
+sn @13 60000 lt and @2 fBitStretch or and{mtx currentmatrix dup 1 get exch 2 get 0. eq exch 0. eq and @17 60000 lt and fBitStretch and{@16 3 bitshift @14 @9 [calcX 0 0 calcY 0 0]{@17 string @13 string
+currentfile @6 string readhexstring pop 1 index @4 @3 @5 @12 @2 smooth4
+@10 @11 @12 dup string 5 index @15 @14 @16 dup string stretch}imagemask}{@12 x8 @11 @9 [@10 0 0 @11 0 0]{@13 string
+currentfile @6 string readhexstring pop 1 index @4 @3 @5 @12 @2 smooth4}imagemask}ifelse}{@5 3 bitshift @3 4 add @9 [@4 0 0 @3 0 2]{currentfile @6 string readhexstring pop}imagemask}ifelse
+@7 restore}bdf
+systemdict/setcmykcolor known{/psuedo lnop bdf/di/colorimage load def}{/routines[{.3 mul add 1}bind{.59 mul add 2}bind{.11 mul add round cvi str exch i exch put/i i 1 add def 0 0}bind]def
+/psuedo{/i 0 def 0 exch 0 exch{exch routines exch get exec}forall pop pop str}bdf/bwi{pop pop image}bdf/di/bwi load def}ifelse
+/cdb{/@7 save def/@1 xdf/@2 xdf/@3 xdf/@4 xdf/@5 xdf
+systemdict/setcmykcolor known not{dc}if translate scale /@6 xdf
+/@18 @5 dup 60000 ge{pop 60000}if string def @6 not{/str @18 0 @18 length 3 idiv getinterval def}if @4 @3 8 [@4 0 0 @3 0 0]@6{{currentfile @18 readhexstring pop}image}{{currentfile @18 readhexstring pop psuedo}false 3 di}ifelse @7 restore}bdf
+/wd 16 dict def
+/mfont 14 dict def
+/mdf{mfont wcheck not{/mfont 14 dict def}if mfont begin xdf end}bdf
+/cf{{1 index/FID ne{def}{pop pop}ifelse}forall}bdf/rf{/@1 exch def/@2 exch def
+FontDirectory @2 known{cleartomark pop}{findfont dup begin dup length @1 add dict begin
+cf{/Encoding macvec def}{Encoding dup length array copy/Encoding exch def
+counttomark 2 idiv{Encoding 3 1 roll put}repeat}ifelse
+pop
+exec currentdict end end @2 exch definefont pop}ifelse}bdf
+/bmbc{exch begin wd begin
+/cr xdf
+save
+CharTable cr 6 mul 6 getinterval{}forall
+/bitheight xdf/bitwidth xdf
+.96 div/width xdf
+Gkernmax add/XOffset xdf Gdescent add/YOffset xdf/rowbytes xdf
+rowbytes 255 eq{0 0 0 0 0 0 setcachedevice}
+{Gnormsize dup scale
+width 0 XOffset YOffset bitwidth XOffset add bitheight YOffset add
+setcachedevice
+rowbytes 0 ne{
+XOffset YOffset translate newpath 0 0 moveto
+bitwidth bitheight scale
+sn{
+/xSmt bitwidth x4 def
+/ySmt bitheight x4 def
+/rSmt xSmt rb def
+rSmt x8 ySmt true
+[xSmt 0 0 ySmt neg 0 ySmt]
+{rSmt ySmt mul string CharData cr get
+1 index bitwidth bitheight rowbytes rSmt tso smooth4}
+}{rowbytes 3 bitshift bitheight 4 add true
+[bitwidth 0 0 bitheight neg 0 bitheight 2 add]
+{CharData cr get}
+}ifelse
+imagemask
+}if
+}ifelse
+restore
+end end
+}bdf
+/bb{.96 exch div/Gnormsize mdf 2 index
+/Gkernmax mdf 1 index/Gdescent mdf
+3 index div 4 1 roll
+2 index div 1. 5 2 roll
+exch div 4 1 roll
+4 array astore/FontBBox mdf
+}bdf
+/cdf{mfont/CharData get 3 1 roll put}bdf
+/bf{
+mfont begin
+/FontType 3 def
+/FontMatrix [1 0 0 1 0 0] def
+/Encoding macvec def
+/MFontType 0 def
+/BuildChar/bmbc load def
+end
+mfont definefont pop
+}bdf
+/wi LW 1 eq{{gsave 0 0 0 0 0 0 0 0 moveto lineto lineto lineto closepath clip stringwidth grestore}bind}{/stringwidth load}ifelse def
+/aps{0 get 124 eq}bdf
+/xc{s75 cvs dup}bdf
+/xp{put cvn}bdf
+/scs{xc 3 67 put dup 0 95 xp}bdf
+/sos{xc 3 79 xp}bdf
+/sbs{xc 1 66 xp}bdf
+/sis{xc 2 73 xp}bdf
+/sob{xc 2 79 xp}bdf
+/sss{xc 4 83 xp}bdf
+/dd{exch 1 index add 3 1 roll add exch}bdf
+/smc{moveto dup show}bdf
+/ndf2{udf{dup /FontType get 0 eq{/FDepVector get{dup /FontType get 0 eq{ndf2}{dup /df2 known{begin df2 0 null put end
+}{pop}ifelse}ifelse}forall}{/df2 known{dup begin df2 0 null put end}if}ifelse}{pop}ifelse}bdf
+/kwn{FontDirectory 1 index known{findfont dup ndf2 exch pop}}bdf
+/gl{1 currentgray sub setgray}bdf
+/newmm{dup /FontType get 0 eq{dup maxlength dict begin{1 index/FID ne 2 index/UniqueID ne and{def}{pop pop}ifelse}forall currentdict end
+dup /FDepVector 2 copy get[exch 6 index exch 6 index exch{newmm 3 1 roll}forall pop pop] put dup
+}{/mfont 10 dict def mfont begin/FontMatrix [1 0 0 1 0 0] def
+/FontType 3 def/Encoding macvec def/df 1 index def/df2 1 array def/FontBBox [0 0 1 1] def/StyleCode 2 index def
+/mbc{bcarray StyleCode get}def/BuildChar{exch begin	wd begin/cr exch def/cs s1 dup 0 cr put def df /MFontType known not{
+df2 0 get null eq{df dup length 2 add dict begin{1 index/FID ne 2 index/UniqueID ne and{def}{pop pop}ifelse}forall
+/StrokeWidth 1 0 FontMatrix idtransform pop dup nlw mul pys div ps div exch 0.012 mul 2 copy le{exch}if pop def/PaintType 2 def currentdict end
+/q exch definefont df2 exch 0 exch put}if}if mbc exec end end}def end mfont}ifelse
+3 index exch definefont exch pop}bdf
+/mb{dup sbs kwn{0 2 index findfont newmm exch pop exch pop exch pop}ifelse sfd}bdf
+/mo{dup sos kwn{2 2 index findfont newmm exch pop exch pop exch pop}ifelse sfd}bdf
+/ms{dup sss kwn{4 2 index findfont newmm exch pop exch pop exch pop}ifelse sfd}bdf
+/ou{dup sos kwn{mfont/df2 known{mfont begin df2 0 null put end}if 3 2 index findfont newmm exch pop exch pop exch pop}ifelse sfd}bdf
+/su{dup sss kwn{mfont/df2 known{mfont begin df2 0 null put end}if 5 2 index findfont newmm exch pop exch pop exch pop}ifelse sfd}bdf
+/ao{/fmv true def ou}bdf/as{/fmv true def su}bdf
+/vo{/fmv false def ou}bdf/vs{/fmv false def su}bdf
+/c{currentrgbcolor dup 4 1 roll eq 3 1 roll eq and/gray xdf}bdf
+/bcarray[{/da .03 def df setfont gsave cs wi 1 index 0 ne{exch da add exch}if grestore setcharwidth
+cs 0 0 smc da 0 smc da da smc 0 da moveto show}bind dup{/da 1 ps div def df setfont gsave cs wi 1 index 0 ne{exch da add exch}if grestore setcharwidth
+cs 0 0 smc da 0 smc da da smc 0 da smc c gray{gl}{1 setgray}ifelse da 2. div dup moveto show}bind
+{df setfont gsave cs wi grestore setcharwidth c gray{gl}{currentrgbcolor 1 setgray}ifelse cs 0 0 smc df2 0 get setfont
+gray{gl}{4 1 roll setrgbcolor}ifelse 0 0 moveto show}bind
+{/da 1 ps div def/ds .05 def/da2 da 2. div def df setfont gsave cs wi 1 index 0 ne{exch ds add da2 add exch}if grestore setcharwidth
+cs ds da2 add .01 add 0 smc 0 ds da2 sub translate 0 0 smc da 0 smc da da smc 0 da smc c gray{gl}{1 setgray}ifelse da 2. div dup moveto show}bind
+{/da .05 def df setfont gsave cs wi 1 index 0 ne{exch da add exch}if grestore setcharwidth c cs da .01 add 0 smc 0 da translate
+gray{gl}{currentrgbcolor 1 setgray 4 -1 roll}ifelse 0 0 smc gray{gl}{4 1 roll setrgbcolor}ifelse df2 0 get setfont 0 0 moveto show}bind]def
+/st{1000 mul usertime add dup 2147483647 gt{2147483647 sub}if def}bdf
+/the{usertime sub dup 0 lt exch -2147483648 gt and}bdf
+/6a 6 array def
+/2a 2 array def
+/3q 3 array def
+/qs{3 -1 roll sub exch 3 -1 roll sub exch}bdf
+/qa{3 -1 roll add exch 3 -1 roll add exch}bdf
+/qm{3 -1 roll 1 index mul 3 1 roll mul}bdf
+/qn{6a exch get mul}bdf
+/qA .166667 def/qB .833333 def/qC .5 def
+/qx{6a astore pop
+qA 0 qn qB 2 qn add   qA 1 qn qB 3 qn add
+qB 2 qn qA 4 qn add   qB 3 qn qA 5 qn add
+qC 2 qn qC 4 qn add   qC 3 qn qC 5 qn add}bdf
+/qp{6 copy 12 -2 roll pop pop}bdf
+/qc{exch qp qx curveto}bdf
+/qi{{exch 4 copy 2a astore aload pop qa .5 qm newpath moveto}{exch 2 copy 6 -2 roll 2 qm qs 4 2 roll}ifelse}bdf
+/qq{{qc 2a aload pop qx curveto}{exch 4 copy qs qa qx curveto}ifelse}bdf
+/pt{currentpoint newpath moveto}bdf
+/qf{/fillflag true def}bdf
+/ec{dup 4 and 0 ne{closepath}if 1 and 0 ne{0 doop}if grestore currentpoint newpath moveto/fillflag false def}bdf
+/eu{currentpoint fp{0 ep}{grestore newpath}ifelse moveto/fillflag false def}bdf
+/bp{currentpoint newpath 2 copy moveto}bdf
+/ef{gsave fillflag{gsave eofill grestore}if}bdf
+/sm{0 exch{@1 eq{1 add}if}forall}bdf
+/lshow{4 1 roll exch/@1 exch def{1 index wi pop sub 1 index sm dv 0 @1 4 -1 roll widthshow}{1 index wi pop sub
+1 index dup sm 10 mul exch length 1 sub add dv dup 10. mul 0 @1 4 -1 roll 0 6 -1 roll awidthshow}ifelse}bdf
+/setTxMode{sa 9 2 index put exch not{3 eq{1}{0}ifelse setgray}{pop}ifelse}bdf
+/SwToSym{{}mark false/Symbol/|______Symbol 0 rf 0 sa 6 get 0 ne{pop 1}{sa 7 get 0 eq{pop 2}if}ifelse
+sa 1 get 0 ne/|______Symbol
+sa 4 get 0 ne{vs}{sa 3 get 0 ne{vo}{fnt}ifelse}ifelse}bdf
+/mc{0 3 1 roll transform neg exch pop}bdf
+/ul{dup 0 ne sa 2 get 0 ne and{gsave 0 0
+/UnderlinePosition kif{mc}{ps -10 div}ifelse/UnderlineThickness kif{mc}{ps 15 div}ifelse
+abs setlinewidth neg rmoveto
+sa 4 get 0 ne{gsave currentlinewidth 2. div dup rmoveto currentpoint newpath moveto
+2 copy rlineto stroke grestore}if
+sa 3 get sa 4 get or 0 ne{gsave currentrgbcolor dup 4 1 roll eq 3 1 roll eq and{gl}{1 setgray}ifelse 2 copy rlineto stroke grestore rlineto strokepath nlw pys div setlinewidth}{rlineto}ifelse
+stroke grestore}{pop}ifelse}bdf
+/sgt{2 copy known{get true}{pop pop false}ifelse}bdf
+/kif{currentfont dup/FontMatrix get exch/FontInfo sgt{true}{currentfont/df sgt
+{dup/FontInfo sgt{3 1 roll/FontMatrix get mtx concatmatrix exch true}{pop pop pop false}
+ifelse}{pop pop false}ifelse}ifelse{3 -1 roll sgt{exch true}{pop false}ifelse}{false}ifelse}bdf
+/blank/Times-Roman findfont/CharStrings get/space get def
+/macvec 256 array def
+/NUL/SOH/STX/ETX/EOT/ENQ/ACK/BEL/BS/HT/LF/VT/FF/CR/SO/SI
+/DLE/DC1/DC2/DC3/DC4/NAK/SYN/ETB/CAN/EM/SUB/ESC/FS/GS/RS/US
+macvec 0 32 getinterval astore pop
+macvec 32/Times-Roman findfont/Encoding get
+32 96 getinterval putinterval macvec dup 39/quotesingle put 96/grave put
+/Adieresis/Aring/Ccedilla/Eacute/Ntilde/Odieresis/Udieresis/aacute
+/agrave/acircumflex/adieresis/atilde/aring/ccedilla/eacute/egrave
+/ecircumflex/edieresis/iacute/igrave/icircumflex/idieresis/ntilde/oacute
+/ograve/ocircumflex/odieresis/otilde/uacute/ugrave/ucircumflex/udieresis
+/dagger/degree/cent/sterling/section/bullet/paragraph/germandbls
+/registered/copyright/trademark/acute/dieresis/notequal/AE/Oslash
+/infinity/plusminus/lessequal/greaterequal/yen/mu/partialdiff/summation
+/product/pi/integral/ordfeminine/ordmasculine/Omega/ae/oslash
+/questiondown/exclamdown/logicalnot/radical/florin/approxequal/Delta/guillemotleft
+/guillemotright/ellipsis/blank/Agrave/Atilde/Otilde/OE/oe
+/endash/emdash/quotedblleft/quotedblright/quoteleft/quoteright/divide/lozenge
+/ydieresis/Ydieresis/fraction/currency/guilsinglleft/guilsinglright/fi/fl
+/daggerdbl/periodcentered/quotesinglbase/quotedblbase/perthousand/Acircumflex/Ecircumflex/Aacute
+/Edieresis/Egrave/Iacute/Icircumflex/Idieresis/Igrave/Oacute/Ocircumflex
+/apple/Ograve/Uacute/Ucircumflex/Ugrave/dotlessi/circumflex/tilde
+/macron/breve/dotaccent/ring/cedilla/hungarumlaut/ogonek/caron
+macvec 128 128 getinterval astore pop
+{}mark true/Courier/|______Courier 0 rf
+{/Metrics 21 dict begin/zero 600 def/one 600 def/two 600 def/three 600 def/four 600 def/five 600 def/six 600 def/seven 600 def/eight 600 def
+/nine 600 def/comma 600 def/period 600 def/dollar 600 def/numbersign 600 def/percent 600 def/plus 600 def/hyphen 600 def/E 600 def/parenleft 600 def/parenright 600 def/space 600 def
+currentdict end def currentdict/UniqueID known{/UniqueID 16#800000 def}if/FontBBox FontBBox 4 array astore def}mark true/Helvetica/|______Seattle 1 rf
+/oldsettransfer/settransfer load def
+/concatprocs{/proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def
+newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx}def
+/settransfer{currenttransfer concatprocs oldsettransfer}def
+/PaintBlack{{1 exch sub}settransfer gsave newpath clippath 1 setgray fill grestore}def
+/od{(Rvd\001\001\000\000\177) fg copy pop txpose
+1 0 mtx defaultmatrix dtransform exch atan/pa exch def
+newpath clippath mark
+{transform{itransform moveto}}{transform{itransform lineto}}
+{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform
+{itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}}
+{{closepath}}pathforall newpath counttomark array astore/gc xdf pop ct 39 0 put
+10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack}if
+statusdict/processcolors known{statusdict begin processcolors end 4 eq{/4colors true def}if}if}bdf
+/cd{}bdf
+/op{/sfl false def systemdict/currentcolorscreen known{dcfreq dcrot/dcspf load dmfreq dmrot/dmspf load dyfreq dyrot/dyspf load
+dkfreq dkrot/dkspf load setcolorscreen}{freq rot/spf load setscreen}ifelse savescreen
+/ns false def/pm save def}bdf
+/cp{not{userdict/#copies 0 put}if ma 0 gt{{t1 the{exit}if}loop}if{/copypage load exec}{/showpage load exec}ifelse pm restore}bdf
+/px{0 3 1 roll tp tt}bdf
+/psb{/us save def}bdf
+/pse{us restore}bdf
+/ct 40 string def
+/nc{currentpoint initclip newpath gc{dup type dup/arraytype eq exch/packedarraytype eq or{exec}if}
+forall clip newpath moveto}def
+/kp{ct 0 2 index length 2 index 39 2 index put getinterval copy cvx exec mx3 currentmatrix pop}bdf
+end
+LW 1 eq userdict/a4small known not and{/a4small
+[[300 72 div 0 0 -300 72 div -120 3381]
+280 3255
+{statusdict/jobstate (printing) put 0 setblink
+margins
+exch 196 add exch 304 add 8 div round cvi frametoroket
+statusdict/jobstate (busy) put
+1 setblink}
+/framedevice load
+60 45{dup mul exch dup mul add 1.0 exch sub}/setscreen load
+{}/settransfer load/initgraphics load/erasepage load]cvx
+statusdict begin bind end readonly def}if
+md begin/bigs[lnop userdict/letter known{/letter load}{lnop}ifelse userdict/legal known{/legal load}{lnop}ifelse userdict/a4 known{/a4 load}{lnop}ifelse userdict/b5 known{/b5 load}{lnop}ifelse 
+lnop lnop lnop /tab load/a3Size load]def
+/smalls[lnop userdict/lettersmall known{/lettersmall load}{userdict/note known{/note load}{lnop}ifelse}ifelse
+userdict/legal known{/legal load}{lnop}ifelse userdict/a4small known{/a4small load}{lnop}ifelse 
+userdict/b5 known{/b5 load}{userdict/note known{/note load}{lnop}ifelse}ifelse lnop lnop lnop /tab load/a3Size load]def end
+systemdict/currentpacking known{setpacking}if
+{currentfile eexec} ( %endeexec) ok userdict/stretch known not and checkload
+373A767D4B7FD94FE5903B7014B1B8D3BED02632C855D56F458B118ACF3AF73FC4EF5E81F5749042B5F9CF1016D093B75F250B7D8280B2EACE05A37037F7BDF6E12226D7D4E2DF2C52FAFD5FD40FE72A0D3AC4BD485D8369D4C87636E920D1DAF222D92155A9CB1667E715F0B82799B37CC8F5B32B74B39CF494536DC39C7EF04A7BCB29E2CEC79073CADCCFB23B4AA1363F876F5121B618071B7B4EB1E5DE75FAA2368A3E5DB2B198623AFE92AE9484270FE7F57A850E88C0D3EEA156611C91D8E480D4370B025CCA6929A2BF40AD3D01B2CB7EE6DFB46E12A830542337F7819B67F9765210F76DB06F34DA5B13A11759305C582E16D2B854939F6D9121F2A4F285282F5DCD3D15896D121E3D6F5BE79E087451BB0ED233CDBEF090D3B4AC2DC34B97E70C61D95FB072B8C12D2ABD843520949A39DCF99E2C1AA8FBCD025E47E0A82A8D96E75BAF40F52AD402495BBD4DE0F356C8B14E764874E639C9F045A0D1908EC6456EB6C5B8A6F826192F767EF2C55A21C58F5F9CC1F59247B55F2387828C7FE89D5E7D8484D1BC86CB6673BDBE4FE17DD9BDE95224FE645136F41330BF155A4DDE1B0A32233BF471CE58FBC660DC7E641B0A0D30018454E2191C414A3011FF3FED1C0D88FE1FF9F75DCC456D097947226FBEC92509146D3A4CFFC0471B31C53222ED9DD88566F60F6C0D705AD79DACF53B070026F083ED28B5CF757AAA0A169F6F320A75E9D2ED50ABD939AF85B6346C2ADB25D168F10508E1516D194C635E6B187FADEA0829DBF0390C0F003F0265E215BC96CA3CC13D4A8E01570BE193CA75A620728CD275ACF1986EFFB3A13419FE55EA7C4467B7E7EEDC1FC29C9F8C46A557D2CCDB914EF7B93E7530D555DFC2398AFC68CAD991F062EF85BAA1884EC166C7C5DF8543666D8C41BE267D706BD1588F1F662F705CAE4D29DC38EF66BFAA89470D8A099B6F1B4587F7B024412276106FCD3EB5AE17A5D1DF1781992DC40EA0A992F706F701304CEA9D9073E7A74F1E687D81C3E5841D31CF86855BAAAD9B5D30317C75150A857C6B114735315CDD1AEF36C26BBB0645499406DEE2F24B3B1C72FEC97C7BA31AA2CDAB25418BB1DC4C7E4757F1D625087B0FD0300C03A65F2A72CE734925735277E034CDCF599129679F70CC8B66E03878851DB75041F275E1E5761F3EC753BE1359CA364A22047AE4886217F9259FE19FF5B116E8019B98B143114B313E8BEF87EC949D85C82E0812E6F50525E73890AF362CC8EE8A85F4197E6AC18638EF12E56A808D439AF1BFD363F140314BF4E534485C42F1856688CC35288E8D770120A420FB9F1FCF8AE8BD6D6156CC23E6C51119FE4DE1B68C9DF3487E9974BF9ED31F8D3CE93FF101867319F2FF492D5D398B4F09A66F2F55BCAB34B99173B7EE89039D00DD21A7B3A52E9F028F8301B5FC12D409412E064513BC579AAC498F577EA8ECD1FE3E42DC3CC320786C7B00194FEDF344402C33FC492D4BA86992B01683F440220FFE756BC88A94223D316078D69D33560E8EAB76B24CB7AA4320CF435593D76F624324ABE00B5587A4F283C725EA24567133F25F472B5E2E4474DDB5A16AC5F2DF32350395D3E3892FE361F4D5C9A610C654C9227614FBBAFF3356A90A2266E00F66234061075491571A65616211257F160000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+ %endeexec
+
+{currentfile eexec} ( %endeexec) ok userdict/smooth4 known not and checkload
+F94E00EE41A71C59E5CAEED1EDBCF23D1DBA1EE99B9BB356492923BD8B1BA83A87CEB0E07377A31FD6241E814681118E17DC7CACE570399506E6E441B871B6043831BD03EFC11DBBD8001EE2FF8CFBD485065D455A2E15AC36F1A84AD8789FA6461199C7CD14CB9FD64D4B06452B7FC0A8FC263F70F1CCB893295D4DE70ADAB771C0F84396FA98C60B11DA02ABA157298DF0A23621853BEF167443A985ADC09BEFFD51CB4D29179E2B34609EF38A49DA61F4BFC256A3DE0732D7D29754A194857B9C9E9971227AA1DD0611FBB10E44E5FF66C062D9C24ED3290529330BC317825E876929582DB0E39B9FC5EFD20CC1D4F94920EB9C534D0DA90DE70D25BC7287319CF28602B3F46633C242CAFC8905E960317E3C2FA20AB8DB06ADBAF292FC7BA2CA14EE65DF28B99CC11666B70AD33E8E1D57D63D4B89ECC615AE5747C1CA752C833D8D6DE54CD4A0350B44310555CE3BD2C615ADD27B634CDB350AF3A432CE78AACD2909A5B586F666CD87919A36DB1CBE86B3CE281DFD01CD7E1B8A18A4B415CECBFF79A5C4390A15EA77D14D6BE12BAB5A8268C3F286D0590060647CABED674443CD258F11415E866AB330A251691B61F2422A61AFE59B6B4FBDCF85ED9BA0F8E483C034089E6877FF5923698D3A0DC0EED6B9CFD32DF0839BC4EA5F6D1FCB6DD0920391E57E84745131D02D100179F4E0A68EC0A5FF6680A6F463D038B04AF63FFA13D743B995A26A743C26D387209023C91DE43DF047A16F328AC9DDC08573B38BE9EA341EA16C78EC32F3A1B36B90D95A50610F4D050EC1C33497F3F3A81A1B4C8BEF0BA84EE2FAA32DC112DAC490AF53E1749C4A0D866CAF7B893E52383B0D38065C333FB122B700D7246F7EE87D942AE3DB5C1DD77E9E76C80CC5AD63D28DFED0E229CE604673F78CD47F258FDF5BF3A3EAEC5C9BC8E482D8DBA9D268A35DA8C095A690679ED2123E8B8F5E4826FA3B199EAA5D482D4B6AA86572E387CECEB7149C8947F41D6339328A748A17F8C4AD3B0555F1E409450BA0C564F1F488BB5096EB003568D4D5EF6489897E27409547D0EE4487D30184793B0F27BD265A64BDB3EA6761569DA955620C612E718677B77D6D81B999C6298877AFE0D1D6F6F358377A8BD2402F669C64B972B3A065EF7DD4BDEFFFE17E63DB8898FA6E69166B710AAD6BA2EA9AF61E4B8C8701638D4D6E4DFFFC192AEF6BC027095C4C72D748979675BA29FAF61E75343E14E61034602E5A79CD2519796ED6A9CC4EDEA46A9B59D4A807E786B5EE46F25B0360BC8E7C12D723122CDEEF247C9776F4C99C8EBED6828AA19744B5ADF0D07D95D98B3072372388D41B0FAB1CCE2775170679575ECDCA13B22A17FE9C6605C3445F58F1A829512DAB6C528F83580C8AA53C35D605F626F5AD0B7FC1EA87D69A835E3F53A1F450FB0AF42A5772F89D92A50D10F15BDBDA409F50C0B8AB93FE8A16D029DD8BB5C480D1466735ED4D9CAF637E5ECD6C2ECB6BF3B3EFBEE7AB936D2C568E3009D156B87CACB1FB3A48A70BC91B2EC35CC9147FFB1A524E2B2F2E4E2C1B12F1C1C63768BB95CD62FEC01CBA79B9FA282DD4DF49990F27FF8EE4E2DDE2F0ACD83BC9D4BE0090192C7A799967EC4DC2D63C0835E22D4C4B366D7FDCF3A05A4B53DF780F986EF25C79B665D5C00EFF7F17C0BB6D544F9D83A7FDAC47D9C5683A656011374253C918FF6EA64749DD971B2300DD5320033E01EC591F6318CCE94CE2B81C04322EC52B624E50643B52391CCD2AB56396A2AD8E2D3CA61B80D9D4CC363B2DF7863526958CDF3497E36648406C317E58EC563E7C26149A2A3C643ADFB39A8DD92974C6D2A2A9D7B71CDF3FEBBF32BB02E7B45CF53AAEAD5E963A4AA4AF9A149A08A4EC303D5F2369977E93F54897EEAD31B06C5845D63F49D65F8E5573962241A57CCD717CE6CA8C784A11192943616EA059B51BC38429E18D0121FCBB6FBD5D909B0D89E616C66DEF6A0F165A7030BD911A1B120468329CBB006C8D37720E531CF31E878CB4AAAC137633675C3D546F5162487AB35F470C042BDEB945E0F2532BF92AA6FD53434440221ECD3533A7AA89900CB19EFE2CD872DF8B7969AF0D3B72BF31DC5DD69CA6460966F61AB17CB507964098DBA3AF122EEC3128A9BAFE1034493F372B36BD1351205E9043A67C544402D8BCE24358C8A5CE33867A00794CF7097D59C88279A11EE9C854E7E7AAE881F9828C569D208F5F33375F59E9A3818CFA38AAD0CBFBA32F9F44A8BB79DE4C40E3886457C16DA4A27953AA1E99472E35F2323F0BAA5E37DC28CBA46FEFB73B190016055ADD4D27615D748499A0E1C4B8C7EC339C1C4D95A813A85918A8D01EEB485DDCDCEA6EA3F2C2A9D85C139CD90CCB352634F9AFE836BCAC0C274E352BA2071B5269D5DE4CCDE3FF990CBA974980C7332AE1545A9C60D5D1459D3AE95C1AC065733AF14FADB440A110DD539563B8D850CD0704C52F3F7CCCB53630D776560CBD22D8FF08F5B354487A171AEC15F5F54DE9CAB668BCAC573E788D92762EF63E76087005F4AC2D02E0CAC173C11BE62ACE5DC4D3374F2F9746C9981E125FF9AB8CAE76D13039E2C54DFD708E028A619EA1ED78E6B46F06DF0D0B74BBEDD8C190C7C0CEBDE8F7A4888CC36575313478DD2CFE392E9BB7B2416955D44B7024A3BA43FBF37293B386D64746D7748895411D243FAEC50638F2AA33337D7FA018ADDAC5835A0DDFAE99AD6299DFB4CA6872C59853E3AC12FC9E3D26629C5B49CF844C87B3C4BFBE3074E3A1CE6984758C20C661084381CD6B4582D84F19C0000B5FC0DCB42B567E396031601C095D7016283EBE5F13CD8A3A374A74DDBBABD36081149F8BC242085F2F7297CC97FD3B8BAD206D8AC9707A39ECCC7963B522E08DA391A1EF12DD4D746DBDDDCC0834F88160CF189A9645567CEC2F023A571AF0DFD15DB85B744C28C000DF53B05F8F210841F6E87A04F20C777B7C0BE6182BE2E90226E5301A12532A745F2FAAA81637CF11B78CD2B99A4D18B862D6C5DBD31793FB16A2D9AAD376D4484D75AA833D0068B1D34DB74E3302480854E3B5484D8A47E39A89A2FA927BC3641EA7F8E004FDE4C2F08D40D99F1ACB47CAF6887629BF6DFE12968D297596D28CE0CF148B12E7DCB49FB94F5ADBD214C3A6CE1E249831BA9EB8A189F2CE1ABE39A7B537253E369A508A2AF2ADB9463F9B56BBBFF31D535FF997F537C6675C196E7ECBD493F652FA7CC6D9C1CA3379BFDB5AF7513C6E834054494296B91A6EE800114363D5D5D0759F41B4DECB653B9DE3E94583579EF549ED5F3FAFB12661ABC0C57A332406517ED3454EDED34B386C60F78DC976266E0EAF54FC245FB0E3EFC8016236436B599C1C97A8C5E0AC8F7836161873C71F01ED9CC25C236420F41FD8277993D3959205912FA0927B59E3DAE7377D82079447D6E41EE5AEC0DFFF79AF8F4ED47F17EE708FEA45877860D56F8CBCE65A061E8E1CA4A5FBAF0E13429A7F0ADB6F178FA449F46CC539BBC0107E3A53B1C362A04B20E6D721E7E6E1E4976A11DDC98C7614D22B53DFBB6DAE533AC9BE882021A735C30DAA4A44AED09F49A390E8CFF59BD9C30667AF21B03EC5CEBD5C2C3AA2769E8D714191A48E7DDF50B13D1560E82EFB65FCE601AE9E8C351FBA1DED80B7351314E7F9F9A784BFE3759B7E322A84E7B51F9DC5F5D9C8050CD79B27C0A4B0DD68A3C27A948AD6858E35B960D2DEA838C479CAEA83B1A912174ACB2100E55E7A14892D7A9B3711FF0B20065C1995B49E1F23464A92DD140642E3A7B1973849E64D1A3CF60000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+ %endeexec
+
+%%EndProcSet
+
+%%EndProlog
+%%BeginDocumentSetup
+md begin
+F sgd
+svsc
+
+T T 0 0 4654 3193 -178 -171 4832 3364 70 300 300 3 F F F F T T T F psu
+(roy; document: PAG95_F1-Layer#1)jn
+0 mf
+od
+%%EndDocumentSetup
+%%Page: ? 1
+op
+0 0 4654 3193 fr
+0 0 xl
+1 1 pen
+0 0 gm
+(nc 0 0 0 0 6 rc)kp
+0 setlinecap
+currentscreen
+3 1 roll pop pop 60 45 3 -1 roll setscreen
+(nc 0 0 4654 3193 6 rc)kp
+64 gr
+1024 507 3482 2699 112.5 112.5 1 rr
+8 8 pen
+0 gr
+1024 507 3482 2699 117 117 0 rr
+64 gr
+750 513 968 2697 109 109 1 rr
+13 13 pen
+0 gr
+750.5 513.5 967.5 2696.5 118.5 118.5 0 rr
+64 gr
+808 800 913 2554 1 rc
+891 801 gm
+F 1 setTxMode
+1 fs
+bu fc
+type42known not downloadOK and{userdict/TrueDict known{TrueDict/initer known not}
+{true userdict begin/TrueDict 8 dict dup /version 27 put def end}ifelse}{false}ifelse{currentfile eexec}exch( %endeexec)exch checkload
+1861AEDAAA5472E4FDE5287D4C4E53EBA565E192AC8F362DA1CD77A9FCA31B071701B025F68DCF4C631ED8451E912BED309E5278415CE3E471ECE22F5E04FE2BB3D1A2D8230D516E93FA22D5104354FA6E4E3829811FF537A9F7B7F5016FF9A084424DAB04EDCBABC563D12827F1CC491C3293A798745679001AC866250518DB0B49285770FEBC68DF6E17BB50AF9CAFBEF120D620DF592619702193CA3AADE920B625BAA080FB2A726FE91651E9FB3EEE976A2287F2F027FEB50AACB5EF681A16162D2AE14E15D04ADECF363381C4F3E35E8768A1E7914E4DC7650B2B47473ACC0C4DC14376DEAFC10A35F7DC679B5B39ED192974819103CFB23FBC6462980B3BE920C8475D031A56EC00FA233CA5F0F36CBEED798633E06C05E6C0EA120F2124B4F7EA89F3C1E0542A5EAC7E3F01F1C89AAF15F24E6FDC822ACE898B5FF00FBD5E6C4893C022DB038B738BA79525C6A7F403085861A572C26B5E2ADD44A076FB7B2E2C59D41A05FD307740C7EE200E00AB089C720398CBC3705C787BC015FBFDAC3EF229E8CF0FD6CE9137EFD1D8D68B327F7170099E3796EE38A79EA0063638D6B40639464A00A2CCB6496516A40196CA59C31CCEEECEE825EFF90A20864B269AFC6F452B262EF34E72D2C7F569254030D006DA7430F36BE07451B6F7311882E2248C360A56591F988746870C29FA3467DE2FB3F1208B988EFFCDE963789295930ADA06B83F49D42BAD98EA6A3D747B098CC0B1E07C7F8C05B0E2B0478E5BF4656512B9C2E6BC03E1BFBBABE9774880691C4D20C1152D9568A759DA0B1721E26FFE91F80EE62A98FDE3DCF8884834767BA45AB350BAFEAE18D135A6F1D0A61370396812FC6A03117FDEAB78FDC153F4E757B9C328FE919425CE1522AC45C73968D98FF8D0608F24C2CA0AE51B56803D6BE1DA5587AE71C72593436FFE5ADCF659EE48297CE4C9295C530AF5B12182C1040C5A78B7F8621B505F37A7FC4747D1D23C758E31C862BFB3C223591210C1D55A5F8912B1854881A467101DF113DD991230C0EBA85E94CC5246123556772BC7347D388564A82460F39A12B9BCE237AE4A00C2BD89B077C5B58CB555011ED569A5F3BA7FD204686677FAF5E13863A7225CDAB24952F686E1E9A92A06643831D182FE4E01AC26EE493F072592B158FD78212FF8E75920FBDED1EB6D168D387F4C9802721C16A398BF404B4B665893A324F4F08D766753D3E5336AB90BD18A96787F07ED67F6DF15F231C0ADB7D3CA0AD76CBCD4AB65EF56ED98F4FB511322C0749D30B85BF604D07173C97BE11F9E5E8EA1BBA697D7769F54BF8DC9410841A3524B42974F66DFDFB0DF4AA31AAA0527ECD0C44B7140220F3061ADD554B1BF684EDFC12A3AC05F883E2D6A185A5955E6AC272342E761C44BC379413F2369EE5533BEC2C8375136EAAAD22642F3CDF09D
+CF04FBD2460B6DC8615AF7A514A0D269FF0631AF9FE0BC30053832809695A953148CC9422C123EF919844852F2AC38412FC7A643356B06B87546FD38080D4B5150E0DE2DE3C8BE9109F9B69640E07CEB405F11A63A9444666CCF9025E74E5CEA386CFC038C70B51162B716504F31C113783134547554E748E3E712B1741A16F92ACC838485DFFC26C2991E7F2C937BBD7299B3A62D9682E6515BCC4F5930CCC560DDA4551B7A81F988A9B68155F654A5AF2D38C29F192D74702DDD63D73198A6C7F7F4CFF83C001876E7D165E2A5A34625D69CDC1D151D03BF45ECEC46EFD1D8A15B34A173C34C95C128668C1C4DD1F79B09D716C5FC82A6BD7CCD764A92A2C88B7FD84CF5EE778C6CE1EE4BA55C5E69BC880498EA0339A72F08E8DF764CDA37880B522791B6AD8C3A6F01F61FC873048CE72F3F9EA60639BEAFF23C5913D877E8065A2392E370D0774B438B969858CA62A008BA516E629136B7E27EDA1E46CD64BBAA8DEFF655A16CC5F1BDD6B660800B3815E1FEFF59462284C9B717DE1B5B1C9C883E46B79129D37F636B83D90ABD532C13E2648712824F87ABE8E9FF7653AF4E7837ED2A2179183EF9FD451D61702223E2CBE2304DC4D9A1B763C812A5575D10F468E6189AFB24ED061E96AB9EA3FC1E5DBB7E20142F27B90202852E654A153DE40AE78B4BACA4FFD773D82672062E79235579C492F9020C1D427E9B49D387C84178D1418105BC5055ECA0C9D35C931AFCAE03AD75F49197CC817AF9A4C99F34849B7D78CF7FF780A6136BB374ED81631994AD87F5C24540A050DB5EE2E54FFD495850DD6EEBB810B5564DE516210126AE4FEFC556ECCF26E9672C3979905CC92764B9D9DDABE289E17C236A94E1F19F4C50E334403F8163307403395DA75F03AB5C153775A1169FE21648B2EADEF25CFF6B97BEE0219BD363A1A7FCA1E6F9B0D41B44C635C28A42E76C89F5373FA2ADA955192F209D92AB0051A966C5B68A06B2427824B896E2A1501993171FF88A89EE13AE3F39BC87E8D08739A953376C37BA66D9D4A3A5C05AB987F9AAFD0C9F98D64AE46F8C7B9A7F1EC134970701E08EBE4254791DE842CF6967D101FD27C642B44906560456F9F7CCC802FB3FB7ED4A1BC3B274A4EF652B912D575A9BD9F39C33CD2F9142B32316DF11DEE6E500363D314328D2AB2339B6A0A7217C8971B9DB546C728B091D6B1F954EF1F5B9537F33A6BD49A9075C65D43B4F51B2C8B1BBDAA3B6C1471AD017B10037409E82C7665B39894157DEC02C187BB1D2C921FC89F976E65A5960D140871BFB631AA04BBDCF8EE0FC26A8F2580426CA6A347395664246B38F19F3EC2F21DA6AF6EADF997884415FFC8140BB91D683888B09DE172BC3210C6689C686B2559720256ABD0D758C3AF54568B463FC2468C5EA914F774E889E915C21491B29C63B8E5463657C
+19DB0E92F69954AA74A81AC6ED3C2A676C8833508181D9FA1D42621A060C85055682A65FD853500A5BF9D4D7A7571BCD6306A9E2113C7DD879F8F60054A7A3B08051EA7ACE1A8BF3B43962E6C1A6F5DBEA53D5AD767A8B17A751A2421A2D8FAF45DBD9EAA8E66640FB81304EA1DFB62C42D505EC9C2B05F3AFF2F7AF197CAFEDB940B1D2B3DD09D340EC18CA0E1D6CB9713EF437ED9C3ED3B7D7F3437C1F703CEF6F5AC0E834C04A34C3847A44C76B02B7EAC2AF0928F9CA50395BC961156F44F81B6B6E78C2A206340E9059999BD379DF5125E97C2AD1609B477B9B29B547424C35012A8F84D67DD38BB81B8215D4E376AF8C67144DA71839867CE1AB0A3B2EEBEA4E662DCF3CCCC17649AC1D31B5999085788AEC35FB764523C7C61A80C7E1BF0151FA18D283C0A9D885FB3DD2796073620572F7CED7CD0E0485D463308EE9A2AD39B2C20798BC6D9950F85823FE8E1BEC8C39D0146850793817B4A26D8937FBD05093E8D010985F7E28C67F7687C5BD0DF8B61032EA12DF4B1F735CBD52D461C9D88DA511175408925DC2EBDF60CF53A3348F0ED2E536876318A89C632C7A7EE0E79A7E97B9C26321728E39A737CE3DB5AD9C51EFB64288C7389FDBE286E6C993A88E7D56A0F9D3967E6675D0125473C4977145FB87FB4E5C2D17577E31F6096B6FA8E8FF6B375DE68ADC97B6F9F3DF3CE92629DE8C31D500AC964A996DF71C74016FFAA2E83B67F63147B673C9AAF9874BAB63B417FFAC3A43446A9318C51C24239C1F9656C9D8112A36000C76EA06FFD42037EEA314A3E04520B9F8DCA5434946AE6DC8D9D2E54D7BC794452AD81F1D8A10823464CF2C4C3AF1647D2103DB559B0A910A8611F2E0CA78C2CF58DCADFAE14490079A186B7811AFAE4D9A72AA46EE0F9EF3613481CD3F47480F271978747438ED5722BCF5DE8CBD4C0D3165331FC660C197BDFC333BDBBB9EA9D6B18D2BD549593E177C418ACABB3F419A651802D48CC6CABBD2B2EF1C6228AA3F3601087E55C26F603AD428EC0A40D0E95417E1CB6B8C14E366D0E28C956DFA769FE30507D26E8F0C2937419F453871265E349D3F35FCA0C69CC0211760ED105F77ADCCD9CD25A36133DC0178CFF9A27C597C703596FB4E23AE627AF5AA8E45F84D7030EC793369BE0145FC753DEA4E30C64C442923919678EDFCE3C39A3B358ACF2051048B01CDE3E02398805092D5257A4793DFBA07F903D091E03F1119DC48BBF56E6F0AD0529C8631B7168288DA3B6E7D94C2E6B4693B310BB54E06DD0FA113F5302D6AE10C51E679B688618F22529B36D9EEC446ACFA8AD7A3CE5B461F22C6E5FAE56D64637B22B08E7699775D2A422A54DCF3418980C889E216A46F7E3716E6064809A7037F6E8F3E018B73BCC95EFC50102E754C217F7BAC47637C3404F55552930270D75F2470215E37934AC06D
+0742E0E6203130CD3D11E791F54851CB3D1397BF8B7E7F1F8F9E745BB3EC0D37ED16077B95AEC9C2943708EC5D92134A550499D948775A159B667B6A7ADEAFD17DF63AE4C20BEDBF23B31B02ECB5E544392B5E697F36E9554EF5EFEF22AEE18DEEA9C55C8EDF0F451456C4D6B27CF78E2590D320D438A4EB202D0EF5C76E095A9493FB04B24C8D45961C26E233BA7474445489521317DF979CD933B9C38880D49C9158F7FE449F2E5AC55CC821B9C8900CAA699E922535FC4A1A1C80A5F243599544581F7626EA091213D5E068CAC873A5A3FD36782A8DFECC91308DDB89DEDEF00FF19EC8EC30616AED477A4A82DCD878E3BAD0E996BE2B9321C1B2807CB161FF79BB795A293DB8E9C8BD8240077FCD7AD466DDBBB58C3B42EF8A8F8571963419AF55FFE1E065135534501B3B97F87B7B76C47F4B90555AF6F9C3FB3AAF9D7E33C12B2B6353207C9315A9F3A71D3BD01BF778D0D50E3F128854F05ED5B802BA12A494E317CFBCB833FD124EC64FE87FE863327407388CE09BF7D8A17928C4B6EB09A8F032E41DE754B6B6B7F2FF3F8E674D91AFB301486C88096C15AEF7317E580267245E6E5424696501094A43E0423E6078891897819F937340605A87BC90A9795CD97AAC48286D3B06D51A53D2844B6B6676F4E8C085D4E7B718D54FCB96275FE03C192605DAB34AE0D997454CFA9182352279E63100093AD49D9663BB620D916EB2E6DE744E92E28391463CABE5A1D33498728AC54DC694022BAE408B483FF050E1605A60C0F5C0C2FFDC51C7008A274AD023964B71670F67459C19794B719577360B893ABF0EA2BFCA53BCFD4D00D8E2A0129810041B1AB15AFD374C280DF4FF993305914F9BEEEF05EC30FBE234CD543D4651D70422729F166CD41DCFA630B158F58889F3732A32707DE5C9FE2330DE32AFDEA3C8746808C09DB8C0B68DE8F50CEF9494326E63477A9BDABDED17795DC4CFD911F0D032B9A83F9DB253624CEF5DA80BAE3326D4F394D7A0E87EA9DD3B5ABF9C60D2E93C65E93D83DA3A0761BC6438DA89B0B0B32E3D189819A5A39E75087EF8F223354C2C5DDA6A84B372665E7AED6D09B017EA3476F3B18AA50294C8C596ADF6D9B3681CFDCFD43D5291E6DAEB1466343A6D3C148CCBD3ADAAC39D3F482502BC49ABBE3C7E0B09A1D7A05DE5F75E4AA3364246C578F549687333D76D673C8898D240364DB074AFEFAB827081ACA50C98C913C9A5B314AF0C07B5FFB7CD9E6A92C97B41991056259AC161B493580474E1BCBEBAEB3BCE6AB3D8BF70CA8498F1B5DE89808A7443E29DB7585933196452671940B294613E2D885F44A156D6BD6964749570FD561E3B426C3668E924BEDB7684AD1E4D432687B9FC86828D26A248D21D31A19DDA6A539A6C896BA897FDA9E3D30628093B6C24B1D20956D510A4E0FDF06669FD1D9BDFAA66
+4CF49D817C7BAFFFD50086FA5753F6036A4BD0230D6C9B8867BB7EBBC570F415EAE2D94C66D5D85742D1AC6A2D10FA10ACD3A88E7A1DDEF09D3E9D42BEE831AF8D93437E6D2DC8E058DD3D52B6415DBA2470AA136F370FA66F3418919CCE212D3F2221B7787B75EF65C8F2A8DA769A35CAF7E2B77A02274401758201EBEFB9FAB0EBCA8CABD9E2A2FA01FD4562514D8921707CD7B538D8B86CCB0EABA1232299EE2EEC8F37028EE8A68115F8F586E6E0F0650311347B5318231493C86FB77C2AF58C57BAF800064B63996E7803B411C812902BE1B8C8CF60D7F897B8B1BE9C7FAA4BA96EBA48D8F4A2E69DE87792696FAED2056344ED8E7AE00E9F70F1A5C09595B5F63345AA25E4DAEB0EE2CA1C920D58E7BA8E6158CF9F4653D46F1A347E3DDA21AB36117C0B99E56B7445E75D6D7D4DB28A0388E9F4B13D5EC21F92285A00105B5BAA9F99513040E015C1376C430E722BB7ADD17ED852141E77ECCB62403DE10E9C625E767B3B1E6AE5C013FAC1D18E374FB47CC29A1534A0F8CDFC547C2DA8E1083B0E5DDDC943941E70E4A9427F065CC5D62AD153B0B15F56E4028C3942B46C91FE9318B4E18CB5F98142A5F0541718E6DCDEF8F8788A8ACE0AA1D2BD9C60B79933397006D3BB9DB5D05D85D8DA487BF042DA74DBDA012512F321C8FD89651C042DA89500AA37F84020DA5A75970B9D175028B90A96B9584767F62E9A01ED6921722EE3C08EAAB65B2683380B88835960CBD27DAC29D3E555FBA4380FE190CBC9A53E125EFC297735411AE1BADB429AB7E6A468930F8A96EE8E61C5CF23643CD3B5B374EFB14884A2584D1A8037F68CEC48896134BCFF4FB5FDD569C3FF69587D955510DAD5109B50920985AF09FA90133DD43CD9E734BCAC0CA54297C9794DC7E37966279BB32A2F6A42BFF61475223533E2D2D3E01E68375CD07202CC6563E4404FC480025D6A2A585A4DA399EFFF0B3D4B79361A99A353C32D4B58CA12FD3CE829157CA8F1218C46295744AF5FDC984599C1F3B755BF7D72E19D6592E7B6EEA771D6B4B45182FB946CF0929C96A2D716D0CEF1A6942D840075E48ED6201B26DE179DA7F11340B94A933347048FB7869C90D0369EF0B05829B3AE9A9D0BE17B1F994FB6B96A1274F276E818A0309F7F96B430745E65AFCEC069F1446000CE768851E92AB5083E101E84E5E513492ABDDEBE7183D2BC54D411C22EF74B7A02E8A0087F84DB301D756399C68A87ECED84316B94661248BCBFA3C0B0E96FBE350417EE04F9B449A3489192FDDDB3F743C99806F4AE3416A6F25EBCE8627DEDAB9CD03B5A97A7F913844351CD7293E29A80619CF365D9B0C6930BEDE849DF042CBE18DEB9702C6D948CFBBDBF9C291099E080E5DD81ECA9C39D521D5C2A71284A5DD0105DC96760BB07B410EC1FEFDC087101AAEE116EFAB1A89843BE42E9
+AB5325A26AF6DBDF2CE7B3AE1F43959AF974ADA03AF001E8E5A2D09A5CB79EE2723A6A44F371D25182FCD3E6AECB1376C113890C4350F8E2E9EB7F467C7E75E1667CE70863419FB265012F57BF9AB5096E58484F50198BA3869EFF2324424D1C2DD9D5538F1C98F0A121C9883B12D7976A1F38A2A5142AD9D78B3870A14984A678E5D37A7D5B449145BA684EEA953F78C6ABBA87C36792153A7A4E44349914CD9943E3DBF290153CB1294F4C5ED3F2E2AA58047216A06BE7FA651BCD48CA08AA0B471D4C9BA1AAEC3FEEA87FF21DD4A2841B844679DDA824CAA2D8E77AD53011103D6B794449600C9779A4952471B137B9A3E69D0612162FAF47A95DDC865D286E0F46FF6040D2D205B877239E91BA33AA6DCABB5A96271163EE5B0E1EF785FB5F2751D111EB428EA7F39D648D40E6306C38B9A399E1CD8A70671AAF3CDF248A34B41BE20EA6FEB52830249FAC72A1FAFD114D0B22B4C14347297F1881F56F1A5DA72FE2674914B8D367ED3DB5E357A7339E3A00B288327F788118331C25AF9AA79E6849C64CD754A9B96D26925CB8ED04A3B215F1E54B727E16FD185B728C817008E911F4D55A9D830250035C350BCCD13B2B5946175A0948862B715FA2096224AF9BC372AADA19C39BCE8A6F4C14B69C8CE3F4743FC2E4D028EAE31970EA4A064D600A13E26156B4823DE79A6614703B0944CB748FD2E8E7D5FDAB7A19A06A7E69ADCDC859251DE55F1DA29EB8A63AAE8AB9696BDAACE242E2737DADD9AE6788194A198F5F5A23E67736E091D88CA0E584857F3E0586C1E3B56FAD7C4F1114F95DF14C391E0CDF12B1C61C5881AF0D7B578927B35511C3ED63397577B9107A397E0BE66FBE877357DC8A19FB92FAA1CE39F67151EA93089DBC620D64590471FB075284537AA4474B9562A9165F2F7B0C51CBD13B78164E2456F8AD02B286FA43058320A9ABB67F4F10ABD4254724A88D5C08DEF99D1246AF508A47443971BC01F2F539A77B84B61A7861874FBD68FF639334616B2CD3E2F35A559D86A2BBF6482D3B9EE8D850A02942FC5EBD11936DC1288E9FC962B7CE42D68CA101EBE7D37914CAFA604441E8B3E71496BEEB7CBCAD468FC074310A01BC364903ADAE53DDF6FD615DC2E9A7B44AF96B5C065AAFA92D5DB431C40C6A4D80E820C86D82D5DEE9AEC2B09582392C76362EFC051A8E4338560358793815C7580A6577105CDF272AE50AE8F424E2BB63298627B6A8C07CA802B527C700354B3BA3BF644207BBC969C602BAFEC040F503E8F9FCF601AF34675E8D44A203220704AB29A0C5A6E41738F43AC46C69A19AFDEE89095AAD24C7026C2577A37B87095CE4FF3E2B57C2ED638700C8B79F2C95ABAA9873642BBCE658C1D073705E3A94EC353F08D922A4D2F2E3C62C47D2818CDDB457950D74FB051BAA177AE7563B4FA54F74B36C0E791E
+C5CEECF2EA21E3D8A0FD9D10C1B6D6BBB85EA1EE16C8C14E5FED8F4A932B1C2A87426E16A2F04D553F0B780544CEC73E1F2444D282F56EFEF6B228325C4731F7DEEB329F5621B121244369F1ABD01C04B5259026F9B8CC0BFC516F8EBA82ECDB9FE0603C17AD078912ED791B25B0B67BE0F99BDBD8F2924DE4A3FB1741D5242B5066FBA829A12ECB1D232A35ADBF10767DAB54489F60D0515BE2C8B1ACCC5F152AD8BBB627C7B3E590B918F2FFE847B542CE15A94DED365AC0B45271C479B8F3F77034FA7C654082759156C58D62FBAB7C507AA5B0DC4CE103DC12B3FDF7CF1849FE4303FE272EA0C2067924B94AF6CB5D914D32C16B9D9051EF1DD7F533675EDA01E48207EEC6FEEF48DD33C428C04ED97CF6912CA69D51D0A21025C1D7872B43376636A54AD70740DE42F184C0B6B08A78FD3F6045DA5DB91E2E4E8E426A74D7A641CAAC43D15D4D48D150709112C2B9699E658516D901E4925DF9218188F27D3E3A926F04E5E4C53B247D976022912E5D260963DC9665F09378E44711A53AF8D065F8D2020A7D018A054DCBBD6F5D12DD5286B18BA541D58CAA56D61500DD5CC1C20230FD8BE9C26B64B109C57B9D9888D6D1C696CFA12D56295BFF1209F010647D6E34B0CA4BDA9EE1DD4785A03EF80B5EA28AB4F097CF4A80337E142CB210BDFEC48BE89950BC87F5376BA7232B7A6A8AE6E656E041E51C0075A177E9A4CE5EAB8D6152C727A1BEF625A00B76ABCDC74BA8347204511DE926A9E1158A7EF7EFCC94756B5E4A4C0CBD0C143D1E7445E7875E2D86D3E2935D97C7741D555CC595FFD6697EF18B16A907DB099F9BC98041BEF1C62EB4A82FDF3B2B3ACE84ED3391812A67A2F1A16AB06102A38452DB87FD6A2AECE8E2674C4319CFAFA51F615EE9163EE8D69EB880D1317074B5161D735FC6FB362151C468481F80A24E597CC5597F106B3A3EA485E8D3D33EDA952EDA66F12B04177FEC02653A6AAD402014A03E23BAE509A1FC6AEB2475A0B0F4BCFFE26B1474EF6BB9CE55D595D193C28830CED7F05022362F2DE552BCD16FE6238FDD2FF2223334C0B168592F6B956568C54C1C147AB2EB9B48C5BB81BDEF08D86A7CEFA647DC4286F7DD80F8C3661A8901ED11B2EFE627FA29C912C3F12D95A1522049BCB1D3FD6B187D359AB80F8C79B189C62FC09DDCF18119D86EDB771896FB8821B5FEDEACDDCFE68D421DBDF58B161EC8A0A2771C4DCC86C1800E37A60C1068C6238335B4EE164D502C145817F65E8A507CBC5ADB265AFAC174A5C34B57FB663D4A712E7F029C1E0A75D7630DF909889FAC76256B01D77F7C3E71550498C49C1C6AF4858AF5850BF7856FB2F07B31C4A4CDADDEAAC83F201DFF06603DA5A1DF7CE940E020FF1A1BFCC56FC8FC259FFD49F4A70229602BC5CF11C5B179345CBE2B385EEA0B4EB02CC616BB00FEC5
+AB6103AD773ED81898A0E98A2BF48C6506FF658CFC19D5E80C1B6E5712239C69F639ED446F04655390B329C763F8EBD152AD2762D2260F4EA264136119F4E090177E9AF1588DB13B73DAA25136FA4DB3ADE710A37B088AA2137A83238B58F63F3669FC663B99FFE7F6AF3E7DD69C21EEC399247FCE9EC78E56C2AAFEF87A07471611D39BA326AEAEF02C2ED84313486F51C5C0786A92397FFC59600BA09C637D3C9130766D2E44A9E9F8D7CAE5A64A95F2F16D6AA0F58A3A7F7289FAE6CD61DF06AFFF81212E8308A2456E4045F9FEA0BD169EC0AC9B828052E58B3AEAB131FFC881B5976ABD72BAF77856EED3FE526D839C4C7687D754FB2F055D239D4ED9CF389FEAB17CD2A4895B6330AD60AA44AD5F263E302773D38041F19BF1742BF7B6462E20A5DA1DF19857B0E5A049337BCB330728E079F92C29C130DEB5DF1D3F9CABD859583CF9DCEB38C85A7CE323865274D798597106058313808A14D2C3060BA12160CB5D53CD616893B765DE871A46A10866DF7367028428055C99EF4E04467BCFB54A9401BAA9751DE42C247CC62B9A4AB1AE89DEDDE12E2B19B039EEA06559228F6D5EBFE69109A90AC5636E03D298B95F2209AF520A03D859963943643A2FBAE5E58FC6D113EA5550B41C991874DB613A9487F99ED9A65E5240B68BFC85414C0B6D25E258A6B647539DE0C1E0A2406DFCB90A0E84E261D856CFA9E7A9D3C62D6D107013C97AA580C3823B575538340B3EF908A3AC55371BCB6B7F6C29B33677DADE72B28269E4DE6016A82B5FE51082B151E18BEDBA02F6929F72B156CAC6127311D3E23599246900E38998E11B4050157D8F08AB82AED8C436F242510CB9A13CBCA7293D5C502516CFFFBE54B70B47829D7124ED09C5E4707971514C1F79F25E4EE503C5F9E2257182EBA63D75AA7BB30F8FD11A76EB23641B9CFE2EE455CF9FFBBCBC25A503161EE4F9C0F31DA2A4357E582794EDCE9DFEAC3B6A0A1F6169B3614B52A88A15BA48D6647E2C45BE5995A3B7D3AD6EACD5741A39587839449C3C210E1C7D94461218049C05628724E9C0DCCAB3A92ED48A8837A05F75C76D289F024C51C681E84D0332A342063A506E3840EDED46387350FA9ABE0F97250E8E67EABDAA0F8DCDA549AD147C13E548AFE0B9E925C5EA95CDA9A428CE749A563CE5BFC80F85735F52A63D8252BFAD67AFD6C9516056CC0B0C5EED9A266B0FF8D86FF958B688383B14478FECBD07E91253E6E2EA29A66A20664E5129F3C3740C48D300CB8F3908E4561A0480F93E30EEF5049E79D4AA2D869A5F52A9C4409524C04DE20259859D05A84BC85E3C20CE8C89F894F539F26516785F020228E0C637038324490660060F998E11A0210F409E58C7D48DDC7737A892126855C1ECB67519585B4149ECF0DC84F94731B619BF970BE14E3AAA114A58C3F9E770A55D4A
+BE259DB02032DA7543F38A8355DCD3F907FF192BF214D9F9B6EF544601C884D5A8D57DB82426D065645D5F1ED9CF47C9E3289F1793F7400962F78B062C73FEE4B549A96B03A3E089CCB7993F8CC61FD75F1C5910210912CFD3B75977F405CAB20F2BF4861921B5202675B1FDFD12FCED851B29F9A6A82A8B7674AF1DEEEC6D88442E4093CD158B47E0BFB307F2E47470209505861CEC493E8819D3E798F03405E744A278A1FA43A4D5811E3621623BE9C4D54D5A3493D168477C0B8FAE27EA2F0BE0B68B7C85047613F34E28F01BB9889AB5F4ADDE64FFDFEC1F4D5923CE3E3B4B2845ABE1EB0B971A490C8BA3631B1BD3DFCFFE18058EE7A659991A172A34FF3AD6AB1110DEB3C9C36D9F252A44AE3C632F1EE6354D95C1C823C17FD4EF68EEE56D2AE7943F19CBAD9788E16AE3E83968AA33DDEE372B2CF82F17D146945E72BC4FA42519BB8F92B7A72A8411E16170F5F937FE97CF92A34FE6A4D144AE7CD24998DAD80D747D1C72E54B0CE4BF2C02E7805B506E3B8F143D8AED19CBC8B967A29152201A82EFD75C1A78BFC9DC21CCFA3563B465D77E1856DA8B8B3018112C36DE5AF1650A9A266E28EC3E5897A1651EFB357645188EB388996F6E87B96E4CE3DADD1EC37B0D983434093A2B5F83F37420AF6D072DA5E5695DCEB2D979D5265E1C4FBC6A7D4DBA578805B86ABF68D17B5DEEC956F1AA9A5DC41EF9694D8C6BFB7A333E8A12BBE609C8459121E35F723E10867405667F049E994E373D0E50265203B4B7C718CFCF06700DF51E6624E6AE6638003D9B389D601FB79C6A3674C8C5F4F5FCFE9D24DC11EFA392EA229DFC1DAB1B99000A4C397F36695FC44B643FE561FB2A5B80E6BE092094A334BDC47839570066A359D66893825635F2AAF10488349FAA688FCFC43B5EC7BD4ADA4DA317E86F347C0B2FD169BB61E5E73791AD198BE7C2B7BB4CAF6F1EAFBD5EADBFF59401E7C078AD1430CA69E3817F53734FA083B9E226685B3B130474422D105CAA25BABB00AEB1EE7C3B5CF6CB84128D4203D2B5DE74CD16289073DA63F8FA4402934FEEB72DED9200322468F382AA521E2660BDB9A86C8B97D5E8B53154257958E7694B9C0452DE65BA958725B766F0A827EC8EB5F835B0DF4D7637DD1265D0CE27734594D4AB42AD4D383E9F1F438F76CD62B4D63127AD2568A43C2312282C12A8B551675EE408963DB762CDF5187CE5FD937AC64776B3E851CE55E4F2D29B1AF43BAE9F57C9BA8F99F3171A4ADFFF544F9178530359384E2B5F28762664AA1EB8AF84501FD3B313D2441C167EA3EB9E0FCBD8EB5D157D7510ED5F8592E2A553DED5D536F91FE7F3FC2401E7F81467C984AA94B7B9485DB9C06213AC34D26CAAB6C6CAB659FD5401B0AD8C07112412BDE689840EF54C0AE20A3E80BA510C6A5AF2CA051976EB3B0A518D43F5E175B7E2
+DACFCD03A9CA5BF5A47EE078526CD001D0B770C9D8E52B9F0D40D0FC0EBD271CF91FA56463B6DCCA85E9180D23C89D4B8A340EFD0EFE1EEF7DDC6A6D902FF63A13643FFA7D0B5968C34D62358C1180FE68A8157FDD0427BA3C5B20ED8CD8779BD316E94771D16C98EEF5F86B20C450804C756248C624E4BCA3AAC4BDE9E85C0416A55D2A38ACACF3859D8095D110EC2059506A16C4F580CEF05591D88054C2D1C30342C27E4D17CD627EB6A78B73BDDC97B0072C7BE9DD6A867C84FF042A073D91D1EAA6AD91EF63D1F641B300A278AD0DBA910E46B09EF98472C7470F224AB6CD5FEC1C908CACD2261F2A16CC6E2E4827EEC1458F8BF6B4E552AB5FBCA7C7C14355F0D33BFB6CC284F2D95B9B5F144B76917A6C7100712C4D5AE167335037FE006F89CD9E87DEC0AFB85AC09298CF5939A92C37F43697473D4CEFCCA44491EC2D204F7D0513901D5F8CABD857B81DC722510D05DCF0164FFC2D69A80A20174190925E6ED1DA395699F78F400EBCC69B4D445B39ABAF3EE7CF4E1B74A09047F3367B5F4817056267AE41FC22369F174931869C950C286079F90AB7C5937B48EDA273C77C8F2C32B2330A9B94C5128E6D2EE3AF4563B4A462294C2EF86367D9D4FC0D0BDBC12A23B309BFBF8A3E9CF5EAA9013FC654766701A3CFA0B3057B84736619259AC5D0474F7A1A26B8DD2B416BA88C2E38889ED49FD5548FCA60E45017B5CABC02F2EA44A595D842031498D0D4118F75C4B84F6CAB2C03ADD2263F8D6716E3D7C76C5B25E8246732499EDADE4A0998DB25E99EDC2661508504FBCE27720F8E6BBCCE7DAF9FF1BA405C65D323FF0CFA5E9EDAF91068F1976307EDE8C52FE3742CCB6CE1031088495743C8F85712402AC7132B96F6672EDC8B4EF52EF96B0C668645774A10123C5F2CA5B828DBA1E4D6B95AC16A23DE5E1A46131E4786F5E2F71D3415513D6658D24B8FBDA1464F718B1B32CD63F4449E41A027D92B3E89763E668F96875171BD32AC38E82416BAEB378FBB518F8F4D576248697462832DE09FCA6480B18F0F3F8EE449F024FAE23DE5CB83D256B10C96A7A5382695C8E3B2AD8E91B23346FC31D72E355C38082444D05667238D3DC9049C11D5761C159331E4B629543C91C95DE027296D3E123C8DA79F8808E44447818E38889F6394ED85669D297AE8273E8BB600A4ACC29B2D8F2B0697233C8E6F76BC680E8C5B34A5CD7FAA44BDD6A3EBDE5B04DFEA9AA81157B0A81198770AA2EDEC9663D7EAED38AB1BC0DF631DB1C385D914DA668103BA8B45683552C64E51B4F7D03498562B20778803D83899A60CDD60BDB2DA9E2FBFC058068432F73799C82C2509C0D294F0FA50F3485D02FBF13F88D69C6D03A1BC522C3F3711D73EA3D7CB1D117AB760BE7876962E1C8C3A1CF00234CEED00C82135835E6A05D396C246DF3DE069C36EB2
+E532058191278F0706FBB7D3A1AA797746CB7079BA00853734176A561CCB36CB1D9817E0C63221DEEA4E72369B64982BAF1034728E4C72135A6D9D4B7C7B53E2FB4313B11497A6BF8F33B26884F00DC5E45A95F4E4F6E0124B4FD1BACF3F62CB38462054B5A24008FC57525C0F8761960307E1367959E797205475717DA0A1ED0CE82762AC5F8A3D0DFF6F2078B3A0C152B8A17F4C708CB320EB2750916AC0F6639E9E8928B4237A4201E4A2A90467E9D444C21DA49448A8D3ECA002168B8C673220F9583BDD4E59E26DE1C939723BAE2CA04D0778211A451B9008DD7A4EF54844CBAD7AE4ED50CFFA066B95B5234997156FF56CA7A5FE9DD45C8F95FCCE049A1450041B705E8346E1FCEC5BCA7A0FED310F31E1BA6C19DE27A609013A69DACE4691260C69967EDA7934B915886511E8778E59750D777658B8384FF32DB1AD7F80967FAABBEB61001AAE312C63D61E23619E42A3E3B4BFABC189229CA45C599839F8C105C1220B0702AC6A785A13DD105D0F00310969A995D3A7D2ED0FC43812B93D8774078AB04779C219E37B1A69AC46C821C37FD5603CEA4E8A82BFB1D4808A2EE79C1E4646BB7A6280CECB08749A680A3BDE077660180CA59635FC48CB293EC2AB64386B379BC73AEC263F8D67D098D37496D2AC7C21E77633D921DB8A44824CE708DD09AED42D1DC3CA2F8F0A84E0182593651998D6F5015794F490C57B881A4DEEEAF98E76404AFAF241125207458AD19E05CB434CDA0E6BBF13E160CFE2CF7A09EE889EB50C77E7CCC3E409BF4FE35C0DD3E8F771BEB74BF243B0025A6E12350F6308C43D78D4E7C737C9309D14496A2236E88EA01140D8B64E529FCC18CCC83D923AFDE1E8C4C6F69A6A26BAB110C78E3D9FAB2FE0A2D2C0A9BC8E55C55A0567D90A103E100E8DCD33C3CED2733B60F39467BED42B16A7461104F75BFB198B5DD361CFC064C94B06A0C9E3C116F433F2D68375D7A3468721C26C839C4283E6C153767276A7E119A6D2CB5B8C6B13C101045D16D3D878D12A1A39EA8A5849D416344C54EBBBE504E22E4FBE53EACE3838B4E00B020930A528FB83C6AD43D5DB8622C325F5A6CF514B2EBB71DAB1E0BA591421A2E710016AFF6B4F329D6432A6E0D509AFC066FEFE2C4C6F928E36D6AA66EF57BCCFD4B3498E359444272A0C54F1999B87AC32F55C5BC8D197F450B1865C934B48DCF43D0112A89CAB9D447F0A7B4E196E9C085B1D76B1E7C3F42AEFC28BBED1C54ED7C4EA0EDF74032DC418166511A9EADA8B66637A7F0D3AC8F0DC1BC563E27590943207492C5B1F74A5FF11776FB1CB75AF210520D319A85E7239F85FA0630EFA19DBBB76A37C075AC0C51F071B810838807A810E414CEB2C77C4F5DDB5D1011E5088421258BCB528049E3CEB0BC40A8A2856213307FE3E439D197B84AEB7DF0A16FB7F8FA22DCED8
+9A456A808C769E5399F33F0BB4B4AD7CE7415AA1562B6A50045906D1175C644182FF3500FFFFCE31BC833D60807EDF9AE9B0D6E9CADEEEF5627024874209F80CF2F0130CC75C444E442765840F34C0BCE5A03A443D0EEEF72C9B9CFCDD15A4E0962E284D13674729A755FB6B1E71EBC9C514535C0292369C90DAE827F30D6ED2029750FB0A7D5F0DA02AC95E05EC08BD02415B59304A6E15EBB6EDA7BC278B28601749F481C5D5744889A0991B557CE8F8B9772913AAED427FA0D833D47EEED900668BE76DCB2ABCD0A3F8F830F82774A480F0D63AD8960CB7D348374FDB98D9B7E5F2619E3CD474849B4B67F09C1C678AECAD8D5FC3DD2622810EE551F8E019BD03DF5E2BA5B923320DFAB48F34DC38120AF0E578FB335B33E4621C1A35FDEF04158C614EDBABF0226943AF4DE91DB529436E0B2D6AD11611F65DDE30A8D7569FFB75DFEB897198FAE3AD74273BD723592BB4C21EA2723FA556BB0BAA927C7F9C3C75148A593E4F8E00E39775B5FC7FB22F35B1EA8F40255E9765DC88760E9D2FC6CDB3F501B2AEC772533D54DD882A6BA97ED78B88EF04DBBD2C81D64DC346464C30A577AE191F9D57A1F9729B641DF93D684780B4C0E2879FE196DBACC66F7B6CBC694EF329F0E6E82C9C375BC3993697592D87E4E6293A51EA4E60620570B409C439341F0215E21C7840A56FADC6088BC7B29EB56A3B436732F6A6095A982D4BDBA3F646321C870159FEB50E21099CFD5F6F97B7F43615852808F77890CFE5D34E99C80585BBBEDDED97473914CD1E970A1FB5D20CFDB04AE9E9853C58034570F340A868478EEC8E32160F8245265B55D8D2ADB69948C9181CEC7949EDE8976B0BE80C5D6B3FFFE6A53CD9B432771D2F5A4032C2608311C04DE19BB10BF828E786BC1AE07E9244320D57FC9AFA730B802D3768C7817B30466AF49C3AB3BD2AFD3815559DC92E086FE2F4C47BA5924B82735A1B462396D4AD3F840162CE1F6E37E3478E6E9A1FD9BDDC15239911B5290CFB1524F93A47C5D71057B61B0609128F76004877F89EF2F4F337FFB96E68A4ECE83D9A15A5DB5E0C887797450E483E4B5AF964FBB9D2B315FFF4AD1D3D793099571EB982275B8540DFBBC4FEBCE7095E758A88BFCFD2C93AA422196E675420C80690D740937E2B8FBC77DDA192438E0A040D623DD82512547460A812E7FAE49DBDD5E8CEBD2462CB7BE8BA18F7E7B5D096BDC3A032C304D5D84DD745FD07E4E6D569CD6B671796457051DD275429B974E73D8DC38B4896CC74A40EC73A283B65F3EA1CEA744A800BAF26EA894B95742E2DC20A334509A6759312B7D6DB8235528D23F577F5694B62DAA8F1124BE6B81445CC680C4C8037029D47F8B21367B487727B2A7722A55C173A0A248818D6F0DFFE8C7E96203AFAC8A64975E53A496D3E97E8DBC8098C73D3FD35D3A004DB
+B281892E4E9E2E9B9D5930815632B296E8C31206C3C149E72CA657135CA3384E673EEA142DB1FAADFC5BC91E66EA44AB32C838C62B81904495CB67DE92FA96AA708447ECCCD35F2DADDE21C7DACA0BB996A92CCCC98363987CE7D66D0A6ACD91E2507A7C250A3D162C215ECCB836457AB86CDF0CAFBA1874CF7E30C6C78E6620BD63852D9C2FF59EE7742EE689DD38F0DA2497CBFA8926BC4AD8F26A5075F05976BDBE9ECF1F5E0F6EE653FAECF2A30A543FC632B1C873135106A3F15F77A2035E9ED31D4A76CB38242C2E10A80991E20EB6B3483C5D7CB75568F7AD2DC93F8F3A1A2C41394709F3494E30142344F822F93EC69CE1445F0F058A6721C2775CABF9957B5FA2C1E8AEF7D3D05EEE4334D449E1819421A57BFF56AA9E55C37A3352209D70AE594C496F3D382022D60D6723C3A0A08B671E9331D4F23D5F0FC958F668069240F272279F6B4197233870E69770CEFE6F362B6B96A8523B2460B16E566E3A21425CB305AFC56CCAF0652A8B0C1D355561C78100C78EE7C62B3CA94BECE7AD3382BCFF59B038348910756C800F3B62EB4E09BAE8A695227199AD44ED54A5C70426FCDF014FA19D9587B3F953B29D27BE7048922FDDD61659D4DA4D25022FA1B931AFD778891ED958AAC8BC33AA196B2B9A837CF5699090F8FF347BD1DEB8A198CD693CF9134B2CBA559C3AF582FBBEF85E046EFC76D27B0CADEB06B8C11DCEF8D55FBDFACA1C2864768EF46133D10E6031A18A1F4D8C6EE7EC51E925FDC480A22E9EB593E83C9C04EEAE8172EB46151E978592C774BAD8A0FF78A5D8934859F44EABB2D55DE8995B2563E85325661B4ACD227BB0D4E2F0F3D54C48AF31F89EA8F7B051881B7BD33774933B2A3C61DA575A6B354B0F97336B266A844BBF539E060A2FEB21A5BC3C0A61558905424749B0A98F6386F1FCEFF5A7287003FDDA0C2E6EE93BCD8E2C51A16CAFC5FF44563FFEF91B2AE65E9D4FEA38764B71B92DD6560A9984F10B40EB0220E4571526411A23F8ECAF9A8C29C0D67076DF7F54595617CFF9BDDC113455980E96E9CBDA85540187209EC608416FC83147C56E77418C4ECBC01790844A42C2F2FD6C30EC951148CE312C4F81612CC2327080E26E9D5379079AD2B433AB8C2036A5CCE0591239DBA4410FCE4E8C37A3E388BE6467BB74F500C701F309EDB3779A9FAFC98ECA3CF1F4CAF08846CD4F0E5F3C6F30EC9D2553D1CBB5FC2F4297D8AE926F130E3B5CB9E520B230A9AF1B950D275BE6AEA141E43B55EF2A952ED2FC2B6B96DCDAC578337AA1243F7A9DA5B5156560E67D00519A950CEA2DE2D2FBF373BC13A90AFC77CEC893C01CB31D2ACED2B621B9F523AEA2FD33BE62EB514A09953475F2D9BE644B48B47FB99A67089A97D474ADE353685FC2E0090A238A71ABA9197ACB287FFA81BC915EE298F72DC1D6A4351981
+C74634D15A81FE8DA02157492ACECC2E256337B95627AA14A230B801E776A22469E0868192C6C1C764467EE110F326AB92320B4334F4D5BB60E041863493D1CEF3438B2A1FD5CED43AF187E0DD080DED00FE28A462599E4B0646771A5403C8275DF62E63E2696EAD98EE8DFC3B67E3CD4CCF065E67C7EC1BEE531962EB3911E457636786B62D3F032D7DDB1A37D229751A583713A17C1B6392E38DAE6BBF7934B7F1EF06CABF544680043BA67A3551C61BBC6FBADCEA63E413C65DDDCF732D6C161FAD451101305AE9811A9408EFAFD859844F2D9DC4630760505B5964A9E2A273596CC0D8FCB67E8503DC6647210763E37DEAB945B88DC97B456CA18CBAB84F0BE9535EB9383F918CA0D0776667B7EC38BC93B9223D3E6005CE97FBAA7D320C7B4E54FCFBC2C55336BC7C847743DABDBFE0B28F72CDD9FD1A86802D871DC9A15CB50025936957027897348812B9B1670DDD76A6C6A86D0DFAE87ED259F9CA00C684C3A7CA3A20662927BA36A774BB00F548D62D185CDAB96E9AA024F9B1B5E130F6E2FEAF9EA576681534F527A1ED8A6E6FD79BB1C06293C23A42BAFC8A3B271448D6B66829BEB76A2B6EC0AECAD84AA571C1C040978DD1F3318A6870A64F538018B45053DF0A3A3B459335A5A3F2961234EE8C4DAC687A37DA3C75AF38C108DF26C8CD04AF068F6E867155745054B5FEB8C9E9882C6C6B1A8FC7554CF14D7CCFEA2FD3159D9222F1785D27FAD9E7379225C256662B47C5B7F52D5EA341E89F3F29378E4BD5DABBD0F54A6BE5FB7295F8E7229B535A4428B03ACEB2706F59B382493C9746A5B5B181E203483CA37C8176BB6053C817CB20B752357A62DAD9D302B0B555F3C99C90C7AAAEBC6E14E68FC96265506E0B756A0165FA5CAE94739606099D9BF2E21AA79FE09BD7CD24FA67B8207111FE53EBB60A800D5BA95245CC3E4E8CEDED633F9C308148C82A006783B55075738C75B295E6F7618FB89F04D6FEB2D016A26BE5390E8501982F8C588EE1DFF51C227E5A1E935F8A98E026C2E4FC5DA2EFC620C99822BBA07643C23C5C7186806A08FA493369859BBDD9347597A1DFC651EB663E564799F496D0975637038FDCA7324F388BA3165D8FD59C378067F053A4291DB3DE422E0D9C73AA2829D12B543AD857B55FD27E191D7D725CBA346BB5BA0818784A61C7E7C01DBD129EB2EFB2D2759DC29640F1FC2875B0DC3A1DE413855863A042B5A4FD1F1292F3177837E60AE5C476FF3BB82510481623A28717E4468852257B86DC5793782948102A910639F1874A1D5604FDCB3BAB1E48A6E15D7F8C2F1CC60706825C16BDB91880E12B5278E26174C37F93683F6C9063BBD373977A572EF42D4CEC790D95BBA37ABB49A5622CEEB55CD632BC9C990EA7E4757D37D2D0F0E2391F2E67F8A8EDBA1A7E647D668CB7AE8570CD1D8FE7262B
+6C6508D11AAAE259E449512FE140C72129EA3449D20EF36975F87FFFE3153F4196546D5814BA9D5A41DA3831B3939F17E0B3C7FA85FD543FAAD1DFF931CEE0B6BA54DFC39CC9D5D8480FFF5C9C74B67DF1C2AB68AE177DDFF16728BF55F0AA202D73D7092F926FCFAD4619DA3647BA24750039D9DC5A0DA2A4F1EEC83F69080B497C14E6BE484AE6007EB6AA93F18C47B6ADB1D60F5742779C0996007ABC8A56FF876FE440A3105D498C6A3FA8CB728E5DCAD2AB425F32A3BC5E29ABE61176589E6CC4AD529D4E50FCE99AD73A2C2F9ADEE4FA39AD67B1D22B58308CD840242AF26B009D887EE31DDA0C4443FEBCCB68472454B363A1D97933482D70BBDF71FA3B1754BA03A4DBC14F42ABB06690CE8F2E6F070843ADDE8A6CE137E26C74098FA0B859C59854A55D4A55C0F8AAD0971385C7084D6AE3332BC289F499E9B9BACBBDEB5FAC6826BF0B10001460F21265B6DE30ABEF71B182C7CD3E38977AC2610AB0CF67D650139BA6DAF54E25EB3BA57D8FB27CF3BD15BA8DDC8E4034F9D0175A3719D6EA54012555B94DE1A83B6D3EBB96A4E750F1292F3BFD59071485C869859463837CC04912D659EC8EAFBF1F6AAD5BDB8980DC018C72DEF680320A67498ACE35417BF000A4C69E6926389874CC203B4DCCF2E1B4A17EF6A568A29ABDAB2E8A976B1024B38060BFE77A3827B75EAA333ABF71F9632C33584A14ED18EEDC2B32DA74394E5ECCBCC1BDB2362C204CBDDD5BA0B91E0855B41978D17068B32B31BD7B5874ABB84D9A134D4727E6B254D6908D19BB879B81715419591DE1B0826F38ED7CFC2FC22D088E59BE854559EEF6DED62E8B4C570A59B8780FEC2DE2CD5E1A62FB205C148A30DB1839846D6911BB1752EF53107194341DF4792643C14D73E052753A98DF862E3301124DB6C4AE3CE19A37869BD660BA1DC820BC1B6E53AF5058DAB89CCA4AAAC1702A47E050C069A72A4371340F133A8681E0C39703D8432BB2DE888A210C0CECF03EBA9FB9E4072D9B4D7DB5C3261F7E4B02A6614E037A66C8ADE27B37DBA106452D378E096AAB740CBF8FAD11670B05D489FC0487EF7129CD6725FC6D024DAB4E0866BFAF7E31DF29958B35DD7F8F1C523EE07780254EB23099810F93A2DCC4D25E6A009584C1129B4CF644C277BD975E15DF0ECC2CE5414052F76C312AACAAA373C64D60B0B65956EC4628EAC7D80BEB66579E5C9B202F76928342A3C461F658BCE95ADD003C913FEE3CC226266825037FE82FDF2016811EE86259E6D9FD05961282E4BFC1E9AB10E03C55A8DF473AF427035ECE90AA201DF6AECD7EAC800587092F6CC3A38CECBD4FD296E59C0811668E4D77CD40AF30AAB23C63EA7C70DDCE433017EA4A43CB555847E02AE69B6078430447A4EDD4ACAEDA39C03EB0338EABCDD0B9054733BE4704DD81C234520C24A3A718FF5BCC
+9EB0125D9A1D59471743C92E030AD7CE4BE37E6372AD6E880DCDC8E15B55EB62393BFA35EAB235C7EB833BF84A95322EB23B402F598B7FBB56C7EFD7C66D7E287E1E9024D6F38FAED5C421109FED623F69FE67890CE35C859C2A66D4601548E6A645FE24770EE677C90ED2FE106DD55037E7DAE616A1F8E396DA5D911079BB1055F292C01BAB1C6A50FC8D42C7A91642B9BBA10E98DC1F39033635F2342BE2BABAF60C3FE5B488541F5FBE6A9BFCE536D6A396249F9C82A3F9270A23C6468AE233DB74F829120ADAB7D578C93BB4E5743557485DE57F05D3C2A5014BA2B37A4240B81B29928ABE1EFC84167C767CA83ADD2713BE8AEEB4E59159D7F8E622C40DADD3057379A8C885A71A22EF397D1051145CD334E709ED32D6AB42C9C140E95E192EB82004654A7054F866DFD410E755B9BF5E8402101D76CD7CAC5FDC3780DF0F500668F271DEE873750873E00B84F2BDA87CE59290948F03D4BB4E963CDB3788FC870850C702EE0859A2D43372361AB3B43AA165965956CAD3AFB1766700064DD38A6BF70F1AEE85EC65C531918760AAA7C072C51D3B6A6E5B8B4A864B268AED42D407152BB6CC931F112B436981A7B59E831E790887A5ECBD9C5B1C53E8A93A59329D1BECF589070CCF7BEE9A2418DE57B4BC5D25F2CC9382835F61A2764A8AC1F77973BE61B2F239E252CE95BF161B29FC4908C2197B15EBA453409D6F2FE509AB83AD36132FF5521B16097B5BC024B34594B159C17AD568DD845AF2C5003A3E62FE9281304827500B71DDDCB4FE7BC11500EBC0AA5B8D2B049CAB702A6066ACD2B731FED11C99D684760F7D27426402E1E7706FFE5DA7BAF38964E8BC9171A532FD684B83F910BEA11DE39CF4C3F9A314A1A301C788C67D5DACA3BC2DC8B6DEF5ED1EE7E8CD1C2D0B9CDDCED0FD592FAA9C0D1149CB57706C596D033B120EB4AA582BE9B97B7AE08ED0005F174970893A282E0F2E79FAE6ED771AF3E86044C3A646500261F4558F63F9F466A7153842D04B4E1A831376D1831D6DE9DD0E18F1FF14007597D4E98FA79C52599A7B7C2D1CB2A1FFD5E5DBDEF42BA4F4FFAF54A61B515B305D729CA4599302FD206BF2BC397AFDA043D7C983B5D4223519292C75017D7CF91A4D9F563310880C030208FBB4FDEA4040BA2307A39079E18A090CE7BC560301E086E2D16B2C259A3617619E6CA27A68C6C62334F4E63B6868978A6105C79ED35A3C16D5D9BE973C726EE2AF78F99CF387535A2D3F9305649D26CC26C076DCA41EAA6F6FECDE4A2ADE906F83D37E14DD41628A47A002F912CC9E99DEB773D839684337DAD564538B92BA8ED2B7500A44558CFC4E0011EAB1706C0A5B608FEB6CB22E0629FF8204F3DACC2D28F46C4BE08EB7C4EABA5EF24B6AE568B579E9A72F70989862181921030102B75014B5C440F030194D9DFAEAB77EB1
+579EA927170FE4FF8628CBDEF71C0493756BA92D014D63A9E8D087A01E74919869759E9339D7DF0C71642496C713E007FB405DB0E0D5B9C0AB3779558ACB6F27E41BA1847C20ECCB4C28FFEE8DB7F92A1D35839EFD6ACC519839FA4363137E03C11637B0CC94DCE8A4BEF915EDB5391CE5253F3F04F67A1B727FC08F67DEAF9EB306D6E6227BF488FBC5E267C549A49BB84FB5EE4F159320DF21D624A18A5F2BCEEDB5915910D85D0DEEADC23CA71CEBA622C0709289BBE05330A84DC8F1F63E5295FCBED08D008DB040BE7E0EBC7E68A0E6FC523808EA3D6AFB0A7EB707418F5FA4F4C875D2E9B7A44016570E55EAD9997A70B202576D0D64F10096D1A62A9E48749322247E1AB09D954BC1A1BF8D647F4B44B87DDA13CCF16487DEBE4249AAD3608662F136669ED6FE047CD8C245942CD3D9C6E1B660F1CDA5FC038AB7A32E223A75774925BA019625248330E104D31FE9F2C84067133BE9370A13814538924C1C0D05C61476170392B45113F54CFF2AA42449EB29EDA922EE0D2697FADF0DC7EF6E58CB0B259ADE0A2486D84A0C814C9DF3EDC0CC5F81D72B7664F8C89C589ED0BE2FC0173ADB3D2BDA341AE8CC5A46FE63ECEBE3FDA6DC3A5532D6440473564F0ACE3DCEBDE16B8AF2A7259CF5491EEA56E63DA877A8A4315E0971B325C004F193599A895EB06621BA266FF19A9FED537A449E732531A75435266133EDB8DD05222A9BC1E728588C85F1E097FC6F2D38382E6A08C2E10E4433EFDB133115C2A84156D55286DAE78F82371C7CF710A0B59F91B1D3DBF03C3A08DEABBC49B1DC416E99C15D4E11A893334E0736EE593819E053B1F8F4EA05B1355F60B7CEC171077D41F48533B39C4220B2E4D0FFBD2696D63FE2918F357C62FE0DEAF6FB306AD6CCA5AED67F1460DB5D71A37537837841414F70F7945465FE78A89D13B6CF90735C238F8EAF70C71B83295B0F1AB961C9F58B25F8569DD64604697576B071392C8F3E37B4CDDC75B042D3FD09BC380355CE62DFDD2E0E48AD15DB22FE0C416D98E08991987D3536890F9A062E5FDAA0D88D558CE5B5A429E7FA87605F50041171D3C30A4D0A4E4F3ED3913543E838EAB0F5F454D2A09447B118DF33E7CE0A0FEFA2152B29EB805C635CB1FCADAD65ACA41FF5FBBE8052F026450AB55295D10920B896B7C89DE11A8A721C063B37C64469BAA93AE16E3E2182B5DB980A5D3677B1C71988DD7BFB8F0F320118590C5BC1C15CB9A09E745FEEF8BC0FA0C27E78616D0B39AECB49E292882B588ECE537E644A79C706C600ED8FB8FA15FBB80B3EC223689248B587B7E0FDB48B3907614858C44A9D52A796CDCF5EA27B5D83ABA7AFB8ADC233C26CDB04E2FDB80383AB39537D4E9F59C3AF4F5FE373DABB7A33476127A23B85003AC6A641E6AC72C8342954AC4EFED093D3CB957C1E799DB77033
+9F5FD7E4043CDF57D055F9D9194A95C9744DFA41B9038C9B6A47F661AD89CE54B77D4486E0CBC3815F8C123843182E09E5E9A216B65A251C6DD149F0C3BB59AC25A4512D9E8D5E4FED1A2D4045230FE4BD39D1BD032E44655D6730EC32631CA0663F52D276E33701B4C6BB9F74750B4BA3E80F82B7DA52E482D40BB2201FDEA7E6959F87EF85377DB669217F0AE7DB4DC16FCE5FB6B928596E9DA818DF0158F6E0A1F0690FC351B153AB080DF5C72C09A9D29F6441808E5D8BE729E02A891BBDDF95B52F375DEEDF2E0A08593F739B0A86DB636E5AC095BB02C5E93ED48B00BBC6E7D5F3300DD22BFE43D4D4DB68A18F94EFF869CC91C81E7406515A064770FA9B435DF66055F8916D5AB20F827A290B538FBCC22F3936E3369BDC5165DB91B3539D3653CA738021FFCDD1800D31FBC637EB121F15AAF84A63938F7089851528441B652049DB1FA876F1CEDF9B5D8A92AB8CF128E833A0AF515C4F4DDE5FF3B2B0ACB8A0F82ED2B824E41CE33024DDD9513C64FA85A9D08EF725204646D18F96335490E2E4E433B81AEDDE88C3413898C1F102D0A90F53FD07FA992A66988C5C5DA4F128465AD09C0E91CEFF15998BB735CB7F54FB143362CA8C46617F80C3B63C83616ABCECFBC50EEAB74A147BB049265DDD339AB838BDDD5831C2661E06E75451353BF75178DF3760E31004196E3BA4966AD6649C9B9A9B5292BF4AE58692E005506D67CFBC24B1CF2CB5686EE1E7F19AD3F14453A384D7D7B62AED6C30783895EA6860D02CA8BE2EF98A3DDE82B39E7104FDCC621D4D78B052364F14763DC1BBEB00F8F5530BFC957F12702CD7733243225B7286EDEE93D59126BC67BDB0AD5094419A297751E3F4C6F54F5093D363B07D2A3342AD68E94A20171622930CD70D0FBFAA35BB886225166D71C55E3ABCF6DB0FD2D13D95E8B6E19C12B734E578727F35AD04CD97DCF76D15EECE03F270556E5BA6DDE36765ECB26C2046A8449E37E82CFE48FE42A7C8DBD28FAAB00A0EB470F6DF072C5444AF01D27C78F72D5C028D9B3F93A6BC4E715AFF8E796F139205D5A72033281C416811DA606A30271D68B275D91D6ED18E0F653990C19F76946AA164DDC837FC6105741593D30E10C36C9DDFFB180710BE28B2D08F89EB7BC0877CAFB7B07F2F16A92ACDDE2EA2E44F98022177268965D12575DEC72FB39C53861FCA7D4430AD11AC008A5AB1D3AEACFDE6B9156828AF0BFC2C9C18B5625A9C0AF982BFD18112A5D5AE7E158FF05D0F69365E77709FFE1FF381FE5CD15B1BF0320A293F05649D88F4D3C72863799ED3AC63C23D89FB5BEB208AA64028AD3F0BB6F21C04C4158F10E78A633258A111F323DEDB68FC963B29A2D18C0F5687D86DD0D78B3F922CE06D10865771B07A69A0C22AC30247B94FC9486573F31A910051EE8ACBACBAE8204A594FB02CA9BBBD
+7477DD251C2CAA259AF67CBA1F3D64F54BDE0FE6AC04F8A6EC3FD17FBE4F992922F01461A7ABDD3494A424206D3568F7A6A52D9BCEDE81EA8F616D0A87662D37606FA51774C940A381D4ED12A4F5B37AA948BC65E570DBBAAB1955C58CD2AF28B15B67C5F10F0EE2E52EB5D8F0CD91E11E3BAFF278843BD3941F42B06AE80183176AB00DD64CE7B84D021982F339AD880045B9579A2329B1D3655C7CFD2030859CD123E026133263C16C3E6A7B4F8216B1DD1A8355225FB1A67BFCDB19FA50F5CFB7315FF3FEF8BC38D077C133514ABDC44A2BC2BBFAB3B7C74435993D76A905E16190320C982919F311C4E9059C1C4C7EB3CFC82960C0EC02E8E428E2D10DD23544F7C8C9B0A8EB81CC581723BC1DE393469C1190701789973D010F8E2EB2E71732BB15BB71DA502E7DB2D99028817A77513312237E0178C7AE1FB28B214E6D63D261051ED304DD3D77ED43B40866F9982C5B9EDF07B96A9E156689D3B088CB7302ECC12B62F927DF6DD3576EAC5C53C524C504132BFD78FEB50B29C543E5E10B6B44342E2AA9CD7D16F7BEAE74ED4F0BB30B566C5A02B50A6A0A997EF743581E5BE2B98679464D97ADBB092562A93FA4E63BC4FF4A9CC4D7F386F5CBD3BA54046D333CF439AD3B5D34D91504DDACE3C18D51E227698F12FD005F32FD0C7D07408E28628C2A49182DEA29C8F7C3A5AAE5EBEE414E2FD479B186A8C5595F00CBFC3D9855E064208147C411D6F8E6CF92F931CBA3979517F1EB33BAF603526BAEA28990E09383F546BEFC258E0EFD42ECB99910716F11A30B29CBBD682341F123FBDCD800ECF2D6AD8D98E3ACDCA64379012E2FDB60E9C94D8844208373267D9458266CD01E0B51BD965D039CE4C7A26420328D28F1F57F46596964A659CDF6D7307C785F028C111495C8B471AF7D76A4884F1703D0F6669668B55A84FC03C9300F44F02720348FC5ECCB04262105341B721CC58C0D8808DA7ACFCC2C216EDCD7CE94D943F3D2096161FAFE9105516CC124ADBB720B06B9338D02062245934FED46678FBFF331003FAFADAA4FC39E0BFB835D38BBF8776D21611EA985004BAEEDBD630846692367A7122F64E988A60289203993D317527797CC89F021228E8606E5C0CB24FCB9481EA8C5032EF90F239722B7D9BB1A48504C525EE07A9FB1600B8CD170D4A5176C6CB391DB7AF40CA32E61C4AB0E946A402AE0DB7F11A0FEED24F2F63DF4474ED7AAD674B2BD9E95549490CA3C3C1539FC59D88742831AB6EA311D1A8DBDD5DEA44C7DFEA2A66DF60A0885E77BAA625AB3A26FA32BF953953D355F5FAA7BF2CF8DE545458233F8640B35130C022681BFF3B9FD94D6807797FA1E65D6C834DC9BDB100EEEA9BA49A93D121842A730435F938D13DA3E30A55E7D26B718D3B7E13D2CA9B47F7E6E286BCB3659A8AC5750D4FC927179612B9B936855
+FE2851C7F1017CB2BB4EB133CF53691B124A504C9D0A538EDA17B730EC52EB9BDB8D80BA77421FC2FD4B467163743D7D5D44551B6EE36EAC03799D977C1C9DB2312D8FCC26B8907D2BCB55B3C8D65CA4E7264A6FD3A8E3BFF9A2CE75221FC597AF0740EFB82A6E681BC31A1627B24A2349A43A9D41BA0DF22EFC8B48C444D6C30DDD11DC4D44CDABEED90CCFB7A333210C2787BA8E63A1AA72844E6774E443A43BC77677CE2128A45B3C9A0DE4C85113ECD58D7ECB9564938C2CD3D56BEA3DD1F881DE0BC790E9B79C49F2695B3C8C485F0643A607975661AF862D56D6206998816870C893E1038C07DCCD225237FC6C7569B76B4BD81827270CAD78A61E8796C3AD788992C6696EA7F202EF52281E82B1995770D0BDC8C1FBA209B7FDB70914ED76A3D053C1E2373F029B738ACBDD56AB13247F733EB51DDC1E17821A0C979F61DE194EFA56195A9CB17B5620FF3E78E1DD78AC539155BB567F812B4A407AB068FA133ADCAD77AFE5252109734BAD13AFEB149345C5EB31177F2CE24C4226DF93A8BEF47A3A3A1076C7A6133E9361BE0CCA324ABAE6578F9A590B6FCD6801FA4FA7AB41BF1D46B5A4875BC92632030F2DA0FAD3EE05D349C849D635301182B10F854677412F7ADB4B8A9ACF8B7ECE68E34069C311E76623F66D908ABB68AC7247E2B2061A33EF1FCA50858087F71016536422291195A4BDB78C97FB41C1F0E5BBB183318FA61FB03DCBC67866020B1BEA34CC4349C40570DDD0F3E577DE1BB1A8592B77A81149FCEF387F50E9272941EE448C171B7A636DBA655E20DD4E47E8CFC8A3A7A89BF3AED7EB34123616EF19AC9B26ACCB1836A57206FA716A024777385197F0FB3686D75A2F89BF8C417216BE4AD18591C531718F535AA82B027E9007E7BF5C7D3DBCC1C0AF93C3C78C0E63E241BA3A7EDD8FEDCFBFAE18B5030051F7EC836E0A95D7CF88304829F62B484A0E2BF4EFEA0BE555013D0DDC4FD7C2BFA9DD0644D54F3FDA84913018448CDC92DD8927CB098DFC72458094B5EA10855A349BADA9B93E181DEE4A196BCAC3E82D3B7E50D217AA88E9E9B0D9290FA27D4DDEAE7CD427E78B1A0ADA74B5ADEF1DD80FD23E6EBBDE8AB6FF8F1C65723724F6A17FD4A602E714E7E98112771F224C100496974918B0D46844798E0A6A48BF94ECC3664375BCA521B7971DD9DE4C664D833B8A7452386DFC920D78CCC39B62C27094BF80D62A8F1A1A55A7E1D082D3C2D4601A4A1ED00D67C754DD22B1E87905E54EE262BE6D465702D1D72C94F0C20CF6FC146C9C8BCC7CCDF95D5703F35EB03C73A661F2B2EFE3DCC77C94D105199938D849201180BECD15D97657F515A1A9A34B5A8949B046CF4EB037C3600F4B1A9C725EB805F384309C95221949009AE5FAD85C8C2AC12D31746416634346EE6D63B62C0CBDC2245710F888DF780C6AB3
+08B05E9315F78643D6802CA77B0070A7665E0CD22C5F390E07103DF272826430634CCF17099FB9A240B5D8EE6D880C333A178448DBC281627802081175F5E2A023C3F79E0A804C99C6F7503EBB345A1545A6037C178BB46273099BEDC197DFC6573D80D0B0F4B71582C101FF756FDF5E66DF1B04022B0F7E8FA8BAF016B04A330FD8CE64C4EDCE918E9BA6AE05B5F7DEEEF5BE6EFC106E537A118F98404AF994F1F15456C9571AA855698936BC42D9F205EBA1E49CBA54D11FEB5782F6E87DB7042785D731A82DE040260CFB4E7B49E7B233240AB434F62294B4DF875399D9DFCF2DE85316A9675481AD8D43B2B8357FA71FBA06478C96AAD9414D83BB73E2BA0FCAD4E57AA52CFEA76CDEBD10A685E6E1EEC6592F6233304934D0B28726CF13E32674087B95DF182DEDDAA6CEC8F99E47FA6D28057B1EADFD973C3C8C18E395B52F1384605B5F55F2A3527023AE3BDDB86326F59F9F7D8D531A73F01E02D23A67081F766A13C0C6FFEA89E49BA79F8818C325DA0BCF105E705024F3EAD21B65CBD5D7F314CA14B64674E26537085A9E8B92C751B47A8B45E9F901B81ADA5284AB5C74E750FA776E08D9295068E6409A932C21C736BFD483E6EE953B323B1A266EE6F37D7571A2F88AB0AA16C3BFFAB58DAC4B047F2CB37D5A9B6F4D08FD96E62CFAD600DFB830660CF258CBA51475395D1F3C067839CAD6B9B7A4D16822C3EF7BAAE43E3EC6411CCD46616041654A3A1BE4C9079821E3FD7389CC01559A99F7B2487A958983409A3A707216767C26EAEAD9E1A4C8A8E6B59747A162CAF79026D7D87B5B096411DB2F09E58CF1E3C4817FEAB9475B994129541A095F16F0C31EBED0C03CC235A1450DDA33AEBAC5981FC3AF444C09665D973BCE1AD09581F3A29360104EE9E2B7C6C30734C47C0084CC6ED81219741E74F8465AA616C8867B5C93059EC133E916EFA01CFB905BE09742EE3D27EC6FA37386D5330723CEF2BB33362D700F288E25B1593A2000932054FEFD7CC3A09FB593FD356B65379478FFA6129A305ED5322035F8AA350817C1809FB8A4AA1991B0276B8079B29EC0D58EB1FDD133AEC86A7A86FA04DA4D18D5E0B5F06C9EE40B5F345DF5DAB6471976590BBEE58A14C71B89733FFCFE1AE58EF4EC0AFAB3C328E28C4A2C07A6320FD73838822633C362673266AAA8662AB27708FDD217256F18273140B3F0923EABA90EFF726957E15602AEB88719292BC028289C77623E9B4B28750FB121BE2888CD86085B7495D01A12E92723D1BCC992EC8A664CEA2F6806C5243F5B612CC2BC4DF33DDE9B8BC6D94A13193DFF5EB8258B9609D01444977EEE8C737404B6432B5D02D67A9DBF2E26597DAA0B49A676996D096304ED7F78DF36DA94A6ADE81A6876A2BDDBA8D72D26146AF8DCE8DBF3CD27192712A8FEE94FEF7CC40B154D82061A5B12
+2BF0944E7085A47E8B4086420F04B21B42B7C4D1CEC9DB70856380F7A30FF6FCAFD0CC0E657018F1856528E2C925639C9D05F67FC3A2A2D9F99690FEDDEF65B962462ABB3138283BF0D39E3F17306B4347DB069ACE98DD6FA87E42269A1994C749AE4B6146A3D092BD84AF7F87D6C8B1A794B7AB4385E65B672E78CD64DFF80D7C74ACB18E8890F38F6359653A2575C593BC89C3B8BD15EA521C28F2C3B1812522E7CF0AF52128E90C57CDF3A30D88715ED700E246A196DB1D3950ED8B4086420C7364E3531FB60930C9EA0D493BE927E28ECDA1E02AA8B84498A89E38353193D909E1A44F5F5146E472E5A9E52C5CBF6D86CF1726D5A30D90AE9B183230644F8ECB59EF9E7F2A7D744A1C09FF42141D79A3B84DCB51FF13112BCB86620C29D5FF1DF24D5AAA618FA7E4D94F1E0B8CBEFC1CA11EF451D1F14411F9BB715CF65BB00C3FEA07D34E36F706ED5F2A26B5AE2082415ADEBC8D92A870D3BC1D996604B6AFE604E2966319A58C01EAF01721D82005E805DE30D5C766F235A9F1884D07F73273C7D906904F202AE2ECF3C76D3DE01161F1196ECA09D8FB0AC2F7A38F8B4A7927AAD4D0A9BDACCAAA20EFA24BD33532128E60D97C112747E5F3F7410A86DAFB43D4EDEF8D8F08668045C6C73FE9054A7B26EA3C4D417AD005171298584E36698B40F0191EE7C503E16C64C3D5F79F2F0B599BE1E07BED270B09423C65854D342CCE92A93907466502688EFFCA298F481089D90CA3D59BE600685F558E3229F70B16BC472ABA5C338673CBE1BE57EFD5D5F0577423E99B7B895A4A0258F7D6740C2F01BC21CDD4DE4B08DAA5FDDFBE8AAAAB481495DB7957A72629AB222B354C712100B04DD6BAB8BA8F7410FF5EABEEEAADE8C51A057E4F84A910851AD3429FA45E444BE002C79423B11D418F80FD2E20358412DC27F0B1BDCA3FBB620E905F0E27929E189FA7BFDCA71584FC75566391A7EEBD1895B7D26A773B96F87264751C77DC6D586B0D7D30830F820ED5242876ACEC6DA3028E3761B1A6B1E89DC74C3537B00A783BA73343A21FA2AFFA5C7939E07CF2F1101D863A280F286FB48D9B5194058BD2BFECF8CC2C2BBEA95F8A9079DAFE098CEC33751025421D9554BD8679D4C2C0F82FE6698B2CFDA5FBCFA0C4EE20198147FC134DA42229E99B7B73DB5CDC3B5DF503A5BF5D3D6DA972CAD076949127C277880BA28C0924A5E347A313632516F48205204605AD5E741C9B80638983AD222A6F94CECF12AFBEE01331F4DF4203CCA8338C797E5DE46EBD000B6B6E025EB5FA35CB2251F24E8DD0190E14A615C0205D0647E97574B2599B1C4DC82A624E3CC186789635A1DB62D637FEDE4323CB12B03EC8964EA0FB5762435DC3AEC478226882F68E3BA24002D59F5F92BA657CAEEFFE22B202A1D8B27B98249581CE81BC8FB5C30F4EEA6F749022
+0F8A5C01F676D2B72F9A50A2CC1D6BF658C3887AEF0E1A6E607DD795B18F8B863E6530822F19A30309D456D3B514C8BD176A6D5F0EA2B949741FA4380226F2136A6817AF9044E7CF9B32908D3567E03534CAA97FB1FEB6B3326DFF2F2E48BF7AA304229E9156C2E1F8F03ACA302A410411AFEA7CDD643BE09050609CE240EE4597E80B5E49D129BBE74C2A391C8DD9B42E9D232512D23CDA6A30C42CD262BFE6E1D4D80EC2F50C5D6B034EE530F5CC8F2936C990BC4DE4183A5073674E34C8A3748D0CF040A7CFC06A9F1981781692633C9D3F3F8914E0CD57A82D62060BE90ED20F8B5182E21D2ACCD2088E8210F14B74F71EC5FD15AA7FC91C3328A767ACBE12094089BC64FC248DDBEE95945979F4C59A9315EE47CB88D94F423CB32AC8DC2D3FF82469019F71E3CC576563342E824B8D66D5C590AB24BCBE242903F64189287232C06C34186201FAB2144DEF670DF24829A1CC2608D5CB5767D929CE14D9A6CB1FAA8F7487B32A22C306E818C6A369E6A54AB09BB55E36333A2DC55C09EA2CAD12541A5767123845F96EFC714D3863A3B0F343BAAC7AC0971806B710C07DEB5D129DC33022023B62B9A760D2ABC6DCE87894C773CFE10D88CD91683874A6FAB9D28597DB2E32D200C3D8
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+ %endeexec
+
+
+type42known not downloadOK and{userdict/TrueDict known{TrueDict/render known not}
+{true userdict begin/TrueDict 8 dict dup /version 27 put def end}ifelse}{false}ifelse{currentfile eexec}exch( %endeexec)exch checkload
+1861AEDAAA5472E4FDE5287D4C4E53EBA61D516861E6B44ABEFEA3F41AA6265F561EEA329F99C57BE14D599EA9627B771E47DEA5C3F4348515CCD2F77B6D7A104A321F49A3F7E10CCB09E0F18E3DB6F66BEC10C986A33AEC7BC881833274B6807D8D4F3871CB44A265B633E2C2E88DB139C9E100B819F507490A87FBC0C2B35F2D264C5BF78F3FBCD4069AED9FFF05234274FFA12D9FA2205799ECA89AE87295C17598015BFC7E1C31769F9496E96CA921DE592EFD6F1F750AA4E6EC470B6C094EF710F5D52F74A4DE887B9D64E60C8194DAA4A97549158F44A258BEB54121B794A70AC586FBC1C7FC08E30901D89FFBB02A7E6B18AC4AA0B87C05A4F8FDA2F7A947FBA46D1CF7CFC24DBF78B2DB3E9768B86982D8312BAD12A1A77862F21120AAAD32F686E88749CA078F054DAE900EFF33DE0F508EEFD7A605F271626FE8C629A60556339D879D0049C47350BD3F67C051B5610706E203DBF71AE4F022A716D1E1295916BC44576C02C55257ECBF8F5E9978ABA5742AFC086D508004673EF7F634C37BEE15A5A2D7BB9BDF95946025CCD907FC204526D009010D953A648F332CB7C1F4C094C18D16FF74303642A5C522129A1320CE2375DB5354D81EE91BA309143F40F2EEBE2C923FEF9A2E82D1192AAA3D65E1FBFD3A2FB898B7BF45EA41B2D98C80E736CB4DF517AD013A09B8027728007E608709F2492DBF145A782E5056A54677D237F743042C77BA748DE556814E31BF124E4EA043081DBB688A63D3DEF0A54C44AE435AA184180B30C6CEF3D9515DDF1F1998974A77EFE67EEA6F0EE9DBCAF5AC7F49AC49F5DBF093A96A943DB165BC81558F72DEA242A46B424C2245E92726A0ED5DEB702F488DE84A248137C29812514D077CAB67AA0BB30D18431DB3A0A03FBBDFB84593889E622636DE8DDC651512725E702F174A0AC617E94F528DDDB567BAC531E9D4A5571124811FBD53CE7B519691F99392B27E62A9C5C904F9B21521D336FE10287A84B2B6A5DEE847D22F7A062777E91B6C48E91472CD18A8C3F2E5317BBF9EB737A46593987EC1C972C27FA204FB59D59FC6DA487EDEE3ACFF771A6A2EEC32FE4378B6FAE314454605F271AC0579EA382FF19D7E75DD5020E0E8BA9BD142280D59F39AD362E267CFAF0145997A6AA9602D782193F67F3EA1E199DB42CB9C80285FA7E2E28F97E5DD05E9273CB9A6ECC5C2DC7F47C63FF4640D840CDA0F775B826EE06CB8F318F1CB2A79249C639D68FFD1F0230121442185D825AAF3AA95D179E8589B0A1868B4AA8B588DC9F27E366602F73E7996DE83E8F15F1DEDD3477E05FC2186F7A4918C3F3BCB5306F22685639EC6C33EDBB70A5C79C627CFE9FCBF7605C5D64D5CC09E934E14FE746AFF7B3A0033202D1F10752D79D418308AA0D16B98A7373FDE8FE28F0FAABC46B65949463E020580B43A
+99D355FF1424998FFA8A242AAD3D2B57CDAEDBCBD7EABA48D401AE54840D338AE621A21C2EDF6056DFB5B585F84628376426111D97DBE58C944A6B9DD9CCE9FABDA3A09083A5DAA9408CCCAAA71BD7CD7E6C7B29D23D9643C1A33FEC705C9D17F44AE8F1D88C672397588E4F07CD8C579A63D3801D58E6D7C178A4F0A502269531576132BB4EB53E75ADDACAB718992B06FE4CD1A03AC0CFDE20E3E2306E8C2763A1CF6C49EBF66608AC420174133481D6068E61FB009C95440F2E1988713E5ED9735061AF2CE5149A92218F05819CD35697C28DC00BFF9DECFFFBBC3992B99F2A42C2A95B86672B8DFA1B5849B2F19F6FCBF37AF2C7F0BF87931209BEB51C49C00822E65427DA586AA08A2CEEC94F076743042AF365B5DF679696F5B30857F4D00BDC3833D2BF87D2915798604ACE456CD69DD4D1CE1DCDF0E8A3AC710F41F741A0622A13AF8B0136DC17F7C0B9D64270F955CDEFE3833BBF97D5134FDBE11DBC7B6391581CF5E5281D1C6F1085F963566955DABA32CEB68076C62783870995C468A2CABEE6B0CAAE21E9536247017E15F4F47A225FC53786B2B5CAF485F0F3E093C0953A16C3D1021FE4EF6DD6B9816E422A39AF591AB03F9DC76E052D7E8A0DEDFDE9D35BC88CBB8FA4693DC26A71C8D1E61DD5CFAF42890360F3806E3E02CE56D754A6B5DFEECF9EFC2513C4D63AD9727333B4795A2C3B071F9F7778AF76C4B057B3B1F56DF1DF4BC6D30C5ECE465C2A3C97BCE6E9C7675938671CE32379D589C8631A3A465CCA2925A0CCD58CB2D85A124C5A27BBA1B811AF904182E5323B087EF7A916BDA8F253FEB8EBE44FBF5171C29BD204A4E10A812AA46AAE0B88E563FB7F119F6DA9679CEA40E9D66B3198E6ED8ADA6A79ECBB657E1234159DC811C66C3200027CC9DABDC508D610555C0462AA274018AD7F25F2C9FF6435C257B9CCCAD57A220AD491B36C62281CC95AECC1EE9FCFAE4E6703F12A6642E92606AB70B2DAA9A03E69DBE7F814B16402A58C50956106C9F9D4ADB6D06ADEE309A3771BE22559CD7419EC67FA84FD47E3CC97546344C982BBD63544860BF4EC044274BD67C2AF0A7352DBAC5183FCAAC3D04E9F923B2C7389405C96B3C71418D5A6DAAF8422FAF3229418765EAB198679E1BAE62EAD505B67C84DEE812A2B727A2188F476A90B0BF78023173BDE4C781D557C615E1871CF361C494C1796D06925125A70606863198B0FA1496B04E367F8527E641080B185663C9A32926B8539A7B4077EA27352C4A0E41FD869D11317F0EFDAB26C9F0FD4CB606BE364A6AC5476A532EC2CA5FECBBDE484150E0E2A9CEDDE066D821D6BB51085FB372EF5968DFCB16FE13996EA1161091F7298A9B813684E5EC58B7551461616D433442C7770D4670C1C95584686E50EDFC5DA2C9EE66B498D8E2B1F204F308D5631F98B668E3EA9
+69233326797183E444EF1209F1563B60A8332B73FF6B511DD6FBF87DB10086D7DCF66EBDF929C6F4E95FC74CB4C80789CB8DDC7A6DD6E4935545E55FF777ECA8A03B3521FF2F5FFF72E749350BECE6D478A0F28E179D639F3156F54B5AC0292A6099C5E7F2D50C792A33E3338EA4D654376C86FA665386EE6624C5AF3F51FEEAEE722FACAEF4553F795A224FD8E8EF9076824042432EFA70AE978C1855C17199232B2F2A551888E024F91062856EA362DF7DB1B6882C27C4CEFB993D97D32A63F25EAD0CD8E9B55B96AED3E06AFBCC0B2A228E860F05D371C9F8EBF67DED0B0ED24E230D8E79D01C16A9A8E0B85C32025286B884F807EE7264C489D0A289BCBB711FAEB1F118922D19D9481A68E598DDF17ED26DF449F0A9484367FC5DCC6861D05A8FEFE4295BA80D696A9305CA6C47CB279EE520D313E6001A82F3EED6B7286E1348AA7C7B44D8796BA71C0461BA5CB0996AC4405145F0C2B2FFE30F61F52AF08C01A9A53F278AB66EB33335CDE3FC01753F1E6B68B8DC251DEBC8567CBE3BE025E2B0792F8BE0D914B8F729C223DAB71E29CAB0A13294D32014BA1B3B91E80AE989EC7A91835B3B8885217B6A32106D672E49840C8D4EDC19B6777DE7C3D004371EEB3207251A0D18F3CAAF47B4C555755551D952B3EA9A3A1EE352DB161A9F7316A5110AAB33DE798BF69C366EF87516B4E0ED22D50A7142D964DAF7FAEBBB56B93742A1606239B52854264BA62424E6FC2EDC6509F5003F8B6E3618DA9900523A4286D6E78528400A9BFCFA1E2E2FDDB09FA993DAE2631392B55283AD51D0F7FA006BF43BD3E0864E5E8081ECCE10395662E3E0C0E5986CAA738A9F58107E4670514A538BC828E067C0D425C60CA1CF2F9714A150277834678620538FBBE3A0172AAFE0AABB26FE907A1CF99C84F796784AD5152A0D0B14C4E45AB5E2590B3BB1F17119FC92AD39160856C35F64520EB3C49F826E25A9A6CBD4115A2822052C5B9F56E2E7C0442D0498AC55D96A91E4D80DA062E644EE7C3C04E14AFC84521976FE27AFDDEC1CD1636ED6E0259BDC590CC5D18DC0461002555AE792B012ACE808FA7CEE68FDEFA04CAD5103D76BEDBA015904D2F7916F0170CFF5F6B2D51D2B8BFA231394D44F64524ECB64F4170BD3C2A4A5BEF2841CF47C5E96551B5ABAC4A9C43A400B1D0236B14192A90786E15B642D4AEB876C943E41D667ECE444091182FFD5673936D0609E0B4187557362A54DFB75496622CE388CF929FE6B5AFEC76231AAEB1B3AEDF82831CE8B4ADCDA23ACFCF519D4CEC99919ED5D3C91840EE3AC7C07B71F821CC982709A7FDA6230A91BA00B25ED9F52C95ED286D6DD80E3C12B496189521968ADA7147E4D0E812E156DB9195A33D565162427906F907A9FD08E6E1CD5D65306D219D14996B605734AD3B5CF200627FAB98F1ABB9507B6
+18F1DBAA43212B450B4B431BD5C3F51C447574C4FF57696E6D5B773269A63A9A1033830C5CB6D984BCB32A8506D478B551B31A71DF1A215C5A4435DF7117FDC8945B02A1BD212431FF861D23C29CAD989BEC623F7809FCB26C736163126B2C43519CE72D9737711741B2037EFB3A60000110D7F2C8EE16BE6FB9A8FE906A742CC5BB3ED52A3882859810CE3813865B352620F08B9FFA16C10DC601AE8CEFC83AF1360F1E4A2BBEE41D4EF78A387766C750D16A9E88E4535B9CF7641AB0FDCF69374C26D7BEFCBAEE854A352591D0EF050B20A22C584FC27EE179BB29AC543DD35C61BFC87810D7393E65E62D7EABC544A2E1A316ED9F7C6244D36F5BB0B473F81F7F58DBEDDDF5C377544FE67A800B7CF6A7D2EBC63984140E8EFBCFEF2B3583DBA03AE52CF6496A91953948F8C23332CD31C0C312854E7238F3646567D681FC0BA32146EE448D8F1D1FDFA1B8E5188280094C8E470CDB430361EAD7A850F80E63B7FE1689B68FCE20D46D831153DC9F9DAF83FAC7D9ACB4ABF71E9C4656A79AB46638AC59BCD43151CD7E50BE3730E64D583318BE4FE0E6EB06E58E5B9C76C5D32229405E0BFCF7D4A690BC13A0793FADA35FD6A3B7FA47CFD258676D6BBA3DC726AE19FC410ADF5DE85017D480DFE135958CB4345792C3C7EB6F50E77671E2625E44DD6BB3DDE8B06E29EE9A3CF2E1A01C7EC7143A447024396A9C960C4D14EFAEA510254A7C73758918A6CD7F94057C147D037EF0CAA4BE7493F6490CAAB83713F7831393E7443B8A76D4D257E457355FC5595358A697D4E6933A79E1DB23839509626081B3AB1E91D405D03A92AD926178807653C4F0BCE1EE2D37329D9B9ACF684A17DB8C077DE318C122002F21DFB7A5C56EABE159CD516B825A4FDAD6060C468278EE32FA93C14CC75C8782863E53E9AAA36890ED30DDE7506AD5F12E5CFAB963E3C51834E7E06C48575C98E1DB702DBD2BF82D1596B9663B34FEFC46D3C588626E3044D2F0B69EE753D4C0818D732C2735D6C8C8DF959D0BF6E3A38BF11525A17892949B59AC01FF0CD275B84DCC04D47488D91660582A57DA33E23A8F127BD01C46F4FF6A282C6EB36045930C78DEB48E5C46F602EA986DA177065BFA94E4C9FC80402938EE0CE9ACABA6F1AA8804FFB3F2031BE98208ACB4976DA470E31D5C8034633404D0418D7E788C04889862E9EB5CBC1757AC01137828EEBC4E9F47A0F6BBED728CCA0867BF80D07F6A76ED8F0FD940636474CCC71E1E7E10E8BF28ACBDDAB024778D74D7D951904D51B4233B29AA0BA1561F998B7F4EA1563262F6211861C58924AF6F163EB77AD68B1CBC7CBA8A852470306FA40B6FD08B64AB59BD5CFB2DD82E753E4A9EEC9BFA30254D1DA54E857076D4DE0BAF672AB31587A7DF0756A6B2521BE938803099DA148FF163854F2FD3EFDDEB22CCEA8E0D
+B77ACEDBEA3420EB257A65EE2A08B74A1D2705D454B487DDA26622A307796B2E61873FD6C5466490BCC303C90FB3CB148A77B9C3F0863E9F4F61B36540C2E1C4811FFF5C7BA4CDDC807CC50B5ABF5FA3E98C0C54EFBEEBBD78CF5261143E8DAD1714F25F855DCCD517AB636CC29CB6BA014D6577B1FA2212CB985F273F8BB52F75FFFBF234C8E0D5DC6BCD8E54B2E77545FE35A406A6C26C483EB346F52E86A13A694529F2069941A71541D3F0E1988F08CA3EA553EC909ADFDDB33759646662A5D4D8EA8CE44A90D5C60B444F169452067B3581425A8404403924770D83431460755C75F52BF42D23131E9C704F7898D7E7F0B8B88A623A423875E59F9928C79085170D46934A8FCE39624A513AD99535C557C6CB3F988670C6F752080EE3920C528970633D9A83E0EBFD1D35B903A07B4ED1B32FA91D280E0E3EB0700A9FA6FCAE70F99CDD1971875A56C8F6185B911DF58B4895D0F80541450B9B98E40838E66D869CAB3143F528BBE7D8CADD33961270D231C7FB5660764842CF195B654E1D4DF4359C114735E7412C395E628A18D90088E4EC88E72CB1B4CCBCCC7DA056458D44AFE5977075AB0C85F531A9390B1D7E7CDFF9EB719A4DD2D5D8E3D5D74E591AC9583D7822E80D420D7869247150077EC2D448B80671694CC90BBEED4DAE7B22D425E3103BB2E43AA4501C6183A4E9993BC194C0381B986CD7B6F34383FB5788C8D0176601B1B170CA5D4AE28916F03E945F331AB97B3C24952EB445054191D62D9EA083B9E6DCE09AA5534CA12E273A55F5D594044ADB7B3083B7F2442F5DB85FE2309831F492DC3CEC98D63BF21686AA21856E3464B0E79B070696AC7DD3E367DA2CB7D9742C1D75ECF0DF46FA1202BBDC861C6650E98C4C49FA4B1C74C1229020092B0B7E4DA40FD82E00757FEB1A888CB16FCF266C45B6B9A6093955A0DF0C1E974648A38E1B6650A21AFC284645294BD4F146DA9CF8D0C6C5ECEBEACC6C22A57D735DF41B67815DF8A5FC7788776E603067B6A1EFADC3DBEC84F7448BF9FF23ACF233A5FB850FE1F2374A324C6EEB0042C41BED091772AA22A139CA382D7E75A40D666166F7D7601D86A1B0FD71B66B7C1BAF210B8F3AE23F5EAC2FD47E8A8D9C4DAA78A0A4236CF79BE24A725E9297E5806D80D7295F5322031B083E950C7BB9BF79E759D724413A6CD6E84B3AC84433988E6E36FA3922FEA54905C7083197823B196D316EAD2D4F34DA595BE04392AF83405D9A3695BFA739B710E2F187776AC7CB3E6B97E3B52778532DB88DA829B54CA0757C31417A436723327046F914656E1EBA3B6AFCB44C30744A37AEDFCE4A4B65500CB7330E7392189D38BFE1C64D330ADB7C6ECBF5F58987CB2F41023C5C7731193D2EC0C8B6845436B8803194442B6C8954EE5EE75EF02DB6475573C5DAD8E24E1C28948ED8B05A70
+C7655949E120DF205173498E05DE282704552FE9E73FCEB17B035836390C4A0D31E14AF9D4DF5728028F406E83E045C0A540EE5555F9E9F1DA84B220B09CA9D196987FEC306B73B061C2F3BA9EB267EB79BF1D5698FFD905661C0B064008D6E30D752CD07A1899F82D5D85329CE49B26A59E7720CB375FA0061332FB2B440B4C9D00D299944DF24F8DFFA6BD234AC7CC75FF8BA922B82CDB5E86F8147BE02BD0143B40E7C91FADE5F124B88E451F0AA4D9465591B7C5A381CB1C9B1D0A18177DE4A522BE7C1C205C16E1F1EFDDE7FBD60D1537A94DCB8A60F8A688A924658C5E74A2D4A74BF909C0AA67B15EF87E86EDEE33693850C16CA241D854127DC9E63F3CEA37E7C85CE58CE8B5BFF264B2D0E4B5F03B61BC8590827D2B9D67A94112BF0EBA0D1A88861B6B64DA1EAA6F12B01D53275228E69D6BE2A1788B37B4EADC88368310FFCC4B006A7C8F92F09CD31316BFE7B5ED6DC6A6981724C6A5073ECB4B3F2037BAD7668513F3D9E9EA5EDD92AAC08224C417E10068B5647C93BB5A06E6507DF914082C0AA9BD6E7640F5722ABC6E7EE7B776D28A27C0E1E026E68D2A44A6DE168C3F363FBC42444FCC5D5EC89803BC6AA7A2C27EB18F57A6BCD4A37378E5806C86243008BB05F86B93FE11B05AA369A56A0F96FD413153ADF87B34869869C52F9466321C8E57B3072C18B6273E668D7FC990192143468D9B61EB407A6E094A0B0835ABA9E3537E1F974B6823EF0F8EC023499829CEF7B334C56B16842ECCF40DE0BECDEBD5DA6FB917FCE49AB546FF0E6817C01D14BBBFBEE65C251359F52C979AB9C12579E06D3C0658D64A610CC9B84F7D73AD1096A6C43F5C2802493EC5C6F9D432FC26CB7E45FCD41E3A7829853F3380B61D83AEF2F96D18EBA626FCB7DECA9B801332E321C9E62A345E1C049A934B6812672041EE283871978F3B019F2198F0C9DEA713003C1FA37A9CD8E164CFAF7AF95F92723D7D03B533BBAD7AB92D2D4447E9188EC2667777EDE290B6734BA6DDCBC687A223D929D204FC7DE8432B8F3EFE8A5E9A553B9F531977BF00F644AB91EE41F5BB7BE06CC69E0759F752E0BD618D6909C4F4868A2B1BC2B7A97B3A26AA92543DE059D30A4EF8D9C62FE5CD6105E10B21152B42E5C05380A0015CEF43BE1F8C1B81BC5F87D507ED9173DAB1E027090A5F761C980706D688D65BC737F3C9FFE403542D380BB99FF60E0CB0C5E1707717C4ACC6D007BC4C67A666EABADC690F0A702EE2C9A36595AFF9AA1DA3688B7AA16FA09FB5091C19AED55CBF6FF2373429E3A6381388E04CD77E94C4FED3060166C2E088ECC53F79D2B77E753C79ED0BC3D13D8F33857311FCA74520621F98A451863B301047AB3CA58DEE3CBB1A7287025113453C7F285B84F9A64E2C66E1940893B7509FA368E73B533B09898A6ED747207C10F6B1ECD80838
+8101C8751D1FD32C8056205C83E4DE989EDD725A4F96F5AD02D7B4A63E8A26CEBF9E26AB8A21E1A8B87EBF4A87513B398B912449361CC59CC0D8F46D63B7A81553D461DE9D9B46D861D6DA6EEA5212D81C4ABF9C591ACF6A1759AB855FABF12143D12F46ACABED307F23F1C04D456A9F607D99486D874998CC52D294AA5170555250B67381B9CC77F6155DFDA86A084CAD623ED172EBFECF8A1FF6C0294875B6893B405755EF619519F2D8C2AFDCADA5964B811C8B6E422DF13C4AED13A196B2C14FA2E76CD26D4396E902A5028E3AAC8B98260451589B88CE2B4C4A23FCD8C769E991F90B335AEE9DBC3DA3D8AA32772F37B94B0ACA332000BF18FDA20DDFD7D65EAC88EAA2D1155EEDAC4A62B2F85C66B92872DC9319807D8C62D3A8D95E019C42A097A54DD80111EC24130A559CE3977A38CDE8C5C4B37E52FDD49EE956FD66CA1CB0A29AC2D482F0E17F1666573D4890829E21C4C3490781E48CC41A05578FA0C0CDDD62B78086FB9DE87378B2D0CA311B3C8807F5EF8402CC15327EC85E8212D6739C218A12D88E7E9EC6A8D00FC6CAB1EC025C90D491EE305C81721B1A4BD257A90B669D5861A7BB8588E0728640A2622DF22BE5E787F95F0FCA3B5B2F24F6B4A6D3CC2F5FCC4873D999DF931FBB3FC5591247533BF53013985FF8922FF44F74DF9C37E314BB6461D071F144DC7B14871D86D7C8A01ECC05CF4864B855FB26761BF9562F9E03B6A29271F4F030B29821EF2E4A76C0498A23E723653EA5E63AA2E23AE407BEFA06F5A178030275F5406496672AC4F63EABEA58EACBB2C750118B6BBA58FF0DA32FCBD57EFC99A5AFE649C15854D7857454DE5BCBC9FBAF4AE77BD4254E98E181CA1120D6ED2EDF7AF37FDB68600941A21AAD5DF910E39095E30DCA8C0AFCB10C80858515698057F19927E2EE5A0429B8E7CD73B6626F559EB49F6DE9B8BC4CCBB41DB84683411A5BF9CBF510A1C6B39BE54E1C6AE7A6ABB4EC3CF251BF27C39DA391869D43D6BBD1D94464EB3D8BF7FF46880C7A101914A7A6B6D3B4512D514DF879182CE8CCB9C62AA4D4D323806EA3466CF9D075FAC2770232BD693A3CD6E0C499A70EFADE31E65FCE6391B1F6B9B7CF9C8287080610A019421FC53A6D49BBE7355FB6B33F70006EE97DC75975987879BE914859436935D909004C861F24B101FD74C679DFA9CECC0F37BF61A4CE7992FC0D1AAFAF9A57C2DDF23409DDB40F509F6B14B6309BE827FBB68886E9BF8EA3673DDB04C41A30D3BA32EDC6916C40DC693CCBC47EE499DF9746AA6EFCDE477D8ABCD27AB4C771A48F0472125C5B5F43015C42822A5CF19E15F261D50A56C688FA6BFA7CCEB62E623E7CABBADF1ADDFF86D5E87F721A827EC12B5046250446CF89A1AB266F7CFC02B4F8F15AACB92DA3B3E9E9475220A6EC6F0B0857DE23B842BBC6363A04CA
+52B15AF815034089F571745CB5C144C235D553D5A10244390A5DE45CA12E290E3C9B7E3FBCB02D487C4BF540463F0E4808D6F3F9D55C8435A3D849ADE039B16360A94E8B8ADBC69D6B61DB605596E3BE95AFCFAED67A9D998893A5E0F93312F0B30546E17C69C35538758EE0BDCDEC9E30266745150C12882DFE9A2533D13130EEE36C0E05AFFFA422DA6355BBEA19A312DF159F094811E86F4D78BE476113A61C9C5A0776D138FE937580ADB80BD8B1A98F8C0587EB176934A0D143AE32B81AE66779ACE3D33325FF2D36A7648CCC8251A79507CAD09F1016BF77049987E3A5A328BBF4A90D70E906737CA56FF1EF91BBB58FD7E769A547CD5DB3663CB11E446B7A3A3EBEDAE1C3CFC06A98AA4C90E98C5BDFEDAE934CC61E42CC2618D2FBA426EA97202C07B49E17CC65CDF8615687D9AE6C616D2BDDF14870E0963DD5E2580AA6911FFD57D7FA8D16C90039117526F3DD9A6E3DFB1E554133A4A421CB03CACF15551E192D32FAD3EE410D661C4074E208920AD8A6FC4D0F24E668FFBE9C5671D3C3F28EBFD9E95F49CF9C03DC11FC1D9AD85BFBAF725709769CB8F461866585A2F1B93A074ABC5B7FA4548DD80F4EEFCDA32F5E6545982D977B5F11704E73D08BEA4D1D4D047A71DC3BE69768E7DDD4B80AB8BC90130A3417C8A41A3899A4DDAD64FF917C686BE67FCFB43F8B508A3D2E053B2F3F97C0574CFD340FC8E7A92472C420DA811B61DCC55743E8D5EBE6250B2E9CFA606BB843C0713F8976798D675F8E173357AD4DB7E3530C6D4A71ADFB3C98246A2FF0824EE3980F0B1A3F95DAE33BFCD4EF4FCD1FCF780A949A7EE699A3ED29E0EAA42F5BE3F851212E6883A12A168BF6125BFF6F1C2337581A39DD9E2C328ACF36646B7682CC50B75B2E1CC2C9718070A3A3894597149A09F2E5EDC58248A1EAED9B14E48F13C13C2E0221D3C0981DE04A08CA10C83873DD3B23F2E310CBFB3DF372FF257B2B6D36E63AC9DA6C3081C7DDDE110331731294ED962C65ABA1F9C9CA785985EBC965A93DE267AFDD7F6E3604FD3632DA3100B4437E40F44AC98396B4425326DBBE0C88B189721A465F33DD57D05C5BD95A822549BFC611F90B4C49A22B76C6006FDAEEBFEC18BBDEBF17EF872DC140204FEA1FF1E131C50AA4126828F11147B3882AFAED5D9C1F6F1B9F43EED8D0E957B909E333B3C3E7FDE21A292F9744E49392FAA46AFF27D13743F550E5929EBEF5985DEE2C0E419AAFBD130C5337B9BCC51C442D59D4BAA87F1B5A7805E8C57918089FC9EEC715517D9FFF8E7036EFB4D1B2CEF2561DCB7B2B235E69565D9FFCFB8B1460B72CB421745392BD327B4FDBC4C945BF1A3A8EC0A7C7C948ACFA90E91B1422AAFA8198255DF3ABC02BF1603E985C96055D0309C328663DA3FBF769A5AEB526A8C078800526CADA363E38A54572B48D6A9213B5
+816C95139DA6CEE71B4556B16584FF56926DC2FCA6BA8E88B3566A6DBB4BEE5135EF7DA7B38322F48B9190E5A9325500A1DC6FE3AF2EE8374E660C2FFA0A6D21E4FF1B4E94B36F6F9BBF0AAC62FDCA5DC221E6BCD1F6193692F30F57DEA75D69A264AA8910611B4BBCFE1D880500D8C78E07534BF53C70ADEACAC02F6047497DCA4F03967AC3EA09AAFD6C5EAB146FE2DA7A7C99D4E5D6E29B1BEF93689FE3C298AC0A38721EF6A10CCAEC71D8AE2F3BC5A7035D97A702C0A828351B8B893765C19DF8A1AF0149F5DC1B8AB2B323C5633B8777EF50509E50A72FF57E84122914D60B91245BA1A1A4E2F8E31B95EE3FB4FDCFB2DC491A9D7F6475EECF5A9F17EF41AC8625C43DD20A72C8831871B579F8632AF8B09BAE31F8793A476B049B51924614DC8E3FF6CA0A16F27DA53E2F5868B0A565A50057CA468E3B90B3B1F73AC20CE8B82CF833DCC50643F174F071A5FEE7A0D9BBB3130BF9A1A414A63982C0A0430E9D69DC33369BAF62D1BA21A3FDA8F91324325716F1286DABD1CAD913616A1317E6F8EE4F44D4EAA7D3C884FD264CEA35244306B1E503BBAE643B3415AC0AF2CD3BD92F0D094214CAB6CB2EE39F80E878ADE0EBD3CD716ADCD88223810A423222D5E7A0F453D15AF6C6F0962C792A49744792C2E102B49B2C900244C4BC3B22BF161F025E0DCFCDCD02A49331EDF0A1689A6A7C6BC8AB29D462719FA5E89500FBD6677547AAE6A404A430B34C4606580578C2848DD99F20D8A98F87900713EB037D2517CC0FF2E3D9E52C20CCF0EC2F8A2191A802DBC8D4CA8C7400400CB43D21C1E7236A312059357776FAAD77FF0FE525CDF7C5E462BDBB4EA539088928792D694142E060BE791F3AE6DAC08867A8493FFEDF396F29008E651B304839B54064D5FF429077F5B6D4FD108F01CEA4439A2348A287444D04666110958728D055BF922219B482FC6DD8E341847BAAF605B59FEAEDD02085196F029B129688A6F52A89230B4C068E42540A2283DC504C01733DCF0D2201F7382097057215A798FE7B0287ED6578DD63449DB1CC72C81951DF59F3F4945F696015CAA02C8104B66DC66CD065F96AC793534A644541DED838DF3BF7BA3C87D4333732B9C70720895B6B7E85EFCFC4C849D6F3CB74D0F66253D7A37C30DA58FF79F5A008F77302E3DF3F77CDF7F6E3658B99E4066273329CC0C5E907355C0678E173E5135B24972A86C6EC0C4C6EC82E6CB2B28F00D18215D3C84611004499F211FF45E690C30533517EF5130EA161CDF9FEDA3D46D3AB285F1531DAFBE0953D63B510486DAE8537088E8718823B88A72C6466182D8D293D94F8C92AB16F01C1F5CB9041272B927FE646570DB421748D521995854437C5727C1EF328923F04C5D77493889D8E0DFC96C8B99C67CB5E5C3EA1A7E2316421AAF4A0B0BB980B6F3159AA2E142712E009
+5AE534DFA217B7E7BF68A16E354B067E93C6B458540D2175B849435FA423CF153C5DE1F217FB7E1D696569879EE11E4140C5EBE4FF7E2988599E0A359D6E660D44631A52B2B46AE01C25CF903816FCAB8D392A1CCCA93F0E1BB9F1C8CD40DFB64066663CEAF56318EF836BEAE3039A9B53427D1FAFD5A731BB2EF20272760EC95E20A355A613680579D72413E0DE0DBFF704741D5E290FF707293C7D0EE8AC0439C1211674027580736ADD2D9A0BAC725C7B5F807533CAABC964E57E0F61D5069454DEADE05B30002D7515861B1F1AFC681BDB522010DECEBF55C551881903AA6086A0866364B7508450C30C75F344D9A13304D5C51329A4ED7596DC4E480216674893D9007057DAE43A1F2B685E2FFB6CB205953DB7968EC8FDB08B92739E7FBD7CC14FC380C005A31A2E09E45EF86957ECE3886B36956BB2C9C31B347A28E67C02FDB69B68F5BD956CDCE9CBE4E6EAA08BE7A9E137BF7EF62206D59526B27AC97875CCADBE6E6905E974433F39CCCAEA34D5F8A8DA08F4AB4779D5CBD3D2A21B210E40952CA656781EF5FFA0C6DFD0C6D2CFC99A48EC1E7D0D9977A312B398F7E999148ADC26AAA3DD6719FE2415341934A07948E2F0233661769D37F379DBBECCD1521CC3889BF9B3EFA7F6D7BA0881CF5E66886ED7B083D52E8CBF3926152AAFFB58AC77AB2A6B8C45E9256C53DBB4A456DF9B2BAF5D905B946357B088CDB311E2263A0EA9BBB0614B4EDCB47613E78F18E641B531D95BA45573F3B8903A6E5874F0B2C98A65B07744AA62CC2FC6E741D17B4C75087BE54805480D64EEC42F159DED5CF4C739449EC88A4E2782C63C972B5B6D2A9BFEF615E687911FF1A1F606764F9CEF48CD5F6DDFBC5F5EF9DBFE6FD2444B3EB2F87659267D052BAE95142FB50CE9DB0D4AC2127967FC4C3973978A1C730DCCF5469432A1296B154AF4ACE64A994FAF684AADD72CABA823B2371D40B9EE6E9B321C5C6B193BEE340E6FAB142AB8CC0259AF86B8D03D509F2496E05EBB3D1250D8281BA3DD4AFF4D30EC23DBB0D121968D6AC794245F5A5746B0E857945D85D9B4C304BD5A99DA7358973B3BF33D7C463D3F470EC0F7113E0FFC1F5DA457ED01B2F55CE7C7092496BD64265A682D761A7D86BE90634AB16006220DD5D5FA088478EFF1663C9C5C9E68CCFB2B54BB7B80B578E5FEC0434B1FE073358C7A3EE5AD4861CBF3100CBD75DC49F62C8D393F8D60DA13F298CC2827A7D6E33CA45AE59731E4B30F97BA3A8A827389398A1F5E8CECBE6A9D4F8AB88EEDB77D782C7305349D6948B87B14A41015496E4C99A345215965499338996D6B89D392B1DCAF2BEA7DFE2BEF945800644AAD9D46EB7F7A9001A9FFE063D2F6626B7A88E188E914FDEA90C5BABE0C682FCAD381C1136584618CFC2563315073D94CCB27D2BF7B79DB107F9456A6D9875F044B
+6D3CB2275D1FBAB50AE8504FB4669F84B769823E9AC6133AD6754BCC501A75BD1364655173134A888E5DC17D7F0A2DFAD9E67EDD33B7C9F4C9E6DBA67945C4AE66CEE463F6425FE29FC78D23E6CE2DC00B567D9063900A5C265B8A32DCDDA0E0E8B6A07F8460BEA4EB71208F6C7F71F82714C91FA329AC1B8DF6C6DAE50D1668996C07880A2D0FEFBA629BED5DA235961F872C2B576F7F0CBEDA4D4A506C2233534359EE5664518E1935F9C416BCA6E7C020CF380283593CFEE1C4E9F8220693F8F6D4D6F0C8872DFA3FB9995DD33CDDFDA02FE5D07583124F493976AA36A9E112A0C917003E59E03BDE51DA5960ECC5C7AEF871AE825C844C7783A5E781105BD2E79476D279E26701E2651CC82DB980DDA8D1C23F4D06E0A3C6B40F0BE5CB2ACE6BFD1028D976A441C2DF5F454C2CFEB6CD8770D1275B976B045AA97DDB5D3383EE116D486B9385ADEB25CB995E34A51C968F187A21D5B2EEDF055775162E4BC3BE24F31F76A334835FCF3B4ADDB5667D0B2D887ED300038C0E0704697CFDF84F231EC211A46BEDE0101C6B2D9C22B89D5615E22ED10D0C15F0D067BEBEE90E455E97C940FD641845DA15AE92AE7FC6CAE145036764F9615114B45434B8AEFD68D8DD8578FCDAA7FDC880C4726D901BE9676155C5C8E41A3D09609A033EF01DC59F12BD55994B2FCEA7FBD33C8434C1EA316D5AA96F2E2EA47A6FDD2D43DF2F324F3AF326901804CFDA9495CF479880677628EAAB1510E4779786171030910D4DCAF9639CB2D818A776BBA487BDFC99736702CA57E23EA0F70A7D9D93159DF33FEF09A44E8AF59563C54FF280507AB2BE9E98DE490CC76DEC3ED3E2463EEED16903C6888313E635BAF7263A53DC1AF764EBAC19CE8B4EB8028EAB43FF37774E1D94D49BAB85402CFCF6045D4F7267020761384F81EC6F05408B3304E3677EE4D6722BB36A95F42781CE5448801C017677E464CFE69701E150EE7A40216A39C1DA1227C8DBF6C33AC9A823E3449009B6A5E280DC59843F48FD031CB72F279E1F69AEDFA402A4BD74F8D8499AC1E2F49A44AB2520185A6C482E9AA06F5EDE3EA33857C5CE6B901BBF04F241E46B3AF7DC3749DEEDE9B0688A1E9A9B127573A157C82EFC04B50EC51AB227FF4C783D11269D6D0B74C8258B0F80CC1CE141FAA39881397BBF534B234C00A3DD50B234A41F6475E4C84671CEA174D0EE4A3E27B93BC327B58B77A7EF0DB133DC10E5FF66DDAD7DA8AA69457D3722270E5D9EEDB63A3F001879A9995E27637A1F584AB4BA57D90EAA223C7D88BC3E53CB84313D5CC6BBE2A94863728E62FBBA551CE931D8C874CDAAE3905F0D016FAE152739D9C4378D63D1E1C317C51AB801D02FD16A6D57702C592FE1795725A945E5AF1D377F127B6FE89F857C7B035831B22DBC71D66F2F987DDDD90F9578334298B4251CA9EC
+750F60CDFB1F950F0C54CD03F39F28296F1BFC092FBEADFD27BFCC414E0BF02D222931867C9D0068B8DFACCEC738DB859A26DBD89D4F7A626B10AA8F0FB93C8E8200285A1FF4160852373894996B3D5DEA45E3B9EEACF67277C245E7C27A8724AC3AE541F3A6884250B28E1100491105E033F45034BD4C325C58A608B74AD361E9B7792967A45E24FF6E40E9529793CFBD7701A14BDF873DCA7148AF53836F1EFDF20FEDAD49684AF77E5FF8D66331789DBEE740344EE97A1D872B00728CB586C9F4039AC617020BF44A188F3B6A17F7A0E3DEE95A4D9656A27049615B2893D49C209DD08667532CCFFE428BFD95F77936D5494101C61A5885328F732C49074B39695EAD4DE1766F4FAFF464A1B62981FFE307633072D5BEFB11B34BB3FB9AB1DA92AFC87625A4E7CEB9FE81160BFC2E669B2119E4B0D90595269D3C687327240075053097E1C4571563D7784E48B5FB52074C7AE8759413B30E996CA7011E1B1EEFB82A53BF2DA35CAB36DAD668F29E4F04985D164B4EFCED5328818811A66E83F9BBD86C66C3FA966E667AE1D10874A942EC7C5403C88F5F1EE3E0E7B2E02E6C825E2D399B492F01848864242BEFD59C4E96F88FBD1E8C64887D774EC70F5332044866FF391151CAE6D11D8F959BCCE8F334B3344172C6AE031E5FB6A61724F85A7F73F77589B8776A67CD80C6D946C6EA5E81FC365B476A1CC9C4524FB0E92420186543CBCE53AB1538FE74F8C04B2CC8352E79D94C4BD20586F142171AA0ED0EE8DF6796CF43AAB2A358357D585A178F7B05C14901A7EADA687632650813473582C2C505F37A36A9BC32740090FD1B398000AC0507E7449C679E5660CC3A618F6108DA8A7DCB8DDD135BE05EB8C877CEB4B402061BB7F61651D2AC5166FF7CAD0B397217F8B9A8C1A5622C76546C9864D2E1A96B4C2D97AF6AF6B679755C4833868AA9A4740BE4A2C3D96E039DC53286B51A6E9E5ECAAA538A6E71F779A29E9ABD0584FFC1E85A28B58F2D8FDF8A830626E1111D3FFF672173D3F4956999815489948EF6F5FF1C000250BE18A7C55DC846B67667096B6F1730D6EE0BCE2380C376536658676047A17CB26EF2AFC9AB1669A76CE2DC76451BE16A48BB63A0FC5EBDABB21235BC3BFFD469072BF00AA35C93305E0E177BB4A3625EB5F096CAE2382A83BE4EB35911CC27E4DC41612F65F94E49F385AA1EFE9EA6FB4C83A34419BF5BF81E74A2411E5314D7F25B6B2E7A4EF4FC97C6BCA7A428ACD2B4BF64FDE87984B53D61031A0420FA0359F0CEB739C738F5D06A51208312FCD774474FB6CDF6105EF0B9AFFFAB3FC7A5B9828823BDFEEAC2C541FABBFE94CA8CF48199D62E83EA2C4C2B5ED394F7DDB7D6E9E1837F12671C4D0ADB931D21F21D29E020BBB8C27F4BC903A515DBF5301C24A626034A4C73DA7FAF00134AC2517B196EB631
+77B4F570B7F972AB9091B8C891FE756496E80015784CD10B4629B7142D902A32DDB54E9AD0DD4135BDC6EFFAE6561418D9E5A3F0E452E7E9D93DC286B161BBCF7C58F64CE668E39AC7ECFA10667FE54EF98CCBF761B7D64EB9A2DA9448B280D1FF2E6EE0DC0604F468AE5CB9CA88F9021539E1B7CDE1E3DDB95E525686001A9D6EFC5D2F109ACE5F7BD17F158E2707C4981E1F18A79ECF430F99E0E82A984B0E63E16E9B576EA3D61135291AFB759188EA98AA48E8C022030908D3E4894E181C228734A8DF8C7F43EF3A31FF47ED47C7DC2008B9EBD60BA639C45DF16C73C40C829D0330C93CD8DF8AB0448C723FDCF520B06ABE5DAF040D65EC65C9BDDC34D64A7D66F6EA08E07487700FE94EA082F3B371AFB411390148F7D842DD631C10C9C71D0EEE4087D8CED7CC5F5591281C0075A832044E9655A67A442F4B1CC25395CE294C32389A8DAFEE17FA17B193E04B6FE3C3BE4E9BC1928BAB6E371D216F783CB45E93C4D2146B7D0F593EF1E51DB123A1536D10DC8E24CF489489D24CD16D061FE65BCEE43DFB1C0CB49E9B9B3FE3E90BD06F65F0AD7BF3159F7262B88EEAE1B810E8901CAA6C9B4886AB2E4E2DC9F48EFFC1803150A3B1B1D245522CA45AF2F2BD354B155357E3B21B565398FB77631C4D4C4B97C6A9BD5F0CF9AC78CDAC195D60C452B97B9AAF3EEA41D51C712B937AD2B0AD0146F43877D5DE08EEA613FC43DAB6A35507DD4C5B16A15632F6B560989F4FFFB61E745600FA8195B626909C9CAA1F6FEF1DAD830A0AA1DED41DFE40FAF60CA521F2236695DFEE1E565AC8A6843300F9BB50ABF350D0DA08B63D14456D6A79FA750351978EC91C9776BD079133D493E94D710748AAA942BD094273F37CBA21F92D6CC954B1B5344E0C6C032F9333B9A48D1690A2390C1E6E242159DAB70FD4993C7D9A5890084D4FC39699C868EE8CB4DF9B380FA8D4E1A5348D1911D25E66999C397F702785EBCB2DB743A3F60DEC3CDF007D6B4DAE27EB0D19FEC9D16869C53C671A07B6A41BE6510EE28351CE6D57C47B88A6D2714BFB3FE7DD0ACA3CBEF6ADE67A22B5933097A6ED43912E0DEE684BE12C10DB917B3F0A93A366E5E17734F389F7C916249E2E3A3588027B28DCDFACF323A2E04B8CE2B175731F6C4DF3F379264DA19D0674397BAA53EB0F56D62DCD679867E5BB61ADF84D02329AF591CF4A7ACEB161F4FDD54733A790067CECE133D8FC54185AABFA75617E969A70D3D0476026DC2779586D1D98CACEFC2F5987F34DD2718A4642112BAFD762029530AA2E69E4C4FA9DC076FBD3507D24BCEF23B17767F9AFA0978B4169EE26967AFDD11EB1E0642737AE91FE0AE410567AAF0224FDF5BFAB8D96BDB2D014A1125D7D9BDE80C60B091CCA1C3688B54EB48523809DDF596AC9C4E367A827B63D34DA617C9941687BA7FBB70FB38E55
+11C6E9A0DEBD38493269212E6103E4CF2903D066BE9DF2294C4562FD545FAA87EF4D6EDE2AE710C4C4F88E225B7E88E353A603FB7E3CA799648EC5A26C824F6A83E7A578317BE0E39E4BB89638DEF533DFD0CDA2D5554FE86143C9DA2318CBBEF2ED8A8F9CDC524BCB0E1CA4EC4312CC758400D2D18924BE0BAD405F8F49A7F2B2F4DB0EF8E35AE1B2076CA72A63116B8B8F6B0D1119309235708B79C20BDEE1A885416670F89B1E82AB77741EA56D9352EE2654E7B05C8065C3DE3612FDF407F183A74BEBCF57A30FC418E8C8E7B45BC7EE81485738E0F4D44930EC65DF87AB20B72277BFF12E4E43F3782B79F1DF1F6B77A54CE0BD1618A25EF94FF51FC3ACED63108EA0F623D8ECDF2CAB4984F0E5B363FDAB41B4E7C823375E347AA6A75C6478E5C64AC6BAE2611CA6265AEE8D8408A277995B5350DED816048771D692CC7DA77BF2648B681EC33E08BEF01B5F4431C88FC3C4AF2EEEB7696E90E50A3C426F8080D4311B349C39910AD4D48F9090FE17697F684ADF001F47997975A73548DC35944528BAFE30EE582963B7768BB6A0F4A46CB1C67CEACB32DEB725018C90AF3F0C2C4DD22C261323CE4A9288639BF24A5902DD01CF74111CF206A0488B875AA23B9AD872BF26B3BEA7586067E3117BA7F2BE2690CF21E40F978EF9D1CECFFA936994B89B49DDDD62B7F28E8C873CB6506D41DDA161A18E53D237EB00D93CEF3EEF6DFA5C9BDDED20867467AB90F0D6A824B1C0549D064A3DCB0D886BBC1CF688BED9D59F33987D7BCD0D25ED3ADC4F95C70BE80EFA9A27C7D34A8A3EDDA47429CB868F7155A2EE509FCE612D64365EF34F16526CD4DC0CB827633FACD627707BD564743A753D31E37A1F7EFCFAE2A4700111A47E5459A675771B44999925D3DBE537E53526DB621D07771DE90037CB3DF5215FE651ED80E997B1A140ABE6FE021CE0E835CBBEAC9C7C94732DF516B476FD029A592FD25925D8E9CEC3EC799868986E1E48616C995ADB6A070162645028D7598C92E9611FA8F39DDDFA6B0C4D32FFB9B1EF609826526DD2784DF329F97DB8265464156B022617D9E7D82FFBB6337CEB8B1760754D4ACF3D739A49E246A8D008EFB9C1F312681938F9A65C51631FB9386F2338E6CD7967CC6C66C5DC326966FF1B4928B693B7F6F85B5AA668934C124E1FC4C85DC18F0CB6D2E4FFAF1908EE4348865C9A682BC85B25487A9A16C00C407C763BD19334160420CC33391683B5EC7B9973BA569FA156CB1AB0481A381109F0170C55F21FE799B746FC397DEBB5DB9890BC301F2C8C93A52F3A6BF6E6F47A89285A4F84FAE7FE9CD9EF3582E6D736AA2DE7EEBF3AAF64FD75340385A972465656DE16753F9706F372A18D05839FB803C0B30B5AAE9CE8A0AB9C920C6B6B258B2E1FC995EFF9BB579BDE101316D77961B45441A3F3051B111B3927
+7205684F9E7BFD178231E74925A4662059289B7AAA78BB3FD83EC375F66AF0FF15F62C814C51B87E965A3E2E530BB43EAC9D8FF825BD5162112D2DDD2B171B2D6B8E825AE587278EB37CA4B49BD00D18FF23C6A728898B2AAF7F5B38740FBC18E110C32C532D997715F46F60055D5AC833F734A570A574DA4742E12E85AB086E1E5AF74F59E7E40004B686BC5719BCE2C966E91054E202FE7375D426F8CA29F0D75F4413BCDC4150F5687EFF97D57AEDEF78F2B201D114AA341FEB664BA2D313A3A5700F6138D983A8CE4A086A91380CB55129B1BD01AF23D6B72669AE4BEC5B8FCD5E7121A054171F5A64336A1EE5DF1BC9E824CCE6DC78D9BD93498A0468C5C535C89181E2E8B38A8EC1AE818FE1C70E4F0016886E5D9BC2DF82A04CE7349E39DB0AC8D85001A0FD27864B4B121AA9ED29C1C5828840781C62795FA5E0434393ADB34E4EE30D7938D7BFFC70856843AB1B798F654ED64C0088A8FA76F8EFE5C2987CD72BD3279B5BA0086B65836C27C5813FF56FA08FBB9D854887CA42CECAF2954600B75DA12B2D0A579E7A7AC82527C515F3C0A25BBC586F015E58C967E62D6CE2C55A8C06E6E9018493430779D073FF20A9CA72E565CC44CA946FA57B6186C6AB2EB7AC6E10C25A799F590106166E59EDE109A601C85999093ACEE39A2C6D7DEED115F34ED43EF549787544D30384DA9F901DFF2B525386CC0CCC2BC259F3A4241B65BF3FBD4DA623608EF3CFA2BA8F99454E9303246B5E36B191828F3B534E5846D24F0EAD726C966DB316E60DD1B26EFD62C7079289F8E60CA5AD75C33D35757FA8ACB558D2E8CDA979F3DCE357AE05299D485800037E5302AAA8FA99D34E17264A16C75D2F0A46FB2907D2272AB06625DB9DF52E60DA3A8F0B0D2876D89AA6AE30118E4E69CE5B4C80BB459455EA64164AE9DC1029D4B83C614FDE23E216FD2BD39A11107E01C3B43E23C0337B96CBAA01CA3C4172C0A18C63D9511261A2CBAEFA22DCD34A827C85748F865FE4CAF448520FE3D44A15B88D2FFB03C8731EE1ED17E3A55F5EFAB5F2E9460047A3A7AEB6385828268B617273E8614D6A9189E6E39FB989B5A5E07E886EFA017721289477CB5B11864CCCD1665E8A64D57DC04B6D706BE52F6014BABC80317FA0EB719E296F6ACD81B92F1A890935D22E73471AA9875AFBFCD97EA4C3614A3DAC89F0ADBA391037E40AF5FD3B58D7FBF9DC4ADD2BA6E17EAE990C36603062E4C4B53CDFEC8791142A987B052E3C9924AC6A9281A67B4BD37497AC6B4A8853D37D3A722DDB412199CCF190A228630056A3CA756CE2D95CFD89A5E4BEBD04DECAD47E7135391C0E753AB9FB3BDD80A24C58049677E27847B4694DE36716F2E9DDD1D6948E7F186A815AED2F1CBDD0EA2B7F825EC5DFCAB4E0152FFD6EFF438B9AF2635CEAF625C1BD9A48F261BAEB4E09B7
+A15E6C93485A09BA44F43E503A7F7650AD66EC60147CCB6F282E8639A396546D10567ADC35A86424910BE1E4BFEAFBE0D67049602027B477666729C5C2D8481AF0CBEEE6E41866690D5E651414E76B42486655DE2CFA312B4CDC1BEAA12C2E37814EB4DB3B2E02A308D348A1715087988171005D5530135A757CBB3668859D9E61C9F9FA10557B6001DEF173BB6025CE29613EB05A4C3F01F15A5AFA0E3E765E575E864421A7FB2D03D660D075F97C6C2AFF2A7CAFFE38C63E2F95C2E0A2C0FE426FDF6EDE56244B3020D0D4C75711C60290993F191F7ADF8C3D0F1AFC5A384814A2C24D493138D600948AC20EDFFC8905A45EA6EA99591C5E30E9A76B47997B6137B82E12D830437576858B27BB25C4767F343455EA8F96A3DC58D186C6D21C7EDECD561B4B8FF67C9B662CAA79B4B3F5CF51E10182E7E424BE48EA1332EAE65E4E7870149CA0C348886E6E0C83E73D8A73D50B6D178B31556E403EB5A8A64359695C754DB72EACC17CD4D4E2416158F1455BEDE6F67F7C9209A33022BB77C3C8C061F46836DDE31FD4748AC98C9DC75FFC94A0ED6D4EA374FFD05ADEFBC343E40ECFAB8BDF4D386BFD6DE8F8265B4BEF0687F41ACA67F24694304E286C9BF4C59D73A6B7BBD90C16CDDC2A4BA11F31710AB23C9F487DDD79A9F121BAB12D73555024587D94F97A8F3809CA87033D0C281BF2C8A2DA2D4B284A0BB4A6BF3B23A5646F4694D75F32BD0DA6AA5DB81F0A25442E82CE6B9FDC325381D1ECD36B28A24CF7C1892D31CCBEA6C0185539509A8F1D9A374C7347BE52C3A6E50DAB88E7DE7C73DADBF93EC666922D00FD2947402A9AA2AB691D1E0C8C7F38ABD9BF48F13293A3FD240262CAE135671A8F4CAAF66551B1F2CD0129E16E91CAA2DA33C6E1D96BD7F9C3F80783897FDE932C3041C94232F0B4440AB3F7C3909712CD38AE874604C5E9496DD1EE70160DE5BF8FFFE95A978EFCA52CF0FC87102088C51ACE6CAA6D24BE34856A1C8AC498AED33364C0B950B3FF868C00E8D9227588A51FB0A24F31355296064C814D23A8CBDCECEF68A056783D6E4AA2C580DBD0EF878A88DBECE1C579CA4927AE45606DC8FDA97F4B1922DE0DAA7D8D867F31324B7E1CAA5C6EC3B430F6C38ACE1885A5DAD4512C24B4D061C346E1B12DDE82A0398DD035F0BBCF5F5C972B39C2ED53BED3E26517D3EFF521B02C863EB084FA78868620F19E280C563C7D5A97004B589C43166F29AB81B218DC7A0544DE5E1EC64AFAEB3915714BF889B1C165259A33D81A6B9681BD29695C28BB24692075B39BC5E18DC464133BCD0FFBAC0B92AD79D67D9D6361AEB18268A3F861C8A1D2DAB3C1023BA56521092EEC654E52E7931BCE13BC20411CBA3C5256A0CF6A8409A65C5C3DCAF9FBD7E90232377EBF63F9164EDC0B2D939DC72EA9555AA15F12C3B379D03A82986D
+6023DDAE102850CCCA3E76E2C7BE4ECA1DBD3000D763C12D2CE8038388F80561F580DABE793D14EA152403EF97EA65A96041E9EF282E2F8D50BD267F3ABF6491D6144B31C90DAA3C9DDD3B447C6D14CD7D2143C3200B79ABE6D55C710122333AA7D831361EAE29F08B89909890977B603AE4B355964AC4A8045CFDB2E75D9A825FE90CEB3D1A8893D653DFBF95AC8893F27C655CD111A629E95678D78EBF965E8E4377AA929D97E5977C6DD445AD9B8F63D0AA91E638E19262A031C13AC6A5137B75E295D38F77DEDE8BF2045D1A5F82CC281DC99636EB7A8E19C8B54ECF6861D8D6B04699EB567818F6490037B7ABA2845F57461495119642E73D1A2B64BA560B8759BB810298FAD10B2E3436B60F2111F683FD6A0C95C5A8C4A1A96128B9017E364DC628A13231FDA68EC804D2272C5FA12E7A8F45D618A967BE4EAED4899F17CB3804B89F57C46F66968842924509EE1418BED0EE786872E2F532449D95FB4EBFCBD7C7097ABF66DB9BAE5217B7B29DE91692B9659636BED9A7AB70D1CDD22FE94CABD1D9CDCC5E6070CE82DC5DAEA48532AC3D180DA9FEBC628ACAB898D8238FE6B7F94B17DAC99E05746D879BE53C0091E2E3462CA977B82288CEBC86307B727F9090B2F100146B0563E89B3376E5305960D030DBA34C2F040BFF7EA0F9EE7EC87F1889FF43FC77D28E8CC134D56B45FB5CACC484470EB49A2A0EB2A04821EE83A44C622471CA1D2FE04F7E16457377F7D87F419EF2609A64278FB75563B05327B5A20DE42EB0D8A05947058C56D8F43E825D3E5A36396A08EF13CAE4014F459C123F11AA43B587D09652B692D10A20A28E97DBE02311088D98986ED7439D6A00ACE8E778FDAB99EB1F5B2C107EAD940448D544415106B3893DB3D05658D810496F951505ACA9FDEE4A5D599C24F7D12C46D8BE5EEC70F6845E09726B895664AF9CAA5AAAE10C60DF27E0BD412A43454B3F77D6D8F4121E9FA05722F7DFDC04CD36A2A04A05043D0CF658A29258DD258871ED926B56BC5FD862BAD73FF502D2946317538557AC022BA8C512E8BF7BCCBD45D7B87827E1987AB89FA5C83528D623D5211D83148E3412D2F54AE9A38ACF0972B9FBAA26EC5C9D6D41CF35834A88168FF64E620C4E9032ECC959557CA396E1D9F73841A5441CEF6E388B745020013A033DAE43D70406413F824117599AC4B469B587378E0C17266A9BE44EE58184B46A0D59B09F6C4DB310DD2042257BEBEAF1112F7E5397852ECD5043BF3B76058A66D88AE6BFD45945E282AD9A5E1D1046CDE23C7C17F6E66B7B875F7FCF40F28CEC9A3E7D00F2387F81B4732E540CC8412D08ADB1498D417C7A2F2BBA6BB097B0B79CEAE28E7F1740482BA7077DD70E36FA160FF16AB2FCCE81F38132C8402022F7034DEA0F9E374A4AB781EEB81CF89C7C8CFE4757A345E9702B7A2DA6
+F788438361555AB0B0B6C34708D7593B4DB54ED45C3608175A1783829E24BD733E73B63E2CCBBF181C1BF82262451469E696A4690CF1EDA82BFD5EDAB00A2CC7D6498A50A8049A3C896BC41938F5D475789A0E10F4DD96F6E7A31E1760FF6CB3AE72E833037BCCE6DC7DA3F7FD66FC6874EFEA029A5DE940FDF0CA0F0E302761C6E9316E5A9985A66A8C2210C14185C435100E9BE39B8CBCA5A0B73CB0A88371BC13DB7E237F9FE29CF101547466D79609E2655E3433CEDB42186E6E1E658F365309CE59692F84309AF7D8664C62D1066A5D5D6A2D0D9863585EF056F61D3BE58F6EFB2D91DEE92F6B09C71A720E5A7DAAD73E9194B14D6EE372DE3A6C83E1EB63C0FE6460604D18435BF1121739BF12C72B99DAEC8EDEEDF3BD2B8773C46C31316B19658C122C1A57A84ACD2D087A6A999B09D6B871693267E8218FF35D054224FA908D9DF6ADF021F1F23A2D3221037EB49516630E8778FBD520166EE4940699FA2ABB015C4745CD510E1CDC13194DBDD718DC147A8768BA22951146E5076A32876F080FF9325A6D8C1FB487BC3255F62528CAE8BEDF0CF02B910A22C2EAC0D4CF7B47A8B11B859163086A9C167447EE26246888BADB68DD5101E2B0ED4B7A9E6A061EA1E37EA190A94692E716C102E612083CE5145CA68E40F0E4FB87562B56C9A9BFC77578DE56DB67EA347B2F8E358D2A9F5BA144B0FEC92FB7C469C7BD15071D5A76BFC780640DC5001867A94D5AECCA95EE0CAD8AC1A518F6BE49AB2453096D1F5E7E96D207C2531450E2AE6DDCCA9B45216B7479E5651F5F36B718734323610BFB3BC0DAD7DD6DE2B6A21D006A2C8F815ACB71981F50AE68AAF2C2BE244E7DE5A697AB2C6DEB6A4899D05587F0A784A80353DB46C1EDF5B4368F7952AED6DA002BBE02F5ED05B32F234DEE7D75E5559A8F6DFBC6B95AA19CCAE281D5E5585F9CCDC9B63A58EF0BEFBA31EB2BB69D3DE1B28811C89C78A68AA063BC2E05D0BA2308F49213FBB9EF505D75FCCAF3FD90C25C4DC0CBE804E0D52659E282B8D177E38E1BFF739D837D49A260236A392F9C44BDD2EB5897C6776B54C2F120BBAA04B1998F6B083FC365F022D9FFD3279A3CE919E57DBDF43842F998589D98B6B66768488044D413BEC4DA3B59F51E7EA816983C7DD78638ECFB1228A34128079A103D68645181C2C9A288F478FB59DE97371A194346236DD435977060A461BC222AE498BE09CF855D57B4E8AF037572B873A1C3FFF1BD68286E88DED7B66CFD4A323FB702B9E2EE013C2EA076318B23E0FF122ED4EB70EF7EF496558A91ACEE68F667D704EA8041B32E7270355F05EBD275DD9EB4D9344A94D7BD88201344AFC2A7714BA30BAE58A83ECB10CF629435B744A41A5998FFCCCE882AFF5179722A569324B0FF1264451747BC23AD52F79BD02181AE4E95A2F9DFF4C5DE7AFC17
+171CA91BA8C44882DF298E7C908B11AECE4A147DB6E448B4C9FDDD322F8B1430F42DE9075C029EDCF35E11703C72D583C1328A8F2AA307574B3A3066AFAD9A5CE4941B36B09A675DC87E7E684E4CA09B8F543EA54CD0519E9A878D81CBD455A68FD371A537E165C8193C34CD23986C4B8116
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+ %endeexec
+
+
+type42known not downloadOK and{userdict/TrueDict known{TrueDict dup/imagemaskwrapper known exch/bander known and not}
+{true userdict begin/TrueDict 8 dict dup /version 27 put def end}ifelse}{false}ifelse{currentfile eexec}exch( %endeexec)exch checkload
+1861AEDAAA5472E4FDE5287D4C4E53EBA61CAEF92E8AEB14ABA4A2E2B6244640C5496385510841A394FD06884F86E70A30A329E392A84AA145B9917DA1EF1864F9033671C25CB6649D97C4A0BDEDE3EC8E137AF461E91A42287D328816F4002511790A2B09DBBCC7992559D1AF62FFAA1A55F98FAF62168200E799DDFCBD37B5C4279E85B4AEF4FD2A30983FD87A1A7B0C07DF26E4B0B8159FC90380FD6E38968F89F8971E93F5EB0D60586C6C4E4F247F874A0F118E6C94CFB3E27610C123196810BCDD5D25E14CA96BDEC2C3E279FF96E39571AFDF8CBBE538181045C34A1895987FADD776BE35DF767C94FE9A0D8A1E1188398B2830FFC0218086EA54B5ED6A145B7DF84CB82F7C142DC2390A583EA01DC114E49778D1611BBADEA454DBAAC4C76F487FE4662DF257030AC2AA422282F22E0595AF77AC5D134A7CE56AE7FB81EF7CBA5B7493693AEACCA7EF3A6B99C3A00F009DC13AB4CAD6754C184DE326F4616EE40D097D8C050698B31A94BEA99848BDE5BF58B1C5AFBBBE67C7B2EC5DE8B83B59BE238C53E1CA7E59EEC4A6AB0437CC32E85801CA973E5E29553FFF68AD35624EB7025EBA70C6B0925F507E685522F00AA9C8A9631C3788083FF49BE6B79486C550F42FB085B120366AAF04E8F8E079796BEFE5F907E61DA38B4E518338C236F8AA099B8A741D73A56DD9ABB210CC81DD568F7C0312206B05814763CC6B2C2781A216274C4F69EF67F44CEA96A80978D462740F8A9CBD9DDD90243E70D92B7F5AC5EAC151B24F1F7E248C655B9FC1A4C099B9A721F6F9A2A979F6F536075D4E3F1050CF8749959951FE42E8E6FE8FCAFC1441D68DBC07E5564E5E0B84AD6919CD846F8812AB776FAED6772704610C49A1968FE4295939FD56D1838B8AF8D48300CB0AE1983227F024E4405BD6475B83E4638C6BC989417E0C1214B24564610AE8509FC92DD4994546712A411B4BD3D4E995DE52E172003B18E7605B226092EE9F65AFFFC3A9DC30E44B54F2923F8AC2D672B09F2BC1D8F35F130CB446C9125EA8AB5E75DC34D1E83F57AE5BAAE61E8E3ED66416D69FEB2EFD5F6AD7C410539F8117C0342B76118355A3B24CDE5DFFFD55EC7767BB0E0A6EE0C6DAB91C47F8F5C90948C18A21B7DAD8DC0F0CD4028C2AEE16DB5E03C5B3DD10B85983733CD340F5CBA503E94D3D8327C64444F58BDE00E9945B2E652828A9616CFBF93C4B7E3C62F42AEAA7918C706089778AA870EFEFB15316A7484EB610B1874A2B9634C2CDAFBA4E2A634334762FE8D72DFEC7574096CC5EAA91CCCA79FCDD8A6CECE3488B3D9C5D6891416C1D106B4C17E371490E6DB73610622501A3F6F6EA0963AF373836DDA950518978EFA49C497E0A847FAF986AA0E8F56DCCB45806AECE351ECB40EF5AC9EFBCD704A2A61819FD6795380B0524DBABAE3A8BA166F38629C2
+FA3F9A24959581863A98FA55235185E5DFAB6F5CCFFDB352A9B1FF8E7A6E31B0F0BFCB3387B23CFAF147E47165CF5186CB6B97B03E48E1D6043BD96DB1F38B977478058CDA5CA43AFB0CA3BFA31B060AF62CF3BDDB493314487EE641E46581196DFB066DDCB018ABDFD82DA8C293157A1F65A391A59736FD38C4824B24F3B3D20082941A8B95E081185DD409036584A966CAAE1BAC6C5FCA53FFF98C092FF2F7771B215229FBF957EC204254BDF793C5F19CE411731DC9A5C2D86DE23D48A547E10134FDCA0AA60697A722F18ECF1A8D1647BFB7B49859E2E240B2F20CF8B2AA37062AE08AB03679F482813140D270F55054020A766EF2179DEB7C5B43B503DF328CC8E092A239DE2293D98B739E0EEFDCACCEFA8A16114DD1D625BF52052FD0AAA212362D6975DA1B4F6DDB461A3A9E0A3E475EA95B871C58F707DB0D7306FADD488BFD63ECA67F860E0C828C544F0BC9A0290D877D50D403E8992C7A96912823518EA06925AEF5720A34767F600DCD027D86AE8E14D1488B0C349FC7E27082A34A4A534FB42A2D14587E4B22034EC202AF7E3E056093155CE93CD8956A65958F3C3F663D0B45C62AAD3490405802A6F63C0D8329D90834BF88B73EE104FC363BF1ECFB0A7F42B80F0F73B2DBCB2DBCAC9A8A51CB2B564AB91FDEB079E7F12073C81076281040144B263E55F4A273179DBCA68E8D677A91AC6A7322AC6F76248D26A7EA661F472CF646E393AD3CA6F169C6E9BAEDBD76F248AC4AF48628D656E742FD3982E6EBE9E35B746CCD6571CAB25C099FA5B24110357A4E3B9959308102BB2187E89AAB135139B2EB8284CB65BAED3B2FCE92D654BF0CCEFAAB1FCFF8582C59653B76194FC36A5D963AD885551F800BE27295386E1928EF69355E41A02C35B6E9190131437D3B571C3AE46E293ACBEF031B369514EDCFF6112A455295E8F3B10CC0F75514299E51F567E1DB74479202B69028483B5D5E490A64563AEF6F4EBB3F0F2BAB4ABECE1478BC2A1BF0B4430B4085A9AF0F729C6E54482100F18AB2C491038344810D872E17418B02FDD87C585670836733FFC843A90FDAA7B893D5B7252EC40378892B2138BF120DCF3CBB212608CF33D7A5DA2176CF82A17ABFE7771C6FE363040E5E35D694AFC61E4507B4F89EDE55610B55D6BC049F61CE9BAC477E62BF3DC24E624E1FDF8FF69153BCBE64C7880A75C18212F665D8160AF96A54466A5FA71BEF5A667537EFA7E67C2F80368F0AC0409B1DAFDE8EA5214E7A80FC5B4C3731831260F0D5FFFEBCED4DD597A3B5ECCAE2F778B5C04332A193A8536D78590D9E3D811A34CAB11CBE32F8ADF04ED7E3E8A56EF1BF722DA7CF50F4C23F74ADBDE0C2EB7F2A52E71804F7D5FFDC530BBD9D0E491F91DE2B72B9120D2DA737F74D2E5F7E91E8A331594BFBD4192F0976D86BE1700678BBB4F35931
+7724A27684C7600A123529C92484C338B5693770B7147FFDE7038A7DC6F22F2775846DA94C39D5B5EA4A8093E21E7E73466F0B3F278D80FCFF413701F4EC9B62E975DE02A8B2CA1DF3A304AE7986F239E3D3447E0CCD1003F59B0A57E857ED42A602C8CC2A2A3E93F8C23B627927304B67B4FE0D91755E67A691E297E485E7A7A6F5B514C0B4FCB2033E45C5A0F11E7C588D517EA3483E0868BC6B5B24220A86574E25B8B9798C52C118517B0234C1769ED6EFCA1ED61CB884D551637CF8C17E3653821953B6C1CCD26A997B596F48BD69BA34C4296264EA30D69FDF9718ED48C90EDD25E91A99B2286978377EE5EA689CEE678348D28E61A6F560F4D5EDAF3648A3447D1A6B56008B74B26EEB2F786FFBD0AE01367090FEA909316E58148AA86FB4F439E84063F7F109E5B9433B22FFF5B2DE6BC1ABB8AF3B7DA77ECB26938EEA9DCCCB566611BFAB68693A2AA09182DD670E1D79A085EE6A88431C7DDA8BD6B8EFD9FF5847C1AE494D8F67A394C7EF7FB112BDED5545B7544372C8ACCA934EDF1389C36FC82F9EA77AC9AE701E1D3748129888F55C9F2DD9CF3445070DD913C9734860DB4E4087A95B5AF9DDB21BFC5265D7C500B19F8D1227E53AA791926685487307AA891A3ED72A1236E9B09297C561FC26183B27942211F20E3D877065D141D0FA8F189170A58B64D7F18F472E88D836AB3D83A9A4B506698609063F6BEF83E364BBB279820A22B8E258C193CFFBD5806645E6069BEEFAA9209514C839FC81743C6F3A452CF292343E257876FCC4D1A8AC724E6D1790ED05B20983506C52477A44F19EC79A42B5BD38986E0BD055C2DA6331BACC6669AB3575E3CA3EDEF6739E86BB6BF31E63A88D69BE70424FA77755B66DB4695A198DA78D231C828377261C063E9B554FD743EACB96C516E221502F80A51CA445A68B0CE09E9E9D8420061705F16638BB0C2E4E250AB1030DDD95D00EDEE5C12CCA69A8069C90E3DD1240582FBD5E67C77CB6CE7FD5F271BB0AA03BC36639B136E4CB33858E67C36D409305AC6CA84EE77DF1E2B2E7994229F73EB2D3D0157414C8AAB85A73DA68B7610F09E203851F1019E877CB43355EEE1EC8872D09EEDDE8B64AB4CAC28599BBB803ABC1A1E7797C0C43E7E2FBBD10DF28F2E5518AD5913E41E29881FC47F7130F5C9FE07A4329F5BCDEB50BD60BFCFBEC64660F808C8BF3F3926813659822E302410E3542D1B77A9780653F464C65052845D007DABC743ACAD6A5AC537EF2BE3A3AFEEBDE12020FCD1267DA6D39E4D9348585AAB8B93B2F21649C6CCC4D13E040691C525E83AFD212E6A982EC428C955DBE06AACE94D80A8BE0913B5BB919148C651966B56BF3BA1E9F5BDE8272546ED551A460883CAA890DFA69138F9AD33387327BD999B7BDCD640F54577931BB3203E35BCE5CE7BD9C368F249993612FDC
+FA60CF791F407BA58B6365CDE409D7D84F87D660B25692D8E4625B896E1D6220B0F43562A4C8C784A6C82DA2F3CED05B933136B633E93FAC1BE5147BED537B4CAAAECF6EDA4EF69C8067D0CFB1A3DC48B4FEDCB331A237366701178A202661AC8D4317B948ACF1E5067451575C5357B4D54A67D7E5C2BA1E0EF6D9F9554591666E4851C2ADB2696EA63CD6822B182797AEDE41D520CF95552E79A196D3537E3B19965E715EB474B7ADAD1FBBF6506916C41482680D01739F8C6AF0EC183A3BF093D574AD352C0856DD88B9FCB48743977AEEB845F8FFB02E1E3E5A41D161226C1F37292B0E379510F7739E8A4822194D3C1FF61890312DE2E6C9709854EF6A76156188C939EE4FF95106295FB1CF147B0AA2E6A11EE118ACA15A4E97E08C2ECAE6CD216A9DDC0DC73EEAE1D3813E39A36C04D129C3265B661D736FC550D365A0A8A1C7FBA16F7B42CE62C9D5C2C47F50046AC2E5B789849809DE5BBC36099B9C34C2BEA734A58645D00D9A62FBD12811C392DC55C4729A75670397A9CF929B57C318FAAB42FE37901ED66930238DCA41AA6B277CAA18240BABDD8FA5CE483C3CB10A2AB9F2AE0BA4C8CFF4A18E602E41A93D7F39495EF6FBBBCAA5DCD6701887874E2601249F391641906A2BF88F77404FE3D797C4C64C6F6BF30F9E161C4A776D637DE52EC3064474DDAFBCA9BA2CEC96E26D59DE3EBCD34025154DAC2FDA78B1972A5A3D0DFF82A100795EB96797EFA69C7473BE2491BD69EED8E36C78830B07D3BDD6874523AE34A9979C7C53A15F874004C0703C451FD23DFF6D734B44877B2BA09A4B7A5E236021556CED026B46AF63F58A9D856A3B44F2ABF98EC6BD390DED6206FA82C9EA2650250C8EE4FD602D51FEBB0994105B0BB7E1FBD248EAB3E2A1D173AF85098671F3749FC5B3E4FB3D6397CD0DEB1A8D7820DB5A212501B20B8A35391B3060196B2EF35766C165469BCFA6633CDE5024677D68EDC362BBAA5BCF5D9CF3CD08C19824DE73B96542F4B0BE884EC43AA43474402DE1FE1A0B65E610A46D6B6EA1086FBA9FF4DD9CC1578C03577A4F6499F1AB255D325995DF0EF5D3F8FC1AC02B60694881DD56AF509736D44503CE3E5F8F91EA6680CE0F1D156ECE25BD7CECBC872B4B156F21B30CAB858233FB7D6E8086824E9CC7530E71870D6EFC8B89E49F0B153CFEC64E9D1FE3A39A83FF66B6909B6378C0513B6F47266AB8FE4C69B167C0C352380C3E90644F6E33DB52F28216FBB7CA5642D3350D7A3B957785202D0586F59390C90762DB4279A7438698632B10A657559B17BB3C1CA1CD99ABAF26CF1102F678D36A4F46CA83392B7A50BF3A12171AC8A54D664A100709606F7353F0F0567C4E7936EA06D1C4653B2FBF9A41D25E4C552A6D42B18DA25143BFC2CF3CC905AB8D84AFC05A88754D5DA015EE5AE4EF56FDE5F0D35482
+BCCDE9A518FBEF896B2DC7F27DDF0558C213F979CF9CE5F7A6B1B5730122DE388846669F517CA5E49FD79F44549861D0F5C39882CF68F3ADA692754B19BD88642833EC6082031E6478CF6691C172DC025D5CB824FEA05CB3396BFE19DEF8CC8EA6B7CE68B952B71760563B7095B45D868E1225DC3AA7FF07BB98FCF24B3A753D39DCADB38D716A5D1B3EFDBA7D1CA806C7B9418A6FC0461B28DA73696FBC778926BCE007255F75370D27E35E58AC1D5559BC55966F257EADF55EDC42509EDC4224DB36C3A472E227D73001B96BCF8446D197E24D340EE8BB53D1C607B8CB038040A3E8681D618439E417A046BB367C926095FE0F08D6C67D081705B415AB95760744859CE55A0D5D6DD706D56B16E7E0362DFD3BF48AE605B21F5F5DB0D044FFF9F00EF72D18A749C0A0F09D5F8E0654DC724E01E5C8DD3246C7636329F98B6526329CB1D73DE4CFE3FF1AABFBF516D2AC0D19BCBA1B6B9E944F78BDCC2A4B154B765C52C00011F7FC1A1F16BF5C23F2102C72421D96BA352DEB1BD340127F294F84F40EF0698DCA74CDDE0435EBEB59DC095BBE784D10C27D862F28812A9858E374F8955A8CD99B2FAEC397E7FB2C2BE8D41D1045DCCCAC9DD3368264884E60D653B0BE5595D68E892008AE36DABE19268588EF9E81C72725FB919AE6927F6C064E177945F86B0AF0CFAB2FFF806984991139C3C7810F9FFAABA58FB4125472BF9C486A2728FAF5F6D734FFD7B225875D41D244CC84D7B6EEC6C8088C8601854A896AA76D3ACEB704EB1F1E091B870971A9B16EB2FFF3E37C2FEC1BBA1D9F7D4595481AB87536A589C9DD141EFA1D4E56056967E8D9512B1B186F6405677C697E10D0CD46F02BFFDFC19987F2F18875C6E7D86224FB8057ECBB9D5D9D9F153F5DB5C533E6BEF0421EA5DE624C70FE096918C323769A8A480D32E6DA767FF139F370AF84B526360FD46D725BED920CCE92122523E81A3C6049DE6650897976558531DC49CF5B07CF4656B84C59418CCDFAD17AD63DE342F6ADB3AFDC112FFF80E0324FD74CAA51086F69F1F9A4271C6E8B032E5ABC79049DE317CE2CD235D49F3DEA25AE603948B4C7172DF6461E3E47386CAF2F81D3BE1E8740B858FB8E63271DA195736EE51B45E6A0B6DBD8F5A2ED7EBB8ABB138F6671EB8A8D75C3682785B53AF08247ACCC94021BE383F5A571EFBC8F9913C95135FB903F5ADB60AD72C3063451173AB2B68ECF4D70F545614BCFB54D932C01A37072A30FC8CBD13B9253A11D661115A655FB4357E356738BD1BCECDACDD0C9F3487698BB2D63A6C9278E693FF98EFA2AF0AEBBD8A5F10EB85EFF96CB6F958C92EF4BA0B0F99A9E84E8EFD0E4DB0AE8A2846C2892F4FD7794C6582C7F1E8285A87D7A864709DB9CA41C574B97486D9B183EC9D91076BD66658C08C95324833BB8EC5D06C088F632855429
+49B35685AD5562729FBD6E70E37893305D5D2D79B85134EFEC29BDC60E506825B88807F8181F7A73B440349AB533794829D8C4633C0080772A139BF1B35E91BD1F9D2F10069D6EE280AB2BC3EDDDA73080A7F514D844A1B498E1C229542615E540F07D63F7F4E8FF85F6900362749B6C5B94852339E176E6D081821A31030AF673D3C1C2FA30DB3AB6C4C869A542114E8D82D7D0C49C1BDBF413F5B98AC44018E212A76FD07DB4D1EAFCCDDFFDAAA5A070365A1D58C1B75976D98531C670C93CB6ECEF4DDF83F5CC4361AAA8EACCC3E164F06B79C0B50EACE6949D666E8CE29314316650BB04CDF51F88DFEF925563EF5245F400273957BAF09ADBAE8084350C477472A833D0F4C5AA1093000B7A0DEEA7848F277E95BC78555E28097BA65A610504424299133898C81570E5BB666D6FF2BB2999A6E2981DFFEEAB982DC7897E5BFCF6C9EFCE91D004E762B8320948884239852E7350605F86BC606748D4C3B07C26FC227DC377B603945FD49A5302F526C03278CEBEAF1987566A403A3A6EB346EE858BCB6848ECCA491473E92E26E77CD5105FEC2C5D2E29493B0332D530AF3F1F56111E15BD96F047AF12A786332051AF3F086CABFAE56687DC69694C246F9362883AA80763E194CA969760D4F28EEF4DB00EF6ABC4AF16F052F14F1402C88B71FE5663EDD79B0F1BBABD930E2A215418ED2763A710E51F9E7107A3AE45FBE5A0381308ECB0856CA0128A36487323A11964AB4A4695D4188998845081A808AAF64AA2756DC33FD14CA3120DCAF106804D9B9DBE78C76910314B2DDD5E843D061382B8ABBD2D558D7C74B3ECC6CD9D424FD5090136DEE22ACB3772C4F314AC42AA4F05DB0ED372431440227B3797CADBEF8A2E50BC4F268178C02741AB6E9847A74123FA4D3797969D8B03EC44C7073A15C592D866EA669A253D792F6A4742E47B096082F1C6644D51F95B0581F17A513A822450C772BBCB4F245345FCF2FD38C4FB8CD2414335EED5C7B44D17B5E6EE084BF144595652A9886B732817C4B636A12885CAB9C9143D39D80347DF1FB3872E51B5AD4D156D816357180BD64E59173D6378A4B85D84963595DA5DFF0611D13876C45CA60A76324A40BF17A2C6B0CBCED7E4C2B59D5B3DD8E88EDF45870F1C7A3FC35F26B30441F1906D8F9C25310E385C178BE8CC667E6A674C17FA290D198D4A0D939FF51136F25FA1E5AC870764C3DD7E1837C1BCE7FCCEA62B22BADA120C3427974DB27D9629B7219CA1B41240E4B897A43A11467FA07CB8B13E63525C1E95951CB587657F90B2781E006D7663EF5179E7FA281E129D1BCB55A6FC4AE222241239DD98EAA6B6A1E4B8AEFFD7CDB5D7D7C440D230B8A6D082DBC1700D5035A6B663FFF53D8D690CC0335AA0459E5EFA028FE48E6B3870D646AECB825B6E50A7563F644E7C2A677EFEAA6854BF
+C5D29778B98324AD7C603C0D8F3C3C765512C0000BDD1471E14C758968E76E4A9A30488C04DD30D036AA28A8BEDFC73FCE5BEFE0AEA4FE82C6672474347FE14F5B3BFF11C157B1A78307817DECD0CB0CF49AD97386F0CAC0AB78AEF8D7748775E3FBC0E42C373F20D7778ABDB050B04619C4F73752FFD99AC15297C2D5C8B422B960AEED1B97D449DFE92E5C8CBBAE997ACD260488FB0BD7C66792C1349523B931966A8BA443181CF37AAAC008F8CA3564CC6CC9BC4341681F294F0831B7ABB5060C6A379B64F5E6421E125BD2F01383076BD37A7830DCD53463538374BDFAF2272BC08EBC9DEEDD0F2305363B389854C72828A855F6465E07B19474D531D15C195BAC011D7AEB54A72DF3FE2D55CB96C2F27B7DFA00245CA4524D8FC616D04211FB8C4349BEFC482A44C3C47DF610D8BEB840DEBA5EE7AE7A6C63FB346C029AD99A131E55A4C15B84B3781B6B44184E7C24439D2F6BF41F94F77FF463902AA8A5BE5FC9156333BA4A0BFC9967A80E692927FD7246EEC01471EDC4048977E8847C40AC0BF1C90486D560F2A356971814452744CE6D879F826F33355DF482296AEAEFD34D9E9DB2053EB30D5FC4E740A1497B4758F7A585D68198EF2D30A512CD889F3E8646F2F12E6C845F22555886179EDFAB55D022C7B3CD2583128D9B5F124DACCA7341FBD18A99E3D10CA71376D85177938F4345AC920F5BDC3CF2BAAE8AB13C779B13C77835106A755FAE5F2F308407A1AE5B52613B36F9E94750EF8B61F45B0142D961CB98038BF62E2794E441AE85D9FC952A87F1519C5B7138884CF1D183E25CC0C348D7C7320AB4746432CDAB944D795F3009B90F2AB3BC9B66C55B463D24A72BEAA6E432FD6E7408D6A11E5B72599E7AE2CD54F268AAF0DFE6162C838FBD2DABB1474E6FECE5C72556AE3053B5D786E62B7EE261AC2C96BB0C34A4F4CD057E6A27214981E939987ADD265634C3E946B05E315FAA21E306B76E37B88DF94060A9ABB570D4960F8EE1ED3D5B9EF12DB7D0954EC225F84C45351181F840C09A1CDF68A280A1D9D0C599F7A362BD8C36B466206D52CEB6F0E2B3D688C2CBC95B90DD1F2CA5E919918301CFF97C047D7B60C4D49595D0963E3374D28C1A697DC4961745D849E4D752E885610D0D64960D31D8F7058DC729E3A625FAA737D097D40CA00FEBEC6E1D969083F7246E875DB25867E68F9B69EEA26179A72A53B9ADE14017D414240BD1F314D9BB3F68507030B6356DA621D3D5198C0CC474C7E07F67AFDA88DB8FD39403592E5862D613FAFCC6325B8C92170DAE4A526F484782C4E8CD8353E0D113094BA30805F3C4248DCF472AB1369703E9376FDDFAC1646B4EACFE8C9865DCD19C1E94E8B3253AFCE5CF4EF79C605E8EAA2C5CF708F3369B8C96E25C4B09A431B4D6EEB062AB6F3630012AA37DFEF6DC30FA256940D1D4
+E6340B14A2A7A055F2765AA1B5CA32E0C3470F8F7A253651DC47FE173F5CA1AA74A91ED0DCD0837F34209D97E78684E620DB4E0CE71D64013BC8D7ED38CDB3736E3336D9CDF49D8A75288FCCF3B5DF41B9EE78738C42EADEB297A19D2A38C9D6F6AB37D87483763AE231A946220B2363915DB5EBC34A7ADCFB45377BCDE5580B6357C94B7B1940CDC37CF2497307B76B9142D3DAA33B075548A49839305D1CCA880BE87B7A1266B77820E7DE551A4AF10DC12253109639FA1169CE35603C9BF880F74B9C598F5DF3A40287D8C65B1F5E5B9A24B6EF5C90C26A9A6A2FBEA15DCD44B96A4DB5B4DE4B33AB63C22C278B156E3664D51512D60CACC43CEC06971F225DF8C2977F9A86DD1D9FBB10EE37E56F4FD25EF4C6D818CF457EBDD9F81BB9C7C7BDC534297988390B0730EB53ADEEE810058D535E5C1A4FAAAA4F52533081055C692B430F9CDBD5A45EA8E52BB8862307056707641E7537445014080267924AB7E3CF6DA7E306E4484A784CB52CC660CFDDFADFC7AD21E7705DAA42D692F9FCDCC3683B419733F7167E292445112A0CE202FB205F4831EA167E416EE8E8C72F2C644E2A81627B10D45188DDD7B02B61FC4012783C190C904F76435A83C5799DB1CC840401467047A26777A1E8681D617647B15769B3A052EDCFA477EB4462950AA4A1644ADD80012793DB0908E02F7DA3F37818F10CA0E29B88FF789F7B72A5DB295E6270A3CD8C3D348D88C07D0FA2D43DAF27154C04344F6FCD97265CA6C6283D2508E8586882CEC65EB6F0E4BD20490F5A7E209E7B2969C3A18647EFF4F768D3B4AF667E8458ADBA31FB31364F975F062A5CFC1D3B48484219B56DBACE1834E501D55DF4232776EB73200EFEB404E65C5184E31EF97A09C64049DA1DCB48AB2723F49AC0BAAD2052127203805145D549358C705B23157055B5D6F0EEC0B1BCF2BA4326D2A74742CE8FCD21AE396F41CAB7AE3EA60CCCF6DD0D01B6EF8E8633DADEE12E0737100C1C604CAF180B12D3E95F528815B0F194C45647AD09185A658F48D0BDCB7A45B5E2149BED5C744DC05932CAEE89B5724AB2851BE4B395A04C299292D90DE2B9594F689DFD364A9D2937A99DAF488769807AFA2144FCBCE3D662C7644DD6D5F76B72D7D6B665F5E4F17301258547AF15106F0FDB165ED126CD06C24B9B5FD752775AB8BCD20539BADA1B719B1DFEC52B25F97A577EC99B80BDAE8F9E248D181E5E5205E99E316853E3EBEAD4BED7983C120EB5889C846224FC547B83CD9468589F8CE382C407E52F77C0BA166F66090D6A6CBCC277AB0F944B14BE87A2E5D8289C9045A42168BD04545A4220531D20B8C1D30DF419E483878E9B830CD751451DFC4EC7088B523B9EAB87FA14683F7D9F545D6561D24C2F6FF14F384F0637A8925D49A2C614CA8A2AEF5AC45DC857B381B17D0F5DD7A19573
+69169B1015A81E5C0FAD95096D91AE698A0A02ABE2DDEF6A97E7A2865CB73E1DA62A655D589BAAE7C018A7AC77AABD5883963E3985C0B8B6A877ACECE3EE0F58678C94774B7EA545C1BAFA33D1B16847CE169C70B0DD8440D74E4592262AEA51C65526A37C6229B5385F65E0511D25B66027322266C8AAC4CCC555D7E963AF8EA60C4BC6E991B6EB1E28B61973696AFE5BE7B2E9C81B93781E0108679B604027E20535BD5FFAA63BC4047DBA00D852FD39D8E3CBFEDF42E58BB95874BE55271B9B5A979D35DA249F160B63147DDE93FC08AC0C7F705FBA8146A20E7253E826B2746B9DEFE4251B430F5AE9CCC1222FC46EF7EA5E3CD6ABE6043E54029A81A53CE64B9DCE4F57FBD7B060E5F777EE31501F13EBE115523EEB941106D286B4FBBFC66A0D68646C5104963A2DEA21AFFB53A88DAACCD898A61AB10D1859256FB671E8B0990BC08EB2B21C28584E134DE3C911256D007040A42F74C95E8F8A700A0CA137D59BCC102F3E701A161F447CA0DAF622EDCFD726B20DA671D3DBAF295EFD681D5E209F06C196AE51F2520DC71E4712E34C1FF57FE54C4641E518CCF3DB34A567462D27282C303FC0EB3E353EAE3BD2D46F50A4DE38B323EB4AD1823E916231D5B51063A51EA47C6C1E8C857740B16AA0FBE9CF3635AC166D7F8501D6C7CF1D7FDDD17B7DA1FDF6D2500F38B62129D6504506AFC673F935A0BFD39346A007A9FE199B25BB39FC49801D2D48A52047F07D77BBE68B2049C15BD8CE1ACC6FDEF9D4FBCBC140BED419195D6848053AB2ADED0D102397455F7EDAF72E9B58F7721BFA5787F067814708126A42F9EE6C0855A0E0AC3EC5002EC26FBF7042EC0D38BA7E243F13CD12BA07A072A716D4F4A37B711D15C72D8C5AFA4AF7659A459BF7902483A74F74C6071AA3C006C577965DEF649DEB835032D77D5B62CDA15C9D228940836EDDF03CD985F14E38BFBD24EC22607FC1AA79099B10746182CB3066971862AA6801E978E0D3CADD493BEBCC2AFA737E583ACBAC8B92BA99A7821EF046453A174610631A1DF52DFC5938924550ADFE81B1C16B26326B12BC168111A77CB52267A6BAF758C4AF3869201FAA302143596D16434AE7AED02112C64EB5855B1115F8B211459C975CFA16FB6A80963696FEA7603D3EA8837047812955EA15991A5275699616016D0EF6F95BF0DB454EB67183AA1AB65C8DD3F9584650890DD18E23036D2292DCAC7EC39521325BC5AFD8485CB17C4FFF86A2584AA05D0E5884843558445C5E4304D5A8D8A12EEEFE3CE9004590ACFCDEB6C56CFEE727ACCE9A76459081AE42CBD0460E44E3BBEEC73C5ABB42DA1D01FB97330412BFC2A7CA21B190626042CE12F35CB82741A11A9376131409D8E5E3983290973254081078D71E5EF188FD35E59A5799F723C1C30A537EAF32B125C12C6B64A6444D047BF0D2
+D272913DE19094EE987A82A1C8C2B16429DA34EA56BDF002C8D7478FF3CB46558ABB1EC51AA614F068C87C5AB9DF93C1B99333CB7B21D2A2065946D8AA139A4F38445BDBC932019DC4B159343D2F38E6F1C2E350A0ACCA94BAC31D6496321ED437CCE019598D05E70DE7F324807F010D4851416E772BCE32DB376507D451151D9B7BA74A0CCF6648D9191806BA76F984A8F2A5D9D9AE5B0331944B08D7EC47B77304A3685168AABC1C3D59237F8F0F5D27EFC7A1ADDED1673774CD2D3B72E1D813CE0A1F96E25DBB83F25F60DC5ACEF7A722295B6F4D47E027EA066E094B205B3266E1857B27F17FE088982D059DD576098F89B68451E9ADBC8ADA24EA33B5B6710E4A6843099C9F295F75C14DBE90154B5B2771F4F9FCFC81B1596D0B0535DB6F60126AD2C78E3505E8939F2E2216325F363A689E235A6FF033E27DF81E62D1AF5B924260348CE4DEA2563458C3A1189CCA1E9442DBE3305BA8089BB242855E1C4E2FAF43CD25206EB80B351E3C76E78801A72D5712E6F7CBFC2D4A42492A432888D06108F62EC72223A4C54188016D4874B258F3E0E7C354ABC63FF204A616951EEF5A7C89A8ECB7995021BE35BCDC46C4E0F90925B63E9B83F55105DF5516F9BBBC187BE48AFFC117BF5BF15216DE4597044A79225E398B5248E6585D6ABD90A87166B8A67C6938A6AE6ACCF45D9E842451AF5A7C927E7CE58F445DE704A8685BC428956D37893C7E93E4E1D851296B53457E7AC0686AF4E1C280E9D3E16E39FE0060C0045CCAEA438F27B416D6C28663B4AF08A4F1297BE383749BD9AF2D91825E5170C4CBD0560D6943D117C17B21DCC678E1F6E38FAE48F1A3824CB12CE1AF540B5B282E3A5086D2998166434F827EDD80AB996C4688551D540EB264E3D1C7AC709151C4523DDC5406EB1F01387DA27F3019B688F96C003C51C1AA2A7443AE74B5791A0BACC92AB9536A43ED52BF1080A2B9C9A363B802F3322246078AE23B946D1E38D5E9E866FC12F92C44E52F418FB8AA189C4D0BCAFC9C44254A0F05896097BC1C47669E416D23ECC09AE1D43B092482E39DD65C55D330AFEAAE13C191BA7726DC2DB08F8A5F6CE107070CC31D804B10FA901ABA8F714AABA17F879479B247F9B417CB3A49B01167C9ED6DF527B3DC3BDB86F1767C5778A1DC41593E88F0CF9385944256EECA26275F28D38F4CD9DBC2050D143D10CA034E5C876BE3735B2E2553F99A60C75518D1ACC07D311B5FD4979417A4CA9E2D121097EF8C2D0B0F39BA1F14DA4B4B87ED435374D605C0FB5DC18E49BBA7117EC1B1DD0245491891F1DE8986DEA38DF323A9BE4EB620B023568FBE8CF5778BA03E5186300032496AC98C9A4F9D768E984BE803C98CC3622812F726FB2ED703EE07D9F8CDF1590AC2A5377616D4320EB82BE6E6DA51D2786CCCC164558CB3AD9054ABDE9C13
+86CDCF0947ED12F9C11E3842CC437DCFD006CB530F00A2766353BFF3BEDCF3C0F8CB2B1CC1B9B3058720EA9414CA04AB00BC012B8EF31F31A768CB5990CAC70149097F0EBB5039594662460D866064680505A38EFF9C14391EBDC105F9695CB4748E28691ABF6D242A6D110BC0785221FA7F1F3326DB29D305C83861E9FD05A40A59F38BD02C0972ACC5AA165116597E17DEE19B77628ECF82AEEA8C5437F6025BE91CF1F4D8C009D424C2508A72B69CFB7F82585B7B8B7BF1DE3AA2AE33C9D25C80D85E125C731C51463638B6A992F7BF0C28F68A4C1BED08473366BEEB23790D4B321B1A311A732A14DFF18583412FB7AFBF47B819F5EA112BEE880E9F60781B6D7BABE55BF4909D4A9967067B0D228A566930EA9C3F052120E42CDDE0D81E605C31EF856F34CD58E7B4627DF207E3B05C9E56A82783E0A7B799EE01350EB4D806DFE5FC929E646D24F0042E639F9A5213B69111B87960FEF41EFBB43C4E4176E70B44AD73F205091B4DE2B2BBB561E6D86A9644F09AD5E98462AEF7EF302A18CA7AAB8A2718C2E55B5E2FC7CD5156A6A77ABE5C245A6C183D2F542DB23586947487B0BE585F9FD013765DDB2E80864C49CB19933351CC54F6A84BB60D7565916671D3F70E4E0ECDF0C745912A25A97A05CEE9DBA676D9CFDCD6157913E60A6C98D5014953FCF8C38369FB7494C5C364A94B0D76C47A53D0017E4CE19D882852572B70696EBE510BCEA12A861A9E5D5CBAAF176D6AA3BBC6D50FB34468205FBA7625BF4B5144172DAA6E3FC57859F1207E12A006313BFCD84960B67806ED27A75A0052CFF702468376CB9EF4A940969A4C0D844B329CEA7524DAA5F18FB2254A140A1A6EF795ACFE9F7E8B44D14EE7F535B89C4B5D10CFAE077A4B2363F4016DD8F33349D157E03F6E2207AE15ADE05E7D7DD55C2F0D9D64C98ABB1A3354FDCEA7A45529DFDB317A513A31EEE09A901712F61840A16BCF7653DD54E04B66D377398810AE05F9D28720FF8D0927932D018947BBD1A460BF39F79D8FDD0418D779BE73BEF71C5DC2C9546641B3EB90D4A71A8C9BF876B3FC05AC99F5D4E00A5C0CABB0D224718FB347795B45B88415069E82FECDDAAC9CF5528FDF3623A9B65A38E70A0F9CA921025CFCE3BE354A0FFF524F7AD11E0831C07EE2875A0CC1DBA37A3C6C9C83C0D94CC5D9ABBF8905D085E05B57A0F39E4F649678A7589E45298EA317D95C067B7096259298605B072A20EFF9BEAD7BF8269069A9E3F5EFA11DB25F54331F94D144EAE682E39C1E9694F4B6D5920D2D1A1CBE16114A22BA9E7655BEEF51AEA5A07032904A612BAA9FBB5E7CC47221980CC8624A177A4B99C7EC80D35DB85BBC5928F23CA8F752BDD361E1E1118977A008FE37190D25563E402673C1FA77C1CE7D6319F2BBDC499EE4E96007313ACB6056DC1B5DF7611C75A3736D
+58C0C17A6CEB185F869634EE87910193C08988C3DE37CC5C17684659DFFD7AC9944075444EDDC19405EFABD1E08B574525D77770F27900D4EE6E2882B9F3E57844397C034E584CE52E4EC05CB1C714EDB52CAEAF11F74800A935A320234371FE80497DDB5DA46AA296729D66BF13409D29ABBBD310F8B8E19DDA55BE2F45C249B5B11F78BB462ABE9DBCC26B1A00CA179A372F8D96A9BCF88E35431ABD3C6876EADA581DA0B7DD24F8B410CE3C8FE66DF0E943E703F49EB74280858E4076B1317E24DD9595E1261DA53AE86388EF4F824BBE34A641D0A17A8905BB122540754C3AB6461009635E1E29F5FF9AAAA31B58A5F38F86AD80D76073AA94899D90EB2FE5A48B0F0AFB99811C0A6B1DDA94E4F80ED4EC9F04B87BCA4DDC2B14F1FF8963430849E6BD5A72645D6981E37A11DD6E845C573D64E26447A6B226A45A71E54007221E06A44F9E4E422FBA2DC1805AAF1127385C1A392A1D6F21D4AD9D605AF0B9589F65B6BB4864B7F2B02488670985A1D8FC0288F3FBA6F828C38E02ED0FB9CBCBB557FE2BEE6ADC5BD3128B839E5F0B357E4870C68C5514AA4E7E6893D94C7B6128575E71B04908FAC8F288005B93C99B85D72A1271BDAD1943F7C9F24FB188563F7A0554B356CB498596A7F2C7E1BD1144EF5169F91A8E6BCE8D2F572E2F04FA3EA7A909AF83DE7CFDBAA147F7704D94D977CD8386F7F60C0D327A17419D834D67F031D22A7C139785F1FBA04A8955E1EDC31612482456B826D6760BDC075A35B1EBA81ECBC02C9D901A257A6E1A3E77CCEF00E20B3A2CBFB050BBDB0654F0C5E31488343688A29B6D0B9018FDC3744271C5825B77AE529863145F3B57F8B879601FA095CEF4C0132EBF1D6031C0EFDA53C80EAC5D214BB7AEB0DB78A92C0E0FDFEF7EAB154B9D0117EE43F44BC655B39A0C5C5A0E3286E03E7ED494EFB09D8321B23EE85FD5C9F28FCFE70A28A5DF04DCA3D6D8FFBA2CE354D7AE95864C5F287930D647E1EE91F2440C0B055A6E28A71DC2D10A84CFE18C360242A6ABFF33512650103F7872A326B428F5979AD5F98EB429BB71491F4257E376F9AF4E99FB67339E0176F2368609B99BB5D4FDBA1C44CB4581FD885F6F77AAE6C19E38C3BACFF8C46A5E879146032FCCDB86BE595E29B9B5273CFEC946581BDD3623DE38E0C62314BA3A4814DB1677FB3BFA96335B0AE867BC145D13456197E390184F4B9C187D11998DD8823F6325DC89B5E6C5FDBE3D0A550AEF03F916E95C4B2A957606116931DFB5876B69FB90681C5424744F3DDF024B55FF89863FBABF86FEC96E86B2839E5D55A5866721F0C07A29D84B00291FF49F9B3D8ADC7EFC1EC50E562956B41C5E287508B6DC07B14B88DCE1FF9DED024EE68461F362A35C95F92479AD1C86A2964FEB9608AA6794ACF93D4F2FFF2CE4AB14C1317F560613D3CD97AC3F
+0DAAD653CB2417B792AB665E650369F893B76C61DD9E9D68BBE495572CCA32485D494EEC6C522B80804D152F632A09064E27D65276D9150B9ED39851EBDE770639AFBEA8A9A0E97F63DEA7C530695F1512368479F83D51DC144842438FC88D4A158BB4FFB90A68CF7A27D832E02B8A3AA3EBE5FF551F2C09F3097774BC6F626F57552FC8B934E8505157499588A31169C6D0977E5D1ED1975B210BD0878B96C61BB52F3E55151BE96D37EDF6FE21B07BCB54F1387A99700AEB7684116072574EB6954ADED837FBB9C20828734A48D7320B3496895DF6A515E84F8EEBAA594B6E0CA2DB383D8F5193B991C8141792F5CD9154E419E537A0225DC9C83322EFBDFD3F596940AB3C70E2B0846055B026A8FE0E8C57FE80C51F157AC712A1BF964CEEFF1C7DFB2C02B7E26BACBD36EC293E7DD12F5282D1A0F40B1269378CE753CA356AC9382B206DBB80D2F5CD0FC0FB5A7B4A29C92EFC74009766FDD50BEAB2C460CF3D9007AA3B85F9BA256F0FFB6EDB453513D425927C4488901511897B746A6B45A7D939B796BEDFE0C6EA366C31034763DD52199F7367DFDC50826B45E4F7862584A3154084F14B9FE54F66D6237D67BD9A663ED266604A39F86BC663C8D922361D09FD9EBE37FEA762C9DDD7DCA84653D173CFFE3EA649B173F690E08D5C4A583255AB29A486789CECB7442DEC29F45CF44ED6881720BAAE35831DE5F586872C632B90C1BAE2DA86B165BA236724B36196A5F4501933CC3DC028E3BD7D85891EDC91D14598729BDC695BF19F2A3C4FB85D38521AEC1835B64B6B3478E1A51D3422AC2248950975890FA20E26737B6CC66F2E259F9CB38A4652AD0816848B47CAF997FFA961CA40875ACC1A19EFDE1DDF8445944A157968C1B663DA42FEF67216974510E66E1B98F55E3F257760146B5142388E12204885FFC1CF359CEC5241F1A1CB81C6F821AC0FFCB407DD94BDA69120E8854011525FED75DEEA2B78EF7FC51B43FB5E1BE194359E0B66F23E1AB5B078FEFA8B93A15E5F70E0A044EE7893758B2B53E8CA986AB3D774EBFA1ABCFAACC7832389BE0398FF537E85FEE3B7FC7F9CC6DAFFAA2B73BB02A9758BE83BF2455F1F6E4CA380C4F9BDCFFA1F155AF8C99E62EA2552BD213D2C9FE7C2C5359B2151F8DB5871CB64637D463A7169FF15B3D8997E4ABBE8B1B1ECD2A3E71A13C2A1B3A39A9232EE2105914D438469149237364BC5564371E5EE5D0D549E4F2F4A91DE0C337A7F6C89874949F02F39074A7D022E6199DBDDF28FA44E88849AB2BF34D2CD8C936BADAB566C5551905379E2A80AB4FF21B88EFA3D7A9C8F719C92835A7EAC208251473435BAD561532D4ED1620EB85DD89BC8D90E9B94396E4CCF010AD340AEC962513C8B734BDB7A478800ACDE06711D32BD3E15467E00723BBC45C6D72D56124B25F3D52943E3E40ACF5A
+0AE34E78A1299E7BDDC39F071400908C77EC89BE08D6128039CF9988521797A451DE37C33C415756BAE4D1B1F86DB7C25A548A7D99D61ED9FC9011177C163D3CFE9F5D7997D2BC310F8A1EE1E70C5CC11F3BCA0F600F4E182920F0543E140276DDD21E298CB381106FCD818693CC717C79F05F69C94BE2DF999B1EDF93F2E4639285AF97B91436B30A7315D4FA25DE63920B08C94E72F0952AC7B1B2C696CB156BDD6C920A3359D3726271F45CD8566BB968114B172F4B07AFE30D8E016DBBF44326E87BEB2317CBC6094412096A7313855A5ECAF59744EF3389C97E02A927971048A5D3FB15CA79FDB84CC2398061979B81BA8F5EA327AD2A8682A8BF35D4C0E8EC7B058DC1406241552CCCB182637681FED9F2595E5683D1EAB8D138B12ED1408007DAF0DD87B4B3707E59A86F4987ED8204F877E68BFE2A4D7DC19D8D942BF895AAFFBD4141239B7644AE8BC9B14FC09B2E06DD636A187C08FA2B76D1554514A55EAF97D003E222B5C42620EE15B53D8BE2EE54EB71EEF2BACB2FBA3FD9A147538E1F5F877B64A9D6C27369A83C5978F191E51812D24CCCBB31C9BA5AD308CB0C79F2D0DBC9C4D384F5FD592DABAAEEFF7672FDCC7994C25D9738A4259FBB9C22B9AF613BA62D0B0A09B2EFB29F2A25A0EF730C25457E1B8E09D00F77C4DC246AD1CF284DADF2FE9AFBC252D457C8D353B2BD785AB04CC79D88DCE1D9C15F640CF16F587ADC6FF95DA16A6E9F04A2FF6187CE11C384EE86B9AEE0C16E90DEA62D4098A43049D96AEB7B7350BF9352CCC0D63F98F0D148011E42DC6813AE33329E42F0C3FA1A47E3130D109AE31912ABABB4D771B0349117B687DF7780FDDCDAE3DA2B9A601F9CBADF956F90BC59B64770B53655C8CC819619C9207D46E872FC8BD22C4FB52B739BA88012F6F3D8B33185F90B15ECAE90F671783BB27F0B982D649C08426D0DD55E32FF3D04B3E781C82D7A98D3ACD8292081472A67E219D341D0703C22FAC9803ADFFC2DA5D1935F7A7F312E4765E3AD1AEAA9A6D3ECEDA713D0B1D5534476E19A804D948875050F514A7B0E453F0231B25493F01B2255EF03F33C1D4C055970DF370184FE931A282343FBB0F28E7532C86E2F8436437897A4490A0F68B6CF19C04346167B4AD73004EC7A4BCAB8DFF7A2B8B88B2AA03F9AF016961C0B178A3392F12E7794AEDA83230419EDDA3A1442D75E43F479D0D4E0F79DD3FDA2E9D7C0E5FBB2E0887418F0CC496D8DE7DBA7BAE3D133E2E36C618016CD0555F119C741947A6B6138A55FD7166A42015170EA6541DA1D6EDA0A734DBF3B21AC8D9679D450D9F2F25A243B0B27AAC5AFDD0CD093A0657C44EABC1DD959C5343F487AB7CC4F8A58025B2FB5E4A0F653221B83FB90AD480FFCCE1650304F7B856BB2641B14B8CE5F9B7760FB1A953E1D9310DD2E3FE4FFC5C157514248
+B520AEF69524EE9B3A186867B0F05FD39D1F13C170A2A7AEDD5FDFB7B5B8D9C842CF46E2A2E6618EE9545B67C7A264684E835AE38F0E3A5D75AC54596D651F59E1DCA2F5DD8826AA2606DBDBD5EB4CF7AFA9449D839A0D209A344629BED8454A98AB878F1F5B3612279FBA212EF858707A3D6B2D7E2E2C15B0F4A4D1A3BAE3AD6B2E0D5F730CD78CDF87188AEEBDAC3CD53CC10B5BEDDCD7FD6677C1CDD8756CEA99E754B638F4D29AC988816D33E01E2233E08426E4E8ED2AA03B6D06483AB3B5D80D29648456752049414E73DD1FF33283C935A2B30937B64178C41C41FC1B01CC5B6A8B7335BDA8622429C7D308571271909992C01FB00882806CC0DAA6675B30464F360BDD96258C1AF1BA9D83EE2FBE60C5818C94CE5866FF0960B73F7E1036C711BBF0583F225F339AB824E4026382A1A567BF8A6A94D0D506AB28DCAA1813EAC89B29B0CC9F9EEE63C09EF7BB67254A3EE107FA35D327C7229AC31EFD1BFB0E4353BCD215B145E45DC06432D3DDD23E7C91F3E2884BC99696F56E0AC0622C40DA05C86473E4A60076AD0A9D3DA37CB5E8DFA7FC1E22AD0D274A0F4A1C7DE93DE891263EE4D88C15F6C18B3A2077ADE200D2FA591E2032CCB142212F06EA3A5DCEE7281AF5EE00E11FF849DF1DAC54787833033EFB0E1C28DD7124C2F5FC154B2BE0E8B82DF234A5A83F2784674E8424582130655860B83D220E9F3758B24BA3371EC73238512D704588713E5CB5CEFC7E27BA298C4EE6A0CC1111A4CBBFF4F90947E94E0FC97F94AE084A8D9FC852F429098915D9D8C6EC06860533C3A3DBE9BE5733CEC98AA68ECC2A76ABE22C16D8057733E99B5E2329E017B8739819654928A5E5AB41F2FEA018CFFD97681D7919CF70382508C82017588B60017269627913DF7C76A91DA8C5CDECC2C1DBE88F0444B3360D9B97FD75313A65CBA5BB2F92E28808903F4499C1D89A65A36727700051EDF2BAA80DD9AA49172A6D3F5231398BF106DDCEBFB0AE516E4BFF4B64A2978DC592A74D7087D2504DABC61A0C492F6009B84F3A6A9E72D35137C8A568E74780E9744A3D0F9633CC18806C12AB77EB54F683689988A1D558F2CCA0C486FF999780133F36D13DB394615F0C149C575B926CDCA5CAB54DD9C7181A6B91DB5F56A1607DFD10DF9768BC01C5A132820E297D38541B73A10B3DC4FE49E67CB0E4AFC5E5E131BBCC544FE5A147F8494138465607876DDEC4AF13DD47547B26482563B21CD0E2FAB446C2F7A3A6AB88A393AB5B134F33E1F6B368926BB69369C353F7A3C250054E7DBBD46A7BBCB398ACA33B236FFE5926E5407BC2EA7BD3AC565071FA4F3EC158223A33D82CB65B121805F083BD6474C63E83B54A8939D5ED1BB5A01C077DB3809F78412EB4626E4584E3C32C20586D250A967055DBDC06440E289393143E672E9C1D021503008D3F
+97E66480BD60542B8767EDB533DBD36ECD80EB9633F1D8A3ABD6DD258F9F12FB42FB7DDE9D5162CD43477DFD231892730294F24FB6F7D793792D9841BA7EDC971CB94E0518B0459BE8386A8BC2D32C1B56A352920D1E6C724E3469184C7D27D272CB2A2F2C34FEF09C0338F86BE5321ADC82BFDB2CABC1D71C0EDA0DA70097A13E1E3B04B953FFC18A82FCC00396728EE3034BDDC79E78942B2626F7B926D69CFE1380F3C73E8935297C363ABFF4CA15D60FEAB4782787BFFB2D5A596A3B0446523875BF4BAA083CC427FCF2BF0E0C7B3A9C846EEBF3DB8CBAE695D26A43FE9B711C09E7F31A8483B309FBBE6ABC138710BB550AFE2A614B71FF6873943CDFD92D028677C6CAD58DCF1ADD2B5C894B496D02161CCA64DFDF5F790D2D0D1441634FC860F76A0A7BA7F236A927C7C0E5E92444DAE0C4F1483986A34A462FEB75DC47BE5751E875C9A98F0FA5891285EA7E906FDFDF13368E15C343E3E9A93E2DAC14FFE5FCCCAF638AF63CF1B1E5B871D964154EF40C86ABCD1379D1767A8F419260CFC02EB074BF43E555CBF0163C5FCD31CE9088848EDBDF7DD7D46EC0E12197D973C77D8436AD0C4B6BF31442E01BDF0090A49A6288076A5244C390143D4A89EC0D729AEB7926294829FD62B6E498DDC52AB3CDD2BD41399F9C607F62A86DA089AA55773FB77B0F7923C4507F2ACC07E7DC8E8AFDA1FD963EAD6CBB5BB66DFB11A694991FDBE5EE93E9AC5F0B4782AEB2F739F8E27EC8DE1121258D3FC810FFF156B9536395A9DFCFB7ECF2E580C0C97AA6C981380689D7858B80444DF74A79C809581EFC7E053285240647FBCD740A9DC4EA9E41A94B240601CF156D746090F08930E165B0381546E5345B97CC7B72E0DA7F50251F620FF65D159F22767A6AB047CF2C3C89B099C73AA7F7BDB29EB7FF0A54CF70C17D4BDC22153956523BF95EC61BACDCCD8D6F8395324404CFD997D3FE19B0587F886165AC3280466BF45586EC7707CE88216021400E4C28AE907D4C9E4AC480522690DBAB3861ADC578DD5C18E5628462A6A569002BAB7718B1243274E30FD616DDD61508E2CAAC96F32FA0B2737905EE4B42679E2ADFB2CF6E0DBD0AB95FF2CB13A826C226644497D57405CA9C950B9EB39DCE06D687E91206A9776B0D6C779AEF4603A62F22B78789B9CAE0B3D0DDB99461614905B2045442D73D319DC0E41BA2AD05CDDE412561EAE9F081CC6A3CCDAB715B73D2C69FDE50C384F8814841E0007CB68C4ECA723C74FC5B97AE585EAC10394516480EEE139EA3410EE4082A30D482438C7623B6AC16350DA1432CB4A682B48DEC159FCF816E56EC45E31D03D1BADD5E78F7A59DB9311BC6B64EE35AECA31B94A87E660C08E4B78D029459DD763EE1F0D1B70BB7C160E30D435DF6CEAD1104B63C830D0BA6B4CB2C64242B682E987ED102A643A00C25B3
+B1DD42B485E263D0C918804337EE36B7CCBE9981F5FF7D9555286320D2D93F60BC80563C764EEED77C6788CDA7A2C36D860E3CD36BF9760454F2FB2A829576F3788BD8595C262F985B731BE968FB2BDA84F289FA36181093BCA04AD1E4B0C44E2B6A861F968BA661E5B111A168F0FD04897DA7080DC0D8F61C440B4A151A1A05F34633509F80547E2BB0FDB3042366E6F9BB628714458D07F9E41FB781C36A132A42B3632EADE239E64E22D86692D43045BC9E0A661C9196FAC402FEF7BF16ECEF2472C713A1141C0BEFA61F1C92D3AFB1E6E3CEF44008311FB6BBE3716D1EE71C1A0A0C360A4FA0ECC107F35E403BF64F7BA8F67C11D7A42282F937148929DB7AE07D44EBCC059A590AE9DC4C368D20722578EDEF0547064FAF9A6EBF9484A353E33BFC6F2A4618EF6002E7BE0FB4224E86EB37FF082183A5097B7DE8CED15C1B5DAC189066AAF74BFA0C37D4E85DAB82C6D5F5BB91B0B664C0C7C32AA5A33EAE7C2E062E6FC94EB0FB9D6896938AB40DC37DBA670E8896014ED5A995B173FBD3840F5848ED7063CAECB2501C7A2DAEBD3A7EC05F681C7022D8860A78926D0BD4EAA030AD4EE4B444CA4590C1CD57EC6B102DBBCB67E088DDFD4A9B1E6EFFE480F2B69757FC5AAC6639296284AADD52E5B0FA76011E77412D4B6B850D72E694642311DC4962E04C9A79F043A9F0E3B316884AADDE9792F5E30E57D2A9952BDE7B9D7624279B73F187744349D23E615F600B08BA497F1951D8409B4608B99625D67548013157DD1E689D5BB60602BC336DF23BF25822619A7A66D0F718E7EB79CB8D1156E69E2033BB772C5FF292F89917117E0786CCD6146C16C9A8F833B1C08A344016758187BF3998DC8FCB1DCFBF6BE4DDA2759FC5DE6F0290FB8A8A31788851B11A4F0780107CB3C5A246174904812AAFC37126E28E11380852878858E0D97BCBB23DF2400339CCC83682199A6E2D8E044870ED9DAC5E686116F53ECE3FB5260324BFA642A2C75AA66D070DC90A43D7004C8E5A67525E43D1B160D5E3800728B387E335FCFE5F88A8CC1D4F8B65CDA1085FE08F73B2A0268B0B1B8CDA649220E0664FCF0D40626EF6297F60FC97BD89A45E8CA30DB2867C5C90D3984154032E31116968FE1E17BD0203ED6D302648E19A00E8BB5B42F45025D188639936EA10602DB44B60C9E92CE33C351C6579CCEEF6E95B5D50E6F2DD01EC53EA87188DAE48DB4597D3F9B3D9BAF1BB48C88492195C44E4687DC7A315BE70AA3E9EF73358CE879F45D2261DACE463409D639FAC6386E66C358FD65705F38E7C1517D53B48E650906982F49B5FF541251E9E6D3F17E196B2EF446E12D894BB006199B0632E4EDDDD0E298F347BA03BBAA8A3987DC16FF9DC7F41320AC6462F8F59BC9DE6F80DCE2769AB086D3271C8F686F1F39B8AB8CC86E8DE2DEC04EA0DA6A59709
+C71F2E61C64F60FA3BBBBA196F79D0D74CCB97AC95E3CA87B1D902B60F23DA914BA89431B88E24B437665FC79B92C2342F8E018A64A2F43B9686E4937ADE92BE440832EB33E5BCAAC3D685551D9B50D895D6FFF7BCFCDD6BE2D8B91A36D8C0B49F32E58AEA6AE837E1E991265D6456F848D69BC38EC88EC453157F69584322E4B6D9EA3CC44E48AEF71440DC1B51F14C97DABAD4377C9C1044A276AE6EA61A890BA3BCFF94D0577927DE16072E8E22AF4BDEA3FB4202DAA3AE8D6D7B9B40D649BED1BC149FB713FCA49D543EBDA936EEE0C5D5AB4B142D7C5E85B50AC691FB3C086BA8975CFCC722D6FB3EAD667148983E020A9FDFD005277F96FEDD981240F10D89637B9D8F7C91EC1644366FE715B8783F1EE2EBD0C42F88A6FD6DB4397D18938A0A6E7737A5AAB83FD499D5985C9099DEE16A9DB15F0373AE16F5BC1BE49F9D9D2E2E033621D7616B91C0EB0FE8F8199330206A7AA783B9D34C382C040E916449419FE3571A01ED4156A333ABC0CF825431FC73EA078127EA3C5C848762CF87C3D3CD38D80FF74FFFE118C39E823E6C738036540D94E7FCF3EC4727D9296468EDA28ADAB8E1916C28EE01DD2EE035E4EE4128BE9BA3507C415C6F2C24FEA07DE74268CC3B394D6E61BD69ED469EB694BF8A4AEC01B456889517CA8CC2DBA7076E7242A74F324280E5B4744A1156838820E44AADA3CA3C4F07EBC0FE0FC96F2A3115C96057826249FAA129AA4A6AA68F27495C08351F77C53207BD2CB24EF1F18FFE457E463B0D2FFAC4B79F7EC9C6DE58E1A3A8D74EFCAF2F2A134471C0A0FC574AAA3ECF5C8771820F9DD5E13F9A0D433936888D420B66CA575ECCD33A3AB327C2209967C1BFE9500A3100D9DAB3E394FCD253C59C51BF507E6AD8CAB7A568E52C6D0876DC6503F6EF907020A46DA9697B0EBA3D89CC3820E61583E98A490759E400CC341B4CFEE0EA3F9BE199FCB581D224D54AD2B7B964C770A8FF26D57D33DC4BE38D55B212C5A4056391E5A251C24E7011B82077BC983227C8DD75FF95C9942A1641ED39DE039A3BCE91FE6C7D5EA95022C482655D1425916E8658B144C81707D90656AD36B02066044A1EAE31D2B23DBBB8C184EC5D5B5305776A2D4D77FA273131A14808450F917B73BE6791B9A5EAF98A2A830FDD58125B8B86975D88D85781EAAFEF3090F8718D1EC63D298863322F738EB890553D334C9820B1C67AAB9229DB835EEDBDEB3D955C83788CEED737382831930F4D118622B3062F1879B9F2C0ADBDCAF138D4957ADFA86EC30CC721CEB119693D7FA89893EAE77E4C8335B1EC9F5B079177978768C57F2D64A26DD04333993FE720EEC27ED4ADCC87023E04369C0739C6F11010E2DC18ACE4159C70C05151B6F6BACF7A14D5A041AB6B32BCD7967951CC9D2A0B18C60F56D832D817C18AACF4A378025E876D6349
+4A7DADC6F8C5F860FA93FF4F0A4D93BABF4B92D240DF6FB9A8566904BAA74E9C5993847E9C0F899317FA8971DEB25083306BC7C307117EEB6824A4FA5933794179C9EF0316D908482ADF4AEB10DDFE5D6E91A301D8A50A64B5C4DD675D42FB08A601ADF00381E72A947360F38B4B5191CE97E204E2AF86F228AD32EF9AC94B3FF0C976391BDC2D5695194E62B4A07CCA4080316B4610A60FB90B2A361BDC054D8CEC802FD0BA4E21F029DED6BD6E28DC530B9166422511F7AAA5E3F301A315689C6F0BEB2DE645A33831BEEEF8CB273C5A5B79F01B6DC396D82C4FA988AB92BF8174D6CE2A8D641E4B2F57237BE1B6D3126B29710790DCBB14F709CAD25995A448AB50FE1D9336D2317B20929B32D3557CC0EEE7ECFA1A5BACABE8502471831553A9D1F1B432A27D8EF3213883FFF8D907C130B96F08035892E02B36935F91992D4FBCACED7067F0B4FB9F746FEB7FE0FE9A644CA48225F5D39381F6FAC6E7AB2BEBD38C4E146C96138FD746139AB7EBBEC4148C82E49B608801545BD924A77A3E010A9ED7452C4A8AE7D701C0E5BFDFFEBD02141152E9595D73AFADFB14FB6B2643029F4404086E0A33325301DD10DCF1F452C067B55191EC91287AF1F646B0D42A2D29A66C6D57295D7410E8F8A55246594A0AC0E44F8475CDC558DE09A435D80692EB7FB672789786DCAB1F282C104547E8B7A80BDE89AEB32A96F21F219AA6E05C7FB79AE9251B05E479C009D2A2BADD15B81317FAE4D0A95C68DDB12C78837AB934136E9D3AD419D26ED1BC893D94847D58F859FA1D00F7C9A76D265C00122AC93C2C653D3674DC534158BD4EF9D18CB488153C363A9986A166AEB7DB31736E3A525ACE8BBE53340503E9287A464AC4153023933A0CB61F75A05C56AA145407D7A159431AC1D3A7F7F52EBA7733313EBD6E71028F6E8E3167D89F5FC3FDD721CF96E3FDA6E632B82C6E033E539DB516443D76179F0B75631222728A79084EA25DA7F575C20943BBCD5CEA998D3CD29C0ACCBEAEE9DC96F825DB1026A857A249C6063430DD44306D5C795CC1B6C5640EC04238198033769933380499DC5590635375DB1C391BA68AA6DB6549A042FBE08A95038591C91FBF38CBD95950FCD796C93FA2B08B91EEDA3F4569EA1F4614FFF0AB5615D89E21D6DCB6C1B3F3C50945C42CF05D721D45FF657F0F45E5480A382B04B13E5C038813E0F2A41B6D23832E6AC9349735BA9DC09AC7EBE26750802F20ECAD92076226648FCCD24DFC5A0813A47E0AC7FDCCE0CDD9165AC411078AE3144FC1E483D2A5C855DE2E5684816E7E31F625E6F59A7961455C50BF2D51B9A10D556E4B9F6B144EC34EAB5F3F6E6F1B09229A12F83A4EA170D7276E72FE6246BFF4CC0EA6C1A2A42820FEE0B9DE7E4A41F65E4169072DD0F86ADB210D48B720DFCD7E1CDED5BE1E0E069896E2F5
+48D567FFFEA43B24000C2948B5CA7ACD4968BD921FF50425BBE92E583828E8B967E7294C0BB21D841E9C083774D583BEBE629CABBF2112DF2E1CD38C6BF5C124AB718D91774715D941586098ACBAE2A030270D4BDC9A2315A3830100CCFB4DB8C73A71DB7FCCDC40C95884C53E3DFDD68565C1FC8A563A36DC9B9CFEF2325BEB964F6DB8D9B573DF203F59AEB4FB6DF2DD20DFC6A7D9D846561DB1690A99542DB7F798366AE9FF42A7CC9F01E6F1FE5CB1B2C6999742CFA972431502A740627C9382529440D2A7A6A3E21D8ABE5200DF80B481ABCB39BAAF2AB385906105C2137D8CBBE7F7B86EB8CA7A85CE96D6720070F466AB4452541D51B0D259E32CB1EA2359EDC43990B03B4337D5E9829B1D1E9475CC1E9074A41CD05C5EA20C9B48327833AF855A1FFBE92779107C33717DCB1E169FE0945AE58D609152179E2483B835E3A2288A8DE5C56933FEF4229F8D75DFAAF89B8E331D7B3C0B92D2CB9260AF1605D37B8B653C29F2E68CB5BD70C6F86369B4D132E65EB67A20D42CAC28303A388D8FA42E2A36E40E637EF36E4C7678C7FC7EA9A932D08009EA04A550E7DA99288F8F7E97CBB58BACD685C58F8E5912C20965B6DF669BF5490F23E9203BA1F87DE7417C0C9C4AB8BEADD75AC2527581B6D6C4463B06491E839D5B2DACC183492FF0565A618CD06E3D18A729DB480FBF0EB2FA62F9558BACEF6AF7323253DD36A86001D9FB2A7E84D84D79558178EDDB00AB863594225FFF57202B985C454AEC0215389F079C0F46F3273B5B1D4183DD079B3818197F700952355ECA12593E8943BF51B652F0AC74B927051A2CA24819962FDFFAACA559FB6CC55DE202D896B9DE2B1AAFE4594A591659B1A8D4F4E5970E301C508161A4634334416F
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+ %endeexec
+
+
+
+%%BeginFont: Helvetica-Bold
+%!PS-TrueTypeFont-1-1-1
+25 dict begin
+/FontName /Helvetica-Bold def
+/Encoding 256 array
+0 1 255{1 index exch/.notdef put}for
+dup 0 /.null put
+dup 8 /.null put
+dup 9 /space put
+dup 13 /nonmarkingreturn put
+dup 29 /.null put
+dup 32 /space put
+dup 33 /exclam put
+dup 34 /quotedbl put
+dup 35 /numbersign put
+dup 36 /dollar put
+dup 37 /percent put
+dup 38 /ampersand put
+dup 39 /quotesingle put
+dup 40 /parenleft put
+dup 41 /parenright put
+dup 42 /asterisk put
+dup 43 /plus put
+dup 44 /comma put
+dup 45 /hyphen put
+dup 46 /period put
+dup 47 /slash put
+dup 48 /zero put
+dup 49 /one put
+dup 50 /two put
+dup 51 /three put
+dup 52 /four put
+dup 53 /five put
+dup 54 /six put
+dup 55 /seven put
+dup 56 /eight put
+dup 57 /nine put
+dup 58 /colon put
+dup 59 /semicolon put
+dup 60 /less put
+dup 61 /equal put
+dup 62 /greater put
+dup 63 /question put
+dup 64 /at put
+dup 65 /A put
+dup 66 /B put
+dup 67 /C put
+dup 68 /D put
+dup 69 /E put
+dup 70 /F put
+dup 71 /G put
+dup 72 /H put
+dup 73 /I put
+dup 74 /J put
+dup 75 /K put
+dup 76 /L put
+dup 77 /M put
+dup 78 /N put
+dup 79 /O put
+dup 80 /P put
+dup 81 /Q put
+dup 82 /R put
+dup 83 /S put
+dup 84 /T put
+dup 85 /U put
+dup 86 /V put
+dup 87 /W put
+dup 88 /X put
+dup 89 /Y put
+dup 90 /Z put
+dup 91 /bracketleft put
+dup 92 /backslash put
+dup 93 /bracketright put
+dup 94 /asciicircum put
+dup 95 /underscore put
+dup 96 /grave put
+dup 97 /a put
+dup 98 /b put
+dup 99 /c put
+dup 100 /d put
+dup 101 /e put
+dup 102 /f put
+dup 103 /g put
+dup 104 /h put
+dup 105 /i put
+dup 106 /j put
+dup 107 /k put
+dup 108 /l put
+dup 109 /m put
+dup 110 /n put
+dup 111 /o put
+dup 112 /p put
+dup 113 /q put
+dup 114 /r put
+dup 115 /s put
+dup 116 /t put
+dup 117 /u put
+dup 118 /v put
+dup 119 /w put
+dup 120 /x put
+dup 121 /y put
+dup 122 /z put
+dup 123 /braceleft put
+dup 124 /bar put
+dup 125 /braceright put
+dup 126 /asciitilde put
+dup 128 /Adieresis put
+dup 129 /Aring put
+dup 130 /Ccedilla put
+dup 131 /Eacute put
+dup 132 /Ntilde put
+dup 133 /Odieresis put
+dup 134 /Udieresis put
+dup 135 /aacute put
+dup 136 /agrave put
+dup 137 /acircumflex put
+dup 138 /adieresis put
+dup 139 /atilde put
+dup 140 /aring put
+dup 141 /ccedilla put
+dup 142 /eacute put
+dup 143 /egrave put
+dup 144 /ecircumflex put
+dup 145 /edieresis put
+dup 146 /iacute put
+dup 147 /igrave put
+dup 148 /icircumflex put
+dup 149 /idieresis put
+dup 150 /ntilde put
+dup 151 /oacute put
+dup 152 /ograve put
+dup 153 /ocircumflex put
+dup 154 /odieresis put
+dup 155 /otilde put
+dup 156 /uacute put
+dup 157 /ugrave put
+dup 158 /ucircumflex put
+dup 159 /udieresis put
+dup 160 /dagger put
+dup 161 /degree put
+dup 162 /cent put
+dup 163 /sterling put
+dup 164 /section put
+dup 165 /bullet put
+dup 166 /paragraph put
+dup 167 /germandbls put
+dup 168 /registered put
+dup 169 /copyright put
+dup 170 /trademark put
+dup 171 /acute put
+dup 172 /dieresis put
+dup 173 /notequal put
+dup 174 /AE put
+dup 175 /Oslash put
+dup 176 /infinity put
+dup 177 /plusminus put
+dup 178 /lessequal put
+dup 179 /greaterequal put
+dup 180 /yen put
+dup 181 /mu put
+dup 182 /partialdiff put
+dup 183 /summation put
+dup 184 /product put
+dup 185 /pi put
+dup 186 /integral put
+dup 187 /ordfeminine put
+dup 188 /ordmasculine put
+dup 189 /Omega put
+dup 190 /ae put
+dup 191 /oslash put
+dup 192 /questiondown put
+dup 193 /exclamdown put
+dup 194 /logicalnot put
+dup 195 /radical put
+dup 196 /florin put
+dup 197 /approxequal put
+dup 198 /Delta put
+dup 199 /guillemotleft put
+dup 200 /guillemotright put
+dup 201 /ellipsis put
+dup 202 /nobreakspace put
+dup 203 /Agrave put
+dup 204 /Atilde put
+dup 205 /Otilde put
+dup 206 /OE put
+dup 207 /oe put
+dup 208 /endash put
+dup 209 /emdash put
+dup 210 /quotedblleft put
+dup 211 /quotedblright put
+dup 212 /quoteleft put
+dup 213 /quoteright put
+dup 214 /divide put
+dup 215 /lozenge put
+dup 216 /ydieresis put
+dup 217 /Ydieresis put
+dup 218 /fraction put
+dup 219 /currency put
+dup 220 /guilsinglleft put
+dup 221 /guilsinglright put
+dup 222 /fi put
+dup 223 /fl put
+dup 224 /daggerdbl put
+dup 225 /periodcentered put
+dup 226 /quotesinglbase put
+dup 227 /quotedblbase put
+dup 228 /perthousand put
+dup 229 /Acircumflex put
+dup 230 /Ecircumflex put
+dup 231 /Aacute put
+dup 232 /Edieresis put
+dup 233 /Egrave put
+dup 234 /Iacute put
+dup 235 /Icircumflex put
+dup 236 /Idieresis put
+dup 237 /Igrave put
+dup 238 /Oacute put
+dup 239 /Ocircumflex put
+dup 240 /apple put
+dup 241 /Ograve put
+dup 242 /Uacute put
+dup 243 /Ucircumflex put
+dup 244 /Ugrave put
+dup 245 /dotlessi put
+dup 246 /circumflex put
+dup 247 /tilde put
+dup 248 /macron put
+dup 249 /breve put
+dup 250 /dotaccent put
+dup 251 /ring put
+dup 252 /cedilla put
+dup 253 /hungarumlaut put
+dup 254 /ogonek put
+dup 255 /caron put
+readonly def
+/PaintType 0 def
+/fcheckload{{pop}{save 3 dict begin/mystring 2050 string def exch/endstring exch def{currentfile mystring readline not{stop}if endstring eq{exit}if}loop end restore}ifelse}bind def
+userdict/type42known known not{/type42known systemdict/resourcestatus known{42/FontType resourcestatus{pop pop true}{false}ifelse}{false}ifelse def}if
+/truedictknown userdict/TrueDict known{TrueDict dup /initer known 1 index /render known 2 index /imagemaskwrapper known 4 -1 roll /bander known and and and}{false}ifelse def
+%beginsfnt
+truedictknown type42known or( %endsfnt)exch fcheckload
+/FontMatrix [1 0 0 1 0 0] def
+/FontBBox[2048 -349 1 index div -475 2 index div 2050 3 index div 2016 5 -1 roll div]cvx def
+/FontType type42known{42}{3}ifelse def
+systemdict/product 2 copy known{get dup(LaserWriter IIf)eq exch(LaserWriter IIg)eq or version(2010.113)eq and not}{pop pop true}ifelse{/UniqueID 16#00B018F1 def}if/sfnts[<
+
+00010000000900090009000963767420664128BC0000009C000003786670676D3E898A130000041400000329676C7966C98307AC0000074000009DA268656164ABA250870000A4E400000036686865610CD105D80000A51C00000024686D74787E0548D20000A540000004086C6F63610055C78A0000A9480000040C6D6178700945034A0000AD5400000020707265706551528F0000AD74000003BB05C0001105C2002D0597001D0442001D0000FFDA0000FFDB0000FFDAFE53FFEF05D0000AFFFDFFED03340000012200000122DFFB011400AF000700B7007E000400D200AA0109002300ED013200D9011D012A00D800FE00DB00E2001A008B00A0001A004500E801F6000900E90128013200360082009E009FFF700070003F003F00E801050015003800E9FF7BFFC8FFF90042008A00C401070113011DFFB9002F00870087009A009C010C0262FFB10018004C00770080008200C900DAFFB2FFEA001A003600E50111012F043BFFDD00020005001A0039008900AA00B701210123012A015BFFE5000200180023005C00AAFF4DFF76FFB2FFEF001A002F004E007B008A00E1011F0126012B019A01DE03EDFF80FF8E0007001C004E005500630063006D00810098009C00AD011F01260162041C051500390044004B0063008E00CC00E800F2010001290142017802D503EA03F0043B049AFFC400050055005C0060009F0103011D012401550164017001AD01B401C301F602370261033903D5047004A100020055008800A100BD00C700D300DD00EB00ED00FA00FD0104012B013E014F017B019D01AD01E20233025D027D028C02DA02EF033103DE0407048B058505BBFF04FFD5FFFA0007001E002A003B004700510058006500650066006E0075007F00840107009700B100C300CC00DF00DF010A0110012F013101470154015B016B0179009101A401BA01DC01E401E601E901F60213021F0223022F0276027D0282028902AD02B202B902ED03110374037D03C003DE03F60415045D04C004C004DF052D0574061C064B0751FE94FEDFFF2DFF90FF9AFFEA0016001600240029002D003E0104006D006D008400870089008E009C00A400AB00AE00B200B2FFFB013900C400D100DF00E100EF00F70121011C011C012101320138015001510154016C016D017F019801A401AA01B601BA01BB01BB00D701D701FB01FB01FE00190209022D025B026102790279029A009802D302DA02EF030C03210328032D034B0353FFF103AD03B103F20425045A0471047B048A0498049F051C053D0557055A0570059505B605CB05D605EF05F4061D068706A406B406D307080734079807FE012201320120012500B400BE0082009603700132012400430184011D015600CC010500ED00C500FB00F900C000A7011D00FE035500880026FFA100B8FF8800DD00BD00B5
+
+037C003C00910293024AFF3F03A803090132FFF7402A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A090807060504030201002C4523466020B02660B004262348482D2C452346236120B02661B004262348482D2C45234660B0206120B04660B004262348482D2C4523462361B0206020B02661B02061B004262348482D2C45234660B0406120B06660B004262348482D2C4523462361B0406020B02661B04061B004262348482D2C0110203C003C2D2C20452320B0CD442320B8015A51582320B08D44235920B0ED51582320B04D44235920B09051582320B00D44235921212D2C20204518684420B001602045B04676688A4560442D2C01B9400000000A2D2C00B9000040000B2D2C2045B00043617D6818B0004360442D2C45B01A234445B01923442D2C2045B00325456164B050515845441B2121592D2CB00143632362B0002342B00F2B2D2C2045B0004360442D2C20B0032552582359212D2C69B04061B0008B0C6423648BB8400062600C642364615C58B0036159B002602D2C45B0112BB0172344B0177AE5182D2C45B0112BB01723442D2C45B0112BB017458CB0172344B0177AE5182D2CB002254661658A46B040608B482D2CB0022546608A46B040618C482D2C4B53205C58B002855958B00185592D2C20B0032545B019234445B01A23444565234520B00325606A20B009234223688A6A606120B0005058B21A401A4523604459B0005258B219401945236044592D2CB9187E3B210B2D2CB92D412D410B2D2CB93B21187E0B2D2CB93B21E7830B2D2CB92D41D2C00B2D2CB9187EC4E00B2D2C4B525845441B2121592D2C0120B003252349B04060B0206320B000525823B002253823B002256538008A63381B212121212159012D2C456920B00943B0022660B00325B005254961B0805358B21940194523616844B21A401A4523606A44B209191A45652345604259B00943608A103A2D2C01B005251023208AF500B0016023EDEC2D2C01B005251023208AF500B0016123EDEC2D2C01B0062510F500EDEC2D2C20B001600110203C003C2D2C20B001610110203C003C2D2C764520B003254523616818236860442D2C7645B00325452361682318456860442D2C7645B0032545616823452361442D0000000002009A0000053D05C200030007003E402105061D02010004071D03000A05041D0303021A0906071D0100190809AA216C3C182B2B4EF43C4DFD3C4E10F63C4D10FD3C003F3CFD3C3F3CFD3C313033112111271121119A04A3B8FCCD05C2FA3EB80452FBAE00000200E10000021A05BD00050009004340220205000004590728090A0B17171A0870091C0003040304017000190A0B7021813C182B2B4EF44DE539397D2F7C2F1810F4F54E456544E6004D3FFDEE3F3939313013211103230313
+
+211121E1013951955307012AFED605BDFE8AFD5002B0FCDAFEDF00020017036102A305C200030007003A401E0206BC0304000917171A00230194022303070423059406230719086C3C182B4E10F44DF4FDF410DCF4FDF44E456544E6003F3C4DFD3C3130010323032303230302A32FB42E6A30B42D05C2FD9F0261FD9F026100000200000000047105970003001F01A040EC0A0D080F0A1009170A180B19091A3909390C4A094A0C58005A0D5A1058145918591969186919790F9714991EAC0AAD0BA80FA710A218A219BB0ABB0BB90FB618B619C90EDA00D80FD81AEA0DEA0FE714E71CF90FF71C2B0901090B0913180117101813290E2618291E57199514A6140C8A018A1A02121516161104071F1F08000415190E010712190E0207121C0B0304151C0B0504151D0A0607121D0A0908111D0A0C08111C0B0D0811190E100811180F130712180F140415180F171F16180F1A1F16190E1B1F161C0B1E1F161D0A16151208070406111F0906051E041D0D01001A04190C02031B040B1C1CB801A5400E121D1D0A1013141704180F0F1818B801A540151219190E1D1C19180F0E0B0A08111F0E0A040C0811B801A6B7020712B916030415B801A640161B1F1685191C1D03180A2117171A11BF1F1F206747182B103C10FD4E456544E64D003F173CF43C3CFD3C3C10F43C3CFD3C3C3F3C0111121739872E2B7D10C507173C872E182B7D10C5173C10173C10173C01111217390F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F87103C3C87103C3C31300172715D0113230321331323373313330333133303330723033307230323132303231323026351A64EFE6DCB4FCC2DCC6DC76DA66AC76AC92DC951CC2DCC6BC76BA46DC76DCB02380124FEDC0124A80193FE6D0193FE6DA8FEDCA8FE700190FE7001900000030038FF13042F063400080010003D007C40433F043F054F044F05780BAB02AF03AF04AF05098A2D992D02351D100804183034092B280518CC001C3D12130D2A353408000511291D1C10090512123917302F04393F0CB80132B52118173F473E4E1076C418D64DCDD4FD4E10DCCDD4CD1112392F173CDD173C003FC4C4DDD4E43FC4DDC4C4111739313001715D253637363534272627030E01151417161713233526272613211617161711272E01353436373637363735331516171617212627262711161716151407060702684F243F3B23545F57543F23496161C561AB03010E0E19277251BF9D3D37475735665FA35DA906FEF908162664EE5287B9719BBB0A1A2E7156321D1F028E02594D54311B17FBA2C716407301157E2B431401AB1838C88D5D9837471B110885870D436BF059294707FE83523F69BFFC72460C000005002FFFDA06E305AA000B00170023002F00330102406ADF05D00BDB0CDB10D412D416DF1AD020DB24DB28D52AD52E
+
+0C580054015B03580458065B075409570A5B185819581B5B1C541E571F58215422104401440244034418442244235401540254035418542254230CDF02D805D008D81AD01DDF23D92B075B005B2102313232B801AA405812333330323302083130231D2C201ACF2020261C3233090E200BCF0520141C3130002F1D3F1D4F1D4F234F295F1D5F235F290829201DCF30230123202F352F0830024017501704172002CF301101082011193547347D46182B1076CC4EF44DFD5DF6FD5D10DEFD5DF6FD5D003F3CF4FDF6FD3F3CF4FDF6FD011112393911123939872E3D2B7D10C531300172715D0072710036353426232206151416332406232226353436333216150026232206151416333236351606232226353436333216150133012301E55D5D42425D5D420174D99B9ADADA9A9ADA02F75D42425D5D42425DD5DA9A9ADADA9A9ADAFDED98FCD89B03905D42425D5D42425D05DADA9A9ADADA9AFD6A5D5D42425D5D429ADADA9A9BD9DA9A0453FA30000003006FFFDC059C05BD00220031003B019D41A00009001B005B001B00550021006700210076002100C5001000CD001800070076002600010006000B000B0007002F0031003F003100590037009000170096001800CA001000CD001100C6001800E8003700F90037000C00090037001900370025001100260017008B0033009800330006001B001A0037001A0038001B001A001A0003000F001B0010001A001800190026002600190003003B00260031001B000C002A0018001A00140013001B001A0018003400030026002D00140010000F001A000F00220012003800380037001B0038003100370010000F0003000C002A00380037001000030034000F002D001400DB001F002D002000090000001A000A00340032001F000B001300540014001C0015003D0019000C0032002A01100019001A003D003100540006008D003B006E00220019003C003D012100210090004600182B2B4EF44DFDFDED4E10F64DFDED10F4F4ED003FED3F3FED10ED1139111739011112173912392B872E2B2B7D10C500111239391239113901111239391112391239113987102BC42B3C2B3C87102B3C2B3C2B3C313001715D00715D12363F012E0135343633321615140607133E0137330607060701212706070623220235001716173637363534262322070615021633323637010E01156F84961F4046D8AC9DCD7B77D1242701FD063A2048010CFEA6664A407295E0FC01B91C123C3C1A323C3D2621329D775D467D27FEF26B45020ABE5D13489651A1B5B99082A245FEFE347A4486894D5DFEBE7D45213B0108A102C42C1D4A2A1D363F2E48151F43FCD47A4128014E476C4100000100630361017405C20003002C401702BC03000517171A00230194022303190405CD219089182B2B4EF44DF4FDF44E456544E6
+
+003F4DED313001032303017432AD3205C2FD9F0261000001005DFE63026505DA0013004640292703261077027710870287100604110F131419130E0F0405136E09FA2F059F0502051A151415D52142B901AC00182B2B104EF64D71FCFD1139393910E4003F3F3130015D1213363F0117060706111417161F0123262726355D82485347A48B325320317E3DA9A255640333012CA6736202FE93F6FED0C4A5FDE870DED7FAFD0000010015FE63024D05DA001300344018121109131517171A120D081309036E0DFA09191415D52142B901AC00182B2BF4F4FD11393912394E456544E64D003F3F3130001712111003060F0123363712113427262F013301894F758B4E4547D384345920317E3DD70506B8FEF2FEEEFED3FEC9AE5861EE9801010132C4A6FDE7700001002F032502DC05CB000E00D940896B006B056B066B0E7A007A057A067A0E8109850A810B960AA50AB90AC90AD906D90E11470A540A020100002F120E0E0D000E0A0B0A090B2F120C0C0D0B0C0A090A0B092F12080807080905040506042F12070706060E0705000401A10210080C090B0D07060D0C0B0004010E090807050406041006040A0A50046004029004A00402040E010F7D46182B10D4C4DD5D713D392F1810C4C41112173911121739003F3CDD3CDD3C3FED3C39391139390104872E2B087D10C51808872E2B087D10C51808872E2B087D10C51808872E2B047D10C5313000715D1317353315371707170727072737275ED1ADD12FD58B808B8F808CD5051E44F1F1449542C75BBCBC5BC7420001004900000484043B000B003A401D0700220601010A03060A0A0D17171A0685040922030A8500190C6A46182B4E10F44DF43CFD3CF44E456544E6003F3F12392F3C4DFD3C313013112111211121112111211149019A0107019AFE66FEF9019C0105019AFE66FEFBFE64019C0000010076FEA501AA012A000D003B401F00EE0A08040D710528040A0F17171A090A035A06700004190E0F70217F3C182B2B4EF43C4DFDED39394E456544E64D003FEDF4113939ED3130173E0137231121111406070E012376565106AD01342431358F1BED187065012AFEFE4494363A3B0001002F01B4026D02C2000300214012002203011A05DF000100190405D5217D46182B2B4EE45D10E64D002FED3130132111212F023EFDC202C2FEF200010080000001AF012A0003002640130128030A0517171A01700019040570217F3C182B2B4EF44DFD4E456544E6003F4DED31301321112180012FFED1012AFED6000001FF90000002B805EF000300594030390139027700760187019702A800B702C702D701F7010B0102025D120303000002010301000302030A011A0503190405BA016D00210129B1F0182B2B194EE410F618003F3C3F3C4D0111123939872E2B7D10C53130015D0133012301
+
+CBEDFDC3EB05EFFA110000020040FFDC042805B4000B00170075405917012707D70F03380D370F371338154B0D440F44134F159815B713BA15C613CA150D1700530676007606040606A606C80F03084017050240110D05830E0B830EA71014301402701480149014A014B014D014F01407141947184E1076C418D45D71E44DED10ED003FED3FED31300072715D01720012333212351026232206110012111002212002111012210163527F7F4F4F7F7F5201E6DFDFFEEBFEEBDFDF011501CDFEF70109FA0106FCFCFEFA02EDFE7AFE99FE99FE7C01840167016701860001008E0000030705AA000D0032401E29053905020D01CC09040C0C0BB3000938200C300C600CB00C040C0F470E1076C418D45DE4CCED003F3FF4CD3130005D13353637363736373635331121118E8736563625130BEDFEDC03E8C2060C133927412713FA5603E8000100400000042105B1002100884061071401041B071C6F1203041D19011618660160046206671A97019502981AA6010B001910193419351C041C190402041E0F0A4013051EA1210C1E1C04030E07B316731F01020E630F7C1FA7102101702180219021A021B021D021F02107212347224E1076C418D45D71E44DF4ED393910F4ED111739003FFD3FEDDD111739015D31305D71007136373637363736353426232207060721363736213204151407060F010E0107211521443F3DE3C53A59665F822F1B05FEEB073C720123E60110603F90726B4F1B0279FC1F9C8191A28D3D5F715C7A61387AB972D9FFD2A17D5366514C442DFB0000010036FFDC042105B100300076B609200198220130B80108403C2C171E25250BF66F0CDF0C020C0C2C13401E0504402C0D252507106F210783290C8C1663177C006329A71030303002A030B030D030F03004303247314E1076C418D45D71E44DEDF4FDE610EDD4ED12392F003FED3FED12392F5DFD393D2F1810CD10ED3130005D0171011417163332363534272623353637363534262322061721363736373E0133321615140706073217161514022320272627014E1C3489547D74428E8B375F6158655F02FEF60421234B389A70D0FF4C303427496DFFFAFECC783F0701BD573969736C8F301BCC02192A805368806B6C6155483336D7B5805837144365AFB8FEE9C96BAD00000200360000042F05A1000A000D008F40450E0C480C480D8F0CDC0C051F0C0158077A0789079907A80705050D460D830DD60D04110D01040500030C090D0A01080B0D0A030C0C0D0DF512060607060C07040A0DF70005B8014C4009030C0D07050C03B30ABB013A0001000901A9B3060F470E4E1076C4184DD4F43CE4FD3C113939003FF43CFD3C3F393901872E2B047D10C50F0F0F31300172715D0072710123112111213501211133211101042FA4FEE9FDC202150140A4FE45FE9501
+
+38FEC80138F90370FC760272FD8E00010036FFDA042105970020005E40160E0F0FA1121212130D0EC213094017171D12A10F0420B80155401903401D0D113813120D0006831A0FC3006F0E381AA720224721104E76C418D4E44DE4FDED10ED11393939E4003FEDED3FED12392FFD39F4C401872E2B7D10C53130011E01333236353426232207060725132115210336373633320415140021222427015211605C6A6F686E34264322FF0066031FFDAF3442253E59B4010CFEFEFEFFCFFEF60F01845D6595716F990D18410C0321F2FEC32B0E17F2E7C9FEC4DECC00020040FFDA042A05B8000C002C007540494C0D4C2C5C0D5C2C0437265713022C110A0215084018181E27114029052002401E0D0A0C0D6F2C7C056F1B15E40C6F1BA71022302202702280229022A022B022D022F02207222E472D4E1076C4184DD45D714EE44DFDE510EDF4ED1139003FED393FED3912392FED39113910CD3130015D005D001633323635342623220706150134272623220706073E013332121514022320272611343736373E0133321617015E7E615F6D7C5A49385401911B2E5D8B3B200C358C5AC1F7F2FFFEEE82650E19483EC98CCAF00F0156948F727F872C41910272232A449C56A83F3AFEFACCCBFECAE5B3011BA668B97B6980CFAC00010034000004380597000E003E402416021503F70503000CA10D04070C0B00068307C60D7300A8100C300C02D00C010C10470F4E1076C418D45D71E44DF4F4ED1139003F3FFD393130015D010602070602152112131237211321043840E44D3D62FED80DF39D6AFD2D04040004B83FFEBDAC87FE7A7D018601A5010567010000030036FFDA042505B1000B0023002F00624016681F011A0E0E082626202C4014050240200D1A176329B8015FB605831D0E11632FB8015F40160B831DA81023302302A023B023D023F02304233147304E1076C418D45D71E44DFDF4ED3910FDF4ED39003FED3FED12392FCD392EC4313001015D0016333236353426232206152436372E01353436333216151406071E0115140023220235001633323635342623220615015E6F62626F71606071FED86F6B693FEED9D9EE3F696B6CFEF1F3F3FA01426156575F5F575661013A76766B6F73736F67C63246A3479EDFDF9E47A33C3CC67AB7FEFF0101B7023364644F56616156000002003DFFD6042D05B6001C002A005A40361E231519402A2A0A234002050E11400A0D1E0E15E42083060E6F0D7C276F06A8101C301C02801C901CA01CB01CD01CF01C061C2C472B4E1076C418D45D71E44DEDF4ED4D10FDE51239003FFDC53FED12392FED39123931301200332013161110070221222427211E0133323736370607062322243504373635342623220706151416333D010DD7014B7B464380FEAAA3FEFC13011C0A58498D391F08272C5075
+
+ADFEF4023234617364493452696D04950121FEDBA6FEF1FEF9B0FEB1C1B940509C56A5311A30EFE1E8223E997B90294099818100000200E8000002170417000300070033B2012803B8011540150528070A0917171A05017004001908097021813C182B2B4EF43C4DFD3C4E456544E6003F4DEDF6ED31301321112111211121E8012FFED1012FFED10417FED6FE3DFED6000200E8FEA5021C041700030012004FB7070F170F02012803B8011540210B280904EE0D1271090A1417171A0106090E085A0B701200091913147021813C182B2B4EF43C3C4DFDE4391139C44E456544E6003F4DF439ED10EDFEED3130015D132111211136373637231121111406070E0123E8012FFED165281907AD0134243133901C0417FED6FC261D4A2E58012AFEFE459336393C00010017FFDE04B1045E000600634034030403020422120505060302030402221201010003000504020301040605000201BB060403BB050B011A0800190708AA216747182B2B4EE410E619003F184DFD3939FD39391139390111173C123904872E2B087D10C504872E182B087D10C531301301110901110117049AFCB70349FB66029E01C0FEE9FED7FED6FEEA01C0000002004900B10484038B00030007002C4018032202072206070204900001001A090219080965216A46182B2B4EE410F65D4D3C103C002FFDDEFD313001112111011121110484FBC5043BFBC5038BFEF90107FE2DFEF9010700010017FFDE04B1045E0006006B40394806010304030204221205050603020304022212010100050403010402060800000201040605BB000203BB010B001A0802190708AA216747182B2B4EE410E619003F184DFD3939FD39391139390111123912173904872E2B087D10C504872E182B087D10C53130005D0901110901110104B1FB66034AFCB6049A019EFE400116012A01290117FE3E0002007B0000047105D1000300230056402A1916100D0E0F0623142E0128030A0523861F24070113141314027003030A231CFC0A1A25226E23192425B8011BB3217F89182B2B4EF44DED4E10F64DED1112392FED39392F2F003FEDED393FFDE611173931300001211121003736333204151407060F0106070607213E013F01363736353426232206152101E8012AFED6FE9FBB76ACE2012B41266C473A130C01FEF206346C4924162859767461FEDF0121FEDF050E774CD8D482593654372D3C2650A98154391B2037424C7D9A53000200C7FFD7071205F1000B004F00E84057252B352B48095A2B56386A09782B892C080913151617412A13370938174A1048174839592A533C692B7840863C8A40980F96179622953C9A40BA101528170132333233452D154B021E3B457F3E013E3B25710216113B02B80113B4083B4F1C45B8015240327F2D012D3B360B4B4815160B17321B3342210A0516
+
+171817481817211B05200E1B0E3A702101213B427F2901293B3A195051B80124B321C578182B2B4EF44DED71DDED711239392FED2F123939DD2E87DD0312391112391239391139391239003FED71F4F4EDF4FC3DC41810F4ED7110ED1139391112393910C9313001715D005D002623220215141633321235002635341233321716173733030E01151416333236351027262320070611101716213237363F01170604232003261110373621201716111400232226353436370607062304A340366896433D6B89FE53A1F6B3693A2C0F24BD800F0D282C56ADEC94B9FEACCEBADAC10116BEA55A6018498EFEB5B2FE61E4BDECF80183013BCFDAFEECB15C630101262F557703C148FEFD79495A01455DFDCBAE9CB5013C3A2D3A7EFE4E3533131E35E1BA0113784CD0BCFEF9FEDCAB9746254411706E730102D601250148E4F1A5AEFEE0E3FEBB683707110A482B4D00030034000005A805C20002000A000B00DC406B6802012705280A380637094806680A780A880488069A0395049806AA03A504A806B801B80AC801C80AD803D80A150107060602000809090200080A01070502140A0A2512090902140505251206060207082A010000020A0B04030206090A0305080B0D17171A0B0A040605B80114B2090302B80114B60A190C657572182B764E10F4184DFD3939FD39391139194E456544E6182F003F173C4D3F3C3C1239392F3CFD3C05872E2B7D104B5158B004C01BB004C459872E182B7D104B5158B003C01BB003C4591112393912393987103C3C07103C3C3130015D005D01210B012101210321032101022F0176B8AB015C020AFEB25FFDE166FEBE02BA022D02440151FA3E012FFED105C2000300A10000056105C20009001400290059402CA904A707A7120377168716021C0A2A010127002A28020B2A27081C100536184F10371F1A2B000B2527192A2BBC011E00210052012A00182B2B4EF44DFD3C4E10F64DEDF4ED1239003FED3FFD12392FFD393130015D005D01112132363534272623011121323736353427262700171615140706071E0115140706070E012321112101C7016A617950456BFEBC016A6136625F35600146714444264A7173422A3F47C171FD6402CC04C2FEBB495D672117FDC7FE771A3088732B18010335995E8387522E2629B27F8368452F362805C2000002005CFFD7057B05EF001E001F00744029570A94079408035B02591B581D660477018905A914B204B70AC604C70BDA02DB14DD18DF1BF8181017B8010B40231A08081A0C411F030312411A091F16371708371F1E071A210F371E1920219921AD56182B2B4EF44DED4E10F64D1139EDD4ED2F003FED3F3CED12392F10ED3130015D005D12373621201716172126272623220215141633323736372106002120272611015CCFB401160174AC5F07FECC1E2F
+
+54A5A8C2CD9EA2552F1F013128FEB7FEFFFEC2B6B602900457D1B6F4898A6A3660FEF1F8F8F76A3972F1FED2CCCD0165031A0002009C0000057B05C2000900170053403277120107082707270C58126A127B048C038A048A12980398049812AD030D022A15092A160215080637101A19012515191819B80120B3215256182B2B4EF44DFD4E10F64DED003F3FED10ED3130015D005D01112132373635342623361716171612151007022901112101C7011CDA562F8DD2BD5B9B604D3876A0FEB2FD85027B04C2FC3ED776A3E1F1FE1E33886EFF0074FEDACCFEED05C2000200A50000050205C2000B000C0054402C24032404330333044303430406052A02020901410C0A02064109080C049C0C090B4F071A0E01062509190D0EB8011DB3215256182B2B4EF44DFD3C4E10F64DF41239E42F003FFD3F3CFD12392FFD3130015D0121112111211121112111290104DEFCF402CCFD340330FBA30439FDEB04BDFEC7FF00FE85FEF705C2000001009C000004B105C0000900374017072A040409032A000209080676011A0B03082509190A0BB8011CB32152AB182B2B4EF44DFD3C4E10F64DE4003F3FFD12392FFD3130132111211121112111219C0415FD1D0287FD79FECE05C0FEFDFEADFF00FD9600020055FFD905AF05E8002200230085404BC808DB08FA1AF921042902282139134B1859159821C619C21DF80909130A1222D41F0E2A0F0F120441231F0312080A41170923131213120D0322000037231B22AC0F101A2507371B192425B8017FB321AD79182B2B4EF44DED4E10F64DCDF41139ED111217392F3D2F182F003FED3F3F3CED12392FFD10ED11123D2F183130015D005D012627262322021110163332363721352111232706070623202726111037362120001701047B23884C5DB2E5F89E9BC617FEAB0266CC1F59477AB2FEDBBBC3C5C501440119015519FD7803F6973C21FEF3FEF2FEF0E2B391F6FCE9B8692B4BCBCC01620166D8D8FEE3D501F2000001009A0000053D05C2000B0035401C0A2A03030502020B0808050825071A0D020B2500190C0DC0215279182B2B4EF44DFD3C4E10F64DFD3C003F3C3F3C392FFD31303311211121112111211121119A013102400132FECEFDC005C2FDCE0232FA3E0292FD6E00020084000001B605DF00030004003040110402020108040617171A04002501190506BA014B00210135B179182B2B4EF44DFD394E456544E62F003F3F3C3130290111212701B6FECE01329905C21D000001002DFFDC03DE05C200130032401413130F090204410F0908370B1A15013612191415B80173B3217579182B2B4EF44DED4E10F64DED003FED3F12392F313001151E0133323736351121111407062120021135015004436E6D23150134416EFEE1FEE1C4022F22AB8B4C2D6B0407FBFEBC6EBA012D01042200
+
+000100A1000005B605C2000B00AC4067D00201580679038A069A03F906051903D0050218033704360548034704470559038B0308050506080807090203022803034C12040409080702280809072512060506080705040305090609080502040A040301020A070608061A0D02092500190C0D99215272182B2B4EF44DFD3C194E10E618003F3C3C3F3C3C121739011112173905074D2E2B087D4B52787A10C407052E182B10047D4B52787A10C410083C08C431300171725D0072132111012109012101071121A1012F0239018EFDA4027BFE74FE3993FED105C2FDA1025FFDA1FC9D028497FE13000001009C000004AA05C200050029400F000202410508031A07022500190607B8011CB32152AB182B2B4EF44DFD4E10E6003F4DFD3F31301321112111219C013402DAFBF205C2FB47FEF7000100970000062805C2001200C04090090007080809051116081909290027082B0924112A12370735083C0938126A00651179007511890086119A009611A800A611C700F708F8091C05080A09160818090407121A071A0A1712220023112F123D073F0A3F127A12B909B612C7120E0F070F0A020A0F1211090800050E070203120A07030E1100020E0803081417171A0204032702120F0D0E270F19135279182B4E10F44DFD3C1910DCDC18FD3C104E456544E6003F3C3C3F3C121739011112391217391139313000715D01715D01211121113436350121011416151121112101046D01BBFEE102FEE9FED5FEEB02FEE101C0010C05C2FA3E03E52B9B2AFB2B04D52A9B2BFC1B05C2FB7900000200970000054405C50009000A0057402F080257020202060701072A120101020207080A0301020806080A0A0106080227051A0C07082709190B0CC0215279182B2B4EF44DFD3C4E10F64DFD113939392F003F3C3F3C3C12393904872E2B10877DC43130005D1321011121112101112101970143024B011FFECCFDA6FEE1026205C2FBFB0405FA3E0417FBE905C50000030065FFD705EA05EF000B001B001C00414027160C16121914191A971A0505411C17030B410F091C02371C131B1A1E083713191D1EDF21EB56182B2B4EF44DED4E10F64D1139ED2F003FED3F3CED3130005D241235340223220215141233240706212027261110373621201716110103DFD7D7B7B7DADAB702C2DFA7FEC4FEC4A7E0E0A7013C013CA7DFFD3EDC010EF9F8010FFEF2F9F9FEF27AD3ACACD3018D0195CBACACCBFE6B030C00000200A30000050B05C200080013003E401C97019706020C2A04040E032A0F020E080837131A15030D250E191415B8011DB3215256182B2B4EF44DFD3C4E10F64DED003F3FED12392FED3130015D002623211121323635000423211121112132041503DA796DFEE1011F6D790131FEF8F5FEC7FECE0282DE0108046062FE4E6A73FEFDD8FDEE
+
+05C2E4EF00020065FF9505F105EF0014002B00BE406EB725B829C725C829F81905B60F010619181A191905031B1B1B1A1A041B0603031016182B0A191B1F1816150603050D141905191A05621204041A05040304050604100A181A1B032B231B18191F270304050604140D41270314411F0919AC0A372B1A2D103723192C2DDF21EB56182B2B4EF44DED4E10F64DED19F418003FED3FED111739111239393901111217391112173908872E2B087D10C50011121739123939011112393912173987102B3C2B3C87102B3C2B3C3130005D015D2437363727371736373635340223220211101716330007060717072706070623202726111037362120171611035A311B2A959F95230E16CBC3B7DA9C658D02C530274CAAA1B2513B638AFEE0BCE4EABF011C011EC2E0DC0D07128EA68E4836516CF8010FFEFCFEFDFED183550158857F549FA8A8311421ACCF01910194CFA9B3CFFE8C00000200A30000057105C2000A002A0058402A20231B1815052713262A01011D002A2902271D081D2022130617220637171B57101A2C00272528192B2CB8011EB3215256182B2B4EF44DFD3C4E10F64DE4C4FDC4111239113939003F3C3FED12392FFD39111739313001112132373635342726233616171E01151406071E011D011417161715212627262F012E0123211121112101D0015D68345C593264DBA73A30386A7A6655080C2CFEAD0E060C0102026388FEC2FED302D304C2FE74182A7C862E1AFD464438885769CB2A29979B636524391B25311E3E41898D5EFDBE05C200020055FFDA050E05EF002E002F00A3406A080F07210726190B190F17211726660C650D6922E52D0B29102915281A26273A15381AB915CA15DC15D22CEB13EB16F913FA16F92D0F0E00110B22181F25170825220E0B04182ED42B18D41C412F140304412B092F18962F11174F0896281A311F36115700362E193031B8011EB321AD56182B2B4EF44DEDF4ED4E10F64DEDF41139ED2F003FED3F3CEDED10ED11173901111239111239391112393130015D005D0116171633323736353427262F012627263534002132041721262726232206151417161F011617161514002120003501017B0E294BB66D44814040899CE6589501200117E9014908FED8086C486B778E462D93FEA75584FECBFEE6FEE0FEB6025101C765325B182E7D4928271E23343D66D9C60106F7EB85382560564F271A233D284368C5CAFEF50107E6042800010021000004CB05C200070038400C01062A070204080917171A00B80158B2022505B80158400906190809C0217572182B2B4EF44DF4FDFD4E456544E64D003F3FFD3C3130011121112111211104CBFE47FECAFE4505C2FEFBFB4304BD01050002009CFFDA053D05C2001500160033401B160C0102064111091616150A370D1A18023715191718C021
+
+5279182B2B4EF44DED4E10F64DED12392F003FED3F3C3C313013211114171633323736351121111407062120272635019C01392438BCBB382401394988FE81FE818949025105C2FC7698467C7C4698038AFC76EB83F0F083EB038A000001002F0000053B05C200060077402132040425120506053201012512000600060305040100020302080817171A020001B80111B2030506B80111B6041907657572182B764E10F4184DFD3939FD3939194E456544E618003F3C3F3C3C3C123905874D2E2B7D104B5158B002C01BB002C459872E182B7D104B5158B003C01BB003C45931300121012101210103FB0140FE09FEDDFE0E0149014005C2FA3E05C2FBA10001001E0000076F05C20012016A40F20A040505090C06104A044505480C880487058A0C880D870F8610D904D705DB0CD6101116001A041405190D170F05010202000304040206070705080909070D080E180E0209030A0405050606080B06110712170A170B180C79037904760576067611BA03BA04B405B506C903C904C605C606D903D904D605D606E903E904E605E6061F58035A045505570657116903690466056606680B66110B090C0610190C1610B50BBB11E50BE511F70AF50BF3110B0B0A02190A2512090709111202191225120000020E070203110405090A1205000211100C0B0808090B030A05060C030E070001110312030410030E021417171A0ABE01B80007010100020101000E01B8B612191365E572182B764E10F4184DFDE4E4FD194E456544E64D111217391217391112173912173918003F3C3C3C3F173C12173905872E2B7D4B52787A10C487102B7D4B52787A10C43130015D7171005DC487100EC487100EC487100EC487100EC43130017271011317371321131737132101210B0321010165C32A2BA60145AF2D2DC50139FE61FEDAB23434B2FEE2FE5E05C2FCB4EBE60351FCB4EBE20355FA3E035E011DFEE3FCA205C200000100210000053D05C2000B0103409A58026803970095049C06980A06860085048B06880A860B0523052A0B31053D0B8A0B90059F0BA405AA0BB305BA0BC305CA0BD705E605F705108605890B02D005DF0B02051804050604251203030205180605040625120708070B180A0B000A25120809090B18000B0A0025120102010205080B040007060403020A090100080A0806070402000B050B03070903010D17171A099901190C7572182B194E10F4184DFD194E456544E64D1018C410C41139391239393911393939003F3C3C3C3F3C3C3C1217390110872B08104B51587A59C4181005872B08104B51587A59C4181005872B08104B51587A59C4180587102B08104B51587A59C431300072715D01715D2901090121090121090121010187FE9A01DAFE3D01700107010E0164FE3D01DFFE8AFEE802EF02D3FE2101DFFD39FD0501F600
+
+000200230000054205C20008000900A7404CB900B60702290229054A024A055A025A0566089408A902A905B408C508E308FA080E0B08010518060625120707080218010125120008000502080406070901040002040808090B17171A0001B8015EB5090802250705B8015E400906190A0B99217572182B2B4EF44DF439FD3939F4394E456544E64D2F3D2F18003F3F173C1239393901872E2B047D104B51587A59C51805872E2B047D104B51587A59C5313000715D015D0121011121110121010303E5015DFE13FECCFE02016B01320D05C2FC68FDD6022A0398FD7E028200020034000004AF05C20009000A00714044170629012606380137064B0146065B01580568017805880598010D890186060201050606251200000105012A0A030206002A09080A06010A030305071A0C035700190B0CB80178B32175AB182B2B4EF44DE44E10F6D41117392F003F4DF53C3F3CFD3901872E2B877DC5313001715D13012111211501211121013402F9FD1A0466FCFD0305FB850246010403B90105F7FC39FEFC05C200010080FE76027605D00007004140261F03018F0301039F0010100501800501059F07120917171A0205BA042707190809BA217F46182B2B4EF44DEDFD3C4E456544E64D003FED71723FED7172313013211523113315218001F6E8E8FE0A05D0D0FA47D10001FF90000002B805EF0003004D4024A700B700F800F903040703010302025D1201010000020504030302010A011A0503190405BA016D00210129B1F0182B2B194EE410F618003F3C3F4D0111123939872E2B7D10C5313001715D130123017B023DEDFDC505EFFA1105EF000001002FFE76022505D00007004340271F03018F0301039F0410100101800101019F07120917171A05022705BA0003190809BA217D88182B2B4EF43C4DFDFD4E10456544E64D003FED71723FED7172313017331123352111212FE8E801F6FE0AB905BDCCF8A60001008B024E044B05C2000600814031F700F90602070008061700180604220332034A035A03040304030204351205050603020304023512010100040201030305B8011740150600000817171A00020186040603860519077F89182B194E10F4184DFD3939FD3939194E456544E618003F3C4DFD39173C01872E2B087D10C505872E182B087D10C53130005D01715D0901230B01230102DC016FFBE3E6FC017005C2FC8C0236FDCA037400010000FF000473FF6500030019400D01EC000205000405BF216747182B2B3C103C002FED3130113521150473FF006565000002FFCE045F01CB060000030004003040180228000407040617171A04010300BA02190506BA216778182B2B4EF44DFD3939394E456544E62F003FDE4DED3130012301211301CBCEFED1013D1704D5012BFE5F000003003BFFDE0438045F000E0039003A008F404F
+
+3B0235367901890104D81E0126F3E62AE7230E0D05020005131A2B24232204262E262E2A0D050200041B0B221B162C3A1F072A0A0B2C320B3A134D004D2E3A352A3E261A3C1A4D1B2D084D35193B3CBC01190021004801AE00182B2B4EF44DEDF4ED4E10F64DE41139CDE5E52F003FED3F3F3CFDCD39111217391239390111121739111217392B3130015D005D010E010F01060706151416333236372736373635342623220706072136373621321716151114171E011715212E012706070623222635343736371302DE1B3730405A2742513A5C9B03AD4F223D5D5A652A1E0AFEED0947710113B38B8B02031C1CFECA0D0A033B4D5C7494C19B55A57002121115090C1017275249416C8FEF0A0F1A37433332253F8F5C904747C5FE0C344A38280D2A213A25402D35A99BC95A311501D4000002007BFFE3049C05C0001200200042402509200B0E120C00192412070B0A2024050B1584021A221D1F0A1F0D270B1921229821504E182B2B4EF44DFDF4E44E10F64DED003FED3F3FED3F1139111239313000121514022322272627152111211136373633123635342726232207061514163303A9F3F0D787523139FEE9011C36414D77257A1E39999B3A1E7C7F045AFECAF5FEFEB23620508905C0FDF44C2832FC74B291744C908D4B778CB80000020047FFDA0434045F001D001E006E40459916A81602871C01491558126812780A7912B815C713C81508180206041DD204241E1A07160E0A0C10B70C24140B1E10360F1F00361E171D1A20083617191F208721484E182B2B4EF44DED4E10F64D1139FDF4ED2F003FEDED113939393F3CEDED113939393130015D71005D0126272623220706151417163332363721060706212002351000333204170103100821306590351C1C338D64540901230A5486FEF9FEF9F80112F1CD010518FE1B02BB3D31428F4C7E7849886C568274BB0138F901190138B8E901A40002003FFFDE046505C00010001D004F402CE80C010706151D0210030017241007060A1D240A0B15031A131F061F0327041A1F1A360D191E1F98214845182B2B4EF44DED4E10F64DFDF4E4111239003FED3F3FED3F1139113912393130005D00161711211121350E012322003510003312363534272623220615141633027A9A300121FEEB3D9C74BFFEFB0101D7B77E653E527D757779045C574D0208FA409761580135F201170140FC72B48FC85634BD8C97B50003002FFFDC043A045F00060021002200AB4049460887149701990A04060109050610051A4B05461049208601850F871F0A031603171316131748084C164C17491A5C165C175A1ADC01DB04E91DE720F720104A014610880583100402B8019540334F0E5F0E6F0E030E0E1B062422210717122C1B0B160302220336177B221E600C800C020C1A24021F0E951E1923249821
+
+484E182B2B4EF44DFDE44E10F65D4D1139E4ED2F111239003FEDCD3F3CED12392F5DFD313000715D01715D000607212E012336161716171607211617163332373637210607062322001110003B0101D06D0E01BB077B5B88DA4740130B02FD1606613B5358371E1701230B5A8CFCD0FEC2011FE51403747C6A7175EB666E61804B8DA44229321B3061649F010C012E011B012E00000100150000028B05D100170081412F00150003002C0002001F004F0004005F000400020004002C00170001000B0010005C001200090006000E000A001900170017001A000A001F0003000D0015001600090027000E001F001300920010001900180019010E00210060006600182B2B4EF44DF4E4FD39393CD4F44E456544E6003F3F3C4DFD3C3FED5DF4ED393130001617152E0106151415331523112111233533353437363302322C2618712BBBBBFEE49F9C3B3EED05D10303E803033520203CC9FC91036FC946AF426200030042FE42045E045F000D002F0030005A40108A1E0111120524302F071206250D2429B8013F40201C202C180F30021F121F2527302C131A321C841B2D09362C19313298214845182B2B4EF44DEDF4ED4E10F64D1139FDF4E42F003FFDCD3FED393F3F3CED11393130015D2436353426232207061514171633121716173521111407062122242721161716333237363D01060706232202353412333702BD8A836E96391E203A960B3D68400115477AFEA6D1FEF80E01360C1B2E6D9A3422292F5588D2FBF2DE5BEA97A59BA28D4B6E5F4A8A0372192B739DFBF6D36BB8A4A332162767429C464623410127FCF3014B0300000100870000045E05BD0017003F402505022702580E680E04141712000C24170710070A0836051A1913102711191819BE215045182B2B4EF44DFD3C4E10F64DED003F3C3FED3F11393130015D0016171E01151121113427262322061511211121113E01330343A5352D14FEDD1E276D7175FEE4011C3EA35A045E46483D8192FD80029758364C978CFDB205BDFDF75F4B0000020089000001AA05CB00030007003B40224C004C015C005C010401B102000406070A0917171A0006270107190809B2215045182B2B4EF43C4DFD3C4E456544E6003F3F3F4DED3130005D012111210121112101AAFEDF0121FEDF0121FEDF04C40107FE77FBBE0000020009FE4801AF05CB00030013004F402F260E370E024C004C015C005C0104042C131F1001B102000B06072C100F1517171A000C4D13010B191415B2215045182B2B4EF44D3CC4FD3C4E456544E64D003FED3F3FED10F4ED3130005D015D01211121011E013332363511211114062322262701AFFEE3011DFE5A1814082A2B011D82BE0D332604C40107F9640201293B04ADFB4EA59E020100000100820000046D05BD000B00F040B240024605D402E502040F
+
+080A09550589058F088E09C505CA08D907DF08DC090B080618062F032F0428052D06370338064C0348065D0359066A0369067804880497039507A903AF04AA06A807B603B804C603C9041A4B064A07560588048308C405C808D903D904DD07DA080B050909040505060B0B040802070904050706050A02200303CB1204040909040302040602090A0403060A070A0000061A0D010A27000B200B300B400B040B190C0D872150E3182B2B4EFC5D4DFD3C4E10EE003F3F3C3F3C12393901111739874D2E2B047D104B51587A59C4001239011139390F8710083C07103C313001715D00715D13211101210901210107112182011801630161FE83018CFEA8FEFB76FEE805BDFCE6019AFE5FFD6401D27BFEA9000001008B000001A805C20003002540130200010A0517171A002701190405B2215045182B2B4EF44DFD4E456544E6003F3F31302901112101A8FEE3011D05C200000100800000069C045A002D00C2414D0037000200010006000200160002002500020069000F006A001A0079000F007A001A0089000F008A001A0099000F0099001A00A9001A00B9001A00E7000B000E0002002100290003001F000D0024002D00180024002D00250007001F0006001D00120008000A002F00170017001A000600360009010F00290011004D0014010F001E0020001D0027001E0019002E002F012300210050004500182B2B4EF44DFDC410F4ED39F4FD4E456544E6003F3C3C3F3F3C4DED10ED1117393130015D005D00161716171615032111342726232207061511211134272623220706151121112115363736333217161736373633058F8C392E100A02FEDC142666762D17FEE11424697A2A17FEDF0115352F53847D4D3E203853586C045A38463953376AFD5102B63E284C623449FD770289612C4F4F2D59FD7004409F552440373350602D2D0002008700000461045F00160017004B402D0501150125013701580B680B060112100609241716070E040A170536170F021A19110E270F191819BE215045182B2B4EF44DFDC44E10F64D1139ED2F003F3C3F3CED3F39393130015D001615112111342726232207061511211121153637363327038AD7FEDC172A7691361CFEE401133731588769045CB1CDFD220297562E547B4165FDB204409F5425420300030042FFDA049C0465000B00170018004D4028170301080C880C881003170D180F660D0305241814070B240E0B1818080236171A1A08361119191AB80176B321484E182B2B4EF44DED4E10F64DED11392F003FED3F3CED313001720072712436353426232206151416332400212000353400212000150102EB86867D7D87877D022EFEECFEE7FEE7FEEC0114011901190114FDD3C9B2A4A4B1B1A4A4B266FEAB0155F0EC015AFEA6EC02400002007DFE53049A045A000D0020004A40291713
+
+080A1C1A022420071A060A24130B190E080D180D36101A22061F1B1F1827191921229821504E182B2B4EF44DFDF4E44E10F64DED111239003F3FED3F3FED1139113912393130002623220706151417163332363512001110002322272627112111211536373633037473819B3A1E653C52777D1D0109FEFDCC82562F2DFEE601112E345F83029FC2934E78BE4D2DB8990239FEE6FEEFFEE0FED2412445FDC805EFA1472949000002003CFE50045E045E000E0020004A402BD81EEA1C02F80C011213072420071306170E241A0B160E031F131F1627151A220A361D19212298214845182B2B4EF44DED4E10F64DFDF4E4003F3FED393F3FED11393130015D005D2437363534272623220615141716331217161735211121110E012322003510003302E63E28223D996C831E3898405431330113FEE6209B86BDFEF6010BC4D27E537F644F8EA6A9714889038C432657A2FA1002374267012EFC011001460000010082000002FB045C0013004AB900030147B3020F0D06B80147401913070D060C0A200230024002031517171A020E0B270C191415B80164B3215066182B2B4EF44DFDC4D44E456544E64D5D003F3F3FED1139D4ED3130001617112E01232207061511211121153637363302DD0B131B2A0DAC3B21FEE1011042315080045C0101FEDC0302703F83FDF70442BE6D28430000020042FFDB04250461002B002C007E404F09100626190D030904210B0B4B0A490B472144204829D703081D22200C0A04162B04161A2C2C1207042C280B2C2C0F150A201D164D2207152D074D251A2E0C001D4D0F2D004D2B192D2E8721484E182B2B4EF44DEDF4ED12394E10F64DEDF41139ED1139391112392F003FED3F3CFDCD10CD11173931305E5D5E015D0116171633323635342726252627263534363332041721262726232206151417161716171615140623202635010163091E358F54632828FEFFB94C4CEDD7CC010113FEE306192F715D4F2A2AFFAA5554F1FCFEFFF501FB015C4C203932323019193D2E45448097D9A3C837203A3A27311617382851527BA2CDD9A803030000010015FFEA027805680016004AB6102C0F1F0C2C11BA01710004015C401607005C0601061817171A0F06F4040927009203151718B8010EB3216066182B2BD43CE4FD3CF43C4E456544EE4D003F3CFD3CED3FFDF4E4313013353311211133152311141633323637150706272635111598011AB1B122570D1D0E87CA4A30036DCB0130FED0CBFDC043210101D505074D3166029F0002007DFFE80455045F0019001A004C402E0A161A162A16381656076507061A070A0006160E0D0A0524140B1A0D0A271A180B1A1C013618191B1CBE215045182B2B4EF44DED4E10F612394DFDD42F003FED3F39393F3C3F3130015D0111141716333237363511211121350E01070E01
+
+2322272635112501A116277292361C0121FEEB042016437D54F2542F01EC0442FD6F5D2F537640690251FBBE9A0532133C2CAE60BB02911D0001001A0000045704420006009E404F270654066406A506B506050406011002470457047A0274037704064701880087059705A705B705C803E701F701090320040427120505060220010127120006000602050401000603020A0802020001B8010CB2030506B8010CB6041907656066182B19764E10F4184DFD3939FD39391910C618003F3C3F3C3C3C123905872E2B7D104B51587A59C4872E182B7D104B51587A59C43130015D7100715D0121012101211303250132FE77FED3FE790140E30442FBBE0442FCDC0001000E000006210442000C028C41FF0050000C005000020054000000550001005F000700050021000F0007008300020082000C00D7000200DA000700D5000C000600130002001F00070013000C005200020052000C009000020090000C000700090001000B000E00030007000400030008000C00060050000B005F000300550008005A000600090021000C000000030001000C000600020008006F000000600001006C000600630008007D000000720001007D000600720008008D00000082000100860005008C000600830008008B000900DC000000D2000100D9000600D6000800D8000900EF000000E0000100EF000600E00008001B0007000200080005000700090008000C001800020018000C00DB000000D4000100DB000600D4000800EB000000E4000100EA000600E4000800FA000000F5000100FA000600F500080012001A000000150001001A00060016000800180009005E0000005000010058000300590006005600080057000B009F00000090000100970005009F00060090000800100000000700080008005C0012000C000C00000001000700060006005C0012000200020001000500040004002700120003000200030009000A000A00270012000B000B000C000C0007000200030009000100030004000A000B0005000000060009000800060005000A00050003000400020009000B000A000C000E00170017001A000401B90006000100EF411B000200FF00020002000201BA0000000800E0000C00F0000C0002000C01BA000701B9000A00190065000D000E012300210060006600182B2B764EF4184DF47CE4713939E471183939F4194E456544E6181112393911123939003F3C3C3C3F173C1217394D05872E2B10D0872E2B10D0872E2B877DC4872E182B877DC4313001725D715E5D5E0072715E5D01211B012101210B012101211302870121A6AA0129FEC4FEDBABADFED8FECE0132AA0442FCEF0311FBBE031AFCE60442FCF20001001A000004500440000B010340970800180002070413041A0A032702240426062A0A3604390A4504490A5504590A9504990A
+
+A004AF0AB404B707BB0AC404CA0AD204DB0AE504F70417040318040503271202020104051804030527120607060A09180A0B0927120708080A0B180A090B27120001000104070A040006050302060B0908000A090705060B03010A0A0402060802000D17171A08A900190C650C0DA9216066182B2B764E10F4184DFD194E456544E64D2F18C410C41139391239393911393939003F3C3C3C3F3C3C3C1217390110872B087D4B51587A5910C5181005872B7D084B51587A5910C5181005872B087D4B51587A5910C5058710182B087D4B51587A5910C53130005D71015D330901211B01210901210B011A0174FE9C015DB6B20153FE9A0174FE9DBCBD02280218FEC4013CFDEDFDD30147FEB900020015FE470450045F0013001400D94070270A560A660A950AA40AD30A06050A0106061C07110D2D07200D3D07310D4B075D07580B680B7707790D0D170F360D8709880B980BB80B0614140C080D02200C0C27120B0B0A0607021F0808271209090A0607020D0A150C0B0908060709001F022C131F100F14071617171A0E0D0B0CB8010CB30607090AB8010C400C13920819651516A9216066182B2B764EF44DE418FC393939FC393939194E456544E618003F3F4DE4FDE43F3F3C3C3C12393911123901872E2B057D104B52787AC533872E182B7D104B52787AC5011112392F3130015D7100715D1F011636373E012701211B01210102062322262701B1242A4C1A192B04FE70013DEEE1012FFE8A6C7EBD262E2E0182D102020A12116C0C0472FCDC0324FBD0FECA95010306140000020021000003CE045F0009000A0092406008034803C903033704380984048B09D504DB09060704260429093604390945045504830994049B09A404AB09B404BB09C304D609E409119604990902090304042712080809030900A001060804A0070A0A070A0A04090103051A0C0108190B0CB80172B3216066182B2B4EF44DC44E10F64DC4113939392F003F3FFDC43FFD3CC401872E2B877DC4313001725D71005D1335211501211521350103470374FDD7023CFC53022F4F035AE8EDFD95EADE027C01050000010000FE63027D05DA00290059BB000401B3000501B3402A201C1C25132F1211242F25202B012B17171A24123A182F20011C20FA020709294A04192A2BD7216A89182B2B4EF44DF43C3939FD395D3CF43C4E456544E64D5D002FED3FED12393D2F1AEDED313037342726273536373635113437363736373637150607061D01140706071E0117151417161715272E0135D04C2E56612847111E4842593665531E2E1E3395875D02361E4B478FD7E17E432918792128458E010C3338613934110B019F121E2E73E870426F45379281FD6F311D169F0204A39C000001006A0000017105D00003002540130300020A0517171A012202190405CD216C3C182B
+
+2B4EF44DFD4E456544E6003F3F3130011121110171FEF905D0FA3005D0000001002DFE6302AA05DA00260065BB001E01B3001D01B3403120090900102F1111012F001B201E0A09080306222F27012717171910013A0C20060106FA18224A1E1A282728D7219046182B2B4E10F64DF43CFD5D3CF43C4E456544E44D5D11121739123939002FED3FED12393D2F1AEDED3130133536373637353436372E013D0134262735161716171E011511141716171506070615111406072D4B1E33026E7883634757643659434334412867552C4FD294FE639F161E326DFD8E893340A383E86F50129F010B1134349839FEF48F4328227918264480FEC798A7040000010004013104C40309002000454021D51C011C2205108620DA0C010C2214201A170B08041F106D111A221F6D20192122B8011FB3217B47182B2B4EF44DED4E10F64DED111739002FD4E57110FDD4E57131301236373E01333217161F011E0133323637330602232227262F012E012322060723153F2E31683718273E35E9294D15424E12AA1BA78E1C1F3C52D11D5414395813AD01A8AC373A2F060A145A100D6749BAFEF60509224F0B125759FFFF0034000005A807380232002400000010008E0B08FFFF0034000005A807E0023200240000001000DD0B180001005CFE29057B05DE003C00734013282929362D1B371E3308081A0C410303248E2DB80146B4338E1E9C17B8010BB71241381A09372830B8013D40172121173C1637170837071A3E0F373C193D3E9921AD56182B2B4EF44DED4E10F64DEDD4ED1112392FEDD539003F3CEDEDF4EDF4FD3FED12392F111239391239392FC93130123736212017161721262726232202151416333237363721060023073E01333216151406232227262737161716333236353426232206072737222726115CCFB401160174AC5F07FECC1E2F54A5A8C2CD9EA2552F1F013128FEB7E53D211C10516096763348213C263915301E3C343A211328192B5EEDB6B60457D1B6F4898A6A3660FEF1F8F8F76A3972F1FED25A07054F4A5C6B150A165611050C331C2A2209082893CCCD0165FFFF00A50000050207630232002800000010008D0C04FFFF009700000544074E023200310000001000D90A1FFFFF0065FFD705EA07650232003200000010008E1C08FFFF009CFFDA053D07380232003800000010008E1608FFFF003BFFDE043806000232004400000010008D3A04FFFF003BFFDE04380600023200440000001000433A04FFFF003BFFDE04380600023200440000001000D83A07FFFF003BFFDE043805D50232004400000010008E3A08FFFF003BFFDE043805E8023200440000001000D93A1FFFFF003BFFDE0438067D023200440000001000DD3A1800010047FE290434045C003B008840264A33E637020C311A314F314632493705222323302715
+
+31182D3BD2042438072D8F18E910B70CB80145400A32140B278F1E0F31222AB8013E401C1B1B32141504353B10360F1F00363B1A3D088435193C3D8721484E182B2B4EF44DED4E10F64DFDF4ED111217392FEDD539003FED3F3CEDEDF4ED3FEDED111239391239392FC93130015D005D012627262322070615141716333236372106070623073E0133321615140623222726273716171633323635342623220607273722023510003332041703100821306590351C1C338D64540901230A5486E83F211C10516096763348213C263915301E3C343A211328192B63BCF80112F1CD01051802BB3D31428F4C7E7849886C568274BB5D07054F4A5C6B150A165611050C331C2A22090828960138F901190138B8E900FFFF002FFFDC043A06000232004800000010008D2204FFFF002FFFDC043A0600023200480000001000432204FFFF002FFFDC043A0600023200480000001000D82207FFFF002FFFDC043A05D50232004800000010008E2208FFFF00710000026F0600003200D700000010008D0404FFFFFFC6000001C30600003200D70000001000430404FFFFFFAF000002840600003200D70000001000D80407FFFFFFCF0000026405D5003200D700000010008E0408FFFF00870000046105E8023200510000001000D9171FFFFF0042FFDA049C06000232005200000010008D1804FFFF0042FFDA049C0600023200520000001000431804FFFF0042FFDA049C0600023200520000001000D81807FFFF0042FFDA049C05D50232005200000010008E1808FFFF0042FFDA049C05E8023200520000001000D9181FFFFF007DFFE8045506000232005800000010008D1A04FFFF007DFFE804550600023200580000001000431A04FFFF007DFFE804550600023200580000001000D81A07FFFF007DFFE8045505D50232005800000010008E1A0800010047FE8E042505AD000B0045B304093507B8017E40200A03B90000900D010D17171A037101064C0007719F090109190C0DDC216A7A182B2B4EF45D4DF43CFD3CFD4E456544E65D003F4DF43CEDFD3C313001211121152111211121352101AA01160165FE9BFEEAFE9D016305ADFE3DE6FB8A0476E1000002005E032E02E405B40007000F0030401909C4040EC407051117171A0CC40108C405191011D721EA7A182B2B4EF44DEDD4ED4E456544E64D003FEDD4ED3130001610062026103602163236342622060225BFBFFEF8BFBF1D5E865E5E865E05B4BFFEF8BFBF0108BFFE7A5E5E865E5E00020045FF0B043405070008002E00F64095050701090503040602210C07241A3C07351A351B4C004C084C1A5907591B6929692A991B0D111C1A1D1B28292910080E071D2B1C2A2A0F071D2B2B0F2B281B1A110E08070821042B28071B221E081A16110E010F2A2AAF1229291022B725161607081A1B051E
+
+010F10110E01240B0728252B08292A1E24250B28291A1B07080E0F110904213622101636152B2A048415872E30472F4E1076C418D4E44DED393910ED39D4ED111739003FEDDD3C3F12393FED3939DD3C111217392F10ED01872E2B7D10C500111239123939111239391239011112173907102B3C87102BC42BC4053C3C87103C3C2BC42BC43130015D5E5D5E005D002322061514161713040033321617373307161716172126272627031E0133323637210E0121222627072337260235025412646F311BAAFDE00118DA2E251E326A3B6C436814FEDC0B190F19AF10180E44700F012311E9FEFA1E261D3B704A7EAC036ACC8975851902664B013F0406B5CA254366B43C271A11FD8503045E66BBF90403D3F2300111D20000010042FFDC045205C0004700B3406C06350C4616351C462C2424353F233C243F2533357B0A8B0A0C080900470A0701040D28031E42211B2E3D2431203713143D473828000343312E01033337082C1486102008EE1F09094718321000470B2C204333223B0B20231454137C38211C24038D1B6E0D2338DD004947484E1076C418D4E44DF4FDFDDDE410F4FDE6003FEDDCED3F3FED12392F3CFD3C10ED11123912173911173912390111123912391139391112393912391117391239393130015D373E0135342726272335332E013534363332041321262726232206151416172115231E0115140706073637363332161F011E013332373637170E012322262F01262726232207060742489A100915B2722E2CFFECC4012009FEF10A24357E5D6C2642011FF404053A257150263D3A244527291B250D2E3E24365232B4532C6038392518282A2D34225BAF27AD532C382036705A894F9AF4D9FEFE633D55734B2D638C7027341A605233681D09100C0B0D09051A0F1FDF213E1612130C0608120D2A00020041FE76042705C20039004B00924068360D3915302F313A3E403A443649791A8A1AA339BA3FCA3FEA140D360D35163A28031348473F3E39322F1B160A0B250B3A0F20060022202A3A250A6F0A010A1C47302D012D541F314B32171A4D3E3F120112540323602501253142329F350135194C4DDC216A7A182B2B4EF45DEDF45DF4ED5D394E10F64DEDF4ED5D39F45D003FF4ED3FFDF4111217393130005D015D12272635343633321716172126272623220615141617041514070607161716151404232226272116171633323635342726272627263534373637002726272506070615141716170536373635E02526D5CCF4663709FEFE0717295E3F508CBB01464A294F381A2EFEF8A4B2F911010E0E1A2B623C562D2DD2B7436B482A4D022E301A2EFED534160E2B193F011C211724037B3A485895D8A056813C233E3D3B4444569ACB7F532E29302A4963BFC9B2CE4A21384A3B3528286A5A3A5D857D523128FEAF29
+
+151898162B1C2031261721950E1B273600010121020002DB03BA000B002EB9000B0104B5050D17171A02B80104B308190C0DB80104B3216B3C182B2B4EF44DFD4E456544E6002F4DED313000001615140623222635343633025E7D7D60607D7D6003BA7C60607E7E60607C000001FFC3FE8E043305C2000F0042B10105BA018D0006011A401C0C0E032F0D0C00009F01011011059F04090D1A11091011BF216747182B2B3C4E10E64D10DDED1112392FED003F3CFD3C10EDFD3C31300123112311231122023534123321152303B6CAC4CABCDFF6EF028B7DFE8E0689F97703610102DAD60121AB0000010089FFE5049A05DA002E007E404C681D010B0B21201532141C11215C20202E02283204112E0A1832110B0B071C213415150E00076E25311C6E000E100E200E300E040E1A30022C2700001000200030000400192F30DD216B7A182B2B4EF45D4DED394E10F65D4DFDF4ED1112392FE611123918003FED3F3FED3912392FED10F4ED1112393D2F3130005D1334373621320415140706071E0115140221222627351E013332373635342726273536373635342623220706151121893C6C0136D801081324617D6EE3FEE80E3B22161E0C9E3F28673D936B2C4871507E2718FEE6040BBC62B1D0B243335F3A35BD81B8FEC70507E402015C3C649438210CC7011626726057553283FC160004001A000005DC05C2000F001F0029004901754197000400050004003000020009000F00290001001900030001000C000D00070015000700190009001D00080011001B0035004D0029004D0035004F0040005B0035006B0035007B0035008B0035009B003500AC003500BB003500CD003500DD003500EF003500FF00350015000F0035004A0035005B0035006B0035007B0035000500330025002B00430040003D003B0038000500480049003500350048009E00250025003F004900DB0024009E004F002B00010040002B0001002B002B0013000F0039001B0002000700390013000A003500320029003E001F0032002400490020002A003A001C00320040001C0041001C00290020003201660030002A0090002A0002002A002A0017004B00170017001A000B0039001F00E00003003900170019004A004B00E00021006901BB00182B2B4EF44DEDF4ED4E456544E64D12392F5DFCFDF4E410E410FD3C10E4111239003FED3FED12392F5D71EDFD3C392FED19392F1811121739111239313001715D5E5D5E005D00070615101716333237363534272623000706212027261110373621201716112427262B0115333236350111320417161716151406071617161D0114161F01232E01272627262F01231101FDB3B0B3B2FCFBB2B2B1B3FB02E1DDD7FED3FEC9D5D5E6D801230131D8D8FDA4422C5034534B54FE384C012F1161406D73544D2748030407CC0A
+
+060A102C18312F2D0544B8B4F7FF00B3B3B4B5FDF6B5B8FC63D7D0D5D501370143D6C8D8D8FECFDC1A11ED3C43FDCD0331010107233C87675C09101F3A7D490C180C1727941A2B110A0303FEDF000003001A000005DC05C2000F001F003B0111416E0088001D00010003000100030005000C0009000900110006001600060018000900260009001D000D000D0010002C00750023007600260086002300850027000E0000003B0010003B0002003B0037006C000F0022000100220028002D00F30031006C0009000F0028008F0028000200260000002800100028009F00280003002800280013000F0039001B0000000700390013000A003D00170017001A000B0039001F0017003A003B002D002C0034003200090000002500010019006000250001002500C70003003900170019003C003C003D00E00021006901BB00182B2B4E10F44DFDF65D5E5D5EEDD4C5C4D510D6ED4E456544E64D003FED3FED12392F5D5E5D5EFDEC10DC71FDD45D3130015D7100070615101716333237363534272623000706212027261110373621201716110006232226353412333217161727262726232206151416333236373301FDB3B0B3B2FCFBB2B2B1B3FB02E1DDD7FED3FEC9D5D5E6D801230131D8D8FE75D371A8F5D3B875568C22BC11372E37536A75524B4D0BB70544B8B4F7FF00B3B3B4B5FDF6B5B8FC63D7D0D5D501370143D6C8D8D8FECFFED68BF0C3B60100304EC3035A1F1D898A897C523E00000200CB02DC071005C20007001400B1406B7409850902060816084D0F46105A0F54106A0F65109B0F9510AA0FA6100C490F44105A0F56106A0F6610760F7910840F8F100A0E0F0F2F1209090A1110102F12090908100F0D050409110E00130203000A0802001008110F0A0E0909110E0B1114005D065D055D03141516B80124B321C5E1182B2B2FD6FCFDFC10CDDDDD11393D2F18123939123939003F3C3CDD3C10DD11393939173C05872E2B047D10C405872E182B047D10C4313001715D00711335211523112311251B0121112311032303112311CB028FDDD8032B87850134C5A1A8A1C50510B2B2FDCC0234B2FE5501ABFD1A021AFDE6021AFDE602E60000020076045F02740600000300040034400E0070020407040617171A04010300B8015D400902190506BA216C47182B2B4EF44DF43939394E456544E62F003FDE4DED313009012313030274FED0CEC0170600FED5012BFE5F0003FFD5045F026A05D50003000700080035401A080207CA050011080A17171A0804014B032E064B0419094247182B4E10F44DFDF6FD11394E456544E62F003F3C4DFD3CDE313001211521252115210501650105FEFBFE700105FEFB014B05D5EDEDED8900010049FFED0484045000130093406388109701A701D705D80FF701F71207010D000611020A03061105
+
+0904061108090407100B0A0307100C0D0007100F0E130710120E1306111007072212060611111007060400091011130E22000D4A030A220409070603001A150E091914156521425F182B2B4EF43C10F64D3C002F3C2F3CFD3CFE3CFD3CDC3C0111121739872E2B7D10C5010F0F0F0F0F0F0F0F3130015D01210721112107213723112137211121372107330484FEA15301B2FDD35AFEF057FB01725AFE34024258011158E80284CCFEF9C4C40107CC0107C5C50000020012000007AA05BD000300130090404A2201201124139701040211120102110F13011212251213130410112A03020B2A0802080F040101062A04020C2A13120F081204010313000F250C0A9C06AC0D070C0C130D1A1513191415B8018EB321E556182B2B194EE41810F6114D392F3C10F4E410FD3C111739003F3C3CFD3FE5392F111239392FFD2F3CFD3C01872E2B7D10C50111123939873C3C3130015D0123032101211121112115211121112111210321037685E30168FEB40572FD0902ABFD550305FBCCFE476BFEC004C2FD680393FF00FEC3FCFE80FEFC0138FEC800030047FFC705FD05F6000B0016003200CA4079670AA815B815C70A044E17482B582C690F7904F62FF63007063001151E161D1C1D271D28281B0A1E0B1D191D2A1D291A272A2E16150B0A0406191C201116150B0A040E03191C272A0424031A291A1B29EF1228281B29281A1B0341320328290E4124091A11371B57201A3428063729572E193334DF21EB56182B2B4EF44DE4ED394E10F64DE4ED39003FED39C43FED39C40108872E2B087D10C50011121739111217390111123939121739113939872BC42B3C2B3C2BC487102BC42BC42BC42B3C313001715D005D002726232202151417161701001633321235342726270100161737170716171615100706212226270727372627263510373621041D45486BD6BA120A1A0279FE078E4CD6BB080D1DFD8C0198FB61A455A8382E2DC5C2FEC47AF36DAF55B63A2C34DABC012C04A02228FEE5EC6252304702B9FCA2370142C5423E5F45FD4E049A5853B251BB457B80C7FEA6DBD74B5EB950BE4E778EBB015AF8BA00030019014705890475000B00170030006E40433803C700D700E700F700F72B06041B0A281928292839284928062027202430110817D62D0211201A2D073217171A1D200BA5052430243005320EA514202A1931425F182B4E10F44DFDF6FD39393D2F2F1810F6FD4E456544E6003F3C4DF53C10F43C113939FD3C313001715D0026232206071E01333236350436372E0123220615141633003633321615140623222726270E012322263534363332161704C5554C4B4F382F594A4D54FD0A5C2F38614D3D56514201A99C6BADB8B3B26E5C423C45B86BB2A9BE9D5EA65103366850745E646D5CC964656D546C555C6D01F568E6AEB4
+
+E44B375F6F74E6B4AEE5627D0002004900000484043B0003000F0042402207FA0A05A10C04FA0E03A1020A0A1117171A0A0085080D22070E8504021910425F182B4E10F44D3CF43CFD3CF43C4E456544E63C003F4DFDDEFC3CFD3CF43130251521351135211121112115211121110484FBC5019A0107019AFE66FEF9F6F6F60140F40111FEEFF4FF000100000002004700000482045C0003000A006C40130506062212070708040A0A221209090809040AB80103B2050708B801034020200630060206070135000A0A090706040801021A0C050401190B0C6521425F182B2B4EFC3C3C10F6114D39173C003FFD193F5D18FD3939ED39390104872E2B7D10C5872E182B7D10C5313033352115013501110D011147043BFBC5043BFD6D0293F6F60238FE0126FEF69A9CFEF6000002004900000484045C0006000A006C401305060622120000010403032212020201000506B80103B2020401B8010340202003300302030707350A0A01000805041A0C060702030400190B0C6521425F182B2B4EF4173C10F63C3C1139003F4DFD193F5D18FD3939FD39390104872E2B7D10C5872E182B7D10C53130132D011101150115211521490293FD6D043BFBC5043BFBC5021C9C9A010AFEDAFEFEDA1CF6000001FFEA000004890597001600E04043261428166F0260117704A605A90E07081518152015641504120F131515161414B31213130E040100151616B312000500140E0F12040B1316010405040008150F0E040FB80136B6010F121F120212BB01080008000C0136401905000E100E020E0E0A13161400040A0C15181A00063802C200B80158B31508B30BB801584009130D3811C213191718BC017B0021012B012D00182B2B4EF44DF4E410F4FD39F4F4F410F63D2F18003F3F3C3C3C12392F5D3CFD3CFD5D3CFD3C111239011112173911121739072E2B7D10C010C0C0072E2B1008C00510C0C0013130005D015D01033315230721152111211121352127233533032101130489E48FD16B011AFEC0FEDDFEC201186DD593F00153010AFD0597FE2988DA87FE2901D787DA8801D7FD91026F0001FFCBFE2504BD0442001B00AC405F2600261B591059115912B718F7180703187618021909010C1211110E18041919001B1A1A27121919000E111127120F0F10191A09071B0F0E00061210110A072440052104401723185015011211100E0C00041819091B0F1A1D1B191C1DBE21B80141B1E3182B2B194EFC4D194E10E64D18111739003F1ACC1ACC1ACC1ACC1AED3F3C393F3C3C3C12392F3C01872E2B7D10C418872E2B7D10C487100EC4C48710C40EC43130005D01715D01030E01151416333236373E013713210321370E012322262703210102098201026131487C2318221B4F011CC2FEF91C2DB76B2A421157FEDE011D0442FD2807100844355339
+
+27849101A8FBC0B64890180FFE1E061D00020024FFD7045205F2000B002B00604010641F741F021E1B15083211112B1B201FB8019B40231B20230302202B0B1F1E1F050B2905B427151C1854271A2D0B540E192C2D65217B69182B2B4EF44DED4E10F64DFDF410ED39111239392F003FED3FEDE0FD12392FED3910C93130015D0016333236353426232206150A0135340033321716173E01353402232206072736373633321716111007062101397D51669264696E8B20F5011CDA504E5B2F0104767820351A8C36344C49CE86A1AEB7FEF10122719E846185AC82FE4C010ABEDD01252430461E3611A5010E1717BE1A1118A6C7FE7FFEB8EDF80001FFF7FED404A805BF000B007D403F98080168099702DA03038D090104030382120909080302020303821209090A0304090904200A02220B000804220709040302040B012D051A0D0A2D08190C0DB8011FB3216B88182B2B4EF44DE44E10F64DE4111739002FFD393FFD391A1911392F113905872E182B7D10C408872E182B057D10C4313001715D005D0111210901211121350901350495FD330203FDF302EAFB4F0247FDD505BFFEF2FDA2FD8FFEF2DC02A30290DC0000010007FED405C205C2000B0037401D00030A072A080004010182004A091A0D0482054A07190C0DE0217F89182B2B4EF44DF4FD4E10F64DF4FD002F3C3FFD3C3C313001710121112111211123352115230507FECEFE1FFECEBB05BBBBFED405F0FA1005F0FEFE0000010031000004C20442000B0032401C2C042C050205020A5D0B0604070A042702072708020800AA0A7B69182B2FED39392FFD2FFD003F3C3FFD3C3C3130015D01152311211121112111233504C29AFEE2FEDFFEE29A0442D1FC8F0371FC8F0371D100010076FE5003D3060A0020004D401907230A3206230318231B3217231306230751211823171A221FB801ABB220820FB801ABB30E192122B80162B321EAF0182B2B4EF44DE4FDE44E10F64DE410F4E4002FE4F5E42FE4FDE5313004070623222627371E013332373637133637363332171623072E01232207060703028F2B50CB2B72361826301C49191006260A304DD03E50500A152435204C1C1206249364B91714E315125034A30398F86BB11314E311125034A9FC3400020028033402C005EF0011003A0091B6070401D91A0126BB0137012E002A012F401923130D0502041C152B2E262E2A26130D050200061D0A24191DB80144400C193921032A140A3932140015B801ADB72E942A23261A3C1CB801ADB21D2307B801ADB336193B3CBC01640021007D01AC00182B2B4EF44DEDF4ED4E10F64DE4EDF53C003FED3F3FEDED123911121739123901111239111217392B3130015D0071010E010F010E0115141633323736373E0137273E0135342726232206072336373633321716151114161715
+
+232E013506070623222726353437363701E1121D202F4839362A23281A0F131503401C242F1B2F35340BB40C2A46A77B41781019C8070934233E4A89372152367104920C0B05070B32262829100C0E0E283796031B182F110A2D2D5B3353182D96FEBE273509241123182D13215531436C3A260E0002000E033402E205F00007000F0058B7A70EB70EC70E0300B801B4B20A1404B801B4400E0D031117171A4301530163010301B801A54009084C065C066C060306B801A540090B191011A6214247182B2B4EF44DED5DD4ED5D4E456544E64D003FED3FED3130005D0036342622061416240620261036201601CD5151AA555501BFC0FEACC0C00154C003C570BA7070BA702FC0C0013CC0C0000100310000060705EF00210057402F120602150C541D01030216152205130A2317171A0423210605440209A421191344160FA41923DF14011419227D46182B4E10F44D5DF4FD39F410D4FD39F43C10F44E456544E64D003F3CFD3C3C3C3FED1117393130000607211521113E0135342623220615141617112135212E0135103736212017161105DC8093013EFD9A827AD1B0B0D18577FD9A013E938089BB017C017CBB89026EE58EFB011762CCCDEEE3E3EECDCC62FEE9FB8EE5AE011BBEFAFABEFEE500030038FFDB06DC045A00060016004D00A740201816150C090706232C43341B3B000643124015380C3C0709341824062C281F06B8019540353434461F2C24280324282F07122C460B003C103C023C382C400B061F1BB134344E4F00953C1F331F321A4F234D242D0F4D49194E4FB80189B321484E182B2B4EF44DEDF4ED4E10F64DF4E4ED1112392FEDE4003FEDCD5D3FED3F3CED10CCED12392FFD1112391112391239391139123911123901111239111239391217393130012E0123220607050E010F010607061514163332373635273637363534272623220706072136373633321716173E013320131607211417163332363721060706212226270E01232226353437363705AF076A6B6C7006FEF715223B6D5E20364654573A6891441F30502B486E2B1703FEEA0BB075B58163373C3D9E68014C753E05FD161B328E50761C01210C578FFEF987C1354ACF86CAB4894C9B0292697D7175890F0D0C16131624532F52203A98F90A111A344F1D0F3E213CE15D3E2C18313441FEEF91DE713C6E37516464A366505F58C488B9552E18000003002AFFC204B4047B000A0015002E00C64066A709F70902091E0A1D1F1D281D29291E14151D1C1C2B1D2A2A1D1C1F2215140A090406282B2E111C1F1815140A09040E282B2503291E292A1EAF121D1D2A1E1D1D0622292E111E0E182A252907032425070E24180B1D0B11842A2D2E1A3006361E2D22192F30B80176B321484E182B2B4EF44DE4ED4E10F64DE4ED003F3FED3FED3F1139111239011112
+
+3911123908872E2B087D10C50011123939121739113939011112393912173911393987102B3C2B3C2BC4043C87102B3C2BC42B3C2B3C3130005D00272623220615141617010017163332363534262701240021222726270727372E01353400333216173717071E01150304462B2977890E11019FFEBF1C2E467B7F090EFE6302DFFED1FEF684673A43874A8E45310124F48EB04B8A478F42350354140CB39C31622301B9FDC60F18C094323F42FE4909FEB72C19348E3E905DD75AFA014D3D3E91439557C55F0002006DFE6C0463043D000300230057402B18150F0C0D0E06130406231E2406132E01280206131213120270030309226E231A251BFC1F090109192425B8011BB3219088182B2B4EF44D5DED4E10F64DED12392FE539392F2F003FFDE62FFDCD11391117393130012111210004232224353437363F0136373637210E010F0106070615141633323736352102F6FED5012B0161FED4B0E5FED740276C473A130C01010E06356B493E160E6B5C88381D0121031C0121FAF6C7DAD1825A3753372D3C264FA68354393137222D5B6C6E3B44000200E1FE80021A043D00050009004240210205000459072809060B17171A0670071C0104030304007001190A0B7021813C182B2B4EF44DE539397D2F7C2F1810F4F54E456544E6004D3FFDEE2F3939313001211113331303211121021AFEC750965308FED6012AFE80017602AFFD51032601210001004900B10484038B000500234013032200D9020222001A070419060765216A46182B2B4EE410FE4DFD002FFDED31300111211121110484FEF9FCCC038BFD2601D30107000001FFD5FFDA05120771000800AD40297C007C01890289039900054A014A045A015A046901050202010303000708082F120505060100010200B801A240181205050401020100022F1203030402030503020104080D07B8016B4016040740010203000444800806050503071A0A0319090ABC017D002100E2013C00182B2B4EE41910E611392F39391A184DEC391139391A003FE43F17390108872E2B087D10C505872E182B087D10C505872E182B7D10C58710083C3130005D015D05010727251301330101E1FEF1AF4E0185F80218A8FDA426038E6B8ADEFC6906A3F8690001001EFE50045205E300260086401A3A214921960C031C1F1B1F1B1B82120D0D0C150D1B1D14113218B8017AB71E0B1D1D00030A1EB8010A401C260332230115141D2817171A0026311F1B0D0C1C09060BDB1D192728B80118B321815F182B2B4EF44DFD1739F4394E456544E610D4C4003F4DED39F43C1139FD3C10F4ED391239393901870E2E2B057D10C501073C3130015D012E01232206070E01073315210306070623222627371E01333236371323352112373633321617042122331A24391612180CF7FEED79203D66C32F732E32
+
+28291C48371E74F9011839395ACE3A5C3504DA12111C2A2A7548C7FD21C16AAF1813E3170F7AAC02ABC701215E94121400020049006D048403CE0015002A00BD40952A072A0C2A172A283A073A0C3A173A2845004B074B0C45134B17451E45214B2856005907590C56135A17561E56215B286600680C691767217600790C7A17762186008A0B8917232A002A132A1E2A213A003A133A1E3A2108202926232A2A1F1CF3262A8F199F19AF19BF19D019E0190619150905022A140A11F3052A0E25241B1A100F040308142A091A2C1F14192B2C6521425F182B2B4EF43C10F63C4D111739002FEDFC3939FD113939D65DEDFC3939FD1139393130015D005D1236373204333237363711060706232224232206071100070623222423220607113E0133320433323637118C7C59630155486D613124303A585866FEB75D5C72470417395E5F63FEAD565C75443F84556201554956933A01C53E019A45242DFEE32B1E2D974152011601021F349A484D011538469A5045FEE40002FFFA0000057005C200030006009F40553F05A8050218052A054B05033B059F050249024603590256036902660388028703B902B603C902C6030C080207034A0245038902860399029703080506050406821201010205040506048212000003050302020406B801A3400D000A0602010403050500010708B80121B3217B69182B2B2FD5393D2F183939123939003FFD3C3F3C3901872E2B087D10C505872E182B087D10C5313001715D0072715D290101211309010570FA8A022201328AFEDDFEDD05C2FB47037EFC8200000200AF009703C003D00006000D00C5405A3F003C013F0435063F073C083F0B350D4E014E024B064F084F094B0D0E170018061707180D670068066707680D08D500D906D507D90D04040004060407040D130013061307130D080D0C0A0B07080A0906050304000103020902B801A1B50801BD050B04B801A1401B0C050F17171A0B0809030A0CB4070D010204030305B40006190E0FB80116B3216C78182B2B4EF44D3CFD39173CDE3CFD39173C4E456544E64D00192F3C18FD3C10FD3CFD3C308710C48710C48710C48710C43130015D0072715D1301150717150125011507171501AF0156CCCCFEAA01BB0156CCCCFEAA02AA0126EEAFAEEE0125EE0126EEAFAEEE012500000200000097031103D00006000D00C140560C000C060C070C0D1C001C061C071C0D083E023C053F063E093C0C3F0D4E004E044E054E074E0B4E0C0C190017061907170D690065066907650D08D900D706D907D70D040708090A0D0C0B0A0605040300010203040BB801A1B5050CBD080209B801A1401B01080F17171A060300B402040503010D0A07B4090B0C0308190E0FB80116B3216C78182B2B4EF44D173CFD393CDE173CFD393C4E456544E64D00192F3C18FD3C10
+
+FD3CFD3C308710C48710C48710C48710C431300072715D015D09013537273501050135372735010311FEAACCCC0156FE45FEAACCCC015601BCFEDBEEAEAFEEFEDAEEFEDBEEAEAFEEFEDA000300BD00000744012A00030007000B0039401E06050A0301280807000A0D17171A0A7009A5037001A5077004190CC578182B4E10F44DFDF6FDF6FD4E456544E6003F3C3C4DFD173C313021112111211121112111211103680132FC23013204230132012AFED6012AFED6012AFED600FFFF0034000005A80763023200240000001000430B04FFFF0034000005A8074B023200240000001000D90B1FFFFF0065FFD705EA0778023200320000001000D91C1F0002004BFFDA07AF05E1000C0028007C40406613682276137922043C250102032009210C201415061C2A1919201506411003184115021D4120080C412409181D4C15202028161B4F1E161A2A09372819292AB80125B321E856182B2B4EF44DED4E10F63C4DE41112392F3CFD3C003FED3FFD3FFD3FED1112392FFD111239111239011112393931300171005D243635113426232202151412330037363332171617352111211121152111211121350E0123222726110345958880B2A8AEAFFD76B9A3FA7F5D333D03C2FD55027CFD8402ABFC3E34AC6AFCA3B9D27945028E4E72FECAD8D1FED30363F5B7301A3B61FF00FEBEF7FE80FEFC654E3DB8F501570003003FFFDC0747045A000C0033003C00924021390646158A23A615F9000504210322142113224F214F225F215F22822182220A1BB8019540353B3B250F372C1307052C33330722291E2C250B0C2C2D0B3B1F0F292F1B3F1B021BB10202301A211C3C95221F1A1A3E093630193D3EB8018CB321484E182B2B4EF44DED4E10F64DE4FDE41112392FFD5D3939E4003FED3FED39CD3F3CED3FED3912392FFD3130005D015D243635342623220706151416331216173637363332161716171615211E0133323637210E0123222726270607062322003510003300272623220706072102E676728F9D3A1F7A7796BA3D503A5F8A7FCC483A1410FD1706736A596E14011C13FFEC87643A45373D6CA0F4FEE3012AF303C71E38914233600601C4C0C495A2B9914C79ACB2039A58474E1F3266604D7B50A27F9939478DD737204640223D013EFE01110131FE8B35631D3995000001FFFB01D0047602AA0003001D400F005D03011A0500190405BF216747182B2B4EE410E6002F4DED31300321152105047BFB8502AADA00000100F101D0070E02AA00030020400A005D03011A0500190405B80187B32181E1182B2B4EE410E6002F4DED313013211521F1061DF9E302AADA0002008B039E038205D0000B00170052401710040E02040903160A4B1509CE0F03011917171A041C0AB8019DB5085A0B101C15B8019D400B145A0C191819DA216B88182B
+
+2B4EF44DEDFDE4DEEDFDE44E456544E64D003F3CFD3CFD3C11121739313001343637150607061733112125343637150607061733112102659385652314049DFEE3FE268F89662312039DFEE3047198AC1B681F512B28FEF9D396AE1B68204E292CFEF90000020097038B038B05BD000B00170059401CB70AC70A02980AA80A020C00EC170B11054B1306001917171A045A07B8019DB5006806105A14B8019D400B176811191819DA216B89182B2B4EF44DE5FDEDDEE5FDED4E456544E64D003F3CFD3CDC3CFD3C3130005D015D013637363523112115140607253637362723112115140607027467220E9C011C8B8CFE28652313039D011D8F8903F41F53212F0107D38FB51B69204E292B0107D393B21A0000010089039E01A505D0000B0032401B0204030B4B09CE03010402091A0D081C075A00190C0D70216B3C182B2B4EF44DFDE44E10F64DE4003FF4ED1239393130133436371506070617331121899187672213049CFEE4047199AB1B681E522C27FEF900010084038B01A105BD000B002B401700EC0B054B0600045A071A0D0B6805190C0D70216B3C182B2B4EF44DE54E10F64DFD003FFDDCFD313013363736272311211514060789622514039D011D938503F41F4A2C2D0107D397AE1A000003004900000484043B00030007000B003F400F0B280A0722060228000A0D17171A04B8019CB4020928010BB8019C400906190C0D6521425F182B2B4EF4F43CFD3CF44E456544E6003FFDDEFDDEED313021112111011121110111211101CE01320184FBC502B7FECE012AFED602A1FEFB0105019AFED701290000020021FFDA03EA05EF0003000700EE4016A604A906E7060317042704029900990299039C070404B801B1B612020201040704B801B1B612020203040505B801B0B612010102050605B801B0B612010100050407B801B0B612020303070607B801B0B612000303070406B801B1B612000001060706B801B1403512000003060504020600070501070302000406030B021B023B02030202010301010B0917171A008603050103078620021908425F182B4E10F41A194DFD173CFD184E456544E6003F3F12397D2F5D173C181112391239014D111239123908872E2B08872E2B0810872B0810872B08872E2B08872E2B08872E2B08872E2B3130005D01715D090703EAFE1AFE1D01E3FEFC01040107FEF902EFFCEB03150300FD00FE4201BE01A8FFFF0015FE47045005D50232005C00000010008E1408FFFF00230000054207380232003C00000010008E09080001FEA3FFDA02AA05A50003001FB41702010201B80183B6000309010203004E2FCD2FCD18003F3C4DED39015D05013301FEA30366A1FC9A2605CBFA35000002003600CA043C04D00007001F00CC404B470C470F4818481B570C570F5818581B960C960F9918991BA60C
+
+A60FA918A91B10480946124615491E580956125615591E9A09961296159C1EA909A612A615A91E101C311731161D01201AB801B2402510310B310A1106200D0F211F212F213F21CF21DF21EF21072117171A141611311017032014B801B2401B0B1C00201F1D0A31001F101F201F301FC01FD01FE01F071F192021B80118B3217F88182B2B4EF44D5DF43C10ED3939FDED3939F43C104E456544E64D5D002FED3939E4E4F4ED3939E4E43130015D005D0016323634262206263727371736321737170716140717072706222707273726014F88C48888C488D4478C8C8C73F0738C8C8C47478C8C8C73F0738C8C8C47026B8888C4888816738C8C8C47478C8C8C73F0738C8C8C47478C8C8C73000100AA0097020003D000060079402F040004061300130604D500D906021700180667006806043F003C013F0435064E014E024E0607060503040001030202B801A1B201BD04B801A14016050817171A010204030305B40006190708D0216C78182B2B4EF44D3CFD39173C4E456544E64D00192F18EDFDED308710C48710C43130005D7172015D13011507171501AA0156CCCCFEAA02AA0126EEAFAEEE012500000100AA0097020003D00006007A402F0C000B061C001C060418001706680067060435003F023C053F064E004E044E0507DA00D70602060504030001020304B801A1B205BD02B801A14016010817171A030600B40402010305190708D0216C78182B2B4EF4173C4DFD3C394E456544E64D00192F18EDFCED308710C48710C431300000725D71015D090135372735010200FEAACCCC015601BCFEDBEEAEAFEEFEDA000003001C0000045705D1000300070020006A40414C024C034D0E5C025C035D0E060B1F0E240A1F200103B10000040614195C1B120616070A2217171A051F01270700148A0A161127171F1C9219192122A9216045182B2B4EF44DF4E4FD3CD4E4DE3CFDE44E456544E64D003F3C3F3CFD3C3F3FED3FE4FDE43130005D0121112115211121001617152E0123220617153315231121112335333534373633033B0117FEE9011CFEE4FEFD361D14261B431E02BBBBFEE49F9C4D45D405CBFEFC8AFBC305D10402E801014A4F14C9FC91036FC946AE5550000002001C0000045705D10003001C0063403A4F0A5F0A020724061F0A241C011C240A1F07240601000114115C170E0612030A1E17171A012700108A06120D27131F189215191D1EA9216045182B2B4EF44DF4E4FD3CD4E4DEFD4E456544E64D003F3C3F3CFD3C3F3FFDF4ED3FEDF4FD3130005D01211121001617152E0123220617153315231121112335333534373633033B011CFEE4FEFD361D14261B431E02BBBBFEE49F9C4D45D405C2FA3E05D10402E801014A4F14C9FC91036FC946AE55500000010047FE8E042505A500130055B60BD3080D35070EB8016840
+
+25120411350312D300001517171A07037106010A4C0F000B71119F0D010D191415DC216A7A182B2B4EF45D3C4DF43C3CFD3C3CF43C4E456544E6003F4DF43CFD3C10F43CFD3CE43130012111211521112115051121112135211121352101AD010E016AFE96016AFE96FEF2FE9A0166FE9A016605A5FE53E3FE0EDF02FE4C01B6E101F0E300010071022801C00374000B0025401208D0020D17171A0BD005190C0DD0219088182B2B4EF44DFD4E456544E6002F4DED313000062322263534363332161501C0624545636244456402896161454462614500010092FEAF01B40121000D003FB6D700E70002000DB8014D400B0528040A0F17171A035A07B8019D400B0D6804190E0F70216B3C182B2B4EF44DE5FDED4E456544E64D003FEDEC393130005D173E0135231121150607060706079754449D0122011726502F60E41C5E6A0121ED744063341E1C00020092FEAF03740121000D001B00584009D700E700020E001B0DB8014D400E0314062813030A1D17171A125A16B8019DB51B6814035A07B8019D400B0D6804191C1DA6216B3C182B2B4EF44DE5FDEDDEE5FDED4E456544E64D003F3CFD3C10FC3C39393130005D173E01352311211506070607060725363736352311211506070E01079754449D0122011726502F6001C06322139D01220414188B62E41C5E6A0121ED744063341E1C6D1C4D2C4F0121ED7C3D4671150000070004FFD2080205DA000B000F001B00270033003F004B00AD40100D0E0E91120F0F0C0F18020C363C2739BB019F002A004801B5B242213FB8019FB530420E0F0D05BC019F001501B5000B019F400A1B100D0C114D17171A244113019F002D01B5001E019F00330036019F004B01B5003C019F00450008019F001201B50002019FB318194C4DB8018FB3216747182B2B4EF44DEDF5ED2F18EDF5EDD6EDF5ED4E456544E64D003F3CF4EDF5ED3F3C2F3CFD3C10F53CFD3C01111239111239872E2B7D10C53130000615141633323635342623253301230016151406232226353436330006151416333236353426232436333216151406232226350436353426232206151416330406232226353436333216150119494A3434494934029593FCBE930135C1C08989C1C2880536494934344A4A34FEB7C18889C1C18988C1FE964B4B3434484834014BC18988C1C18889C105024A3434494934344AD8FA0005F4C18988C1C18889C1FBCB4835344A4A3435480CC0C18888C2C2887E4A3435484835344A0AC2C28889C0C18800FFFF0034000005A80763023200240000001000D80B07FFFF00A5000005020763023200280000001000D80C07FFFF0034000005A807630232002400000010008D0B04FFFF00A50000050207380232002800000010008E0C08FFFF00A5000005020763023200280000001000430C04FFFF0074
+
+0000027207800032002C00000010008D0404FFFFFFB20000028707800032002C0000001000D80407FFFFFFD20000026707550032002C00000010008E0408FFFFFFC9000001C607800032002C0000001000430404FFFF0065FFD705EA07900232003200000010008D1C04FFFF0065FFD705EA0790023200320000001000D81C0700020000FFD10595067C0021002E002B401317141A2105022B2E242B2B101E090D10301E2F10D410D6DCD41112392FD4002FDDDEDCD42FC4DC313000163332363332171617060706151416170607062322262322062322030235341233001615140607060706073E013701E2D5232DCC4B7B6036355025438E5B2658858334B73F3FA7349D9797E7B0027A023C4138372347029BB304F23E46422641443560747FCC1B7B86C94245010A0107FDEB0128017D140A40984137130B0698DE29FFFF0065FFD705EA0790023200320000001000431C04FFFF009CFFDA053D07630232003800000010008D1604FFFF009CFFDA053D0763023200380000001000D81607FFFF009CFFDA053D076302320038000000100043160400020089000001AA045F00030004002B4016040006030A040617171A04022700190506B2215045182B2B4EF44DFD394E456544E62F003F3F3C31301321112113890121FEDF910442FBBE045F0002FFB6045F028B0600000600070061403B1A011603290126033A013603069506A606020B050B061C021B051B0605020503000707030504010600020702070204001A0904190809A6217B69182B2B4EE410E6184D1139393D2F182F11123939123939003FDE3CDC39013130005D01715D0123270723132103028BE88283E8EB01008004D5A8A8012BFE5F000002FFA8045F029705E8001E001F0077402A0502350F02F402013E06301502370CF802F80BFA11F51C050802080B0A11051C160C250C06153B1E340AB801A0402219063B0D34191F071F120F0402041909391F1A0A1A211C19391A192021DA21E269182B2B4EF44DED394E10F611394DE51117392F003FDEF4FD10FDF5FD313001715D00725D7112161F011E0133323637330E01232227262F012E012322070607233637363313BA34125E2A1A1030270985126B671F39211E511120102618180A821623407E8105DE0C07230E083323698E0F080A1B060516172867355FFE810001FFBD0515028405AD00030022B900000167400D03011A0500190405A6217B69182B2B4EF44D104EE64D002FFD3130032115214302C7FD3905AD980002FFC9045F027B0600000F0010005840269B00AA00B800030F050F060F0E0F0F1F051F0F0609090E0628021007101217171A10050F390EB80161B5063905191112B80112B3216769182B2B4EF44DEDF4FD11394E456544E62F003FDE4DFD3C392F3130005D015D0006232226273316171633323736
+
+373301026EB29A9AB20D870E522E44442E520E87FEA705679191995C211313215CFE5F000002009A045F019E05D500030004002F401400CA030407040617171A0401CD00190506CD2181B9012800182B2B4EF44DFD394E456544E62F003FDE4DED313013211521179A0104FEFC8205D5ED8900030042045F01F6067D000B001700180043B20EEB08B801A1400F02EB141807181A17171A181711EB05B801A1B50BEB1719191AB80104B3217F88182B2B4EF44DEDFCFD11394E456544E62F003FDE4DEDFCFD313012163332363534262322061526363332161514062322263513A5463131454531314663805A5A80805A5A80DA0572454531314646315A80805A5A80805AFEBC00010012FE2901F60000001E007540430B171C170224103310431053108F11052B173B174B175B1704090A17140EEC051B1814AE1E3D190A2017171A020A1718191B05091A6F11014F115F1102116D02091F20BC013400210149012700182B2B2FD5ED5D7139111739104E456544E6003F4DF4ED3939DCFD1139D4DD3130005D01715D041615140623222726273716171633323635342623220607273733073E013301966096763348213C263915301E3C343A2113281981CF6D58211C10774F4A5C6B150A165611050C331C2A220908756F830705000002FFD304DC0342060000030007003A401B3F003F013E023D030405032804000303B83001010104B806190809BC011800210042014200182B2B4EF44DFDD45DED003F3CFD3C3130015D0121032313032313021F0123F4C401F4C4950600FEDC0124FEDC012400010042FE2901F6000000160052401319011A1429012A1439013A14060A160B0F3B07B8014CB7160A0B1817171A00B80194400B1604C812A116191718C421B80151B13C182B2B4EF44DF4ED10FD4E456544E64DC4003FF4ED3912393130015D21070E011514163332363715060706232226353437363701E8434542423116301F2D1E3644698654316D3032482C2E350C0B9011070D75515B4D2D3C0002FFB6045F028B06000006000700AF408A2602290436023904490046065900560669006606A602A904B602B904C602C9041026022A043602390447024904880087069706A706B702B804C702C8040E090007061A0016062900270699009606AA00A606B800B6060C04030C011C014C015F016C017C018C010701000707070002010406050307030112052205320503051A0901190809A6217B69182B2B4EF410F45D1139393D2F181239391239392F003FDE4DDD5D393C0131300172715D1303331737330307A1EBE88382E8EA8004D5012BA9A9FED5760001FFF1000004AA05C2000D009D4138000500080004000900040002000B0003000A0003000A000A01A600120004000900090004000200030004000500080009000A000B000800010006
+
+0002000C004C00010008000D001A000F0008000B0009000A000B0025000500020004000300020019000E000F011C0021005200AB00182B2B4EF4DC3C103C4DFDDC3C103C4E10E6003F4DFD3F121739192F2F18872B107DD4073C3C10073C3C3130290111073537112111251505112104AAFBF2ABAB01340130FED002DA02366DC26902CEFDEBB6BBB7FE18000001FFE80000024B05C2000B009B4137000500080004000900040002000B0003000A0003000A000A002F00120004000900090004000200030004000500080009000A000B000800010006000200010008000D00170017001A000B000A00090008000B0025000200040003000500020019000C000D014B00210135007900182B2B4EF44D3CD43C10FD3CD43C104E456544E6003F3F121739192F2F18872B107DD4073C3C10073C3C313029011107353711211137150701A8FEE3A3A3011DA3A3023868B26802D8FDD868B06800FFFF0055FFDA050E0790023200360000001000E12F07FFFF0042FFDB04250600023200560000001000E12C07FFFF0034000004AF07630232003D0000001000E10A07FFFF0021000003CE06000232005D0000001000E10A070002006A0000017105D00003000700484119000001B600010000000601B60005000A000900170017001A0003000400220000000500190008000900CD0021006C003C00182B2B4EF43C4DFD3C4E456544E6003FFD3FFD313013112119012111216A0107FEF9010703870249FDB7FC79024B00000200120000057B05C000110022006A412500100017002A000D001A001A0015001C0000002A0015000B002A001C000200150008000700370022001A0024000E000D001000250018001A0017001900230024012000210052005600182B2B4EF44D3CC4FD3CC44E10F64DED003F3FED10ED1112392F3CFD3C313001323736373E01351027262B01112111211124070229011123113311213216171E0115029C7D36593B36299654AEE30136FECA03B4639FFE89FD9A8A8A0268ABF158434001001019544DD3520130693AFED0FF00FE6EFAC2FEC802920100022E677A5DEE90000002006DFFE3048B05CB0022002E00CB414A000500FA0012001200050012000800FA0012000F0008000F000F00080007000F00120007001000120005000600110006000700060011001101AA00120007001000100005000600070008000F0010001100120008000C00020025002000220022001C000C0010002B005D001C000B002E00820019001A003000060007000700280082001F0019002F0030017600210048004E00182B2B4EF44DED392F334E10F64DED003FED3F12392FED391217392F072B107D08C418070E3C3C07082E3C3C060E2E2B060E2E2B31300016172E01270727372E0127371E0117371707161716171E0115140023220035340033
+
+002623220615141633323635025B35324D3D36DD66E2371F28EB212F2EB666B2712B44295339FEEFF6FFFEE80109BF013C70806F878B67757F03EF060D543B2F646763271C20681623234F674976334F458DDB74E1FECF012AE6DE011EFE81B2999C9894A696FFFF00230000054207630232003C00000010008D0904FFFF0015FE47045006000232005C00000010008D1404000200A50000049505C0000D00180050411C00130024000B00120024000200000000000C0008001800360006001A001A0012000C00010025000000190019001A01740021009501B700182B2B4EF44DFD3C3C4E10F64DFD003F3FDDEDDDFD3130132115332004151007062B0111210027262B01113332373635A5012BC001000105E279C9A1FED502CA5F367C8E7E7C3B6A05C0DDE4C1FEDC6B39FE8A03B22A18FE6F1A2F880000020080FE55049C05C0000C001E003B40210E062411070D001B0C24170B1C0E0336141A20091F0E1B271D191F209821504E182B2B4EF44DFD3CE44E10F64DED003F3FFD393F3FFD3931302437363534262322061514163303113E0133321211140223222726271121110322391E8274618D7A79EC339B66D2FAEBDD573B6640FEE4D1964E7492A89AAA9CB204EFFDEF5957FEE5FEE4F5FEB017276FFDC5076B00010049019C048402A10003001F4010022203011A050219040405A9216A46182B2B4E10F410F64D002FFD3130011121110484FBC502A1FEFB01050000010055000B0478042F000B006740340805090904020B0A0A0302050606010B08070700040304090922120A090A0A03060607010122120000010700000A040601030907192F183CD53C00192F3C18D53C313087082E2B1008C487082E2B1008C4070E103C3C070E103C3C070E103C3C070E103C3C01170901070901270901370103C0B8FEA6015AB8FEA5FEA9B90158FEA8B90157042FB9FEA8FEA9BC015AFEA6BC01570158B9FEA80000010050024401F605AA000B0026410C000000010001000A0198000700050007000B0195000900002FDDFD39003FFD392FCD303113353E01373E013533112311506E3E161D23A4C7049C74051211153B22FC9A0258000001001A0244029E05B4001D003841130016019700170198000201970006000A0005001D019500160015000D001800060194000700182FD5ED10DD393CED003FCDEDFDED303100262322070607233E013332161514060F010607060721152134373E013501E1463A561D1202B503A49287B95C6B492C1A370D019AFD7CE48E5504E24135204E9C9894825387452D1C1428199DCD9A605F3A000100120236029E05B4002B0054411D0022000C000D002B00040196000D00280198001401960018001C0005000C00110195001F00080195000C0025002B00170194001800000194002B2FEDD5ED10DD39EDD4ED
+
+2F003FCDEDFD39EDCD2FDD39303113161716333237363534272627353637363534262322061523263736333216151406071E0115140623222635C90412215725224040276C59243F46343C41AB05634B878AA33E343757B98199B90355401E37122253521B110479020F1B4D36394F3F87553C836A41551A085E6286938798000003002FFFDA065505AA0003000F00300081412D00010091000000020091000300000002000300010000001700120197001B019800280197002B0008000400050005000E01980000000B00050030019500290028001E002B001601940017002B00000003000B000F0195000C00042FDDFD39D4C42FD5ED10DD393CED003FC4FD392FCD3FEDFDEDCD103C2F3C8705ED10ED30310133012303353E01373E01353311231100262322070607233437363332161514060F010E01070E010721152136373E01350482A1FC95A1E86F45162018A4C70489423F561D1102B458548D91AF65604C181C18122308019AFD7B03E39A4705A5FA3504C274051612184213FC9A0258FDFB47381F4C90574D9D78588A3B2F0F14110E210F9CD1976B5339000004005AFFDA065E05AA000A000D0011001B00924132000F0091000E001000910011000E00100011000F000E0006000C0007000D0001000501970009000D000D0007019800020008001200130013001A0198000E00170005000D00070005000C000301950000000900020005000E00110017001A0195001900122FDDFD39D4D42FD53CC4FD3C113939003FC4FD392FCD3FFD392F3CFD3C11123939103C2F3C8705ED10ED303125231523352135013311332111031333012301353637363533112311065E61BDFE89015CD861FEE2EE8AA1FC95A1FEE971345DA4C8BBBBBB95020EFDE20174FE8C0465FA3504C2740614245CFC9A02580004004EFFDA068E05B4002D0038003B003F00C04143003D0091003C003E0091003F003C003E003F003D003C003A0034003B0035002F003301970037003B003B00350198003000080023000C000D002D00040196000D00280198001401960018003C001C0005003C003F003B003A00340032003A019500380037002F0034000C00110195001F00080195000C0025002D00180194001900000194002D2FEDD5ED10DD39EDD4ED2F2FD53CC4FD3C1139392FC4003FC4CDEDFD39EDCD2FDD393FFD392F3CFD3C11123939103C2F3C8705ED10ED30310116171633323736353427262735363736353426232207060723263736333216151406073616151406232227262701231523352135013311332111031333012301040313215728223E42276A5A243E3E3D4C1E1003AA056C4B7D8CA1383A1F70B586CF502B07064061BEFE89015DD861FEE1ED9CA2FC9AA203553A203B132254501C10047902101B502843361F39925234846542551D026B
+
+637D986F3D73FD66BBBB95020EFDE20174FE8C0465FA3500000100000000045E05970011006B4126000C0008002A000F00070005002A00020001002A00070002000A00100004000A0008000300760000001A0013000700060002000A00B3000D000F000B001900120013011C0021005200AB00182B2B4EF43CC44DFD3C3CC410F6E4003F3F123939ED2FFD2F3CFD3C3130012111211521152115211521352335331121045EFD620240FDC00136FECAFEE8A8A803B60497FEE4FBD8DFC9C9DF03EF00FFFF0055FFD905AF07890232002A0000001000DB2310FFFF0042FE42045E06000232004A0000001000DB3010FFFF0084000001B607550232002C0000001000DC040400010055FE29050E05ED004B00B24141000D00000010000A00210017001E0024001600080031003800380029002A0048004900050027004B00210024000A000D00040017004B00D4002A001700D4001B00410013000300040041002A000900480009001700960016004F000800960027001A004D001E00360010005700000036004B0019004C004D011E002100AD005600182B2B4EF44DEDF4ED4E10F64DEDF4ED003F3FED3FEDED10ED11173901111217392FDD11123911123939111239313001161716333237363534262F012627263534002132041721262726232206151417161F0116171615140021073E01333216151406232227262737161716333236353426232206072737220035017B0E294BB66D448180899CE6589501200117E9014908FED8086C486B778E462D93FEA75584FECBFEEB3E211C10516096763348213C263915301E3C343A211328192B63BCFEB601C765325B182E7D494F1E23343D66D9C60106F7EB85382560564F271A233D284368C5CAFEF55D07054F4A5C6B150A165611050C331C2A22090828960107E600010042FE290425046100440068403C1D1E0A090414442314182C1007042C230B410B2A3131414222230520440A1E1B144D2207132D074D201A460B001B4D0D2D004D441945468721484E182B2B4EF44DEDF4ED12394E10F64DEDF41139ED113939111217392FDD003F3FED3FEDCD10CD111739313001161716333236353426252E013534363332041721262726232206151416170415140623073E013332161514062322272627371617163332363534262322060727372226350163091E358F546350FEFFB998EDD7CC010113FEE306192F715D4F54FF0153F1E040211C10516096763348213C263915301E3C343A211328192B61B0F5015C4C2039323230323D2E898097D9A3C837203A3A27312D3851F5A2CD5E07054F4A5C6B150A165611050C331C2A2209082897D9A800FFFF005CFFD7057B07900232002600000010008D1F04FFFF0047FFDA043406000232004600000010008D1E04FFFF005CFFD7057B0790023200260000
+
+001000E11F07FFFF0047FFDA04340600023200460000001000E11E070002003FFFDE04E405C0001800250050402C0B04090505180700021F2418070E0A0F2524120B1B1F0F1F050603270A090C1A2722361519262798214845182B2B4EF44DED4E10F63C4DC4FD3CC4F4E4003FFD393F3FFD393F12392F3CDD3C3130001617352135213521153315231121350E012322003510003312363534272623220615141633027A9A30FED9012701217F7FFEEB3D9C74BFFEFB0101D7B77E653E527D757779045C574DFD98737398FB4B9761580135F201170140FC72B48FC85634BD8C97B5000000010000000100000F3018F15F0F3CF50000080000000000A2272E8000000000A3C1D703FEA3FE25080207E0000100090001000100000000000100000629FE2900000800FEA3FEAC080200010000000000000000000000000000010205C7009A00000000023900000239000002AA00E103CB00A70473000004730038071D002F05C7006F01E7007302AA004602AA0015031D002F04AC00390239007602AA002F023900800239FF90047300400473008E047300400473003604730036047300360473004004730034047300360473003D02AA00E802AA00E804AC000704AC003904AC000704E3007B07CD00C905C7003405C700A105C7005C05C7009C055600A504E3009C0639005505C7009A023900840473002D05C700A104E3009C06AA009705C7009706390065055600A30639006505C700A30556005504E3002105C7009C0556002F078D001E055600210556002304E3003402AA00800239FF9002AA002F04AC007B0473000002AA00070473003B04E3007B0473004704E3003F0473002F02AA001504E3004204E300870239008902390009047300820239008B071D008004E3008704E3004204E3007D04E3003C031D00820473004202AA001504E3007D0473001A0639000E0473001A0473001504000021031D0039023D00A5031D006604ACFFF405C7003405C7003405C7005C055600A505C700970639006505C7009C0473003B0473003B0473003B0473003B0473003B0473003B047300470473002F0473002F0473002F0473002F023900760239FFCE0239FFB60239FFD504E3008704E3004204E3004204E3004204E3004204E3004204E3007D04E3007D04E3007D04E3007D047300470333005E04730045047300420473004102CD00890473000004E3008905E5001A05E5001A080000BF02AA00AF02AA000E04640015080000120639004705B400220464001504640013046400150473FFEA049CFFA703F4FFE505B40087069600750464FFF10231FF5602F6002802EC000D06250027071D003804E3002A04E3006D02AA00E104AC00390464FFD50473001E0464001504E5FFED047300AF047300AF080000BD0239000005C7003405C7003406390065
+
+0800004B078D003F0473FFFB080000F10400008B0400009702390089023900840464001503F4000F04730015055600230156FEA30473003402AA00AA02AA00AA04E3001C04E3001C047300470239007102390084040000920800000405C70034055600A505C70034055600A5055600A5023900760239FFB60239FFD50239FFCE0639006506390065065200690639006505C7009C05C7009C05C7009C0239008902AAFFEF02AAFFE102AAFFF602AA000202AA00D302AA007B02AA004B02AA000C02AA007B02AAFFEF04E3FFF10239FFED055600550473004204E3003404000021023D00A505C7001204E3006D0556002304730015055600A504E3008004AC003904AC004502AA005002AA001A02AA001206AC002F06AC005A06AC004E047300000639005504E3004202390084055600550473004205C7005C0473004705C7005C0473004704E3003F0000000000000066000000660000006600000066000000DA000001400000035000000490000006300000088C000008D600000966000009E600000AF800000B6600000BD600000C1200000C5400000CCA00000D9C00000E0400000EFA00001002000010CE0000119A0000129A0000131A0000140E000014F400001550000015E600001676000016CE000017660000183400001A0E00001B2A00001C0E00001CF200001D9C00001E2A00001E8E00001F9000001FF600002046000020C0000021A8000021F2000022FE0000238E0000243A000024C400002616000026F600002836000028960000291C000029BE00002B7C00002CC000002D9E00002E4600002EAA00002F1600002F7C0000302600003058000030AC000031F2000032A00000337A0000342E000035540000362000003712000037A40000380C000038A6000039D200003A1200003B6200003C0000003CAC00003D6600003E1E00003EB000003FBC00004050000040F8000041C00000448C000045CC000046FC000047C20000489C000048DE000049BC00004A6A00004A8000004A9600004BBE00004BD400004BEA00004C0000004C1600004C2C00004C4200004C5800004C6E00004C8400004C9A00004DD400004DEA00004E0000004E1600004E2C00004E4200004E5800004E6E00004E8400004E9A00004EB000004EC600004EDC00004EF200004F0800004F1E00004F3400004F4A00004F6000004FD800005048000051D80000535A000054D00000552C000055A8000056B20000590E00005ADA00005BDA00005C3200005C9600005D7400005E5400005FCA000060CC0000614C000061EC0000628E000063C0000064D0000065BA00006672000066DA0000673C000067F400006934000069CC00006A9000006C2200006D8600006E5600006ECA00006F1000006FEE000070F00000723600007302000074080000750A0000757A0000757A
+
+00007590000075A6000075BC000076BA0000780A000078420000787C00007924000079D200007A3400007A9000007B0A00007C2A00007C4000007C5600007C9400007DCC00007E6C00007F0E00007FE4000080A600008144000081960000820A000082C20000844E000084640000847A00008490000084A6000084BC000084D2000084E8000084FE000085140000852A00008540000085FE000086140000862A0000864000008656000086A20000872E0000880E0000884A000088E400008932000089C600008A9C00008B0200008B9E00008C7600008D4C00008E1800008E2E00008E4400008E5A00008E7000008EE200008FC2000091260000913C00009152000091F800009298000092D40000937E000093D40000946C000095400000965E00009754000098D80000998200009998000099AE000099C400009B5600009C8400009C9A00009CB000009CC600009CDC00009DA200010000010200500007005B00060002001000100037000007E8028C00060001B10840BA019000145DF44009011F04000B1FD819EEBE012E000D00E6012E000D00B0012E400C0D000963833C1F63838348294109014B00370401001F014500240401001F0144B224AB1FB8013EB224231FB8013DB224231FB80102B2371D1FB80100400937241FFD37621FFC37B80801401B1FF824931FF724931FF6243F1FF524311FD1371D1FD037471FCD41B80801B21FCB2AB80201B21FCA24B80401400F1FC824811FB537291FB4373B1FB227B80401B21FB141B80401B61FA437811FA384B80401B21FA22AB80401B21FA124B8019AB21FA024B8019AB61F9F243F1F9683B80401B21F9527B80401B21F8227B80401B21F7084B80801B21F6FB3B80801B21F6EB3B802ABB61F6D24261F6224B80101400B1F5D246C1F5C24391F5441B80125B21F4D27B80401B61F4C27CD1F4B41B80401B21F4024B8019AB21F3683B80401B21F3524B80201B21F3224B8019AB61F2C24BB1F2884B80801B21F2241B8040140131F20244C1F1D24261F2CA0961F2C245E1F412AB801A8B748282A2448279636B801F4B21F4D27B801F4B21F9527B801F4B21F6E27B801F4B21F6327BD01A700470029015A00250199B348296FB3B80190B21F83B3B8019AB348283725B803E840121FB327482784274827362748272527482755B80154402C0797076407550733072B072907260721071E071B071408120810080E080C080A080808060804080208000814B8FFE0402B00000100140610000001000604000001000410000001001002000001000200000001000002010802004A00B806008516763F183F123E113946443E113946443E113946443E113946443E11394660443E11394660442B2B2B2B2B2B2B2B2B2B2B182B2B2B2B2B2B2B2B2B2B2B18011DB0964B5358B0AA1D59B0324B5358B0FF
+
+1D592B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B65422B2B2B4B5279B35279EB56456523456023456560234560B08B766818B080622020B1EB794565234520B003266062636820B003266165B079236544B0EB234420B152564565234520B003266062636820B003266165B056236544B0522344B10056455458B156406544B25240524523614459B35045484E456523456023456560234560B089766818B080622020B148454565234520B003266062636820B003266165B045236544B048234420B1504E4565234520B003266062636820B003266165B04E236544B0502344B1004E455458B14E406544B250405045236144592B2B4569534200
+
+00>]def
+
+/CharStrings 258 dict dup begin
+
+/.notdef 0 def/.null 1 def/nonmarkingreturn 2 def/space 3 def/exclam 4 def/quotedbl 5 def/numbersign 6 def
+
+/dollar 7 def/percent 8 def/ampersand 9 def/quotesingle 10 def/parenleft 11 def/parenright 12 def/asterisk 13 def/plus 14 def
+
+/comma 15 def/hyphen 16 def/period 17 def/slash 18 def/zero 19 def/one 20 def/two 21 def/three 22 def
+
+/four 23 def/five 24 def/six 25 def/seven 26 def/eight 27 def/nine 28 def/colon 29 def/semicolon 30 def
+
+/less 31 def/equal 32 def/greater 33 def/question 34 def/at 35 def/A 36 def/B 37 def/C 38 def
+
+/D 39 def/E 40 def/F 41 def/G 42 def/H 43 def/I 44 def/J 45 def/K 46 def
+
+/L 47 def/M 48 def/N 49 def/O 50 def/P 51 def/Q 52 def/R 53 def/S 54 def
+
+/T 55 def/U 56 def/V 57 def/W 58 def/X 59 def/Y 60 def/Z 61 def/bracketleft 62 def
+
+/backslash 63 def/bracketright 64 def/asciicircum 65 def/underscore 66 def/grave 67 def/a 68 def/b 69 def/c 70 def
+
+/d 71 def/e 72 def/f 73 def/g 74 def/h 75 def/i 76 def/j 77 def/k 78 def
+
+/l 79 def/m 80 def/n 81 def/o 82 def/p 83 def/q 84 def/r 85 def/s 86 def
+
+/t 87 def/u 88 def/v 89 def/w 90 def/x 91 def/y 92 def/z 93 def/braceleft 94 def
+
+/bar 95 def/braceright 96 def/asciitilde 97 def/Adieresis 98 def/Aring 99 def/Ccedilla 100 def/Eacute 101 def/Ntilde 102 def
+
+/Odieresis 103 def/Udieresis 104 def/aacute 105 def/agrave 106 def/acircumflex 107 def/adieresis 108 def/atilde 109 def/aring 110 def
+
+/ccedilla 111 def/eacute 112 def/egrave 113 def/ecircumflex 114 def/edieresis 115 def/iacute 116 def/igrave 117 def/icircumflex 118 def
+
+/idieresis 119 def/ntilde 120 def/oacute 121 def/ograve 122 def/ocircumflex 123 def/odieresis 124 def/otilde 125 def/uacute 126 def
+
+/ugrave 127 def/ucircumflex 128 def/udieresis 129 def/dagger 130 def/degree 131 def/cent 132 def/sterling 133 def/section 134 def
+
+/bullet 135 def/paragraph 136 def/germandbls 137 def/registered 138 def/copyright 139 def/trademark 140 def/acute 141 def/dieresis 142 def
+
+/notequal 143 def/AE 144 def/Oslash 145 def/infinity 146 def/plusminus 147 def/lessequal 148 def/greaterequal 149 def/yen 150 def
+
+/mu 151 def/partialdiff 152 def/summation 153 def/product 154 def/pi 155 def/integral 156 def/ordfeminine 157 def/ordmasculine 158 def
+
+/Omega 159 def/ae 160 def/oslash 161 def/questiondown 162 def/exclamdown 163 def/logicalnot 164 def/radical 165 def/florin 166 def
+
+/approxequal 167 def/Delta 168 def/guillemotleft 169 def/guillemotright 170 def/ellipsis 171 def/nobreakspace 172 def/Agrave 173 def/Atilde 174 def
+
+/Otilde 175 def/OE 176 def/oe 177 def/endash 178 def/emdash 179 def/quotedblleft 180 def/quotedblright 181 def/quoteleft 182 def
+
+/quoteright 183 def/divide 184 def/lozenge 185 def/ydieresis 186 def/Ydieresis 187 def/fraction 188 def/currency 189 def/guilsinglleft 190 def
+
+/guilsinglright 191 def/fi 192 def/fl 193 def/daggerdbl 194 def/periodcentered 195 def/quotesinglbase 196 def/quotedblbase 197 def/perthousand 198 def
+
+/Acircumflex 199 def/Ecircumflex 200 def/Aacute 201 def/Edieresis 202 def/Egrave 203 def/Iacute 204 def/Icircumflex 205 def/Idieresis 206 def
+
+/Igrave 207 def/Oacute 208 def/Ocircumflex 209 def/apple 210 def/Ograve 211 def/Uacute 212 def/Ucircumflex 213 def/Ugrave 214 def
+
+/dotlessi 215 def/circumflex 216 def/tilde 217 def/macron 218 def/breve 219 def/dotaccent 220 def/ring 221 def/cedilla 222 def
+
+/hungarumlaut 223 def/ogonek 224 def/caron 225 def/Lslash 226 def/lslash 227 def/Scaron 228 def/scaron 229 def/Zcaron 230 def
+
+/zcaron 231 def/brokenbar 232 def/Eth 233 def/eth 234 def/Yacute 235 def/yacute 236 def/Thorn 237 def/thorn 238 def
+
+/minus 239 def/multiply 240 def/onesuperior 241 def/twosuperior 242 def/threesuperior 243 def/onehalf 244 def/onequarter 245 def/threequarters 246 def
+
+/franc 247 def/Gbreve 248 def/gbreve 249 def/Idot 250 def/Scedilla 251 def/scedilla 252 def/Cacute 253 def/cacute 254 def
+
+/Ccaron 255 def/ccaron 256 def/dmacron 257 def end readonly def
+ %endsfnt
+
+%beginsfntBC
+truedictknown type42known not and ( %endsfntBC)exch fcheckload
+/TrueState 271 string def
+TrueDict begin sfnts save 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt cvi 0 72 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt cvi 3 -1 roll restore TrueState initer end
+/BuildChar{exch begin Encoding 1 index get CharStrings dup 2 index known{exch}{exch pop /.notdef}ifelse get dup xcheck{currentdict systemdict begin begin exec end end}{exch pop TrueDict begin /bander load cvlit exch TrueState render end}ifelse end} bind def
+
+ %endsfntBC
+
+%beginsfntdef
+truedictknown type42known or( %endsfntdef)exch fcheckload
+currentdict dup/FontName get exch definefont pop
+ %endsfntdef
+
+%beginType1
+truedictknown type42known or not( %endType1)exch fcheckload
+/FontMatrix [1 2048 div 0 0 1 2048 div 0 0] def
+
+/FontBBox{-349 -475 2050 2016}def
+/FontType 1 def
+/UniqueID 16#00496671 def
+currentdict
+currentfile eexec
+
+DB68F4C27EB05F612E927AFBBE3B7781387A059133813066E91F8896AA45FC11450185B75D385F363CDD5CDA321F078968A21130B16A5299ACB19093D0E69761C78A5015087D1DE5781EF1E7532403C7869DB26CF29663AC240C5DB8BE3571E4D8F5C6E563FDA0A2D4874925D61F3E509863621FA9D4EC7BC0B238D5FF70B95A107DFBEA2B84123F76D9D2C183958A57586C3DB9316F12FB93199322E1C02F3F3C03AD1DC2DE6BF33393260E4D57574EDD3FF55AF4AAB8B3BC398C058027D3AE8236170EEF7F473B055F36F5431A821E60FA50BC03497941D0495335BF2ADD4600DBBB53E9111A49F6A4409C7D59F4CB56E7EBA0CD9903F8CC2420DC01FD7DAAC17FDE5A748A5125CF878F95A30D43B511EA754D036B8B0EC28C1664C5877F732BFCA897B2E1D0B55D2B6ABBE3C6354EB67132D7EFEA9226B02A35F57048666806D2CB1EBC26122E2EF770AF797EE2D4DDB8CE5AB16E65B8B4C496B4FA5746AB044A00A257B93BC4E7356E0B0DDEB18C2E9FE710633F2B04A0BE479C0D433B17B3E545241919C1D873D3E64C58FB9679D6BF6108B871D47FB5522DCEBA52B9DD880C00B004A66D2F4A91A76FE083E6C3CCBA115B7A9E367E35BD187435F2DA4A11677A5DBB3932178938906FC2EDD30D922D18A4596EA41DEC9B0E229236194C3DE0591469CBBADD63BB24288EA3B9A11961C280AFFF833C2479B1113D1457145B41363C27DE0580E2CD2AF03282EA030FFBA08F4236B8A76D1C37A692F5E4E3CA6BFCCC281B65F1140C63C8D55E809F88D6CE2C9B183A12EBA85D0ACCEBAC4C575A2D09575B53266747E5068CF74B4241B5A8176BD1E516F4C023EA7A74CC720DAC1F293AF29B6E8F91C52007510523CFDCDA5964AF507A16EE93897AC496AF8D7FCB35B3B52F04F90D680DDC5CC3A68B8595D7531915DDBB0A983AD79E49AA2FB0B3095475E179C9CD0B540287D8581F70936FC06001AB18FB6209A5CA2D9781B6E1B837F41C7F8A47E70C65F94950F68E2A801CC650521846F1ED6BC3A9A8D6EF51711BDA96F07496D20DEE9526E6AAAB3C186FE35D7EC13887C96866FC856D537BEC467D5AE0614631398F84BF67CFF790598EC26628237AE2C72C16E0BB0C2517B65F0DC1C6F58D1DF23DC7532A83C2EAF06236431BD63A852BAB999DEBFCAEED13CD8752F09E977DFE5F3867809B6CAC3DD081A2C344051F3D10C7BF6C26F06D61CDB11CFA5FBD355C59D00D9126EF6A71D1013E9EA60EB82D58B9FF524E0C5B81F25C2C37DD6F00E547707304F934174EFA234E448859AC11734A1E6667A76F5BA98EF37A6DC9CA7536C81268E870949928F5D01705C3D73B825F2BD5AE98BC62D0BD52061F8F59DC742BDB1A33E35BA63043938D6D0DEF55ABFA3ADDCE87287EC2710E57179D29F30436D8B666DBD7E6EB1FA84B144C586EFF93F56D
+0237B25C6E3ACC2B7D6AD6DEE4719B34A8C8FB817C7C01A6FB148FB986439DAAF57CC74AD112BE6125605A0A130696D2AEE09F75ED54DD3FE8D9275B3AD15FB14C839D2109D2BF374F6C5A1B6143C61F81137266DBCC327A127DEC657E0F875F434317B46AFD6499D6947AC410E2DAFC27A7BFDA3F41FD0A5DD89136443884B219423D38855C9D7C766BBBCBAA86FE75680B2BD7BD026A21EB65F1897BF26EBBC2160D10FC09107C0CAC49F4E491C85372392EC80618E665D8A1767FD55BF8EF63B141557EC10E8A7D6C2DCC02E84D64742CE2549843D0E7FC209EFAA47BF0AF35C45731FBFC2F984810615861CB0823D0C3FAA68F61EF10FCEF8D3FA517370C5105CA1D6B94D9C3C14C72C735185B3F399C9C81DD8F9FB2EBD50CA7682FD7FDAAC198AB98F1B0CCE5FBAF962D37CE089A5DDEEBC0B96BD60359E4F47F4097BEF039F541D2FA7529779D56304CA37AEDF1A4D806FE1098F8184C23D68A8D8A3FCE1036C8CCB068F712E2004EFC540A42208418867521694045087D6C39060CF04559C4504E4729E749610B049EE4E5410492A3A0320F38A8BB2961B0B622514CD6CF4ADBD77ED2ED4BD4A25593E45DC13F5377D5B5BFDA60DE14D30C9EBF5160322A183C07563721899D8C1A4D7E0D4B6C593C316232AF7F81DDF29AF3EB4E527688B80501402EB48C143AC02A2EBB7EFE8ACCCE8D587DE69A18F719DB630CDEA5928CE41BDDF1D56117132D2F234A48DBD67A278B8235B9980E49D657A99EE18218D0B321759AD65592FB804C17EBF89944E645CED380C068C796E28A86ADF05B4CE27154A616432E97CA9DED9FEE59109DD8C1857905932C070BC42B75F52C97C52B8F45E1F6042ACC30A54D6E89F52F8A9725FCEA2C507814E1AFC7E519F94391816DACA49925117ABAFCC66681956F7FE2E37BA3E78B2BCEDE10BA16F571233BA3015D1D7873601FA5E24AE164D88B568EBEE2069BDEC44AFCFBD410CF1DAF1CA22BB6F96789435695D68BF541A5E208DE895152BB4A1589C4F1A4DC59F985DFF67E4462FF74CF76673798DB6DEA1A7E2F862E4D63926A041604AF1C69DA942E9B0DED774F6E0E9F349DDE5A841C7FAA5A00BD6E69615CFB485AE5DC5A9FDCF141AFC1D28ABFE394675760E80B262143EE561E737E58AE63A84AD27E4D8EC509644745727438F2B9074C9D5BA09587E630BCEDAE1BAE11DC93C82D7A227620CD08FA5E5A101DBE28A450C19100C3517545EBD4C100CC8C7AABD28FB5FDF1E0FB6DF2D937C38C922EAEBC49B562993EAB601945D33426220E4870E2B851A7DF5034E56C900666417A5772BBF516724268BB77933EA434E9EAE8D2042A987355AF1664EBBABEA5D2D8E627E5C98D53A63FF6EBA346173E5B3A1C11D841654D491D3746A208BD1B64DEDC9E2C099BB4987FA334C9371AF167C2F2E8473B7800
+DE0336FFD216362AB9E4819D84209EBAE6B9C2501C9DE7666615ED2160509D7B967055ECA11DB28A857231CAB5AF3A26574E37A8A02C0F1E7005A5AD564F680D5D401E6A4FF0BB2F4F0A4269AA4295D9C3660923C1FFD3D344BE57E091420C57BB18AF75666083593CA25AE8DA551F855586D05CFE65E1021BE1A18FED8940FF69DE0DAA4AFD0D10084EDD0C586233ADAC0DE6295AF97D40D017E19608EF6841722A4C22A0A659985988C984A2C4E78F0AF17967B9DC33258F20A263C9DD66F844CFDC55DBC20C4DC9AB8758FCA5163EA0FC53D6CD5F832FB51E2BB0ED86BA28E73D6F606486A851ACC43C02E601879ABD52967220BEBDA4FA24A5A2E21323D31F05788650D8321BD67A38C5B400BE8F3EF22271DA844F6D1F8F8A80E0492A326DED2743958141D3E540335CC60E2D24D781EA879AF7D912AC005D74CA09DB0087809F958BE1788606C286E73DDEA1883EBC39C216D2F62C76D6881A82D74CF8C0426BE62AFE9D36421B6D151A872398AAC7C7E045B4D8837E8BFD2EFE00E97693DE875D0E048C43F06E7985DE60F259836C2A2D81C0BBE4877B357ECE76F9BE1A25FB01AC210AE26161D0F4ADBB1541D059F590B32EC71080FF76A09516CF4A4EA716D60D7F1A4138FC74F510E884EEB21ECA0A228BF9F1642DE0F6A020AD0B915216581739132E4AC3049D1EE48E37BF5C7F1B4CFB2909F054CB45817C968DA8A41912147122517492CF5818E6887DC76024BCE3DD1932185E5F976914132FE695DC0E6662EF4493C7C8740A2206BD1A2D240C1798F3307EE6B19CACA917995A60ADFCF890C504F9B1CACE6D900745B27D48933C8F228B858034E75A4A2EB5316F69B5AF403C07C2D716B15C5DDB827543279BD47D551F2F28F084C9BF396E868F9D578543CD9EF07FF5CEE320656C4229E7CA70A2DF77B8A1BC97ADD4BF0E56EBA4E7133433C71CEB5B9C046D059EEE5656D8820C8F2EACB8A4708B30B65D77968A9B37E066E10B50096776EB9DEA8FE32A19EC51B58A3DC67617BE28D3E6443FDB35BB440FE7F46BE312FFEFBEEED085CB514D923E89CBFFC55C8070E8F5CC43C52318C95C786C590C18396406EB4BC89F523299D150F66F921FBD8B029A1974AA2F2FB741AB69B7D12632E659FAF7CC1EDB203A17404020AEA904D070A200229878CC2A24F785C4B334790E7C6D70E47CC3CE7492CFC4D7A790629650BBF8EDBEB07A542715D03465FEAC56677DD3D3AD9AC662A88F5E420F54700179E08E59D00C323DE2B13FB9BFDB5A2106AC01C0E3E875DD7DEC2E22B0CAC45CE5E1EEB022FBF7383A68DA344FC8574541E91E8065AD130F9A9DCCBC80DD3012AA399C0C7F3B494C6BEE41601188429DDFEC0A0678D1467A9DAB60917DD96288883A399C2905396484EECFBFAAC96DA77DCB52B994552211659FB783F2DFF3526F0B
+D7401AD3156A3EA842B6C3EDE2D6968E52EB8FF7E13D36E4CEA5C89E0BFF1EDA79E4CD662DD087AF3EAF977F05799C2666B75B5892C8FE6F9CAE674E9945DF1C9FE99E315DB7823FFE6EB38DC144C41427162A536079D87FBEDCB8D19FFEDBACFAFE1C9BB10AA8D3E146E4CFE18964540EAE875A134F4159653D9271B100CEB7A37F76A7BD3F3D61B9CBC1188B1B960D0925E6AFEAA2A459333E38DF68BD44568E0D21D6B7EEB29233D5FD1B30519D2B1794B0464DF2D9030E1C942295F263CCDD31E84E01A99736CC7F2B322FEC6961F9B86B31F57136FE7095DDAE4A38A1FA19B90EA3B89BC2156790872B52AB023C2C05B41828443BE1ED3A79F9A300D3F0A5554E536B1B6CBE38582EA795FBC2BC116C12B4367A00BFB5210105C663C1B1333A1E8F1DA016A0F6DB98841172FFC1A2FC2148D8CEFB68D5BA047466DC78AB5DBBAE75F684B5CC8BEC6F37E72A3A8E0654D465DCC8BC7AF6DAAC42E1F77D929298984C7D2C574472EC5E73AE6EA3D46C774E5344BD02CDE6971E627122014D1EF9E0C70B77F31FF0ECFB903A6841B656764BC81D4057285DB4EED1D982ECE67E39FEFF577ECD80F47A548AE842C3D88569E7C5F5F0F8FA5306CDE57922D871458DE6DB36B68F3FC3B4FCB20737FB04B82790287E9639EA6FDD61882DE826DC1534871A815E0B205DDDD35729FCDBF123D485105C82F28A54B55B8563BC1398E8157C6FAC5B565E240FFFCD890B8789B42EEB553E07136170E3B3AED54D848CEE01E09E10B91FE7EB2C035083C6BB0D59C5C84DCE1BA52BBBE41B73738D70A6BF752A7F3316DBACF3741B95BE0B69FEFA70446805F8B7780F7A92422026CAB26EAC6D1509F7D453E996CD8FE1FBF8CA8B08A295383550F13A47348327DF1334761F4B0AD6A9128A77C7ED7F8101D3BFFA36670B169417B99271978280AE9E22796DF23C475A8F34752D5B401AC5C61EFA01946A8B7EADEB5BE3E2F7312AE3B76F93A24B94691A2B6AFC6F325193AAA7F8EA26DD3A0EAC326A91EC22B7C567F2FAA0157F2E478E68BE705D8A3342B3E3F612405D1FCC196B20B8A08E13B0A278FC0B5A604F6ABE7DFB40CB799D22E24F63E829C16BAD9B0A2EC1A33E67D8FBFAEAFEE102BF7E85F34E1AFA3AA8DF60513D9443F065AEF9C28231008E82AC623570F778A72A193CB3C5A0C2E9270B73D074704E89CF2E19CA0C5AA5D80EAFA0393E3D053E9817CB4429F7EC0F0A81FA43138D6A7D6ED8753E6B59E3C817FF3C7C4493CC11C5159720F94F0B1B1631CBB5BCF2C34AD4D46179F1A356775D429962EFF25C690E7B81E04C82A940F3B6A93D781B859F13A772A7935D0609F81326107A29BFE9724CEEC9F1FEFCDE14329D5F9C3A59C5DC39DDD58CFA7E7AD959A5F1FE14416408080710DD43A25BB709126DDDBD844A06CFB14F76BAD9716434BBD1
+58F15B655C46DE7E782C5AF05393EF2D6A982920A44A8E9BE3320A0AF5C349EBCBA32C2E09F54198193737825502555C1605D79C94AC06E865E59FF0558F0C14C64C50146F46F4D1D17FFA325FE9D025CD50B6B75B332AD8904A3797AD1B9FC2F8FAD5D8EDEF5566EA89ABCE18D4EF56BD0E75F7634B189BF76E81B71B877990814BEA4279A367A4D1AE34BC1AC702DED3F5AC5480B85224D76FA72231C70436D7444D9C69F499358CA9A47E0BE27992749951E5DD29199237D162D7DFE8BB153ED701BBC54A8DB96AE300A7CD5924290AF77D5E3974A3DD468BA7683C0F81F9972E69FF908069E6B5BCB3EC5817D3AEEC5B4F35E6BEA3EE97D802623D52BB07DFB10579D1F2D3B2D0D64567B94722AE52AE6C283A70104E06BE1A5977DF08796EF3AE6D4BEA483BBA3E45580E415D85098D3CD84193B0DA2177074ABC556717E7DC23901098151AB1451F07FD3516123530C57087C7AC53EE25165BBD63FBBB6721EFC93C12E5F8E0F1E133649EBEFEE98095DBDE223D66FC99920D70FF5378EEDA5823EDEFD12EB2016944E71A346822B5DCE180C82512470B632D3C72357A51C4C56756C72E85D5C694AA910795A12F447D682D935EA9B1A96DCE14B440E10ABBC3DB2A2C4503E73A9648BE56BA511570A5FE77F4067EC1CAD3786FFF6B70A192BC78C1684FC22F3CEE17B4B2F376ECBF7C09BE29FE22D2667301508874437C11C34FF4C3DDB27210A07D16E6A2C75D578D1EE700013202969F6E418A82D7763152ADD7D519A92454BA746F4C709787182CFAA5705BE159055E13C0610CDDEF43CB6F7687545489B15AD1A742577B97958F77F12C7853135253C8839DC782EBE7E0476A7C902B9AE574E941E5723035DA74B6AA6E36E87CE12BDC67C0FF01128B423DCC7A1163E13D3FD8E030A8C167387CCD1E33C0051529022F451A77BC4E719ECD754B9AA7661135358F3E2A79554860199B3902152EEA389134C866EC2E1D42BE0A1D72720948FBF31FE5EBB6FB5566BEA54A5434A19C673A2E07E185755EE24A0F54C4F592B6174BEA971810AA2FF742B3FDF63C45CD5B5C26C104D3700D60DC8EC4BB1AF365A9A0688DE7121AC1466D7DA6CD40AACD087E434341C4276DC23BA3831A75E8FF8D26B047633A32D62190AB5DA531D9FE8DE6A10ADA1230B3A78E99E089D33FD1EFEDDD6846E0E4C599CE93FE6D8F4C754EF1EF50B9692BBAA228BC8FDF7D1C4E660B197B29632E7A829FACE7BB23B78E1EE6E438773B4D8685E0D5A46874A2C7580889A88A53B4B49BDB7ACF4F008ED4808D0A3E067BEDC1ACEA6CBCB37B38AE9F827108603BB312FF6A715498269FED86C73597747409D608A8D9AF340B3A2F164387543BAE1F34F836B16D14BD8B4B7F97FFC841507CD573CEAC6B6218E8B7E8ADC294EE409BD1C62BB15D5AEA821892B2975BF8F2
+618AED1F419A87C168E90922F14A152F0FF4C311FA6A2A7EEA0C4CADEB6742A883BC85D3D72A6AFD02A99EBF26087873D13F7AFA40A08C375528A05E0D39E4EF09844197E1C326767BB1900CC4F65DBD63B2F8D5170D62AB736AEB77CDE192D85F94B222429DDBC90A4CAEFAB1E6B896D11B69AFA46460C6DB7AE21FD57E0F92950D78DEA904B04F1413401930E1BB3A25F5FDC7451D8564FE7E8E86CDF9F7F4E61A8EEAF4044AD46C9B4F8CE8A43B775A6AB173C3E43F8EBEC842F05022CBDD3377EE79ABAC4683AB7F8D9A3450E32C903E91BBDD5A82D4738F89C00305CB152221AAE56ED1B1ACFFDA49C2B8DC4634B645F72E8BAF4E4DFB3C3BEEEA33FE85C745EAC5C73264E92EAD47F267B30A5799645AB7FCA4B840BF924C07BC4A3AF887026D6167B9972E224C229AC61715CF0C761C6AE0F472EB1227A0125C968BE1BEE50C350E5686DFBD1C45D1284B90E21F031D3FE6115C7719DA4A00EAAC9E0FF95689B46BD9EC01FE41CC4B8B1DABC3ACA0FCDA04ADAC814CE05969944F63AAB608D744B2CD482700086A9B372D7D4241A32966B4A6B75DC4A58359F6F6B7C0DA3A70842757807A76A1F0D47A532077D9F15132B8E6C12B0FC21408FC8218B504C3EAC21C87DB31A786BD28421EED1EEF7A013719FCEB1C0ECC7517AA3FF23390587F8512E2872312E742BFFC9D290FA7A2E5134128294B2277247E5F09762A537777DC132BBF02243E07EFD509B19D49607DCC5AB398847C72DD73E102F1751411DC9848F2C6D8AFDB7A7AA02F726EAF53115DDE298ACC1FACB4B2F55F4BEDF61CD3AA4F491F79A7FD7BEE422C8055D8AEB2C57C5703EA408142AECE8DBBB5E00F4145B5989116F7795CAC389A4549F5B721387BC659811A303A391830C7B1C42D357A12073C10CB20FFFBC2369771D54FB75157F1195856CD45A088D5F8829ED3A92CDD17032808BD68E810200E7620155AA82E0D54D35C01BF37D60000D73495F1701A284A2860C13931CF929581D1AF1EE619642181E52E360E93EB83F561084C5ACEA71C2EBC2BAB0D22D738777568BED921DB6047E77314602C6F8FF5035F41D381261BF245014F06550201DF7C2DAC364788C7686854089384EE4EBB4A05938A70F421372A0A936EDA925ADD43154655DD3C838438CD6B1E34E56C4680B5509877CC99AF2CEBDCD762CB240654301D8D9D3E5ED34F13761931B4190C9C9F82AC3530FF18078A5D8B3642C4413A127EF6AE08490A730EDAFA70F5EE02E4D8EC13A841C528F9BAAA766D293040E813118DDB4F51ACCE093CED130D89D91C0BD09B27E1CC28577E79F8978951F1A7995F236E8DDD4148DF019DD3B3EA9366E850AFB2635B0D278FC2F38F8CF02BA0424D236512C87CD86C94C56ED49850161ED80AA9FA8AC0D076D04940EE12DF05819609ECCE23459EA5F96482E433A2
+E6F74F24F8BB79BD55F8866509D9291B74E43772A825F537508F562DDD806F5B5A4186D349DD7AC70385AFCB4073DBE85C5EC95B5F569034A2B2F3DFB14C8A89D10F68A42A5C0E95F6EE89C3FA433889D6A520E337377CE74DC4AE0BE68BD4584BCE12636743523F29FA80D89CB4BED9ECC977F18D31E0E0B6B4C83C9A529E20C90C59DC204F625BD2B2E3107071BB72E845A99737A24BE1C9AA9562401FCD4EC8CE85307A4DE955A710EF787544B02B2AC74BDAED760E528AE2570BC6808C7D5C8D9F3092A79E1E8196C9E82C4D5E1234DC43C86B2602495C4D6FF2C238AF585731AC5569064C697F5BA90B99D71D6108BCAFB3108BE054EFBCBCCF778EC165EA8B1FB283E3FE05583D7D970698588B31E54CA89D242EF82DEA553A0779A5313BE4AFB5D99649604B35C3EFDE9BB2A8A95C2FB6B075A19FDB8DAC0044EA16A3D2C28B77FC6A349BCB3C63CAE1881F5400416D082AFBB59C8905C638D7EFFB233AA0A8311580DBCD28B178279AFA60999DDE60C2827DE0755C42BECD34D75148DDEE1A05E5D7034CC04935FF6AD4A3A85B3BE94D63D31C6EB56C1913FFC641D8BA6B2162891F9E7D27EDF695699E1C291148FF51A04AD8D47F73DDE8DEB85E03C8713AB77614028724590233E791C1A1F8B7F50A9E4B868E28509939E230E715895B7EF8D2C110B9B7FDA63C8AEF2C71967CDB0EAA6C6C1292C12BCBB1DB80DD4FCBA4544CC1B1331A69CF2B0CA5DC293A8A6FA4F99F7C7D4AAFE76D1DF7C37BEAC1108BF8B0F591AE319263D85D54755073FDC2ED529CF4FB2F8469BD72547E04D5234FA14169E437014C5E4B3C97A5BF7A9B54630B70EB3DE5DDC877BA3CDFDA3FD8E0B73B85C0A68795649312439B4775B145C1E68E4F3B25536A7646CD5517E47EBD28EFA97E5B06C574F2C3647B016584B1BDDBD6439FE0E9D53B54A72D5237A8FE8A3DF0CB51314ACDCA8B380B6F24A1D56344DA14DF430BD58CA2C33A33C135A95224BC7A03FDE2C08CFB8DC4F43E7079B557C35DE4D2654040AD79147E4D70C213683216C014D731E8D111CB0B982A4E5E4CD68ADED3EFC37B1BC673861DC77DCC9D2D7B3D81A4E0E830AC87A3AD797D5A42D72B0D69741297DBE5375AA5170D62A7D653D7085D1D4BE4E07E5C47541FFA5B362A5F6C58F70BA4CD717AF0C67D00E4BB826EA45C8449DAB2DAAF0AC371F2531FF8F3A86DDF7F90BD909566BA15441AC58CFB71EB4B084E5E1DE0EB70B3F39A9D0596C84FD9C0AA4227AD6E3733D9D4422FD91AF1FC0A8CA3B1447A49861F3DCDB3EADFF648D42D613E7C195A1CC369D000D9B4AC74AE11A1F68B1D53972AFAC0DE394996C4571F8A07279507B61004B16D22B169E1229E8D5F928C56446D3D9EB261E8F5E3C978EEDF82605CF784A5A5603B7EF4C11D69B5C628D4ADAF14DF1698DFA0FC16CB9FA1BF
+9F2DB426FAACA606C2B91CE537B07B6CB9FF70229FED3A5212602666B3F8637A31D35D84A5EE8C3C9FFDA911E98ABA6BBFD1E603EE16154F19F4DC8E69FB3E985D87DF9A34439D9463FFB214E7B6448E5297DF8A8271A6D1CC96375992D866D4410B374041C249DE2E450E0EA4FD50CEE26F96332222CE908F266EA0911CAD07A6D868C513E85ADF3D2F0C83E1518744E09CC6B27F67A0C701989DBAA28B481AB669ADD9E037B7B3E7EF157D72716156BD5D73FAFD9B7413CAD49E089E46BCCDD15213D1FA6CC756DB9AC2D3768C132C03FE4C5F50CC5E7F45DA238C23750603588A85DCC1BD0430AA72F574A60BA73D1952EE311C102D1BA7015167710B06A67494573EEAEF05D802E9396AA0C47A7BFF985D9D661CAFED668A643FB26A1B6119D950C48899C6224136899351EF061D526C382991D227BAE1598BF7F5E96401473DAE9EDB99423CD1EAC296B9130B4B934F7EF6AEAD9582C85B5929C2AE59D7C62C876D06ABFA66BDE89E03871DD07F49EDF5679215B64E94C7C50BCB1072F3AD3563AEE95925A3733708012AC8BEF249AFBDF162ECF5E7DD37DB67349541467D2420A029D3714D3F0A31B48EB9F5FA33648898F5BD37860376030A2D73958676DB0349CFC954C47BB7784DCFAE2571B3CCA63808FA4F8162101DEFC845486C1BB2B2C0576FC9F6BF1B6F7D8A22D4C68A56697D90EE42F44CBC4FFA1C14113AD087341A2BB0C766EE56E92AD9C89EF4E9710D1849CBC162A1D3F78B4D7E583FA67552C072C1DDAD801C46A453912D5F957C174BA37EF77E96458B46B5DB79AA1B257B66E895BCD5EECD0BB1E15BC0D693F006ED155B12784DD21A0205A10A880C2A76EE120E8AF716051581DFA76BE72BE5303A33048C3C215822E184894D56DE4ABA9F2DD0793A7AA0F049D85734223F877A32F2F4F230000760475A6E9AFF127595539A14CE4255E2166F643A93CAD14E28D1EDE2007CEF2A21903B2CA6C742C3F922C38CEF07D17D190DFCFD149DDE45223F1289CD1055DDCBA98ABCC43B4DC365A3D45CE2348D3DD9D7DA498273D8BDE8B074B972B3E8B8A3550605BD66D6100182C61204E9B3A43AEABFC10339CD3AFA3C1CDDF78893155FB8650538D2B29BB212D6D0F00BBEC64A1523D9AA16B33128B833FDC24966530EC454167D85EF147466165BF752F9C264F524E8D93C550C883A11B44E007D911F37F99A7A7F24270DA484B7560CAC3D546C4703F1A084AD35C5C7431AC174F6225364AE82F49B8B050EFC3047CCE20C90E5E6F94E292D54D0612A6A42C030E7486E71E5B5EDA36BBE8E321C8446377947F564124F67150AFC3E973AFBB956D36E3582B415D4B5220F46B176A4F5A8D0331D5C4AD78D4D460DE2514CDC33CF1960C43B4A8FD1BA288259199004585015FA612516D27DB2BC86A08B87456BD0D7B8E0CBCA647E
+AC3BD52810677AD7F52BBA307FCE12079A407140CBF6325C872D9343B8B5AEDDB5F250749DE9944BBC0335F7BCA07BB77D68211EF4D723BEC7D30B0F485F1C66CA36EF445B1ABFC0CCDEBCB69E4AE485F01A108B432E4C630EBA8B9FF04C32BA2BE702BBA66ADB3C90600EF5B657326D963C60870B27B4E40A43820615F8317C5D69CAF197B2D8B40E5528DA8A84274F59AEFEA9B925D37D9EAB3A79917ADF64B221B5413687BD1885625AB7E96B652676C4BDC7A84D053DEEA4497097FC055601CECC6AA7EE0AC2C3C08769D10B4532A057091E3034490A0E606513E30FDC6D39042F3C4D2205AD11E4CE9F1D24B7E9D2379E4BE5C05FEE8A8E06C1D6854EC31D2F272DAA9EE88939E2E457EE258DF224FDF219C892DCE36B395D4A21605503C1A16FD4031AA6EE8C139C5E54520637F522F4A0BFF8A77E525D6C85BB239FE1741660BD134390B5F1DB3646EAA1287660D818718F5B941C9112B6250B49E7AE7F3A2C7B489D00DADFBFEE9BD116101C620E4FFF144E2BF656068CC856339292D45C7D758405D5A716E3EFB972932281D52773936FD5892737928136677EBD18B8C76B5786B7E5A9783D3A25895750EE02E1E262D621BB32EB0289EF735608B68BCBF3E333AFA4E5BAC097603185DD04422C99AB1EFAD847827841EE961A0F3CC7654EB71F192C7C0360923388A0A0F4F22E06581B1260EC9B565D9112A7FFE95EE50275E1C6CAA7CD72DAFC196ADBB2DBCAF4169D8B050522A47D635E33136A5A7F5B1F4A8BA31EC723B2B007C3121A66977A2C2D8D9B7F21B8F0C491BBAFA5111238B6D0A475F8E1B90CE7DD7BD2E407BCD9B6A825548690D8554013FB3363BF87DB482BAA33F34F41DBE0FAA8AD7234EC479EF7059A3A92DCD4D14AB17CDC5850535D8035988C50D9AF86E6ADC9F467C8F2E04B9FAB97A729B2412D331DB466962796F9F49CB1184642BBE3E1079C2F558EC6DCD59BD637C906F745631719A277D3099907799183D3D65147CF968905EA9DDB092FFE74432162E314CC2A1106B14F013A967C33368334017EEF7EB176EA596631AEC84852F3460878D25832680F93C31517131FCBAEFAE60D0147EB5C7AB585D6702AB49AC8BFB085BF286422DAC8C4DD384B9F23F757F48D1D47C8CB09329083280F20254199FBB3F27E354969B96E22EE55A8DC0F38A6EAFEC9193A86F1500FE9C1A713BE69C2C62BD4A0B319662DE5EA57B4313FDBC481CAC50F7B174BC369E0FC4C53CBDDA7C823BD0EA19C2C7FA8CAA7EAD5B3215A4BE9ACB2352700F0B5D9247E5F2F689249EF1F28AAD7908B4762B7F92497A2F892685CF71F7B41192B165028CC2DFF88ECC458CE945A7B9A51D7036011D2CBBE0FBB89A4C93DE5E909DACF68A84712755DCF7C8264EE3034A3B38E3DE7CC7DE4517C86BE8A3BA9C8D08465BEDFE691F6BC9AD620
+DFFCBAA12CBB3F4A2A025BC3431373E8314147A36893DBF9CBBFDDD7D445BB806233CD35B0C498FC1208DD1AC53B581261A8B0D456FDAF66D602DFD0B4BB5820330AE5D951C42DC956782617DC39B76625F10923D80D255633352C0A063D4AB560A8DC3A70A09B435F47FC8A3E88163DDAAAA180723D3B30B937535A4AC5FEF94F845AF5085AAFFD3D8D2EF7BAA58F7754D6A66D8597C02DD7AA590433A00DD6B0D17500C188CE040807DFBB07B39AF428C09E9D0BB63DE3409F110795251C836D039EFA16AA5A415BC6FCDB7745962225C20F1B4FA67899DC43DB22AE7C6294A5B0FE279335124A7CDCC98B41F2FB274B327A2D39E2AEE79917007A729134875ACAECBFFC9FA73208313EFF0F3F2D652737F180EE7C480E4D507FE2D18BA5B7C8D148CD570AB87F0CC56202FF8AC5B035ECD4F74C00712F4AF0F952AA66F8FF5078658FB9E8016869E0BB0B92FACB1630541503FF293283EDF8EB569B2568644E5D7FBC027B5A909851B5AF637E87BD0DC5308473C3648F9FAE3683A39B685BFF7817DF4A65CAB58C42078FABA990E81B800D86C4F8FDEEBB740140B75904992334E88DBF1FD99B1BF3F37AED36C78C48CA6BB2AF8ADBF01CC42792CB563A9C560C3B1E610AAD24FFA2B8029030A137302E942838656EC670DD5C64FB6D384B9C031028F93C49220266DF3D41CD62F83F6AC9E5935419920EC3233A28B153381B1A28BD85CEE3B52F8EEAFFC54199670F4AAC2AD441E547DF619158B2E6E428A28CE66D438D95F13FDEF8B3F549CEF3AA337BD5FDA30485A053771EACB47E3B759C64A82FDF3B3C7981B1EE3E0676605A063357DD3107E2D7544D676525485F3F9FD7CB8F4277BA8A0E09433BFACCD8CA6833A84485238CA11CD41C7EE18A092C3C6F34210D877C43748C31C0765B5A949ACE7D7EE232BCAE41AB93850A3538E93990787C7B74E118BD55EAEBEEB9B2D83FF7BAE60C1E6EBA0456C37ECA0E558F8B117B03DCC1C0564847FD1E2A056CF71636D681BC77CC116430A3883B32AF2CCAF3CBA36A076522977FA474893BB42A3DD1EAE1BED5B48294FAE30699947C70866979D8163C0A44D2F74DF85174212C8E2B4284F326264E3A66928AB15AEDABAC3ED41B4CB768C0A7815AF09F2C998210BB8CA30E29F2B51A79AF393FFD8B3D853C7C62AC9596F3E107A60F726CA3C9E26F964D6AEF9A66996F6C722BB3FAB13EE86744642D52F2F9A3563CF92FDD1770887D16CDEE62FFE989112FD397EDDB3F57EE27D0051BA9796ADCA75E9CC3EC13ED217858C0A33A2820794A0C641E7F88447953765C93B08E924071B13DCA14E426115508E0E35AFAC37703A7F5B9E18196FA5BC15D93B0231AA0D79719C343615449A0FAF0E691BCB69AC226FB2324CBBD181445216C4E3670A4966C58F1ECDEE9C6DA3B0F43162F6A2DD9EB7766
+BA916B8BB45201A5B7C71258FB0A710D17B426ECDF70A4777A57160E3402C7A247B8C46ECF4D0B924A60DD282C1DA0A99D2B7CCC20831B261826CA16778E566596C2D9C078F4661BCD8F788731F41A441519F2DAC3C1FC5DD14FF9536337EFAD317CC393732964B5B6C83A4C753B122FBB1E80739922F9BD8036720868BF315D8B654CEB8C42193755AC1404611331E91E619E3D9F11657BB0D992B008FDE84D35A557C55441D0E1045CF0B4E73EB3DC17E5D20F679672FE2A162B5E915360D08B1C26D06E3941E9D701C3A314C05AC15B7BB2E88861D09BA1C4C894F8CD01D08119B5C60E52EB1F98C4D2F8E1B241DFE6F064835DD8FD008BEA7A282D8E38CEFA485C99A0D3A97AD00F5641909A8CE3105AF9E0891B15A901E30852FD3DC85964BA1ABBAE4F7FDFA364E65BC2721967E1F64076D680CCA356FBD78A488442E162952D0B92C4E1663BECE16DD64D2FD556437DD1EE6776CCBA11F7EF2F77249756DD2CBCAC36F6C3C4563FE882D053B086E0F81E14C471CB052227233A9EEB87D8A7214FE3A4DAC7AF466BF9FEC328C8450CC5ABAA33B5A6E5A139D953C3BAC8377A61E73A5D240A14264A46DC1F8BF5AEF31F9206BCB90647F191AA70D599CF60D6E9A93229923392375AD136FBB92CDDB95A0B29BA8B84D91338DF034CB874A5650B6276E37CD6B26B67C3FA0BA7EC0E2F6AB2D49296E303F6F3096764C31D53077902A600219E1F0D3A1D5CB7EF7EE5F7AB2B73C48FE703D06EB96533049DC179ACEAFA8A610946302971031D9EAC452DF1CD448AE04348DD5B460A08C11D0E8CE7D4CDE5CED700F88C2479A5B414A4A817E2E9BB5BECCDB3959C9121355B2800522437AC2BA18DAB0B582010EA54EE14A546C9882C8A42237186238B82EBAD4782236C408C3C01D9F66B7D2E2939DEE713F4E85DA8271B30E439EEC9D344962A22EF96CB8EA05783B6B3540FE74C24972C9F370D2049E7467626394F0F6BBAF05639715ECDAF290B5ECAE7134B17CA3D3AF57A7B6041A9760B7B22ED5B61CC66E5ED283F9D7CA6FBAD1E7F6FA2A0C4EBD2E2C88F2AE8FAC24B0DA786DDB55CEDFBE80B271B08EF5ACB45C837A601587828431B80C6C679B9063B4C4B433DEB56D583B0A771B1E1FD1B1B9974A66035034FDC552B93C987111C9939F94002B6F49DB53346BD66C2C1F822048C28A8646960FFCDBAD866F8F4071C04DD363D2FBEACC2C4C665C249D82F0A5ABC2964A78A09FFE8425A15A81EF589D84B55E1C92768280476E87A331E276AA7A33AA8CEFF32205B9D51A7DD7ECB213BD998A2EDC2F082787C8CF8B7E0F15DDB42A8A28176B5984804181C990E6D7A139EC8BF3CD334068F497CBA88A878D56F77706000100B3F5DE555F1C61521DD7FC28EF0439FA4392C958DC8D0B1D933DAC1EB7F3E2BE2E3C424CDFACFCA6F02B48B6821
+371C2A30D9907F2C458EA34AFDC2D49BB2C0E759B1BB0939404418F13BA9A406A315A48B7899EC89AC13F6D885552CE94F6AA777F035592E5C37DEE23A08D59C0EF95EBFEC74DB61C222D4EF929D9A3AF57BE4407D5745867182FB33A54DD8C7BE6985526C8824D9C4A4CFF62792397FF5B3F6804688232CE9658AF8AB42C4875137FE477CDC32E3168AB760B68576FAC548476C364149259ABC1383B24BA1543F9552165A5D2F1EE1DDDD7AE2CA9A9E5E1D64553A289569AC070C75870140D2A1C2A6E09CEDC8378EA9BECC55A186E9048694994904829E2544FCD08C7A647D58DC0F61D53592D57C07EF641908035B9C6318433F04A506BB85C3CAA836135E140EB73E7921EE7A77084B001C3D90414ECF3167BC0A5E607C74BBCC52F4D4D93ADE996676FE30D00CF99207A70836A3E1159EFF61737DC46ED3A274307F61E9F4C41B638A51357568F5FB224B522BFD7D9F7CA2EC5B768D48F3D57EC3E116B4D759327629EA920380B8E7C3DA0599F0FDF95E6E587E07F0126ACE99138AD94A69553091B2CBB7EC771BE5883ECD562D398936E0E0C805889815AFBB0C6DD870B1D7237F235C7F5A85463FA639C59F2BF097C80C4E259FF8D394895424C21669317FD071D4BE120DD7EC6CDFEAD83C27D2FF973A7DBF052C40A537498E4CA058ECD517DDDDF88E7947409E5057AFC23ADF10FE77C517B3EBF7DAC17955CD65B1BD03F94D9E26716525A9CAEBA0E3C33421D0F7B7FF08E3A5677F05A6BF951883E31AAF6A1F9D7A685B64A53577762E908BAD0B7F094F1CDCC77ADF38B3D44BFBDFF7A380C4112966A5452EE9B94685D852543C0CF32A9F0E3E13C32AF04026043028045A36E539AF387812C063DCAA9AD2113DD4A1B0180A238B65E647DCF5B4298BDBFB52604EDDCD2592AB8DDBA01669BF5F089065B87E594EF50B86219CB71E37AA5CF9E29DBBA05474F9D5BF367BE0E36AF6960AA5BC137A1A3B56F6B0BA3F53308B746AE2D68905455DDE0FBCF34ABABBE67CCADAC0A3B7FBB85C4C7C1905EC036BB993762034428FACFE8FE3C936894BFC6F7B3A83878E869FB54C86702E7E7F1F822B30F80FB687653622F1D4F83DA8D0ED66FD7CE5DB6FF91FE64C30D78BDD0084092FC6B2697D29A9AB22510BA3D925D4C89FB2D4EF6001DBA3872EEC5127BA6150020ADCA191A8E4D21536598B3497EA513DFB606986D6C8C4F57E8DEAC608EDFB868EEFAFB3DFA6A22E7D2F9942DFEF206DF104E922EE54E3F9F347A234654D89EDAEA11C4AC0F5F3CCF0ACEF6F468992CA69BD16CE4967CCD6E9869476518F14BF4334DD85DA3C5565B89A8A7B175B86E9373E9E823AB9EA10C3DA5FB7A0C88755896570B58F10C70EE1AE61FF27892A45AF52600B5EB0CEED86C3CF424181116FC50A90BB07736C994374384FB86FAAC1AA7A12AD642BA3701A
+A8C2B597D7B5E3C954AE949B81615E87ECDC49443D42190AC4AB329130639BBFF4796A2C50C8AB62B20A832E76C9A71DCD07A2F3FCB62F91F2A07764E234EAA1FE9867A5FD9E7491E1C3FF097EFB62917D874BF817EC0C3A28DF2D7A760299E07410072F0E3CB0A0711745B12307BEC5D246074291E294B9F36B0908B0C671E57DEACF750340F61EC6BEDE58EB62C626A8FAE59B189985070EC3184A32E643F4642FF192D9323B6429B52A363B21B92CEE54815A08D608FA94C0EE7129E0089B59C3CDA0CB67082E117A17C0CD406A5D336D1E599801FE333DC024984A814517C4C23BE301287B0A46167F957CA2D39CF6FA9610360333D53BEFF5E406F86CEBA51A96C18BC2ECC69784B55D8945EF240E15EC524CC9EA7ED2152154E737B70B6192D6AD0C8E7FC11CA53781692AD14CC9C6C594DBD7B26A94FAF4AA4ED7EF8DF6D43570929B141537BC3B30DA1D91E4D5A57588301B419B2140B60DA5D9C2D6FE522A4AF2C92437E502DF144B6D3E585ECE5B8953884AFDCF59A56138883B716EFBC20AAAB923BF6788BA40B544791AB47C2527CA59016252E213E65FEE1C4916C1574080DF7905976E5C24E4234C6EF0ACDC5AABAED9688B1898C77D2BBED62BAE5901E7005A9B65299565CEECE17A703FFA8BF8BCADB9B39D533C39A67049302CBC0F3FA2F8B07AC816936B43BE61105E8D44500E42689C30DA8DC699047F7567B4CAD8A5315E3727272651E1D8996898E34E829DB2984B2A2BA10DC81C5463EDFA9F846BEC3C983A50C5E68EA272CF11F3DD39020EDBE86D2AA8B30C6EADB92FBB476634B31CFF6D2A2B042C2CB1E09F1F5B50A9536B0333B8FB63097017A95086AE3001B0A1613E04E1F9525895C24535774D4FB6B83839DD4817D576CF25C18943717DE9FC795EE8474347C1FA8DA6CADB9AD0D8E683176E494F56E4891504AAF27AF345B1EB53F20CE6CA201A384C8159EC7EDC3EA8105FA087F6782AA8787F8411ED36B3927C52449695AD18BBEC3408D837830B12EA1A34AE7C42796D0C9D86357AFF1E12AEE3EC3A09F2D160378B9F87A781E6F1901D828D8492670EBD24A7C92B30368211C41DE34A8DE14A834AE5D7EDF6E9BB557E03905BC6D7C474C4165408036A1316170FE3771BC593A786E514A8A6164DD578427627F718EC9517E466B16455495725865A8AA69758C8882E9EAE0826B2F3B2AE0321E094B9E993ACC5A5F1B1070AE815E95A84B421B99D6DC608A568BFDE693E41758F0D7EFAE22E56433C8AD842CE31920BD1287C7021DC0EC16AEC6DC756816DE482170BEFE0969DCEC8F60C533A24A6DF7075724A042068ECF656F42B6B7D28F26A0D1ED6C47B02EDBA5C015DBE63B16719B614DA999713F298535ACB31908F44BB71D12EEB1150367B44DB0C7B8864011B536C92312FA3B165A03F31998064FCC37B
+5798CEDF8F957A997415DA145ADDF5CCEAB8AEDFE247B4340E64A491BA4BE2D0E9DE8BD0F597402882AE1289069F6DEBC95EC6D3D6C46FFB4DF5D442109F60D8FE8C7D2D52326433C93151B4F8B0D260E8930B61570A24489996BCF3E3C7A1F28BF9A4B60ACD741F540D8A8527F1DB989C07863F458B87242A4D3AD8F84470B1AB0224C404A391E1AA21F198324EFB55E6A75AFFDEF81DDB1535FCDAE33FB4929A7FB0416B587FB34F87FB5F333ED59D3EF0D09F42466F8A6D940125735FAD8B1884F072E320D3100571073B3E645C8DF76A3F1BFD5AC3A975E2BF675068FC7A058DFA9775ECFCF4444CA80C57693353526A05A9D08D38A5316D561CBE219682A790054804F49097E94D3CC6B5F5189E9A396CF49FD3F3F4BFF24ED2E60479A2914E05CC2504DA53E4C60B2EA685C0726C9400446D6CC760D1872805F559BFF4179DBC0ECC29F7404AF1C4F359C5729E4C4705F30F4D6EFA7F3E0F99BB3C602FEBB3DA72DCCB7D4D9EE88AB97007FC6140B8657014CDCB9194B6CFF70B3605832D1C68A1BE16AD2AB60AD884C0A55F218C0015CA896E1759C43D6A447C96E7171BC7DE1178838C2E0B2698197AB47E0DA37042FA21CF7BB780B6FAFBF1D25B4E499E30565AA759223D193C83CD7316C5F8B0323C945FDE087082FB0DA62E338657362DED96B06F5847AAD5D004965BD37659F039530BF44180034DDB36932EBD522303A535C5BB977A0C8C2000CEB16AB067CD8DD84A1A5404B566CFA85CC9010019E3F56A5F67706D65CDF4390C2218932E811F7F494D904BB922074352410768D7B131EE534CFD2C61224B01456C66B5270228A36FB19B0A2F7AC555DFF077CD6DB57896CBA699F705D5171481461FA04B1F272EAB4E4B0E52BB660F0EAD54FDA39B6B2DAC6C8764ED030A38BA3095B8434F523DBDA33BF199ACB56FD142C59EE68355819967AFF97FF1AFE474F348209BC96CDDE16424FEA8C4E4D6825E67A66A114F0E662FE931D5A487DE970BDDFD5842C822FCB1331F6167A9D2543DA60261C244E25EA67C5FA74003A883E62175C8749783142D452B5206A5A79AC0C52C626E35CE5FAC501195D5A2CBB3C6983F6E1540552C9F240E890BB331C99FC639416906341B1C098503BCA8D4696282354061BAA55F9F46E20E0E8699F07127E0F66A614576D3EEBEA1FB3A21582428357C90B33B341AFFB8CE575E19C266841EE9BB10A1F4125439C5FE2E9577A9568D549B39B75C23D177DDC04355648A412381E69618B5DF05BFED4519B63BB36BDC739E1766692E1B77463B704B571442D05A2DAA2B2F4BCC0D5A1613B5F5C7281FEFEC00F543560A9BA26137B4735483D0F358A9F7BED6F465B6733A43D940EDDC27E10122A937F5236DCC4C5535F085871C6E07374C337506C3735028262F4B84D65BC5A397A42A7B1B5C32660F9070
+E9D9586B77811510C1EFF7236C29C1A49419849D91B7DDD561AB8DB2DD88FD859434E6267012CA802956764BEA898671F98352A3EB40EC0639D68C3BE3CDBDDBC58B661A07DE84DB3F81E48033D363B942C60916F95AEF53444DECC7F63916CBD9422B8C9FF511806A52515AA160BC270A3C3F5B2A88027531EDC5B4B3BCDA3633A649A4995BC53CCAC1CBE775BFB5A3CDE54B965C7691B7422B1257DFAFD0D00576C0C1127591327BD89BA5A3745BBAF564C27B40155B2C32F45A62CD792A6D6F93EEB6D5F379DF4B8044560F613CAE22E71C9BD5D8F59A030BBEDF27FAE9ED423F3C24B4BE0505745ED833F3C9449B317774148DAD98AB77EAC7E0FDE5CDD35135E6FB4C898960A4F5FCFC2E6430A3162336E3379E71F6E2E25DD2DA6112A2D9E86EE275AFB4FAB6D1700EE022414E723E4A0DD87806862E463481F81C0ACA968D63D5DE1815CEB78C679DB8825DE32F984891D0694BB2A2F88E42F9FB01E610A1B3C2B2646936835C3FFE78033F68753F9558E65E8B6A09A71136208E0BE0453B023A52291B0EE2AA4EA483BF3EAD25C3DFD2043FFBE3B82626F875AFFC3DA00A7CADBC60A848E8C28BAC0193474DA3EFAF45A8BC62A9B62D1A0B1AD7CCEB05C5127F2A730563C4EB162734E43BE87AD14147F1528EE862972203A0075C4F5038888090F8B71753327DA6DC581C306447CAF4FE619CA699DE5AC5560D610F4D73AB45EB033DFB8A88F47FCF0B74739B8B3FE8B550470B1AF15AA65E5DC4ADA47C1CE0C8AEF49954730DF01D6F744B38EA794C44B3471BC73DA132ED1D78557988A1087F7046FA0764079E26A774A766B29F60FF5E85475B4264CA62C7D3F255729C330A17E2C13C6C78A94D72602658E10F1AA7D17BA2C179A8A7BE188E0CCE3D58B9A87D6A879DC672F5BF98610305DB9F3EB7620FB3D86152BA2C61570C4742391F9B1B21BE9DF1F754B67D3DBC996C89CE7511A6A90FF6191A9F72BF07C878B7D98E1FE060D2939469EBEC3B89FC7D89BE00494CE6B10273138D7C75432FEA41D6381909EBDE014116068549BCE7486D07A86EB90DF42D881B54703E44C715CD604EF5C3CDF722147F1C610900FFD1409F676C667F5A2D76E437859D73C0CBB04702C268F646C9AC2D85739FFB8A7FC0BAF70DEF7F71D7B326CE50767EC6F0A78A5A18344EF49B82C4E722E181C76AC3751BE6F43D5F03A8B76366762FF479219E060714DDDB9FA25F85A7D25DEED46601BD0586EB7EA15AFA30EA998E4666ECCB7489DBD44539241F5943BDFD363D784AFA5A7DD8EA55112F8D2DA261994CFD5976FA4DBEDC7517CDFB1D519358E780296EE177C1F48AF61B2F1428AD83D0F744D3B6DFE270B915B9891E891CBB364557C4C0D964FE8069AB09B5683FF8BE68D33A424A9673109057D65A2F34A1A3954A2B0C0AABF029C31C97A3E383
+C874B363E92C4ADCB559654D0F0FA5DD1BBD2DE6FB9940124BA46AA2E820CC14F430095FE07835BBF786585EB423D548180BEEC634733C5BB72B7DAE3999ACC3DF7972D5B8FF6D565877667F5FE0A9EA51A25730FB3DEA9142FC4B026C6EAD68AD30ED18DE66DC9973907719D59F2CC6EC668809323E63D5377AA08D1D05268AD27F6089BF9EBAD6B4171074D8A07D8A8936430770AF3AE8EE6D8A738C81ABE2A0CE7A8F4316AF5AD62EDD3FD83748B78EF9D4BE9F95B142AF59A4EC0A1FB68625421E8531DA9C90E528687F84EC4407760C2A6F3B4226818AE7AA7B13D6DC3FD671D0F06673ED5AA24FF2298C1C45468998BF38CA26579DF207FDD5098D6DC768E75163FB308344903E39756D1A8EDDA19E0F40D59D7D9E435581B6B51754CD062DCE10728D7830A7C7B8464BFD911F9A015AC6E64959618E38E6624F5C2626E4878F915C9D2CC9FD2E0F2D6D7479DB16A871D0DA08A856EAB1A495E8E8D0F62F4B50BE2649BF688BD46A240DB66DCB0526173D5F5B36B890E520614D23EA619F702B6B84DDCA0D640B159CDF46934C905FA33E30731D7E63AA436618AA0AD6C4E957A98ADC07BE3872C78A5D8501E137EB962309F52DBCD368F279D7BC3BA97B14FC6996DB087016FCD16F47B5B85FB4D56CBF0C65F82E2CE535B3AD606E372F93CB8DDEC7270FF1EC8459ACDE4BC90EF8B2CBBED86F409CB1F1A35E2DE4B5090E9FEDC236FE1118E0BFCE673C66C255C3E3DED45090FE65A79D0797959DCFFA1526A8D9A95FFD083FCA4ADCFA14AFFA4150EE539D45A83A4536889DC0716F33DEDFCB03F5A6B5A9478CCD5AD8F945457D107B43116F615923F187B528C0C69A5142772D67351429A21E7DA86FCDD24DB6E81D68F1944F00FD471E35DC886845BA3FCB18E55AB1ECFBE0B17A2A96DEEF095FB9B23ADA95A2A7947B73E56C0DEB53EADF75C7172620BF29A2FBC73D41A1CA107ED094841079DCCCED49B70EEE9A24E639E8E30117E4D127CE752F8300AD0EE6C5078C5EED3DFE5217B4E25C8C1A20773154375BF1C658727BA10523F78072BCC3AA1CA9402E29FBD0184E351D8D5B0E7FD49DF13CA447D9BCF2C42BC0FF0476B2A0FECF32638F7502D14D5BD4E80FA6B16B0370B0976236ECDCCEFC7C9CC8035F0656350ED47981448D5B674FD651543FB9F6F5152023775FB921461F9146729392B63633362D025AD8C18F96E12F1503DF825C4FAC921EC8D80F75A8E3D221A6B1CF530108DE32B6DDDBB134181B9E7A361A28E8CFBE9F3CC53A7BB21DCE1BB42F62C9E3ED895BBFEDED807B031C79B1FD9907E868857629781AEAD774A480B432EC46848E48CF18BCA71A731E0C24D2D043969163C402F5BF207C0FC52FC2D69700824B8830F6A49F00C96EFB54DB36F30BF09F071C42DA8D73A2EF30FD767829AD28A5FF079195D88FB1F0
+098FA714D5F4EC711BD1019CE9F01C39689AD8C2368DACE89D0369E5C07FF5B21F62F449AAE81B8442DFA1F3870964AD73AA2D7EEE7FEBA3A38E8EE1C54B3890B4C13DDBF131946D7BE54BC231BFB6D713EF3B94A0D923B2883F1EEF0B68AB99A4422885EC21D356B581EA4244BEBE259B04695180EFEF8DF783C06CFFA4C663AE2A86AE7F74ACD566EEA3DDAEA54022E0FF5FBE0FC12F7664AD4C918221A352EF70144A7F253F89C6A48B848FECC471282934D942983867A7CF1ED9CB2B9254F2D02468E643D698DF066E8AA9A70AA0971FDC9E0514B41A45DFDB7F49A895F0B3ED8D06A11AAB8A1327CF62E0481CEFBFF92C82D60846F65F9F44CEC26E25D22992D7609F82905CB4CC7EC49346397A7112DD09D571678F42143A8B489ECAB2D61B7412D96F758EB76A501738ACFE27F75D2D6F628D1A272357E79EB51CE3DC8EB89601F9A3952B7484911782B0D9D5EACBB791BEC60063747CA3CB084783F8454653B266EB5D72BFE49BA6549815A3E8B3040720980C94F54D67EDF161DDEC104831CDA2D4262EBDBE92AE91C3E4BE366F41995BBBF0BE650F85CBFBB7A02D4F0847D91C28319C1980B3F8314A4805D18BB17501E7879F4DF151DAD6AC968B34D366E536F6E65589DC0EB7F85AA42D190F4DFA672CAB09B013C4CFEC3E07F6BF86AE9E0B6D48C8B05D28799F536071290914A5FEBDEB6CBF65191A1D10FEC5C0F6EBA0701C943A8A42BEA238F695BDFDF961AF3FAA927F35EB1D36C9750EAAE19A977D980CD43C181FC4C0814ED37ED94AF3348817215A7FEEC09CDEF134C96C5EDC1D2F3A368CDC8655A8681EC6DDFAE33FA92944AFB9103737005723A88EF236DA091E57CDC1060CF5EBEF3511F3996DF443FF248883CC5278C9605CE3B59AC2901A716A6A184D864F54F9BC3CEA694E27F28F4EFE6CBFEF31FC2747E4D41708547216AC3B8F238E024824136FC9B509F8C47B1FA4198255A29A8FA587188C5FE94E6E16623C024064CB514B05F3B744A1FC83C0BEACAD9CEE91A87A901F8A0809EB8363A162A47A9CB5963E70702E73280EE52C7153A9F2CC0FA7C5277ABD3134262CF903FF55FC3B63F4102F63A6A8D49A2430B61B1E1E608D2A15D39430040308671AD23A295CE5EA8115F9F861CAE44CEC46DB155B8E608846DDDF9E9D1E699DF155729DC934593CB472C2408E78D7ECCDCD6B9E7609FEF08A6AAE7067E3115D0398E760ADDF3CEEEE8DA76E308658393EEE66874B1BCF89FA79C47BB71BA1BB18D97F76BE97A513C2975CEAD505F685F097207AAC78CCA8CE9C4DBBF41AEC314A42BEDE49C93B9522C166071CBF42D79589CE3B5A84AA80C8D66A665890B205B6D0462F6423F77F333A536C1548EE43622643AC09578A09F142BB1F53CEF93327D8535B5B8E32E72A62E2858156720958A045C3D26E5433539993D1
+99AB673E066FC1CBE607800E9CB24720DFF5585912BB350ABCACFAD2656C7BA9BCC353140E8ABA67E1A4BC1A3B90A19551E8557A2CF6C984DF3FFC7F5DD2137D984A2D4A78C93E4EDE27BAB36CBA6676F9A773F073EDDEADEF6593D17F1538CA30BBC445EB275DC6079891741750892382C6C5E1AC63AAA7F416244C1894CB513DA37D1AEB6EE8D73518B52B8505599513CE1A77F87B713878EC69209F3D8C2F56E81805FA39680BA6488CFDD88729B2D1498A6DC1C4785E71817E9AB1A4F7377777A562BF570D7E613D03766C584DBB72631DBFEC76A29EC6C3CE4C29AA966CE48EF7ACC0C472B49120C59B365B1F2F41881BE94AD9911448A11054F0FD2AB22084C2D95347D1F479C8E2D4A0B6B4A5CE6C7443701A3F8B8065842925B805E7FC9BB53882F1AEA88E4273C865A2643B1758DE35D7A31C21BF90E5973E48ED6D1AA11DC5E24E65D7DFF0EE89671741C99C0A7EEAB7DCB1855700905F57179C41B61E6F73BF4409274F62CDD649AAE9B9353EF24431DE9A4019EFAAD8022BFE8E7AB20C4BB0C8A565F5FADF6154F450DACF7D0DEBF374B6E9BD7C0DACD0611BBE5502A074C07BD2C0612D70D49D8B0FE8FF759CBB55FA32EEC599852E9BCA332A238C500817777C86C41551AA51AA38B174C65548042AF08219E51D8FF6873237C84FE49BFE3ED349412517605D58DF7CF312E45E00D8C444C5DAB87338F6FAA7F9E0A5FF819365F5C193398DD52860F9311862FC5C3DC4494AF3DC89065D54453FA08F4DEE76E00069A4E1C46AFF66880FB055611AB6DB11563C1D0411D6E89D25E24001AFD08B603E41310145E345679770F93D36537D3423A7803EFCFE60380F0BC0F9C54B39650276657CE82478B91FD7FDC6FABC011EB8D874353B0A9665046449DEE01DBFFEAD966F0F0C1F2963020733250963D0E71D93C0651B85AC31D8B478F5A1B237C676512B2A886A46C9A2E52BCFEF5070D8E796C085F97FCB6B94EF8786A4379AE410691D6D470A45783D9BDE263640464093186E808D328B975236669BD8376CD8147AA05AAB2DE3033DAA8266C0B677B98DAA919528B58A090C1C39645FB285D139FF89D1044859BAF87169A3D03837E2D39DEC109CE248609A514459DEBD347A4F51C27C3CD3A1AA7ACB473386DF2441ACE2A4D39A7006E6B405C1B0534BEA494B57230EB665315C22CC20A15060D24AAB852FB058D2EECE4A430BDE6FB4CFB901369CF764D26502CCC5D6EB724CB44AC8C756F60BF810335AE2709ADB29955C97CA60E402F0BCD55D62A4B7D774419D3F3A5CB1181B108485A3A9C0653E48BCF9B06D035153E6F8FA10F8D9B7553CEC93BBF026FA76EBC0A0B3C7BAFA59C13EFBC2808529E3DD7797BB01F6021679D3D15AB8435736974DCCEDDA8EB6C235823D1C2D72782D23D4A54919731C27A1D408C1DF78EF693A57
+11521CBCBE327A2864C6143CE6D51B28697D0A5834D20D245A10815143C9A361B0D29711C8D33098F25B3B1CBBF1F51B6ED599101E7FECBB09505F6CE210B8BF94380D57E492FAFBB6226199983B7C9A160685369D26FCF7CD1A518CDC99CDA3E5C674C8635932C7C028423E425D2764CCE482854A610EB749220F9398CC548B8ED62DA96B6F0F94CE72F6BB369ACF7BB428D7078E4211F401547E391CDCCBCBFEE54455BC75DEF8B59C4226337189DFF1DE94CCD0D01CC5738F5C69E02D7830576D31E2A6191C25A608497CDBA112F72E2C27E9CC2D89BC5B557845152E24A12A716559DFD36F5877414F6EB103DFDBC7ECB26B16AAF9729E9FAE24E4F3A051876E2B1063DE25E62C41C974CC4ECC262E75FE17478F8D1C9EA6F21923226330885F6E7344B03D236E92EAA848127784F6250D7A7F06CAD0A94DFAAB658970B452AC46DE0B0C01745526407CF06E8CAC0841B8BE5FBD9A005519DFF7AC0B97016F1EDC20FC0CAF78732E8CCD40C8AAC46A18CDBC0BB51E6E913EF8FE00B8D0A5EAC98A461C9C832CD74845E02E907D121C26D69B42E77F99147FB6CE85EDB4AF17B5DD320E96D0936F48B248B27AA52186119E0F6B5F506E35671FE458587475BC195C75108F4C4E006632F12B0693E344CD26916F615D39A14946E8BDB4C6904C9CFCC8758EBBCD2D1EC946F4CB4D0FC4E440F8904A0C97EFE27EAE242FB849ADBFA8EE7FD25F66E7936269DBD8FAF247C1B26BDA8EB951CB5E57D2D45190C3F880E10C9F99713BB7F7406F9193F6ADB3DAF7300A92357CC755ACB3CA5439B39A8D79019E9F1B48FCDDD72A15A6E4353FA002CFF8A01AFB20A3CB891210191D355926636AD527A87A8F19DBE8389E229F2BDC0360E87B21ADD0FB0FB9F6B0E2444EA68B53F0DED6BB94A076F7AECBE418A03BED8ED0DEF0CE7BC396D2EF8538C0781354DC06ED648A64EEA4638E13B22CC7B649CF47E1064AC4B3906BCA6CD66107D63A1252D94EEC362B9CBB0D3640CC34074E68B872A4192CB266F4373EEA0F916622F58871DD2A764E240410960B43AE278A921F71234A1A5AAC178FA3D6F95980EE8FCF50DBC1D6FE0226FCF806BC57A118AFB8714796B6E596894864CC369FB4D1787CDAE4EF1491927C1B5B844785133791046ACEC520540274B5F63218A23B004632D4257449552F138F14BFD4F94AD6E42E2B9AC029DB612F9FA98B212EAE9FE614A152E2D63E54DB61D008C7AD9BD1909BA0DBCFF168B8D1819870BB855A42184ECE972C00E0C05B851B5776D7986DA850DBB9D3C3405450C36AB79946799A4C01B0628D33714833B145152BC41FFF44D775E6721DF853B81CD72C82436F033128AFF9B0C3DE5224FEF1641B9A364123649E0F8534C9B0D1F0A54FAC4943EFA5940E118F31FFABCD8E5B900D040CB9821CF9FC9FED6CC034264737
+CC3050C49A5A90187C72BA53EA130C707CAD341A2F7703991CF6A33C3B0D62A8552FA01C39A632E0971C3ACAC13996CC71DF92DA83E2711288AE0AA9A44134F55C4364BB4E0F92422EF1DF59B3584FA13FF322540D63FD2D291E1CAF3F89DA98F84558C556B265E12EF20C70BB598D315A9B837DCE7D4AD7EFE723C593402C8EBBB9F42CB4623C99058E49BD5B65FA73508F9DE9B737DE05087284E3D52218FED02527BDCE404CEAF206860062A1CBC2CB2A9BAA4073576B6BC1D33E23552B63ECE493C39D1E7C2AF3BC30A93A34289D801B56349DC96983B16B4DD52E7A4F5C9FB694D54DA415B3034A3DCEE0980BA7C9A96B536D5053C982300155B10A4C58884BDEDB713FC838A4EADB89B08E39A4B5F083472434339595DD6B5E1F3C12CC61DF5340010081B7D17D92BE46A0D69EA772DF6DD753D982F171853D269B617C5C34B1B37CA8BEF46F5943191B70421F1FB752322D67618E8E5233504946927CCE3AFEDB4D1EAD579EDCFD564938323858F22B7C91A07DC222FE7EC5FDA0D1BC7DB6C7DFAC5A514B060ECCD4EE159E65670F987813A05915F54E5BB70A5159980A4DFBC6B966D2A445692B29869827AAAA4854676F860ACFB5F4B7BFF68EBB343CD943B9287BAF5A1A2D7902292D55A67D299622724AD3BA71809137611BA014CCF0C6292091DFA050DC3A4E270E660F6A868C7DB96CCCDD827F426CAB331A6006720840FC42EA90DD14B6800AB2D2336C4CD1B1BBB9796D50FA0BBC79C39A3DB71AE0C7E5FBBBB97ACCC6828AB084361E4B0AED945388A50AAF4E07B694A1331A1581A4FE1BEE36ED248D1C38EB7BE62B26C7514B3AEA6F1F436CC74364DE738CCCD2DE3A6D1EE1B09B4D708954419736BF69E68FCABF45A2658705C7145A19569A3EF11A65A0AE86BE5DE4716197E8F567EDA068D12784D4EAC6DFC00D6B99B0616B8FB66C9C700A545CDFEC0A2FD5FC1C4A7614CBAE908F38F631C49E2C3E2AAD009B05AE93AFCE9AA96217C9CB28563F6768C8F5496211894B5F4FD11A6034782DA8965FB80A1AC9453AD6AB16684D9EE6EE8BAC14493E4AB8638D3FA05F4ED89640A95C1D289EC9D7AF78EB32A736868694FBF2C968AA491A6FD7CA701858F47F412406C8DAF7F4B0755664C6F46F9B4AC3369B26179DA3C3CBA8DACF6AD6FBEB134287858F3166553556084C361924CEAF18E1799D926FC19AC2106B6D1468C8738389612EE7D1AD73911C44D0AC82EB618CAA87CDED43711EB19EF31A7BDFB525CD337D0633C549D956777823DC6A9F2802F7095501CBFA0A59BFA16B5543BBFA883FD821949B5C7D82A81540C36404F0BEF6EF0581D6698C3375D592E979852EC636FEE09DC85975BEAC30F0F5297D014137D457DCE93767E5EBB82AF1089EF3FD99F3694F087344D5B8328E468AD11BA76A0FB4AC9254E9579A8554
+A0A31A0F51C172C748157BDD3A75D7F6F226B873CFCC14ED059A01A9252DF0D1AD21F3697BA9AC786356CF1FE129ABB30DD248FD94B26F28A511B611AED4CAF60AAD116C1E98D9D18A3B0C9783330FE299F78C9F8B219318910F18AC731E56CA059C860A0A4613C5C1F49CE62FD0BB2D39B572599A645F69FF3517DC4CD0E0BF35F005CAC0B7EBF6B95B553B85E7F366837396DC848CC4607BA81F8C63B4F14C179E025CC92FA805EA78291B3378FE37B960C49A32ABEAD2E017D113625AC6CF4C60F77D5DB8A6E983295311FE8F1C5E7D20192195D005B7C2D7C7F903F6CB866DE2A159F210F2590FF2A28B00954FE6FE3D05087A646EC01BC8DCB5A869B64865580489E67562DC2743C8153B7FE39AFAFD5D7DCF93673855588D3A4DBEA8D1C8348939D98E528981B6FA12985C3AC5445F0E2C2D2D077B92564DABF567F47C3AB4814B6BC2660D6D20658DFBB3D60BC49CFE5FED243D92130E00A1318305FC7184C80B4993B744F2744D01495AEF1BCE5F596245228C43F6B6667925E4D0AC76DE0B4C77210757F8E48E78E082DE036E417F502FEF40BE50006BE30922160E16BE777C58716F720D3A68A8BC17CC333BCAAA462FED1C9AAAAF628E600616C9536519AE2ADA31F2212D1580FE9CEDC9DAFBCAC29F852A038F93231A36AD256C504F9FE9F24A600EDCD58917BDAA30CDBDA7EE712CD1403D5F476EF70FD50B8495237EF049EBEEFC967EDEFA64A5536A66EAA227CFF333BDC7D315251C6404E346F4B1BA5F375424A2C248E6AE65654709300D4EDD8B23BD935DF1AB485C752430FCFAFE8E2A64753CE6334301B3C6E9B267BE02454371898751AB9B3B2BADFB286A56C123AB083225FD00EA4EFE7F71E673946B5CFC273AADEC214668B7AA242ED2E01CF7C7D05F56471CEE61FB324BAC686515ED2B96711E690AF08DCB141AA70FD75EF8693E2E33810EDB90A019746ACEBD48FEF0A24F9BA779F91773F2AEBE4FD9CEB8817FEBF99A624421336B1207CF9B54C863509C56239C952B4E11176A8BE3C5241385485C96134617725445838863D0D331931B7A851E1C9E47801F017DA84AE4080222FC1060EC2EC042CD82E9AA116D36AB95BE5B893DBB2D620B5CE888C467F92751C088714B4E8309E5D27F26498E60CFA30F8B736BD27EABF6164F96D501A1C061BECB774598D86577FF5D46AF9F6E1744F40E7732243F69620CA36E6E779A1DA3F20DB732F6C58B2FD1134DBF15335C83EE23A44AF9251859DB0388AC2211B4D6567CCAA0F4A7EBF8087C90DC716402B917983441E100FD7D2485B6E5AEC823F8B009172888212BF52ABF7AB49367AFEC4BE9E72C81441D4A8CE0AFB8EE9BE73A6949FB85687524A51E2539FB692E32106D12BCA727788C8F04938CAD6D8E3A4803218984D610896A26DD67248D227116185A646B7DA4D620
+F6DD7C649061F8EE18906E80331A89CBAF88063C653C31295E23AE28A9A094BE44153A5698D1BEC41E3F05E9F7D0A4FC9B1AB9689D4FCCBF17D8C062CFDAED8A71C39CEFF546E5AF1B38405D74CC4B6F65B145BE9B309874CE7D0E3D8332CF7BD774097D318F9D39E1B539620F714DB3C20DD0AEA2740BF8D4DABC0ABDE2301D0203496ADB82B3D1A242CDEE2F51C9D0AFC6BBE5D811FF3BB3D0A25B981E79462012330C6B55518DEA5431FE55A6EE33CD135FB6A5E7F4AEDE6803A98730818AD0727B8B59A85989B1A771EF12C6056EA6489E724FF07AD4C80B6C500885666003D5F3343A3E8B76081E714635155DF3B08B38B993A51C25EB3CF5568D2F2C4DB068B5E0637572845399746E4567577C2D3A9C61807F613809AC837A89CE180760FE720BCBA5EC032970890171D5324661EBE50A944D3CA015B14DAE291C7ED45683F4F5C43AEF7A588BF04128666EAAB194C77066AAD3889406C022026C0753B5457CB9D98F785560A23CE730D17BFACE50D443563CEC92BA4A86B7F8869A8C19E37BFC5FEF5C5A1B8FFDE57C26C7556A3EE858F4897E4F7F87F904986B64BCFD5D12FB600BFAC35902D24509DBF0C61CFE7881D02EA69CD24595F9D3577983353CE3F1B7D7B2690F777F25436D0BE8A48C45BF42271577CDBFE2E34A704B8AC7EA1883333EEBAD2E3FA6C4453FFF5E9C48EA1716DD5894E9298EEAA89A8ABE4B72D613DCD9264346F09B9E2ECE3926E5768ADEA4FAC68957D367EB76D0D56C34EC9EDAEA211B6D60B4C6F6F283847A46F1DAD8DAEF342F8719798EE8CA21426188B50B5D9DF5D52ED0DF529631D86E34B1C0B1048DE115D0F70D9329E5B56BECCE7242AB6FF18C330D122F2F586CF64CDF3327BB418D9289BB1AA5754CB40CC4A13265A45AA4A2FE762FCCDCA81DA744F732F4EA0F18FB5072CC84A8E43203F96509304D1467422EABA316EA4B814D9CF991231C56120A774DF4659248EC28ECED559DB07C8722F7CB117DE59D51B036A4194A9046501EC923DCD2D06569121CDA18EB62693B19B5724C4C5B3E9B026DB4C95A3D0CC49BE3D20CB422AECCC4C5E745866EC14D3A8821B4D42CDCD160EAC29D1B1397104912407A22AAA5EADE7E74D755D1F31C4A38EC3EA4C29E3E22CF9C1519DFBEE68A21148B33418F96875D7E4F94A5A759C1A354C145510EF53B84C0D235EC564AB3DE18B61A7F3017482D78E7F1C4087EFFD320F520EA0554B1D2C4A7F0EA64AECA8714B35A4545A37D95281441B2F67F2D674B418870BED07E9016A4F61C81A2ABFEDB5BC42AFD6F869E208FC9EB8CCB5306DDD81C3E32E1A17F673C655062A157478B2E6ADDEEDCFAEAFB9621E38E37B48C592F7CA093F8D3A21BB36DDE6766ACD50A307DB63CD8AF97A1633CC7C0E25FFC832BF7CA6E7A1C5BAC4B8F50073947B548700D4DF086A0
+4FC96E91AF527D05234CDFDCEBAD455BACE2F4A88A67FB497A106CE9C58D1B056A62E99DE181C9745532DFF6E5F32B61A34D621675F4BACD8E9B5773C2BA378CF97723D756AAE0871C4A85A93E13F3D59F3300659CF49AAE8F1D0B2BF1131F9A6BA27D17BEED49A17888B16E19546976BBD17A8C7B793E36F7902639C6B4E54ACEAF6C2949334F929939D854270BFCD204246171E4D97011C56886A5567E92A737B3956E64B0A7F29BAEAB3D70F1B1038CDDA7FA80560DAA8FFC5F7FF7C54998B6474469716DC427A1657C6FFE519A6A45EF3D6D0E228CDF2C2BF43D176767573CCF490F55D2C2218601CEDF73B4365277FD0FD9D8E320D9CB0916AA763275CB09AF262F200D472F00996E1BF37319D58225A124C2F3F63FAFA3C3BEBBA6385D9525F9F9EC6E57BB8DDFBF5151E34A4D0B1D1D1980BFEFD9220166A8A2055CD3354286B7F52DF7B1AE4B53CF7C3D46EDA97C2F5F63B4CA3517AD77C8F1D943971D311CD2739CC68E54630B3B4D21CDF3FCB10E2097DF44980734351496E4713E15F0560A784AB80E85FC32633EBF440F2B7104851F50A121E298E79FED54D8B421872FC3691BBE4DE9974522170B288734E0C0CDE38FDD77C16F0D1B8453B1C97FC5E72089298582B5E93D4326B6B4BF163EDA007D257CD844F1AF172EB33AE09076C216157678135426A4428FB9C7E9F20A3393768B3E51A4A4980A066AE0A12CF78D7B05A5B3578BFD26F2D99B2CCC8B96819F57AC8D32BB01909E83AE3634ED6BFCB96C3D53B2D4F5B0D2A6EA59C288943ABCF986EAAC868D77F63F9F9636E7FEA1CF8669FAC1DDC08F9B982F914C7397419C051759BD5C25183F07DFEA8FEB3A02B37E3558DA9858AD6D29F520A8AE218432E0FF0AE82278B147EE5AA12E42F03050DE7CCBDB21DDAC6DE7FDD2F5117ACA12208E9FAE492E21ED32412846C887A3D74C59B3457599357466F9048B2A0052DE1ECB16399A864F6F4E6371935130D0F467C3D9228CD2037232E86C439AC6DB5ACEC7ACBB1939526AF63EF1F8DEF3C7E4CC5FA34F1F6FE9EE31493C6A964514D6563D668C9807754D3B8B3113D520796367CED2C56D2FE8A5D8B9F7E794CC4D1473B1D402A5B23518500A093752D863BC66B341E8FCBE52581A6F997788C7F111EDEC0E564222135720DDA37A88181AAA25B9BE3B7E61E1C84F011A331B76564CFFCB469CA9FD51BF6CAF889815E0F143198E85042508E0F7CDF1D305A692A93794AB12E1D6DC60E4EB8A9FB787A7FD3D9F87E213BF8184936F3A3E768878B5D94DA235A147704DAF75954D96FE7C83B23ABF0E7D52124AF96AF0591243F88AE833516EAA0C007C03781F0DF007B5DF7A61B0D836694544796253C5115CDF0210C880FEEC2147D6213FEFF3108FA994239CFF6B307868DEFF176455B69C69189B011C763ED3279B537EF82387
+8ABE546947FC161AB7C03114AD0B34543C601427D0ADF94017603EF7CC4C5F85C419C24B789E8AFE10FD2A6BD603612C3F5E84C833DAFD20AC8E8DF8F9DF996D13F75DECA969982A594648216DC1C2482A6386172DD18CAA608A2983F89E65450C9F4F39CF508E22E6C0F16F8157BE77F270D49E3C43C0285D61044C5B14A64B565E31F3AEF601DA7CF071BFAE8710C6DF8682A1DE43ED8DED4603DB85711950B3256DBC60EF87F048448F4747D0659A38CB7478A7C19E9CEF5EE6DCA35424F6985685BD5165638B47B0C1CFC70DF469830ECB21EA2224D892506CAEB7901B68BEFE4392DAA94DDCED531A3039A3B5DAAD2FB16A534C9E1EE8B6BF4CF83FF8EF890CDA330A931B8B7E1BDBEB961204402E01905B6C3289FA42755B3CC02DD274236912BBE1CFB34B92546F9F2DBF5AA5B71F4AF07B290CFFA3B97EEF37F749FBFA561A6BFA57D510CC10E9604742E8A175C2B907660315F2DEA0910D88534F70DD3654A2A003102BDFEB673E0491EE8BBF6CE9CDE8A7E5291CD6C50DFFDED632BC1592CA92721D9103B6F2B39A87C7FF7DC7899A95A5EB58056E3117D32653C100B80AC872AB595258E6E555EBDC3C92145044F3F7667A765560E5DF1367DC2F940114716DF3E99069831A2BE5CF6F31DCECC56C3636F84CFADA5A625B20C36995C39BF4C394CBA8CA35E03EAFEF86ABEF82B176485F9FAB2C38899275B4A66D08D4F847B2AF86BFA39C9BA7AF115F8DB1563DEC165588EAB6EB4FEFC5D7AF0C396202DCA94589BE79CEFC4B53A1E02499708FAFD9015CF471A2FD593630E6200D0C2A6E7CFE2A34CBBA8E8ED282DB7538F8974B68AC9C32EF129A74359B41BFEC6666082B66C285E415300229D29AF21D90B58119B0F5037851031C1B0E1DD33E20393BE5259CF35406226292DCDD1B22DCC70F575B5ECAC8E4D6FD16B5B6387F1CA8D78C1F6F61CEED8571C3B3B3C79B652FD8FFA7FABD1D83D6407AF25FCA9CC4E5E3CE1CA8D5F7FDDF06BCA244BB84A6B0F0B78232852EE310606F02DCA6530ED139EDB69F53B064EFAA3B48C5F84069E73A1052089783218385661AAC7D7887E12E6AA96E1C1EA94228DC617E5DE4097F4824BCBF798EB45DBEF673BEA62323F439BF4D36EE2CB4C7CCA6C691B947896C96A5151E46F3866AFA2BD9773802A9D65F9F2B7AA202C0C0F41DFC80FCA9FCE8ADE757CFA2BB188D78BC4E8B6D22E97ACB7F6B4E556AF8FD67B442715930C60625A5ECDE04E3221EF10EF266A916F158F1850F9B1A68F30F769BDFED7950625205D36D4EDB1D6A96AD4B90F9ADD6FD3E1324949494C29633A1A141B7462928717B0A979E7E2F4445BD8670286B6BC43C4CBFF69BCB7BC84B7DA6C5B2C73472CBE7FFD89DE09B9C6A4B2BD322B08926CB17518EBD0BA60C35D96B546BBEBFA167060BD8EA817E3479C816C0D2D1
+5A878288FD7B902E537706BF1CC05B313646CED57C1194B3A067F49BA35166E48C84959848743EC1EE4D6CE699A14822710D5DB816A8B7CA2AF46926778809D765C8297A5DA0B322C87D53F59AB918C35D9E775DE0D202B5F689FD76DBAE49C5F2F515046202BAA7D904651863F0EE8C8A30141C239EFDD5A5C66880A227B46E868DC4C03EA41CA6454F0CA43C3571C3EE23015FF7CBD01331D84F77743780338C95A358ECE69A702D486246FA89DCE31B05C0E1AEA75D8F79D40F386133925331B7F5860943FDD168C957FA9380BB726D89FCC4E2E71F2929A3F346E2541B8D233DF64739B61F426EE10A27263FF7AA8D8DBEE3C9FEAEBE567225280068E486DB35490EAA57474048DC0DEEEB729C2482CA2DFB2F9C3A176C01158329AFC6F1EC232FFF019BEC86D2DE4F3B5409273DA2004C84AF5AB56D071703AE4768DDF4215C5D8D189D819872C1967A119104A6FE5C1C702B185379208F33D90FDEE529C9ED6821B58D2B5E9436ED7957E28ACC35FC5468A08129D5D8836BE3A3A63AEAA35A7A10A109AAB0A1AA2073B073B3093FC96F417E18813D1AEEF478B94D0319CBF92847FA417AEF2EA1D30B6FEC91D3CCC86C280F60AEB0CC16DA6FE7EDC69B4DBC3569D85CF888A2384EF230E9490C55B0B25A34CC99E7DF9C6810A2FF29D840458427B73CF4084C29C2329C720740994BF7358EBE01F3DB160EE85FE92E5E5496A894B6D14D89D16EBF0C7DAE075F54C3CFB97BEBBD49A2F3F927595522BDA3A8D706CFA8C4F07CF1AD567ED8B543E7DF519B1CF59C6CAAB8A866191457E8DE3EF8C4860BEFA53C0AA4E3C3438F48A5BF5EE2FC7ACAF595C9CD39B16E38E2A67682DD278F8D7C4D442421DB094FFD5F9ED1BAAE613A293F855B19A26B5F7CCB41AB41253D15158EFE27AE4803DC4C4547686C8E6CFDCFA17CFBF332E855774CE898664D1DCBB4EFA0311399A13D1EEB6BD2F21B9F83C4891525A805A944C184AF7C79392A1FF1A621E5E3B3A089B26F10FBF14741CF9B06E8015AC3A1C766C467A7E11EBCA20EF9F898A25F7C833433CB2889B072D5E466277AEA873F3DE057643F480435AE7F565481B342E175FF0624C96B62171148B1F9D4EAEAF1748D2B440D5E264A5708DA1537BE11BBF4D33BCC487C8797022AB3C3226244F4E38AB59E5CF0F37DB58AA231DA862F83BD482784044F17420B732CC0B319B18A5391D89CBB1E422E85E60C1E0F38BDC5A8AECC8F82D177B352444839A484E9B31BFB29705C3F76D8610E9326E0103C050063D11D722A408CB67CD03871EE49ED7BED08F554A6DDC8A14B3675D45724199004C9D4A8A6DD8CB6968B2630BD8CA5C2235857A18D5B998593F37711635DCC9D8C9A95BCBF6A6C84FF12D3B7FBE06BE558326FBFEC0885E0D183E51C4E799D969BA0E89A3C0F6444FC6E206CBF1C04AFCB
+10F8C8732A60298AB7BD56C4FC319A17E65005016D45D3EAE54EA4CC6C5E596E8F7AFBBC000BB677BB77B1235F87E6FE93D00AF1BDA22B0F3EE681DE63F8A1B9BE82A250844FF2FA499F62FE76247876DC6F5717A68256BE262C98DC5D236E59AD49CCF8A53DD3F659EDEDF2474CCA617CAA1177A1F4AB1CE4204DD0DEC29815CA0B58403394092CBE41FC8A54B0359DBA8FE8974560AE3F5412897753C74CB4E33D6C1AC75555D70D14015FFEABDB9F44CE4F7A449644ACF81010E96FA33ACF8814DAC30648DF442E37F5C9B244851FBE389830E841BC5EE3700602612D5D27B1FB615545DECFBD47B6F7B1FF17EF3FC71D994470AB201E09949A9688133E334C7AF11E96767D93ECA1EA2AC0E6604D87FEF5A489AD4C58F313F822547AD258C4CD7BFDCE9BCB7C87163F6AA360FA7966B898D00E7C8D798DCBCD858C3C364486639DDCFD47629F36A2566B96E2499453E833B3D126F56BCB679822E740EBE24429FFDED0242C9323B11AED2A6C33E204096D0CFFE6710E5F6FF47F999B9EA45C4547C770710DA67AADA071332BB3EF0D263A378607E11B22DB660E6A64C184B6B86AEE8BB5380FA7EB4D60A59B1C3158FA2AD69B93C04B9F2FE51BF31C7B52EFA25F81BAE8C766D1F75C0E190678BA080058232F80A9483867CD737E5ED0400C0AF96B5AC4F0B229A58431F34CC3DEE183165A7B1F4FDE1CAAE35D2B6774A0619382F22D65591D0E9B9A3C4465A96C5B6D5DAC925F3A92C4B03A150E575FB3372B17D7050CC23BEDF221CD57E82F47CF512CBC8FC161912BAE4A6E4EEED50EAD0C828AD871E2C99EF6D7EAC3D9AC5A7909AB310E8C5F69B365EF0450570490F2F7A1DA19C5CD269910AA545AA5E39A3ABD6C4E7B3F5B9F53216DBEAEAC6F6194DD8D88BDCB7D88E98574CE17747878D81284B810F8B002D37C9A8C19FD1B7DDA9C29A207694E6556FF1978B38A45EB5264C4F670562233C7F3817A3667FF458095E24BAD343BA99EB980E4B33AB34004FFC7E18882957AA9177FE1D5CE697998C25D540538ECC29FB57808155D1E2B522BEDE23323B05349273556EEBA479F8E506B799C90A19D723AE7BF516B4BFCE3E63E8CC0FD31E504DCA7B40578C5F96744355B96C658D61A4463F55665452A3C5D95DDE0558B32A741C70F8E2B644480C3E4445E0DE978791B4CE303ED682A8EAAFC0B12C978482F5532BD291037C7799DEE4A873933B0E83D22428C439E79FA267DD1E8F5F34ACD54F71857356EEDAFF79CF7822A4DD2B99CF6BF4C27F24E5D329CAC2FA9D45DAD4371090D94C4CFFE528538F96073526BE3BF0B554A5C1E9D5A240175F6940EE172A47C62D9657DE3C836BE983013EFE6FC76E1BC6BBE784CF6DFA6B8D1A971C67CEA556526F58DB9B2240E60ABA080FE949CFD448C65A81EC778DD82B1D0F58A09FD44BB714168
+5A2503F742EA124DDED4B3EDD6A469FE8878CC91BFB87EE52031B616E6709F4912B23AB148DED2FDE22FE918433B3A0D38CD91B57F3D31E37E5B9A5B376D796DCAC6599B9E591C708D9C5955D3546E5D57C5FD8F84159A69D1C5A3FA113132A7E03C7671BC9A336219349E226FAD636A6C8FA639655824DAA8CE295F2381BA83F20C9002845F80B07C0DD9840795B2DE262909CF24BF2CA33FFF7C2F9B119AA7371AE1D02A7E019A61A221EBAC9A184422DD05F64D4282419F4DDCAA9C67BC443126175BB7D1D80ECBD685F938983DD4D9B52D7F94E938DE85C39FB8392EB453E9317DD8B67B4B196DDE9A8949282B900DEB0B553F53145EAB77FE0E91A7062A9DAC67A7CD713E4DE687A66566FBB756CD26305AC27A6F9080F712C198452CBF04491C148A73467AB3CCDD132C55721777C28C07F257F7C3C516ADBC8A8C937D10BB74CF231DE3A8FF0A63C95B7D6983165FFB541D53C36992D49F881E46147B9BE6FF738F81DA0A37FC16F743D728556B2C0A3D44D0981AB427C1C78684CB977BEC40E6D10595B89FCC90774D7A1E22D434E62C1E5605304A336CE65F2DAC46B6113CDF0B541111DB91FC64317FEF3D328B6E73D2C6890309B59705D0BBD4A10FCE7A5FBC31D87C9AD0A257DCA5C649590F1B7DFDBE4FC0C53438F11C2230AAF87C116DEAE65E0DFFFDD8C7DEC53D4BD31C291F7173A2812F463CF811DF4FCE614482DAF9C416B8D7D08267F264622B6037645055C0688828B6E20AE166517D41A30C46E8FB4361761119DC1A1B3B997FDA507125F2617C36B9B85647F61F669C7673F8316F1D4A924BE584C9BC47B9E201C056A6393BDCD3D0B55428E2286F49C2838CC4AD4BD20A4032A9B3354CD559791C76CEEF8AA3CC00DF7716CD1D1484D96083BDA0F09B837050D0FCEC426F016A82EF7D8BF94AC59E03C92D1E9FA71E32B2A3208101C1176740FC91FA7605490562FFCA861BBB8299A402D8A9164BDE09E6ACF6156738B01FF68CF4E6FD2DCCCA2B44671F4689DFE23864D1218BC940F6A9707D51C9036220DA4792A656B445C56DB45339CEF9F4FBBB8CB0A451900A4157036F585CBEA2B2643C5064DD9B0C2577556A9922FAC2255DE4A8DE1AAC7B68B2AAD33C1FC76C8526C873C0C5AC693417F0C64DB4590518E245672F043B1B4A65ED533B331C2CD8579A139E8280E39E56FFB8A043876B0C96FB96A9A8612E491F2A8B35197F095AD0A56E71AD0A5D2E4BF93F822BCA891D6E3EB854A52256E233875F4C9A8A37FB0D51E0F48B12A33E7C55A59CF2F788FB6FD7DEF327E50A4F65D44A30B3718EF05DFF8F883E42072A654379B123DD85E10087A45FA85AB2A8AAC34F90634F037A25F36958F6A5DDEB1485244D72227A63F7CB598059FF70CE8C989CC94A1591F9F945EF083E9411ECF76D2A65320DC0856E78062DAB9D
+C49DEF5E541733D8D947ED6E43CA3E38110364626A6DFAE9BCAADBADA67FFDE44F7083C4C455D8E42F8E8C407F2985C07DB386C8BC6EEF6557FC09086BFFDBE7B9F64275896F57CC99E08357CCBA5049C7A93951D6F27BEDD2B35733C71DA8F21D6EC8ED476AB7253F632F8105C36DC2F2E5FCE4E8EE33835D580E74311D0589CE7EDC0647F7AD22554F0D00149DFD71E91694436A64072F006320ECC1C43AFE700D89FD967E57FFDA3B1B7629B8D5C85255F3D893E6818A8D661F6A93ACE8F9C15DD73012B5EE56DED0D0814927D76C2AA8E278A5833A655C052BF999786FA4FA6DF5A5988D06B9858DC5E5BF5557D2622865EE67D352C66CCE9A7B09021A264E3916051DB58B2EB012E0646FEA7E16A5B4F1F0A0C1E4BF715527A2B114F4A156CDBAE6634417178EF394CB3BBE58FE7EE579761E46C2F0DDD7187A003B9E5EE7B4797E6469CEB9C11F87FFEC013B3599EB031433D15AF0348CF012A98DC52D8ACF2548B899CBB4A21CA5FDCD27D5E7BFF2830DB1691BB0992DA67BA605ACEAA5B1436626E021FA571ADAF376709DBF428A7F63BACFC70507E196861D49CF5DC28C7D9337B03354A43591CE26BCF58C487F1806256A938F55FE92D6040FE1BAC3B3507FC66A40917DDD0F6714F7744B43461F936F4B4C27480969799D67B32DC7D0181663D0088207641D9663C7390391B05D41A571BF077BBDB6E7863952460EF6F6F09CE8430B4B829284FA39A7E7F40FA9A0ACF4AD78F9468A54F5A3D0A3390F3EC80F0AB07552A4FACCB4C03A580CFBF6ADE7DAE0763CE291BEE5A0C66BE9FF41B7DC15BD6E1D51F2808CBE471666DFC6A83FBA02442181B98D3C4819C87A8197BF9E8C79A607FE0BFB35E63CAD6E8EB277E197849EEBCDEB59495B72E8E89DF07C42E699C51AB239C2571F4DD4CB15C68F0CEFA07A0B897CCF2249E981C6D38586312C9E522BA7F7D7CC7C8C48A5C804DD96CD74C9165BF983405762CD8CDE4DFCD85A6BFF5FE84A83BE92B90AD785BFF66AC066E7B0F0BB37CA391D7656B1C2FCE81D287CAEF694DEE33A12EDC92FC8DAFA1CA2CD66E4599AED9A9784F301F4E8D3C4DA14858135D446828D1E77A5C627BCC6DB59B9104E42E2799B6B012C1457B65D5CBC76E6E47E6985E83DF175A5221C0D818203E798B5B428D817758A160B6D03C2FFC87CE7AFCEDF8EF744FCC20C302BB07317B4D2105A4036DC7B704253A8E04575B13BFE8E08BA689961FE53B9D681A3E7570989FAFACD935188D3DDBB7C2643272F88E1A346FDD832ED7D4A9ED8B79168911027A5EA25F91B613C7005908082C2B190ABB3710B79C336767C8593A26354DCBBC7D7B9FBC772898E3DED5674D3A2B872036D5CED85CC0578E34D70F96CBF736E1B7C18201C628FA2475D224788CB738CF9652E66F77C70A874769F6D1D9C7C522D0B06CD68AF
+5CDE84389EDDC3D0DBF025EF3BF646465B417494F67E852DDB68DB9B173426ED2E8ECC291382E3D8B85BC2F3F4ED66E283076571E1FEE9EB8D6D849D7A35D221BDFAB3E22B2DC2513F232CBDD375A61E466129F249D5505DF7191F382F51D92F956B5B005E37E69DC2CD9A4F77380A70A7515CCA4C90FEDAE6A68BB35F9489259BE8BE54EE1B3BBCD5476F828F123C2484A90AA9B25335F76287952B204F3E2A33D04B7D400220A39C49AF824D517686B90E410B096173CE3813C57B0661A31EB9D03111506EC0F130D7456C8C00B41EB8DC8870AD5D575501BD966AC1D96DF8A373E811AB414ECD4E6C177CE8CAE4E0154FEDF3C8491403DAAE2B861D9013CE5857533C8D55234FDEE469046A12679665E3291CE5B551507241247DC65CB90D5A064462733B4C8A5564DB650E97A07CDE946CB61D0EC65EC11FE594E756F82B1C85A146DF0530B9363E53FE512479563A4A9A14F4DE1425D654902F35A7325630AA09C377A7784126FA6F4772BDDABEB5D4AE51B8EE0253E40786993236A6491D2C0DCABFEE96D269D2FEB0851011663D00A3144017B91FE304FE6538BECEC156E835A2EFD7FD4560217B4677BE812C9F165E00C206EF2F00758663A3FD5184D13802731E3EABC62366F62FE1E21A0049CE5B2EE184CB71091AE178AC15650F5933AA0F50C522D3D07884050F7DDA96A15EB87202C0B3FA9346D2BD94BAE21C34ADE797BC199328BC093E4EFDEA8BEE09438A1651D7E26163A8395EC534F0BAAC29F0A75110B7C18B7568C67268944317E41CCA69E16A6CC94091BAC2E0AFC863749274D7BA1678B46FB69C4DB222440D8E35FE53FD354BA38F55548DEB2D3804C0CC96E9EC4D9C5FC212E1C4CF2F2D5CB1D692D2539491C51F141E840B15542D7187229CC0A58608F75FC402D678179D72FA72455328AF3A67DEF20AEDF81D8422DC072D57675344A5FE67B43FB1B885549CB57E93AF13FC47FAF89AC8B1C0E6EFCBFAD12A5ADE08D2491EFCEFA48553FC27299316D2F5990CA19EEB6CAC09D5EC130B65EB857F9DBAA80375902E8CF0D40D510FEE6071375E41E1752C6F63FD8374DDF8DA5C2F28D19C1A7549A5349E20287ED133F2C6E268E94011458B961F464B7BA0657A7CB77BF0C7FB6EB1F99CD831F917AA632C7E4B43D8B7A5F08F310C22C1CDFE066C4D9925ACA61C54FA7D0F3D69CB1B6690848A21B314B9780813A1BFC44EDC7DF3017D16B4AE21ADCDC1829889F7AEFA4A3FEE2F80E180E857AB67E706BD9DCD4BEA5C973CF2049DB29BA0B9122B3FD7E2441A4AD9D3E23FD692BE1D1B5553628EB6A2C279DDA59AB020EF6B590CD7CE0438CEC537DC303BC63396A960AEF3B336F1EEC9464A0BA127E851CF6A9B7B009125DDAEF1FBD9D7A116F3A351D4A5D1214CD25575B4CDFA1FAC0F908509DAD93EA1B81E099802B569
+BEC452C57B318ACC942A5C03BDBD625B694E7229BB7A1DF409202EB085F793595D3535BB9249E56FCCFE3FED925C3AF2F0E35A01E16BE1FFD62F05C97506240FE8AED27DD2CB348541B2B16E81E2EB5528BA3860BBB85E85B5CA81487EB033B1B837931860BDCCF9BF5EE9350146E301854B7961A3CDEA03565AA193B50D67BEA9670732B13491646BC07A5C8D7EA1CFD2C32D61177172098DDFC862CA58BD53EBE3D45FCC68FB639FC74FDB2788CD8C00718F41D99E42765AD6C5244AC84BB59218D2EC402BB22862B093FBFF5D8A64CEF94E541D4AB9D7012A22651B6E3D20E85B58061322F3A18094FA7E655FE769122198ED6FD215C5E4E40F0F29C8B9EB8F3129E022B56B0A1CABD754BDA38170CABA925D46B908CF6B51167A9E37B25D495FD53044E0AB20C574DF054325D817CDDA633331943C984BF2C00C5EB38AC61DB0EA166094B05611DB1CBC0E81B21E77B708C4C1A98DFE99459E4A2E778865D12C0A4071945BC47B7B1EDFCC9729E836BC05E2C9E50B9C7F05DA47B20B1193407077C4F192AAD0D3C49D2F0C9FDA70C851C555D0C9B67508D0AE02AA5ACE261ADC73980BC6B1153964C2322061ED3F7751ACE5C5E10AA8411CDA7837DA05A9BABF9F0E4398C62356886EF3601DCB65DD396DE662C96AE2EA488E5BD39DD0EC898929F939544AA3ADA51B0F4F3A1F7487215A3B4FDD5C7C5841C693BAF93C34A9587DF9D5620BF5EA90F6114FFD8B58B90E755A47BA8B56794E702DA6CFC34ACA05CF7BF2037279579743AA2E2C6B1EAB41EDAD8B98E85C65F6F00C94C5158B69EFB8036C707F414CCDC02BC56FCF0133F095BF120B27D30F973BE70C6389C8AAE9813EB7A6EF7AB49696A0498C72030A84E35818FB2F7B2DC0336E597CE162E85DBD87D25DCA154BF060CA87280F47726B136C23276398D01C4A9D745578282953E5495A1EB789F5795814B8724459951A7E1E4CC57FD3502FAA6FDA9E65D49EFFB419BBE07623625E94955BE2914B29869310CF97406491CBCB76C126FCDA76E45383FF17667E1EBA47F78B94956AC0B9A4AA3B7A66F16C9754CAD80F5FB8744FE17E2E3DA34EEDB04282C6DEF18AB4798E8F1A3F54D35D8F3660384641CB85F1FCF7C3997D724CFA346A43B0921107F1E6071AF33010B4E98FDFC837F7640CF337492A324DA70404DB14D2EFD5C1A1220CEC073EF9A264200E5EDAFCDB913046D188D7D9A62446C4A26312956F03E4BFFE74C2C532543FFE33895710E99DC53686E0A798EDF8E357C5E50F21500555820A37D11F9BEEF6EE7202FE6316A76D5394B7AF92C93B6F36CFDEC4B8F75E7A009F2F0C6CC828A20A555A1EC791CF6BC77C34138370F2F45798E3833CB16A7D45C49FE13FBA6873CA689C7373CB50C3EDADE3C8B34F43D7A90BF51BA6716D2DD60167A0DA41B6B79F6BB4E5150700
+EE7775E66F0E2AA8FC6F4549744C0D44BF325910F429BB37361E3EFB2B8828F09EFBDD82C3EFFBF3CD551E4A2F8514597624F9F929C51076B59A8427256EF45E49F89F61C940F4D254B971B1D46E278A725A5E099D158221DF09309A3BB2D7DAFB77A6677ED9D1E0D3B13E18428D568ECD531368BF9728965796C3F863AD4769650FAE69F58F22C2D93D06D14D608642805976AB5950DF479C1F33D708F7354D978461E05533E550E474F6CF5FB0C723966091E850CFA588329B506043850A3EA94ACED85E630918F9180293C3839AD7B8077BCE8B7F6C61B5742F117C4CA5900E026C8D55D02C0E4723527BC6542E853BFD774FF4A8216EBADA79A7C4F09DBAC473085365708E55F1DF8E73813BF7FD4C3A8561872D9D62EDE7E5928B90B5BB56B93A8C57EF40ABE2876F04B04A701C8103FEB1B60F164BDCFA9AECA4982CE1B2B9A25C631DC437BB7F49EBF89DB58A9CBC47199FA1A330B2FDB24596E7064BA1CCF843575DEFE644A2C7235A16B0D4B416B11990327CB6001778CDFE644C4F666543538C74695A73FBDFA36F7F15508FC3F4E2ACF1482544898036A6E024E04E7FEAEFC7045AA3C5B694CDA1685385F23897A23F5733555D981F23758AE627C3E10674FF7FE3CF96A6325412D7F886DCF70678E0506D2D0A067FFD03D2B116B658A6A8FBA3A14CA5B6AB76F6CAA2FBA6B4D59E0004A1CB5C9C1733D6FEB31EFF1DA6623ADBE95DDD7C190A30BFDB01FA19295D71445D0B666835C55C200155C6A7F29C4C1540E41D6DC07E826B5C6CD7A7A87017626A007C585EC2C86283E493D0475DF8BFED9ADAC7408A26666F867ED816ECD3B760A244DB5ACF6AB2C71AA464100178500E079EE9736E89E23308915A06CB8B212945CEFB990D
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+ %endType1
+
+end
+
+%%EndFont
+bn
+bu fc
+{}mark T /Helvetica-Bold /|______Helvetica-Bold 0 rf
+bn
+100 fz
+bu fc
+2 F /|______Helvetica-Bold fnt
+bn
+-0.00460 0.(AUDITORY IMAGE MODEL  \(AIM\))ashow
+64 gr
+1190 540 1425 1579 106.5 106.5 1 rr
+0 gr
+1190.5 540.5 1424.5 1578.5 118.5 118.5 0 rr
+64 gr
+1274 724 1349 1416 1 rc
+1332 725 gm
+F 1 setTxMode
+75 fz
+bu fc
+2 F /|______Helvetica-Bold fnt
+bn
+(middle ear filtering)show
+64 gr
+1190 1619 1482 2661 106.5 106.5 1 rr
+0 gr
+1190.5 1619.5 1481.5 2660.5 118.5 118.5 0 rr
+64 gr
+1278 1778 1353 2483 1 rc
+1336 1779 gm
+F 1 setTxMode
+(middle ear filtering)show
+64 gr
+1486 540 2081 1578 106.5 106.5 1 rr
+0 gr
+1486.5 540.5 2080.5 1577.5 118.5 118.5 0 rr
+64 gr
+1528 745 1603 1370 1 rc
+1586 746 gm
+F 1 setTxMode
+(spectral analysis)show
+64 gr
+1958 583 2033 1566 1 rc
+2016 584 gm
+F 1 setTxMode
+3 fs
+bu fc
+
+%%BeginFont: Helvetica-BoldOblique
+%!PS-TrueTypeFont-1-1-1
+25 dict begin
+/FontName /Helvetica-BoldOblique def
+/Encoding 256 array
+0 1 255{1 index exch/.notdef put}for
+dup 0 /.null put
+dup 8 /.null put
+dup 9 /space put
+dup 13 /nonmarkingreturn put
+dup 29 /.null put
+dup 32 /space put
+dup 33 /exclam put
+dup 34 /quotedbl put
+dup 35 /numbersign put
+dup 36 /dollar put
+dup 37 /percent put
+dup 38 /ampersand put
+dup 39 /quotesingle put
+dup 40 /parenleft put
+dup 41 /parenright put
+dup 42 /asterisk put
+dup 43 /plus put
+dup 44 /comma put
+dup 45 /hyphen put
+dup 46 /period put
+dup 47 /slash put
+dup 48 /zero put
+dup 49 /one put
+dup 50 /two put
+dup 51 /three put
+dup 52 /four put
+dup 53 /five put
+dup 54 /six put
+dup 55 /seven put
+dup 56 /eight put
+dup 57 /nine put
+dup 58 /colon put
+dup 59 /semicolon put
+dup 60 /less put
+dup 61 /equal put
+dup 62 /greater put
+dup 63 /question put
+dup 64 /at put
+dup 65 /A put
+dup 66 /B put
+dup 67 /C put
+dup 68 /D put
+dup 69 /E put
+dup 70 /F put
+dup 71 /G put
+dup 72 /H put
+dup 73 /I put
+dup 74 /J put
+dup 75 /K put
+dup 76 /L put
+dup 77 /M put
+dup 78 /N put
+dup 79 /O put
+dup 80 /P put
+dup 81 /Q put
+dup 82 /R put
+dup 83 /S put
+dup 84 /T put
+dup 85 /U put
+dup 86 /V put
+dup 87 /W put
+dup 88 /X put
+dup 89 /Y put
+dup 90 /Z put
+dup 91 /bracketleft put
+dup 92 /backslash put
+dup 93 /bracketright put
+dup 94 /asciicircum put
+dup 95 /underscore put
+dup 96 /grave put
+dup 97 /a put
+dup 98 /b put
+dup 99 /c put
+dup 100 /d put
+dup 101 /e put
+dup 102 /f put
+dup 103 /g put
+dup 104 /h put
+dup 105 /i put
+dup 106 /j put
+dup 107 /k put
+dup 108 /l put
+dup 109 /m put
+dup 110 /n put
+dup 111 /o put
+dup 112 /p put
+dup 113 /q put
+dup 114 /r put
+dup 115 /s put
+dup 116 /t put
+dup 117 /u put
+dup 118 /v put
+dup 119 /w put
+dup 120 /x put
+dup 121 /y put
+dup 122 /z put
+dup 123 /braceleft put
+dup 124 /bar put
+dup 125 /braceright put
+dup 126 /asciitilde put
+dup 128 /Adieresis put
+dup 129 /Aring put
+dup 130 /Ccedilla put
+dup 131 /Eacute put
+dup 132 /Ntilde put
+dup 133 /Odieresis put
+dup 134 /Udieresis put
+dup 135 /aacute put
+dup 136 /agrave put
+dup 137 /acircumflex put
+dup 138 /adieresis put
+dup 139 /atilde put
+dup 140 /aring put
+dup 141 /ccedilla put
+dup 142 /eacute put
+dup 143 /egrave put
+dup 144 /ecircumflex put
+dup 145 /edieresis put
+dup 146 /iacute put
+dup 147 /igrave put
+dup 148 /icircumflex put
+dup 149 /idieresis put
+dup 150 /ntilde put
+dup 151 /oacute put
+dup 152 /ograve put
+dup 153 /ocircumflex put
+dup 154 /odieresis put
+dup 155 /otilde put
+dup 156 /uacute put
+dup 157 /ugrave put
+dup 158 /ucircumflex put
+dup 159 /udieresis put
+dup 160 /dagger put
+dup 161 /degree put
+dup 162 /cent put
+dup 163 /sterling put
+dup 164 /section put
+dup 165 /bullet put
+dup 166 /paragraph put
+dup 167 /germandbls put
+dup 168 /registered put
+dup 169 /copyright put
+dup 170 /trademark put
+dup 171 /acute put
+dup 172 /dieresis put
+dup 173 /notequal put
+dup 174 /AE put
+dup 175 /Oslash put
+dup 176 /infinity put
+dup 177 /plusminus put
+dup 178 /lessequal put
+dup 179 /greaterequal put
+dup 180 /yen put
+dup 181 /mu put
+dup 182 /partialdiff put
+dup 183 /summation put
+dup 184 /product put
+dup 185 /pi put
+dup 186 /integral put
+dup 187 /ordfeminine put
+dup 188 /ordmasculine put
+dup 189 /Omega put
+dup 190 /ae put
+dup 191 /oslash put
+dup 192 /questiondown put
+dup 193 /exclamdown put
+dup 194 /logicalnot put
+dup 195 /radical put
+dup 196 /florin put
+dup 197 /approxequal put
+dup 198 /Delta put
+dup 199 /guillemotleft put
+dup 200 /guillemotright put
+dup 201 /ellipsis put
+dup 202 /nobreakspace put
+dup 203 /Agrave put
+dup 204 /Atilde put
+dup 205 /Otilde put
+dup 206 /OE put
+dup 207 /oe put
+dup 208 /endash put
+dup 209 /emdash put
+dup 210 /quotedblleft put
+dup 211 /quotedblright put
+dup 212 /quoteleft put
+dup 213 /quoteright put
+dup 214 /divide put
+dup 215 /lozenge put
+dup 216 /ydieresis put
+dup 217 /Ydieresis put
+dup 218 /fraction put
+dup 219 /currency put
+dup 220 /guilsinglleft put
+dup 221 /guilsinglright put
+dup 222 /fi put
+dup 223 /fl put
+dup 224 /daggerdbl put
+dup 225 /periodcentered put
+dup 226 /quotesinglbase put
+dup 227 /quotedblbase put
+dup 228 /perthousand put
+dup 229 /Acircumflex put
+dup 230 /Ecircumflex put
+dup 231 /Aacute put
+dup 232 /Edieresis put
+dup 233 /Egrave put
+dup 234 /Iacute put
+dup 235 /Icircumflex put
+dup 236 /Idieresis put
+dup 237 /Igrave put
+dup 238 /Oacute put
+dup 239 /Ocircumflex put
+dup 240 /apple put
+dup 241 /Ograve put
+dup 242 /Uacute put
+dup 243 /Ucircumflex put
+dup 244 /Ugrave put
+dup 245 /dotlessi put
+dup 246 /circumflex put
+dup 247 /tilde put
+dup 248 /macron put
+dup 249 /breve put
+dup 250 /dotaccent put
+dup 251 /ring put
+dup 252 /cedilla put
+dup 253 /hungarumlaut put
+dup 254 /ogonek put
+dup 255 /caron put
+readonly def
+/PaintType 0 def
+/fcheckload{{pop}{save 3 dict begin/mystring 2050 string def exch/endstring exch def{currentfile mystring readline not{stop}if endstring eq{exit}if}loop end restore}ifelse}bind def
+userdict/type42known known not{/type42known systemdict/resourcestatus known{42/FontType resourcestatus{pop pop true}{false}ifelse}{false}ifelse def}if
+/truedictknown userdict/TrueDict known{TrueDict dup /initer known 1 index /render known 2 index /imagemaskwrapper known 4 -1 roll /bander known and and and}{false}ifelse def
+%beginsfnt
+truedictknown type42known or( %endsfnt)exch fcheckload
+/FontMatrix [1 0 0 1 0 0] def
+/FontBBox[2048 -349 1 index div -475 2 index div 2050 3 index div 2016 5 -1 roll div]cvx def
+/FontType type42known{42}{3}ifelse def
+systemdict/product 2 copy known{get dup(LaserWriter IIf)eq exch(LaserWriter IIg)eq or version(2010.113)eq and not}{pop pop true}ifelse{/UniqueID 16#00B018F1 def}if/sfnts[<
+
+00010000000900090009000963767420664128BC0000009C000003786670676D3E898A130000041400000329676C7966C98307AC0000074000009DA268656164ABA250870000A4E400000036686865610CD105D80000A51C00000024686D74787E0548D20000A540000004086C6F63610055C78A0000A9480000040C6D6178700945034A0000AD5400000020707265706551528F0000AD74000003BB05C0001105C2002D0597001D0442001D0000FFDA0000FFDB0000FFDAFE53FFEF05D0000AFFFDFFED03340000012200000122DFFB011400AF000700B7007E000400D200AA0109002300ED013200D9011D012A00D800FE00DB00E2001A008B00A0001A004500E801F6000900E90128013200360082009E009FFF700070003F003F00E801050015003800E9FF7BFFC8FFF90042008A00C401070113011DFFB9002F00870087009A009C010C0262FFB10018004C00770080008200C900DAFFB2FFEA001A003600E50111012F043BFFDD00020005001A0039008900AA00B701210123012A015BFFE5000200180023005C00AAFF4DFF76FFB2FFEF001A002F004E007B008A00E1011F0126012B019A01DE03EDFF80FF8E0007001C004E005500630063006D00810098009C00AD011F01260162041C051500390044004B0063008E00CC00E800F2010001290142017802D503EA03F0043B049AFFC400050055005C0060009F0103011D012401550164017001AD01B401C301F602370261033903D5047004A100020055008800A100BD00C700D300DD00EB00ED00FA00FD0104012B013E014F017B019D01AD01E20233025D027D028C02DA02EF033103DE0407048B058505BBFF04FFD5FFFA0007001E002A003B004700510058006500650066006E0075007F00840107009700B100C300CC00DF00DF010A0110012F013101470154015B016B0179009101A401BA01DC01E401E601E901F60213021F0223022F0276027D0282028902AD02B202B902ED03110374037D03C003DE03F60415045D04C004C004DF052D0574061C064B0751FE94FEDFFF2DFF90FF9AFFEA0016001600240029002D003E0104006D006D008400870089008E009C00A400AB00AE00B200B2FFFB013900C400D100DF00E100EF00F70121011C011C012101320138015001510154016C016D017F019801A401AA01B601BA01BB01BB00D701D701FB01FB01FE00190209022D025B026102790279029A009802D302DA02EF030C03210328032D034B0353FFF103AD03B103F20425045A0471047B048A0498049F051C053D0557055A0570059505B605CB05D605EF05F4061D068706A406B406D307080734079807FE012201320120012500B400BE0082009603700132012400430184011D015600CC010500ED00C500FB00F900C000A7011D00FE035500880026FFA100B8FF8800DD00BD00B5
+
+037C003C00910293024AFF3F03A803090132FFF7402A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A090807060504030201002C4523466020B02660B004262348482D2C452346236120B02661B004262348482D2C45234660B0206120B04660B004262348482D2C4523462361B0206020B02661B02061B004262348482D2C45234660B0406120B06660B004262348482D2C4523462361B0406020B02661B04061B004262348482D2C0110203C003C2D2C20452320B0CD442320B8015A51582320B08D44235920B0ED51582320B04D44235920B09051582320B00D44235921212D2C20204518684420B001602045B04676688A4560442D2C01B9400000000A2D2C00B9000040000B2D2C2045B00043617D6818B0004360442D2C45B01A234445B01923442D2C2045B00325456164B050515845441B2121592D2CB00143632362B0002342B00F2B2D2C2045B0004360442D2C20B0032552582359212D2C69B04061B0008B0C6423648BB8400062600C642364615C58B0036159B002602D2C45B0112BB0172344B0177AE5182D2C45B0112BB01723442D2C45B0112BB017458CB0172344B0177AE5182D2CB002254661658A46B040608B482D2CB0022546608A46B040618C482D2C4B53205C58B002855958B00185592D2C20B0032545B019234445B01A23444565234520B00325606A20B009234223688A6A606120B0005058B21A401A4523604459B0005258B219401945236044592D2CB9187E3B210B2D2CB92D412D410B2D2CB93B21187E0B2D2CB93B21E7830B2D2CB92D41D2C00B2D2CB9187EC4E00B2D2C4B525845441B2121592D2C0120B003252349B04060B0206320B000525823B002253823B002256538008A63381B212121212159012D2C456920B00943B0022660B00325B005254961B0805358B21940194523616844B21A401A4523606A44B209191A45652345604259B00943608A103A2D2C01B005251023208AF500B0016023EDEC2D2C01B005251023208AF500B0016123EDEC2D2C01B0062510F500EDEC2D2C20B001600110203C003C2D2C20B001610110203C003C2D2C764520B003254523616818236860442D2C7645B00325452361682318456860442D2C7645B0032545616823452361442D0000000002009A0000053D05C200030007003E402105061D02010004071D03000A05041D0303021A0906071D0100190809AA216C3C182B2B4EF43C4DFD3C4E10F63C4D10FD3C003F3CFD3C3F3CFD3C313033112111271121119A04A3B8FCCD05C2FA3EB80452FBAE00000200E10000021A05BD00050009004340220205000004590728090A0B17171A0870091C0003040304017000190A0B7021813C182B2B4EF44DE539397D2F7C2F1810F4F54E456544E6004D3FFDEE3F3939313013211103230313
+
+211121E1013951955307012AFED605BDFE8AFD5002B0FCDAFEDF00020017036102A305C200030007003A401E0206BC0304000917171A00230194022303070423059406230719086C3C182B4E10F44DF4FDF410DCF4FDF44E456544E6003F3C4DFD3C3130010323032303230302A32FB42E6A30B42D05C2FD9F0261FD9F026100000200000000047105970003001F01A040EC0A0D080F0A1009170A180B19091A3909390C4A094A0C58005A0D5A1058145918591969186919790F9714991EAC0AAD0BA80FA710A218A219BB0ABB0BB90FB618B619C90EDA00D80FD81AEA0DEA0FE714E71CF90FF71C2B0901090B0913180117101813290E2618291E57199514A6140C8A018A1A02121516161104071F1F08000415190E010712190E0207121C0B0304151C0B0504151D0A0607121D0A0908111D0A0C08111C0B0D0811190E100811180F130712180F140415180F171F16180F1A1F16190E1B1F161C0B1E1F161D0A16151208070406111F0906051E041D0D01001A04190C02031B040B1C1CB801A5400E121D1D0A1013141704180F0F1818B801A540151219190E1D1C19180F0E0B0A08111F0E0A040C0811B801A6B7020712B916030415B801A640161B1F1685191C1D03180A2117171A11BF1F1F206747182B103C10FD4E456544E64D003F173CF43C3CFD3C3C10F43C3CFD3C3C3F3C0111121739872E2B7D10C507173C872E182B7D10C5173C10173C10173C01111217390F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F87103C3C87103C3C31300172715D0113230321331323373313330333133303330723033307230323132303231323026351A64EFE6DCB4FCC2DCC6DC76DA66AC76AC92DC951CC2DCC6BC76BA46DC76DCB02380124FEDC0124A80193FE6D0193FE6DA8FEDCA8FE700190FE7001900000030038FF13042F063400080010003D007C40433F043F054F044F05780BAB02AF03AF04AF05098A2D992D02351D100804183034092B280518CC001C3D12130D2A353408000511291D1C10090512123917302F04393F0CB80132B52118173F473E4E1076C418D64DCDD4FD4E10DCCDD4CD1112392F173CDD173C003FC4C4DDD4E43FC4DDC4C4111739313001715D253637363534272627030E01151417161713233526272613211617161711272E01353436373637363735331516171617212627262711161716151407060702684F243F3B23545F57543F23496161C561AB03010E0E19277251BF9D3D37475735665FA35DA906FEF908162664EE5287B9719BBB0A1A2E7156321D1F028E02594D54311B17FBA2C716407301157E2B431401AB1838C88D5D9837471B110885870D436BF059294707FE83523F69BFFC72460C000005002FFFDA06E305AA000B00170023002F00330102406ADF05D00BDB0CDB10D412D416DF1AD020DB24DB28D52AD52E
+
+0C580054015B03580458065B075409570A5B185819581B5B1C541E571F58215422104401440244034418442244235401540254035418542254230CDF02D805D008D81AD01DDF23D92B075B005B2102313232B801AA405812333330323302083130231D2C201ACF2020261C3233090E200BCF0520141C3130002F1D3F1D4F1D4F234F295F1D5F235F290829201DCF30230123202F352F0830024017501704172002CF301101082011193547347D46182B1076CC4EF44DFD5DF6FD5D10DEFD5DF6FD5D003F3CF4FDF6FD3F3CF4FDF6FD011112393911123939872E3D2B7D10C531300172715D0072710036353426232206151416332406232226353436333216150026232206151416333236351606232226353436333216150133012301E55D5D42425D5D420174D99B9ADADA9A9ADA02F75D42425D5D42425DD5DA9A9ADADA9A9ADAFDED98FCD89B03905D42425D5D42425D05DADA9A9ADADA9AFD6A5D5D42425D5D429ADADA9A9BD9DA9A0453FA30000003006FFFDC059C05BD00220031003B019D41A00009001B005B001B00550021006700210076002100C5001000CD001800070076002600010006000B000B0007002F0031003F003100590037009000170096001800CA001000CD001100C6001800E8003700F90037000C00090037001900370025001100260017008B0033009800330006001B001A0037001A0038001B001A001A0003000F001B0010001A001800190026002600190003003B00260031001B000C002A0018001A00140013001B001A0018003400030026002D00140010000F001A000F00220012003800380037001B0038003100370010000F0003000C002A00380037001000030034000F002D001400DB001F002D002000090000001A000A00340032001F000B001300540014001C0015003D0019000C0032002A01100019001A003D003100540006008D003B006E00220019003C003D012100210090004600182B2B4EF44DFDFDED4E10F64DFDED10F4F4ED003FED3F3FED10ED1139111739011112173912392B872E2B2B7D10C500111239391239113901111239391112391239113987102BC42B3C2B3C87102B3C2B3C2B3C313001715D00715D12363F012E0135343633321615140607133E0137330607060701212706070623220235001716173637363534262322070615021633323637010E01156F84961F4046D8AC9DCD7B77D1242701FD063A2048010CFEA6664A407295E0FC01B91C123C3C1A323C3D2621329D775D467D27FEF26B45020ABE5D13489651A1B5B99082A245FEFE347A4486894D5DFEBE7D45213B0108A102C42C1D4A2A1D363F2E48151F43FCD47A4128014E476C4100000100630361017405C20003002C401702BC03000517171A00230194022303190405CD219089182B2B4EF44DF4FDF44E456544E6
+
+003F4DED313001032303017432AD3205C2FD9F0261000001005DFE63026505DA0013004640292703261077027710870287100604110F131419130E0F0405136E09FA2F059F0502051A151415D52142B901AC00182B2B104EF64D71FCFD1139393910E4003F3F3130015D1213363F0117060706111417161F0123262726355D82485347A48B325320317E3DA9A255640333012CA6736202FE93F6FED0C4A5FDE870DED7FAFD0000010015FE63024D05DA001300344018121109131517171A120D081309036E0DFA09191415D52142B901AC00182B2BF4F4FD11393912394E456544E64D003F3F3130001712111003060F0123363712113427262F013301894F758B4E4547D384345920317E3DD70506B8FEF2FEEEFED3FEC9AE5861EE9801010132C4A6FDE7700001002F032502DC05CB000E00D940896B006B056B066B0E7A007A057A067A0E8109850A810B960AA50AB90AC90AD906D90E11470A540A020100002F120E0E0D000E0A0B0A090B2F120C0C0D0B0C0A090A0B092F12080807080905040506042F12070706060E0705000401A10210080C090B0D07060D0C0B0004010E090807050406041006040A0A50046004029004A00402040E010F7D46182B10D4C4DD5D713D392F1810C4C41112173911121739003F3CDD3CDD3C3FED3C39391139390104872E2B087D10C51808872E2B087D10C51808872E2B087D10C51808872E2B047D10C5313000715D1317353315371707170727072737275ED1ADD12FD58B808B8F808CD5051E44F1F1449542C75BBCBC5BC7420001004900000484043B000B003A401D0700220601010A03060A0A0D17171A0685040922030A8500190C6A46182B4E10F44DF43CFD3CF44E456544E6003F3F12392F3C4DFD3C313013112111211121112111211149019A0107019AFE66FEF9019C0105019AFE66FEFBFE64019C0000010076FEA501AA012A000D003B401F00EE0A08040D710528040A0F17171A090A035A06700004190E0F70217F3C182B2B4EF43C4DFDED39394E456544E64D003FEDF4113939ED3130173E0137231121111406070E012376565106AD01342431358F1BED187065012AFEFE4494363A3B0001002F01B4026D02C2000300214012002203011A05DF000100190405D5217D46182B2B4EE45D10E64D002FED3130132111212F023EFDC202C2FEF200010080000001AF012A0003002640130128030A0517171A01700019040570217F3C182B2B4EF44DFD4E456544E6003F4DED31301321112180012FFED1012AFED6000001FF90000002B805EF000300594030390139027700760187019702A800B702C702D701F7010B0102025D120303000002010301000302030A011A0503190405BA016D00210129B1F0182B2B194EE410F618003F3C3F3C4D0111123939872E2B7D10C53130015D0133012301
+
+CBEDFDC3EB05EFFA110000020040FFDC042805B4000B00170075405917012707D70F03380D370F371338154B0D440F44134F159815B713BA15C613CA150D1700530676007606040606A606C80F03084017050240110D05830E0B830EA71014301402701480149014A014B014D014F01407141947184E1076C418D45D71E44DED10ED003FED3FED31300072715D01720012333212351026232206110012111002212002111012210163527F7F4F4F7F7F5201E6DFDFFEEBFEEBDFDF011501CDFEF70109FA0106FCFCFEFA02EDFE7AFE99FE99FE7C01840167016701860001008E0000030705AA000D0032401E29053905020D01CC09040C0C0BB3000938200C300C600CB00C040C0F470E1076C418D45DE4CCED003F3FF4CD3130005D13353637363736373635331121118E8736563625130BEDFEDC03E8C2060C133927412713FA5603E8000100400000042105B1002100884061071401041B071C6F1203041D19011618660160046206671A97019502981AA6010B001910193419351C041C190402041E0F0A4013051EA1210C1E1C04030E07B316731F01020E630F7C1FA7102101702180219021A021B021D021F02107212347224E1076C418D45D71E44DF4ED393910F4ED111739003FFD3FEDDD111739015D31305D71007136373637363736353426232207060721363736213204151407060F010E0107211521443F3DE3C53A59665F822F1B05FEEB073C720123E60110603F90726B4F1B0279FC1F9C8191A28D3D5F715C7A61387AB972D9FFD2A17D5366514C442DFB0000010036FFDC042105B100300076B609200198220130B80108403C2C171E25250BF66F0CDF0C020C0C2C13401E0504402C0D252507106F210783290C8C1663177C006329A71030303002A030B030D030F03004303247314E1076C418D45D71E44DEDF4FDE610EDD4ED12392F003FED3FED12392F5DFD393D2F1810CD10ED3130005D0171011417163332363534272623353637363534262322061721363736373E0133321615140706073217161514022320272627014E1C3489547D74428E8B375F6158655F02FEF60421234B389A70D0FF4C303427496DFFFAFECC783F0701BD573969736C8F301BCC02192A805368806B6C6155483336D7B5805837144365AFB8FEE9C96BAD00000200360000042F05A1000A000D008F40450E0C480C480D8F0CDC0C051F0C0158077A0789079907A80705050D460D830DD60D04110D01040500030C090D0A01080B0D0A030C0C0D0DF512060607060C07040A0DF70005B8014C4009030C0D07050C03B30ABB013A0001000901A9B3060F470E4E1076C4184DD4F43CE4FD3C113939003FF43CFD3C3F393901872E2B047D10C50F0F0F31300172715D0072710123112111213501211133211101042FA4FEE9FDC202150140A4FE45FE9501
+
+38FEC80138F90370FC760272FD8E00010036FFDA042105970020005E40160E0F0FA1121212130D0EC213094017171D12A10F0420B80155401903401D0D113813120D0006831A0FC3006F0E381AA720224721104E76C418D4E44DE4FDED10ED11393939E4003FEDED3FED12392FFD39F4C401872E2B7D10C53130011E01333236353426232207060725132115210336373633320415140021222427015211605C6A6F686E34264322FF0066031FFDAF3442253E59B4010CFEFEFEFFCFFEF60F01845D6595716F990D18410C0321F2FEC32B0E17F2E7C9FEC4DECC00020040FFDA042A05B8000C002C007540494C0D4C2C5C0D5C2C0437265713022C110A0215084018181E27114029052002401E0D0A0C0D6F2C7C056F1B15E40C6F1BA71022302202702280229022A022B022D022F02207222E472D4E1076C4184DD45D714EE44DFDE510EDF4ED1139003FED393FED3912392FED39113910CD3130015D005D001633323635342623220706150134272623220706073E013332121514022320272611343736373E0133321617015E7E615F6D7C5A49385401911B2E5D8B3B200C358C5AC1F7F2FFFEEE82650E19483EC98CCAF00F0156948F727F872C41910272232A449C56A83F3AFEFACCCBFECAE5B3011BA668B97B6980CFAC00010034000004380597000E003E402416021503F70503000CA10D04070C0B00068307C60D7300A8100C300C02D00C010C10470F4E1076C418D45D71E44DF4F4ED1139003F3FFD393130015D010602070602152112131237211321043840E44D3D62FED80DF39D6AFD2D04040004B83FFEBDAC87FE7A7D018601A5010567010000030036FFDA042505B1000B0023002F00624016681F011A0E0E082626202C4014050240200D1A176329B8015FB605831D0E11632FB8015F40160B831DA81023302302A023B023D023F02304233147304E1076C418D45D71E44DFDF4ED3910FDF4ED39003FED3FED12392FCD392EC4313001015D0016333236353426232206152436372E01353436333216151406071E0115140023220235001633323635342623220615015E6F62626F71606071FED86F6B693FEED9D9EE3F696B6CFEF1F3F3FA01426156575F5F575661013A76766B6F73736F67C63246A3479EDFDF9E47A33C3CC67AB7FEFF0101B7023364644F56616156000002003DFFD6042D05B6001C002A005A40361E231519402A2A0A234002050E11400A0D1E0E15E42083060E6F0D7C276F06A8101C301C02801C901CA01CB01CD01CF01C061C2C472B4E1076C418D45D71E44DEDF4ED4D10FDE51239003FFDC53FED12392FED39123931301200332013161110070221222427211E0133323736370607062322243504373635342623220706151416333D010DD7014B7B464380FEAAA3FEFC13011C0A58498D391F08272C5075
+
+ADFEF4023234617364493452696D04950121FEDBA6FEF1FEF9B0FEB1C1B940509C56A5311A30EFE1E8223E997B90294099818100000200E8000002170417000300070033B2012803B8011540150528070A0917171A05017004001908097021813C182B2B4EF43C4DFD3C4E456544E6003F4DEDF6ED31301321112111211121E8012FFED1012FFED10417FED6FE3DFED6000200E8FEA5021C041700030012004FB7070F170F02012803B8011540210B280904EE0D1271090A1417171A0106090E085A0B701200091913147021813C182B2B4EF43C3C4DFDE4391139C44E456544E6003F4DF439ED10EDFEED3130015D132111211136373637231121111406070E0123E8012FFED165281907AD0134243133901C0417FED6FC261D4A2E58012AFEFE459336393C00010017FFDE04B1045E000600634034030403020422120505060302030402221201010003000504020301040605000201BB060403BB050B011A0800190708AA216747182B2B4EE410E619003F184DFD3939FD39391139390111173C123904872E2B087D10C504872E182B087D10C531301301110901110117049AFCB70349FB66029E01C0FEE9FED7FED6FEEA01C0000002004900B10484038B00030007002C4018032202072206070204900001001A090219080965216A46182B2B4EE410F65D4D3C103C002FFDDEFD313001112111011121110484FBC5043BFBC5038BFEF90107FE2DFEF9010700010017FFDE04B1045E0006006B40394806010304030204221205050603020304022212010100050403010402060800000201040605BB000203BB010B001A0802190708AA216747182B2B4EE410E619003F184DFD3939FD39391139390111123912173904872E2B087D10C504872E182B087D10C53130005D0901110901110104B1FB66034AFCB6049A019EFE400116012A01290117FE3E0002007B0000047105D1000300230056402A1916100D0E0F0623142E0128030A0523861F24070113141314027003030A231CFC0A1A25226E23192425B8011BB3217F89182B2B4EF44DED4E10F64DED1112392FED39392F2F003FEDED393FFDE611173931300001211121003736333204151407060F0106070607213E013F01363736353426232206152101E8012AFED6FE9FBB76ACE2012B41266C473A130C01FEF206346C4924162859767461FEDF0121FEDF050E774CD8D482593654372D3C2650A98154391B2037424C7D9A53000200C7FFD7071205F1000B004F00E84057252B352B48095A2B56386A09782B892C080913151617412A13370938174A1048174839592A533C692B7840863C8A40980F96179622953C9A40BA101528170132333233452D154B021E3B457F3E013E3B25710216113B02B80113B4083B4F1C45B8015240327F2D012D3B360B4B4815160B17321B3342210A0516
+
+171817481817211B05200E1B0E3A702101213B427F2901293B3A195051B80124B321C578182B2B4EF44DED71DDED711239392FED2F123939DD2E87DD0312391112391239391139391239003FED71F4F4EDF4FC3DC41810F4ED7110ED1139391112393910C9313001715D005D002623220215141633321235002635341233321716173733030E01151416333236351027262320070611101716213237363F01170604232003261110373621201716111400232226353436370607062304A340366896433D6B89FE53A1F6B3693A2C0F24BD800F0D282C56ADEC94B9FEACCEBADAC10116BEA55A6018498EFEB5B2FE61E4BDECF80183013BCFDAFEECB15C630101262F557703C148FEFD79495A01455DFDCBAE9CB5013C3A2D3A7EFE4E3533131E35E1BA0113784CD0BCFEF9FEDCAB9746254411706E730102D601250148E4F1A5AEFEE0E3FEBB683707110A482B4D00030034000005A805C20002000A000B00DC406B6802012705280A380637094806680A780A880488069A0395049806AA03A504A806B801B80AC801C80AD803D80A150107060602000809090200080A01070502140A0A2512090902140505251206060207082A010000020A0B04030206090A0305080B0D17171A0B0A040605B80114B2090302B80114B60A190C657572182B764E10F4184DFD3939FD39391139194E456544E6182F003F173C4D3F3C3C1239392F3CFD3C05872E2B7D104B5158B004C01BB004C459872E182B7D104B5158B003C01BB003C4591112393912393987103C3C07103C3C3130015D005D01210B012101210321032101022F0176B8AB015C020AFEB25FFDE166FEBE02BA022D02440151FA3E012FFED105C2000300A10000056105C20009001400290059402CA904A707A7120377168716021C0A2A010127002A28020B2A27081C100536184F10371F1A2B000B2527192A2BBC011E00210052012A00182B2B4EF44DFD3C4E10F64DEDF4ED1239003FED3FFD12392FFD393130015D005D01112132363534272623011121323736353427262700171615140706071E0115140706070E012321112101C7016A617950456BFEBC016A6136625F35600146714444264A7173422A3F47C171FD6402CC04C2FEBB495D672117FDC7FE771A3088732B18010335995E8387522E2629B27F8368452F362805C2000002005CFFD7057B05EF001E001F00744029570A94079408035B02591B581D660477018905A914B204B70AC604C70BDA02DB14DD18DF1BF8181017B8010B40231A08081A0C411F030312411A091F16371708371F1E071A210F371E1920219921AD56182B2B4EF44DED4E10F64D1139EDD4ED2F003FED3F3CED12392F10ED3130015D005D12373621201716172126272623220215141633323736372106002120272611015CCFB401160174AC5F07FECC1E2F
+
+54A5A8C2CD9EA2552F1F013128FEB7FEFFFEC2B6B602900457D1B6F4898A6A3660FEF1F8F8F76A3972F1FED2CCCD0165031A0002009C0000057B05C2000900170053403277120107082707270C58126A127B048C038A048A12980398049812AD030D022A15092A160215080637101A19012515191819B80120B3215256182B2B4EF44DFD4E10F64DED003F3FED10ED3130015D005D01112132373635342623361716171612151007022901112101C7011CDA562F8DD2BD5B9B604D3876A0FEB2FD85027B04C2FC3ED776A3E1F1FE1E33886EFF0074FEDACCFEED05C2000200A50000050205C2000B000C0054402C24032404330333044303430406052A02020901410C0A02064109080C049C0C090B4F071A0E01062509190D0EB8011DB3215256182B2B4EF44DFD3C4E10F64DF41239E42F003FFD3F3CFD12392FFD3130015D0121112111211121112111290104DEFCF402CCFD340330FBA30439FDEB04BDFEC7FF00FE85FEF705C2000001009C000004B105C0000900374017072A040409032A000209080676011A0B03082509190A0BB8011CB32152AB182B2B4EF44DFD3C4E10F64DE4003F3FFD12392FFD3130132111211121112111219C0415FD1D0287FD79FECE05C0FEFDFEADFF00FD9600020055FFD905AF05E8002200230085404BC808DB08FA1AF921042902282139134B1859159821C619C21DF80909130A1222D41F0E2A0F0F120441231F0312080A41170923131213120D0322000037231B22AC0F101A2507371B192425B8017FB321AD79182B2B4EF44DED4E10F64DCDF41139ED111217392F3D2F182F003FED3F3F3CED12392FFD10ED11123D2F183130015D005D012627262322021110163332363721352111232706070623202726111037362120001701047B23884C5DB2E5F89E9BC617FEAB0266CC1F59477AB2FEDBBBC3C5C501440119015519FD7803F6973C21FEF3FEF2FEF0E2B391F6FCE9B8692B4BCBCC01620166D8D8FEE3D501F2000001009A0000053D05C2000B0035401C0A2A03030502020B0808050825071A0D020B2500190C0DC0215279182B2B4EF44DFD3C4E10F64DFD3C003F3C3F3C392FFD31303311211121112111211121119A013102400132FECEFDC005C2FDCE0232FA3E0292FD6E00020084000001B605DF00030004003040110402020108040617171A04002501190506BA014B00210135B179182B2B4EF44DFD394E456544E62F003F3F3C3130290111212701B6FECE01329905C21D000001002DFFDC03DE05C200130032401413130F090204410F0908370B1A15013612191415B80173B3217579182B2B4EF44DED4E10F64DED003FED3F12392F313001151E0133323736351121111407062120021135015004436E6D23150134416EFEE1FEE1C4022F22AB8B4C2D6B0407FBFEBC6EBA012D01042200
+
+000100A1000005B605C2000B00AC4067D00201580679038A069A03F906051903D0050218033704360548034704470559038B0308050506080807090203022803034C12040409080702280809072512060506080705040305090609080502040A040301020A070608061A0D02092500190C0D99215272182B2B4EF44DFD3C194E10E618003F3C3C3F3C3C121739011112173905074D2E2B087D4B52787A10C407052E182B10047D4B52787A10C410083C08C431300171725D0072132111012109012101071121A1012F0239018EFDA4027BFE74FE3993FED105C2FDA1025FFDA1FC9D028497FE13000001009C000004AA05C200050029400F000202410508031A07022500190607B8011CB32152AB182B2B4EF44DFD4E10E6003F4DFD3F31301321112111219C013402DAFBF205C2FB47FEF7000100970000062805C2001200C04090090007080809051116081909290027082B0924112A12370735083C0938126A00651179007511890086119A009611A800A611C700F708F8091C05080A09160818090407121A071A0A1712220023112F123D073F0A3F127A12B909B612C7120E0F070F0A020A0F1211090800050E070203120A07030E1100020E0803081417171A0204032702120F0D0E270F19135279182B4E10F44DFD3C1910DCDC18FD3C104E456544E6003F3C3C3F3C121739011112391217391139313000715D01715D01211121113436350121011416151121112101046D01BBFEE102FEE9FED5FEEB02FEE101C0010C05C2FA3E03E52B9B2AFB2B04D52A9B2BFC1B05C2FB7900000200970000054405C50009000A0057402F080257020202060701072A120101020207080A0301020806080A0A0106080227051A0C07082709190B0CC0215279182B2B4EF44DFD3C4E10F64DFD113939392F003F3C3F3C3C12393904872E2B10877DC43130005D1321011121112101112101970143024B011FFECCFDA6FEE1026205C2FBFB0405FA3E0417FBE905C50000030065FFD705EA05EF000B001B001C00414027160C16121914191A971A0505411C17030B410F091C02371C131B1A1E083713191D1EDF21EB56182B2B4EF44DED4E10F64D1139ED2F003FED3F3CED3130005D241235340223220215141233240706212027261110373621201716110103DFD7D7B7B7DADAB702C2DFA7FEC4FEC4A7E0E0A7013C013CA7DFFD3EDC010EF9F8010FFEF2F9F9FEF27AD3ACACD3018D0195CBACACCBFE6B030C00000200A30000050B05C200080013003E401C97019706020C2A04040E032A0F020E080837131A15030D250E191415B8011DB3215256182B2B4EF44DFD3C4E10F64DED003F3FED12392FED3130015D002623211121323635000423211121112132041503DA796DFEE1011F6D790131FEF8F5FEC7FECE0282DE0108046062FE4E6A73FEFDD8FDEE
+
+05C2E4EF00020065FF9505F105EF0014002B00BE406EB725B829C725C829F81905B60F010619181A191905031B1B1B1A1A041B0603031016182B0A191B1F1816150603050D141905191A05621204041A05040304050604100A181A1B032B231B18191F270304050604140D41270314411F0919AC0A372B1A2D103723192C2DDF21EB56182B2B4EF44DED4E10F64DED19F418003FED3FED111739111239393901111217391112173908872E2B087D10C50011121739123939011112393912173987102B3C2B3C87102B3C2B3C3130005D015D2437363727371736373635340223220211101716330007060717072706070623202726111037362120171611035A311B2A959F95230E16CBC3B7DA9C658D02C530274CAAA1B2513B638AFEE0BCE4EABF011C011EC2E0DC0D07128EA68E4836516CF8010FFEFCFEFDFED183550158857F549FA8A8311421ACCF01910194CFA9B3CFFE8C00000200A30000057105C2000A002A0058402A20231B1815052713262A01011D002A2902271D081D2022130617220637171B57101A2C00272528192B2CB8011EB3215256182B2B4EF44DFD3C4E10F64DE4C4FDC4111239113939003F3C3FED12392FFD39111739313001112132373635342726233616171E01151406071E011D011417161715212627262F012E0123211121112101D0015D68345C593264DBA73A30386A7A6655080C2CFEAD0E060C0102026388FEC2FED302D304C2FE74182A7C862E1AFD464438885769CB2A29979B636524391B25311E3E41898D5EFDBE05C200020055FFDA050E05EF002E002F00A3406A080F07210726190B190F17211726660C650D6922E52D0B29102915281A26273A15381AB915CA15DC15D22CEB13EB16F913FA16F92D0F0E00110B22181F25170825220E0B04182ED42B18D41C412F140304412B092F18962F11174F0896281A311F36115700362E193031B8011EB321AD56182B2B4EF44DEDF4ED4E10F64DEDF41139ED2F003FED3F3CEDED10ED11173901111239111239391112393130015D005D0116171633323736353427262F012627263534002132041721262726232206151417161F011617161514002120003501017B0E294BB66D44814040899CE6589501200117E9014908FED8086C486B778E462D93FEA75584FECBFEE6FEE0FEB6025101C765325B182E7D4928271E23343D66D9C60106F7EB85382560564F271A233D284368C5CAFEF50107E6042800010021000004CB05C200070038400C01062A070204080917171A00B80158B2022505B80158400906190809C0217572182B2B4EF44DF4FDFD4E456544E64D003F3FFD3C3130011121112111211104CBFE47FECAFE4505C2FEFBFB4304BD01050002009CFFDA053D05C2001500160033401B160C0102064111091616150A370D1A18023715191718C021
+
+5279182B2B4EF44DED4E10F64DED12392F003FED3F3C3C313013211114171633323736351121111407062120272635019C01392438BCBB382401394988FE81FE818949025105C2FC7698467C7C4698038AFC76EB83F0F083EB038A000001002F0000053B05C200060077402132040425120506053201012512000600060305040100020302080817171A020001B80111B2030506B80111B6041907657572182B764E10F4184DFD3939FD3939194E456544E618003F3C3F3C3C3C123905874D2E2B7D104B5158B002C01BB002C459872E182B7D104B5158B003C01BB003C45931300121012101210103FB0140FE09FEDDFE0E0149014005C2FA3E05C2FBA10001001E0000076F05C20012016A40F20A040505090C06104A044505480C880487058A0C880D870F8610D904D705DB0CD6101116001A041405190D170F05010202000304040206070705080909070D080E180E0209030A0405050606080B06110712170A170B180C79037904760576067611BA03BA04B405B506C903C904C605C606D903D904D605D606E903E904E605E6061F58035A045505570657116903690466056606680B66110B090C0610190C1610B50BBB11E50BE511F70AF50BF3110B0B0A02190A2512090709111202191225120000020E070203110405090A1205000211100C0B0808090B030A05060C030E070001110312030410030E021417171A0ABE01B80007010100020101000E01B8B612191365E572182B764E10F4184DFDE4E4FD194E456544E64D111217391217391112173912173918003F3C3C3C3F173C12173905872E2B7D4B52787A10C487102B7D4B52787A10C43130015D7171005DC487100EC487100EC487100EC487100EC43130017271011317371321131737132101210B0321010165C32A2BA60145AF2D2DC50139FE61FEDAB23434B2FEE2FE5E05C2FCB4EBE60351FCB4EBE20355FA3E035E011DFEE3FCA205C200000100210000053D05C2000B0103409A58026803970095049C06980A06860085048B06880A860B0523052A0B31053D0B8A0B90059F0BA405AA0BB305BA0BC305CA0BD705E605F705108605890B02D005DF0B02051804050604251203030205180605040625120708070B180A0B000A25120809090B18000B0A0025120102010205080B040007060403020A090100080A0806070402000B050B03070903010D17171A099901190C7572182B194E10F4184DFD194E456544E64D1018C410C41139391239393911393939003F3C3C3C3F3C3C3C1217390110872B08104B51587A59C4181005872B08104B51587A59C4181005872B08104B51587A59C4180587102B08104B51587A59C431300072715D01715D2901090121090121090121010187FE9A01DAFE3D01700107010E0164FE3D01DFFE8AFEE802EF02D3FE2101DFFD39FD0501F600
+
+000200230000054205C20008000900A7404CB900B60702290229054A024A055A025A0566089408A902A905B408C508E308FA080E0B08010518060625120707080218010125120008000502080406070901040002040808090B17171A0001B8015EB5090802250705B8015E400906190A0B99217572182B2B4EF44DF439FD3939F4394E456544E64D2F3D2F18003F3F173C1239393901872E2B047D104B51587A59C51805872E2B047D104B51587A59C5313000715D015D0121011121110121010303E5015DFE13FECCFE02016B01320D05C2FC68FDD6022A0398FD7E028200020034000004AF05C20009000A00714044170629012606380137064B0146065B01580568017805880598010D890186060201050606251200000105012A0A030206002A09080A06010A030305071A0C035700190B0CB80178B32175AB182B2B4EF44DE44E10F6D41117392F003F4DF53C3F3CFD3901872E2B877DC5313001715D13012111211501211121013402F9FD1A0466FCFD0305FB850246010403B90105F7FC39FEFC05C200010080FE76027605D00007004140261F03018F0301039F0010100501800501059F07120917171A0205BA042707190809BA217F46182B2B4EF44DEDFD3C4E456544E64D003FED71723FED7172313013211523113315218001F6E8E8FE0A05D0D0FA47D10001FF90000002B805EF0003004D4024A700B700F800F903040703010302025D1201010000020504030302010A011A0503190405BA016D00210129B1F0182B2B194EE410F618003F3C3F4D0111123939872E2B7D10C5313001715D130123017B023DEDFDC505EFFA1105EF000001002FFE76022505D00007004340271F03018F0301039F0410100101800101019F07120917171A05022705BA0003190809BA217D88182B2B4EF43C4DFDFD4E10456544E64D003FED71723FED7172313017331123352111212FE8E801F6FE0AB905BDCCF8A60001008B024E044B05C2000600814031F700F90602070008061700180604220332034A035A03040304030204351205050603020304023512010100040201030305B8011740150600000817171A00020186040603860519077F89182B194E10F4184DFD3939FD3939194E456544E618003F3C4DFD39173C01872E2B087D10C505872E182B087D10C53130005D01715D0901230B01230102DC016FFBE3E6FC017005C2FC8C0236FDCA037400010000FF000473FF6500030019400D01EC000205000405BF216747182B2B3C103C002FED3130113521150473FF006565000002FFCE045F01CB060000030004003040180228000407040617171A04010300BA02190506BA216778182B2B4EF44DFD3939394E456544E62F003FDE4DED3130012301211301CBCEFED1013D1704D5012BFE5F000003003BFFDE0438045F000E0039003A008F404F
+
+3B0235367901890104D81E0126F3E62AE7230E0D05020005131A2B24232204262E262E2A0D050200041B0B221B162C3A1F072A0A0B2C320B3A134D004D2E3A352A3E261A3C1A4D1B2D084D35193B3CBC01190021004801AE00182B2B4EF44DEDF4ED4E10F64DE41139CDE5E52F003FED3F3F3CFDCD39111217391239390111121739111217392B3130015D005D010E010F01060706151416333236372736373635342623220706072136373621321716151114171E011715212E012706070623222635343736371302DE1B3730405A2742513A5C9B03AD4F223D5D5A652A1E0AFEED0947710113B38B8B02031C1CFECA0D0A033B4D5C7494C19B55A57002121115090C1017275249416C8FEF0A0F1A37433332253F8F5C904747C5FE0C344A38280D2A213A25402D35A99BC95A311501D4000002007BFFE3049C05C0001200200042402509200B0E120C00192412070B0A2024050B1584021A221D1F0A1F0D270B1921229821504E182B2B4EF44DFDF4E44E10F64DED003FED3F3FED3F1139111239313000121514022322272627152111211136373633123635342726232207061514163303A9F3F0D787523139FEE9011C36414D77257A1E39999B3A1E7C7F045AFECAF5FEFEB23620508905C0FDF44C2832FC74B291744C908D4B778CB80000020047FFDA0434045F001D001E006E40459916A81602871C01491558126812780A7912B815C713C81508180206041DD204241E1A07160E0A0C10B70C24140B1E10360F1F00361E171D1A20083617191F208721484E182B2B4EF44DED4E10F64D1139FDF4ED2F003FEDED113939393F3CEDED113939393130015D71005D0126272623220706151417163332363721060706212002351000333204170103100821306590351C1C338D64540901230A5486FEF9FEF9F80112F1CD010518FE1B02BB3D31428F4C7E7849886C568274BB0138F901190138B8E901A40002003FFFDE046505C00010001D004F402CE80C010706151D0210030017241007060A1D240A0B15031A131F061F0327041A1F1A360D191E1F98214845182B2B4EF44DED4E10F64DFDF4E4111239003FED3F3FED3F1139113912393130005D00161711211121350E012322003510003312363534272623220615141633027A9A300121FEEB3D9C74BFFEFB0101D7B77E653E527D757779045C574D0208FA409761580135F201170140FC72B48FC85634BD8C97B50003002FFFDC043A045F00060021002200AB4049460887149701990A04060109050610051A4B05461049208601850F871F0A031603171316131748084C164C17491A5C165C175A1ADC01DB04E91DE720F720104A014610880583100402B8019540334F0E5F0E6F0E030E0E1B062422210717122C1B0B160302220336177B221E600C800C020C1A24021F0E951E1923249821
+
+484E182B2B4EF44DFDE44E10F65D4D1139E4ED2F111239003FEDCD3F3CED12392F5DFD313000715D01715D000607212E012336161716171607211617163332373637210607062322001110003B0101D06D0E01BB077B5B88DA4740130B02FD1606613B5358371E1701230B5A8CFCD0FEC2011FE51403747C6A7175EB666E61804B8DA44229321B3061649F010C012E011B012E00000100150000028B05D100170081412F00150003002C0002001F004F0004005F000400020004002C00170001000B0010005C001200090006000E000A001900170017001A000A001F0003000D0015001600090027000E001F001300920010001900180019010E00210060006600182B2B4EF44DF4E4FD39393CD4F44E456544E6003F3F3C4DFD3C3FED5DF4ED393130001617152E0106151415331523112111233533353437363302322C2618712BBBBBFEE49F9C3B3EED05D10303E803033520203CC9FC91036FC946AF426200030042FE42045E045F000D002F0030005A40108A1E0111120524302F071206250D2429B8013F40201C202C180F30021F121F2527302C131A321C841B2D09362C19313298214845182B2B4EF44DEDF4ED4E10F64D1139FDF4E42F003FFDCD3FED393F3F3CED11393130015D2436353426232207061514171633121716173521111407062122242721161716333237363D01060706232202353412333702BD8A836E96391E203A960B3D68400115477AFEA6D1FEF80E01360C1B2E6D9A3422292F5588D2FBF2DE5BEA97A59BA28D4B6E5F4A8A0372192B739DFBF6D36BB8A4A332162767429C464623410127FCF3014B0300000100870000045E05BD0017003F402505022702580E680E04141712000C24170710070A0836051A1913102711191819BE215045182B2B4EF44DFD3C4E10F64DED003F3C3FED3F11393130015D0016171E01151121113427262322061511211121113E01330343A5352D14FEDD1E276D7175FEE4011C3EA35A045E46483D8192FD80029758364C978CFDB205BDFDF75F4B0000020089000001AA05CB00030007003B40224C004C015C005C010401B102000406070A0917171A0006270107190809B2215045182B2B4EF43C4DFD3C4E456544E6003F3F3F4DED3130005D012111210121112101AAFEDF0121FEDF0121FEDF04C40107FE77FBBE0000020009FE4801AF05CB00030013004F402F260E370E024C004C015C005C0104042C131F1001B102000B06072C100F1517171A000C4D13010B191415B2215045182B2B4EF44D3CC4FD3C4E456544E64D003FED3F3FED10F4ED3130005D015D01211121011E013332363511211114062322262701AFFEE3011DFE5A1814082A2B011D82BE0D332604C40107F9640201293B04ADFB4EA59E020100000100820000046D05BD000B00F040B240024605D402E502040F
+
+080A09550589058F088E09C505CA08D907DF08DC090B080618062F032F0428052D06370338064C0348065D0359066A0369067804880497039507A903AF04AA06A807B603B804C603C9041A4B064A07560588048308C405C808D903D904DD07DA080B050909040505060B0B040802070904050706050A02200303CB1204040909040302040602090A0403060A070A0000061A0D010A27000B200B300B400B040B190C0D872150E3182B2B4EFC5D4DFD3C4E10EE003F3F3C3F3C12393901111739874D2E2B047D104B51587A59C4001239011139390F8710083C07103C313001715D00715D13211101210901210107112182011801630161FE83018CFEA8FEFB76FEE805BDFCE6019AFE5FFD6401D27BFEA9000001008B000001A805C20003002540130200010A0517171A002701190405B2215045182B2B4EF44DFD4E456544E6003F3F31302901112101A8FEE3011D05C200000100800000069C045A002D00C2414D0037000200010006000200160002002500020069000F006A001A0079000F007A001A0089000F008A001A0099000F0099001A00A9001A00B9001A00E7000B000E0002002100290003001F000D0024002D00180024002D00250007001F0006001D00120008000A002F00170017001A000600360009010F00290011004D0014010F001E0020001D0027001E0019002E002F012300210050004500182B2B4EF44DFDC410F4ED39F4FD4E456544E6003F3C3C3F3F3C4DED10ED1117393130015D005D00161716171615032111342726232207061511211134272623220706151121112115363736333217161736373633058F8C392E100A02FEDC142666762D17FEE11424697A2A17FEDF0115352F53847D4D3E203853586C045A38463953376AFD5102B63E284C623449FD770289612C4F4F2D59FD7004409F552440373350602D2D0002008700000461045F00160017004B402D0501150125013701580B680B060112100609241716070E040A170536170F021A19110E270F191819BE215045182B2B4EF44DFDC44E10F64D1139ED2F003F3C3F3CED3F39393130015D001615112111342726232207061511211121153637363327038AD7FEDC172A7691361CFEE401133731588769045CB1CDFD220297562E547B4165FDB204409F5425420300030042FFDA049C0465000B00170018004D4028170301080C880C881003170D180F660D0305241814070B240E0B1818080236171A1A08361119191AB80176B321484E182B2B4EF44DED4E10F64DED11392F003FED3F3CED313001720072712436353426232206151416332400212000353400212000150102EB86867D7D87877D022EFEECFEE7FEE7FEEC0114011901190114FDD3C9B2A4A4B1B1A4A4B266FEAB0155F0EC015AFEA6EC02400002007DFE53049A045A000D0020004A40291713
+
+080A1C1A022420071A060A24130B190E080D180D36101A22061F1B1F1827191921229821504E182B2B4EF44DFDF4E44E10F64DED111239003F3FED3F3FED1139113912393130002623220706151417163332363512001110002322272627112111211536373633037473819B3A1E653C52777D1D0109FEFDCC82562F2DFEE601112E345F83029FC2934E78BE4D2DB8990239FEE6FEEFFEE0FED2412445FDC805EFA1472949000002003CFE50045E045E000E0020004A402BD81EEA1C02F80C011213072420071306170E241A0B160E031F131F1627151A220A361D19212298214845182B2B4EF44DED4E10F64DFDF4E4003F3FED393F3FED11393130015D005D2437363534272623220615141716331217161735211121110E012322003510003302E63E28223D996C831E3898405431330113FEE6209B86BDFEF6010BC4D27E537F644F8EA6A9714889038C432657A2FA1002374267012EFC011001460000010082000002FB045C0013004AB900030147B3020F0D06B80147401913070D060C0A200230024002031517171A020E0B270C191415B80164B3215066182B2B4EF44DFDC4D44E456544E64D5D003F3F3FED1139D4ED3130001617112E01232207061511211121153637363302DD0B131B2A0DAC3B21FEE1011042315080045C0101FEDC0302703F83FDF70442BE6D28430000020042FFDB04250461002B002C007E404F09100626190D030904210B0B4B0A490B472144204829D703081D22200C0A04162B04161A2C2C1207042C280B2C2C0F150A201D164D2207152D074D251A2E0C001D4D0F2D004D2B192D2E8721484E182B2B4EF44DEDF4ED12394E10F64DEDF41139ED1139391112392F003FED3F3CFDCD10CD11173931305E5D5E015D0116171633323635342726252627263534363332041721262726232206151417161716171615140623202635010163091E358F54632828FEFFB94C4CEDD7CC010113FEE306192F715D4F2A2AFFAA5554F1FCFEFFF501FB015C4C203932323019193D2E45448097D9A3C837203A3A27311617382851527BA2CDD9A803030000010015FFEA027805680016004AB6102C0F1F0C2C11BA01710004015C401607005C0601061817171A0F06F4040927009203151718B8010EB3216066182B2BD43CE4FD3CF43C4E456544EE4D003F3CFD3CED3FFDF4E4313013353311211133152311141633323637150706272635111598011AB1B122570D1D0E87CA4A30036DCB0130FED0CBFDC043210101D505074D3166029F0002007DFFE80455045F0019001A004C402E0A161A162A16381656076507061A070A0006160E0D0A0524140B1A0D0A271A180B1A1C013618191B1CBE215045182B2B4EF44DED4E10F612394DFDD42F003FED3F39393F3C3F3130015D0111141716333237363511211121350E01070E01
+
+2322272635112501A116277292361C0121FEEB042016437D54F2542F01EC0442FD6F5D2F537640690251FBBE9A0532133C2CAE60BB02911D0001001A0000045704420006009E404F270654066406A506B506050406011002470457047A0274037704064701880087059705A705B705C803E701F701090320040427120505060220010127120006000602050401000603020A0802020001B8010CB2030506B8010CB6041907656066182B19764E10F4184DFD3939FD39391910C618003F3C3F3C3C3C123905872E2B7D104B51587A59C4872E182B7D104B51587A59C43130015D7100715D0121012101211303250132FE77FED3FE790140E30442FBBE0442FCDC0001000E000006210442000C028C41FF0050000C005000020054000000550001005F000700050021000F0007008300020082000C00D7000200DA000700D5000C000600130002001F00070013000C005200020052000C009000020090000C000700090001000B000E00030007000400030008000C00060050000B005F000300550008005A000600090021000C000000030001000C000600020008006F000000600001006C000600630008007D000000720001007D000600720008008D00000082000100860005008C000600830008008B000900DC000000D2000100D9000600D6000800D8000900EF000000E0000100EF000600E00008001B0007000200080005000700090008000C001800020018000C00DB000000D4000100DB000600D4000800EB000000E4000100EA000600E4000800FA000000F5000100FA000600F500080012001A000000150001001A00060016000800180009005E0000005000010058000300590006005600080057000B009F00000090000100970005009F00060090000800100000000700080008005C0012000C000C00000001000700060006005C0012000200020001000500040004002700120003000200030009000A000A00270012000B000B000C000C0007000200030009000100030004000A000B0005000000060009000800060005000A00050003000400020009000B000A000C000E00170017001A000401B90006000100EF411B000200FF00020002000201BA0000000800E0000C00F0000C0002000C01BA000701B9000A00190065000D000E012300210060006600182B2B764EF4184DF47CE4713939E471183939F4194E456544E6181112393911123939003F3C3C3C3F173C1217394D05872E2B10D0872E2B10D0872E2B877DC4872E182B877DC4313001725D715E5D5E0072715E5D01211B012101210B012101211302870121A6AA0129FEC4FEDBABADFED8FECE0132AA0442FCEF0311FBBE031AFCE60442FCF20001001A000004500440000B010340970800180002070413041A0A032702240426062A0A3604390A4504490A5504590A9504990A
+
+A004AF0AB404B707BB0AC404CA0AD204DB0AE504F70417040318040503271202020104051804030527120607060A09180A0B0927120708080A0B180A090B27120001000104070A040006050302060B0908000A090705060B03010A0A0402060802000D17171A08A900190C650C0DA9216066182B2B764E10F4184DFD194E456544E64D2F18C410C41139391239393911393939003F3C3C3C3F3C3C3C1217390110872B087D4B51587A5910C5181005872B7D084B51587A5910C5181005872B087D4B51587A5910C5058710182B087D4B51587A5910C53130005D71015D330901211B01210901210B011A0174FE9C015DB6B20153FE9A0174FE9DBCBD02280218FEC4013CFDEDFDD30147FEB900020015FE470450045F0013001400D94070270A560A660A950AA40AD30A06050A0106061C07110D2D07200D3D07310D4B075D07580B680B7707790D0D170F360D8709880B980BB80B0614140C080D02200C0C27120B0B0A0607021F0808271209090A0607020D0A150C0B0908060709001F022C131F100F14071617171A0E0D0B0CB8010CB30607090AB8010C400C13920819651516A9216066182B2B764EF44DE418FC393939FC393939194E456544E618003F3F4DE4FDE43F3F3C3C3C12393911123901872E2B057D104B52787AC533872E182B7D104B52787AC5011112392F3130015D7100715D1F011636373E012701211B01210102062322262701B1242A4C1A192B04FE70013DEEE1012FFE8A6C7EBD262E2E0182D102020A12116C0C0472FCDC0324FBD0FECA95010306140000020021000003CE045F0009000A0092406008034803C903033704380984048B09D504DB09060704260429093604390945045504830994049B09A404AB09B404BB09C304D609E409119604990902090304042712080809030900A001060804A0070A0A070A0A04090103051A0C0108190B0CB80172B3216066182B2B4EF44DC44E10F64DC4113939392F003F3FFDC43FFD3CC401872E2B877DC4313001725D71005D1335211501211521350103470374FDD7023CFC53022F4F035AE8EDFD95EADE027C01050000010000FE63027D05DA00290059BB000401B3000501B3402A201C1C25132F1211242F25202B012B17171A24123A182F20011C20FA020709294A04192A2BD7216A89182B2B4EF44DF43C3939FD395D3CF43C4E456544E64D5D002FED3FED12393D2F1AEDED313037342726273536373635113437363736373637150607061D01140706071E0117151417161715272E0135D04C2E56612847111E4842593665531E2E1E3395875D02361E4B478FD7E17E432918792128458E010C3338613934110B019F121E2E73E870426F45379281FD6F311D169F0204A39C000001006A0000017105D00003002540130300020A0517171A012202190405CD216C3C182B
+
+2B4EF44DFD4E456544E6003F3F3130011121110171FEF905D0FA3005D0000001002DFE6302AA05DA00260065BB001E01B3001D01B3403120090900102F1111012F001B201E0A09080306222F27012717171910013A0C20060106FA18224A1E1A282728D7219046182B2B4E10F64DF43CFD5D3CF43C4E456544E44D5D11121739123939002FED3FED12393D2F1AEDED3130133536373637353436372E013D0134262735161716171E011511141716171506070615111406072D4B1E33026E7883634757643659434334412867552C4FD294FE639F161E326DFD8E893340A383E86F50129F010B1134349839FEF48F4328227918264480FEC798A7040000010004013104C40309002000454021D51C011C2205108620DA0C010C2214201A170B08041F106D111A221F6D20192122B8011FB3217B47182B2B4EF44DED4E10F64DED111739002FD4E57110FDD4E57131301236373E01333217161F011E0133323637330602232227262F012E012322060723153F2E31683718273E35E9294D15424E12AA1BA78E1C1F3C52D11D5414395813AD01A8AC373A2F060A145A100D6749BAFEF60509224F0B125759FFFF0034000005A807380232002400000010008E0B08FFFF0034000005A807E0023200240000001000DD0B180001005CFE29057B05DE003C00734013282929362D1B371E3308081A0C410303248E2DB80146B4338E1E9C17B8010BB71241381A09372830B8013D40172121173C1637170837071A3E0F373C193D3E9921AD56182B2B4EF44DED4E10F64DEDD4ED1112392FEDD539003F3CEDEDF4EDF4FD3FED12392F111239391239392FC93130123736212017161721262726232202151416333237363721060023073E01333216151406232227262737161716333236353426232206072737222726115CCFB401160174AC5F07FECC1E2F54A5A8C2CD9EA2552F1F013128FEB7E53D211C10516096763348213C263915301E3C343A211328192B5EEDB6B60457D1B6F4898A6A3660FEF1F8F8F76A3972F1FED25A07054F4A5C6B150A165611050C331C2A2209082893CCCD0165FFFF00A50000050207630232002800000010008D0C04FFFF009700000544074E023200310000001000D90A1FFFFF0065FFD705EA07650232003200000010008E1C08FFFF009CFFDA053D07380232003800000010008E1608FFFF003BFFDE043806000232004400000010008D3A04FFFF003BFFDE04380600023200440000001000433A04FFFF003BFFDE04380600023200440000001000D83A07FFFF003BFFDE043805D50232004400000010008E3A08FFFF003BFFDE043805E8023200440000001000D93A1FFFFF003BFFDE0438067D023200440000001000DD3A1800010047FE290434045C003B008840264A33E637020C311A314F314632493705222323302715
+
+31182D3BD2042438072D8F18E910B70CB80145400A32140B278F1E0F31222AB8013E401C1B1B32141504353B10360F1F00363B1A3D088435193C3D8721484E182B2B4EF44DED4E10F64DFDF4ED111217392FEDD539003FED3F3CEDEDF4ED3FEDED111239391239392FC93130015D005D012627262322070615141716333236372106070623073E0133321615140623222726273716171633323635342623220607273722023510003332041703100821306590351C1C338D64540901230A5486E83F211C10516096763348213C263915301E3C343A211328192B63BCF80112F1CD01051802BB3D31428F4C7E7849886C568274BB5D07054F4A5C6B150A165611050C331C2A22090828960138F901190138B8E900FFFF002FFFDC043A06000232004800000010008D2204FFFF002FFFDC043A0600023200480000001000432204FFFF002FFFDC043A0600023200480000001000D82207FFFF002FFFDC043A05D50232004800000010008E2208FFFF00710000026F0600003200D700000010008D0404FFFFFFC6000001C30600003200D70000001000430404FFFFFFAF000002840600003200D70000001000D80407FFFFFFCF0000026405D5003200D700000010008E0408FFFF00870000046105E8023200510000001000D9171FFFFF0042FFDA049C06000232005200000010008D1804FFFF0042FFDA049C0600023200520000001000431804FFFF0042FFDA049C0600023200520000001000D81807FFFF0042FFDA049C05D50232005200000010008E1808FFFF0042FFDA049C05E8023200520000001000D9181FFFFF007DFFE8045506000232005800000010008D1A04FFFF007DFFE804550600023200580000001000431A04FFFF007DFFE804550600023200580000001000D81A07FFFF007DFFE8045505D50232005800000010008E1A0800010047FE8E042505AD000B0045B304093507B8017E40200A03B90000900D010D17171A037101064C0007719F090109190C0DDC216A7A182B2B4EF45D4DF43CFD3CFD4E456544E65D003F4DF43CEDFD3C313001211121152111211121352101AA01160165FE9BFEEAFE9D016305ADFE3DE6FB8A0476E1000002005E032E02E405B40007000F0030401909C4040EC407051117171A0CC40108C405191011D721EA7A182B2B4EF44DEDD4ED4E456544E64D003FEDD4ED3130001610062026103602163236342622060225BFBFFEF8BFBF1D5E865E5E865E05B4BFFEF8BFBF0108BFFE7A5E5E865E5E00020045FF0B043405070008002E00F64095050701090503040602210C07241A3C07351A351B4C004C084C1A5907591B6929692A991B0D111C1A1D1B28292910080E071D2B1C2A2A0F071D2B2B0F2B281B1A110E08070821042B28071B221E081A16110E010F2A2AAF1229291022B725161607081A1B051E
+
+010F10110E01240B0728252B08292A1E24250B28291A1B07080E0F110904213622101636152B2A048415872E30472F4E1076C418D4E44DED393910ED39D4ED111739003FEDDD3C3F12393FED3939DD3C111217392F10ED01872E2B7D10C500111239123939111239391239011112173907102B3C87102BC42BC4053C3C87103C3C2BC42BC43130015D5E5D5E005D002322061514161713040033321617373307161716172126272627031E0133323637210E0121222627072337260235025412646F311BAAFDE00118DA2E251E326A3B6C436814FEDC0B190F19AF10180E44700F012311E9FEFA1E261D3B704A7EAC036ACC8975851902664B013F0406B5CA254366B43C271A11FD8503045E66BBF90403D3F2300111D20000010042FFDC045205C0004700B3406C06350C4616351C462C2424353F233C243F2533357B0A8B0A0C080900470A0701040D28031E42211B2E3D2431203713143D473828000343312E01033337082C1486102008EE1F09094718321000470B2C204333223B0B20231454137C38211C24038D1B6E0D2338DD004947484E1076C418D4E44DF4FDFDDDE410F4FDE6003FEDDCED3F3FED12392F3CFD3C10ED11123912173911173912390111123912391139391112393912391117391239393130015D373E0135342726272335332E013534363332041321262726232206151416172115231E0115140706073637363332161F011E013332373637170E012322262F01262726232207060742489A100915B2722E2CFFECC4012009FEF10A24357E5D6C2642011FF404053A257150263D3A244527291B250D2E3E24365232B4532C6038392518282A2D34225BAF27AD532C382036705A894F9AF4D9FEFE633D55734B2D638C7027341A605233681D09100C0B0D09051A0F1FDF213E1612130C0608120D2A00020041FE76042705C20039004B00924068360D3915302F313A3E403A443649791A8A1AA339BA3FCA3FEA140D360D35163A28031348473F3E39322F1B160A0B250B3A0F20060022202A3A250A6F0A010A1C47302D012D541F314B32171A4D3E3F120112540323602501253142329F350135194C4DDC216A7A182B2B4EF45DEDF45DF4ED5D394E10F64DEDF4ED5D39F45D003FF4ED3FFDF4111217393130005D015D12272635343633321716172126272623220615141617041514070607161716151404232226272116171633323635342726272627263534373637002726272506070615141716170536373635E02526D5CCF4663709FEFE0717295E3F508CBB01464A294F381A2EFEF8A4B2F911010E0E1A2B623C562D2DD2B7436B482A4D022E301A2EFED534160E2B193F011C211724037B3A485895D8A056813C233E3D3B4444569ACB7F532E29302A4963BFC9B2CE4A21384A3B3528286A5A3A5D857D523128FEAF29
+
+151898162B1C2031261721950E1B273600010121020002DB03BA000B002EB9000B0104B5050D17171A02B80104B308190C0DB80104B3216B3C182B2B4EF44DFD4E456544E6002F4DED313000001615140623222635343633025E7D7D60607D7D6003BA7C60607E7E60607C000001FFC3FE8E043305C2000F0042B10105BA018D0006011A401C0C0E032F0D0C00009F01011011059F04090D1A11091011BF216747182B2B3C4E10E64D10DDED1112392FED003F3CFD3C10EDFD3C31300123112311231122023534123321152303B6CAC4CABCDFF6EF028B7DFE8E0689F97703610102DAD60121AB0000010089FFE5049A05DA002E007E404C681D010B0B21201532141C11215C20202E02283204112E0A1832110B0B071C213415150E00076E25311C6E000E100E200E300E040E1A30022C2700001000200030000400192F30DD216B7A182B2B4EF45D4DED394E10F65D4DFDF4ED1112392FE611123918003FED3F3FED3912392FED10F4ED1112393D2F3130005D1334373621320415140706071E0115140221222627351E013332373635342726273536373635342623220706151121893C6C0136D801081324617D6EE3FEE80E3B22161E0C9E3F28673D936B2C4871507E2718FEE6040BBC62B1D0B243335F3A35BD81B8FEC70507E402015C3C649438210CC7011626726057553283FC160004001A000005DC05C2000F001F0029004901754197000400050004003000020009000F00290001001900030001000C000D00070015000700190009001D00080011001B0035004D0029004D0035004F0040005B0035006B0035007B0035008B0035009B003500AC003500BB003500CD003500DD003500EF003500FF00350015000F0035004A0035005B0035006B0035007B0035000500330025002B00430040003D003B0038000500480049003500350048009E00250025003F004900DB0024009E004F002B00010040002B0001002B002B0013000F0039001B0002000700390013000A003500320029003E001F0032002400490020002A003A001C00320040001C0041001C00290020003201660030002A0090002A0002002A002A0017004B00170017001A000B0039001F00E00003003900170019004A004B00E00021006901BB00182B2B4EF44DEDF4ED4E456544E64D12392F5DFCFDF4E410E410FD3C10E4111239003FED3FED12392F5D71EDFD3C392FED19392F1811121739111239313001715D5E5D5E005D00070615101716333237363534272623000706212027261110373621201716112427262B0115333236350111320417161716151406071617161D0114161F01232E01272627262F01231101FDB3B0B3B2FCFBB2B2B1B3FB02E1DDD7FED3FEC9D5D5E6D801230131D8D8FDA4422C5034534B54FE384C012F1161406D73544D2748030407CC0A
+
+060A102C18312F2D0544B8B4F7FF00B3B3B4B5FDF6B5B8FC63D7D0D5D501370143D6C8D8D8FECFDC1A11ED3C43FDCD0331010107233C87675C09101F3A7D490C180C1727941A2B110A0303FEDF000003001A000005DC05C2000F001F003B0111416E0088001D00010003000100030005000C0009000900110006001600060018000900260009001D000D000D0010002C00750023007600260086002300850027000E0000003B0010003B0002003B0037006C000F0022000100220028002D00F30031006C0009000F0028008F0028000200260000002800100028009F00280003002800280013000F0039001B0000000700390013000A003D00170017001A000B0039001F0017003A003B002D002C0034003200090000002500010019006000250001002500C70003003900170019003C003C003D00E00021006901BB00182B2B4E10F44DFDF65D5E5D5EEDD4C5C4D510D6ED4E456544E64D003FED3FED12392F5D5E5D5EFDEC10DC71FDD45D3130015D7100070615101716333237363534272623000706212027261110373621201716110006232226353412333217161727262726232206151416333236373301FDB3B0B3B2FCFBB2B2B1B3FB02E1DDD7FED3FEC9D5D5E6D801230131D8D8FE75D371A8F5D3B875568C22BC11372E37536A75524B4D0BB70544B8B4F7FF00B3B3B4B5FDF6B5B8FC63D7D0D5D501370143D6C8D8D8FECFFED68BF0C3B60100304EC3035A1F1D898A897C523E00000200CB02DC071005C20007001400B1406B7409850902060816084D0F46105A0F54106A0F65109B0F9510AA0FA6100C490F44105A0F56106A0F6610760F7910840F8F100A0E0F0F2F1209090A1110102F12090908100F0D050409110E00130203000A0802001008110F0A0E0909110E0B1114005D065D055D03141516B80124B321C5E1182B2B2FD6FCFDFC10CDDDDD11393D2F18123939123939003F3C3CDD3C10DD11393939173C05872E2B047D10C405872E182B047D10C4313001715D00711335211523112311251B0121112311032303112311CB028FDDD8032B87850134C5A1A8A1C50510B2B2FDCC0234B2FE5501ABFD1A021AFDE6021AFDE602E60000020076045F02740600000300040034400E0070020407040617171A04010300B8015D400902190506BA216C47182B2B4EF44DF43939394E456544E62F003FDE4DED313009012313030274FED0CEC0170600FED5012BFE5F0003FFD5045F026A05D50003000700080035401A080207CA050011080A17171A0804014B032E064B0419094247182B4E10F44DFDF6FD11394E456544E62F003F3C4DFD3CDE313001211521252115210501650105FEFBFE700105FEFB014B05D5EDEDED8900010049FFED0484045000130093406388109701A701D705D80FF701F71207010D000611020A03061105
+
+0904061108090407100B0A0307100C0D0007100F0E130710120E1306111007072212060611111007060400091011130E22000D4A030A220409070603001A150E091914156521425F182B2B4EF43C10F64D3C002F3C2F3CFD3CFE3CFD3CDC3C0111121739872E2B7D10C5010F0F0F0F0F0F0F0F3130015D01210721112107213723112137211121372107330484FEA15301B2FDD35AFEF057FB01725AFE34024258011158E80284CCFEF9C4C40107CC0107C5C50000020012000007AA05BD000300130090404A2201201124139701040211120102110F13011212251213130410112A03020B2A0802080F040101062A04020C2A13120F081204010313000F250C0A9C06AC0D070C0C130D1A1513191415B8018EB321E556182B2B194EE41810F6114D392F3C10F4E410FD3C111739003F3C3CFD3FE5392F111239392FFD2F3CFD3C01872E2B7D10C50111123939873C3C3130015D0123032101211121112115211121112111210321037685E30168FEB40572FD0902ABFD550305FBCCFE476BFEC004C2FD680393FF00FEC3FCFE80FEFC0138FEC800030047FFC705FD05F6000B0016003200CA4079670AA815B815C70A044E17482B582C690F7904F62FF63007063001151E161D1C1D271D28281B0A1E0B1D191D2A1D291A272A2E16150B0A0406191C201116150B0A040E03191C272A0424031A291A1B29EF1228281B29281A1B0341320328290E4124091A11371B57201A3428063729572E193334DF21EB56182B2B4EF44DE4ED394E10F64DE4ED39003FED39C43FED39C40108872E2B087D10C50011121739111217390111123939121739113939872BC42B3C2B3C2BC487102BC42BC42BC42B3C313001715D005D002726232202151417161701001633321235342726270100161737170716171615100706212226270727372627263510373621041D45486BD6BA120A1A0279FE078E4CD6BB080D1DFD8C0198FB61A455A8382E2DC5C2FEC47AF36DAF55B63A2C34DABC012C04A02228FEE5EC6252304702B9FCA2370142C5423E5F45FD4E049A5853B251BB457B80C7FEA6DBD74B5EB950BE4E778EBB015AF8BA00030019014705890475000B00170030006E40433803C700D700E700F700F72B06041B0A281928292839284928062027202430110817D62D0211201A2D073217171A1D200BA5052430243005320EA514202A1931425F182B4E10F44DFDF6FD39393D2F2F1810F6FD4E456544E6003F3C4DF53C10F43C113939FD3C313001715D0026232206071E01333236350436372E0123220615141633003633321615140623222726270E012322263534363332161704C5554C4B4F382F594A4D54FD0A5C2F38614D3D56514201A99C6BADB8B3B26E5C423C45B86BB2A9BE9D5EA65103366850745E646D5CC964656D546C555C6D01F568E6AEB4
+
+E44B375F6F74E6B4AEE5627D0002004900000484043B0003000F0042402207FA0A05A10C04FA0E03A1020A0A1117171A0A0085080D22070E8504021910425F182B4E10F44D3CF43CFD3CF43C4E456544E63C003F4DFDDEFC3CFD3CF43130251521351135211121112115211121110484FBC5019A0107019AFE66FEF9F6F6F60140F40111FEEFF4FF000100000002004700000482045C0003000A006C40130506062212070708040A0A221209090809040AB80103B2050708B801034020200630060206070135000A0A090706040801021A0C050401190B0C6521425F182B2B4EFC3C3C10F6114D39173C003FFD193F5D18FD3939ED39390104872E2B7D10C5872E182B7D10C5313033352115013501110D011147043BFBC5043BFD6D0293F6F60238FE0126FEF69A9CFEF6000002004900000484045C0006000A006C401305060622120000010403032212020201000506B80103B2020401B8010340202003300302030707350A0A01000805041A0C060702030400190B0C6521425F182B2B4EF4173C10F63C3C1139003F4DFD193F5D18FD3939FD39390104872E2B7D10C5872E182B7D10C53130132D011101150115211521490293FD6D043BFBC5043BFBC5021C9C9A010AFEDAFEFEDA1CF6000001FFEA000004890597001600E04043261428166F0260117704A605A90E07081518152015641504120F131515161414B31213130E040100151616B312000500140E0F12040B1316010405040008150F0E040FB80136B6010F121F120212BB01080008000C0136401905000E100E020E0E0A13161400040A0C15181A00063802C200B80158B31508B30BB801584009130D3811C213191718BC017B0021012B012D00182B2B4EF44DF4E410F4FD39F4F4F410F63D2F18003F3F3C3C3C12392F5D3CFD3CFD5D3CFD3C111239011112173911121739072E2B7D10C010C0C0072E2B1008C00510C0C0013130005D015D01033315230721152111211121352127233533032101130489E48FD16B011AFEC0FEDDFEC201186DD593F00153010AFD0597FE2988DA87FE2901D787DA8801D7FD91026F0001FFCBFE2504BD0442001B00AC405F2600261B591059115912B718F7180703187618021909010C1211110E18041919001B1A1A27121919000E111127120F0F10191A09071B0F0E00061210110A072440052104401723185015011211100E0C00041819091B0F1A1D1B191C1DBE21B80141B1E3182B2B194EFC4D194E10E64D18111739003F1ACC1ACC1ACC1ACC1AED3F3C393F3C3C3C12392F3C01872E2B7D10C418872E2B7D10C487100EC4C48710C40EC43130005D01715D01030E01151416333236373E013713210321370E012322262703210102098201026131487C2318221B4F011CC2FEF91C2DB76B2A421157FEDE011D0442FD2807100844355339
+
+27849101A8FBC0B64890180FFE1E061D00020024FFD7045205F2000B002B00604010641F741F021E1B15083211112B1B201FB8019B40231B20230302202B0B1F1E1F050B2905B427151C1854271A2D0B540E192C2D65217B69182B2B4EF44DED4E10F64DFDF410ED39111239392F003FED3FEDE0FD12392FED3910C93130015D0016333236353426232206150A0135340033321716173E01353402232206072736373633321716111007062101397D51669264696E8B20F5011CDA504E5B2F0104767820351A8C36344C49CE86A1AEB7FEF10122719E846185AC82FE4C010ABEDD01252430461E3611A5010E1717BE1A1118A6C7FE7FFEB8EDF80001FFF7FED404A805BF000B007D403F98080168099702DA03038D090104030382120909080302020303821209090A0304090904200A02220B000804220709040302040B012D051A0D0A2D08190C0DB8011FB3216B88182B2B4EF44DE44E10F64DE4111739002FFD393FFD391A1911392F113905872E182B7D10C408872E182B057D10C4313001715D005D0111210901211121350901350495FD330203FDF302EAFB4F0247FDD505BFFEF2FDA2FD8FFEF2DC02A30290DC0000010007FED405C205C2000B0037401D00030A072A080004010182004A091A0D0482054A07190C0DE0217F89182B2B4EF44DF4FD4E10F64DF4FD002F3C3FFD3C3C313001710121112111211123352115230507FECEFE1FFECEBB05BBBBFED405F0FA1005F0FEFE0000010031000004C20442000B0032401C2C042C050205020A5D0B0604070A042702072708020800AA0A7B69182B2FED39392FFD2FFD003F3C3FFD3C3C3130015D01152311211121112111233504C29AFEE2FEDFFEE29A0442D1FC8F0371FC8F0371D100010076FE5003D3060A0020004D401907230A3206230318231B3217231306230751211823171A221FB801ABB220820FB801ABB30E192122B80162B321EAF0182B2B4EF44DE4FDE44E10F64DE410F4E4002FE4F5E42FE4FDE5313004070623222627371E013332373637133637363332171623072E01232207060703028F2B50CB2B72361826301C49191006260A304DD03E50500A152435204C1C1206249364B91714E315125034A30398F86BB11314E311125034A9FC3400020028033402C005EF0011003A0091B6070401D91A0126BB0137012E002A012F401923130D0502041C152B2E262E2A26130D050200061D0A24191DB80144400C193921032A140A3932140015B801ADB72E942A23261A3C1CB801ADB21D2307B801ADB336193B3CBC01640021007D01AC00182B2B4EF44DEDF4ED4E10F64DE4EDF53C003FED3F3FEDED123911121739123901111239111217392B3130015D0071010E010F010E0115141633323736373E0137273E0135342726232206072336373633321716151114161715
+
+232E013506070623222726353437363701E1121D202F4839362A23281A0F131503401C242F1B2F35340BB40C2A46A77B41781019C8070934233E4A89372152367104920C0B05070B32262829100C0E0E283796031B182F110A2D2D5B3353182D96FEBE273509241123182D13215531436C3A260E0002000E033402E205F00007000F0058B7A70EB70EC70E0300B801B4B20A1404B801B4400E0D031117171A4301530163010301B801A54009084C065C066C060306B801A540090B191011A6214247182B2B4EF44DED5DD4ED5D4E456544E64D003FED3FED3130005D0036342622061416240620261036201601CD5151AA555501BFC0FEACC0C00154C003C570BA7070BA702FC0C0013CC0C0000100310000060705EF00210057402F120602150C541D01030216152205130A2317171A0423210605440209A421191344160FA41923DF14011419227D46182B4E10F44D5DF4FD39F410D4FD39F43C10F44E456544E64D003F3CFD3C3C3C3FED1117393130000607211521113E0135342623220615141617112135212E0135103736212017161105DC8093013EFD9A827AD1B0B0D18577FD9A013E938089BB017C017CBB89026EE58EFB011762CCCDEEE3E3EECDCC62FEE9FB8EE5AE011BBEFAFABEFEE500030038FFDB06DC045A00060016004D00A740201816150C090706232C43341B3B000643124015380C3C0709341824062C281F06B8019540353434461F2C24280324282F07122C460B003C103C023C382C400B061F1BB134344E4F00953C1F331F321A4F234D242D0F4D49194E4FB80189B321484E182B2B4EF44DEDF4ED4E10F64DF4E4ED1112392FEDE4003FEDCD5D3FED3F3CED10CCED12392FFD1112391112391239391139123911123901111239111239391217393130012E0123220607050E010F010607061514163332373635273637363534272623220706072136373633321716173E013320131607211417163332363721060706212226270E01232226353437363705AF076A6B6C7006FEF715223B6D5E20364654573A6891441F30502B486E2B1703FEEA0BB075B58163373C3D9E68014C753E05FD161B328E50761C01210C578FFEF987C1354ACF86CAB4894C9B0292697D7175890F0D0C16131624532F52203A98F90A111A344F1D0F3E213CE15D3E2C18313441FEEF91DE713C6E37516464A366505F58C488B9552E18000003002AFFC204B4047B000A0015002E00C64066A709F70902091E0A1D1F1D281D29291E14151D1C1C2B1D2A2A1D1C1F2215140A090406282B2E111C1F1815140A09040E282B2503291E292A1EAF121D1D2A1E1D1D0622292E111E0E182A252907032425070E24180B1D0B11842A2D2E1A3006361E2D22192F30B80176B321484E182B2B4EF44DE4ED4E10F64DE4ED003F3FED3FED3F1139111239011112
+
+3911123908872E2B087D10C50011123939121739113939011112393912173911393987102B3C2B3C2BC4043C87102B3C2BC42B3C2B3C3130005D00272623220615141617010017163332363534262701240021222726270727372E01353400333216173717071E01150304462B2977890E11019FFEBF1C2E467B7F090EFE6302DFFED1FEF684673A43874A8E45310124F48EB04B8A478F42350354140CB39C31622301B9FDC60F18C094323F42FE4909FEB72C19348E3E905DD75AFA014D3D3E91439557C55F0002006DFE6C0463043D000300230057402B18150F0C0D0E06130406231E2406132E01280206131213120270030309226E231A251BFC1F090109192425B8011BB3219088182B2B4EF44D5DED4E10F64DED12392FE539392F2F003FFDE62FFDCD11391117393130012111210004232224353437363F0136373637210E010F0106070615141633323736352102F6FED5012B0161FED4B0E5FED740276C473A130C01010E06356B493E160E6B5C88381D0121031C0121FAF6C7DAD1825A3753372D3C264FA68354393137222D5B6C6E3B44000200E1FE80021A043D00050009004240210205000459072809060B17171A0670071C0104030304007001190A0B7021813C182B2B4EF44DE539397D2F7C2F1810F4F54E456544E6004D3FFDEE2F3939313001211113331303211121021AFEC750965308FED6012AFE80017602AFFD51032601210001004900B10484038B000500234013032200D9020222001A070419060765216A46182B2B4EE410FE4DFD002FFDED31300111211121110484FEF9FCCC038BFD2601D30107000001FFD5FFDA05120771000800AD40297C007C01890289039900054A014A045A015A046901050202010303000708082F120505060100010200B801A240181205050401020100022F1203030402030503020104080D07B8016B4016040740010203000444800806050503071A0A0319090ABC017D002100E2013C00182B2B4EE41910E611392F39391A184DEC391139391A003FE43F17390108872E2B087D10C505872E182B087D10C505872E182B7D10C58710083C3130005D015D05010727251301330101E1FEF1AF4E0185F80218A8FDA426038E6B8ADEFC6906A3F8690001001EFE50045205E300260086401A3A214921960C031C1F1B1F1B1B82120D0D0C150D1B1D14113218B8017AB71E0B1D1D00030A1EB8010A401C260332230115141D2817171A0026311F1B0D0C1C09060BDB1D192728B80118B321815F182B2B4EF44DFD1739F4394E456544E610D4C4003F4DED39F43C1139FD3C10F4ED391239393901870E2E2B057D10C501073C3130015D012E01232206070E01073315210306070623222627371E01333236371323352112373633321617042122331A24391612180CF7FEED79203D66C32F732E32
+
+28291C48371E74F9011839395ACE3A5C3504DA12111C2A2A7548C7FD21C16AAF1813E3170F7AAC02ABC701215E94121400020049006D048403CE0015002A00BD40952A072A0C2A172A283A073A0C3A173A2845004B074B0C45134B17451E45214B2856005907590C56135A17561E56215B286600680C691767217600790C7A17762186008A0B8917232A002A132A1E2A213A003A133A1E3A2108202926232A2A1F1CF3262A8F199F19AF19BF19D019E0190619150905022A140A11F3052A0E25241B1A100F040308142A091A2C1F14192B2C6521425F182B2B4EF43C10F63C4D111739002FEDFC3939FD113939D65DEDFC3939FD1139393130015D005D1236373204333237363711060706232224232206071100070623222423220607113E0133320433323637118C7C59630155486D613124303A585866FEB75D5C72470417395E5F63FEAD565C75443F84556201554956933A01C53E019A45242DFEE32B1E2D974152011601021F349A484D011538469A5045FEE40002FFFA0000057005C200030006009F40553F05A8050218052A054B05033B059F050249024603590256036902660388028703B902B603C902C6030C080207034A0245038902860399029703080506050406821201010205040506048212000003050302020406B801A3400D000A0602010403050500010708B80121B3217B69182B2B2FD5393D2F183939123939003FFD3C3F3C3901872E2B087D10C505872E182B087D10C5313001715D0072715D290101211309010570FA8A022201328AFEDDFEDD05C2FB47037EFC8200000200AF009703C003D00006000D00C5405A3F003C013F0435063F073C083F0B350D4E014E024B064F084F094B0D0E170018061707180D670068066707680D08D500D906D507D90D04040004060407040D130013061307130D080D0C0A0B07080A0906050304000103020902B801A1B50801BD050B04B801A1401B0C050F17171A0B0809030A0CB4070D010204030305B40006190E0FB80116B3216C78182B2B4EF44D3CFD39173CDE3CFD39173C4E456544E64D00192F3C18FD3C10FD3CFD3C308710C48710C48710C48710C43130015D0072715D1301150717150125011507171501AF0156CCCCFEAA01BB0156CCCCFEAA02AA0126EEAFAEEE0125EE0126EEAFAEEE012500000200000097031103D00006000D00C140560C000C060C070C0D1C001C061C071C0D083E023C053F063E093C0C3F0D4E004E044E054E074E0B4E0C0C190017061907170D690065066907650D08D900D706D907D70D040708090A0D0C0B0A0605040300010203040BB801A1B5050CBD080209B801A1401B01080F17171A060300B402040503010D0A07B4090B0C0308190E0FB80116B3216C78182B2B4EF44D173CFD393CDE173CFD393C4E456544E64D00192F3C18FD3C10
+
+FD3CFD3C308710C48710C48710C48710C431300072715D015D09013537273501050135372735010311FEAACCCC0156FE45FEAACCCC015601BCFEDBEEAEAFEEFEDAEEFEDBEEAEAFEEFEDA000300BD00000744012A00030007000B0039401E06050A0301280807000A0D17171A0A7009A5037001A5077004190CC578182B4E10F44DFDF6FDF6FD4E456544E6003F3C3C4DFD173C313021112111211121112111211103680132FC23013204230132012AFED6012AFED6012AFED600FFFF0034000005A80763023200240000001000430B04FFFF0034000005A8074B023200240000001000D90B1FFFFF0065FFD705EA0778023200320000001000D91C1F0002004BFFDA07AF05E1000C0028007C40406613682276137922043C250102032009210C201415061C2A1919201506411003184115021D4120080C412409181D4C15202028161B4F1E161A2A09372819292AB80125B321E856182B2B4EF44DED4E10F63C4DE41112392F3CFD3C003FED3FFD3FFD3FED1112392FFD111239111239011112393931300171005D243635113426232202151412330037363332171617352111211121152111211121350E0123222726110345958880B2A8AEAFFD76B9A3FA7F5D333D03C2FD55027CFD8402ABFC3E34AC6AFCA3B9D27945028E4E72FECAD8D1FED30363F5B7301A3B61FF00FEBEF7FE80FEFC654E3DB8F501570003003FFFDC0747045A000C0033003C00924021390646158A23A615F9000504210322142113224F214F225F215F22822182220A1BB8019540353B3B250F372C1307052C33330722291E2C250B0C2C2D0B3B1F0F292F1B3F1B021BB10202301A211C3C95221F1A1A3E093630193D3EB8018CB321484E182B2B4EF44DED4E10F64DE4FDE41112392FFD5D3939E4003FED3FED39CD3F3CED3FED3912392FFD3130005D015D243635342623220706151416331216173637363332161716171615211E0133323637210E0123222726270607062322003510003300272623220706072102E676728F9D3A1F7A7796BA3D503A5F8A7FCC483A1410FD1706736A596E14011C13FFEC87643A45373D6CA0F4FEE3012AF303C71E38914233600601C4C0C495A2B9914C79ACB2039A58474E1F3266604D7B50A27F9939478DD737204640223D013EFE01110131FE8B35631D3995000001FFFB01D0047602AA0003001D400F005D03011A0500190405BF216747182B2B4EE410E6002F4DED31300321152105047BFB8502AADA00000100F101D0070E02AA00030020400A005D03011A0500190405B80187B32181E1182B2B4EE410E6002F4DED313013211521F1061DF9E302AADA0002008B039E038205D0000B00170052401710040E02040903160A4B1509CE0F03011917171A041C0AB8019DB5085A0B101C15B8019D400B145A0C191819DA216B88182B
+
+2B4EF44DEDFDE4DEEDFDE44E456544E64D003F3CFD3CFD3C11121739313001343637150607061733112125343637150607061733112102659385652314049DFEE3FE268F89662312039DFEE3047198AC1B681F512B28FEF9D396AE1B68204E292CFEF90000020097038B038B05BD000B00170059401CB70AC70A02980AA80A020C00EC170B11054B1306001917171A045A07B8019DB5006806105A14B8019D400B176811191819DA216B89182B2B4EF44DE5FDEDDEE5FDED4E456544E64D003F3CFD3CDC3CFD3C3130005D015D013637363523112115140607253637362723112115140607027467220E9C011C8B8CFE28652313039D011D8F8903F41F53212F0107D38FB51B69204E292B0107D393B21A0000010089039E01A505D0000B0032401B0204030B4B09CE03010402091A0D081C075A00190C0D70216B3C182B2B4EF44DFDE44E10F64DE4003FF4ED1239393130133436371506070617331121899187672213049CFEE4047199AB1B681E522C27FEF900010084038B01A105BD000B002B401700EC0B054B0600045A071A0D0B6805190C0D70216B3C182B2B4EF44DE54E10F64DFD003FFDDCFD313013363736272311211514060789622514039D011D938503F41F4A2C2D0107D397AE1A000003004900000484043B00030007000B003F400F0B280A0722060228000A0D17171A04B8019CB4020928010BB8019C400906190C0D6521425F182B2B4EF4F43CFD3CF44E456544E6003FFDDEFDDEED313021112111011121110111211101CE01320184FBC502B7FECE012AFED602A1FEFB0105019AFED701290000020021FFDA03EA05EF0003000700EE4016A604A906E7060317042704029900990299039C070404B801B1B612020201040704B801B1B612020203040505B801B0B612010102050605B801B0B612010100050407B801B0B612020303070607B801B0B612000303070406B801B1B612000001060706B801B1403512000003060504020600070501070302000406030B021B023B02030202010301010B0917171A008603050103078620021908425F182B4E10F41A194DFD173CFD184E456544E6003F3F12397D2F5D173C181112391239014D111239123908872E2B08872E2B0810872B0810872B08872E2B08872E2B08872E2B08872E2B3130005D01715D090703EAFE1AFE1D01E3FEFC01040107FEF902EFFCEB03150300FD00FE4201BE01A8FFFF0015FE47045005D50232005C00000010008E1408FFFF00230000054207380232003C00000010008E09080001FEA3FFDA02AA05A50003001FB41702010201B80183B6000309010203004E2FCD2FCD18003F3C4DED39015D05013301FEA30366A1FC9A2605CBFA35000002003600CA043C04D00007001F00CC404B470C470F4818481B570C570F5818581B960C960F9918991BA60C
+
+A60FA918A91B10480946124615491E580956125615591E9A09961296159C1EA909A612A615A91E101C311731161D01201AB801B2402510310B310A1106200D0F211F212F213F21CF21DF21EF21072117171A141611311017032014B801B2401B0B1C00201F1D0A31001F101F201F301FC01FD01FE01F071F192021B80118B3217F88182B2B4EF44D5DF43C10ED3939FDED3939F43C104E456544E64D5D002FED3939E4E4F4ED3939E4E43130015D005D0016323634262206263727371736321737170716140717072706222707273726014F88C48888C488D4478C8C8C73F0738C8C8C47478C8C8C73F0738C8C8C47026B8888C4888816738C8C8C47478C8C8C73F0738C8C8C47478C8C8C73000100AA0097020003D000060079402F040004061300130604D500D906021700180667006806043F003C013F0435064E014E024E0607060503040001030202B801A1B201BD04B801A14016050817171A010204030305B40006190708D0216C78182B2B4EF44D3CFD39173C4E456544E64D00192F18EDFDED308710C48710C43130005D7172015D13011507171501AA0156CCCCFEAA02AA0126EEAFAEEE012500000100AA0097020003D00006007A402F0C000B061C001C060418001706680067060435003F023C053F064E004E044E0507DA00D70602060504030001020304B801A1B205BD02B801A14016010817171A030600B40402010305190708D0216C78182B2B4EF4173C4DFD3C394E456544E64D00192F18EDFCED308710C48710C431300000725D71015D090135372735010200FEAACCCC015601BCFEDBEEAEAFEEFEDA000003001C0000045705D1000300070020006A40414C024C034D0E5C025C035D0E060B1F0E240A1F200103B10000040614195C1B120616070A2217171A051F01270700148A0A161127171F1C9219192122A9216045182B2B4EF44DF4E4FD3CD4E4DE3CFDE44E456544E64D003F3C3F3CFD3C3F3FED3FE4FDE43130005D0121112115211121001617152E0123220617153315231121112335333534373633033B0117FEE9011CFEE4FEFD361D14261B431E02BBBBFEE49F9C4D45D405CBFEFC8AFBC305D10402E801014A4F14C9FC91036FC946AE5550000002001C0000045705D10003001C0063403A4F0A5F0A020724061F0A241C011C240A1F07240601000114115C170E0612030A1E17171A012700108A06120D27131F189215191D1EA9216045182B2B4EF44DF4E4FD3CD4E4DEFD4E456544E64D003F3C3F3CFD3C3F3FFDF4ED3FEDF4FD3130005D01211121001617152E0123220617153315231121112335333534373633033B011CFEE4FEFD361D14261B431E02BBBBFEE49F9C4D45D405C2FA3E05D10402E801014A4F14C9FC91036FC946AE55500000010047FE8E042505A500130055B60BD3080D35070EB8016840
+
+25120411350312D300001517171A07037106010A4C0F000B71119F0D010D191415DC216A7A182B2B4EF45D3C4DF43C3CFD3C3CF43C4E456544E6003F4DF43CFD3C10F43CFD3CE43130012111211521112115051121112135211121352101AD010E016AFE96016AFE96FEF2FE9A0166FE9A016605A5FE53E3FE0EDF02FE4C01B6E101F0E300010071022801C00374000B0025401208D0020D17171A0BD005190C0DD0219088182B2B4EF44DFD4E456544E6002F4DED313000062322263534363332161501C0624545636244456402896161454462614500010092FEAF01B40121000D003FB6D700E70002000DB8014D400B0528040A0F17171A035A07B8019D400B0D6804190E0F70216B3C182B2B4EF44DE5FDED4E456544E64D003FEDEC393130005D173E0135231121150607060706079754449D0122011726502F60E41C5E6A0121ED744063341E1C00020092FEAF03740121000D001B00584009D700E700020E001B0DB8014D400E0314062813030A1D17171A125A16B8019DB51B6814035A07B8019D400B0D6804191C1DA6216B3C182B2B4EF44DE5FDEDDEE5FDED4E456544E64D003F3CFD3C10FC3C39393130005D173E01352311211506070607060725363736352311211506070E01079754449D0122011726502F6001C06322139D01220414188B62E41C5E6A0121ED744063341E1C6D1C4D2C4F0121ED7C3D4671150000070004FFD2080205DA000B000F001B00270033003F004B00AD40100D0E0E91120F0F0C0F18020C363C2739BB019F002A004801B5B242213FB8019FB530420E0F0D05BC019F001501B5000B019F400A1B100D0C114D17171A244113019F002D01B5001E019F00330036019F004B01B5003C019F00450008019F001201B50002019FB318194C4DB8018FB3216747182B2B4EF44DEDF5ED2F18EDF5EDD6EDF5ED4E456544E64D003F3CF4EDF5ED3F3C2F3CFD3C10F53CFD3C01111239111239872E2B7D10C53130000615141633323635342623253301230016151406232226353436330006151416333236353426232436333216151406232226350436353426232206151416330406232226353436333216150119494A3434494934029593FCBE930135C1C08989C1C2880536494934344A4A34FEB7C18889C1C18988C1FE964B4B3434484834014BC18988C1C18889C105024A3434494934344AD8FA0005F4C18988C1C18889C1FBCB4835344A4A3435480CC0C18888C2C2887E4A3435484835344A0AC2C28889C0C18800FFFF0034000005A80763023200240000001000D80B07FFFF00A5000005020763023200280000001000D80C07FFFF0034000005A807630232002400000010008D0B04FFFF00A50000050207380232002800000010008E0C08FFFF00A5000005020763023200280000001000430C04FFFF0074
+
+0000027207800032002C00000010008D0404FFFFFFB20000028707800032002C0000001000D80407FFFFFFD20000026707550032002C00000010008E0408FFFFFFC9000001C607800032002C0000001000430404FFFF0065FFD705EA07900232003200000010008D1C04FFFF0065FFD705EA0790023200320000001000D81C0700020000FFD10595067C0021002E002B401317141A2105022B2E242B2B101E090D10301E2F10D410D6DCD41112392FD4002FDDDEDCD42FC4DC313000163332363332171617060706151416170607062322262322062322030235341233001615140607060706073E013701E2D5232DCC4B7B6036355025438E5B2658858334B73F3FA7349D9797E7B0027A023C4138372347029BB304F23E46422641443560747FCC1B7B86C94245010A0107FDEB0128017D140A40984137130B0698DE29FFFF0065FFD705EA0790023200320000001000431C04FFFF009CFFDA053D07630232003800000010008D1604FFFF009CFFDA053D0763023200380000001000D81607FFFF009CFFDA053D076302320038000000100043160400020089000001AA045F00030004002B4016040006030A040617171A04022700190506B2215045182B2B4EF44DFD394E456544E62F003F3F3C31301321112113890121FEDF910442FBBE045F0002FFB6045F028B0600000600070061403B1A011603290126033A013603069506A606020B050B061C021B051B0605020503000707030504010600020702070204001A0904190809A6217B69182B2B4EE410E6184D1139393D2F182F11123939123939003FDE3CDC39013130005D01715D0123270723132103028BE88283E8EB01008004D5A8A8012BFE5F000002FFA8045F029705E8001E001F0077402A0502350F02F402013E06301502370CF802F80BFA11F51C050802080B0A11051C160C250C06153B1E340AB801A0402219063B0D34191F071F120F0402041909391F1A0A1A211C19391A192021DA21E269182B2B4EF44DED394E10F611394DE51117392F003FDEF4FD10FDF5FD313001715D00725D7112161F011E0133323637330E01232227262F012E012322070607233637363313BA34125E2A1A1030270985126B671F39211E511120102618180A821623407E8105DE0C07230E083323698E0F080A1B060516172867355FFE810001FFBD0515028405AD00030022B900000167400D03011A0500190405A6217B69182B2B4EF44D104EE64D002FFD3130032115214302C7FD3905AD980002FFC9045F027B0600000F0010005840269B00AA00B800030F050F060F0E0F0F1F051F0F0609090E0628021007101217171A10050F390EB80161B5063905191112B80112B3216769182B2B4EF44DEDF4FD11394E456544E62F003FDE4DFD3C392F3130005D015D0006232226273316171633323736
+
+373301026EB29A9AB20D870E522E44442E520E87FEA705679191995C211313215CFE5F000002009A045F019E05D500030004002F401400CA030407040617171A0401CD00190506CD2181B9012800182B2B4EF44DFD394E456544E62F003FDE4DED313013211521179A0104FEFC8205D5ED8900030042045F01F6067D000B001700180043B20EEB08B801A1400F02EB141807181A17171A181711EB05B801A1B50BEB1719191AB80104B3217F88182B2B4EF44DEDFCFD11394E456544E62F003FDE4DEDFCFD313012163332363534262322061526363332161514062322263513A5463131454531314663805A5A80805A5A80DA0572454531314646315A80805A5A80805AFEBC00010012FE2901F60000001E007540430B171C170224103310431053108F11052B173B174B175B1704090A17140EEC051B1814AE1E3D190A2017171A020A1718191B05091A6F11014F115F1102116D02091F20BC013400210149012700182B2B2FD5ED5D7139111739104E456544E6003F4DF4ED3939DCFD1139D4DD3130005D01715D041615140623222726273716171633323635342623220607273733073E013301966096763348213C263915301E3C343A2113281981CF6D58211C10774F4A5C6B150A165611050C331C2A220908756F830705000002FFD304DC0342060000030007003A401B3F003F013E023D030405032804000303B83001010104B806190809BC011800210042014200182B2B4EF44DFDD45DED003F3CFD3C3130015D0121032313032313021F0123F4C401F4C4950600FEDC0124FEDC012400010042FE2901F6000000160052401319011A1429012A1439013A14060A160B0F3B07B8014CB7160A0B1817171A00B80194400B1604C812A116191718C421B80151B13C182B2B4EF44DF4ED10FD4E456544E64DC4003FF4ED3912393130015D21070E011514163332363715060706232226353437363701E8434542423116301F2D1E3644698654316D3032482C2E350C0B9011070D75515B4D2D3C0002FFB6045F028B06000006000700AF408A2602290436023904490046065900560669006606A602A904B602B904C602C9041026022A043602390447024904880087069706A706B702B804C702C8040E090007061A0016062900270699009606AA00A606B800B6060C04030C011C014C015F016C017C018C010701000707070002010406050307030112052205320503051A0901190809A6217B69182B2B4EF410F45D1139393D2F181239391239392F003FDE4DDD5D393C0131300172715D1303331737330307A1EBE88382E8EA8004D5012BA9A9FED5760001FFF1000004AA05C2000D009D4138000500080004000900040002000B0003000A0003000A000A01A600120004000900090004000200030004000500080009000A000B000800010006
+
+0002000C004C00010008000D001A000F0008000B0009000A000B0025000500020004000300020019000E000F011C0021005200AB00182B2B4EF4DC3C103C4DFDDC3C103C4E10E6003F4DFD3F121739192F2F18872B107DD4073C3C10073C3C3130290111073537112111251505112104AAFBF2ABAB01340130FED002DA02366DC26902CEFDEBB6BBB7FE18000001FFE80000024B05C2000B009B4137000500080004000900040002000B0003000A0003000A000A002F00120004000900090004000200030004000500080009000A000B000800010006000200010008000D00170017001A000B000A00090008000B0025000200040003000500020019000C000D014B00210135007900182B2B4EF44D3CD43C10FD3CD43C104E456544E6003F3F121739192F2F18872B107DD4073C3C10073C3C313029011107353711211137150701A8FEE3A3A3011DA3A3023868B26802D8FDD868B06800FFFF0055FFDA050E0790023200360000001000E12F07FFFF0042FFDB04250600023200560000001000E12C07FFFF0034000004AF07630232003D0000001000E10A07FFFF0021000003CE06000232005D0000001000E10A070002006A0000017105D00003000700484119000001B600010000000601B60005000A000900170017001A0003000400220000000500190008000900CD0021006C003C00182B2B4EF43C4DFD3C4E456544E6003FFD3FFD313013112119012111216A0107FEF9010703870249FDB7FC79024B00000200120000057B05C000110022006A412500100017002A000D001A001A0015001C0000002A0015000B002A001C000200150008000700370022001A0024000E000D001000250018001A0017001900230024012000210052005600182B2B4EF44D3CC4FD3CC44E10F64DED003F3FED10ED1112392F3CFD3C313001323736373E01351027262B01112111211124070229011123113311213216171E0115029C7D36593B36299654AEE30136FECA03B4639FFE89FD9A8A8A0268ABF158434001001019544DD3520130693AFED0FF00FE6EFAC2FEC802920100022E677A5DEE90000002006DFFE3048B05CB0022002E00CB414A000500FA0012001200050012000800FA0012000F0008000F000F00080007000F00120007001000120005000600110006000700060011001101AA00120007001000100005000600070008000F0010001100120008000C00020025002000220022001C000C0010002B005D001C000B002E00820019001A003000060007000700280082001F0019002F0030017600210048004E00182B2B4EF44DED392F334E10F64DED003FED3F12392FED391217392F072B107D08C418070E3C3C07082E3C3C060E2E2B060E2E2B31300016172E01270727372E0127371E0117371707161716171E0115140023220035340033
+
+002623220615141633323635025B35324D3D36DD66E2371F28EB212F2EB666B2712B44295339FEEFF6FFFEE80109BF013C70806F878B67757F03EF060D543B2F646763271C20681623234F674976334F458DDB74E1FECF012AE6DE011EFE81B2999C9894A696FFFF00230000054207630232003C00000010008D0904FFFF0015FE47045006000232005C00000010008D1404000200A50000049505C0000D00180050411C00130024000B00120024000200000000000C0008001800360006001A001A0012000C00010025000000190019001A01740021009501B700182B2B4EF44DFD3C3C4E10F64DFD003F3FDDEDDDFD3130132115332004151007062B0111210027262B01113332373635A5012BC001000105E279C9A1FED502CA5F367C8E7E7C3B6A05C0DDE4C1FEDC6B39FE8A03B22A18FE6F1A2F880000020080FE55049C05C0000C001E003B40210E062411070D001B0C24170B1C0E0336141A20091F0E1B271D191F209821504E182B2B4EF44DFD3CE44E10F64DED003F3FFD393F3FFD3931302437363534262322061514163303113E0133321211140223222726271121110322391E8274618D7A79EC339B66D2FAEBDD573B6640FEE4D1964E7492A89AAA9CB204EFFDEF5957FEE5FEE4F5FEB017276FFDC5076B00010049019C048402A10003001F4010022203011A050219040405A9216A46182B2B4E10F410F64D002FFD3130011121110484FBC502A1FEFB01050000010055000B0478042F000B006740340805090904020B0A0A0302050606010B08070700040304090922120A090A0A03060607010122120000010700000A040601030907192F183CD53C00192F3C18D53C313087082E2B1008C487082E2B1008C4070E103C3C070E103C3C070E103C3C070E103C3C01170901070901270901370103C0B8FEA6015AB8FEA5FEA9B90158FEA8B90157042FB9FEA8FEA9BC015AFEA6BC01570158B9FEA80000010050024401F605AA000B0026410C000000010001000A0198000700050007000B0195000900002FDDFD39003FFD392FCD303113353E01373E013533112311506E3E161D23A4C7049C74051211153B22FC9A0258000001001A0244029E05B4001D003841130016019700170198000201970006000A0005001D019500160015000D001800060194000700182FD5ED10DD393CED003FCDEDFDED303100262322070607233E013332161514060F010607060721152134373E013501E1463A561D1202B503A49287B95C6B492C1A370D019AFD7CE48E5504E24135204E9C9894825387452D1C1428199DCD9A605F3A000100120236029E05B4002B0054411D0022000C000D002B00040196000D00280198001401960018001C0005000C00110195001F00080195000C0025002B00170194001800000194002B2FEDD5ED10DD39EDD4ED
+
+2F003FCDEDFD39EDCD2FDD39303113161716333237363534272627353637363534262322061523263736333216151406071E0115140623222635C90412215725224040276C59243F46343C41AB05634B878AA33E343757B98199B90355401E37122253521B110479020F1B4D36394F3F87553C836A41551A085E6286938798000003002FFFDA065505AA0003000F00300081412D00010091000000020091000300000002000300010000001700120197001B019800280197002B0008000400050005000E01980000000B00050030019500290028001E002B001601940017002B00000003000B000F0195000C00042FDDFD39D4C42FD5ED10DD393CED003FC4FD392FCD3FEDFDEDCD103C2F3C8705ED10ED30310133012303353E01373E01353311231100262322070607233437363332161514060F010E01070E010721152136373E01350482A1FC95A1E86F45162018A4C70489423F561D1102B458548D91AF65604C181C18122308019AFD7B03E39A4705A5FA3504C274051612184213FC9A0258FDFB47381F4C90574D9D78588A3B2F0F14110E210F9CD1976B5339000004005AFFDA065E05AA000A000D0011001B00924132000F0091000E001000910011000E00100011000F000E0006000C0007000D0001000501970009000D000D0007019800020008001200130013001A0198000E00170005000D00070005000C000301950000000900020005000E00110017001A0195001900122FDDFD39D4D42FD53CC4FD3C113939003FC4FD392FCD3FFD392F3CFD3C11123939103C2F3C8705ED10ED303125231523352135013311332111031333012301353637363533112311065E61BDFE89015CD861FEE2EE8AA1FC95A1FEE971345DA4C8BBBBBB95020EFDE20174FE8C0465FA3504C2740614245CFC9A02580004004EFFDA068E05B4002D0038003B003F00C04143003D0091003C003E0091003F003C003E003F003D003C003A0034003B0035002F003301970037003B003B00350198003000080023000C000D002D00040196000D00280198001401960018003C001C0005003C003F003B003A00340032003A019500380037002F0034000C00110195001F00080195000C0025002D00180194001900000194002D2FEDD5ED10DD39EDD4ED2F2FD53CC4FD3C1139392FC4003FC4CDEDFD39EDCD2FDD393FFD392F3CFD3C11123939103C2F3C8705ED10ED30310116171633323736353427262735363736353426232207060723263736333216151406073616151406232227262701231523352135013311332111031333012301040313215728223E42276A5A243E3E3D4C1E1003AA056C4B7D8CA1383A1F70B586CF502B07064061BEFE89015DD861FEE1ED9CA2FC9AA203553A203B132254501C10047902101B502843361F39925234846542551D026B
+
+637D986F3D73FD66BBBB95020EFDE20174FE8C0465FA3500000100000000045E05970011006B4126000C0008002A000F00070005002A00020001002A00070002000A00100004000A0008000300760000001A0013000700060002000A00B3000D000F000B001900120013011C0021005200AB00182B2B4EF43CC44DFD3C3CC410F6E4003F3F123939ED2FFD2F3CFD3C3130012111211521152115211521352335331121045EFD620240FDC00136FECAFEE8A8A803B60497FEE4FBD8DFC9C9DF03EF00FFFF0055FFD905AF07890232002A0000001000DB2310FFFF0042FE42045E06000232004A0000001000DB3010FFFF0084000001B607550232002C0000001000DC040400010055FE29050E05ED004B00B24141000D00000010000A00210017001E0024001600080031003800380029002A0048004900050027004B00210024000A000D00040017004B00D4002A001700D4001B00410013000300040041002A000900480009001700960016004F000800960027001A004D001E00360010005700000036004B0019004C004D011E002100AD005600182B2B4EF44DEDF4ED4E10F64DEDF4ED003F3FED3FEDED10ED11173901111217392FDD11123911123939111239313001161716333237363534262F012627263534002132041721262726232206151417161F0116171615140021073E01333216151406232227262737161716333236353426232206072737220035017B0E294BB66D448180899CE6589501200117E9014908FED8086C486B778E462D93FEA75584FECBFEEB3E211C10516096763348213C263915301E3C343A211328192B63BCFEB601C765325B182E7D494F1E23343D66D9C60106F7EB85382560564F271A233D284368C5CAFEF55D07054F4A5C6B150A165611050C331C2A22090828960107E600010042FE290425046100440068403C1D1E0A090414442314182C1007042C230B410B2A3131414222230520440A1E1B144D2207132D074D201A460B001B4D0D2D004D441945468721484E182B2B4EF44DEDF4ED12394E10F64DEDF41139ED113939111217392FDD003F3FED3FEDCD10CD111739313001161716333236353426252E013534363332041721262726232206151416170415140623073E013332161514062322272627371617163332363534262322060727372226350163091E358F546350FEFFB998EDD7CC010113FEE306192F715D4F54FF0153F1E040211C10516096763348213C263915301E3C343A211328192B61B0F5015C4C2039323230323D2E898097D9A3C837203A3A27312D3851F5A2CD5E07054F4A5C6B150A165611050C331C2A2209082897D9A800FFFF005CFFD7057B07900232002600000010008D1F04FFFF0047FFDA043406000232004600000010008D1E04FFFF005CFFD7057B0790023200260000
+
+001000E11F07FFFF0047FFDA04340600023200460000001000E11E070002003FFFDE04E405C0001800250050402C0B04090505180700021F2418070E0A0F2524120B1B1F0F1F050603270A090C1A2722361519262798214845182B2B4EF44DED4E10F63C4DC4FD3CC4F4E4003FFD393F3FFD393F12392F3CDD3C3130001617352135213521153315231121350E012322003510003312363534272623220615141633027A9A30FED9012701217F7FFEEB3D9C74BFFEFB0101D7B77E653E527D757779045C574DFD98737398FB4B9761580135F201170140FC72B48FC85634BD8C97B5000000010000000100000F3018F15F0F3CF50000080000000000A2272E8000000000A3C1D703FEA3FE25080207E0000100090001000100000000000100000629FE2900000800FEA3FEAC080200010000000000000000000000000000010205C7009A00000000023900000239000002AA00E103CB00A70473000004730038071D002F05C7006F01E7007302AA004602AA0015031D002F04AC00390239007602AA002F023900800239FF90047300400473008E047300400473003604730036047300360473004004730034047300360473003D02AA00E802AA00E804AC000704AC003904AC000704E3007B07CD00C905C7003405C700A105C7005C05C7009C055600A504E3009C0639005505C7009A023900840473002D05C700A104E3009C06AA009705C7009706390065055600A30639006505C700A30556005504E3002105C7009C0556002F078D001E055600210556002304E3003402AA00800239FF9002AA002F04AC007B0473000002AA00070473003B04E3007B0473004704E3003F0473002F02AA001504E3004204E300870239008902390009047300820239008B071D008004E3008704E3004204E3007D04E3003C031D00820473004202AA001504E3007D0473001A0639000E0473001A0473001504000021031D0039023D00A5031D006604ACFFF405C7003405C7003405C7005C055600A505C700970639006505C7009C0473003B0473003B0473003B0473003B0473003B0473003B047300470473002F0473002F0473002F0473002F023900760239FFCE0239FFB60239FFD504E3008704E3004204E3004204E3004204E3004204E3004204E3007D04E3007D04E3007D04E3007D047300470333005E04730045047300420473004102CD00890473000004E3008905E5001A05E5001A080000BF02AA00AF02AA000E04640015080000120639004705B400220464001504640013046400150473FFEA049CFFA703F4FFE505B40087069600750464FFF10231FF5602F6002802EC000D06250027071D003804E3002A04E3006D02AA00E104AC00390464FFD50473001E0464001504E5FFED047300AF047300AF080000BD0239000005C7003405C7003406390065
+
+0800004B078D003F0473FFFB080000F10400008B0400009702390089023900840464001503F4000F04730015055600230156FEA30473003402AA00AA02AA00AA04E3001C04E3001C047300470239007102390084040000920800000405C70034055600A505C70034055600A5055600A5023900760239FFB60239FFD50239FFCE0639006506390065065200690639006505C7009C05C7009C05C7009C0239008902AAFFEF02AAFFE102AAFFF602AA000202AA00D302AA007B02AA004B02AA000C02AA007B02AAFFEF04E3FFF10239FFED055600550473004204E3003404000021023D00A505C7001204E3006D0556002304730015055600A504E3008004AC003904AC004502AA005002AA001A02AA001206AC002F06AC005A06AC004E047300000639005504E3004202390084055600550473004205C7005C0473004705C7005C0473004704E3003F0000000000000066000000660000006600000066000000DA000001400000035000000490000006300000088C000008D600000966000009E600000AF800000B6600000BD600000C1200000C5400000CCA00000D9C00000E0400000EFA00001002000010CE0000119A0000129A0000131A0000140E000014F400001550000015E600001676000016CE000017660000183400001A0E00001B2A00001C0E00001CF200001D9C00001E2A00001E8E00001F9000001FF600002046000020C0000021A8000021F2000022FE0000238E0000243A000024C400002616000026F600002836000028960000291C000029BE00002B7C00002CC000002D9E00002E4600002EAA00002F1600002F7C0000302600003058000030AC000031F2000032A00000337A0000342E000035540000362000003712000037A40000380C000038A6000039D200003A1200003B6200003C0000003CAC00003D6600003E1E00003EB000003FBC00004050000040F8000041C00000448C000045CC000046FC000047C20000489C000048DE000049BC00004A6A00004A8000004A9600004BBE00004BD400004BEA00004C0000004C1600004C2C00004C4200004C5800004C6E00004C8400004C9A00004DD400004DEA00004E0000004E1600004E2C00004E4200004E5800004E6E00004E8400004E9A00004EB000004EC600004EDC00004EF200004F0800004F1E00004F3400004F4A00004F6000004FD800005048000051D80000535A000054D00000552C000055A8000056B20000590E00005ADA00005BDA00005C3200005C9600005D7400005E5400005FCA000060CC0000614C000061EC0000628E000063C0000064D0000065BA00006672000066DA0000673C000067F400006934000069CC00006A9000006C2200006D8600006E5600006ECA00006F1000006FEE000070F00000723600007302000074080000750A0000757A0000757A
+
+00007590000075A6000075BC000076BA0000780A000078420000787C00007924000079D200007A3400007A9000007B0A00007C2A00007C4000007C5600007C9400007DCC00007E6C00007F0E00007FE4000080A600008144000081960000820A000082C20000844E000084640000847A00008490000084A6000084BC000084D2000084E8000084FE000085140000852A00008540000085FE000086140000862A0000864000008656000086A20000872E0000880E0000884A000088E400008932000089C600008A9C00008B0200008B9E00008C7600008D4C00008E1800008E2E00008E4400008E5A00008E7000008EE200008FC2000091260000913C00009152000091F800009298000092D40000937E000093D40000946C000095400000965E00009754000098D80000998200009998000099AE000099C400009B5600009C8400009C9A00009CB000009CC600009CDC00009DA200010000010200500007005B00060002001000100037000007E8028C00060001B10840BA019000145DF44009011F04000B1FD819EEBE012E000D00E6012E000D00B0012E400C0D000963833C1F63838348294109014B00370401001F014500240401001F0144B224AB1FB8013EB224231FB8013DB224231FB80102B2371D1FB80100400937241FFD37621FFC37B80801401B1FF824931FF724931FF6243F1FF524311FD1371D1FD037471FCD41B80801B21FCB2AB80201B21FCA24B80401400F1FC824811FB537291FB4373B1FB227B80401B21FB141B80401B61FA437811FA384B80401B21FA22AB80401B21FA124B8019AB21FA024B8019AB61F9F243F1F9683B80401B21F9527B80401B21F8227B80401B21F7084B80801B21F6FB3B80801B21F6EB3B802ABB61F6D24261F6224B80101400B1F5D246C1F5C24391F5441B80125B21F4D27B80401B61F4C27CD1F4B41B80401B21F4024B8019AB21F3683B80401B21F3524B80201B21F3224B8019AB61F2C24BB1F2884B80801B21F2241B8040140131F20244C1F1D24261F2CA0961F2C245E1F412AB801A8B748282A2448279636B801F4B21F4D27B801F4B21F9527B801F4B21F6E27B801F4B21F6327BD01A700470029015A00250199B348296FB3B80190B21F83B3B8019AB348283725B803E840121FB327482784274827362748272527482755B80154402C0797076407550733072B072907260721071E071B071408120810080E080C080A080808060804080208000814B8FFE0402B00000100140610000001000604000001000410000001001002000001000200000001000002010802004A00B806008516763F183F123E113946443E113946443E113946443E113946443E11394660443E11394660442B2B2B2B2B2B2B2B2B2B2B182B2B2B2B2B2B2B2B2B2B2B18011DB0964B5358B0AA1D59B0324B5358B0FF
+
+1D592B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B65422B2B2B4B5279B35279EB56456523456023456560234560B08B766818B080622020B1EB794565234520B003266062636820B003266165B079236544B0EB234420B152564565234520B003266062636820B003266165B056236544B0522344B10056455458B156406544B25240524523614459B35045484E456523456023456560234560B089766818B080622020B148454565234520B003266062636820B003266165B045236544B048234420B1504E4565234520B003266062636820B003266165B04E236544B0502344B1004E455458B14E406544B250405045236144592B2B4569534200
+
+00>]def
+
+/CharStrings 258 dict dup begin
+
+/.notdef 0 def/.null 1 def/nonmarkingreturn 2 def/space 3 def/exclam 4 def/quotedbl 5 def/numbersign 6 def
+
+/dollar 7 def/percent 8 def/ampersand 9 def/quotesingle 10 def/parenleft 11 def/parenright 12 def/asterisk 13 def/plus 14 def
+
+/comma 15 def/hyphen 16 def/period 17 def/slash 18 def/zero 19 def/one 20 def/two 21 def/three 22 def
+
+/four 23 def/five 24 def/six 25 def/seven 26 def/eight 27 def/nine 28 def/colon 29 def/semicolon 30 def
+
+/less 31 def/equal 32 def/greater 33 def/question 34 def/at 35 def/A 36 def/B 37 def/C 38 def
+
+/D 39 def/E 40 def/F 41 def/G 42 def/H 43 def/I 44 def/J 45 def/K 46 def
+
+/L 47 def/M 48 def/N 49 def/O 50 def/P 51 def/Q 52 def/R 53 def/S 54 def
+
+/T 55 def/U 56 def/V 57 def/W 58 def/X 59 def/Y 60 def/Z 61 def/bracketleft 62 def
+
+/backslash 63 def/bracketright 64 def/asciicircum 65 def/underscore 66 def/grave 67 def/a 68 def/b 69 def/c 70 def
+
+/d 71 def/e 72 def/f 73 def/g 74 def/h 75 def/i 76 def/j 77 def/k 78 def
+
+/l 79 def/m 80 def/n 81 def/o 82 def/p 83 def/q 84 def/r 85 def/s 86 def
+
+/t 87 def/u 88 def/v 89 def/w 90 def/x 91 def/y 92 def/z 93 def/braceleft 94 def
+
+/bar 95 def/braceright 96 def/asciitilde 97 def/Adieresis 98 def/Aring 99 def/Ccedilla 100 def/Eacute 101 def/Ntilde 102 def
+
+/Odieresis 103 def/Udieresis 104 def/aacute 105 def/agrave 106 def/acircumflex 107 def/adieresis 108 def/atilde 109 def/aring 110 def
+
+/ccedilla 111 def/eacute 112 def/egrave 113 def/ecircumflex 114 def/edieresis 115 def/iacute 116 def/igrave 117 def/icircumflex 118 def
+
+/idieresis 119 def/ntilde 120 def/oacute 121 def/ograve 122 def/ocircumflex 123 def/odieresis 124 def/otilde 125 def/uacute 126 def
+
+/ugrave 127 def/ucircumflex 128 def/udieresis 129 def/dagger 130 def/degree 131 def/cent 132 def/sterling 133 def/section 134 def
+
+/bullet 135 def/paragraph 136 def/germandbls 137 def/registered 138 def/copyright 139 def/trademark 140 def/acute 141 def/dieresis 142 def
+
+/notequal 143 def/AE 144 def/Oslash 145 def/infinity 146 def/plusminus 147 def/lessequal 148 def/greaterequal 149 def/yen 150 def
+
+/mu 151 def/partialdiff 152 def/summation 153 def/product 154 def/pi 155 def/integral 156 def/ordfeminine 157 def/ordmasculine 158 def
+
+/Omega 159 def/ae 160 def/oslash 161 def/questiondown 162 def/exclamdown 163 def/logicalnot 164 def/radical 165 def/florin 166 def
+
+/approxequal 167 def/Delta 168 def/guillemotleft 169 def/guillemotright 170 def/ellipsis 171 def/nobreakspace 172 def/Agrave 173 def/Atilde 174 def
+
+/Otilde 175 def/OE 176 def/oe 177 def/endash 178 def/emdash 179 def/quotedblleft 180 def/quotedblright 181 def/quoteleft 182 def
+
+/quoteright 183 def/divide 184 def/lozenge 185 def/ydieresis 186 def/Ydieresis 187 def/fraction 188 def/currency 189 def/guilsinglleft 190 def
+
+/guilsinglright 191 def/fi 192 def/fl 193 def/daggerdbl 194 def/periodcentered 195 def/quotesinglbase 196 def/quotedblbase 197 def/perthousand 198 def
+
+/Acircumflex 199 def/Ecircumflex 200 def/Aacute 201 def/Edieresis 202 def/Egrave 203 def/Iacute 204 def/Icircumflex 205 def/Idieresis 206 def
+
+/Igrave 207 def/Oacute 208 def/Ocircumflex 209 def/apple 210 def/Ograve 211 def/Uacute 212 def/Ucircumflex 213 def/Ugrave 214 def
+
+/dotlessi 215 def/circumflex 216 def/tilde 217 def/macron 218 def/breve 219 def/dotaccent 220 def/ring 221 def/cedilla 222 def
+
+/hungarumlaut 223 def/ogonek 224 def/caron 225 def/Lslash 226 def/lslash 227 def/Scaron 228 def/scaron 229 def/Zcaron 230 def
+
+/zcaron 231 def/brokenbar 232 def/Eth 233 def/eth 234 def/Yacute 235 def/yacute 236 def/Thorn 237 def/thorn 238 def
+
+/minus 239 def/multiply 240 def/onesuperior 241 def/twosuperior 242 def/threesuperior 243 def/onehalf 244 def/onequarter 245 def/threequarters 246 def
+
+/franc 247 def/Gbreve 248 def/gbreve 249 def/Idot 250 def/Scedilla 251 def/scedilla 252 def/Cacute 253 def/cacute 254 def
+
+/Ccaron 255 def/ccaron 256 def/dmacron 257 def end readonly def
+ %endsfnt
+
+%beginsfntBC
+truedictknown type42known not and ( %endsfntBC)exch fcheckload
+/TrueState 271 string def
+TrueDict begin sfnts save 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt cvi 0 72 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt cvi 3 -1 roll restore TrueState initer end
+/BuildChar{exch begin Encoding 1 index get CharStrings dup 2 index known{exch}{exch pop /.notdef}ifelse get dup xcheck{currentdict systemdict begin begin exec end end}{exch pop TrueDict begin /bander load cvlit exch TrueState render end}ifelse end} bind def
+
+ %endsfntBC
+
+%beginsfntdef
+truedictknown type42known or( %endsfntdef)exch fcheckload
+currentdict dup/FontName get exch definefont pop
+ %endsfntdef
+
+%beginType1
+truedictknown type42known or not( %endType1)exch fcheckload
+/FontMatrix [1 2048 div 0 0 1 2048 div 0 0] def
+
+/FontBBox{-349 -475 2050 2016}def
+/FontType 1 def
+/UniqueID 16#00496671 def
+currentdict
+currentfile eexec
+
+9E5C7C4BC190D9C0A90731F2D4890973BCF8F6845733295A512342824A24AB2B254C5A32129BD0E023EFED16E1C593131DAFC688C0F251A74D63C9A1794CC1DEEB295CCC880F33F31B9FFE15B4D39EFE347279315EF314ECCA86AB0A1D031E25B939AE1EA0E20270E54475A43578FCAEA4F5E7C6BEEFF152A50987C1A13BD26CE6D6C8291F78B1B57B6719E16914CC30459FAAA2076CB8859BED655D12ED17D7160D6D62EF7C0FA8F1B7EAF83940F5C1566002AECC2F7FE97B1C8D1D7C80EF4BAF462F33423845AA999A71D56BEA626583B574B3D7E14F4A46A95A4756F01730E643F89BBB19C5B6D481D47034B0F908BE8FBBC7C540AD0B35FA212104E758B6F2581984CB979B2F88762ED47205080E089B8D1F62EE9A885875F533F149B20E857140AFD05CDD9AB7D63800A6540487C18A63E6D19D004C44EC970027A21CD54757C6C78BBF03F9A5F4982B7AAB00834FD41EC06586A8C8E65428F6971063769BB44EAB88B1064E3E4F444E7E10D71FC1E4C68FC69C51EF37955D0F877759CA363A1DD48FFB0BD430EE691650109BB20BAE005E92B9381C62ABCED0E2F262A60E85F2A62009A63AEBE112FDA1D02E8A6A172A4D02652034F43B1E4E2916741A5813FF79277E42BD7F78FECB45BA2717B80FFB01F0AA1BDF51BDDB8E6699D5DBF505F8F412A66CACD882D0963B545FFA56BBE7B014DD9D064DED065383AE4A3024AD22773DE73FD1A9B9CF59DA2ECCD9165802860F71EE04DD4C9FF85D021DEA984B409521BB2B94CB255678285C2ABF8C918959B68BF4099B3D693CC7DA172658753080EA1CA80652774B83BDE15D50CCE39A9DDDF3F8109D4C8DD5D834268E2D5EB756822E1FB7B556A0A8FFB90F310D5CDF5BBB639462410A0EB11036C090A328EB50E4CA64D54D9A652733DE346DA5BDFC40F7B8CAF50FF209764086AC105235BCE14D24A19414BDADA7AE837C9153C7F59CF89CA095ED5FEBA34FE4234B8085645C7CE26D4D18433CF4AB2C4C07CA56BC157B00AB8A7CD261E0E7447AE3E9AF861ACF7A8A5EC06E8A37E5BF9C1FB60F0445DCD28555141E4F081BE494BF72077A79173A28DBC35C03DEA2F3F1190AA877713A16F8CCD93246650639B42CB590ED257B33B623818691FA38ED196313148331628152B59BE5C9B8D14C57C2A4765E1781C81EAED358A0E921C839538D8B090C8661202BCFF918E57BFFD2A818EAEF523F02F61A39A231FECC3F12BE8FA9ADFA4636D94F78CB89D69DAFF7DEE2B6F7B4E0EBF72E3CB5EE50EABE2DFA0C8A7AA84B2FD2BEBFF95716C806E02211726E76A28B0FBF3D780309424513FA25487D6E7C7C5CAC510C5EF85513C4B6F842BE67E71FA644EE03D0CF250D37C0958F9FB9ECE3960EA70F76C5DB81E426BE9B96796CF35B6AD77D22376E687000DBEDE544666ECD270A06A20C80A0D0EE
+7F056388C16EB046DA1EEBE4E808AB90FE993E7AF6EF4EBE13904D8CDA0DCA50224CE02983794383883D687C59F2314D27B9A26BBE69DD841FB2DDD55AF3EBF7C481CCBADAEDF90A210A5BAD9FF2A4CED1B5C587C435C670BA6F304354B73ED485E19C529337AB5BB156C230AC41F5ECDE4B701D772706A09405C8293E01C8F915C6922543E1F5C1A1B89595A1C1643BEA5DD0E7481E85878582A8C0A0CC8C6167BE5D5348A39A3ECDAA3D7C6D0474D5CE214BCB1DB1A11AA5078C230E60F70538278B4F60623AB973075FA8D471E5AD64FAB8719E7FBAAD4A5C6D9A9686821BF6BD5DCC61922658DD3DB9CD4D60722DAE00C82D23D0C002CFE1056BA5FF058620EB3D9D717B58CF70645A9C431BFE6B8A84F1A5E140B6DAA4DA84EE070D1A921AD06EA651C3C396DCAD7CF6741A384E83DB4432962EBB50AFD7107D020CA04DBCAF41A2526B294B1AE57ADC5543A0BA2F8B2110E260405C112D90589EFD491BD8B961372E8518DE9A0501DCA5FC402E455A852B5C51F3FE08AA9F038A531A372D8A7F8813639F8B25080E4DE44269080ACF2BAC320DE577C8F6027961674598F6D7019443866857174E9A982D7EBD378665A3BF9C073CC86E7337534B81F57773C206A69F039E010E4C93A838EECEEE10C091B58F0762FB6C1F7E969946BDDC6F5188211BCE656EF3F739C9256BE85C9FB4E0C06DD369C1DE027E7348561717F58AC503D89873A3D841E4B9BAF70A3DB4BD97F6C0A9EABCAEF34083529107BDFA5FFF2A2D717C656AA010E023CBF90A4BB9A165FEE916E343A4E9E41A24C043E20CDA72293C9299A001815531A574509F098A78BCA17759461E16BCD93CB3E0D24AED5CA2676BA8742C0572661095A5664C2F3D9547174CB90E7F56F91D493AAFCD504F40CE454DEE5C50713A9883060BBA8967AD645D9C21630140B34FFE6218968FC4EE5ACCD3BBD4E76D59A89C1547A4735006896F6F27A4E57E1B372ED58D7F74C776F067E9756B4EF8DC6E18A6AFC4C00169D0E84E0A28DC7F055DB77A9357FDB12EB1164D9A3F113CFB45ABB6946D97EF513B107C355096E503E544EB6EA55BAC18BA5B931DDBDCA79D254D69092E3253D606507B757F3E8C1F606D9443D8D154866A929A74047F3200C8CA66C67DA6485F7CF5DBE9FB3E3F2056BED22071C1F610FDABA2592C6BFAA2DE16FB5A4EF0C4643396B475D5A4810BFF1D5DD5FEAF458344C73CE76D8660B7CA29B1A6ACEAD67DC03D2739CA4D4A7D179173C0D882685B05A07994F66ADAACE50F279A50EF9FAD1741BDA509B186AFF76904D0EC33C267206A46254CE1A3320446C3FD66217D3DB5C3C3040E9CF1AE33079FD19ECC21F38E3E775F85F58C5188C0E76CEE55328AC1739832BE96D21C43748F2D37D6DD0D20EE4580AE1889B39438CD43D85A886A01A32AF1CBEC6F1FDBFFBB
+3B89455F482302E73F2CDE7B9CAF05AC1DAFBF1C90AAAEC8244E42F4B618F629FC0AD431D4801A58467010CF5738A2DB986C5DDF9F29FEDF61FDAB9D7711A042F1B5933CFF04BC094FCCC2822EF120AB4D632BFD28E5EE6770ADC25BF174A607C0C6F37EECC9BF9C46816D495F7DB06092DF56D592FCDED180C94A2A86B762B0974BBABAAE59B2BC7E8F6A914A0B25FAE3302F7501DF465026BBAB032EB61C7E354CE780C1E38D157F0EE2248CE4570CAE276EFA5E7263D531CDADA10822852FB632B6E4B7C1E4371A63CE5DF0761AE25084478CC5126A4FFB60743DF35FBF14B5819A56875B7DBD1354B3512A246494D71E77FF5EE2B9D55EF405227769E52A7AC1228DA5946043F54344189FEF98941740DACED5019ECC83FD46AEE28D4D8BF42DF64FD8E999E95C1963851E768C48D04F9821BB68104A9AC412C569446D3F3F4788D5968A8C7830FDAB2C100ACEFD8E61F46E7E42BB4AEAAC03020AE5975A14D10213F60112FD9B73A3E1876F115FBDA73D27A28EBA45B5559EE14A594A3F8923969741628824FE7DA56D709372776B17D9F0BC66C0DA221984D2777BD47421BF4FB4AD81D8DB0A7B6EB8C50CF4D79C13678D98CC1A514E577F6BBB376BF59984894CBD8B3B5F751652BA5189833054864D7BB40884F83A5153DC688CEF8866E16F0C9CCAA5BA1661EE4D15A4C22D79AE2E7D074DE5ECC3CCCEB5F4702E46E3F50F5BB2EC66FD11F78246C2E730DBAA42C5AE448633D4FF67A02A83A60794EE740A36325F6B87D25C0A5F97A081277AEAD1A88DD02A9F77B639EC211A7CCE6956A10AEF9C9781082A80556FBFC859CA1744A283DBC0E9445D9FC3D8230FE05240918E357B98D300649CB5CD8B784D1AACC2706E648C2A73AA504CB4737612EB39A9EE6675C5140E3839FD2A75D04BB52F4E02DD37D2F262A9A3336D1B01714794790A5C282E0BC1886F181AB2F676610F83D4C65F58BE4D9CA184F1FF76BA6208866C7637BCF5783F81191EDF0D64C5D5FA3C969D7F5BDB90973BF644EB407A693F3E8286CF7A884DF94393FD3337DE27B96C9AEAC7A7F686E5AEAD1A3E4A2FB147242C63F2988413DDFAC58F8FCCAF6C235362262EA354EA1F731AE0DEDAE6D68EC2C6058CCF35CB9140BA35F5422C4264F778890B8D80433C0B926244C23F2F92E733CF8E86FC28F5EDE43B2F84BF929A9714ECED176CE8B29A9EADD7556EE98FF11624DD0A1119CD77C3B5F0AE9A45B2FEF813BD5963488E139EED28951E87FF1515A70C3204CBA54796536352720036054D5E534EC8E31605A5BDAD14317F58767EAE115F1C9A477E6FE9FEDED0BEBA095A5AECD0CE36303BADBD157D40F06EE4CF701FC4864E2E9D33D9BA9250B04808CEEA290EC000BA8D0926DD6A41BE054CC1E9AE3A7AF78039C29F738CFAE6FD06A12CFA62F60537CDDD5793EF
+44824F27494EFE1AA0810E64F93FF301BFFE1BF761133A4C72374C21AD11459260A21D9B00C78AE49B776AFE69450C9B1010F3C3AF56732C66EDB0E553AF98EE3C2C9E5FA84F1BF9A6CF88A411D5D24204B60D47D46EBF4686845CA57640C441F0545985A20EBC816A893DE6C47D0EDF4D7753E77E90EA33AAAA853B4D6EBE68899BAD12A15D031FB966EB78F99CA9C88A6FC27CC1AC9F854FBE9F5DDAE6A1D5C5C973AEA6394ED695C02CE7CE8FD15727B5D9463590699BFD49F4622DF85B8D37FCB24E411B875329BCE9453CA101EB34A2B49E992A9CF671A1783B4E22372ED771E49F8605C24C94C674B70DA6AB0ED0900AC60C830D2626B6321B40409417CE72D2EA9411E5FB64A8B01B05FEC0C9FDBF49EB0A2B3BA615909E62013A51E7D65EE169BE08B17643C553329721F178DC4CF0C9E6494D00427CFCD062FE5B24F943BA68F4B13EFE63D0A44A4D0EBA1FB9FE8D433D7F01689F7511F28DA4367F35239CD8228F343710BF25B8696A982C17574B56F12E25910F3C9CA6DE779112E2941AB9C460A1B461EC78AC4BB2A3A94B8F5DF5F8491B1AD33F68D5E31947062592ED6171D87017EEF4005F2D08737C358A35D41B1079E9A3E3415F787EBCCA90322C93A9E54AAA4EFB5DDA7A905CAE84C03CC443D4E54FEF47F8AB262CF834C5B9F49D3F5D35266530A52DAD1AF7679B0B8E1D514F6FD6A8698B11C7DF7A96133B46B6B6D3406577334D3C1E21609DFF4B1E1FE624D08168EBC055B1D08BC430AA2B6EC235425DF1DC4D3496F7C2771347092941AC8794600D4696760C7AA111D16526D313F7B49218D4B5902FD173C0CB0364FB63EB5B409FDB63D33B434B015F553BAD76AE70463D4EECE479068F7EA43FF7BFEA1F03DB13B226375887B15DAA5F677549BA5D38B8134AE792460EEE55639B95B2B50B61659E33795483D41BE41B505CBC09CD0837A5316C1C88A67E623956FC8B06DD5DEF5F60A1BCDF53E37E43BEF4BB3EF9F6EEA05BFE4910AE7B66B5D3ECAD1EAAAD722027A0A930CB471B1597B07ADAED1FAC6774447176290ED0039F285C5C944E26D5031C6563B30B4B6E6307F419084CE7210E15A71467DC6C881B0D339E8F594AB748909D8618940334685EE944853667121398F616F29140A451C8299D53846B6DD4A4F0B6D003E2FFE04A0318AEE8DD3A56CD18A17444B0539425748F5ABFD35B0D606D17BE4750D0A9E0A95841F30EBD39B5CAE10EEE2CC896E0BE6870B494FCA3F1CCC20F99F97FF038ED0AE72B116D0D9A56C0AD9B9978DD06635D16CAB6EDFA714E22750492AD195ED7B75D0665FF2248BF21559E74411B7B22A535E338F8BA787C31DB40B3603B4222EF799BD5C9C18EC6D6B680BEF6605958489873B64820FF717DD65F030AF20590DD912D1262E9C80169C50C36F1C2BEABB21CD8CC428B5E74C887
+04558DFC61E6AD7FDFBD78C86C98FB6F5A4A589DC09F66FC5EBF6377173EB8554DF6CE8BBCC03D016A2091C55A6611571033EB8CE0189B2241608C6E76A93930DC5543DF471D1C669D1BABF277BBC019CA6FBD025323A575892DF792232850BE3FB82A5D610FED475B61168C7FD2B6A1BE8B29287E4BE0465C08AD751B151212D3C36266B361904046AEB7DEB32C34D16DDC7FE3F1ADFBA5454DD09ACFDA5130ECAA84377F5EAFEBFC9BF6E33FB87F9788705AFDDE7E2CDA94B7BA5BFB4ABF300EFDED7592303BCA0E3390733FCB588FB26E093B1BC00B060B9A0A1946479334E26DECC79AEC61781392DAA58FEA6524FDB6E004AEB567E945DEA1324574A2C3D76E8F3359FDD3B3515ABE008DA0D0B68BE196AFD71F64D661B4096E407B8B055D8FBADDB458418FECEEF61E924DB712648E023789A3F6C4E992EF7E5B1FAAF7409CBE2D8D263F9A2ECE4E63B80B67E4215DC8555A65EC6B5D4A61D561C64592990935E9D22F5A45A86B45DD9D053FA89618733EB6AE39146BB603FF8024AE70764579F30807B615AB6C8B19BD36C3933F49958C053897C39B41DE248A64F13626ADBBC9D7425DB70B6ADD3390E61C5214E8FB0501958E6D7DF7774785040245B7C4BEA82A1D80E6851C620CF7D1776D4624E8CAF5207F485DCC1E86DECCFC05C6A4658CADDD9294F062952AD14048177E993891A83BF275BB9E2118F6A88A8B0CAD6E302E33AA7BBE47D4D016867641083D045A074DE1405DAA83FE6BCA1ADB5A427B637CD80FD4A24C076633C3B70C6CF09142874A1E21B737603F6C1D62AE82E4383E0600074C0B01FA5FA9340FF9E52F65325288B15DA8DEC9F295B71DE7DBB7EB06CE9553BDD3F459A3F814D26D31AF7BFC28BCC2825746E6BC83A4074E2C1BAA6D3A69C5E8115108A3FADDBF3BFAA346D16C9F96C2328EC775C762E4258CA0FCE19DC11980A6617F202AF6107F47219CAB65291573CAD815442203C41022825152F27D19883DD5E9C311E86E12FB867B1C4E0E6CD8B64399C1014BAE174E2EF896D4B85A7B2614B7D29D25173F537B2A56008FDEDC08CB3CC8E58151A948646BF3C90D0DECF8A9CCFB83F4600CFA3A85B749D98D4B6EA64A14D2CD8D5FD4605E1773FF022F03D3BE93B51982FE594932987E3825A277FF9A382D0EB4C9D06604C3F1BF5B49B74E6E980261952F99A56FF2B7D9885E4B5BD9505315FB49CEE56045F249FFF3EA81B901B8BB7354CDD85C13D6050A51E5A525472CA7F06E9DAE551C773B26C249B2CBF569411C5339109AC9DD8915A1D74E2C6DD8FB4CF836B907029673AFF11FDCB4163EBC9AE366BAA9E9E5187ED0D848796DC06F028FD7B3F1817F48AD28B88902A57C07E2E307FCD596EEFFF2B1F6FAAD87998D862C1CDA2EC2590B5651180B99DCA3C250E831091971CBA40F5E3A1C785AE98FB023
+022320C6B1EAB65786B806017830D3BB08A621BC10680537ADE73CC7F0CCE07ADD9CEE79DF728044FDFE01BF0886053DFD3EE16E63F7A22543A9F44C614BE13C4A3333414FBBA9A0ED5E64F3CE390943DC4C58C9E0AB6C6D4BB64D11E0791185B465D27B0FE32A4A5E0B72A40E7FC0CC56FF743D5A55BE92F47722A53A0401BBA042F1CDD3463B7A65F560FD006E41CDEDE39D19F1793E57D6F87C7CB76A9DC9C90DDB84E084B123815B1AA5E34016A2285BEF4AF6458D00F601FEDD7DA99E3BB709E9CC7420445E55DD44563CAED4A4CF00C46CBC572D604F4A8B529AE82728EF6292919A6B1E2906D14CDC9A2ED93CC8191CD711ADCBAC6011DD038A44D80D51943243A4D6C693834130DBB831580F168B4A542DE0BD763536537F18A3461C0636CB7C97F880574202495DC6A231AC12ADAA8F91DF694409472BDCDCA9E49CB5E165B6DCB5831DC13819BA0A5060359D75F22298542BBB8CDB46967B61E260E2E9922F15A90DE68DD4188D54167B444FCA6C31821D101F7F101114163631BC6D39F591EC0D830C9A11CAE895D2002128F22F9A0A283895F281ED4971C664C43D08E4940734809465A9DE65813207ED7E837B31282B7D476372499CDDA40028D14173E346F1EF55795677E65072D57A0B627FBBFB1341BA2F29ECF5848CFAC95479D7AF033E06EBA2F38B131A2E99F73CBEF6CC79AD0856D5E03A9634C96E376658DE3C34C0D9236AE4DF1DA6961633417EDA13458754E389C14EE5F25BE481FCAED72B2B9E7F5BEE8A9D5CBB2002C43D4BCA375DF8C3E3CF67DC7FC36AB90A2A6A868EC3E1C7FD7B2EF08D1691A0A46FCB4E8B7EB9857D6FC8D409014C942B1F728F1039DF59032197D7BF250962A10D359BE468C9BB29F3ACC6B31EF4F2F9A21D8C811E97A840C7A89EE340F45F1F522FCCB3B0AC0E1DF2CD1016AF06184350B7464839B0CDC6574DBE9E1C568BEFA45DB9F3B4F1ADBA15AC279EAF9446F937B450570688C15E4DC65000F7852270FC08FFC054F1EE3B7779008BB076752B4A9D20A2D4A66D2EE0FF0A1F24771B2DE18302782564A2AA06D693B40AEBAB807E2FF7145B5DD387028A9FE3A8C23C93DE3EA00C39F5F5141E946B4FFE17278A86A2A7BF720E1D03678371FFB96640AD3865B1270DB07A379535D5F281F30680136910474CC06708B4BFD01D19C30B24DA1363B97A397A01FCA067BD3B80F9197A52F72AE11A55FD81E6A606579E4EEC036C13707B1C6AEB4C6949E7A511CD32343B83697C3765B9BB82CFD17F6E54A84DE475A49AA13BE03BF63695138AC258BEDDC6708961CE1E1319532849C2337BEB3D566A79C6B749EDCD0E8200B0A64C9FE0A3E3C43D2550E87CC23BAFBE29013B30F61EA1430D6906792828AEB2EC708AE00772996118E587E800BA4D6F808CDE6167082C032DE770C94EEEC8E9717A
+4ED54A7A0CCE7DAF5AACBD18E85629C74B5930828CA71921C02C688920698E8705D4AC0E5406BF0C725DCD2FAA3EB2C90F73D9DE98122109FD590D729E735BF3D12702EDA0805ED153BB3EC37AF388380366A2BB809D21FA1BF50CF91D326A042EAA799E573A54804F4BEE422082973813387709EF81382156FFA9AE376BFF2FEC6EA7F428A39D1059BC13788E52219D43B55C0C0EE3D7D250AD398C787FB257C5FBBA995C583EEEEDC038C99F99158DC4D34EBDEC9789840A3EAA73225514FF9AC5ED40504974F9031E014B9DE251B070601B3386EEA1B36E6B082438A70B5C383651DE61F82D4B056B376EC4C32FE62F207D42155BD8D953AA5ACBCFD16B8E6A4B00A1506B94DB84506666EFC8E58A74598F0C603287FD12A8AA08DBA6CCB578DB35F295508E56948666344673BCE4A09B0369239E10FD3968F9E964E65A24C4C0A194553C74E95EF89FB96DDFB9FA03510CED4A90B7EDCDFE5469B2E45721826BB295C4D42107184135BE0B8E1BAFB0F1F4A571032D82A349A3DB59B5F1DB57728E9024701AA36890CCE35F2C719ADC3FD473BF9D4EC78DEA4ED92DD784E25DF0ED6A218B9D2994D5D5DE7632384D07E28DA97CB1F385D5E8E4B40277FD2C88A46CE2AA9A5B5E33DC69D614DE70F10877750E0584967E0C75F02C01A1D35F1636677D3374F7F804674037E1B36C4ACFED0D7965CDC66018C9DDBA7A54FAA162815C606E58AC2E77A5ABC9E08A30D2A02698FBA361A090A9E4959894E35282BBE7D33B1DE8AD86521EC5F5F7830238DC13CD8B276282EE473714DADBD1A3EDA00349DF3D4157B6BC306506650B2C4A68A7BA05474D214822CD4C070E7E672A92464CD6A17E2EE4A6736C590141A917826A2E3115D89585611844A3558B7BC5AF686FA88154FA3E6CF46CE1B34A2D938327B4702107898DBB0960659B937BFE1478847092CD97BB280CB0DF521690760607051BD02AD7A0CBE342A19506E44F38FA1F95839FC8B2D4A6C65C051AEE6B317CE8A06139FA6931640568B6ED5849ADDE148AB7F8DE7F16A4A8AF66CEC7BC737838CADB319F257820E44E8F67A31FDBAADE4EC5F67B3B9611C2D414B6EC593125952B148E2680A9954E2BDB637EC9E166F7553DE5FBA975FB43DB1C049D4D52003134B03939F0FF06DEEBEBBABF4C45E9F46B9148238A8449BCEAA3AC1D949320E4BA6A3E939D58901FE66C4AB1D7FA811E8046D528B11180C8B3C28DA54A236D8436DF62432529658A00AB0AC67FF66F4E1DBE85461058C93132BE5756FCDFE84908120195CF91A32993EEECB5EF06D8C6FB6CAB3A544440C0543EB6FC743A19D6B9E2696F7D1BE1FE4AD4D2D8F60DDF115D600D2381455EE8D5422F2E4719D8FD7A352F59806D27BFB913AB99D7C6BDEC85009D4F5837437927524B1768A6E0602291672970EA6E6BBE9516F2AB
+CB5739CDB9E80C34C65A856584099DC911BCF767103F1FE25BA92179A21C642803A5B576BAB2A4BFFA3B23B6A000F6E0FE075D0501CE59158F6B7B7B67A58DE4C3F0330144C51EF78E1B6BC31558D0430F9AF38E472065CAC52BF78EC6288A3D3509323CB706C787B8C07B0E2181E3E00C698DEB14389EA171B2E6C987168A2E5FB9E62116F5679CEC580BB7CACD439615558B6E136C13C0DCAEC501DE2334DF7D24284186210704D212B68FCCC5AD67BA69C118AB9268BFE7F925A63F9831C8323BF091EAEAC5F3031CEE7D50809F8E100FBDC7151C0B0C489367832C62978C591AF6246F1CC84712A35D1E758B2132F20205B8A9D59AB19A89445D655BE30DB3AFCFA719DB22EDDF3AFCD35D1A832839C7BD604E5550D41038E3B25DA69168B06F61A5D6DECD33A3292D28D55DE8A4D29E2E72FF4EF1924FC60601603A322A196CAF63C5ABCCADBD0D11172FE99C12821DB7B8102A428F856E73C41CCF35353A47F9495F43A36EBA6D05060628EB16636D089ECBC8BE1D6DDA85204F9BAE070D90BD2F577D79C06FA2352A3070D0B5AE34A28EDBCA11DF50B4DBBC311A98C0C8DC8066188F9F49A5CC356AD773F5BA12FD217D90D2EEBE574EDF908F5C8C129A8E8231E183803DCCBFD41ADA66B6031D840A72EE82D5166DABE13C815D23B22FAA8B13FC5F5897CC2BD8663254E37A28422CAF56FCDD5206204BC3A35063FB463D99FF74CFCC6A0306A9AB188E2670AD05635C4187911FF643DCD3AB6BF62EF998E824A096A646F0F0D2C9DD5C3BE1D9E23AEFB32FD93DAB404582CF7ABA0EFCD6B024E1F1C6F035CC2E66CCF4FCE4795F27E975F0EC62E87FD0DB624721A3B73EB311AAEEF7AD15B91095F12B402893C6BE6EBEFDD90D04B3CAACCA57D0FC6A00F61A012448D8B2FF375F03A961C0576AF881109580EF50C933BEA1154F5E4736E28AB9399743D338AA7F52B95D0B793C06EEFA7A300CF17BE824F3E5C05F74B4B2883600F36A1B39D8EDAC58B0348BC50B2B83DFA0CF61EAACB25A6416EE7E574BEE993E72D5CA5F8B9DF131AF024423F538F3C8F1CB288E180B62E550BBD08C368FBC48347A7A13EF1570E0F002E3BD689423313B62849CE43F5730B8C2EBF80A016F484C424B1378DEACDF43528FE23CF2C4403531B21030297C0B802648EBA02325F239183D3D1CA310EFDE7969BAE5F8DFF3F9448B41A3E450DCC546A171A769BCD58241FEE67E10773D421B260C1DDF9DE295DBE2E9D4620D86A0F494FF7F659BCEB8BB8F3C6384A3B93218474C2194C184226F94BA77763BB2AD4BBE92A5E1F159B5671040EBEAA54ADC2D05E58E4EB030AC04482D26C5079D0DCBD4D281719597A25E0FD2A18073096AC9C63AE63BFD3A4609ABAC20F0B4EDF15A9667AF8FEB1F457DAC8F3843EDDE729A79AB77DAB7DA71D8ABD3D45A2EEF8867
+3122B6B6B2C50B250248251A8BE1D78D8E2D9EC54933ED0B696B8B4F367441B4E62C24E22309F778219143DFBF0D01DEA55F3C64DC7B54FE523B853708A33AD308A3BE9497ECC5DA6C5119D3EEF54307F352BB6F9E8EB6C7A7B1FCBCC4098948457AD05D453AA08226E29765241AEDB4BBB7655A77D6EF732FEA9DA42A6DC3914DEE09CFC0152FE91600048D96240C301633F520A27DFBB413A97DD75383ECE541A4D3123468B77B2A8C08E0A51951D04E84CA4C899BB486F46CF97A32B9C607A08453C95AAE765337FDA72D7B14A02D32F2F5296C63E04D324EF2839D38A8952BF76D65340ED94166DA2656F1025264205A40EB61FCF91D54B0843509AB0BD793A86DD1FFFA844C13845A9187D2AD74799DC7A529A3054012CBB7B14957258C4A2AAB534A1DB1ABFCA2C2B5580D4B441171CFBBCEB2AFF8762AD83E8638444376F18EA8A12CC4789A82CD2F3F33A1A981F8F7EA9FFCCBC91A53E01195B28555AAB103E5A645D15F056C748570D43DE2ABEAABC09ED2E690BE6168130FDBD8CF81A9CAC694E717B42EDED9D2DAE8BD045C6178BC20A3D7C10A034D75D40A602D865E684CFDA7EC0C2E29D99538474836DF3C93B2247C617190463D51406530AFCB41FA19A5BBA23DA7C1AADE7165DB68CF386E1B70CA27A0115596ECE67F598DCC9CA46E98751325CBC6DD4A9A4B8159BB1214DB1F3101AB096D082ECAFBEAAD1D0D707652EE6C24D97FA8F95343EB0760E257B0C9241C14A1218910717FE2598D932928C168AA2EDA1010DEAA29EFD13E1758B812F484C574BA69EE334C9F73845F6462798AE05B6789A410EC331326936B6840813D4338CE5EE75953DF2A42285D5CB9BC227A22EA835EA9F53671ED65DE7259ABA7D4672F3E1B76A744BAD6DE00ACF7ECE3B80679FA8CFF48B79828465D308982D993946AAAF6B54330916331DAAFD3415A5B2C7292B0B76C59BA858BCB3746722BB2BC03D4F0F145651565DF4A4BA54975977F3737E9D386E2C9BE6A324F0B73C8431449DD1C4240F4DFB27EC0346BC2A6C2DFD1D875B79AA90BDBFC26DFC06F774108C97B0F39A5881F04F85AE57AAF2E8B94F7FDFD1EA85B9425F9C29A40DF4D6BA551E4D0B6C24C10CB520CFEF4A77E464648C14D387D9BE1A19DC50E954C76301085AC6ED3CFC997A35E9888CE47B7698A3D50E03C1A45600416E909B37359CC7FF5056E28DAD48571106F8948FDF64B9D81EB32E96247029D44F550BF063F5EF9C14F7BAF1EEAEE7A43671BBA6687566018852AFF3736FC4BE4097911ACC384998DF630EBE7FCBCF4BA660DE869E4AE235D811D1ADA016B4BA749DE0E365C65F6300E8651EEEEE3BCD0BB7F9FA9D4D2240D46720C6C1ACC2D74C9909D36DE25F915FEC1BCCA3585BCF64EF71070AB14C093F2687AA7413AA0BB04BB0A062D29D1B803994F7555715A
+1599A5030F9CB45C5C6E619D1E322BBAACF3934B70BE7194D77FC2737CBD1B124C8DE8015BDBDDD1274949215FEC058A4422EA63C363C0B50BBC5EE4452898FDB975F5E31E1F688628F07B027BAD8C2B3C04A37A56F2C44FC929BAC436F8BC641F5B026E8401F043BDF5DC9642DD8FEA302B02698369F818CB3879BEC8244D55BDE7D54D85B5A5828B232BF27834A228FEDCB08B3AC0BB82F705417EE5BB06E858C80EDA07AFFC0E026EF458452912C3FF6649E78F4B1CB955A1969A5E6E93407AF6066771DB0A576E54B01AAAC03EA88D63E2D7B8A4898076A881B35B9115FF134E5518BDE6B8709C7067FC57ED06E008DE099CEF67E38FE623C271EC5D0336D5A90239482F84133EFC0D1A124E65A0CC9CB02E760A3C216C92B1B3B6A87238E5C946A34487B07F01DA2D02CEB8540ADC97659E72DB0EEF1D130D209DD5323AB6F840A18780C18A612E38A4D718A021F4FA56C54A52F6B8CF33FC1ED1CBA359856E24931C790E5671A46D352CDE4715E865D2A0250ED285DC481F2E2CE091D048EBCFE9353EACAFC24C10964B73CB5954AEE02B47665ADCCBFA8DAB6818948592FE901E8E7B68482DE77F730A73A8E02FBB174226E57A8C6633CC21BC27073E37CF7DDD903EAF80B75B116A8E7884AB8521E09F36F8C6671AEB91DA12C1D101966F46EE78EB72F769BD6C471B68DA9CD463AC7FB64DB9367893456EFABB4698F8C29FB21813808B48D30793F73B86A077D4E9D9A5A5204354AA00406230BE63DA1A7B60C1457DD98CDD50A7EDCA8144524FCE7986129299CB0C1B001318B1BCC4F91253718AF2C1152D78FCB2CC51C79EF4692AF5DE8442973E79AB58E1CE98495FC6871A9B33487A6F02896E66292C5C062A1877C3D44CC56DFEF859BB49807561FA785FA03461D90EBB0B314EB837B0D3B23EEF6B4B402A76B0621B0948F65E3F02CEB21382124CF37D715E564532F838D79D4317C0BD4A6C701DB04FB93881A56037866EDAB89735F78ED476A06563DD12FBD58B8703A38F302814479A76CE698640D8C9F4FA2DCF6B98ED509A8E0FD687A852A329E1E0546FFB224D6567B3438668C254DF9A9FEB1F50C96A17B89D10321DC6A4B4EAFE80E771BE300D4F867E0A8596302336EF81B408402A8544FFC961CEBA4970C6709D459745F4020146E10A1918935D8418E10E028BEB06D9D851C45D70B063AB58A753AA82B63613C57EE636AF432E6DF4696061BD2E26D3FDB2CA4370B556FE8A5FE2B576DC859C6D5C82E43D10AC580AF8C252FEBE2CCB5131B0DA5BC390C05432AE55A40B15FC3BF663075DCF61DAE62A41506014D74260D9E9E2CD7D9B96E8D13E3DA7BE60BBAFBF355F143CE0D0250C7BAF157B8EDAA4A33D0F906B9038BB6E38A8A3C890619F299BAF96F46412983CDBA3B37C293AEDDF3BC1214D7706AE58ED83F5CC2D49
+03BB5D67A164EFE97232AEAF9A03BDBAD32A8CFBCC444C3471178A73234001F72691A175F959B04BBCF28DA41FB232E9E0E6F8B8BAE3FB59340BB5A7F16B2CD9B02D6430FFCF316441162EBAFC2142108FE62331903DC275EAC50C91C81B1B7533CFABBF3C11CF6A951BEE839F9758E7FFF750D6DA9651824EE7E743D5FB14020FD353D5E472C6F8B002642FD0CBD2483744826766C41DD72D8489C224CE60EF91AE7FAF6D4083DCE1ED99904458483BC815366F87D72156888BAE5561CCDD0533A060B0F548AABB78120A7BA4716A24A5EB6C002BF64F205FF0BD9CDAA420094F259CEF0309A3EBBAAA560EC53B5BB77B38628AFC56134E0457240595E811C5352B7688BDF90827BB5DC8E1D48660F2DFFBA1134096AB6A81C568CDE6F9F8315ADCA279E3237CFE5440E94CEA54F560DF0C92C01530CC256CB6DA93D4450659006861214596B623C01F6ADC8DE5D42480399CA58A297F720E3C06E5DC692C678406E52BF395D267D4808EF782D0A13C65B42C1B5EF2657FD2CD0CD69F831BC6F8A139E078F03E553B6494295FED140B74734EF11DAABBE1B16CE10DF78E9B02D0B013BF4980EC8EFE7DE8A1FC6BC4E76690C1DCBFC4742F014D11ACD511DFDDAF0703C6737D0922B973A5C7B0E5781EAD4F3CFD102728A10E06A9137DB47FAABE4700579C3A1B3AE77161D61A013A966028557E078F6C8D12B798B2CD00EBF893A80FB6897275825B1BCB70CE313A0433197AF8E985A5627EEACE67DD9FE0C2CABDCD7B3140CD68950C9757BAED838547EC971CC3C261C4014ABA6115996BBB29F6190E7CFBD2DAC8CE15283FED03BEC69AD18018012232C92D448A3385287F6531D219F86B0D7D426CDD468F193C1A0063760E52303F23B8F6222F89D4A2B9CAFCCA3DBF45F118060C1FDCB053DD2E76895A8AF199D2EDE9E49C598A940B24FE9FEE26742FA5000BDFDCFBEE657887161B1AE25C7B99B2B7F3BA8E9837DBB4FF82C34717C4CD81E27D54BB0BBCAE022B7A78F329782C5A52250E1C40C4BDBF8A1C20AF7A23899FC3DC5F25E7BF49EF2A71F4044821BA9924F7492883F4654D24BC1112BF8342C183BB800BF4745192EC78E1E1C07B425C1A0F4764D93CFF4151BA4F442F86C63F3A08AC7ABC128D49C7914CD02BD7482B2B5CE81BC83DB7F29128DB0934BDA9F3375FE4BD1339F9642DA2D5D48EF378CA819A94DBC1E5C376CB4BBDC5D5CB17185E420CA4F3D28EBC55508E2FB6BE5BFCEEA68CDDC22C6AD8D7B091AB10748EC2CFC1AA8BB7E7B499535D01357991E5930C77B53BA9245F70EB10C38CE401F937B9992BED775F4E8688B33812E35DEC08C0E352377E69B6ECBACBA40F1DB285D1385555AF71D413250A12D36F6E8B236919225951E05D885018936428933E8F5D12C53ADF880C93B32F33452466DB9CC6318FAC89B398C89B
+AC46D89C20ECFA044878B6459E4F9580A21DB560921B6BBAA70D5D996F3084F7929122FDE407576D5AB3C99B7D02283BB7B0AE6EA9C79F09C4B555BACB6DDB179B1352BBF3D2A984D6B8101C409A5C4C0908BC122465A18D13F95215CF2898B5250AC15786AA9D969C795AB953F5CE0DA8B3E6E2E8205774604B01D1B3311ADB21F163DF773F90B9472BD6CEDCBEA2A843FB390DAA0922B80B4E382DE02C51077F7030914968393DEC1F44EC984FE1693954A70E9CAC0F3EDF3889D7B57AC140D4D46AF93D64F3DBE0E709FADB08D9871505AB5782A01B9CBF5B49A3A1FD53ABB055FF9C40A5DDABAE0A02A514868975474F60550880CBFD02918FE84F9DE1AFF7E45A5CC877F0CA079B0C6296E28699DD095EC31989B753D3A1E73E02C4B1E4399594CC29016001672DD69CC4ABE0A7C09F5DDBD86518C277EC0561FD19E3E024480F11C25EBD623D6B267226BD7261B6CE18285062593EC32F646EE6DF1E04B66A2E9995461EEA7432F3A0B0461E56F3AE0B8FD702D625A319CA3F35B0ADBD18B94CA00C78B8BC5B9846CADB0054B9E42C263F3FA92350C6549A2403F36408540070924724829442383CBC5431C7C123FAC3D74D259E7974784C43ABB0E158E7F277ACE72E3EBB4A4F011A8AA9876B6C2532B08520023F688E25BF589B4331835AA7568FFDC37D96D31215C924D0ACEBB7AC655748DD79854FD9AADCC43F266C5DF302CC3F234341AD61BBFF10B7E5B8EBD9171CDBBF9DB572122FA90D85BB5B5A33E8C70F3427DB54290769EC1D87B2149019A249AA263B417D0852D4349B0316F29CD4EA13DBA7BAFDD3D82809B50C2E1DFD95DEDA6C80D3ECBAD2A83A022686C289673AF8A7344A480FA65B4F07D33AF6B05C286A51FE6322581972FB466D5CC8642A3C7ECB248EB5100B5C32566CEEA32E67E812AD1076660B53E640DDCD26710AB1E2423A1C862CA1A4438FD6672EBDCC3735083DB896BE6B426F88D790815C144885CE17BFFB78E8A3ACAA3CDE992153F3E4A462DC65D00E7E41DDD6E6563B68005DE587BDB58554D1FBC18B4B1052B691429EB707EF482E032A5E206CCEE1D2EAC216823675D890B24E6AFB5E5E8B8F15FBBF0868FCF0AD9BF045A276278E85123361739901608176329BF193DE908CA6D1C3B63AC87A8A8E4C1976BC5B3487265987419C70C2692708DDDBBC02394E55DD1920835C2F2E3C5CE138EBD6D06BE06A8441D737EF99B3CE01F6D17F5FC2DB6047DDD1791049D25719EE1225F219172EC2AF008AD8CFEF1374F659C90DF1BA676F983D5A68A4CF0823A313A672089FB9F245F8D453ACB20340CF909A6E28BA2DB5EEE476D4506737D0000016857B07041F66624DD6245D2028C0AD50B618A10B83E64E28E2FE2A66466C42296EC10512A9AE57CE706B525640BE80D6C699024C5C4309D4D5C0D5368622
+A4E3E27D90E622F40DEC1E93D26D38360B4A96E610F504C39BC2CF7234651CD45D1ECCB73017BB2EA24D0180A579FF74C049A2B2C0D0222F89853011CB13A3540DD5F563713F145BA5E591F77317108D4BD4785C6B71F699833BC18A5E805B0DAEE7C134061BF851A22CB5C5D259C939891E514E80F2CDE05506A6E0D8BD47F638451B2B328CDB3C8DC2A366B1ECD8E9AEC24ED928BBDCF457E48EDAC70C452F8E06573D20B793914944E850CF5F6F0CDBB978B8E56CB3A40329B9BA4D39FC3DBCAB07C04E9DBC167AA76338D96614BAC80F0F7EB7EB715BD063E9ADC012B570F8DC71B8B27623BED08F9810D025A2CCF490D1AB375DEC7416A599D2753733387041380298F11FB8168A9F360948208C2450C8652F04080BDD2C9B31E7503909F9A4B47446112CDD57ACA04BE38DDE44076E8E3A89330E5CAC34102CED96AE5123E1185F3C11FD358F6DCADD33FDF8353689FEB09243AC5FD4E634EC2561B63EFE495A363BFD5D3D66C5E383468D46AB82ABBF598F87E2C87F8541405B85F4296E9DE8FEA71E621CAF2F1A4E092E14E0BE5AB4FFED28655C29FD55258E565952C1049D5C571A96F4F6F21C11C31B0ADC8F4A97AC2C8207FC0A37FAC9FB910F598B7926EC1A66D956AEDBAE92423A7E785078366BFF3FDC61583839DF8713660397D3070CB70B63DE3A5B2A33F5A43B97269B6CDC8C957CAB94DAE8549A440B3DEA4EC9D2A534AF0F36B51E695C8096349A6A892572241F881278029DB864174CEFFBEDDA107B32D9DD61B3196C07DB388E1D175CCDDE245DE390B0A23F46BE170486346013A63946783612876A2D5B48587FEDF3F115B2FD2EF80B4D8C5DB047DC9851AE56B4D4D66EA6BFF0BDB953CBDAB3B8C249A2EB43673980D56616B164AD471F579E906A7DB26EBE22585E914692A98D63EC62AE259F95E30BD2D7CD5A2302D666FAC316456FCD76D3CBB6705DF030609CF4AA486CC870B0AEE9A9DD37F910DD5B7844BB70F08AAFE23E831CB128AEEE81760FB9CBA51DCCA362AB6F41EB92244B5DBE651D6A08411C5B8C9E4A7BDCC3AA08A70AFB097BB62C3E05294AFBC00597C242A71BD1FA91C6E0BBE1E49C061DE254CF496080C4895024C3DD2C97BA2CA3E722081B8C777B6D9FBE2176BC9F1A89D3EAE6C5127521713524848DBAD160BBCB7DFAAE74602C326AE39B871C0B2A8245577B62764E82C1A2584218B67FE1A1F8134F1333CA920FE0D1E23AE5994F0BB266A305BE91F81888C07013CB845A86A7C1158687B8D7B9F20938AE01D8215177C4662C3CF232E4324F6634F95427FD93F0471616FC0ED91C10A011BCDD35479902EDD61A9A6539161683C39C991771F57D4AF837D7088C9196F2B6EEEF49F3997ADB2D572492986E7317CE31D80888BCDEB2ADB6838914055FE30A564FD71148D9DD1724D375864F31D61C
+9666C4E99DD23414A4198C6CA8228F415C8EEDB5726BB076824D0ADC8F5BAE97119C6222D5D0251393BB66E90045D79C528EFF8195FD257007C40F07949366CCD169A912C191E06CBF28465EE502753EC1302685B2EB4AB805B14D372B660C6E24F1B0CC1DCA2B4BDBFC323DDD33678E4DD255ECD23F3CA10BC444ED623760FAEA09D3732381E159FD035CABC553C5D04DE30BF29661C9565695BBE481CDF64E4958997FFB9CA3FFC1A8CD660B89A76973CBB84A8237CE998DBB36291293902905F151D886240EBEA8F8B0B43EE8C081096B1525CC0C4E3DCFEB8BAD9429A59F061CCFFC63625B37B6CA9152DBAC110630E13D6001CF4E0BE0E925C2CE11829F413DD7C09A3D5C5C38F8209F4EE5DB758AA5BA054182FCB0E8171CB5C425D6BE2D8BBD8DBE1E49408FA1764CAC88EED1A85040BB564F87A8AFEBB8882AC7B8045255D046B885961CCD5AE1FAFED3B8C512FD32F001A5E3608226AEA5B15A0808142E8BBCAFD09FD40E453B45EADEBB2B8FFAA51745BB79D912551141E40EC33630ED4655DDC2384D6D1E1F95329CF01C4B291DEC6FCB8C47E5B50DE53AEA2B59802F7B60072B6E882E6FCA3DFD00D19E7F328A8901494EA367999510ECF7569AF8DAEB8524B748B8540BDAC6AD89B8B11A226D32DD4B05B4B1C4EE09FA64D62577AAC9380621EE21A89B547F41794A243213846A0969CCBBFCE6F81B054A47B4678AD68AEEDB297A09F69ECA7471D43254113A9E4C466762FEF5B1FEC8A7DAF2EC31A4DA7406B2D367DC4CE28284253D3F985617C3F11ABD7CC27EFDF654135923BA3AE1E11A952E23B07EE1A51631511AE3A1DE7E1A2D83E99A74046D8B1C49B3F0417D4D2979967C8172067E1152293DFB8408F10478366905FF50FDF90F1B1315E28D17E14692D8C00A60BC264C4EA1385FA8833924B4BD5DBFAB928B31289F4EA7E22AFDC4DBCD7375725D61F31C5F4DD99F019BA9A4DE8322213D9C287B2866673A2240B5BF4FFDFA8BDDD59C9E7B5CB2B5891CED2A32B65953D02E98E7E60B0D97F406BF68CDE0E9AD81DDF254473BAACFF0F1CFDBBE4228991D80CE87A2536568ACD8CE449C2A8C37C77B7C02686A94A1EC3A4DD95633F55F9CABA688A12E58C7DD8A91998CB32EED3604B09C9771F875DE247E7473F86C84F6E0FA8592D0321DC82F3E1D513257B3FCE1ABE8A659249CE9C9C70054D153AC77C8D1597A00BFBB66E2C23410ADE78E9C80CA182C56ECD1B31B76B7B7563E35177A3B18949F514616FB479E26FBDF9E1D5304092D8418C50AF506BE2CD4D9072B8ABF5D4B380F7AA967F2E88E51C10343D1D775958DF21AB16C1A36360B27EB31D612074ECAC4CC7BEE3C681632BCD29B76028DCF09B011C00D5D243F6EFD9C6600E37C0C298222E6273EB9342F4960D3FBC9252D8EB87B63186A2889FD4C6ACC68D803
+56479A06DE9EEB841C5E5C07950A3FCA3158F06AEA09B3C4711872EC9E0A6E67898BA3926C9B7057781AA23B0C7FFD094C51BE8B9D5962791541662933CCB7E8254D72B7127651B5C9790349D171B87B7BE28AB871A058176CDCE60E6DBE91F6A87A86071BCB3FC01CF934717D76BF7A17E4009C27C0098D80E56A97B68A52ED12CBE011C1272D4F0EAA673A2CEBD89EE1DD41047C30DC0E28CDFB8CF4991E06685604A4A9A664BF59220DF892E457AAA93CC8D061E3FF472460C0183BB10EF2AA9BDAA31D215B665F9FCCA1CA70CDB3E05953DA902BEE6FAA791627F4458937DDEBBD03B588AABD741D8FAA0CA4BA5F00B5BE83B18FC329C860671D1637808482F7965527F5A2FA1DE6C596FDAC31CA560A0A168A1BB79193D5934BA227AAF56C7BE21EFF25B2A733FDA9DFB2FC0549342338D0795BAB3F4B6D7F8A19AEEADB0AE08E3445E8D0DA423BE5C034637CFCA94799BE4A799E14EFA0060157CDF2F7A5E9CBCA401F548232BAD882985513984976D084E269DB946A039A5FA30C1E4E91CA376AEBC8D055FDCA84BA7A359C5DF124D8DFD877C81EB2697B32DF5EEDB1B375C189FD8AA9B3E335BD8E491DE72DC9FCC1212C967480D9232B2B7E52C1DD0500CE781FB7FFFF30F563EBC7C285D228605CC79D6E77D5365C5162F521B5563CCE7B0A3BD7DC4C43F4A3AD6D769A8AD411AB6C7D9A83F14336BAC73BBB032D42F3F9A9E3DFC64032C92F07625B40F4BB54C9ABEEE01870D49EB169EEDF889E5DD2197B91851E1EA47D996BA6B5273721E9D8D89CAD0942770D81838B3A7C819E45A34CAD0BBADBBE8D0E864FDC85E4C1CFD275757F7A936ED215BF09ED2DB74C519A6BDBF7764F9812A101091426DEABDD72C23B64DBC206D3CC5AFC4FC74C4529736A72540256A563B62822BFE930469597F670B196E4C97B28FAD2398D275CEB34CB96806DD3F2909D18F7692B7DE78EB9C105AF3882B7AD9B9CA7E70096BC259858968D9C95B02EFD0EB89D9278FB1216AB23DFDA7EFC17A91A4238EEF19F9396F2472CE53A07526670B2121A94A737026D685D8AE64E9E8A9E2F4412D93FFC9FFB5B7D071F14CF153CC62C22052E68AB5A2BBDDCCC425D14F183836D776B3C53A7352B64E7B15772D7D26680030DAF1295D1CD48E0AE498F71D22A82D46FEA51C0B76F4608401B78C62A21AE508CBAE1CC861B81594AF4EDF827E872505EFE237DC3FE58EFF5672C1C973BA35569AFF063E8CD3BA9AADBEA50B6EF9CECA5AE6626BA1AE7D1E2CFAEB4BDE3E937341C3487D299FC3976B2EA5D619709F3367421E288677404E0B7991AB1F14E0BF9895160029C2CE8FDD3FCB755B437287EAE5EA081008B87D2A8E79A16538AF7106933C7E9AB919E03836E8B4D55AAACE1C86E669C4947F74BF08792621E0F6F3B227320887E40D7B9C83CC18D8182E1
+2121DDEE4328D9202B61927CDADDB67522665D83422258E3DC067C64CD0F17C432E667E1F7CE90E8EDC705E9E1A781B27366462FE5774B790CDE303C14E57D1DC652C4687F1DC7F9DB37069153EBCEAC2B33F1AAE936A4237E19984AFF06493C80A3C18EAC7B8BFF5A660F43FF42F756D9C972B74944C37F75C46D530D3DB261B05F6AF3C9077F518878E63ED0F1FD0F1FD36AC84D0752C4AD831F19A235A5A778AE609724A28D4343510B80929E6CB0F7587E77C9CEEE3E313B072462AF321B2C0AC8FE7AE60B7595DDB1ED833B8706C031996F2E49A5F78D7FC2BD3B1CAEB3F5F4AF835B58CD89FDB95B02FBBEA1CA07B7AF11ADA651CA4F31ACB03166126217AEFEE4E83697E19A9F3B12305D4C68846C3D263538DD59AAE807CB3E105ED78D473DB45121A9FBF40718A6434188591A37EC1BF90A62EA48CF53D8EB48FEE483E0A69FCCFA51FDEC19515BDC80874A4501550912C0B4E3C0F3C9E231BAEAF4F16792B82754B34DD114141E497704AD58FAAA80A2F03836AC96297C932DA606A892FB54F9DFC3DF2361D35E59E43DBB751C9A95D3E46B126430241A41CABC5E23E7BBFAA670EDFA33DBD3A01BD7884BC8B09587CD96ED88EFA9D27B574240BAB32F96F6763A88E4A19977D5A1813A1BB2A7B30051F01DF2DBC82E420A9D3DAF44C01C9C2BE4C5F71D4FEC0084E73F26A06D6DB4E23EC90BE1C53C07F3C7E55506CDBD42C2166E94F83943807031C7CC534CB2E00D052A3C7ECB248EA9E709C62C9D89CB8A7FC4E77AE9E2B9D4584AB51A9790B05B04E9B10ABA861DC74B60D40EA093713486B3A3E184BA62E26BC8DBDE44B3DB2DF6A474BCFDA52086256E0197617C099C20F90105F4B7A3134670A5ADAAC6719B084C24338EE20D2666C76ACB13EBD869A90526805C5CE2717DD15BCA12AF98137F80FE73689DBF2D6134581A2806AFCABE0329A4456F8275417B58880BFEAE9E504A2F40DE23962AA86EF1F5D4C0F7D492D909D4AF3A1F7502A35D0DAAA5E195304A7E62ED9A95F81DB51F26AFBD5C68F51D7F01855BE6EC6A28E5572A8E773944226DED48B2AD3F22094098F828463C4BE431BD1E9A5158D2568EAADDD70A35FB0F4C45305D75432CA39878B34FAB6CE939DF35C7013A5F78821472DED3BA7935FA25E6F46D931E101FBF8B841A1D4FE7C0F18EE452BD5361A75C5B74ED087292F7BFA737CBB60403932CB74CE93D66A9EA52F477E2005350D8E29E345114A3C59BBFC0DE6CDD01719DD2667B46C201CD4AEDE2FAEFAABA3206D8D9F2FAAD6C61591FB99B6ADF477CBD8F8061360D2AF0D79D101C6DA2A98D4C7C28F13AAB2827C618EA6D9AA6C88472E68B87D59B1CE5862133B31F28287F5301D19448B4573ACB482BD417B16694CE5CC76A14A7BD00BCF07D19799339DBCB0A67FB8718FA2C004688AA741E6714C006
+E20AF02D00A6CA01D237D3986370E1E13A9DA8D6949F64C3E4040394CBC81E488D7379E3E292E9A1AFB37E347737253EF0D8FDA2EC19C6077F0404EB02E46919452A878AACD94B2D9599F1AA802E86F07D2CE70447D01AEA2E302081A8F31D230CD0B3A821FB4469F588752DE0188B1AB0AE61570FE006B671275815756BA85A68FBB2B717B002F238B12FB75123270094077F9AFF45FF3A216F2DF4024A0BA58BDE6945A4BC5B8989382019E9C379D8291E8E91B0B5C681519C3A909C74A9DE70A3FFD3246E02D212497BFE781EE884AEDE4AD4721FFBC8BB14C110795656B1D764D6C3562DF08F00CC730BFB0322D0FDE0C90A18474FB960B90C1CE11A71D8CAF47119B54F0FCC82F865B243B0EFAC82ADBFA89303BE072F3AA7834B903690C3D26EB65C23472FCFE93CF51957A5F19D52BDF7A0AECD0A421998877687AE6861F2084F4DABCA6F878411674BEF9866FD2462E34AC6D621B13A405CFAC4A317BD3B8340A722A21B6FC1F622567822145172717B2A8FE425D1537B473C019F9BF081DEA690DD84F7D78255106D2CB59BE606D1B8BE51A9DC2808F6EFAC87E143AE074708DA59B9F8C7978F5048788D1A84D94E77122093F3E3F57161F8C28A0A9EB65436664F67E40F78A184CF449495B3EB6F827760EA39DDA6466437287A2F70EC2FF403A4B86ED2FCD8D053C9203AC19C085AFD006447100144F679001EB224625C93047DD8D5EAE6B51D948631548398BF60F401217AF30D5A6F0DF4C6D5DD5A50E653EED95D0A21EDC3D93A7AE6DFD839AF28243076FDE2C032323BB32DF808AEF78A71604EB69F06D9C4DE0497897BF677B6094BEA6995C5E82675108315134D20352D507D479955B01739B4FF3945D3370B9836C5464439D7D95015F9C989187BF1F5B7FD93C7565BF7275D034F7268046C1F830A6FEFF59923BF97882B0C5913BCC4CD2D84342E4C8CE027650023474C88E2108974FEF944C5E491937BE3D904F1495FF4AF170E044ABD506BCB5DACD0154C5E507EED5FCB163899F1A89B426DE3F4C5B68C7CA592F408F9E6D70A7157F69BF531D22AB0598992D56F1C7D5B826ABD1B5D45FE2B0E2D5CFB1D7584681D83449652112C5C68838E0E90E48833A19811B6DBAF9DC4D2213080F825797EA7676D4B6A1066F93158809F03E4E2F4E058A77666CB76928A847AD3FD1EED2C8F88D9191E20404A8CBDF20D60D028A7C901A79ABC1E402AFA6164825D286C242774439E14FED48E8505A6C7409154424321050DD1A14F24F761053882530FDB282DED37E7119FD69EB5BA5923F6CDAB2DBDEB1B8D994944573085CBAAD1A715FC69E343C78D077EC5A530228692373378096F31A4E44F6BA4EC596C005E6D2D74935A3C2CCFF57EB7EEB2945F91A25BFBB57FF04E7112167DF22CE3C9F0C3AD0BB976FE62EBAB720A1958C700
+89901B8A21CD122BC4BCA961DFE5BB2EA565F63DDD962E667C9996BD153DC60ED461FFE6CC8B96F6A9F616D05A0A52BFFA631F61B543F50B10EA52683A3B2A493EE16A594EECA81B61A78556543FCACE82FED3E28EE73D805028ACBDB8B6A4E0C0EB9EC83D64A631A01990AB773B7CEFEA19B67E65FB6E1A559387D9A7246169E956B26EB4C476DD7F129E015E0D756E1FAE645A2BD66489136C10B37A6B6CE471D9C6A995E3BC19E3CD7DA6C02CADDD92E1688D10761D442A254691E9F99EA6393FD9E57BFDCC0435F05CCDFE545EB648DF4B77F31E2790C5A8666A18D1A9C0D883301F884D7031CDC3364485DFEFEC0B4398B3B82547A8E871F2D05FD65D6F51534FF74B61F09CD7B46D12FACBE73EDEAF330818938BE4CAD46DFFBA78B5B68CEC5104019D522EDEC57D6E20C8E83990E3C4360AF5DA2E404A2CC272887F97DAC06B00B9C7E64226675FB8C388534B90B8F1098CE32BA170064CE094E806751EE586477DADF8105907D12FE52B1FC0D033B3344B5092458A9F676897B03A559085D7947609C512AD721F1E4856162D1BDE3BC4800053E4B4DD6DE27127FB5F601DCBAF44E85AE25C80EDC5424BD649D18DB42E41C232AD5B43113580D3DE72CFAC3694E53C8FFB6A1AEB07CCB90821E6C7F0A3475C21DB39EAD517769F62E2F8102DCA2ED9A961052876D5562855E03B18315F206BF624DE253385B5608F8FE79F358EFE2A3ABA44A1F84AB15F935906D735E31CE03F614FAEA00634635BEF42E09F102B5107109A3D3F45705371DCED70577A21CFE3F476EF696DA56311B577281E7AF2DF65E806CDBB528D5262BCE26BAABA2BB79203CF3801CC65A89487629080FF989602B48FCF0CF3D55DC5D5540CED823142B7A6B631F6132497B6D81FF38860BC77303E2997171599575A8DA202E6C8CCAE50B533EC1CD41A3155BE5406F7CAE0039A1B1E50A14B25B2E27C869C61599B45E18E748A5E161ECFDF736B6068F2DBDC53065D0AD621BCA9E12B191A8C22902452BA9D2000434034EE313B7023FFB9754C4EC120D295C7C551BB6D297DB399BA5F8E3F57376A926AFE9D64AE9FCEED70F2EDA813995A71BBB67F46A83203F77BD91975FC8E08B83980AC5E2E8763B09AFED88C9AE702D9EBEC29F4461E88503C6ACE5B20E86DDC76DB8FDE5FAD0BDED95FF56216F129C97F8425665E67FFEA544C6A6AA2053C11EAE4C9481919E67A1D286BDDBCD0663F769960E30F6D2C38A4627C5C0CD434B4C59375CAB03877F1680B8902F2946987813D6AADF7D06A712DDAF0F3B815A526373E68D2133FBD4B3D0215633AB8E5D0DE7AC62B9C07DBA0C3618618170D69BDCB6905DE778516C4F2D9B18074E7D8819378E4FA85EB838A97C7DF2EA44D37B1A463F3F2B4560685A400DD1ED153A6E28B48A057199F070BB60053DD29CA1D2CAD1244
+7415B7DAA440DAA31AB0097EFCA1459CA0BC37F8C1FAA8670BF0C2A8EE9C48367B924757B8E3E7DEE4F688C3859A7EC26E4946FD7066D2AF3F5513C91647641008B0C77DAB1BF16BD5BCB0E8056231D6EE627147BFD18CFC8EDE6358B4D391B4E014CFACEFEFA504EF02E2D637BC06F44887F58F032F4CED2223D173DDA7A8C54B2EC8D6B7A7271C75B31FF1099FDD73EBCD3E9D6570C97EDD04FCAB69DB2469790F42DDA606830AF685CD34D01776FC0DCEA6C30C03F5D52331BEE55859E0FFF2B3AB03A37B186CA614DDE173C30355A3C0C37B602A4C8B6794BF9CA8B08FE56D7F20FCEB3984DF3DC498072E1538DF034CB874A56575C6B6D07F22E6BB7A4F4B8C1E970E068B02EE623540E2E75D8E212CE83B0F6953EAD22AB54964E0AEB1E861FDEE65B55D967BFBF3F4A76D8EC7983F3063D8F2531811DC05328E20D51BDF6385A88B4F8097D18BB0CEDE841AD87C3352927A0510FE29CE1534AB71336C65AD670F7053957F26BC3211D88C23A3AB258D95B959D159CD3E34F9562CC6B837DBE59FD1E4E95CD908BCD4DEC59098C584CB749ED369D51145049995CE0F71A2A3BCD48E5E0C73B07788AC4B860FA349A472B5E2AAEE236E449797918DFFB25F16BECF68FD8C6AEC9F24DC7324534E4046CAC6D1ECEE8D1EDE997EEA9E334B204DEE93BB99CD197CE00B4D991E139F7A6DAE750216D48AAEB5D65D708528D633335929F6FC1B9E3D45F711023904E3A35C44B4FF013C7E3CE063E69B9015ED208C4707A5CC329385E5C73756ED72C35F9DD51DF8C7237DA127EB3DBD4EA31A26140BCBD90294BCDB633AB39A6D0BC78257786BD0FE9E398F7F0D424AD2DF45C1B84DDA85D4A252D3638C9591D57D250868C2F3466741400B4456B4012C57FC41E3E61A316674932A593F135CB1745A7CD5A81ED4C54EA84A46BB915446324038808006226AB4E45E1580FBF5356002FB334F61ED5ACE31EAC9C5884771685B0ECD3E0282F65E3379A270991961069D82695CC81C824ABCCACA3C65662C85738893770CBF3FF378AC4CD0A6487CBB10BCBB5E9E30C43C25BB00AFBDF0FD6F5D3B742BAA78B1446615C6E41F3CDFCD1290D994C6E805BF4ACEF2C0EE238FE816FDC6060049D28D7E5439E6AFBB1B6409E180ED61345F6B02128427400849C2C70D323C2ED47CB8E24AE29641B445BD3F062170CE13A8DF8B58C6CBBA7C05B7A42EA5BD49FFABDE13E5824D932412AA3F0FD680B2A3279F9F9EA4484C7191D4E3B98F55AD46419C42ECD9DC832F9BC7548211805823978F89BF97030217914C9DE19E7F289D3C8D10A8159C834BC957BB0A12448522D770C5773FB3256411B215D7BF48A73AF76C19B3F8083FCA4ADCFA14AFAD454890DD7F985726B41E12ECC2898772F5714B8526B759AE22355D1C93409FB31DEFB1F249990B847439F2BC3E
+A400C97DF2C55C4D8E9C3C150F8D9403C3A52BACE6B9D847A13CB2F0B28082F30AE42E2E7629EE28EA5F647EAA73D43C5DE009617449ECC4D8D1BF449A461BC103099DCF4FBC4852B8CF19B27AE964D0DC4F3888FCCB7CB03FDDAEC26D2DEDF633C1C3BFE8E9189D14BB57C3B32BFC08CCF2FCA577FB362A08C3E5CED58C6687DDF4437F9A96C7C78AFA7AA75EDA544D27D159998178213E0D1BA6A9C8F09C78FB32C344FA3CF8C81FD8AA8B43EC8E7CD80E40808CD24587A12B1C35A1B77E5B07CDA954A03A73986C6A37FBB76F104AB642294FFBECB798F4D885CE9635180B7F38526E21C65A1A92C8DE320170C30FFEE4271B0ADD3D0BECD58FAFF58E74FF1E2BA93489AB002DC26F6224F4E9ED449A8BEC0F2EF34659FB041771687BA40EDA550023B21257952F7731A3C5D623EBC22D560764CF82B7502F1F166235AAE75976D475B6493CBE90F6254ACF6163CB57775B103D3E022784E22076EFE86C6B1C9FDB1E90CC9DF148F6BA3007C0EFF848AE972A24D4AE9C3E3CC60B42A9B080E5928D9CBCF423361C6C48190445BEA0183FEC1DD59A1A6A21E513422420B5C5D8B317677A1B3B2FD6C5817308F50AE0BE857250D6370CB1E4509C086A84814FE0C43FC6C6C218A77A2C6837C30980B25415EE05E9479068D9EDF1D30CC2F371E1569F08FAF6394E1D09F4EEA4E8AC34732FE902C1F7951D368D596F0037F71AA9D52F6FA8E2273019C75E9D3FB7053172E55E5ACA61212F3ED33520ACEFE10AD198B7D03F4C1D13F20187C814BA6AAA18355EDAEF3F8FFB0224AED5E2D9CB8F531B2F31C559CFD79FF3115E1D2B98BD978E44DE78ACB74AF5353944E923E6AB62BF44C4F4A70873BA1AFEB67A52A0F1C0546DD122E9932277460D12C5300016583AEA17211C024D69281DEBCE4A9A3864EF632B94127F03659EDDF860C546EA0662AADCE2BF0971E68CC63AC099E7094F93534EA5F4B0513DE049826C4FAD22E034F68DE004A0E64CEEFC075677C67D68258CCCC7E79E3BA369F01328A1826D7374A3E78BDAF92DC70B472F292E67C3DC7BDC27E6030B6225F7CE5962B3E59C5939AF5EEF57789E50893C6B44EDDFDDB3874138AFEB6859150659BC653037ED4B2389E857835BF36B397F79304BFF20D9917469EE5062B9F7EC754B13D0C380FD2084CD2D4C4D9E76A137A4B66049C3D0DD876BD9906B47A169AE8EBECDB38BD72CC78A5FCE9F1CECC8425282D34D6B843C8C93CB5948F4511C061FD26E126463F6BCCA805DF12D4144487C8C001F2CAE4C1C926069FDBC457FD053FD75F8FF664A5A2ED10935FC22B39CE154ACE7325E09C1693C1FC977F068952CC38E529D399F3A941EE26087FCAE92308C0B7224E65137C48C20730D455E632CFE08A189CB6F5F717CAE68BFB9994947EBB0F6E897439AC1035C60785FA898BF922C9322
+ED9CC6499BA81296ECE7E97C3AE604E16BAD0672CB1B30FCDFE52FF08D7AEAE76D15131631349424CAEE671EA658DA3A6C3EE4AA0D894FCB15A1CAF6EC649A0005C9A04C2CAB82EFBF92D2DDC3679FA78BF7288260C3C8B2A528968A587DA2F4B9DBAC62C811610D0B1AB8EC31F25643823BD7AB02204622AF141797CF6164AAAD414DA6178093CE3C5B0B3C1E0894800095D8B1C5EBBF9DBB2FB2E29594FF3072108B21437A5352B714189D5D48027D93724C16CD57FCDB42A2016CEC47C42FD00E23919DEC8FC4D4DB05E70FB55090F195568D09CBD731DE24CDB9ABBCF60631728A5811281D85901A65FBBB2A23F2050E42E4F444E7F7C6D6391B6410EA54392A93BF68759714B9696D1EC6AC8E08BF8AB2F9596AE46100698838A5F11288C3073D974CC5E44D8D501ACB568179863C622B6782CAB0606E81F4B368AABFEC7606C0235BE9E2896D1C503D877AC794EACF8306919F96AD8FCB91238A5F24FB3CAA0D2C2AD6CD67AA59DAD680BE72BC8610B106FD901FDA3DFFE2393ABF82111D213FE61641CF806FA1117BCE29C2B922AD215C39004E67985B04FDD028EEE8144FCEA6D9379E883919ED0A8F2D49AC7CF15C368D66DA463060C8BD36D6F315086F8931FF8286B952B63606166F52E5CA0E86E1FEC3B1347F61FAA507FFC64B057CF3F1F625714E13444961036B923413E3DAB31098F36334D8C63FFC037A69E347D14EF272C99F05D0F65F4B9CC818F222B89D9B4F332ACEE68281F1E2CD0D66EBF8295E93EB9E342B93A1A9A95D7608F3C680A42DF226EE7271200D598B2E43152E47628416F497C7C5ECFE0F10A1796F27E2CA8CAAA4AE6D40D4E879AEE42EE7940279DD1DF81CC11B4E330680A6331145DD70274FDA80F4E4924365F8EE386C46F794DAAED06C5738A1D4154192A960A42C25AC5DD9AA27E7E3B684135036F3F8506E88DBCF96492759473D3FFAEDD24F77D2A2D934EBAA29AFEF40920D0AE44C16B0D30FA05072C4DF7A85D35794D6B07794FAAD452CF9927238965A5FA7FB8C4AF46BD6C9AC796CB708D1BB73F1CDABACCE9F62C3572996DD318E267E57DA0D21ED5C4B6B274C7EFAF1A4EFB57566ABF16672BC37E07CE7E4CE8C6B6C93D767372CC7E5FF382FED9EB9C8BE5C855E52A4B17B03DB6E430FA69355EA991D05D3BA7D4AE0101FEF350A2704F41DB98E1B3A55731C7CCDA6C02B424718A14DF77804DB0E1B1A7C3E870949796E6497E252AA6192CE6CC97A44E2ADD57386507326BCAC706E80FD0D42353DCA444D47EDD811F97F8EB35A8F1D2E425D814A38EE60A06D3ABC58F44F1960C55B85C562A1335548CF0B0011A37DF4803B8CF4BF52DB054DC04DD934EA1E334B8C792DFFF4E7126F9914CFA0C7632C7A831F9899B1DAFB02957066D4189F38FB1CD5B32D3152E13525979B6504B0B457319B20
+64133C6A161199BA2C03F64A78A3B40B6545262981A06475508A1DED714C8F3F7CEACDDF8406838C4C4842A041BDA6AB9CE64E9F690362AAB804F97EFB46BECB368947F79A17C80CC06AF377EB706073E0FC9834D7B1817146064E921AA22F146D5B75F1F0984F58B907BF2D09881C092207E8F8E613C1AB15CFF60B0801379AD4BC5223E8F73E636D31DE141094DC0FE782453AB5EEB5E0E28DDB32FCC5256F545377F1D2C1159E9FA483785996F0D94B758B3AC7D01A3C13526D7544FF2A0021A1A135F046FB85544F322B13EE9FA742844E66697F32C6D194AE6081407247EF690D11D4611A1F754BCF5CB0DD060894DF3737F8167FFDDB6D05DA2B35691F92EA14B23D92EF5E05A5BE8B12C0FEDC2B10886DD7B61B6707325F8C52F18BB8112E36A40F702FC2987374D924FFB18AD34F907C3DFD2130361C1D736063F0F2345941A85A495174B161016CB6BD0C3E7025BA21A1BD0C31DA4C6F2C075BEF032A19350628AD5B4B5F6AA45A1EBE4A6F7BD229834E1AADF32D047FB329CAECA06570335A764D2AF2BC9C61541BE98AF15CF7D8289B269DE220D885EBA7806188254B47A8648A3E85A899025CCD8344BA6C441A04B3D819403656CA0EC37AED53CA4C7EF0B18C2406164BAFE279CF7737C168917748DC7E607081C6E4F94D12AA138F79D0452655DA108F7DC0B2CD7D67A1EACABB02463E6F55DB0AFFBFF6D0E022AA82888E392ED6B071F8CDC561DE48B7AC55D0B2B1535C0E3825722E26AA841238BF229EDA9594CE9D4BE971D2A814D9480B0E02BD9485D3F9AC250AC48FF727019F5401BF03E953237FA126208AA2A1EF4643B1E6F0D5D063531A809C7C97177E23D89097B0028190C1B01D50EB91D5ED7DA718AD263AC81E2CEC1C8F1B0413547BC6A434AFAFB96974FCD1A340E852635BBF572BE0152DF450F8E885BDFFCF07237AE49EE5141DF3C0CBC431E1F0AB62059B365865F857C785E8B8D4D0084C76A514096D1FBE447BC63192DB2915CA8993EC9A44BE9F46D05898FA38BDB2E85B28A3E14ED0FE059EF68F7A184C1795FD7DA8D01527A71C585898C39B77F35D78EE2E7C12AB7747E068A6B51D2CF3A96902AE6ECB3C32B2FE88F96E763C558F25A94E6B70C300B3F5FD33D23C582E980E718C321E1AE7B349A44EA7AD3E9F4EB3D3FF25C9423014A11A9DD315AB132C09D03B782C4AC04AD5D7666FDAE1BF0B6F07AA7E139F0AC6B00F283058AD9BE5F30C41F35DF57CA17E986F1B6EB4608067AD73213A5C5EFB8AD603F1DAD2C3EEE8BC3E65A67635B8013AB8FC4F0E28C881C788522A72141DCFC6A570826AA78A2959A885A0558BB35FCDB56F890ACA8A510BBB5261BD22DADBD37610CE6AC158D864B69AA3791CE96D01713F3B52DFE330D6540A753F78DD2F3DACF72962C89203CEF0ED2C394F24F0E498366B5ABD
+3AB27414539A621EC3A1F3DC5240C94455D6D9872FCBE116508284F987368F45C751925A1360C711A467A016951FA64B62265308F6073965AF9DD0F73305D1250E93AD3B38981898A37A3B695C069D06DA56E802304E81A6A4B4B23985AA0AFB77FC52168802FB321B9641A5892D41EEAA3CF3F9619EB8B4F7B95BA318BB4BE182279730349B88A9AB36A99B79217735F4C47EF4DCEC865BF0005136628A3E4318FF93D45E1484FBDFFA6410280E316DB5947F600D1CD598EE03B72998DE694D478E34F76C259195F7A073A5E283D6C752EE2E756B4F32828323829EC1F99BCF7C310F29AED6840277AFA25A9AE5827A5BE16590F9C26B49F1F58607FA29B616BE37E8D57379D28E46936D7054DEDC17E5F38F3BEBE530722D27C72C0F5534648A860495D106A812E997388459B7C0104264DB15FCC8B683CCF7802D76397437668BC6038DA90FC02128DF2A03704DF03DA77484FE21388F92CD035968ED2A12727B7D546347113134F5B68F5C07654E352A5F14F4F29A3DCA132FA3042052B032B37F70140A3AF187AFD7EDD380C6300B23DCAC1D0269DD6A5408AA1245691EE3D3A82342F4893F642AE940A3CA2A6C1EB301A723EE3165A4801254CA87F350928A063864876FF345828377443C0885226B880EBDE5D17994CAD7C94074893F5E1F5F82E2540361EA70358B5A883AEA7FC06BC7A810ED38F37B7B6967203D339F7772E079744C1975C001C72A2DEEC6F94BE435520FFEF2ACBBC5746570A8307DBBD7EE4EFB93B4F2F81C2487C7CBB61281DD03EADF3872090AE0C280E0B3BD6AB5E0C3425CF68EA6164C75802DE1534BB5B582514B5A55E0C5976838E4CA33A6B8190B2E6BF149708CB6031B1C6C08AA8A5CA98C6047A7994FECE8887F15DCF83EB1A50326E75B697BBBD501DF46B393FF31AD78D7AC2C62B9DA7EA00B67E8DB4C76E2724FFFE5242E66E6D2CDAF1F173784906EEDF81E1480D429F9C24C0ED5A502577EDC82C4CBF118D89F4CE062174FBDB5FEE7B8C45CA03189F1998F04E62F2ABFC9F5375DFB9E5C6D0A827CE73C96C27BA9328E98280DBCAA945BFACA7BA425E256C5AB29978925DD5F825A8CAB18F7A03D90F329D4E90FB9DC6CFFFB823358918A81817D93A13E58A82185058B7E326AD0C4011DEB199F62E71819F4825A1172B9AD0B239CED9713A5C9475924386D118BB2D70EA5B738A2A5EEFB0298BAE0D7052A836DDC2ECF638870638FD572EEA1E20C1E5CAC2A271468149A1BEA33653ACC75B55934D5DFF963A0D796C80F83F55F9E5BAD2C4C24CEAA6F6466765530F50F539154408B482946ACA6F2BB34B39749D243C5EDA989E68BCC41A0FF758155A3DE5BE0A16D3848A030B46F085A61DC4A4AC2982A97715AE6304B33D3CF83F981EA9596DA07F493ACE8925C6647FD0712C09521ED9CC301AA5C8609
+3FD27A2AE89B70760DB7521BE56834A311331663D68C0C52CD2ED6C3852DDD67C308A36DF447437D097704C26FB31DF920579AAC36ECDFEA667D86E64C8D31732D1592EC37FB818192DF41CC8CF1FFF83FB35ADE22A9FD48EE92DF1D5C8DCD81615633BB1EDC682CFD793274F368B018AF391DEA9D95FC34D57ED2BC4D044C426513EF09E618CA46188F774F80E44662F3CD61AF4C51FF4F798FBD919E9D0B7F49858E4260FC6892624A4386DDDC66F486CD1DD4C7BF602FB12ACE3D0D450603B84ED762F16E4FBACE6DEF3F0B79A75023512287F5D056E4AF9E64662254B6E0AC88B56E398085A6E20C12E5236E86DDB5B9E029D088019E166FF8ABE96D67579676B0E3ED014B96039845F117FC7CD3E5370A19DE103374882F9F5D3D7EB5D4F1FE9B88D22A4418962AC4FD5FCD942D7F99282B3FE070868981D31675050AF7FC6D3B976D4C7056ED2CBCE95ED0C633A0F9545867C89920ACD6A1E36E7C7C96F63A01FF0378DA25819D6D63E73040CE32BBC973F4716A46DFA8CE6F1AD2DF7359B5D49D2BD339B6118D72D611BFC19EE080CBD15CA3936238C1DEF9C30073FC112C6A77A184D7AE06CCE2134C2E79C28FAB7DE085135A461B6D603B89EE67B6BF9F27E48E09DA2B5D48AC44C2862D8066C76099CB0BFFC527CCB874FE10C49850185EE0A5905949BB1BA937C5631FCD7ED3A4B91B0D1DAF4C2660DDA4F64A6B3BD2D9DF98CAA5B88F73737715E883F14491EFB5D1C171D7A8E31819F8FA05D67B2D3AF3B773C4D458B816F524A6906F8F4151D5FE036C876D368F73E453DE0A623673344AD96975BE40520716CF0789BB4B392B1D53C41533051F3C427D61EE0104C364913BED1BA0CC220EA3D75CE67C207A5E376B6F7759078C6F660E3DA8B619A1F90EB46050F12CD82F5A796D4F4FEA33B9003527444F9E3B08C130AB04E16BAEFBC4ADA47DECC4A353FC5B05B3BD9FC287D1570B9ED3BA1810E19AD6363048E6642C8AFCCDDE5120618E9490A7D5DD8F305669B30EC89449EEF51047776DDECE5FC9E06EC30B8C662A9FF49C34A4DD736869036C2DD3B68284E4B25B995A40EC52F80C49497D1E908FC7AA6D4F601AB3D3C64AC8757E266693206C01F190F340F603AECF6BEC4BB15442ED2A6895AB48BB01B9C1FA5FCC7A7CACDA1EF8AC022EB9F37683428C1F3435B8E922DE2FD244773584CF9852767C7ED52105881076CB5F7DDD2C9F4F8E9A22E0E6329A8585F6BCAB7115CBABF5503BEC37D64D48A9B4F9C403ED4FD33D3500C9979DCA3063CED9F77AE9866824C74BA5FC48F4EDB0422B9E2F0152335184F9E3A5015F2A96BA282209F7F639CA4FC81C7945A5FC9ACA0AAADD0D791FC6A95820B54CC29C6108BCD48981503EE13CD150E6E00BDB4ED63CEEDBF7B08F38D51F11B58651DAE0FDE346C6A807E1ABA7C12A05C885
+FEF59CB02DE2B65C076152A00E9115A5F41809DD9F800D3A24D54EBD4D179EA442717CBDA935C0E0EED55D637750EE00693C980AAD337ABCA6E293EABF2C5846507C3D481B915994A573BF7E74F6C697B68788D4FAF77392ABD07FBB12191176F994ABC6FAF028C37CBF386818A0A761907D29A1254631B93B312CEEB26E33A4EF2C1D9D51315E71EB328ABE74D556189FD73A4720B6C5C270567DEC28EAAAA7FC4B9999F1D522B8150A30F9593259F76481592AB2BE272F2B77493AA9953FB92428170B200BF5289849462BFEFE238116B262E5B83797A1D87F708217BC75D5F449F0DDA9540DECA51946A3B3F8C8BD10D98EB622C59FE86A2C92C5637F3A876E531D512AD099657162624A4093FEA7A7479A009731ACA5F687FE6C826DEB400173BBCAFB8E567EF71D2E417F55FA47070AE5E2790D0EEF26F4233FC15F1BDB6261FF0B0DFE127378297BE7976995B401CBA70AB8802B04AF3D4BDC22E618604FA5D940BE7A38B470D7BC9EE5CF1DA1272E783879602ADD69552C97230948942417A960D53FEFAE099AD3BBC0A964CA2A599F7704D084BC66FE03C0AC94D19514BB18E77AF4E4844823B8FE6944BE56C9406B3A7DC22424FD612E9E5FE7885010C8D4AA594189E6DC4E724B35E24A55B1D83219E4DFD40E36EADD919D4B6ADAC722EEB676AD95D8A553478B9B22CC6538E8FD59BFFCDBFEF20D94CC7078DF48B56A89666D98F3D022BC491D088673E45D6C1788CFD48DA6C414765299791AD7163D2962E917E8B0C1AB225E96C647ED6F1C74A5D5FE5A81DDCD52FE93CA3BB8BC59C59C7188129DCB442CD5E8B02AA512AA006B0FB75DC256F99D6D62592F81E4B8959FDEAEAF06E53921AAD8B8464EE0CC6B866CBBE215985B69781FD4792B5B420D5BA84EFA80CFDC92F7C8BEE1F7AB086118E4339E32506690961C09D2186843585FF2F502C4F2621140B0C2210F3E8A3CB32100A63D258EC7B0EE0E51EF909F4CD6C705B6508CE6BBB2E0D2223DC4F9F415C5DE486A5AB9B38D3BFC095860319C891439C1731A04BDB3E478F618222FAB6E8ACCA3B1340BB833925BD51D10A304787D34DFC5BF625FA0EF6881295CB87B362725997730BC6724D845C310C93D0A85BD39D24C09CAB22A1E9F80AE821D78848C4FB62A41634DC4279292B21A725FC58E8DAB749A32E8DFE0E50E65DD50B0EA508F65F61E50A1313981FAAC576B8BC963B9B10E7342D284030394B310B3A6D90DD8C24757FEDC501EA0BC1B991C8432D62FDD50618A3DF6E42D0C5F4AEE2F14DBAE6E6B1D28822DB6CBBE0052E5A516E18C09667E07258DC9CD1CAE035895FC9403993282EBB9EF20CD58AC9A84A6A72A1DD10D1F515D668FC431548630C7C39D626A06CF1E307DB471B4C3D307A66B14CCFBDAAA5829F726DE9E958E8885E6BB7A0349053D9FA6C6B24D1C
+C862680AE9D3E4334976FE4FFFBEB8105AC03200881B1D7E5319819F2F754D1D12AFE1BC0BD3E82616E249C344D4E27C4F6906F443B79FF2911730CB89CA4B6755448D83EDAAFA99082486E19E0DA02BCD86DEB1DAEBB5810ED927B5C7029F0BB17E66DDEA45EA97BC2871201143F17F43FF77F2E29C734AF4C5EA5DC20F694EBE999197F49517BD658420F7D6B2B8BFE17A02F84F1EAEB8F647AEB6A4CF20F7A0259F501F7614D188B5F7540EBFD1E77F3DAB6F177E9B5CA7D8177F6C5392A3F98649B226DFA769BF2B5B1C48531F3FEE5C92E94BF735E70F5E3B1CD410B7D02B7017DFDE82DC1DB3CC0EED0AAB079937841618A19CEF902CE03D2D632DF8F1BE0E79F46013CDA32081A4571EA913709E11A4431D6490EB43A145F2AC4637595B2BE536484B54C1F8E079EE83DA6310FA5D27E8848580416D017A285B9D6077DB3C7ADE373BE4A938BBC374E0C433F7250C2AFA243BC70D91E7A205EBF95993635299FFEC8B35B767ACA0F52371647CDB88E53F197B92B1C0EFA8362FE9172DDE858155A2A211F5B72C6EABBAF1B2DCC30A2BAFE182268A3B414A00F3EB33DFAC99DBE6CA0E957B264B3228CB16564F4F80FC27DDF51A511A31806A33E2F05235F84D1C73623E4AE98175E599919EC965DD5BEA18DC47748C9A0ACF0D16FA8D672AD9E4EEC130C07AF09D102958268530BD5CE0D3279FB7B7551C98F7DD17CF9FE2EE6ADC5A3A8F58B335A5D95C6D82B9B0757285CC10C3729E4CDB4A7FF4EF43F8485EC1FEF61658DDDEFF3CF79FEDA0AA9FB8E077D805A16B7EBCDA57AA0884860B92251241F666FA369CC506036404B0B0691D42C7EB578D85ADF68A0100C8DDC921EDC7B4D86F8249F691495B89AC608BBD27C07ECDEFEB27F0254F0E5D181BEC57EF2E02726FA0246A91777195ABBD1A0426FE8C0AD30A0D7911038C4FC0D9C3EBC7AEFFED63CA061BADB5DA6F5A7219D72A79396A4CC0E7DBB74D8DE19334277E6A29623E4E8B7497857CC60D607E30ED8D01A261FDF36BDFCEFC950912A2B3321E2E95688F0E2126E5BA9F44A70AA3897177505D2881FDBD5961EB569478407DBDA3E5BC20DCECF3C53A089D2BAD903C2E5FE77B52895FCBE3A7A448DCC78E20E1BA84CB8488BCB81123D0AE02C48A8DE2A709A0CC5A5BB4EEE40114FEF690C9321A60DBD9763F006734142F2B9BCD6F277BB7A5D1A98742DDDEAE25F10187F3E9AF8B1D5024608126C6C4B18407B99F61EB991534465C746A141DBF323BD1B8FBED6D19CF3D0690F9277FDCAF2E3490E74C038C8E0D5EC2275304E0479D8CF972325CD416A59E0FC4F076879505836133B76D60EC02B8FFF3E425D8B3806797DE9EABCB3809037A25357350F1A885781E996B0CAEEB4D10824A8ED0BD12D1AD83B567140CD3DBD013CA4886144898757F6283E3E0707E29C1CA859C
+A40E420FC6448E08A3FECF8A6D05C9ADE71976620900A058B74B75739B921D2052721E07E7DAFAC2D708A88A0962827827088E1E2E3312890B404041E8C22951BD35918ABEA0BCAB18202810AD32527D6A2ECE18328461A3E58552EC4A91DB268670D344412051AB632695EFAFD4B958E3E8A9E509734A636E1BDEED6A69CC863E8A9934CF5D5E301AF7DB86B087B660C3D970717700F872B1D34923A1F373009F5072E1DF5291E3DA085E8865AA748555BCFB988B95B9194BA142EE2D71BC7966B1A3EB312CE7A5FF5467C8ECC7C03C5E2FA1FFAD1E6E373D14A26320B2EAC6FB4A10AAC9C4850E2958A7C13724079CF0E608D09CDDE31433C1E46BFF9C24EBA197AF0CA11585D0295385E2746F5CBF77F359406A4EAAFD1E2BF4A03D887D6091CCA11D8E1FB5CCE6CE57203066E79E62EF77A0A8F6A137F22417AB6C7D9A83F1444C43517F98DECA236CE89146A0B2A08A1D93C09ADEA75658F35ACA8A296F64BC918D59B204AECEDD352F6FD48140DD880AD25174E8A46A69EF30C9FB8566C8FC6E34705F36C22CEAF535DFECB6376072482BD97B46642F26CF84E0B5366141157684415014D4FC61B4DEF8CA355D333721C2F504DAAFA5347406B3EF58972EEFEA66111BC7401B42C3034A9F6784948A923504D7354D015D0D72D65C7F9EF17C0B19F1A294ACBADC93FF000D781CC27584184B2CB87C46B15DC59422DBBF0A3DD132FC5ADD64BB89E07450FEB32A86D4A2E45CC03AB726D35BD53278BEF0E297E585B3D7E1A3F540AD499EEC265FDD288253DFEF116B5BF72869CD908F1AEB2848D15503CE9D604B67AC6E302FC7E929E186D4E20F2C180A2B70C9D3BAF212FE151C3742B6E7C31217C40D0AC3E9B49113B386095F482524D69C7FE3932074323ED594E9EE568926F3C1A8E939D54A91E0CF5CBD03F64069D8DA27BFFD8A96BCB672254EFC1D01E6140D7E3ED5AC1F8258C9C0E05E180147C85EAA84515FDCF2CDE810E5BEC1CA7728241CE33AAD84DBA509D5A3ACE19317E5D44A3D880FF9B4EA45C0B8609832279F3BCC92EA56508FDD9DCA448A8B353FC68A1F27B720F1FD626D38C9DDFADFCCE7DE8ACFE488F8AF97DAA325EEF2DC4B537B8B472760C609E7A57A975B2D7D66FA45304513C10DFFF768A970D9DC88D1B97ADAA24B75BA85B89363D8B525AC6CB102F453CC501748E318677CEEBA0BF5F9A9741B10705B045252FEDB2730AEEFEAE3B0AA649C32D067F2E96374BF0142018287365C6C46B4BFADAEB75831EAE21D887F8A7E19BFB9DE8F885D06A168771A628E7B75381F31B61429A02F3F11DBDFAE7181E44C91DDF0A531300D5004B38D1ABC86327DFB9B760AD694EE145DAC2530C89FEF13A3B0D4C44D7DD3A4A876DD08427BD395DD8FD85221D5912F2285977293240D6E516608651B1D9069DB2EA0F5AE24C587
+25671F73EA4EC64CDE96D66AF62E7BA00F4E8D688197EE730C9EE9AB45B03B3A7E0AFD55904754CE1347DDF1951EA3155DABBD77D5C14D85306A9A2455765B97652931DEFCD1CEEBFB47CE5FC2DD6108E72177AF6A9D70558488B9A3282ECB1F63A4449833CDD3FB92307CF8E9D10269E307AFF5182C7A63E192FC0820FFED8DD26D395F55A7F31AF1460A86360AC7140C6694249222A0125932B3CF1F35AA14BC7A036DE2A91170EF6CA89DB02284FF9294F4773F9DE4958B5B2F3088535A94AF290AF5B6AF9F5602032DE37DA6FC6C3D22C73707D29B7DDC707E2DBEDD16AEB11C977A0782FACDF982EB6BFB2CE7AABDCB940FF4D3A41072AE6EE69ECAC367B8FD731562307455ED26008751365AEAB1886407D573363B9A8BBF39F874B4343800B3C003B547C8A531D0E88CA93E1C948594C837D0A3A1F33CB5C4DE89D6BD8BC8730CC71D9EE85644AE7EEDEA544FAFA8CCBE9AEFEB86DD3AC2C3451002EA9473E4E166E5E394571D1E1DF03EE0D18C18A8EE43DFFD91FF29E353107BF19CC57FB6FE0E14818FD966BF442F4D55787AFCF2A7BA8BF08F92CF96FB32E9C7F0620D59F331D9EDF267A1DAB4B8613D20F5A48CE924D05B9B96FD4A4FF510ECB216813E9807D02C2E5F65DD1C58F76D60A2D760BA48FA5134106F0CA8E2DC1F6424EB1419654D95E95B3017F749EF006F155547999E11C67E45D352CBBD35C9EE36C3B3ACABD4131910DBC5A2708889C8595C14EEC2B587CF0E453BF77DB5EF9F0D396C77652D3179CF193DEA1FA09BBE524D733C826737013A6934DDD65A9DAA6D97A1806328DBCCEB2273DA1E5903AD3E695C38A5F3415FC59B0E998EE5E8F8A1243683C3A1912FE6238F080C5CCD56FDABD6FE090CC38A3A410EBE0EDF748F9B6380CA8D8D70226289BEFE2967CFF123DA3FC2D667FB6BE9AC87CDD72505F32C8C1FB0C7E7690800124257B7E9268C91467F3D3CA31A87A515B30EE3E454F40A35A18CD54678614413F3BC487D3BFD78726807F89A5EA78A7F2C8770FE40C4E0298BD360EB3FBB94E4ABE6ED043B96047EEB36AC99742F60D4FECD61C962EF9FCD0CC0600976DE4A5DAD5961744194DEB1573098047B9F78D8CCA5566C6A840875C6A00A69455D77A93A91678F3A11FC277A07906B8ADA12357EB0630C98E86CF69B34DCAE5946155F392833AAB06EB25DCB3E71B9F9DD99CD685C411A7816E46FCA500D36CDB4371D8E1A2A725855FB3B3C15603ED75BFC58CF1E3061EE10D13ECE9F6ECF0C748B95C72B71D22202E5424881E54C473420DF308AB8A004EC8B9109E767BE5D2CBB4B13DA76CC63C064E43C40BDD30DFEE9DFC2DFF1E15DA451365F5E6526B00C3EF789552AFB483B5D93AC0FA2C30B319C7193305AC26B6009C424513B5BDBE9B889C30D74724656797C438A820C30729B5EB2C85D0B60DA
+2BEC143D675F38D81BC97731A2CF71878E384DAECE198ACD395F0C17C6A2305662C6F0DB44CBB4D0679485D5CE68718B07AD7E5DA27830A2EAEED0ADA0D14438BE302A8A10A9AE95507FAD068CBC2685CC52D318C1645917AADFD5F05E6840C0660C89F5881B9AD5C28CD30DD1CE3306E710FF92D268F3476491397958ECB53DBA8F7759EEA5FC8807146C32FF5E669C5BF8117853099C9B3321BA0116D05C7BC8110D2EE7BE8D3EDB2A823A9CF702A00C3EABEC623F16FBE30C4531CD7EACC0C5588D39C9E64CDA6AB04BEEF39CF2B7E412CF3D4524A5C8BA3219BCB7ECAD46C984CA1C925FFC89E26B355ED269AFF05CAD03F2C848384AF87BB7FC9059DD3D60538F990BA878FC4FA05407445465F6657397EE817ED219E342D1C1EB02575AC9C2653070A47BA417BC9380D0556E13A8032CC3D5E2D64E085207D03C22144120E8D2C4A79416571031E74532395EDE3A7F4236DC46BAF581FC741342867990202F94F851019AA55B5B9D9B1B0FD99C7427A6BE85805E2723B46C2A45F114BB93A709F484E440E1664A48407CAEECC45AFCFB0DFC9BF8F75A002A74996152962262192679D13DA86C1A9BA3B7A8775A95D003EEC674873FACCB37EB621A505A4CE8026134C7121EB128DAE76A760EFAF478749A7399F567B190B41DC319BBAE5AA5917E98D21C3A7B6B5BEE01A94EC2A3322FB8F7CA9774236A68A1FFB5F45BD0C7981EA5D38769E0AA4F66C76BF6A6C44A87FDD8FD025F18E80303C0A9B3FD348540119A51099BB0DE177E54E1ADA86367AD441AFE6318004086739B9ED7601713F88B6ED02CCD4B0B6273232CD616FAECD188B9766812AB509CD409AC93023CE4852616BF9E5B6FD5C0D6CA774CDEFEF29DC6714252DA6983C8B3C47738C2FEF879856033467BCD9450CF817B4D5FB94E48CFB60B1DB820677F01164206051DE70A1F543F626AF5020FE5D0E03259483CFED8A478917DA1D49B46A2CB80EDFDC803C60B650629CA256EE0FF7F666C1D83BE96A6305CD8B9326522125415EB6926C374EBA457ED61232EB6DA2630B616679EA4F99510F8F25C6B26B98C446FD992731FAC4AAC5EE9E3307028630277D1F4E278A696F536F77ABCA12CB07B1C3DF73C5409A7D7F8DC7AB58C700AB54231DBAE1033DA760FB617D6B06AFAFB229F636F8816D947C0CD8B3954BA678F11649345CE290D3F21ADBD6133650D2B68A2E9E32244A5C3AD7330A2C4B0F93643232043EC6C0A8BC337EC5FC213797ED9DEBCCF90328BF94959A6665E0237866C45FA6617842C93352F661250815191A6FBE2F390C65490ABF75CB2DAE26E32C87501C297836AE23FAF155EE976344235F8EFBEE0612E6B14766AE4B1FA201C603B8323207AA7B8DFF17954C44777E1F3ADFCCB9CA5CDC71CAB8AE368B327DB5A7EE67B79FC50BA7529287280143EA2CD
+C93523E1C95375687CF9B19B231F56CE4A884B471CFF61C2128AB54A5396156FD29CA5FDEBB91082B2F3C66C43C7DC6CEBBACD0B7D4AF89043A412E1C531B0F50134BF03EFF74A030256B2896F942AE1AE0A0596A567D67483360479C6B5EB0DDCAD66FE8819F5027B4CAE9C26F9F575EC86B99DB88EB9292BAE25D24BAB03EAFCFCEA736B3650773DC939396CFFF4A501EBD8D137DD12761218C5C2C8FE482AAB4FD1CA0FEADF4B0C6470525C3CEA6F2650187EDE9EF5F702F49E24F0AB6187E1CF6B511D9BAA70E7B4FE05F5CED51852D52882E890EE47E93C37B962730EC44011466E3B46ECB24F8082DDFAF4845DE64E58B8BB3C3ADE089BB737A17AF3E8AD3F9A3D55A760125CB5A936842632FCBC29FEDD25900B72A31C49E754F22FFC1BBFC2ADFC874A2954FE0CBC6F3C0538B8F88F096AC4195AD943452E11E9A35CFD8E8197254186FC604F8231AE1F92F64E49802730DF85D492B92A72E61E3AE97FC357F8AA0AB7F0A32896A08EA790DCE3042DC91E209B9C0263CDE11F2F08669D6C4EF853D67FA7E014FB757532CE8636194C29DE184E9C4628D1417AB80B69CD349DB5E8DE66E6B5863834D7CCBAFF6E92D8A2BED6D1AEF05EFC05832CB92BCA78AD5E8EA044C69264CC945B88A8657402D8C4A6813BE021573E5F57A0D2EE709EC48FD370F01574ACDA3B582E50B3EC05DBFE2FD07DF7B8B8879DDB19A7159871F4913A76C671A776F1888DB2C302F0FDA83B212440897DB1D751AF4AE2B73062728A6C4FCDAB5A921E6DE8DCA6C6AFCB6CCA1E7460DB0544A16D2589F8AD4D9CB5E86F8E29F241CA15AA132B74233BD5B5467E6AED50148BEE010C901F86DEF90DD5087D897E21675E0A18C80C9428DF9EE3493CD04EC5921DBA950C43511C10FE8DA4A26233F582AC0E5C60D366664473C91A1C7C19FABE0282CBD44E7442C99784C599424EE44989E1E118C97299E4935491BAD1E7B137B4F04A9F4292AE2C8FF3B8F954BBD332C869B5D2D3648DC5258F3A541CA73A313602FFBCE12EA2AFB9840A96367DCAC4194FC3E2DAA92E5D2753EEFA3907006033BF2A6C6F41386A3D4AA8CF868C61C3C1E3C5E1EA8CC02ED8E2B341F0529EE634219564B9E0184F71EC40E401E7BF868101F3B66BAE39B8BD1998DD7CF82CB2ED2EDC58994D20D49E74581196E8D135874C29BBA9379D6EA311943845AC9939920504D266E599521050C397E0DB0178772C29784DDEC775750EDEA4E0BFB5FFD93164528BAF1BDB1884D91EEDD62FFA556601AAE2407E85F05D5AF42E8AF9660197168911FA176D8C2CDDEF22DCDE4C085693CE42DD8FA9B3FA0375AF6EF04C2E5AEFF3C3DBAD1ED989D01D8741434A34EC35F9C7C4DEB1E3A1E4889EAA2E6E380F04D838E8F71FF292BCC3E9548F83CE5C258E081174BC5EE41D48355029A4A1EC6DBE6AD9
+01970B28AE64EEE56F80EC7850EE1C8D1D92FC8F073CCA4ABD463C85DFEF24B7CF1B76CE1A83BE48BA6FCBAD7B6A643912B94E6D9779C24938FB327E00C82741EE37D7A7A13027A5CE4BD82EC7A26193CD7ADF6C1221E71246B1D5DC521688AF7BF3A355A4C056AE2543EA59830F7A14FE29F9B0101BF1C599C60D5EF2F622FCA5EEA2D0D75A983FC29CA696A5D16B004027652861072CD22AD5F52F8E6923344BAC1611D21269C3C15428F44E6B77F91FBCD61F2A0F600732AA1A19D2B38134226D4E263297261B4981328F02901E50633EF62A3503084F43C7B3327354D7F6E184E36C51F6FE415D1D83AC78119D995A8A207A0A250349FAA37E7E409144232F7431436C714070C71987D3A9C2B404A197425EE148B1E0ED8D534A3E34FE0D712BADF5674F1CB3E77CA697A3613840FCF0F87DB1A9B24B53CD26DD6A0DF9C22AF831194640A23A388BCCF75FB8A4D776B520B49473AC736490E8F21CCEE24669252E067908C3DC9DC9C068791332FA92BA87EAC43160824BE433B087342818874668157534A8331021AA7EA2932A16F66BEED11AAA87F0BF2B75E1552FD36F6458A3AAA856EB773BAD29931B920119B5FD44E8B9EF5BE09BD58347E092E63C831C6585FBFF6ECB1BD2C61A917610DA4826DEEB6039FFDB456B814396887B11A7958F1419429DC112D48F01BE13308F6869D407D66E30FD2ACFF02BB07228103ADE1CE72E9951E87CA6A97BD8AE0BC9A920EBD4C078B0FEDFA0B7B4BC5292A3672BB98EBDD910A72EC0D434ACE120B86B3B9D05981CA8789316B0A31A964472D87C65829A4AEA70CF87D49A967ECDEB6B64F85A8DE05D12BA4CA3635709F0B15CB09AEF5A5D17BCF7A71382C3675CD1E47689675F77AC46010C307B
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+ %endType1
+
+end
+
+%%EndFont
+bn
+bu fc
+{}mark T /Helvetica-BoldOblique /|______Helvetica-BoldOblique 0 rf
+bn
+bu fc
+2 F /|______Helvetica-BoldOblique fnt
+bn
+(basilar membrane motion .)show
+64 gr
+1642 581 1902 1531 1 rc
+8 8 pen
+0 gr
+1642 581 1902 1531 0 rc
+64 gr
+1738 733 1813 1392 1 rc
+1796 734 gm
+F 1 setTxMode
+0 fs
+bu fc
+
+%%BeginFont: Helvetica
+%!PS-TrueTypeFont-1-0.00009-1
+25 dict begin
+/FontName /Helvetica def
+/Encoding 256 array
+0 1 255{1 index exch/.notdef put}for
+dup 0 /.null put
+dup 8 /.null put
+dup 9 /space put
+dup 13 /nonmarkingreturn put
+dup 29 /.null put
+dup 32 /space put
+dup 33 /exclam put
+dup 34 /quotedbl put
+dup 35 /numbersign put
+dup 36 /dollar put
+dup 37 /percent put
+dup 38 /ampersand put
+dup 39 /quotesingle put
+dup 40 /parenleft put
+dup 41 /parenright put
+dup 42 /asterisk put
+dup 43 /plus put
+dup 44 /comma put
+dup 45 /hyphen put
+dup 46 /period put
+dup 47 /slash put
+dup 48 /zero put
+dup 49 /one put
+dup 50 /two put
+dup 51 /three put
+dup 52 /four put
+dup 53 /five put
+dup 54 /six put
+dup 55 /seven put
+dup 56 /eight put
+dup 57 /nine put
+dup 58 /colon put
+dup 59 /semicolon put
+dup 60 /less put
+dup 61 /equal put
+dup 62 /greater put
+dup 63 /question put
+dup 64 /at put
+dup 65 /A put
+dup 66 /B put
+dup 67 /C put
+dup 68 /D put
+dup 69 /E put
+dup 70 /F put
+dup 71 /G put
+dup 72 /H put
+dup 73 /I put
+dup 74 /J put
+dup 75 /K put
+dup 76 /L put
+dup 77 /M put
+dup 78 /N put
+dup 79 /O put
+dup 80 /P put
+dup 81 /Q put
+dup 82 /R put
+dup 83 /S put
+dup 84 /T put
+dup 85 /U put
+dup 86 /V put
+dup 87 /W put
+dup 88 /X put
+dup 89 /Y put
+dup 90 /Z put
+dup 91 /bracketleft put
+dup 92 /backslash put
+dup 93 /bracketright put
+dup 94 /asciicircum put
+dup 95 /underscore put
+dup 96 /grave put
+dup 97 /a put
+dup 98 /b put
+dup 99 /c put
+dup 100 /d put
+dup 101 /e put
+dup 102 /f put
+dup 103 /g put
+dup 104 /h put
+dup 105 /i put
+dup 106 /j put
+dup 107 /k put
+dup 108 /l put
+dup 109 /m put
+dup 110 /n put
+dup 111 /o put
+dup 112 /p put
+dup 113 /q put
+dup 114 /r put
+dup 115 /s put
+dup 116 /t put
+dup 117 /u put
+dup 118 /v put
+dup 119 /w put
+dup 120 /x put
+dup 121 /y put
+dup 122 /z put
+dup 123 /braceleft put
+dup 124 /bar put
+dup 125 /braceright put
+dup 126 /asciitilde put
+dup 128 /Adieresis put
+dup 129 /Aring put
+dup 130 /Ccedilla put
+dup 131 /Eacute put
+dup 132 /Ntilde put
+dup 133 /Odieresis put
+dup 134 /Udieresis put
+dup 135 /aacute put
+dup 136 /agrave put
+dup 137 /acircumflex put
+dup 138 /adieresis put
+dup 139 /atilde put
+dup 140 /aring put
+dup 141 /ccedilla put
+dup 142 /eacute put
+dup 143 /egrave put
+dup 144 /ecircumflex put
+dup 145 /edieresis put
+dup 146 /iacute put
+dup 147 /igrave put
+dup 148 /icircumflex put
+dup 149 /idieresis put
+dup 150 /ntilde put
+dup 151 /oacute put
+dup 152 /ograve put
+dup 153 /ocircumflex put
+dup 154 /odieresis put
+dup 155 /otilde put
+dup 156 /uacute put
+dup 157 /ugrave put
+dup 158 /ucircumflex put
+dup 159 /udieresis put
+dup 160 /dagger put
+dup 161 /degree put
+dup 162 /cent put
+dup 163 /sterling put
+dup 164 /section put
+dup 165 /bullet put
+dup 166 /paragraph put
+dup 167 /germandbls put
+dup 168 /registered put
+dup 169 /copyright put
+dup 170 /trademark put
+dup 171 /acute put
+dup 172 /dieresis put
+dup 173 /notequal put
+dup 174 /AE put
+dup 175 /Oslash put
+dup 176 /infinity put
+dup 177 /plusminus put
+dup 178 /lessequal put
+dup 179 /greaterequal put
+dup 180 /yen put
+dup 181 /mu put
+dup 182 /partialdiff put
+dup 183 /summation put
+dup 184 /product put
+dup 185 /pi put
+dup 186 /integral put
+dup 187 /ordfeminine put
+dup 188 /ordmasculine put
+dup 189 /Omega put
+dup 190 /ae put
+dup 191 /oslash put
+dup 192 /questiondown put
+dup 193 /exclamdown put
+dup 194 /logicalnot put
+dup 195 /radical put
+dup 196 /florin put
+dup 197 /approxequal put
+dup 198 /Delta put
+dup 199 /guillemotleft put
+dup 200 /guillemotright put
+dup 201 /ellipsis put
+dup 202 /nobreakspace put
+dup 203 /Agrave put
+dup 204 /Atilde put
+dup 205 /Otilde put
+dup 206 /OE put
+dup 207 /oe put
+dup 208 /endash put
+dup 209 /emdash put
+dup 210 /quotedblleft put
+dup 211 /quotedblright put
+dup 212 /quoteleft put
+dup 213 /quoteright put
+dup 214 /divide put
+dup 215 /lozenge put
+dup 216 /ydieresis put
+dup 217 /Ydieresis put
+dup 218 /fraction put
+dup 219 /currency put
+dup 220 /guilsinglleft put
+dup 221 /guilsinglright put
+dup 222 /fi put
+dup 223 /fl put
+dup 224 /daggerdbl put
+dup 225 /periodcentered put
+dup 226 /quotesinglbase put
+dup 227 /quotedblbase put
+dup 228 /perthousand put
+dup 229 /Acircumflex put
+dup 230 /Ecircumflex put
+dup 231 /Aacute put
+dup 232 /Edieresis put
+dup 233 /Egrave put
+dup 234 /Iacute put
+dup 235 /Icircumflex put
+dup 236 /Idieresis put
+dup 237 /Igrave put
+dup 238 /Oacute put
+dup 239 /Ocircumflex put
+dup 240 /apple put
+dup 241 /Ograve put
+dup 242 /Uacute put
+dup 243 /Ucircumflex put
+dup 244 /Ugrave put
+dup 245 /dotlessi put
+dup 246 /circumflex put
+dup 247 /tilde put
+dup 248 /macron put
+dup 249 /breve put
+dup 250 /dotaccent put
+dup 251 /ring put
+dup 252 /cedilla put
+dup 253 /hungarumlaut put
+dup 254 /ogonek put
+dup 255 /caron put
+readonly def
+/PaintType 0 def
+/fcheckload{{pop}{save 3 dict begin/mystring 2050 string def exch/endstring exch def{currentfile mystring readline not{stop}if endstring eq{exit}if}loop end restore}ifelse}bind def
+userdict/type42known known not{/type42known systemdict/resourcestatus known{42/FontType resourcestatus{pop pop true}{false}ifelse}{false}ifelse def}if
+/truedictknown userdict/TrueDict known{TrueDict dup /initer known 1 index /render known 2 index /imagemaskwrapper known 4 -1 roll /bander known and and and}{false}ifelse def
+%beginsfnt
+truedictknown type42known or( %endsfnt)exch fcheckload
+/FontMatrix [1 0 0 1 0 0] def
+/FontBBox[2048 -342 1 index div -461 2 index div 2036 3 index div 1998 5 -1 roll div]cvx def
+/FontType type42known{42}{3}ifelse def
+systemdict/product 2 copy known{get dup(LaserWriter IIf)eq exch(LaserWriter IIg)eq or version(2010.113)eq and not}{pop pop true}ifelse{/UniqueID 16#00CBBC67 def}if/sfnts[<
+
+000100000009000900090009637674208D653D9E0000009C0000035E6670676DE644D5E3000003FC00000322676C7966E89B16DA000007200000A3B068656164ACA7938E0000AAD000000036686865610CCA05FE0000AB0800000024686D7478574D52060000AB2C000004086C6F636100582F660000AF340000040C6D617870094502220000B34000000020707265702482325A0000B360000003BB05C0001005BD00280580001A042F001F0000FFD90000FFDA0000FFD9FE55FFE605C70010FE6DFFF1033B000000B9000000B902FE3F3C00C0008D009B00AF000600A800C00028005E009800C9016A00B9015C00B400D6011E002E0080000400B8004C00CC01FFFFD1006600A400AF007400C2009500B1000C0028006D0015004C008E0125FF7A000C0040004C00620084FFA200240038008600BD0039005E008E00EDFFA9FFB300400052005500AA00AB00C200CB012302B10413FFAEFFE4000800510074008400AA00D1FF4CFFAF0012002C004200500051008400BE012503DAFF680018003B0098009C009F00A100C100EC018201B4FF68FF76FFD0FFE100020018001C00530053007D01B401E103AF0486FF9CFFEAFFFE001F0028002A00520060009300A300AA00AF00AF00C001000145016B0174019301950240028202B404850517FEFD00060029004700470048006F008800B400B900C400F200F901EF02180310037403C5FF35FFF3000B004B004C0052005500650076007600870087008E00AB00BB0106013001430150017D0194019501D3022A025502580277027802E6034E035C037903D3047304B2058C0598060BFEF5FFBBFFC7FFD50017001D005B0072007E009C00C200D000F400FA01030106011C0125013B0142015E015E0180019B02B901A101B9025001C001D002AA01DF01E301EF01FB0205020C0215022B0274029302AB02C202CE03690395039903DF03F5043E050205A105E5062507DBFE62FE89FECEFF3BFFE1FFF800030008002100390042004E005F0061006F00700034007F008E00AD00AD00AF00BD00C400C500C900C900C900E3011C00ED00F800F901000112011A0132014D014D014E014F01660169019E01BA01BA01BE01E301EF01F602000200020902110217021C02530262026D028002D50280031B032A034A035A03AF03AF03C803D603FB03FB04050413041504470449008C046D049A049A04A604A804B204CF0539053E054E055605800589058C036305D105D6067E068E06B206EF06F00728074C076F078C00B400C900C000C10000000000000000000000000004012400AF0032006E0063014401620096014301A10161008A00740064018801EF01700028FF5D037E0347023000AA00BE007B0062009A007D0089035C00A1FFD803AA00D70093006C0000008000A70442001D0597001D000040292A29
+
+2827262524232221201F1E1D1C1B1A191817161514131211100D0C0B0A090807060504030201002C4523466020B02660B004262348482D2C452346236120B02661B004262348482D2C45234660B0206120B04660B004262348482D2C4523462361B0206020B02661B02061B004262348482D2C45234660B0406120B06660B004262348482D2C4523462361B0406020B02661B04061B004262348482D2C0110203C003C2D2C20452320B0CD442320B8015A51582320B08D44235920B0ED51582320B04D44235920B09051582320B00D44235921212D2C20204518684420B001602045B04676688A4560442D2C01B9400000000A2D2C00B9000040000B2D2C2045B00043617D6818B0004360442D2C45B01A234445B01923442D2C2045B00325456164B050515845441B2121592D2C20B0032552582359212D2C69B04061B0008B0C6423648BB8400062600C642364615C58B0036159B002602D2C45B0112BB0172344B0177AE5182D2C45B0112BB01723442D2C45B0112BB017458CB0172344B0177AE5182D2CB002254661658A46B040608B482D2CB0022546608A46B040618C482D2C4B53205C58B002855958B00185592D2C20B0032545B019236A4445B01A23444565234520B00325606A20B009234223688A6A606120B0005258B21A401A4523614459B0005058B219401945236144592D2CB9187E3B210B2D2CB92D412D410B2D2CB93B21187E0B2D2CB93B21E7830B2D2CB92D41D2C00B2D2CB9187EC4E00B2D2C4B525845441B2121592D2C0120B003252349B04060B0206320B000525823B002253823B002256538008A63381B212121212159012D2C456920B00943B0022660B00325B005254961B0805358B21940194523616844B21A401A4523606A44B209191A45652345604259B00943608A103A2D2C01B005251023208AF500B0016023EDEC2D2C01B005251023208AF500B0016123EDEC2D2C01B0062510F500EDEC2D2C20B001600110203C003C2D2C20B001610110203C003C2D2C764520B003254523616818236860442D2C7645B00325452361682318456860442D2C7645B0032545616823452361442D2C4569B014B0324B505821B0205961442D0000000200A10000052F05BD00030007003E402105062F02010004072F03000A05042F0303021A0906072F01001908098821637B182B2B4EF43C4DFD3C4E10F63C4D10FD3C003F3CFD3C3F3CFD3C31303311211127112111A1048EB8FCE205BDFA43B8044DFBB300000200ED000001B805BD000500090034401B0000044F072A090A0B17171A07040301250600190A0B6421787C182B2B4EF44DC4FD3939C44E456544E6004D3FFDE63F313013331103230311331523EDCB316634C7C705BDFE1DFD84027CFCF6D0000200520371025E05BD000300070025401402069D0403000029
+
+03042907190809FE21BB48182B2B4EF44DEDD6FD003F3CFD3C31300103230323032303025E1E791FA11D791F05BDFDB4024CFDB4024C000200000000047105BD001B001F00F540A80708071717182718570C771E060E1112120D031B1B04010011190602030E190605040D190608040D180709040D150A0C040D140B0F030E140B100011140B131B12140B161B12150A171B1218071A1B1219061C0011150A1D030E150A1E030E18071F0011180712110E040300060D1B0619191C121818070A15151C1214140B191815140B0A0706080D1B0B0A0706000E03370D049D1B110037121B7A18191815140A0DD51B2147201076C4183CE5003F3C3C3C10F43CFD3C10FD3CFD3C3F3C3C3C0111121739872E2B7D10C5872E182B7D10C501111217390F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F87103C87103C3C3130015D13331323373313330333133303330723033307230323132303231323251323031EE95EE81FE8779579DD7B9379E81FE85FE91FE67B9379DF779579E802765FDD5C023101587401C0FE4001C0FE4074FEA874FE4301BDFE4301BD740158FEA800030040FF13042506340008000F00360103400C85080C1F331E0B07040C3219B8012F40201D7F0C35157F141205327F08352EF928AC29260D19291881032922141D070327B8011D4010130B3203280F2936812E29282D3847371076C4D418CCEDF4FD10173CFD173CDCE5F4F5003F3C4DE4EDFDE43FCCE4FDF4E4111217394B5279B507A91E33A90B2FED2FED31304379405C003530262B251B2620250526242601250D110F28000A340F2800312A2E28001C16192801061F03280100250328010E100C280109350B28000A0B34332F2C32280031322A291A171D2801161504210728011F1E06070223082800252600103C2B103C103C2B103C2B103C103C2B103C103C2B2B012B2B2B2B2B2B2B2B2B2B2B2B2B81243736353427262711001617110E01152636373533151E01172326272627111617161510070607152335242726353316171617112E0135030E41225C357DFEAD836F836FB4DFC95FC7D505AF07223F8AE85387AD60B55FFEDD6839B108233EA8D8CE70753C4F7D412622FDF20362701601D60596528CF40285830ECFAA4C376505FE1A41395EB8FEF6703E14C2C213BB65AC893F710E022129C0AA00050042FFDA06D00592000B000F001B0027003300F04052060C250C02370E580C670C960CA70CC60CD70CF60C0868080D0E0E46120F0F0C0E0F12180C0D2A301B2421F215240D272D240BF23324050A0F0E3517171A2A2402F2302408EA12241EF218242419343F52182B4E10F44DEDFCEDF6EDFCED4E456544E6002F3C4D3FEDFCFD2FC4EDF4ED011112393911123939872E2B7D10C43130184379405200322E0A301B002C002A1B011A22181B001020121B011626
+
+181B00141C121B013206301B0028042A1B012F092D1B012B012D1B0119231B1B00111F1B1B001725151B01131D151B013107331B002903331B00002B2B2B2B2B2B2B2B012B2B2B2B2B2B2B2B81015D71001615140623222635343633033301231236353426232206151416331216151406232226353436330036353426232206151416330604CCCC9091CCCC91916FFCDF6F327979565579795591CCCC9190CCCC90042B7979555679795602B8CC9090CCCC9090CC02DAFA4803687955557978565579022BCD9090CCCC9090CDFB2179555579795555790000030059FFDE052805BB000D0018003B00D54087262C262D372C372D790D051732450C4832583264006A1366167804750D7811783278350C4F0D650D7501034A0D012D302D2E0D0D0026102625253612111125111027262910262D302F052A0D112503030A2627102C2D3006182A2A0D11253B05061806241E002F0A1824340B03360E2101213B0A361B211B372E29362A402E1A3D153637193C3DB80165B321BA33182B2B4EF44DED4E10F64DF4ED111239392FFD392F5DED003FED3F3FED111217392F121739011211173911173911123987082E2B1008C008C005C008C05D005D31305D015D0037363534262322070615141617123637010607061514163302263534363332161514070607013E013733060235012327060706232226353437363702A8243B56496F2B16434E41A02BFEB48D2B42AB61D33FC0A199AC59347A010C1B150BAB11660105E88A5244779BE5D0653EA903C52A4453415E4A262D3D7059FCFA663F01955E324B6C757E032092448EBBAE798D6A3E51FEC0504F478DFEFD19FEC3A8592948F79BA77044660001009C0371015205BD000300264013029D03000517171A002903190405C121BB48182B2B4EF44DFD4E456544E6003F4DED313001032303015221742105BDFDB4024C000001008EFE5E026105D50014003E4009141109131617171A09BB019C00080014019C400E400080044C10191516F7216C5218B80732852B2B4EF44DED1ADD1AEDD4ED4E456544E6003F3F3130010207061110171613232E01272627263510373613025E9D2F475132937992462938160B5D3BBB05D5FECF90DBFEE1FEDEF094FEEAE47E6C94A8574F0128E793012500010044FE5E021705D500130036400C081100131517171A044C0F13BB019C00000009019C400908191415F7213F7B182B2B4EF44DEDD4EDDDED4E456544E6003F3F3130131237361110272603331E01171E011510070603479F2E46513293799A412630295E3BBAFE5E01368ED701210121F0940116F673657DF471FED8E895FEDE0001004E037102C405BD000E00B34066870697040257047704C708030D0C0C37120B0B0A0C0B0708070608371209090A0809070607080637120505040605020102030137
+
+120404030C0A0908040D0B060504020403010D0C0B0A030201070E044D070E0007061017171A0397010E0D970B190F3F48182B4E10F44DFD3CDDFD4E456544E6003F3F194D10EC11173901111217391112173904872E182B087D10C508872E182B087D10C508872E182B087D10C508872E182B047D10C53130015D005D01153717071707270727372737173501C2DA28DA876383846689DC28D805BDDF4C6F47BC47C3C347BC476F4EE10001005C0000046F0415000B0037401C037A050220080B7A0A0A0D17171A067A040920030A7A00190C3F52182B4E10F44DF43CFD3CF44E456544E6003F4DF43CFD3CF431301335211133112115211123115C01B4AB01B4FE4CAB01B6A801B7FE49A8FE4A01B6000100AAFED0018000DA000E002D401600230E0A64080A1017171A07340A640008190F6365182B4E10F44D3CFDED4E456544E6003F4DEDD4ED3130173637363534262723353315140607AA451C0F01026DD66076D10C552D2A070B07DACA77B415000001005501DE024B029700030020400A002F03011A0500190405B80142B321BA48182B2B4EE410E6002F4DED3130132115215501F6FE0A0297B9000100AF0000018000DA000300264013012A030A0517171A01640019040564216365182B2B4EF44DFD4E456544E6003F4DED313037331523AFD1D1DADA00000100000000026A05BD0003002B4017070117019701030102021C1203030002030A0100020003192F18D4003F3C3F3C05872E2B7D10C4015D0133012301D298FE2E9805BDFA430000020040FFD9041C0598000F001C00714017870501460815350F051C35070D1238036F18380B1E471D1076C418D4EDFDED003FED3FED313043794034001B0D2601251A2609250526160E18280014001228011B081828001006122801170C1528011302152801190A1C280011041C28002B2B2B2B012B2B2B2B2B2B2B2B2B81005D001716111007022120272611343712211236113402232202111417163303407C60577EFEE2FEFE7E693F7601358AA678AD9F932F48AE0598E5B1FECCFEDCBFFEEEE0BB013BF4AF0146FAE5F80152F4013BFED5FEDDDB85CB00000100C4000002D5059200080023B10801B80133400C0404070C04079605000A47091076C418C4D5FD39003F3FF4CD313013353E013733112311C4C39A268EC003F68A1359A6FA6E03F6000100400000041E059D002200A6404E3604460457056B1D6E1E7A1E84018702082A085A196B197C197C1CB519050022010F041C0E1921071C19040100051F0F0F22130A351305201F7521220C217F0738166F220E270F811F38222447231076C418D4EDF4ED10F5EDE4003F3CFD3C3FED1112392F1217390111123912393911391239005D31304379401C04190C2511260B120E2800091407280119040D100A280108150A2801002B2B
+
+1010012B2B2B2B81005D36123F01363736353426232207060723363736213212151407060F01060706072115214A85C1C0813452967DB9472604B70342750128F6E37946B5896238641A030EFC29B90112706F4B35536B7D938C4B85BB76D0FEF6A3AC7A47654C3631576AAA00010031FFD9041A059A003100C4401F490C532D6529632D7529752D069626014B082B0A182B140D03F93114350D20B8012340141135107F0D0D311B3524050735310D1896274411B8014A400F0A382E6F021F2920810327023347321076C418D4EDF4ED10F5EDEDF4ED003FED3FED12392FF4FDE610ED10ED111239011112393130437940362F301926000905261D2522260600032800040308300A28011C231F28001A251828010401072800092F0728001E211B280119261B2801002B2B2B2B012B2B2B103C2B2B2B2B818181005D015D0402353316171633323635342623220607351E013332373635342623220706072334373621321615140706071E01151400230116E5BC0C2846B78EACB5A11225131C26166541729865B4452605B2406E0115DBF0472C46717FFEF2F8270117C88B3F719878947601019F03022038906B7478427AA070C8C3B98452331D1FB180CDFEFE00000200340000042F059C0002000D005C402209020A080D010202BE12060607020601050708030106070A02750B05EF030C070403B80117B501960D08AC0AB80158B3050F470E1076C418D4F5F43CFDE4003F3FF43CFD3C1139390111123911123939872E2B047D10C50F3130011109011121350133113315231102A5FE3501CEFD8C029098D3D301FB0289FD77FE05015EB0038EFC5F9DFEA20000010042FFDC041C0580002000BB402B4812881F02390C461357136713043A080C0D07000C0A0F0E0E75121313120E0F201213070013170A17350AB80122401A0D7F0E0E1D123A0F04043520C71D0D1107381A6F0038202247211076C418D4EDF5EDC4003FEDED3FFD12392FE4F4ED1112390111123939123939872E2B7D10C5001239011112393931301843794028181F01090226031E00280001001F20051C0728010918072801011F042800061B04280008190A2801002B2B2B012B2B103C103C2B2B8181005D5D131617163332363534262322060727132115210336373633320415140221222427FD127D4054A09AB7805D852F9C6D02E8FD9F3D322D5069C50112FBFEEDAFFEF310016D9A3B1ECC7C96A44840090303AEFE72261321FEC3CBFECAC5CC0002004DFFDB0423059E001B002700A94039771A0117082508271958198600870188090747080A212721350E0E1403C707351B052735140D032902811E38116F170A023C0A2431172947281076C418D4FD397C4B52787A2F1810F5EDF4ED003FED3FEDED12392FED11123931304379403425261C200F1600060526200F1E
+
+280126152428001C131E2801060003280104031F1021280125162728001D1227280004010728012B2B2B2B01103C2B2B2B2B2B81818181015D005D001615232627262322020336373633320415140223220011103712211236353426232206151416330347BDB21023418497B20A3E5E566AB4010CFEEBC9FEDC417D014C818D7EA674AF9F8D059EF98455305AFEE9FEFC5B2D28E6E4C3FED301310169010BBA0164FADDBF826EC79A9B88B90001004B0000042F0580000F00534036050B1902380B3A0C390D4A0D550256046202B7070A7C0DB40DC50D030209010D0E3A000F04090C020D0800006F0E083809AC0E1147101076C418D4F4ED10E511123939003F3F3CFD3C391239015D31305D01150602070607060723121336372135042F45E558572D1D2EC744E88997FCE805809D43FEB4C0BB9A63DC019A0196EEADB50000030042FFD7041A059C000B0017003200CB4047560157095A0F5913640165096B0F691377250949107B197623722573277C317C32881987208727882E883198190D47083208250E0225320B3511112C05351E0517352C0D023821B80186B70E38296F2F08381BB80186B514382F3447331076C418D4EDF4ED10F5EDF4ED003FED3FED12392FED39390111123912393130437940352A2E1C201216030D162D1428000C2B0E28010A12082800061D082800041F022801152E1728000D2A172800071C0528010320052801002B2B2B2B012B2B2B2B2B81818181015D005D00363534262322061514163312363534262322061514163300272635343633321615140706071617161514022322243534363702A48680838274966688A5AA8581A3959CFEB52A4FE8D5CEEA44265059335FFEE8D1FEDF7C7A0340855C5086865A6572FD3B87868B90938270A302A02B5080A0E6D99186532F2D293564A0BDFEF9E3D87FB9310000020049FFD80411059A001B002700AB402E19052B0528164806580568058919881A981A09460807212727350A0A182135100504351BC7180D07023C071E3114B80155400B0D00291B8124380D2947281076C418D4EDF4ED10F5FD397D4B52787A2F18003FEDED3FED12392FED1112393130437940341F26191A0B13010312250226220F24280020111E28010319002800260B242800230E2128011F13212801011A042800250C2728002B2B2B2B012B2B2B2B2B2B81818181015D01161716333236130E012322023534123320131615100702212226350036353426232206151416330110086B374581B6263CB166CFF1EEE8013977424F83FEC7D2DA0232B19F7B849B8895015A95391ED701495F4D0102CBC30128FEE69BE9FEF9CBFEAEDCA601268DB09E9BB1948CA500000200E3000001B40421000300070032401A052A07032A0006070A0917171A05016404001908096421787C182B2B4EF4
+
+4D3CFD3C4E456544E6003F3F4DED10ED31301333152311331523E3D1D1D1D10421DAFD93DA00000200E3FED001B80421000F00130039401D00230F0A6408132A1006080A1517171A0734120A641000081914787C182B4E10F44D3C3CFD3CED4E456544E6003F3F4DED10EDD4ED31301736373635342627233533151407060711331523E3461B0E01016DD51F3482D5D5D10D502A3205070CDACA6B4876170551DA000001001CFFED04AD04280006006A4040570367038703030020120303020220120100010620120304030420120505060306040200030505010106050A03000104020503011A08060019070888215FB5182B2B4EF43C10F6173C111239003D3F3F111217392F044D1887102B10872B87102B87102B3130015D130115090115011C0491FC4403BCFB6F025E01CAB4FE97FE96B401CB0002005C00DE046F03360003000700274015012000CD07200604001A0907021908095C213F52182B2B4EF43C10F63C002F4DEDFDFD31300115213501152135046FFBED0413FBED0336A8A8FE53ABAB000001001CFFED04AD04280006006C40425800580368038803040020120302030620120303040420120506050220120101000306040200030501050506010A03000106001A08010405030219070888215FB5182B2B4EF4173C10F63C1112393D003F3F111217392F044D8710182B10872B87102B87102B3130015D0901350901350104ADFB6F03BBFC45049101B6FE37B4016A0169B4FE36000002009C0000041705D000030020009C4047281248135813650D750D05690C790C0226080F100D150F0B091815120D0B04201057012A030A20CA1B240601120F31101F0164030309201838091A221F3120192122D3216348182B2B4EF44DED4E10F64DED1112392FEDF4FD39003FEDED3FFDE611173901111239123939111231304379401A191E04081D251C051F41001A071841011E041B410119081B4101002B2B012B2B2B8181005D015D253315230012333216151406070E01152334363F0136373635342623220706072301EDC7C7FEAFF4D5C5ED57846039B24473502416287587A7402405B2D0D004C90107E1AF6A84805D817E8FAF714F2225414662907C4582000200E1FFD5073B05E5000B004A00CA40593636344846215548680967276A3E6742783DC819C6450B192B1939283D3803380E3721060839150A2742460B47115800550358216616C80DC80ED714D715D7410E0B0A190A260A560A04FE0A010A2D2E2F2C200A0302083508B80190B31A234A02B80190B22D293BB80190B51303474A4643B8019040114A090A052D2E1D2E383205352632260F38BD018F0017003F018F000F0732852FEDDDED1239392FED2F1239DD2EDD1239003FFDD412393FEDD4C4ED10D43CFDC411121739870510C0015D7131305D005D5D00262322
+
+02151416333212350003261110373621201716111400232226353436370E01232226353400333216173733030E011514163332363534002120070611141716213224371706042304E1534972A756418797FD97E2B5DCF4019B0164CCBFFEEFA9635E040335A2567B990105966685043293850F0E372372B5FEBCFEEEFE84C9ACA4C00163A6011E77425AFE9AD703BB63FEF3856267013B7FFC580105D101120146E4FEB4AAFEF1E4FEBD5F430B180D735FB28CC701307653A8FE4A333E182D29EEC0E80109DEBDFEE2FAAAC969595A508C000003001E0000053D05BD0002000A000B00DA40504801580168010388039704980AA90AB809B80A06280A010007060601020809090102080A000705018C01030420140A0A251209090114050525120606010B0B0503090A040605010B02010300021E0708B80159400904030206090A030508B801A840120D0D17171A059E019E0A190C0DA1218C5E182B2B194EF4184DFDFD194E456544E6464418003F173C3F3C4DFD3CFD3C11393F011112393912393911392F872E2B7D104B5158B004C01BB004C459872E182B7D104B5158B003C01BB003C4592B1112393912393987103C3C07103C3C3130015D5D005D010B01133301230321032301038EDFED85E10215DA95FDBB9FCC0290025A0289FD770363FA4301B8FE4805BD000300970000050405BD000A00150028008240385A0D5A116A026A0D6A117A02772107490D4811021D081F0F041F131E000027081E17020B1E270804311B690F31231A2A091525281619292AB8015FB3217666182B2B4EF43C4DFD3C4E10F64DEDF4ED003FFD3FED12392FFD3901111239313043794012181A0508192506260718042B01051A082B01002B012B2B2B8181015D5D013237363534272623211101323736353427262321110321201716151407060716171615140706290102C47E466E754282FE9D01ADB74E318F4C7DFE75C3027701026D404F294D7138635985FEDEFD93035023378F90321CFE39FD5A6A435FA03A1FFDFB05139A5B778B592F272B3660A98E73AC0002005AFFDA057105E5001D001E00B1403B1B0597019605031F011F0482018705891305530803861D111115063A1D030C3A15091E021E1E190331023B1031111A20093119191F20A1216A66182B2B4EF44DED4E10F64DEDF4ED12392F003F3FED3FED12392F10ED31304379403A001C172513260E251B260B160932000D1410320112110F10071C0932000500033201010204030A180C32000F120C3200081A06320104010632012B2B2B2B01103C103C2B2B103C103C2B2B2B2B2B2B815D015D080117232E0123220011101233323736373306070621202726111037362123041E013411C221C5B2D9FEF5F1EFDC733D1EC21A92AFFED7FF00AEE5ACBA01472805E5FEDABB8EA6FECFFEC5FEFE
+
+FEBFA95991E89DBD9BCD01AC0145D0E2000200A50000056305BD000D00180067401F871196120232080B1E0F02001E17080831131A1A0D250E19191AD6217689182B2B4EF44DFD4E10F64DED003FFD3FFD3130437940260116112515260607050704070307020705060A10083201011608320109120B320107140032002B2B012B2B2A2B2B815D2532373637363736351002232111032120171611140702290102D06541744A3B1A0FD9F1FE9FC80253012FA795589BFE86FDAFAA15276F598B53470111012EFB980513D7C2FED1EABDFEB2000200AF000004ED05BD000B000C004E4024071E04040B031E01000209081E0A0B080C020C0C02000669023B091A0E03082500190D0EB8010BB3219589182B2B4EF44DFD3C4E10F64DF4E41112392F003F3F3CFD3C3F3CED12392FFD313013211521112115211121152101AF042FFC93032BFCD5037CFBC2021F05BDB4FE42AAFE0EAF05BD00000100AF000004AA05BD000900394018071E040409031E0100020908066B011A0B03082500190A0BB80157B32195DC182B2B4EF44DFD3C4E10F64DE4003F3F3CED12392FFD313013211521112115211123AF03FBFCCC02D1FD2FC705BDB4FE42AFFD640000020063FFD905A105E50022002300D1403E1B0686018502031D011F058601891CB6200540080F04151603106D167E16020F16110D04862210111E13121215073A220315080D3A1A0923022323031E12B8014B4010030431033B1025131A250A311E192425B80167B3216A70182B2B4EF44DED4E10F64DEDF4FD10ED1112392F003F3FED3F3FED12392F3CFD3C10ED111239395D0111123939123931304379402C1B21000C1C25202601250C1B0A320008210A32000600043201020305040B1D0D3200091F0732010502073201002B2B2B01103C103C2B2B2B2B2B2B81815D015D00171613232E01232200111012213224132135211123270607062320272611103736212703E697DB31C524E2ACCCFEE9E60104C7010503FE3402858030654E83CAFEFBBCCDC8BE012E2105E35073FEE0A193FECEFED1FEFAFEB7E70102A5FCEEBD6F2B4AA9D401720171DAD002000100A10000052F05BD000B003F402108091E0302020401020A070804072506051A0D010A250B00190C0C0DA0217670182B2B104EF43C4DFD3C4E10F63C4DFD3C003F3C3F3C392F3CFD3C3130133311211133112311211123A1C902FCC9C9FD04C905BDFDA1025FFA4302AFFD51000200C90000019205BD0003000400314012000203080403040617171A04012500190506BA012C0021012BB170182B2B4EF44DFD394E456544E62F003F3F3F31301333112313C9C9C96505BDFA4305BD00010023FFD9036D05BD00130042402209061906670B7A0697020578040109090412020D9204091125001A150A2507191415B80151B3218C
+
+70182B2B4EF44DED4E10F64DED003FED3F12392F5D31305D011407062122263D013315141633323736351133036D3766FEE2A5EABB6B719F311EC501B6BA67BCB3E5696978796D43BA03D3000001009C0000054E05BD000B00BA407A06052505270848075807770588039803B803C803E7070BA603A60402050528082909A809F9020507050708050903D4020105050608080709020228030325120404090605052512080807050409080705040302070609080502040A040301020A0706086B067B06E80603061A0D010A250B00190C0DD621765E182B2B4EF43C4DFD3C194E10E65D18003F3C3C3F3C3C1217390111173908874D2E2B057D10C5872E182B04104B52787AC510083C083C31300072715D01715D1333110121090121010711239CC202CC0113FD9D0274FEFDFDFEEBC205BDFD3402CCFDB0FC9302E1E1FE00000001009C0000044B05BD000500314013000203021E040508031A070102250500190607B80153B321765E182B2B4EF43C4DFD3C4E10E6003F3C4DFD3C3F31301333112115219CC702E8FC5105BDFAF2AF000100970000061705BD001300CB405944014B03020601090316011903D7010513011C03140B1B0C57015803D401DB03D40BDB0C0A040A040D45028602045102970202290A280D380A380D4702570276020725640D0A0203120301020B0C120306081517171A040405B8019B400D0A1F030B06FD0C0102FD0D1F12B8019BB6130019147670182B4E10F43C4DFDE419F43939F4393918E4FD3C4E10456544E6003F173C3F3C1217394B5279B10D0CB801AAB40201020A0BB801AAB202020387054D2E7AFD047DC487052E7AFD047DC43130005D727101725D71132109012111231134363501230115141615112397011D01A601A3011ABD04FE5DC5FE5A05BE05BDFB2604DAFA4303632DD077FB2904D72D36DD34FC9D0002009C0000052A05BD0009000A007640143701380602070117012701470158020507010202B8019B4017120606070207080301020806080A030A0A010608020302B8019BB505041A0C0708B8019B400A0900190B0CA0217670182B2B4EF43C4DFD3C4E10F63C4DFD3C11123939392F003F3F3C3F3C12393904872E2B877DC53130005D015D13330111331123011123019CEB02E6BDDFFD0FBE023A05BDFB5A04A6FA4304A5FB5B05BD00030050FFD505E805E5000F001B001C008A402C8705C700C701C302C808C90A064308153A0F031B3A07091C021C1C0B1231031A1E18310B191D1ED8216A66182B2B4EF44DED4E10F64DED12392F003F3FED3FED313043794032001A0D26012509250526160E18320014001232011A081832001006123201170C1532011302153201190A1B320011041B32002B2B2B2B012B2B2B2B2B2B2B2B81005D0017161110070221202726111037122100123510
+
+002322001114122103049BBB92A7C4FE95FEADC2AD94BE0174011BEBFEF1EBE4FEE0F701150E05E5FAC3FED0FEB7DAFF00E0D8014A012AD40110FAA20179F50103013CFEC7FECFF4FEB1055E000200AF000004F805BD000A001400614035690C6912790C7A12044814581468147A140407081E1110100A010E0F1E0100020A080206120C0409141431041A160F092500191516B8010BB3219589182B2B4EF44DFD3C4E10F64DFD11121739003F3F3CFD3C1012392F3CFD3C015D31305D132132161514062321112300272623211121323635AF0295C4F0D6DEFE32C70380784273FE74018C86A705BDDDC8ACFFFD9304B93A1FFE0372900000020050FF8B05E805E50015002700E4406B69036A1579038513961BC71B064A1C591B5A1C64157515781CB719C81A083808181B021B191901151A1B1A1A1A0001190100191E121A1A00191A191A1B18150206240001111E150002050D191A1B18042127213A0D03273A0105091E31111A29243109192829D8216A66182B2B4EF44DED4E10F64DED003F33ED3FED111217391112393939011112393912173908872E2B087D10C50187102B3C2B3C87102BC42B3C313018437940281F2606100B260F250725220C243200200E1E32012606243200230A2132011F102132012508273200002B2B2B012B2B2B2B2B2B8181015D005D2507270E01232027261110371221201716111407060704363727371736123510002322001110002105DC64E352BF71FEAAC2AB94BE01740185BB9223357EFE576C28A164C05B41FEF1EBEEFEEA010B01020479AD2D36E0DA0148012AD40110FAC3FED08E83C87E1A11197E7B95680102760103013CFED1FEC5FEF7FEC600000200B40000057805BD0009002700944012070D49014805590158056905641478050816BB01300119001B011C40422321202660127112751403121E1F141C1503211E161404261224251E0009091B071E0B02261C1B082025151F251603310F691B1A29082625270A192829D6219566182B2B4EF43C4DFD3C4E10F64DF4EDD4EDD4ED003F3C3C3FFD12392F3CFD3C3911173901111239391239395D1112392B3130015D013236353427262321110321321716151406071E011F011617161715232E012F012627262321112303478CA3723D66FE1AC702A8A86DCF6D6256570507030B122EF40A0C040C0764397AFE3BC7031C70929D391EFE0A02A1315EFD84A833237280C55429461421133C56F590311BFD8A00020060FFD504F605E5002F003000FE405E290F27232626360E3521472662267A0E7724096B08180E172502590E680EAA22030A0E3A2224220A03041C1886142F2F2B1C3A1403043A2B0930020A0E081124221F28303011182517490825281A321F25114900252F193132A0216A89182B2B4EF44DEDF4ED4E10F64DEDF4ED12392F
+
+1211393912113939003F3FED3FED12392F10ED111217392EFD335D7131304379404D282E111F0008022602262D2506251A26032C002B002D2E032C002B00052A082B011D131F2B001B15182B011918012D042B0009270B2B01250B012E042B000729042B001E121C2B0119161C2B01002B2B2B2B10102B2B01103C2B2B2B2B103C2B2B2B2B2B2B818181005D0116171633323736353427262F012627263534243332041523262726232206151417161F01161716151404232027263701011E073463FA705CB24B4CA2C7C3518C0112FBE70143BB0F315BDAB09A5A3BD0CE95518CFE9DEBFEEE9B9B03024D01DA7D4E92203EA0783332252D2C355CB7C6FEDFF5763F7394626C3220302F223B67C4F4D28C8BEE040B0000010021000004C905BD00070034401A01061E00070204080917171A00FB0203250504FB0619088C5E182B4E10F44DF43CFD3CF44E456544E6003F3F3C4DFD3C3130011521112311213504C9FE11CAFE1105BDAFFAF2050EAF00000200AAFFD9052F05BD00150016003C4023170527053810030A0002053A1009160316161409250C1A18012514191718A0219570182B2B4EF44DED4E10F64DED12392F003F3FED3F3C5D3130011114171633323736351133111007022120032619012101743C59D3FD5B31CA4986FE8CFE8C8549024305BDFC74A06AA0AD5E9F038CFCC7FEF192FEF6010A92010F0339000100340000053605BD0006008F40449001A0010240015401021601017805E6010267046805880403192802251203030400251206060501050203060300020504080817171A0402039E0500019E0619078E5E182B194E10F4184DFD3939FD3939194E456544E618003F3C3F173C123901874D2E2B872E182B4B5279400C01020100030401000102060587087D10C487087D10C43130015D005D717172090233012301011001A601A1DFFDE8D3FDE905BDFB1D04E3FA4305BD00000100250000077105BD000C0156409508090178077909780B870186040547014B02440348044D08420A8908870AC802C703C707C80B0C580B6707680B890286038607890B9902960395079A0BA902A603A507AA0B0F0808070A080B1908160A5707060B08040A023E284528052506060700250C0C0B090401030B020305060C050002080A0B0307080E17171A0705068640080304F40A0209F4800B0001860C190D8E5E182B194E10F4184DFD39391AFD3939FD39391AFD3939194E456544E618003F173C3F173C12173901874D2EED872EED4B5279B4090A09080AB8019A400F120101020405030406070908090A08B8019A400A12040403010102000C0B877D1008C5872E18052B087D10C5870810C5872E18052B087D10C54B5179B301010002B8019AB6090A0904040503B8019A400F090908040503040607010001020C0B870810C087
+
+0810C08710057AFD1808C4188710057AFD7D08C4313001725D5D71005D7213090133090133012309012301FD0115014CD8014C0115DAFE7ED1FEADFEABD1FE8005BDFB5504ABFB5504ABFA4304C2FB3E05BD0001002A0000053405BD000B00BC4070280136024702570357046703670476027808880186040B270B3702370538086805050203020103251204040508070809072512060506080907080925120A0B0A0201020301251200000B0205080B040301070604030201090A0300080A0604000205080B08090107091A0D0301190C0DB8010CB3218E5E182B2B194EF44D18C4104E19F64D18C411121739003F173C3F3C3C3C1112173901874D2E2B0810C005872E2B0810C00587102B0810C00587102B0810C03130005D015D212309013309013309012301011AF0020EFE13F901770174EDFE130205F7FE7402F102CCFDCE0232FD34FD0F025C0002002A0000054705BD00080009008F402A8804011428042512030203002512010102050802080701030403000207080903090904000B17171A0304B801004009060202050625010807B80100B500190A8E5E182B194E10F44DF43C3918FD3C393D2F1019F4394E456544E6111239182F003F3F3F173C1239392E3C05874D2E2B872E182B4B5279B7050402030800010204877D10C404877D10C43130015D133309013301112311132AE801A601A6E9FDD5C76605BDFD3E02C2FC93FDB00250036D0002002F000004B405BD0009000A006340361705180602010506062512000001010603040501021E0403020700061E0809080A030A0A030705041A0C03690900190B0CA0218EDC182B2B4EF43C4DE44E10F63CC412392F003F3F3C4DFD393C3F3CFD3C390111123939872E2B877DC43130015D37012135211501211521012F0385FCBD0443FC76038AFB7B0264A50469AFABFB9DAF05BD0000010080FE6D020005C700070035401C031C0010041C07120917171A0501580304200700190809F0216C33182B2B4EF43C4DFD3CF43C4E456544E6003F4DFD3FFD31301321152311331521800180D6D6FE8005C793F9CC930001FFBB0000029205BD0003004040219802010302021C120101000002050400030202010A011A0503190405D021DBB7182B2B194EE410F618003F3C4D3F3C0111123939872E2B7D10C43130015D1301230157023B9CFDC505BDFA4305BD0001002FFE6D01AF05C70007003E402000070102031C050410001C07120917171A06200201580003190809F0213C7C182B2B4EF43C4DF43CFD4E456544E6003F4DFD3F3CFD3C01113939313013331123352111212FD5D50180FE80FF00063493F8A600010078025E03D205BD0006006B4030680378038D030303040302041C120505060302021C120101000604030200050501040302010405D10600000817171A01B80152B5
+
+0519073C33182B194E10F4184DFD194E456544E618003F3C4DED17390111121739872E2B7D1004C4872E18052B087D10C4313000710901230901230102710161A3FEF6FEF7A4015F05BDFCA10296FD6A035F00010000FF000473FF650003000FB50146000205003C103C002FED3130113521150473FF006565000002FFC90449015E05DE00030004002C401604015A0200040617171A0400C902190506C9213CB4182B2B4EF44DFD394E456544E62F003F4DFDCE31300123013313015E89FEF4DF2D04BD0121FE6B00030052FFDC04470449000F003B003C00DD40382A30010A100B1B0C1C2733481069096A10073908120C09031B320724091D100C1D3B2B022E293BB73B023B322A2512100705081C2722171CB8018A4023171D1F07271D2E0B021D350B3C073C3C1C1407292AA8241A3E1B291C4A0F2738193D3EBC0197002100B9019600182B2B4EF44DEDF4ED4E10F64DE4FDC412392F003F3FED3FED3FEDED1239111217395D1112392EED2EED01111239111739313043794028363715220001192501360F2100181E1B21001620142101212200370221001A1D1721011521172101002B2B2B01103C2B2B2B2B818181005D015D2416333237363D010E010F0106070615013637363534262322070607233E01333217161511141633323637150E0123222726270E012322263534363713010E724E5F59962168326D62315301B43E150C837A8D3B210AA805F7A3BD767517250C1E112A2C265D2A160937CE7C95BDBA978ACF5A2C49A691151C060E0D1C2F67016C082C182D5C534C2A53C69B484898FD971C220303850C06422340486AB58895A41301E40000020076FFDE042505C20011001E0070402EA607A71CD71C0322080F1E02050000171D0507110A1E1D0B0B1427081A201A2E102E01290011191F208721BD5D182B2B4EF43C4DFDE4E44E10F64DED003FED3F3FED3F113911393130437940181216060A1606142601120A142601150717260113091E26002B2B012B2B8181005D1333113E01333212111402232227262715232436353426232206151417163376AF3BA460C8F9F6DA7A543239A6026691918D7BB92647C205C2FDEB4D51FEEDFEF4FEFEB03B234D897DE8BEA9DEB6D1975EB10002003BFFE103D0044E001A001B00A7402FA719019818A808AA18034A08119B14030314061D1A070D1D140B1B071B1B1710271201032702111A1D0A2717191C1DB80107B321727D182B2B4EF44DED4E10F63C4DED3939ED12392F003F3FED3FED12392F10ED313043794034001908250C150A26000E1310260112110F1007190A26000500032101010204030B160D26000F120D2600091806260104010621012B2B2B2B01103C103C2B2B103C103C2B2B2B81005D015D001617232E012322070615141633323637330E0123220235100033
+
+0702D6E317AF10727EAC4A308892708319AF1EF0BBD2FA0112D41C044EB0D76383A86DA0A1DC8977D5C50133E6011A013A0500020038FFDA03ED05C2000B001D00774032370E470E570EA704A91B05250814020F1D1000081D1D07130A021D170B052E132E102911121A1F0B271A191E1F87217242182B2B4EF44DED4E10F63C4DFDE4E4003FED3F3FED3F1139113931304379401A181C090A000101180B2600091C0B260000190226000A1B0826012B2B012B2B818181005D1216333236353426232206150017161711331123350E0123220035341233F692A17DA1A67A88A9018A53303DADA23FAC6FB3FEFAEFDE015FE8D7C9CBC3D0CA0237341E4B021DFA3E956358012DFAEA015700030048FFDA041A0449001C00240025010C40799708991AA71F03050E020F0514150E120F1514400C401408291A014B0BB603C701C603C71BD808D909D61FD823E817E8230BC711C712025C080521240F9A161D243906070716211D1C070A1D160B2507971CA71CB71CD71C0425160F251C05190A0C07110E270F1D27051A27242E072719192627D421A65D182B2B4EF44DFDE44E10F64DEDD4FD391239391112393912392F5D003F3FED3FED12392F3CFD3C10ED1112393130437940460023040503050205010504061F26111012101310141004060C25221B24260020001D26011E1D09170726000B150E26010D0E231A2126011E0521260108180A26000D100A2600002B2B2B2B01103C2B2B103C2B2B2B2A2B2A8101715D00715D5D00161716171615211E013332373637330E01070607062322001110003301262726232206070102B4D638361210FCEF0590978D543014B1074F3152794152C8FEEA0118E2011F0B284AAD7CA805012304476B55516C4AA2A3C55D36473B912E501C100123010601020142FE26754682B38A01DC000001001C0000021705D20017004D402B071D060A1D03010F1439160D06120A1917171A0E0D1129171207120F0E1F0E020EFC14191819FC21677E182B2B4EF44DFD5D39C42F3CFD3C104E456544E6003F3F3C4DFD3C3FEDD4ED313012373633321617152E012322061533152311231123353335B5233FB41124171C190B5220B2B4B295950542345C0202A4020155AE8EFC64039C8EA80003003DFE3B03E80449001F002D002E00B7404D36144908490958085909880CA91BA81DA927A62BB91B0B4008031622290EC40A221D1F070406291D190A121D0A0F2E072E2E051C032E162E2D29051A300C0E270D3E26271C192F3087217242182B2B4EF44DEDF4ED394E10F64DFDE4F51112392F003F3FED3FED3F3FED10ED1112393931304379402C23281A1E0B1124251026231E262600281A262600110B0E21000F0E0C0D251D222601271B2926000F0C122100002B2B2B01103C103C2B2B2B2B2B818181005D0017161735
+
+3311140706212226273316171633323736270E0123222411100033002623220706151416333237363501027C5E3335A63C70FEC9ADEC0EB70D273D83CF40260336987DAEFEFB0107BA0144A47FBE4625937CC24F2CFED104423E234387FC32CC76DA9BA548273C9256DD5250F7011D010D012EFEA1C0B25F9AB5BDAF6384022D00010084000003ED05C200160053402C0607070817071708270427137507750808130D0213150000111D0607150C0A0D290A1A180115290016191718B80106B3216242182B2B4EF43C4DFD3C4E10F64DED003F3C3FED3F1139390112393130005D133311363736333217161511231134272623220615112384B440335782E9532DB91E318770B6B405C2FDDC512139A3599EFD5102A37637589AD6FDC800000200840000013B05BD000300070036401C07E50400010006030A0917171A06010229070300190809AA216242182B2B4EF43C4DC4FD3CC44E456544E6003F3F3C3F4DED3130133311231133152384B7B7B7B7042AFBD605BDCC0002FFDAFE50013805BD00030011003A401E041D0E0E01E5020008061317171A00090A2904010708191213AA216242182B2B4EF43C4DC4C4FD3CC44E456544E6003F3F4DED3FED01313001233533013E0135113311140706232226270138B4B4FEA27931B4263FB00D1D1F04EDD0F93404235C04B6FB37753A62020300010080000003F805BD000B00A740645902013A08011902010706170657056705790678078705B903C903DA030A05050608080709030284029402A4020302391209090405060504066D12070708080705040305060908050204030A00000403060A07060A061A0D09020A29000B190C0DB22162B9011600182B2B4EF43C4DFD3C3C194E10E618003F3C3C3F3C3F1112173901121739874D2E2B087D10C104872E182B5D057D10C010083C083C3130015D00715D7213331101330901230107112380AD01CEE6FE6601B1E6FEB297AD05BDFCAB01C7FE6FFD62021C8AFE6E000100890000013D05BD0003002940150000030A0517171A0102290003190405AA216242182B2B4EF43C4DFD3C4E456544E6003F3F31301333112389B4B405BDFA430001008400000625044700260085403B0708070E060F1708170E170F2708270E270F4819560B670B0C23250A1A1D23190A02041725211D171D0D060700061B1C2503130A2817171A112914B80101B21A291DB80101400A00012E25292600192728B8010DB3216242182B2B4EF43C4DFDE410F4EDF4FD4E456544E6003F173C3F3F3C4DEDED111217390111123912393130005D13331536373633321716173E01333217161511231134262322061511231134272623220615112384B240345971804E2C243CA265D84E2ABB6B4D6A99B71A297066A7B4042F984F243D3F244656539C548EFD3702E86B508EA6
+
+FD9102BB6D324B9ECFFDC80000020084000003ED04490019001A005E4031B706C706020406140627147606740705140C021418101D05070006180B0A1A071A1A000C29091A1C012E18291900191B1CB80106B3216242182B2B4EF43C4DFDE44E10F64DED12392F003F3F3C3F3FED1139390112393130005D015D1333153E01333217161511231134272623220706070E011511230184AB4CAA68E4502CB71D307E40294A382D1BB401A7042F985E529F57A2FD5102A3623C640D1642357169FDCF0449000003003BFFD90421044E000C0018001900904033980896109916A504A808A610A916B808C808D704E50EE9140C3A08061D18070C1D120B190719191502270F1A1B092715191A1BB80109B321725D182B2B4EF44DED4E10F64DED12392F003F3FED3FED31304379402C001704260B1309260000110226010717092600050D0226010A140C260001100C26000816062601030E0626012B2B2B2B012B2B2B2B2B81005D241235342726232206151416331200111002212200351000330702E085304CBAA59696A3D6011EFCFEF7DDFEFC0112E70674010FA6965E94FCB2ABE403DAFEECFEF4FEFDFEAE012BFC010E01400500020076FE5504250449000E00220074402CA908A717022808201C110E061D15070F060E1D1C0B220E0227181A240A2E102E2129220F1923248721BD5D182B2B4EF43C4DFDE4E44E10F64DED003F3FED3F3FED1139123931304379401C161B00051A260426001B022601051602260101190E260003170626012B2B012B2B2B2B8181005D243635342726232207061514171633013315363736333212111007062322272627112302C6A72546BABB45252546BAFE2EAF36405B7BB6FEB7749A7952303BB479D3D2805CB1BB649A7C57A603B18E49283CFEE9FEFDFEA2965F351E49FDDD000002003CFE5503ED0447000E0020007A4033381848185818A801A705A81C0628081217030B1D20071306031D1A0B160E072E132E162915141A220E271D19212287217242182B2B4EF44DED4E10F63C4DFDE4E4003F3FED3F3FED11393931304379401C1B1F0C0D00020126021B0E26000C1F0E2600001C0326000D1E0B26012B2B012B2B2B818181005D1217163332373635342726232206150017161735331123110E0123220011101233F82745B2BC47272B49B875A7018F5B322EABB52D9F77ABFEF2FDC9017E5EA7B061978B5D9FCBD4023E43244695FA2602264855010C01120101014A000100890000029204470011004F40262703260D37034704040E0810020E0911090C270805070006110A081A13012E10291100191213B80145B321627E182B2B4EF43C4DFDE44E10E6003F3F4D3FC4FDC411123939011112393130005D1333153E0133321617152E0123220615112389AB15A46B05181D101B108892B4042FB9369B
+
+0203BE0302AF72FD980000020042FFD703B6044B002E002F012E408F38099805961299149815982A062824252736214621472447275624572766246726790C790D790E7623742474257426A61EA82C1303000B15052D042E13001A151B171C18152D142E280F0B6908262536250225220D0A042B1318C61C1D1307041D2E9A2B0B2F07090E100207002F212F1A1F18161827173E28260727281A310E1F27103E00272E193031B221A65D182B2B4EF44DEDF4FD394E10F64DFD3910F4FD3911123939392F111239113939003F3FEDED3FEDED111217397131304379404C012D022615251A26210E1F21000926072101032C002100052A0721011D121F21001B14182101200F22210021220E0D08270A21012625090A012D04210006290421001E111C210119161C2101002B2B2B2B103C103C2B103C103C2B012B2B2B2B2B2B2B2B2B81005D5D015D13161716333236353427262F01262726353436333217160723262726232206151417161F011617161514062322262701EF082544A864983D27738F894174DBB9F26B4302AA05263E99666945284E77C24269D9DEEFC70701B701505A3057575B4524161D24222A498198BC8E5A683D32474E40462A19131D2F2C45948FD0D9A002F900010017FFEF0209055A00180052B50D2E0AC00E01B8013F40250416391703060E0A111A17171A0301062900150E150F031F030203FC1619191AFC21677D182B2B4EF44DFD5D39C42F3CFD3C104E456544E6002F3F3F3C4DFD3CED10FDE431301333113315231114171633323637150E012322263511233533A8B6ABAB2615310D1E141F43277E5A9191055AFED593FD4538130B01028E0908816702C59300020080FFE303DE044900170018005E403AB814C81402091308141913191428067703D707070800050E0A00060D0A051D120B180718180B160D2E0A290C0B1A1A01291619191AD2216242182B2B4EF44DED4E10F63C4DFDE41112392F003F3FED3F3F3C391112393130005D015D0111141716333237363511331123370607062322272635112501381A3083BC4425B4AA0223346793E5532D01AF042FFD39523460A85A9D020EFBD19E3D2A5499528902D81A000001000B000003EA042F00060102402E4201C5010200670068026803670687048805A700A802084700480245044A0586048905C704C80508492873280708B80109B321677E182B2B4B5279B8FF70B40105042004B80183B703036D1202010205B80183401E06066D120000010506040301010502030603000605040A0817171A03AF02BA018400000184B301AF0619194EF4184DFDE0E0FD194E456544E618003F3C3F173C1239011112391239074D2E2B104EE44D072E2B104EE44D2B4B51794025022912030304002912060605010502030603000605040A0817171A020403AF050001
+
+AF0619194EF4184DFD3939FD3939194E456544E618003F3C3F173C12390507102B07102B313001715D005D7113090133012301DC011E012BC5FE6CC0FE75042FFC980368FBD1042F00010012000005A1042F000C0120407E4704AA09028E09014607490B87038A08850ACA02C403C607C908C60AC90B0B66076A08650A690B76077908760A790B85078A0B0A4607490B0247037700780503572816282B012B043B013B048F018F0406090401030B020305060C050006080A0B03070A0E17171A0705069B080304C40A0209C40B00019B0C190D677E182B194E10F4184DFD3939FD3939FD3939FD3939194E456544E618003F173C3F173C1217395D4B5179400C0529120607060029120C0C0B0587102B87102B4B5279B4090A09080AB8018B401312010102070604050529120606070908090A08B8018B400E120404030B0C00010029120C0C0B01874D2E2B87107DC41805872E182B087D10C505872E182B877D10C405872E182B087D10C53130015D71717100715D1B02331B013301230B012301D7CED1CAD2DBB4FEC9BBDAD3BBFECB042FFCB4034CFCB90347FBD1033DFCC3042F000001000B000003E1042F000B00A8405EAA080177077808A705A907A609A80B060202030101271200000B0203032712040504080708090927120A0A0B08070727120606050205080B04060001030403000607090A03060A0D17171A04010203050708090B0806D4000A190C677E182B194E10F418C44DFD1739C4194E456544E618003F173C3F173C1112173901874D2E2B3D1004C087052E182B3D1008C0058710182B3D1004C087052E182B181008C03130015D005D13331B0133090123090123011EE9F6F9DCFE960179E6FEF6FEFEE40179042FFE870179FDF6FDDB0192FE6E02250000020015FE4903E804490018001900CA406E8A158818A71803070617063812481258126707770377078C1498009705981597169717A800A8161048004B154717C915044405C605028705A600A601A705A8170524280518151716010006150C0B0F1D080E19071919161B17171A050001AF171518AF0C8F16191A1BD421677E182B2B194EF44DE418FD3939FD3939194E456544E61812392F003F3F4DFD3932192F183F3C3C3C123939014B5279401215150016166D121717180501016D12000018872E2B107DC418872E2B10087DC418015D71313071015D005D013306030207020623222627351E01333236373E0137013301030321C7268362429C809C26291E2F2A10322F10053E0EFE74CC011F01042F67FE91FEECAEFE66B40608A40D062118089424044EFC9803820000020034000003B404490009000A006C4042370648005700580157066700680167067705090105060629120000010A0A01060503050102390403060007063908090A0A07053E071A0C034A00
+
+190B0CB221725D182B2B4EF44DE44E10F64DE4003F3F3CFD3C393F3CFD3C390111123939392F872E2B877DC53130015D370121352115012115210134027BFDB4033EFD89028AFC8001CF8E0300A193FD05A104490001FFD5FE5E028005D700230072403E98069813A906A914A72105071317132713380A381F9614061F120C400D4D0C4D201F1F03162D15032D041315002517171A0316AE1A23910812C30C192425B80103B321DD33182B2B4EF44DF43CFD3CF43C4E456544E6003F3F4DFD10FD1239192F1AEDED181A011112393130005D015D05141617152E013D0134272627353637363D01343637150607061D01140706071617161501879C5DB2E9223EB0B13D22A3F8A1391F2543C1C04425059A830B7512ADC6CE6D3F731372156E3D72A3BCDC15720E80467C70965091121197538F00000100900000013B05D20003002940150200010A0517171A0300C10201190405C1217765182B2B4EF43C4DFD3C4E456544E6003F3F313021231133013BABAB05D2000001002AFE5E02D505D70024008A404E960A960B9619A70AA60BA619A822073924011E05040302052024160F0E0D05121806020C0F041208211E191604131C40134D124D2024241C082D091C2D1B13090012C30E18910420AE1C08192526B80103B3213CA4182B2B4EF43C4DF43CFD3CF44E003F3F4DFD10FD1239192F1AEDED181A111217391112173901111217391217393130005D015D0027263D0134272627350417161D0114171617150607061D01140607353E013D0134373637018B43251F38A201025C3C223EB1B03F22E9B16B8E2544BF022E9050977084447A0E72158B59B4A3703E7113721275406BCECAA813750E8F8B97905297110000010012014004B802D50022004B400D081F881E0214110603040B1B08BB0185000F00170185400E220B9C0F1C0B0C1A241B1C192324B80162B3215F8B182B2B4EF44DCD10F64DCD002FC4FDD4FD10FD01111217393130015D0017161F0116171633323637330E01232227262F012E012322070607233E01373E01330166203935DE33213528496612741993952D3E2447CC26511A54301C1D751128322A614102B405081557140A0F73548EEA120B1B4E0F1041265B53754A323000FFFF001E0000053D07190232002400000010008E0B08FFFF001E0000053D07CE023200240000001000DD0B180001005AFE33057105E5003B0112403A060A1836470A03060B1B351836570A550B69357835830186058513970196050C6C0831271632182E03863B111115063A3B030C3A3322231E8227B80131402E2E82186B331509233132331516062B22221B922B2B34140311370331023B1031111A3D093137193C3DA1216A66182B2B4EF44DED4E10F64DEDF4ED111217392FFDDD11121739003F3CF4EDF4EDD4DD10ED3FED12392F10
+
+ED11123939123931304379404C383A282D191D0D14000813260E25292539260D1410320112110F102D192B8401281D2B8401073A0932000500033201010204030F120C32002C1A2E84012A1C27840008380632010401063201002B2B2B2B2B01103C103C2B2B2B2B103C103C2B2B2B2B2B8181818181015D005D080117232E01232200111012333237363733060706210736333216151406232227262737161716333237363534262322060727372227261110373621041E013411C221C5B2D9FEF5F1EFDC733D1EC21A92AFFEEC421D2E465B787C353920362326152921251B34352C1623182366AFAFE9ACBA014705E5FEDABB8EA6FECFFEC5FEFEFEBFA95991E89DBD5A09514B4C6E0F0814510E060B0B1537202F0809298C8BDD01AC0145D0E2FFFF00AF000004ED07520232002800000010008D0C04FFFF009C0000052A0731023200310000001000D90A1DFFFF0050FFD505E807410232003200000010008E1C08FFFF00AAFFD9052F07190232003800000010008E1608FFFF0052FFDC044705DE0232004400000010008D3C04FFFF0052FFDC044705DE023200440000001000433C04FFFF0052FFDC044705DE023200440000001000D83C07FFFF0052FFDC044705A50232004400000010008E3C08FFFF0052FFDC044705BD023200440000001000D93C1DFFFF0052FFDC0447065A023200440000001000DD3C180001003BFE3303D0044E00390101405E9837AA3702370C4A334A345A335934683487019701A70809600821222630261531172D030314061D3907119B0D1D322D83178F32140B26831D0F2230313214052A21212A1D4F1A5F1A021A13331A03113610032702111A3B0A2736193A3BB80107B321727D182B2B4EF44DED4E10F63C4DFD3C111217392F5DEDDD11121739003FED3F3CF4ED10EDED3FED12392F1112393912390010D4DD31304379404437380E130009282508250E1310210112110F102C182A2101271C2A210107380A26000500032101010204030F120D21002B192D2101291B26210009370626010401062101002B2B2B2B2B01103C103C2B2B2B2B103C103C2B2B2B818181015D005D001617232E012322070615141633323637330E01230736333216151406232227262737161716333237363534262322060727372227261110003302D6E317AF10727EAC4A308892708319AF1EF09F471D2E465B787C353920362326152921251B34352C162318236C8E6A900112D4044EB0D76383A86DA0A1DC8977D5C56109514B4C6E0F0814510E060B0B1537202F0809299372A30104011A013AFFFF0048FFDA041A05DE0232004800000010008D2504FFFF0048FFDA041A05DE023200480000001000432504FFFF0048FFDA041A05DE023200480000001000D82507FFFF0048FFDA041A05A50232004800000010008E2508
+
+FFFF008F0000022405DE003200D700000010008D0404FFFF000D000001A205DE003200D70000001000430404FFFFFFEF0000024405DE003200D70000001000D80407FFFF00160000021B05A5003200D700000010008E0408FFFF0084000003ED05BD023200510000001000D91A1DFFFF003BFFD9042105DE0232005200000010008D1904FFFF003BFFD9042105DE023200520000001000431904FFFF003BFFD9042105DE023200520000001000D81907FFFF003BFFD9042105A50232005200000010008E1908FFFF003BFFD9042105BD023200520000001000D9191DFFFF0080FFE303DE05DE0232005800000010008D1804FFFF0080FFE303DE05DE023200580000001000431804FFFF0080FFE303DE05DE023200580000001000D81807FFFF0080FFE303DE05A50232005800000010008E180800010050FEB8041505BD000B002B40150A07002006017A0300067904092F030A79000D470C1076C418D4F43CFD3CF4003F4DF43CFD3C2F3130133521113311211521112311500182C00183FE7DC003719D01AFFE519DFB4704B90002006F033B02CB0597000B0017002B40150E05140B041917171A11021708191819CC21BB48182B2B4EF44DCDD4CD4E456544E6003FCDD4CD3130001615140623222635343633021633323635342623220615021DAEB57885AAB37CC272504D73714F4F730597AF7E82ADB47880B0FE837271514E72715100020068FF13041A04FB000A00310120407235034A177A1679170400180519360F4B0D492C560F5A17582C660F68166C17760F0C3408191C28280F101C28181C191C290F181C292910031D0404070D2B1C2A0E2B28271918100D0C04030A0A14272B250319211C041814100C31070E2A2AA71229290F2A290F0E04140A14142531071D0FB8012440183107219B2AE41C1D250B1427132E202721870A272E334732B80732851076C4D418EDF5EDF4ED003FEDE4ED3FE4ED1112392F0111121739872E2B7D10C50011123939123939111239391239390111121739872BC4053C08C42BC487102B3C072B3C2B3C053C2B3C87102B3C313018437940222F301D24080923261E251D2420260122211F2008300A26001F221C2600092F072601002B2B012B103C103C2B2B2B818181015D005D00171617132E01232206150016173733071E01172326272627031E0133323736373306070623222627072337260235100033011E35203EDD0C20197EAD01552E1735533777860CA80A1E2343DF13201E884B2C20AD1F4981F3252E1B3E55459A800109ED016F62422D03070406E6BE02430505B7CA31B9853B3A3E19FCEF06065E37709562AA0707D0E8470119AE0100014500010038FFDC044405BB003F00D74057082818282828033A08003F3334003F0829070B031D102023032D3A262E3922331617342900033B33
+
+2C2F2208462109093F17CA1A2413003F0B2C243BB82F36380B22224041172716345C08263603431D381022084147401076C418D4F4FDF6ED10F5DDED1112392F003FFDFDED3F3FEDED12392F3CFD3C11123912173901111239123939113939123939111217391139390010C910C931304379402A0B1F0E0F0D0F02061F0C1DC8001B121D410019141741011E0F20C8001F200C0B1C111A410118151A41012B2B103C103C2B012B2B2B2A81015D373E0135342726272335331426272E0135343633321617233426232206151416172115211E01151406073E01333216333237363717060706232224232207060742718A0D0813DD9D430B0A0EFEEDDFE503B98D908C902D490148FEE50A09788045864048ED252F27183153382C49523CFEE5524C44283F764FBF70202B1B2F6805871F1D4D2C9CF7F4DF979D9369346E8D682E341C64C360232947120B23872D16235C1A1026000002004BFE50041505BE0040005200D640720626154126132314351331143A353B374613461447414643571355415A4A0F061D171D2A37032C326641694A75417A4A050323012413231124043C4A40102F0E19422C1C4A49415204454E3019241006494A41523B35131708193C193C06232824231F0E0B240602020736062C361C453606BA0188001C0187400915B3390E3640243623B80188B24E3640B80187B3395447531076C418D4E4EDFCED10ED10F5E4E4FD10ED10ED003FCCED3FCCED11123939111217391239111239011112173911123939113939123939015D005D3130015D005D12363332171617232627262322061514161716170415140706071E011514062322272627331617163332373635342726272627262F012627263534363726272635013637363534272627250607061514171617C2C7A3F05B3003AF071A2F765E6325254ABD0150482962353AD2B2EB5E340BB2081B30774E2F581B101D1058342FB26A2D4F76602C181B021A3B1C32352165FEDD3B1C350D194404F7C79F53855F2D52594A2B451A336ABCD27759334631744387C5985296622E5315276C2E2816180D3C2320774734596F609B3B282E3A41FC7122223B574E37223EB2201E38502B213D2C0000010121020002DB03BA000B002DB90000013EB5050D17171A02B8013EB308190C0DB8013EB3216C7C182B2B4EF44DFD4E456544E6002F4DED3130001615140623222635343633025E7D7D60607D7D6003BA7C60607E7E60607C0001FFF5FE95042905BD00100035401D0105060D0F03370D000E06910404090191000E1A1209111288218AA4182B2B2F10E6D4ED12392FED10003FFD3C10CD2F3C3130012311231123112602353437362901152303AC93E793D5D54882012A02407DFE9506B4F94C0379030123AF9474D274000100C7FFE3045205D300320084404D67056810
+
+7302770504491B4829550E6507660A660E7507760A770E090A1B291B2215231F0A2624221F1F1F322C240401320A15182414110B154323231B30292907301B270E1A34302900193334B80108B321777B182B2B4EF44DED4E10F64DEDF4ED1112392FE6003FC4FDC43F3FED12392FE4FD39E5111239011112395D3130005D131037363332161514060716171615140223222627351E013332363534272623220607351E0133323635342623220706151123C7996698CFDE5C4A5B3E54E1CE302F231828196CB172475F112D1712130B916F79789B351EB40400011E6F46C9A5749825174C60AEC6FEE604069C030488AEA9482C0403A1030293516682703F87FC000000040015000005D005BD000F001F0029004800BB400D381138153719371D0444083245B80191B324244723BB01910048000F0191B41B023B4707B80191B5130A32292446BB018F00470040018FB2363A29B8018FB22E3A0BB80191B31F024703B80191B1174910D6EDCCFDEDDCD4ED10D4ED10FD3C1239003FEDDC3C3FEDDCED12392FFD393130184379403200220526092501250D260614035B0008120B5B01001A035B000E1C0B5B010416075B000A10075B0002180F5B010C1E0F5B01002B2B2B2B012B2B2B2B2B2B2B2B81005D000706111017162120373611102726210007062120272611103736212017161124262B011133323736352732171615140706071E011D0114161F01232E012F01353427262B0111231101ECB9B8B7B801070107B8B8B8B9FEFA02DFD7D7FECFFECFD6D5D7D6012F0131D7D7FDE16B7679805A2D53CE96467D4F2A4B5F5804050585010201034C2D71708E055ABAB9FEFAFEF8BABABABA01080106B9BAFC56D8D8D8D70132012FD7D6D6D6FED0F83CFEDC12215DF51D34986C331B0C0F803D3B1C400A0A0408051A408C2D1AFEC2032600030012000005D005BD001B002B003B00A44010382D3831373537390437080C0C080210BB01900008002B0191B337021B17BB0190000200230191B22F0A14410A018F0005000D018F000C001A018F001B00270191B33B02051FB80191B1333C10D6EDCCFDEDDCEDD4ED10ED003FEDDCEDCC3FEDDCED1112392F31304379402A1C3B22301F5B001C361F5B00242E275B012A38275B012032235B00262C235B001E342B5B01283A2B5B012B2B2B2B012B2B2B2B81005D00062322263534363332171617232E0123220706151416333236373300070611101716212037361110272621000706212027261110373621201716110443BC83A5EAD3AA6B56950D79096C6791412A8780526E1679FD92B8B7B6B801060106B8B6B7B7FEFA02DFD7D7FECFFECFD7D7D7D701310131D7D701CB95ECC4B7F62B4DB34B6E82536089BB57530308BAB9FEFAFEF8BABABABA01080106B9BAFC56D8D8D8D801310130D6D6D6D6
+
+FED0000200ED02E806E305BD000C00140093401048015801680178069806050702010602B801904009120607060800010900B80190401F12090908010906030E130B07080504130E111402000E020702060800090106BE018F00030192000101920009018FB20C1012B8018FB2130D1510D6DCFDCCDCED19FCFC18ED11123939123939003F3C3CDD3C10DD173C111217390587102B10877DC41887102B10877DC43130005D011B0133112311032303112311053521152311231104A1B9BBCE85C974CA85FD1B026AED9005BDFDF90207FD2B0249FDB70249FDB702D5797979FDA4025C0000020050044901E505DE00030004002C401604025A0300040617171A0400C902190506C9217752182B2B4EF44DFD394E456544E62F003F4DFDCE3130090123130301E5FEF58AB72D05DEFEDF0121FE6B0003FFD7044901DC05A50003000700080035401C0803072A050500000808010401C240008006C20419090AFE213F48182B2B4EF44DED1ADE1AED1112392F003F3C10FD3CCE31300133152325331523050121BBBBFEB6BBBB010305A5D0D0D08C0001005CFFED046F042800130096405F58086810B702C71304020E010712030B040712060A050712090A0508110C0B0408110D0E010811100F000811130F00071212070720120808111211080704000A12110F010E20000FCD0A040B20050A08071517171A04005C0E0A19143C33182B4E10F43C4DFD3C4E456544E6002F3C4D2F3CFD3C10FD3CFD3C10D43C0111121739872E2B7D10C5010F0F0F0F0F0F0F0F3130015D0115210321152107233721352113213521373307046FFE897401EBFDC96DAF6DFED3017974FE1302396BAF6B0336A8FEFBABF1F1AB0105A8F2F2000200100000079C05BD000300130094404E3700371187008701040111120001110F130012122512131304120400030F1310111E0201600B1E08080F04061E001E0504020D0C1E120E13030F08030F25070C0C14150A69063B0D1A1513191415B80178B3218C89182B2B194EE41810F64DF4E41112392F3CFD3C003F173CFD3C3F3CEDED1112392FFDF63CFD3C0111121739872E2B7D10C50111123939073C3C3130015D090121112521152111211521112115211121032302E1FEEF01D8FEBD0524FCE402DAFD26032FFC0CFDE3A3D80512FD4A02B6ABAFFE3DA6FE0AAF01B4FE4C00030042FFD505E805E6000B00270032012E40A01718182647004A2857005928573107180E171C4A09470B54005B09570F591D57255A2856315932670B770B0E3208181D321D0E1D311D19190D0A1E1B1D271D0B1D1A0C0E1D1A0D311D1A1A0E0B1D27271A0E27181B041F1132310B0A042E06181B0E2704152331320A0B04022B190D191A0DE0120C0C1A0D0C1A182B3A150319030C090D27023A2309191A1B0306311F1A340C2E31113B0D
+
+193334D8216A66182B2B4EF44DF4FD394E10F64DFD1739003FED39393F3F3FED393908872E2B087D10C500111217391112173901111217391112173907102B3C07102B3C072B3C872BC42BC42BC42B3C87102BC42BC42BC42B3C313018437940222C2D2022121403051326212604252C142E320003220632012D122B32010520023200002B2B012B2B2B2B2B81818181015D005D24163320373635342726270901273726023510371221321617371707161716151007062122272627002726232200111416170101F9A48F010C8361261529FCFEFECE42AF524F9CBE0163B1F7529A409D392F3CCDC8FEC7BB8957520312396784E1FEE428350307D14AE0A6E8826D3B46FCB2FEC53EB46B010B930130D80107594DA53DAD466B93BFFE94DED93F284D045C1C33FEC5FED15FC04F034E0003002A015605780467000B0017003300BC404F821095109726A510AB1205380F3833482558256824961895199D269932A6070A4408A325AD3302253302080E2408241C2F0224291F142422073517171A0B242CF52533053611F517241F19343C33182B4E10F44DEDF4FD3939F4ED4E456544E6003F4DEDF4EDDD3CEDED111239395D3130437940322A2E1D211516090D0001092E0B1B010D1D171B001521171B00012A0B1B010A2D081B000C1E0E1B001620141B01002B021B01002B2B2B2B012B2B2B2B8181818181015D005D0026232206151416333236350416333236353426232206150506070623222635343633321617363736333216151406232227262704E0695C5C92955A5A6AFBE774495CA0AD584C6802003333607E99C0B89D65A144423D5C839FB2AF9C79554C37034282C41F21CF88687D77DB2217C6846EA4562E57DAAEA1E67A86783654ED999DEE4D42700002005C0000046F04150003000F004CB900070189B40905200C0FB80189401C0E4500032001020A1117171A0A007A080D20070E7A040219103C33182B4E10F44D3CF43CFD3CF43C4E456544E6003F3C4DFD3CF6FC3CFD3CFC01313025152135113521113311211521112311046FFBED01B4AB01B4FE4CABA1A1A1018C9E014AFEB69EFEC2013E000002005A0000046D04280003000A006D403C460656060209080820120707060A040420120505060A0906030108070504040C00050A0485090706850803022000010A001A0C01190B0C5C213C33182B2B4EE410E6003F3C4DFD3C19D618FD3939FD3939011112173912173904872E2B7D10C5872E182B7D10C53130015D2901352111150901150135046DFBED0413FCC2033EFBEDA10387B4FF00FEFDB40161A90002005C0000046F04280006000A0076403F4905590502090A0007080C01000020120606050203032012040405060504030400020C01010600850204058503070A2008090A011A0C00190B0C5C213C33182B2B4E
+
+E410E6003F3C4DFD3C19D618FD3939FD39390111123912173904872E2B7D10C5872E182B7D10C5011139391139393130015D130115013509021521355C0413FBED033EFCC20413FBED0428FE9FA9FE9FB401030100FD2DA1A1000001FFE10000047B057D001600CC405E0801380157016A01780186019601A4010804140508030713060803121306161115140516110102010002961203030801000102009612161611121115030D1608070403030C0110000514BE0613EF0A0FBE0910100D0203160300040D0C06BB0195000A00130195B20F0103BA0193000A0194B3010C250FBA0194000D0193B3161847171076C4192FFC18ECFD39EC19FC3D2F1810E410E4003F3F173C12392F3CFD3CF43CFD3C111239011112173911121739872E2B087D10C505872E182B087D10C50F0F0F0F3130005D1309013301331523072115211123112135212721353301C0016D016FDFFEF7AFFD81015DFE8BBDFE95015380FEFEB4FEF9057DFD5D02A3FE4388DA87FE2901D787DA8801BD000001FFB4FE5A044E042D001A00A140591612A7120206000812071A1600171A270E370E470E080B100F0F0C17041818001A191929121818000C0F0F29120E0E0D1A1817031B100F0E0C0B00060D040A10080C0D1A0300060F0E0A17081D140B19180E0D1A1C04191B1CBA01980021012EB17D182B2B4EF41910E618003F3C3F4DFD393F3C3F173C1239390111121739121739872E2B7D10C4872E182B7D10C487100EC4C40710C40EC4015D3130005D01030E01151417163332363713330323370607062322262703230101B1A3040313236191C91F80B7E6AD2A16487B962F621761B90144042DFD0B11190F301C33D58E024AFBD3B42C3D672216FE3E05D3000002006AFFDA040305E7000B002B00AF4031480D580D024A081819050B0E0802182B191D152B1E08082515361D01021D250B2305E7210E1F114C211A2D0B4C28192C2DB80108B3213C33182B2B4EF44DED4E10F64DFDE410FD39003FED3FED12392FED111239123911123901111239393130437940361E2A1214090A000423261F25132601260B1B000324054101141E114101092A0B41000027021B00042202410012201541010A29084101002B2B2B2B012B2B2B2B2B2B2B81818181005D0016333236353426232206150016173E01353427262322060727363736333217161110070221222635341233012E7F576A9B81567391015B8C2F01031A358424341B8239233A42D472658299FEFBA5D4F0C1010B95D9857A84D47C01FC6662294C14877EF91C189F1F0C14DEC4FEC9FEC9EBFEEEFBB8B2013F00010028FED404A105BD000B0094405C77017707D800E800043706370877068A0186089A019508A506A607A608BA07CA07EA070D0A08190718080307080706082912000001060707291201010207
+
+08070101070B02062003000008200B01580807060104050205090D02000C4E10D44DC44E10D64DC411121739762F18002FFD393FFD391139393D2F183C08872E2B057D10C5872E182B087D10C5313001715D005D170901352115210901211521280281FD960443FCAE026AFD820385FB878402DC02B8ADADFD48FD29AD000001001CFED405AC05BD000B0032401A02060A1E0B000704042503001A0D0725080A190C0DD7216C7C182B2B4EF44DD4ED4E10F64DD4ED002F3C3FFD3C3C313001152311231121112311233505ACB1C9FD64C9B105BDADF9C4063CF9C4063CAD0001002AFFFB04AA042A0019003F4023130017201806081F0524150A0A0D112F080229001A1B142F152917191A1B88218AB6182B2B4EF44DF4FD4E10F64DF4C4ED002F3F3CFDE43FFD3C3C313001231114163332363715070E012322272635112111231123352104AAB1203B0D0A212B2319105A2C4FFE54B9B10480038EFD7439330105980403021A308902C0FC72038E9C0001007DFE5C03C006090020006F401E580D680D02670D6812770C760D781205100F1F200807171408180B14241BB80174401E0703240B910701171F184F21081F071A220F22102F20221F192122B0216CB9011F00182B2B4EF44DE4FDE44E10F64DE410F6E4003FFDED10F4ED123939123910C98710C03130015D005D0037363332171617072E0123220706070302070623222627371E0133323736371301EC2D4DC72B2718290F2933185A21220B21124C4DCC283C1C0E1A301D552B2A0C3404DB6EC009050EA211115B5BE2FD55FE94B1B10E0AA60D104D4CCD0372000002003B033B02CE05E5000A003300C3403B7631882D982D0399280130080C0902030E141B221D03022907233100022333221E0C09023306201B11152A112318032314072320232C26140E0A0EB801A6B51D45221A3514B801A6B2152204B801A6B32F193435B80102B3213F33182B2B4EF44DEDF4ED4E10F64DF6FD3C39003F3CEDED3F3FEDED11391117392EFD3339111239113901111239111217393130437940212D2E0F1B0506062D041B001217141B0010190E1B011A1B052E071B000F1A111B01002B2B01103C2B2B2B8181815D005D0106070615141633323635273E0135342623220607233E013332171615111416333237150E01232226270E01232226353437363701EF2E717E333352653919223E49483F0580087E9C9B3D280F1D061C162816343305328A3A6F6E5931520490150F1A53292F4A539604152135323930656E483056FEC51518026A0606392D3B2B764C6A341E0B00020031033B02BD05E5000D001A007DB240081AB801A7B20D0313B801A7B2051417B801A6B3021A1C10B801A6B309191B1CB80102B3213C33182B2B4EF44DED4E10F64DED003FED3FED31304379403000190B2607251525
+
+0E0C101B001900171B011206101B001404171B010F0A1A1B0118011A1B011108131B001603131B002B2B2B2B012B2B2B2B2B2B2B8100161514062322272635343736330E011514163332373635342623020DB0A7A2B953373857BE5963535A702F1C654805E5AAA895C3865872715C8D747972597E5F394D6E6F0001005E000005EA05E6002300A7404D0B0D0C0E041B041C3709470957097A10761AA6200A661975190229081B1A0F0E040A153A03010C0D0B0A1F1E3A1D1D1C0D0A2517171A0B1F0F0A0E12310E071A1F181C1831231F1D1924BA52182B4E10F44DF4EDC4113939D5C4E5113939F44E456544E6003F3C3C4D10FD3C3C3C103C3FFD11173931304379401C1317000601260525160218C800140412C801170015C801130615C801002B2B012B2B2B2B8181005D015D1237362120171611140207211521353637361110002322021514121715213521262726356F93B8015E0170BA9AC88B0161FDB99A4B86FEECE0E9F6EA85FDB40164894981042FC4F3E2BBFEDAF3FEC847B1B15960AB010E01010110FECAC8EFFEA238B1B16165B3F40000030049FFDC06C7044900060019005201344032043D033E0442143D133E144249465846660D098108483816033A0C3E0709371B3506052D032500063936373744201D031D25B8018A40313029073A1D121D3E9A4B440B1B160C09041924192E482D1D2906373753543D273E3E0027351A542429254A0F274E195354B80170B321A65D182B2B4EF44DEDF4ED4E10F64DEDF4FD1112392FC4FD3939E411121739003F3CEDEDED3F3CEDEDED12392F3CFD3C1112393912393911393912391117393130437940614C4D3B431E3510110105403F413F423F0306222527262B253435333532350306114C0F21003B433D26013C3D21282421001F2A1D21012C042F0626002E2D0231002601104D1221003C3F3A260023262021011E2C202103052E0326030135032601002B2B2B2B2B2B012B103C2B3C2B2B103C2B2B2A2B2B2B2A8181818181005D012E012322060F010E010F010607061514163332363736373637273E0135342623220706152336373633321716173E01333216171E0115211E0133323637330E01070E0123222726270E012322263534373637060703A77878AE09A819303D996F304F7F56318237310F0905613332707B643C64AD0AA760A8855F502A3BB16F75C6423B27FCED059A8B82881AB609744046914D9371681D52D17AACBC794D81026D9DA1A19D4C11130A17121B2E62545A32342E301E47EF073A35565A203B6FE2532F312B454D54536150D196A6C2726850A92A2E234C4D4B796BAC88B2583811000003005CFFD004710457000A001600300103407A4A184626591868180445224A2E5622592E6622682E7722782E082C08091E0A1E181D221D232317151E161D25
+
+1D2F1D303024182F1B16150A090405222529112F182225041E2C16150A09040D022317232417A7123030241730241E230722021D1E07170D1D2C0B300B231127293E241A323005271B3E17193132B8015BB321B942182B2B4EF44DF4FD394E10F64DF4FD39003F3FFD393FFD393F11390108872E2B087D10C5001112173911121739011112393912173911393987102BC42B3C2BC42B3C87102B3C2BC42B3C2BC43130184379401E2A2B1C1D0E1003040F250E2B112601031D052600102A0D2600041C022601002B2B012B2B2B81818181005D015D002623220615141716170100163332373635342726270105372E013534123332171617371707161716151000232226270703327C4C91AF0F091501F7FE67723BBD4F300F0813FE10FED8803236FDF27E5F38487D34803F1B11FEEAE76EAC357903763BF3BF484225390234FD5128B26B8B5A41232FFDCCD1874AB87EE301612E1B3D8E32905C774D4DFEFEFEB141388000000200BAFE630438043400030020008D403E280A650575050323080D030F0A0D051F04081717CA12241A01000857032A00060364021F080A07310808171D181F1631171A220F381D192122D3217765182B2B4EF44DED4E10F64DEDE41112392FFD3910F4ED003FFDF610F4EDF41112173901111239313043794018101C1425111B0F41001319164101101C1241001518124100002B2B012B2B2B81005D01331523033E01353314060F010E011514163332373637331604232224353436370221C7C7775B2CB23C894E342481899740240AAD04FEF9B9B9FEFB5E630434D1FE135B7A7298909153365E2B668C6F4093F7E8CEB6659863000200E8FE7101B4042F000300090035401B064F032A080000060B17171A01060508250009190A0B642178A2182B2B4EF44DC4FD3939D44E456544E6003F4DE4FDF601313013331523111333131123E8CCCC346533CC042FD1FCF7027BFD85FE1C000001005C00DE046F033600050023401301CD0320000220001A07041906075C213F52182B2B4EE410F64DFD002FEDEC3130011123112135046FA8FC950336FDA801B0A8000001FFEFFFDA053107710008007D4041470677069705030001020100023712030304010001020020120504050807071C120606050102030504000408000B07060806050004050102040307060A04040503192F18D4392F10C43311123939111239111239002F3C3F3C2F12173905872E2B7D10C5872E182B087D10C505872E182B087D10C53130015D005D050107272509013301021AFEC9BE36015F0115023B93FD6B26038E7466C7FCC00690F8690000010028FE5C044005E3002600C24050470601791A012608080B0B07001C260A00261514002627081B0915141D0B07072F121F1F1E1F1E0B07041D071F031E090B180A0003242623131D091C1C0A
+
+CB1115182414110126143D1D9F26092847271076C418D439FDF42F003F4DC4FDC410F43CFD3C3FC4FDC4111239123911393901111739870E2E2B057D10C5011112391239391139390010C910C9872B3C8710053C31301843794019191A0C100D0C0E0C0F0C030619101B41001A1B0C1A0C184101002B013C103C2B2A8181005D015D171E013332373637132335333E01373E0133321617072E012322060733152103020706232226274718311A66311F2483E2FE321B233590562C46201F2C2E1753552CEBFEFB5A434067D92D3818E60C11643FC302BE8EEC6045554E0E0EA2130F9FF98EFE09FE8982D50E0A000002005C009C046F0378001C003700504012322B22211711050408000A1C0F06180A4003B90105010040152A26203323372A260A1A391D001938395C213C33182B2B4EF43C10F63C002F4DC4CDDCDDD4101AFD1AC4CDDCDDD401111217393130133E013332043332373637150607062322262726272627262322070607153E0133320433323637150E0123222627262726272623220706075C4F724D61014947615C372028365A59195121138A4423373157462B434F724D610149475A8D2D43844A1F4D1F17864423373158482C3F030046329541262AC0251D300C0C063C1E0C112D1C47ED4632955B36C0373B0F09083A1E0C112F1C45000200710000055705BD000300060061403438043706480447060448050105060504062F1201010205040506042F1200000305030200040620000A02060103040005050500012FD5393D2F1811123939123939003FFD3C3F3C3901872E2B087D10C505872E182B087D10C53130005D015D2901013309020557FB1A0203D70113FE7EFE8E05BDFAE6045AFBA6000200C200D503A803890006000D007440260D0C0A0B07080A09060503040001030209022908019F050B04290C050F17171A020405030301B8018CB706000B0C09030A08B8018C400A0D07190E0FD02177B4182B2B4EF44D3CFD39173CDE3CFD39173C4E456544E619004D2F3C18FD3C10FD3CFD3C308710C48710C48710C48710C431300125150717152D02150717152502650143D8D8FEBDFE5D0142D7D7FEBE028EFBB4A6A6B4FBBEFBB4A6A6B4FB000200C200D503A803890006000D007440230C0D07080B0A090804030201050600010902290A039F060700290D060F17171A050104B8018CB706020303000C080BB8018C400D0D090A0307190E0FD02177B4182B2B4EF44D173CFD393CDE173CFD393C4E456544E619004D2F3C18FD3C10FD3CFD3C308710C48710C48710C48710C4313001372735051505253727350515050265D3D30143FEBDFE5DD3D30142FEBE0189A6A6B4FBBEFBB4A6A6B4FBBEFB00000300ED0000071200DC00030007000B003C402105040201040A2A03060803000A0D17171A0A6409F8036401
+
+F8066404190C78A2182B4E10F44DEDF6EDF6FD4E456544E6003F173C4DED173231302135331525331523213533150397D1FC85D0D00555D0DCDCDCDCDCDCFFFF001E0000053D0752023200240000001000430B04FFFF001E0000053D0731023200240000001000D90B1DFFFF0050FFD505E80759023200320000001000D91C1D00020049FFDE07B805DE000D002800AB40402C081D0D011819041510061417181E1615151C110692280313141E1211021A191E1B1C080D9220091C3B113B02251419191A241749133B1A1A2A0A312419292AB80177B3216A66182B2B4EF44DED4E10F64DF4E41112392F3CFDE4E4003FED3F3CFD3C3F3CFD3C3FED1112392F3CFD3C1112391239111239123931304379401E2127070C2225082526260C210A320007270A32000B230D32000925063201002B2B012B2B2B2B2B81812436351134262322070615141233121617352115211121152111211521350E01232227261110371221034AD9CA95FF6D46D4E670BD360385FD3902A5FD5B02CBFC752DCAA5DEB6B47DA4015280A6C402059AB2F29DE3FFFEB6055E615595AFFE3DAAFE0EAF9A4F6DBDD001650127D2011500030047FFD50736044B0026002F003B0124404B0419031A041B1419131A141B069C08201A3B2E0F06032B2F1A9A1D272F39111110101D351D02072B1D09073B1D230B151D1D0B20063229112F2F102619291A3B2727101A3D382726193C3DB80173B321A65D182B2B4EF44DED4E10F64DEDF4ED1112392FC4FD3939003FED3FED3FED3FED12392F3C10FD3C10ED11121739111239313043794073003A04252D250E0F0D0F0C0F0B0F04062926132617253601382600340332260105062C082F26002E2F07062A0A2726013A24382600302232260121141E1126001F20161C1926011B1A1819370035260133053526032E072B2603280F2B260139253B260031213B2602121F152602181B152600002B2B2B2B2B2B2B2B01103C103C2B103C2B3C2B2B2B103C103C2B103C2B2B2B2B2B2A2B2B81005D120033321716173E013332161716171617211617163332373637330E01232226270E012322001125262726232207060700363534262322061514163347010AF1A96F3E3640CE8177C1423D140C02FCE605294CC1874F2C1DB42AFFAE76CF5346D071D0FEE3063408294BB2594C7614FE93C3B08886B6B38D03020149512D55636E615F5774479984519A5B3155B1CA5E7C7A5E011D01175D7448863553BAFE09BEF6C5C5D4DBB8D70001FFFB01ED047602800003001D400F001C03011A0500190405D5215F8B182B2B4EE410E6002F4DED31300321152105047BFB8502809300000100F101ED070E028000030020400A001C03011A0500190405B8010FB32178A2182B2B4EE410E6002F4DED313013211521F1061DF9E30280930002004E
+
+03C2027405CB000E001C004340240A1864081600230F231C0E011E17171A0F176412341800096404340A191D1EB0213F33182B2B4EF44DEDFD3CDEEDFD3C4E456544E64D003F3CEDEDD43CFD3C3130010607061514161733152335343637050E0115141617331523353436370123451C0E01016DD5765F0151373901026DD66472056D0D572B2A05070CDAC994A00C5E096A45060C07DAC977BB0E000002004E03B4027405BD000B0017003F4020000C230B170511640612011917171A04340764050B10341464110C19183F33182B4E10F44D3CFDEDDE3CFDED4E456544E64D003F3CFD3CDC3CFD3C3130013637362723353315140607253637362723353315140607019E4B180E046DD66274FEB04B190E056DD5627304120E60392ADAC977BB0E5E0E60392ADAC977B9100001008403C2015A05CB000D002D401609640700230D010F17171A080064033409190E6C48182B4E10F44DEDFD3C4E456544E6003F4DEDD4ED3130010E011514161733152335343637015A373901026DD66472056D096A46060B07DAC977BB0E000100AA03B4018005BD000D002D401600230D076408010F17171A053409640800190E6352182B4E10F44D3CFDED4E456544E6003F4DFDDCED3130133E013534262723353315140607AA373901026DD66A6C0412096A45070B07DAC980B30D000003005C0015046F040000030007000B003A401D0A2A0B0407200506022A000D17171A04F302092A010BF306190C3C33182B4E10F44DF43CFD3CF44E456544E6002F4DEDDC3CFD3CDCED313025353315011521350115233501FDD3019FFBED0274D315DCDC0249A8A801A2DDDD0000020042FFD503BB05E50003000700B64063F705F80702070508070206050607051C12030203050404050407051C12030300050607060704061C12020201060504070405071C1201010007060503070106060302040007070501030303020001020B0917171A0185000206030485200319083F52182B4E10F41A194DFD173CFD184E456544E6003F3F12393D2F18173C11123911123901111239123908874D2E182B087D10C408872E182B087D10C408872E182B087D10C408872E182B087D10C4313001715D090701FD01BEFE42FE4501BBFEDD0123012405E5FD03FCED031301F4FE0CFDF6020AFFFF0015FE4903E805A50232005C00000010008E1908FFFF002A0000054707190232003C00000010008E09080001FEAAFFDA02A3059700030043402128034803D800F8030408030100030337120202010100050302000102030405BF21BA0148013700182B2B192F332F3318002F3C3F3C05872E2B7D103C313001715D01330123021C87FC8E870597FA43000002004B00DA041504A5000B002F008E40304717471D4829492F5717571D5929592F6717671D6829692F0C0E142F291D1720
+
+26082C1A0E142F291D17202608231127410D0121001F01210002015E0023016D0008015E00150121000D0121B2111E16410901210005015E001A016D000B015E002C0121B4280C3147301076C418D43CF4EDFDEDF43C002FE4E4EDF4EDE4E41112173901111217393130015D0016333236353426232206150337173E01333216173717071E01151406071707270E01232226270727372E0135343637010BAB7B77ADAD777AACC05F8A387745537C36895F8C2E2D27348C5F89397C443E7B478A5F8C2A2B30250248ACA77D7DA8AA7B01875E892A2B2D2A8B5E8C3A7E4A3A7F3C895F872B2B24348B6189367C44557C35000100B400D501F603890006004A401906050403000102030229019F0429050817171A030204050301B8018C400A0600190708ED216365182B2B4EF43C4DFD173C394E456544E6004D192F18EDFDED308710C48710C4313013251507171525B40142D8D8FEBE028EFBB4A6A6B4FB000100AA00D501ED038900060049401605060001040301020229039F0029060817171A010504B8018C400D0206030300190708ED216365182B2B4EF4173CFD3C394E456544E6004D192F18EDFDED308710C48710C4313013372735051505AAD8D80143FEBD0189A6A6B4FBBEFB000003001C0000037805D20017001B001F006140361BE51900071D060A1D03010F14391D160D061F110A2117171A1B1E29181F0E0D1129171207120F0E1F0E020EFC14192021D2216742182B2B4EF44DFD5D39C42F3CFD3C10D63CFD3C4E456544E6003F3C3F3C3C4DFD3C3FEDD4ED3FED01313012373633321617152E0123220615331523112311233533352535331507331123B5233FB41124171C190B5220B2B4B295950213B4B4B4B40542345C0202A4020155AE8EFC64039C8EA81FCCCCC7FBD60002001C0000037405D20003001C005840310200111D10161D0D011C063919090600050A1E17171A0029011A191C29090611060F1A1F1A021AFC07191D1ED2216742182B2B4EF44DFD5D39C42F3CFD3C10D6FD4E456544E6003F3C3F3C4DFD3C3FEDD4ED3F0131302123113301231123353335343633321617152E01232207061D013315230374B4B4FDEFB29595937B1827191C190B4C190FB4B405BDFA43039C8EBE77730304A102012C1939858E0000010050FEB8041505BD0013003D401F12010E01200F0007000B04200A05060E0A790C08112F0207127905001547141076C418D43CF43C3CFD3C3CF43C003F3CFD3C3F2F3CFD3C102F31303735211121352111331121152111211521112311500182FE7E0182C00183FE7D0183FE7DC0579D028E9C019FFE619CFD729DFE61019F0000010097023D0197033D000B002AB70097050D17171A02B80132B308190C0DB80132B321637B182B2B4EF44DFD4E456544E6002F4DFD31300016151406232226
+
+35343633014D4A4B35354B4A36033D4B35354B4B35354B00000100AAFED0018000DA000E002D401600230E0A64080A1017171A07340A640008190F6352182B4E10F44D3CFDED4E456544E6003F4DEDD4ED3130173637363534262723353315140607AA451C0F01026DD66076D10C552D2A070B07DACA77B415000002004EFED0027400DA000E0019003E401F000F230E191209146407120A171A04340A640008123415640F13191A3F33182B4E10F44D3CFDEDDE3CFDED4E4565444D003F3CFD3C10DC3CFD3C3130053637363534262723353315140607253E012723353315140607019E451C0F01026DD65D79FEB03D38086DD5597CD10C552D2A070B07DACA74B6165F0C794CDACA73B6170007000EFFCB07F405CB000B00170023002F0033003F004B014E401D48335833A83303980830333346123232313233393F30311D2331300136BC01A90048014E003C01A9B2420020410A01A9000801A9002F000E014E000201A9001A01A9B529140A333205411301A90011014E000B01A90017001D01A90026014E002301A9002C003901A90045014E003F01A9B34B194C4DB80110B3215FB5182B2B4EF44DEDFDEDD6EDFDEDD6EDFDED002F3C3F3CEDEDFD3CEDED3FEDFDED3F3C011112393911123939872E2B7D10C43130184379407A004A35493F1B003747391B013D413F1B003B43391B01192A231B001B281D1B01212E231B001F241D1B0101150B1B000313051B01090D0B1B00070F051B01344A361B003846361B003E403C1B013A443C1B01182B1A1B001C271A1B00222D201B011E25201B010016021B000412021B000A0C081B010610081B01002B2B2B2B2B2B2B2B2B2B2B2B012B2B2B2B2B2B2B2B2B2B2B2B81015D2416333236353426232206152636333216151406232226350416333236353426232206150016151406232226353436331333012302163332363534262322061526363332161514062322263505F4714F507070504F7180BB8584BCBC8485BBFD8C70504F71714F50700144BCBC8485BBBB85366FFCB5701C714F507070504F7180BB8584BCBC8485BBE271714F5070705085BBBB8584BCBC845070714F4F7170500140BB8584BCBC8485BB035AFA00046171714F5070705084BCBC8485BBBB85FFFF001E0000053D0752023200240000001000D80B07FFFF00AF000004ED0752023200280000001000D80C07FFFF001E0000053D07520232002400000010008D0B04FFFF00AF000004ED07190232002800000010008E0C08FFFF00AF000004ED0752023200280000001000430C04FFFF00A40000023907520032002C00000010008D0404FFFF00040000025907520032002C0000001000D80407FFFF002B0000023007190032002C00000010008E0408FFFF0022000001B707520032002C0000001000430404FFFF0050FFD5
+
+05E8077A0232003200000010008D1C04FFFF0050FFD505E8077A023200320000001000D81C0700020000FFD10595067C0021002E002B401317141A2105022B2E242B2B101E090D10301E2F10D410D6DCD41112392FD4002FDDDEDCD42FC4DC313000163332363332171617060706151416170607062322262322062322030235341233001615140607060706073E013701E2D5232DCC4B7B6036355025438E5B2658858334B73F3FA7349D9797E7B0027A023C4138372347029BB304F23E46422641443560747FCC1B7B86C94245010A0107FDEB0128017D140A40984137130B0698DE29FFFF0050FFD505E8077A023200320000001000431C04FFFF00AAFFD9052F07520232003800000010008D1604FFFF00AAFFD9052F0752023200380000001000D81607FFFF00AAFFD9052F0752023200380000001000431604000200BD00000174044900030004003040140006030A0407040617171A04022900190506AA21BA0127011400182B2B4EF44DFD394E456544E62F003F3F3F31301333112313BDB7B75C042AFBD60449000002FFAD0449020205DE000600070075403C9403A4030203040302041C1205050603020304021C12010100070403020104055A060000070406050002030705010917171A015A035A0519083C33182B194E10F4184DFDFD194E456544E6181112391239391139392F003F3C4DFD1739CE05872E2B087D10C505872E182B087D10C53130005D0113232707231B010136CCA48787A3CB5F05DEFEDFC0C00121FE6B0002FF780449023405BD001C001D0083401F31081D17430D2D0530142D1C4309001D130F04010409171F17171A09231D0AB80104B5172318191E1FB80104B3218A8B182B2B4EF44DEDF539ED4E456544E6111217392F003F4DF4EDFCFDF4CE313043794020151B060C1A260725151B171B001918060C091B010B0A1619141B01080B051B00002B2B01103C2B103C2B2B2B81811216171E013332373637330E012322262F012E01232206072336373633136E53461C2E1838180D056915774716441A352F3B1C232D08620D1E39708A05AD141E0C0E2313267F60100A1311112E2F4F325CFE9C0001FF970502021705780003001C400E00370301CF00190405CF215F33182B2B4EF44DFD002F4DED313003211521690280FD800578760002FF9A0449021205DC00100011007240213408110C2D0456080001111109101317171A092308FF002310191213CF215F33182B2B4EF44DEDF4FD4E456544E61112392F003F3C4DF4FDCE313043794022010F02260E250625030D001B000100050B081B010A090708010F041B00070A041B002B2B01103C103C2B103C2B2B2B2B81111617163332373637330E01232227262701101F38766D361F106314A78EB14D2809013C05DC41213B3B22409382773E60FE6D000002
+
+007B0449013605A500030004002C40160403640000040617171A04019600190506C12178A2182B2B4EF44DFD394E456544E62F003F4DFDCE313013331523177BBBBB5E05A5D08C0000030007044901A8065A000B001700180077B537080883400EB8018D400BC002831814180583401811B8018D400CC00B831719191AC9216C7B182B2B4EF44DED1AFD391AED2F002F4DC6ED1AFD1AED31304379402A001601150B1B000313051B01090D0B1B00070F051B010016021B000412021B000A0C081B010610081B012B2B2B2B012B2B2B2B81121633323635342623220615263633321615140623222635135A4A33344A4A34334A537A56567B7B56567AD105554A4A34344A4A34567B7B56567B7B56FEC00001FFF4FE3301AC0000001E005A4032091E15001A1E25002A1E05340744075307031D13021E041A0E0F13230A1A23043D000A0F1D1E000205170E011724070E1F20B8011EB321EBDA182B2B2FD5ED3911121739003F4DF4EDDCFDD4DD111239391239015D31305D3B010736333216151406232227262737161716333237363534262322060727BD615E1D2E465B787C353920362326152921251B34352C162318238009514B4C6E0F0814510E060B0B1537202F080929000002FFC204BB026E05DE00030007002DB603075A05000001BB018E00030005018EB307190809B80104B3213CB7182B2B4EF44DFDD6FD003F3CFD3C313001330323033303230198D6E07FC4D8E37E05DEFEDD0123FEDD0001002FFE430197000000160065402A280138014801580168010516080B0F0A160F24076E160A0B1F1817171A00BF160436125816191718BF21B8013BB165182B2B4EF44DF4ED10FD4E456544E64DE4003FF4ED1239123931304379400E101105060610041B000511071B002B012B8181015D21070E0115141633323637150607062322263534373637018B3A4A2935331B2214211A323460673A2E61303C3F2725360A0B830E070D704651413441000002FFAD0449020205DE000600070076403B9B04AB04020304041C1201010204050504041C120000060403070004015A0605030200070706010302000506040917171A065A045A0219083C33182B194E10F4184DFDFD194E456544E6181112393912393911392F003F3C3C3C4DFD3939CE08872E2B057D10C508872E182B057D10C53130005D01230333173733010136BECBA38787A4FED604BD0121C0C0FE6B0001FFE80000044B05BD000D00994137000200050001000600010008000D000000070000000700070034001200010006000100060000000100020005000600070008000D00080009000300020009001E000C0008000A001A000F00070006000800050025000200010000000D00020019000E000F015300210076005E00182B2B4EF43C4DDC3C10FD3CDC3C4E10E6003F4DFD
+
+3F121739192F2F872B107DC4073C3C10073C3C3130033537113311251505112115211118B4C70142FEBE02E8FC5101E5987002D0FDA6C59DC4FDE8AF02520001FFD7000001EF05BD000B0061403608050409090B02030A030A0A3412040904090203040508090A0B080600010A090A080D17171A0B08290203040502190C0DAA216242182B2B4EF43C4DD43C10FD3C4E456544F610D43C003F3F1739192F2F872B107DC4073C3C10073C3C3130212311073537113311371507013DB4B2B2B4B2B202656A876F02CCFDA46D876D00FFFF0060FFD504F6077A023600360000011000E13007000AB6393AA0216A89182B2BFFFF0042FFD703B605DE023200560000001000E12F07FFFF002F000004B407520232003D0000001000E10A07FFFF0034000003B405DE0232005D0000001000E10A07000200900000013B05D2000300070033401A03060306050200050A0917171A0702C10601190809C1217765182B2B4EF43C4DFD3C4E456544E6003F3F1239392F2F3130131133190123113390ABABAB03900242FDBEFC70024200000200210000056305BD000E0020007E402B87059606023208120E1E0F00000C02201E0202131E0C081C31071A22110F13250E010C192122D6217689182B2B4EF43C4DC4FD3CC44E10F64DED003FFD3FFD1112392F3CFD3C313043794026031F052509261A1B191B181B171B161B05061E041C3201150A1C32011D061F32011B081432002B2B012B2B2A2B2B815D13331121201716111407022901112325211521112132373637363736351002232121840232016DA6795D9CFE8CFDAF84014C01A3FE5D01636541744A3B1A0FD9F1FE9F0361025CFBB7FEECF4C0FEBD02AFB2B2FDFB15276F598B53470111012E0002003DFFDB04250657000C002B00D940583912461E4620472148274829562066208C169A160A0914251B34013A033B07350A351A3723451A462048244926462A561BA812A714B714D714E614131327121E131E1627121B161B1B16151B1E151C1E13141D1415141D1DB8019D403512151C1C171B1C1D1E13141516092B182010051D2B070C1D250B151D10131617181A1C1D1E09150227221A2D141515082728192C2DB80109B321725D182B2B4EF44DFD392F334E10F64DFD1217392F2F003FED3FFD39392F1217392F072B107D08C418070E3C3C07082E3C3C060E2E2B060E2E2B3130005D015D24363534262322061514171633121716172E012707273727371E01173717071617161514002322023510003302B6AF98A182AD284ACC1A2F2C273A6C6FA14FA495842B4034964B97E66D84FEF6FAEDF7010AC578DED0B1DBD6C0995DAE03BC0D0C195972677043747B6121332C69436BD9B7E0F6F8FEA7013CF60107012000FFFF002A0000054707520232003C00000010008D0904FFFF0015FE4903E8
+
+05DE0233005C000000000013008D011C000000020080000004CA05BB000C0017006641260069000C006900120079000C007A001200040016001E000A0015001E0002000200000002000B0008001000310006001A0019000A0016000100250000001900180019010B00210095008900182B2B4EF44DFD3C3C4E10F64DFD003F3F392FEDDDFD31305D13331521321615140623211123003736353427262321112180C201C8E3DDEDDAFE3FC202C84075213E96FE3A018605BBEAE9BFA8FCFE7B0235213AA4453C6FFE100000020080FE4B042905AF000D0020006040403612381602371337154512471347154716551257160839194819581903200D0E061D11071E000D1D170B1D0E0227141A22092E1F2E1C291D1921228721BD5D182B2B4EF44DFDE4E44E10F64DED003F3FED3F3FFD39123931305D015D005D24363534272623220615141716330237363332121510002322272627112311331102D39C2445B971B22542BDEB325A7FD1EAFEECBD83542E24AFAA6FD9C2865BAFB9C5AB5BA7036B233EFED3F1FED2FEE33E223BFDDE0764FDDF0001005C01B6046F025E0003000DB402200300022FC5002FFD303101152135046FFBED025EA8A800000100740017045A03FD000B0074403F770498019803A801A80305080B00000702050101060805090904020B0A0A0307060700002012010001010609090A040420120303040A03030107090406000A192F183CD53C00192F3C18D53C313087082E2B1008C487082E2B1008C4070E103C3C070E103C3C070E103C3C070E103C3C005D1337090117090107090127017476017B017C79FE84017C79FE84FE8576017B038776FE85017B76FE84FE8579017BFE8579017B0000010057023B01D505920009001FB303040400B801A1B308050801B8019EB100032FDDFD39003FFD392FCD31300123112335363736373301D5A1DD7E283E1783023B02476B0B152065000001000B023B028B0598001A006340261B0B1C0C022A0D251125143800361136144800471147136800761386139709A7090E00180C18BD01A0001901A1000C000801A0B50F0517050B05B8019EB318121A0BB8019EB10C1A2FD4ED10D43CFD111239003FEDC4FDED1112393130015D005D1236373E01353426232206072334363332161514060706072115210B8C6895594A515140019DAB898BA97B85AB1E01C9FD8002CCB2344A483C42506649969F8681777A404D4C8C00010007021E028E059700290079401E2D172329022A172B29361C3724461C4724561C98089715A808A7150B200BB8019FB50C0C13042904BD019F002601A100170013019FB71A050C0C07002010BB019E001D0007019EB2232916BC019E00170000019E00292FEDD4ED10DDEDD4FD391112392F003FEDC4FDEDC41112392FFD393130015D005D1316171633
+
+323635342726073516373635342623220607233436333216151406071E01151406232226279A07162565615366375660294A434845570191A48984A03F3A5446C58781B6040340522037543D6020110379010E195030474B5988978662455A10156D577F8A82A0000003005AFFDA063605970003000D00290070400F030202371201000103000201051B16BD01A0001E01A1000E002601A0B5290807080805B801A1B70C05010026131A1AB8019EB21B2913B8019EB321280C06B8019EB104072FDDFD392F3CEDD4D4ED111239192F18D4003FFD392FCD3FED39FDEDC43F3C2F3C87052E2B107DC4313005013301132311233536373637330036373E0135342623220706072334363332161514060706072115210110035187FCAF40A1DC7C2940168201EA658495594D4E5A2213049C94A68AA46386C11F01C9FD802605BDFA43026102476B0B152164FAF4AE424A4A3B464C4125497DB78B75678243594C8B000400A3FFDA065A0597000900140017001B00A9413A001C001700A500170002001A00190019003700120018001B0018001A001B0019001800050016000A0017000C001701A0000F00120012000A01A100110008000300040004000001A1000800050018001B00170016001400150015000A0011019E000E000C00100014001300070002019E000000032FDDFD392F3CD53CC4FD393C11123939192F18D4003FFD392FCD3FFD392F3CFD3C1112393F3C2F3C87052E2B107DC43130015D012311233536373637330133113315231523352135051101133301230221A1DD7D293E178303408772729AFE680195FEF2B087FC9387023B02476B0B152065FDCAFDE17BC2C2870C0158FEA8045AFA43000004004BFFDA066D0597000A000D0011003D01104164001C000D00960027009700140098001B0095000D009800100098001100D7000E00D7000F0009002C00290023003D0002000F000E000E00370012001100100011000F0010000E00110005000C0000000D0002000D01A0000500080008000001A1000700080032001D019F001E001E00160025003D0016019F003901A100290025019F002C000500110010000D000C000A000B000B00000007019E000400020006000A0009001E001E0019001200320022019E002F0019019E0036003D0028019E00290012019E003D2FEDD4ED10DDEDD4FD391112392F2F3CD53CC4FD393C11123939192F18D4003FEDC4FDEDC41112392FFD393FFD392F3CFD3C1112393F3C2F3C87052E2B107DC4005D3130015D0133113315231523352135051109022309011417163332363534272607351637363534262322060723343633321615140607161716151406232227263505748772729AFE680195FEF2015DFC80880380FBB92225606054653756612949404C45550390AB8283A03D3C642313C388
+
+C04D2F035CFDE17BC2C2870C0158FEA8045AFA4305BDFDA9482E33523C6221110379010E1A512B4A4A5A908F86623C611220492940858B774D5E000100000000044B05800011007A412A00110003001E000E00050005000A0000000D001E000A000A000600000008001E0006000400000008000F000F0000000B0007001A0013000A000E0000009600050001001900030012001301A4002101A201A300182B2B4E3CF44D3CFD3C3C104EF64DD412392F003F3FED1112392FE91211392F3CFD3C30312123352335331121152111211521152115210161C0A1A103AAFD16028CFD74014EFEB2E3AF03EEB5FE64AFEEAF00FFFF0063FFD905A107780236002A0000011000DB23110011BE0036003701670021006A007000182B2B00FFFF003DFE3B03E805DC0232004A0000001000DB2E11FFFF00C90000019207190032002C0000001000DC040400010060FE3304F605E2004B0154418F0009004700190047002A00470003002600020027000B0029000E0029001900290022003500020039000D003A00190038001D003700240045000200470006004A000B004A00190048001D0055000200570006005600070058000C0058001100590015005B0019005A001D005600280056004A00690028007900090078000C0077002000770022001E0037003800330082003C013100430082002D006B002A00210024000D000A0004004B001700860013004B004B002A001B003A001300030004003A0048002A0009004600470048002A002B0038000600400037003700300092004000290049004000030027004B0017002500160049000800250027001A004D001E00250010004900000025004B0019004C004D00A00021006A008900182B2B4EF44DEDF4ED4E10F64DEDF4ED111217392FFDDD11121739003F3CED3FED12392F10ED11173910F4EDF4EDD4DD31305D015D01161716333237363534262F012627263534243332041523262726232206151417161F0116171615140423073633321615140623222726273716171633323736353426232206072737220037011E073463FA705CB297A2C7C3518C0112FBE70143BB0F315BDAB09A5A3BD0CE95518CFE9DCF3D1D2E465B787C353920362326152921251B34352C1623182363CFFECA0301DA7D4E92203EA07865252D2C355CB7C6FEDFF5763F7394626C3220302F223B67C4F4D25509514B4C6E0F0814510E060B0B1537202F080929870117EE0000010042FE3303B6044B004C0161418E0004004C000300000006004B0007001100190015001800290016004B0014004C0013000000180019001B0017001C00180017001100470021005600020056002400660002006600240076000200760006007900090078000C007A000D007A001A007600230019000D0000000A00220018001F0025001700070038
+
+003900340082003D013100420082002E006B002B00250022000D000A00040004001C001800C6001C001D001300070004001D004C009A0049002B000B004700480049002B002C00390006004100380038003100920041002A0041004A00030028004C000200070000001A001F00180016001800270017003E000700270028001A004E001F00270010003E00000027004C0019004D004E00B2002100A6005D00180732852B2B4EF44DEDF4ED4E10F64DEDF4ED39111239111239111217392FFDDD11121739003F3CEDED3FEDED1112173910F4EDF4EDD4DD011112391112393912393130005D13161716333236353427262F01262726353436333217160723262726232206151417161F0116171615140623073633321615140623222726273716171633323736353426232206072737222627EF082544A864983D27738F894174DBB9F26B4302AA05263E99666945284E77C24269D9C1401D2E465B787C353920362326152921251B34352C1623182364ABC70701505A3057575B4524161D24222A498198BC8E5A683D32474E40462A19131D2F2C45948FD05709514B4C6E0F0814510E060B0B1537202F08092989D9A0FFFF005AFFDA0571077A0232002600000010008D1E04FFFF003BFFE103D005DE0232004600000010008D1B04FFFF005AFFDA0571077A023200260000001000E11E07FFFF003BFFE103D005DE023200460000001000E11B0700020038FFDA047205C2000B00250054402E1C080219111612122514000F081D25071B0A021D1F0B11052E1C2E141029151A1A18270B272219262787217242182B2B4EF44DED4E103CF63C4DFD3CE4E4C4003FED3F3FED393F12392F3CDD3C111239313012163332363534262322061500171617112135213533153315231123350E0123220035341233F692A17DA1A67A88A9018A53303DFEB2014EAD8585A23FAC6FB3FEFAEFDE015FE8D7C9CBC3D0CA0237341E4B011676919176FB45956358012DFAEA0157000001000000000006C6CBBC675F0F3CF50000080000000000A335720000000000A3C1D688FEAAFE3307F407CE000000090001000100000000000100000629FE290000081FFEAAFEB307F400010000000000000000000000000000010205C700A1000000000239000002390000023900ED02D700680473000004730040071D0042055600590187006502AA008E02AA0044031D004E04AC004C023900AA02AA0055023900AF0239000004730040047300C4047300400473003104730034047300420473004D0473004B0473004204730049023900E3023900E304AC000E04AC004C04AC000E0473009C081F00E10556001E0556009705C7005A05C700A5055600AF04E300AF0639006305C700A1023900C9040000230556009C0473009C06AA009705C7009C06390050055600AF06390050
+
+05C700B40556006004E3002105C700AA05560034078D00250556002A0556002A04E3002F023900800239FFBB0239002F03C100330473000002AA003A04730052047300760400003B04730038047300480239001C0473003D0473008401C7008401C7FFDA0400008001C7008906AA0084047300840473003B047300760473003C02AA00890400004202390017047300800400000B05C700120400000B040000150400003402ACFFD5021400B602AC002A04AC00020556001E0556001E05C7005A055600AF05C7009C0639005005C700AA0473005204730052047300520473005204730052047300520400003B0473004804730048047300480473004802390089023900020239FFE602390010047300840473003B0473003B0473003B0473003B0473003B04730080047300800473008004730080047300500333006F04730068047300380473004B02CD0089044CFFF504E300C705E5001505E50013080000EF02AA00C102AA004804640028080000100639004205B400330464002804640028046400280473FFE1049CFFC903F4002B05B400A9069600830464FFEA0231FF5D02F6003B02EC003106250054071D004904E3005C04E300BA02AA00E804AC004C0464FFEF047300280464002804E5FFFF047300C2047300C2080000ED023900000556001E0556001E0639005008000049078D00470473FFFB080000F102AA004E02AA004E01C7008401C700AA0464002803F4003C040000150556002A0156FEAA0473004B02AA00B402AA00AA0400001C0400001C047300500239009701C700AA02AA004E0800000E0556001E055600AF0556001E055600AF055600AF023900890239FFE602390010023900020639005006390050065200690639005005C700AA05C700AA05C700AA023900BD02AA001E02AAFFE902AA000802AA000B02AA00EC02AA007802AA006502AA003302AA00A002AA001E0473FFE801C7FFD7055600600400004204E3002F04000034021400B605C700210473003D0556002A04000015055600AE0473008004AC004C04AC006402AA005702AA000B02AA000706AC005A06AC00A306AC004B04730000063900630473003D023900B4055600600400004205C7005A0400003B05C7005A0400003B047300380000000000000066000000660000006600000066000000C6000001160000027A0000042A000005B8000007480000078C0000081A0000089C0000098A000009F000000A5200000A8C00000ACA00000B1200000BEC00000C3600000D4C00000EA200000F3C000010620000118C0000122000001384000014B000001506000015820000161600001666000016FE00001802000019B200001ACA00001BD200001CF000001DB200001E3800001E9C00001FEA00002058000020A80000212C00002220000022700000238600002430
+
+0000252C000025D80000274A0000285E000029F600002A5000002AE000002B9A00002D3200002E2A00002EEC00002F8400002FDC0000303A0000309C000031320000315A000031A80000333C0000340E00003512000035EA0000377C0000381200003960000039FE00003A5800003AD400003BB200003BF400003CEC00003DA400003E9400003F780000405E000040EA000042AA00004348000043FC000045280000468400004768000048940000493400004A1400004A5600004B5200004C0E00004C2400004C3A00004E0200004E1800004E2E00004E4400004E5A00004E7000004E8600004E9C00004EB200004EC800004EDE000050880000509E000050B4000050CA000050E0000050F60000510C00005122000051380000514E000051640000517A00005190000051A6000051BC000051D2000051E8000051FE000052140000526E000052E6000054A800005634000058000000585A000058CC000059E200005B8000005CE200005DC400005E1400005E7400005F52000060340000621000006364000063EC0000648C0000653A0000665A0000675A000068920000695E000069BE00006A5000006B2E00006C8800006D5A00006E78000070A0000072460000733C0000739E000073E200007492000075CE000076C60000775200007802000078B40000791E0000791E000079340000794A0000796000007A8C00007C6A00007CA200007CDC00007D7C00007E0C00007E6C00007ECC00007F3A00008022000080380000804E000080AE000081D00000823E000082AC0000836E0000841E000084A0000084F80000855A000085EC000088140000882A00008840000088560000886C0000888200008898000088AE000088C4000088DA000088F000008906000089C4000089DA000089F000008A0600008A1C00008A6C00008B0C00008BF200008C2800008CDE00008D2800008DF000008EA800008EFE00008FAE0000904E0000911E000091AE000091D0000091E6000091FC000092120000926C0000935A000094C2000094D8000094F2000095AA000096740000969C000097520000979C000098540000994800009A4000009B4E00009D1A00009DD000009DFA00009E1000009E260000A0560000A2900000A2A60000A2BC0000A2D20000A2E80000A3B000010000010200530007005B00060002001000100037000007E80161000600014118008001A6009001A600A001A600030069018B0079018B0089018B0099018B00040089018B0099018B00A9018B00B9018BB2040840BA0179001A014A400B041F5414191F180A0B1FD2B80106B49E1FD918E3BB0119000D00E10119B20D0009410A01A0019F0064001F01A50025017A00480028019AB3296C1F60410A01A9007001A9008001A90003008001A9000101A9B21E321FBE012C00250401001F0126
+
+001E0401B61FE7312D1FE531B80201B21FC227B80401B21FC11EB80201400F1FC01D9E1FBF1D671FBE1D671FAB27B80401B21FAA29B80401B61FA91D6C1F931EB8019AB21F921DB80101B21F911DB80101B21F751DB80201B61F6D29961F6431B8019AB21F4C96B802ABB21F391DB80156400B1F3638211F351DE41F2F27B80801400B1F2D1D4C1F2A31CD1F241DB802ABB21F201EB8012540111F1C1D931F3A1D4C1F1E1D45273A1D4527BB01AA019B002A019BB2254A1FBA019B0025017AB349293896B8017BB348283125B8017A403648289629482725294C1F252946272729482756C80784075B07410732072B072807260721071B071408120810080E080C080A08080807B801ACB23F1F06BB01AB003F001F01ABB308060805B801AEB23F1F04BB01AD003F001F01ADB70804080208000814B8FFE0B40000010014B801ABB41000000100B801ABB606100000010006B801ADB300000100B801AD401F04000001000410000001001002000001000200000001000002010802004A00B0018DB806008516763F183F123E113946443E113946443E113946443E113946443E113946443E11394660443E11394660443E11394660442B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B18011DB0964B5358B0AA1D59B0324B5358B0FF1D592B2B2B2B2B2B2B2B182B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B74752B2B2B65422B2B4B5279B376706A66456523456023456560234560B08B766818B080622020B16A704565234520B003266062636820B003266165B070236544B06A234420B176664565234520B003266062636820B003266165B066236544B0762344B10066455458B166406544B27640764523614459B36242725D456523456023456560234560B089766818B080622020B172424565234520B003266062636820B003266165B042236544B072234420B1625D4565234520B003266062636820B003266165B05D236544B0622344B1005D455458B15D406544B262406245236144592B2B2B2B456953427374B8019A2045694B20B02853B049515A58B020615944B801A6204569447500
+
+00>]def
+
+/CharStrings 258 dict dup begin
+
+/.notdef 0 def/.null 1 def/nonmarkingreturn 2 def/space 3 def/exclam 4 def/quotedbl 5 def/numbersign 6 def
+
+/dollar 7 def/percent 8 def/ampersand 9 def/quotesingle 10 def/parenleft 11 def/parenright 12 def/asterisk 13 def/plus 14 def
+
+/comma 15 def/hyphen 16 def/period 17 def/slash 18 def/zero 19 def/one 20 def/two 21 def/three 22 def
+
+/four 23 def/five 24 def/six 25 def/seven 26 def/eight 27 def/nine 28 def/colon 29 def/semicolon 30 def
+
+/less 31 def/equal 32 def/greater 33 def/question 34 def/at 35 def/A 36 def/B 37 def/C 38 def
+
+/D 39 def/E 40 def/F 41 def/G 42 def/H 43 def/I 44 def/J 45 def/K 46 def
+
+/L 47 def/M 48 def/N 49 def/O 50 def/P 51 def/Q 52 def/R 53 def/S 54 def
+
+/T 55 def/U 56 def/V 57 def/W 58 def/X 59 def/Y 60 def/Z 61 def/bracketleft 62 def
+
+/backslash 63 def/bracketright 64 def/asciicircum 65 def/underscore 66 def/grave 67 def/a 68 def/b 69 def/c 70 def
+
+/d 71 def/e 72 def/f 73 def/g 74 def/h 75 def/i 76 def/j 77 def/k 78 def
+
+/l 79 def/m 80 def/n 81 def/o 82 def/p 83 def/q 84 def/r 85 def/s 86 def
+
+/t 87 def/u 88 def/v 89 def/w 90 def/x 91 def/y 92 def/z 93 def/braceleft 94 def
+
+/bar 95 def/braceright 96 def/asciitilde 97 def/Adieresis 98 def/Aring 99 def/Ccedilla 100 def/Eacute 101 def/Ntilde 102 def
+
+/Odieresis 103 def/Udieresis 104 def/aacute 105 def/agrave 106 def/acircumflex 107 def/adieresis 108 def/atilde 109 def/aring 110 def
+
+/ccedilla 111 def/eacute 112 def/egrave 113 def/ecircumflex 114 def/edieresis 115 def/iacute 116 def/igrave 117 def/icircumflex 118 def
+
+/idieresis 119 def/ntilde 120 def/oacute 121 def/ograve 122 def/ocircumflex 123 def/odieresis 124 def/otilde 125 def/uacute 126 def
+
+/ugrave 127 def/ucircumflex 128 def/udieresis 129 def/dagger 130 def/degree 131 def/cent 132 def/sterling 133 def/section 134 def
+
+/bullet 135 def/paragraph 136 def/germandbls 137 def/registered 138 def/copyright 139 def/trademark 140 def/acute 141 def/dieresis 142 def
+
+/notequal 143 def/AE 144 def/Oslash 145 def/infinity 146 def/plusminus 147 def/lessequal 148 def/greaterequal 149 def/yen 150 def
+
+/mu 151 def/partialdiff 152 def/summation 153 def/product 154 def/pi 155 def/integral 156 def/ordfeminine 157 def/ordmasculine 158 def
+
+/Omega 159 def/ae 160 def/oslash 161 def/questiondown 162 def/exclamdown 163 def/logicalnot 164 def/radical 165 def/florin 166 def
+
+/approxequal 167 def/Delta 168 def/guillemotleft 169 def/guillemotright 170 def/ellipsis 171 def/nobreakspace 172 def/Agrave 173 def/Atilde 174 def
+
+/Otilde 175 def/OE 176 def/oe 177 def/endash 178 def/emdash 179 def/quotedblleft 180 def/quotedblright 181 def/quoteleft 182 def
+
+/quoteright 183 def/divide 184 def/lozenge 185 def/ydieresis 186 def/Ydieresis 187 def/fraction 188 def/currency 189 def/guilsinglleft 190 def
+
+/guilsinglright 191 def/fi 192 def/fl 193 def/daggerdbl 194 def/periodcentered 195 def/quotesinglbase 196 def/quotedblbase 197 def/perthousand 198 def
+
+/Acircumflex 199 def/Ecircumflex 200 def/Aacute 201 def/Edieresis 202 def/Egrave 203 def/Iacute 204 def/Icircumflex 205 def/Idieresis 206 def
+
+/Igrave 207 def/Oacute 208 def/Ocircumflex 209 def/apple 210 def/Ograve 211 def/Uacute 212 def/Ucircumflex 213 def/Ugrave 214 def
+
+/dotlessi 215 def/circumflex 216 def/tilde 217 def/macron 218 def/breve 219 def/dotaccent 220 def/ring 221 def/cedilla 222 def
+
+/hungarumlaut 223 def/ogonek 224 def/caron 225 def/Lslash 226 def/lslash 227 def/Scaron 228 def/scaron 229 def/Zcaron 230 def
+
+/zcaron 231 def/brokenbar 232 def/Eth 233 def/eth 234 def/Yacute 235 def/yacute 236 def/Thorn 237 def/thorn 238 def
+
+/minus 239 def/multiply 240 def/onesuperior 241 def/twosuperior 242 def/threesuperior 243 def/onehalf 244 def/onequarter 245 def/threequarters 246 def
+
+/franc 247 def/Gbreve 248 def/gbreve 249 def/Idot 250 def/Scedilla 251 def/scedilla 252 def/Cacute 253 def/cacute 254 def
+
+/Ccaron 255 def/ccaron 256 def/dmacron 257 def end readonly def
+ %endsfnt
+
+%beginsfntBC
+truedictknown type42known not and ( %endsfntBC)exch fcheckload
+/TrueState 271 string def
+TrueDict begin sfnts save 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt cvi 0 72 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt cvi 3 -1 roll restore TrueState initer end
+/BuildChar{exch begin Encoding 1 index get CharStrings dup 2 index known{exch}{exch pop /.notdef}ifelse get dup xcheck{currentdict systemdict begin begin exec end end}{exch pop TrueDict begin /bander load cvlit exch TrueState render end}ifelse end} bind def
+
+ %endsfntBC
+
+%beginsfntdef
+truedictknown type42known or( %endsfntdef)exch fcheckload
+currentdict dup/FontName get exch definefont pop
+ %endsfntdef
+
+%beginType1
+truedictknown type42known or not( %endType1)exch fcheckload
+/FontMatrix [1 2048 div 0 0 1 2048 div 0 0] def
+
+/FontBBox{-342 -461 2036 1998}def
+/FontType 1 def
+/UniqueID 16#0040B5A7 def
+currentdict
+currentfile eexec
+
+0E0640E4919899A7A1AD6ED128908F38E1DF55BB410DA33B006762D541CC85FA07BF0ED625AB08AB823F335E6EC51FC178EE7565A6CAD6449DE25A66DFBD0780D37939155E11C2AC6589707B6FA6F2C5DEBE5734D03D16785B4FA8AB19B90ACDD82ADB88701410B14FAA6D991B061892D730D76F21831B70869A56F3A74A40B5B4A18E2431091CD53EA38F788154683BF50B6FBD4231FAEED971DD8AFCAB08091D3DC820AFA2246331ADD59B6D0EDC354B08437D57ACAB5BB1C990C0F5220B16BBE1A82FEFB104CF41C7668505A631E0B15131178F1EFF6CDBA7AAEF57E45C7F7016F3261631C94D77FD81C8B0568AD727F30A5BEA47AFFD613BE50451AE0B2AF30748425FC17BFA6233AD908EC339A75036F06C8BA28017279E0E1360875C57E7EE27E701E6B2C862E6174A7DB99771A678E66853168726EF7BD6919B5188B12C71F247CAFA85F14574E42D6E23604F412A1BCDF2D27D885CC1B15DF073449C442A88B7A5962F9876B8266F748B6E81BB03C043C96857FA16662CF8420CEDB22D94ED1D2B5136DB8AA340C968E99BE06DEB7EA49156B35D7CC4438BD90B0D06FD23CD57E811270CE072929CCCCBF72C2BE3AF10DBB589A2886EC6B980BA2BB86CEDDA535D7B6E8E83EEC3BEA3EB65D8DCB01800BC1A304AFE36E68AE206346447196D031A1F112D0B8ED1923B40B1A2F0A6E3E512B6CD5047D6DED5727719099A1193A3280D9F5B0E9A651550B01D7608BC173814C3CDD38D430FCB7845C0C1CB789B9D353259393FB0F9F49DF01864418E243BA3366B2CADCF4054ED3D5894BF13BB7F265A41A3C5F3BAA480EAE662AFCB327EA64A8AEB576F835AF61899CE62FB850697EAFB8A4873F5670F2A83579BDD675C71BF63CF2E569D999D9561CA95C56E6830E9402FF5C3AF3654E9331B34BF9277BF33533DEC189FCD5B4CB33CDA11F273D9B36C820193ECD25F9C502CA14C65B1477A0533483B96726157E7A667A3748264931FF5EB1E5C57AB32F5E337C3E25B42C5A682FA13472C66A4F5E0796A20235335DAE1E5F5D17F3579750E9ED02B5FF4B95135A0CD72D24E8DCA8E93C1B8885BC7203ED2167F439A9341A4D5D3FEB4649619071D291C8105417DB2D6EA8C54FE7AFD5B480B7144D16D3579998F42D7B98D5FEDF8BCB075C7AAAD775FE75DAB99D7267D69428CF85FD71EFA8771AD5C52ABA29D4ED5AF4757E6A8B20894C0AA83C16BCC9068E492D55EA9E1AEF6D193601BB1B746D0DAB02B1A981ADB730CD328642F72CD01762149DDF73C7D769F545704AE41D247F9ED11C2BE83CE2F4FCEAC30DE4C35CD473574C854341E0157789B7C24BFB4422AAE0884437FFD30C4EC88C5B346A745A28F8A266EA82F08D0EAEF22767453EAD44FBD03CEDC0FBDD745B10AB2DB9D25F0BA5C785DEF7086178C1937E0024E5D481F63115D3E
+BA5F672D8E24131105E4568CF443A92A88655A60BD8D310D8A7753D5E7AF516A471DEE3554FE5F7F3DB8643038F8EB293840E7B4F6827940AD356C0FFA14A35E38619ED4066C91665B8CA168BAFDCE38A8E0B7CD62666F210AFF1207500D627B949BEE7059A7CBF37C6769BAF873852A3EC8539128A2C6BA67AE251763B03C111626D4EC31BCA3276B3562E20E2D62BCD52EBEAFD83CDD967092A9909CF8810BB2B90D95F55B8E9D95767641E9C091A5826AF409C3EC33D5C0FEE148B9F827D956C09D72BD9383613C36EE6176C99205260DF2FD58B596A60C13D9E6EFD05D9218BDCCA93473A56B2D6F7E8B288277AA2EBB14FFE9E42094AB8F3B708280E7D4F82CF4307A9E3ECB183BF71A9583058C01D3819D63DE65A165632B2511DAC9351CF3CA6EE7A68E85CDC7EF8820F76C2F41D39D849723F7C2E06CB5AB4612F8BBF339A5D7B2AA6C521ECBF97D8140B5AB4FCE5057F8EECE5B35C2D8122D86AC304A293558A9222ECC75B4CD455A7D15ABC846CA1F65AF41A756874DFC36C6820E23209205C3D0588DB78961E17B7F14E43F756F0E1995FEE10568B5822B1F656258A6D80FA9D33C32E6A7AA02D12D3E3A642A74C71A98A82A8A4A50122F41936C53D1D5D08BAB104EB6DBB54A5307673BE22D51839F753DB24D5E2FB51F1DD247BD97FF2080D4EA93904A72CA182DC86E3CB7EBE667B93FBAF03C6C4094020A1BCFFBA6F80600CD8113ABCBC402626591EFC35C4307986AA19172287EAEA453154C11B3630C42653E38DBB7E75441C183498F057E68D3E51961272D2A68166C721037409F983409B558A3F8C3C90F47F75050E2F80F5808EE02D3614917283ACFC8BE5B4BE682104F02C14749E5C75CB528C482376CA7033FC4EAB8EBB88F12640BDA07001F711ADB16CFE17B5C719E12657A1453C108333DAD9AE46B5581A5235221EBE237FBB9D215D50C99B76E8243B0A74F047E74F4B992FC8ED543406CD2FE9F0F2DA216ABF377EAA4208F9A039CA989A9252A603B566A1D16971F619FCC93272877324097312A5B3F002CA6B0BE76F86FEBBBF0318D084C24E668BD9E496D6A2B94826D5301DF07D95031B627B2857EC9178DEC1F12931D9434A91C3A6EEDC6C209F08DB179AAA1A7F3C0BC9EFB188020B613110604871DB68FD34DBA44232CE16DDDABC701395A37529166F220E81F8F59CA4C52E274FC9202D5758B0847F6F863D5D2E009527865ABEFB605F5B93111A23CEEE1B951E635CE036B18CB6F950654AD7529D66ECF6D475834E046D8D8A781FA68AF346DE480FE1DA4DB182903C9136C03921622819F1BC9997CC13E6639783652A9BB6A05A33D3A346E84C2803412B42EAF6679BA8996AFEF11D0C70B44BAF6831557D6A4DF660C01CF42B23CC99E51F44FE7BA8EF9813FBBA79B9E63A78B15718218D1C34A8410248301
+B6E00EAD2A6B5DB3373F37B5AF2E61D48B8C39EB79F441D01982F2D940EFDAC75EE3DB851AA8D190E46B5C4644418F145B21C7D2E81AB8BE301B0119AEA126F8221803DDF200202749CDDDE0D39D9E13FE24532E45F6FA2991954CCCCED078F49C4BA3909FDFD60389C265E17285BA2C064C3DA3A8D4595A3D07DE0D3841CD3EB7251846C1B21C12FF8BB40742C7CD84E4594A71C99500CDE1199F25C020A5FCDCD15042B9E90CE809126CC4040AC0A394EC464F10808FF452BA74A3787B613ABCDA1CD79F0681260B698557A6BB62D8B8661F50128DE8A326E0F7A443DFD33703EE42752E96CDA216B18863FBC63A925B888BA0B801B6CA26835BA5837F4B3E4BDBF39CAAB307CDA9728DE22E55FBDCBF6805A3CD5EE77928BE50CD55E10DFA05B96E48B188FC78CC3AC79961301F3ABE7FCBD98EDE2E7AFD4D606DED79F2402993B474F32F38CA3FFA582DC3AC2D93B1479229DF4BEA52FEA4AC9A21A9F2305BA822A19E4E807FD0836A1E61C4424D9600794940D45AF0293FE21617564E2484D689A94AEFB7975D9C0EF3A4487B86BC78685E01C846AA9CD5FED095550DD09106451D15362504AC95100C8D3B746C6403ADC53CC378D8AC5BC5A2E8548971505A70473438784D63AB8175E9256027365C9B60F2AFFA200653DFAD4B77E642DC9A387A748E785A78F6EBCB02B6D5285638DAC9F3A3B5BF1F65F04F3DC241AEE3E6F01486521BEAC159396B1BCFFAEA7766B37187E3B688CCABC9CFCAD2040EF0F6070B378C742AAE2DCD662DEC7B4DCD073630E535288A609F2DE0215D30A9FF3FAAAD24DDCFBA8022C210231405C12DBEC3A0CD11C4E0DB490687F30E8332243E20BBCD2A00ADAA23C86B09FE55EA80D0E59394C034BE4DADBA3B59015D862119B0D73B4CEEB45660A27B1BC96686CB64C6DDC5EB429A0E8DD9497E3572ADD9779EEF9CC29DFEFFEE4D454570B24212F206CF4188BD126DF368047754916A21B4610FEAB54B428F1E0C6821ABD9A5689571883951A633B67361E450C636857E4ECEB499D3493421BF9D96D0857AC05943996C898D8E8DDEE6937DC4D2954B2F67292C3AE5B8FDE46A493631907889D09A191074A1FE460B430060584381D38F6BF3AE62444F5BEB5273852A67AE32CDE2ED616B37382B2A8C34E90659726E8A68636EFCE5979918A1ED576DAB0C249107312708CE44B1F61DEB35AB20C003DFDFCC0B71A7BDA641896350E64739A0255C7750A3B2F4A61E0F9BD49AF82EDA97B988084945620F4497D7763B3DABB21B1444D8F9C27C113C9A7DBEF827207F63E8CB127C380257D84661C7D6442ECD1B753F27E6D611029BC3DC7DC492A01A12EDAA4C7A879DA3B63C6D90089AC4987790F860497594CC0297C5AAD12C54D98466D1A2A961E5F36F590DAE37A06F0BE55F231EDE9FCB1AD0F2922E08296776
+A1A1B8EB0A05EF1DB6933ADDF5F057759875EFECD649199F3CCCBDE5DE2CA9C8FAD362A12DE004BD48B375AC7F8EEB0A7D3D5320734290A229B30FF133638AED2C8714AAD44F19E308AB5E6522F41C194ECFD398EF8B3A9D8B974EF5FF91CEC602FDE84DE8421E8040766EF6255778F998B00F2783AD338D132529DAC37F8EEFB804132997900B36464D21BD989852361F2D2C9B9C0FB772CD9E77A7E3923B5DDBCA924E6BB8A6BE3D2A37651843FB01533E1B7E729C4C20750E7B01CD4E9D861396B906E3E85F8A6E19B88C1F90FF58AD84B8A15C5A79C4AC7601DD1A0FAD396782EB3C8B3C6E3EE625598747B78820656FF950FF636B1E5259B31CD8BBE53D0BD8610909AF012BDC29CB7E7849BB8B66E18E4F0CB48CBD6A41CEC9A4C855801EFE78094B9EE3A7BABA76F152D4C1F3CBF3A07CEB5E1B00B48ED7BE7AA6587224426CF4DE18B0762762A167027D019BB4C3C0107420158167C6D2A7FFE652A01135E135C42219B7CB663E79C591DB9DD66A18E2DD43C7BC93B1C348250FAEA2D13A0592D1209579DF67453187AC853DBB402762755855E637A1170D0836BFDC9632E03072F57397B9A701DF9763EBA853044177488AADC37004E8E399304F22DCAA5F5FF06E28368D6434F897FF044C2E158178A48A8A5BC27C599AEA2FDA2816D853F88C3099A995503F83EC4892F5774B34F55EEEEB0C5A7C5BBE9FD17A15A9D68AD04D776BDD8B2B4371E90FCD0E265ADB2CDE82F6708825ED637480391A24420B227807F95F6E925724A38F69C8DC613AEFF58898C65E50D895810DD7B80CFD0F1F9BA6F6C74EB5A65638BE9B36EF6B54F77845B4831648E124EA4A92E49FF2057BBA962BD006D0BBFCBA049C8356321E11814AD4A5721A2F9F10FB9FFF8E983289D3C4606F31C5DF858649FA980EA63E060C791BE53DBC7C28706648DB0E3B760C87B3A5BFA82571E492597DCD74C6369A766A844A6E4A2176DE2F8D9DC37E64A6765000CEC779EE8273A74B693CA58B25DA24628474F4888F17454D97E92F2259DA22DAFE3DA2D6511BECFCC6EB00727B60FB0C481F893215B8C09112B5F4CF07327926BC4C802FE19813B521C98395EC8E91FF5B6DD9D962D36C1F2220270BDCE35C54280E1420F3B9F3FE878B2D52303101FBC9FC99B7EA1598DA190229290EBBC3DBCDA13BA5E6620BBB9006B24443FC2ABD47D259C6EC1234F68276D387FEED3555BA99AD72A523C63A8937F690754B9F6D248B2E68E4A8DF710917552A0B0FFFA4F154F804E4D86F4C875FE4FE530EDAEFC256647CAAE6AF634C74E3AA69C1EE70312BF926CDF893CE7F964EEA96DBF561EF0AEAF28AFEB8AE1FA4F735BE53468C80B27BF9C2DE52680D93E230B418E4E2F06154BCB9D1E54843F703E64F8BE5F552313A33E2700D9F051F47AE9370C24B15EA8BC552C81B91DD
+A69C3AC564BA43D3CA6C49D5406D9E39D9A02DD5CB6573966248A30DC5AFAA1C5FE011829B039925604E327B332305519D9A8D098243D94E97726FFA3E9F3B9E01152225B2DA4881BCB5578F784518673E0B2E959073AD2769B87E0FEF7BF8FB5ED657DBB86225439D13A886A2A7BF720E1BB291B3C13A0775C6A5ED0A4691DC4490DCBD87F6DBDD5F6C4B8E03B07C5441FF30B9FB8CBA3884BB8AA166826EC2C27770DBE1F51D9544F0A816531CB8C46AA89FFA39C058F2EF531D24876B58647351FF9E2AF130B7477708B42D976892DB7822ED0263DC290B057B357BA541A7D4F61E668436EC2E991FA58D0CD16EFD212477FACD5091D78BB7A03F0B2890D26CD9CE2AD486184B59E321CC5AA247457390535F845032CD2EE498A77FD1D6A9F02D9E97CCFDFF2A72C9FF0C9242DF00B22811C50B68E85FD40E72B8DB6833BB48225E116E32BFA3EF4A537C8D550B954E8C3F28DC42BCC8FCD7B215618B9E790AE2CF2709B55861DD71F519AFC7F24828E9C0615F15C8501FAC67742D199E8F9F206411B7ADB1CB6489BF0F26D70108452DB0E743C4E6CBCDD59E741DEAD52A0F6CC33160ADBD4EA32B21C840D4C2C07D1F7BE7FB0F55F4C3530864F4E80A30130F4923EACDF26F0FF3B4DE9E61566ED256F4B6F153B9489FD55666FB036C77581034D0F2052E915624766C42EEF751313437EE588DFCEDF289E51878665A308F126421C37A25E7C05FC7DE907159473BC7BF01A01AA8936600F70BB4060437455C93B231005294E1AC815189DC8C5A0B23F51C6750F5A2AEFCD1B5C07721DDB3A26387B231A59DD203CEA9174260C52F8129B4CFE2FC97E5E0D3B120A980BC6A6A51102734CD792D15755819AA783965B4377812AF5BADCE15BF8DACFA33F0E7437142706B8FDE747D29F4AF6A61CF8A518A98809D83C2D8DE4B415DD2E8CF8EB464DA0BF2B5C18AAF97A79A602FEC3CCE134D27141422CB5CBC1A39EDD18CA48D362784282B7617D1015C047211423DB382BDEB40516A5EB920DED056AB2C247119F753FFF433151473585044A01A5D7BD45AA724C708965CD844D24A3DFADA10B50C7DDE40487D6366D300555EDFDB216E803593A4D2EB8E7A4F48DA433D918067888B5146C7A0051E0B197275B5D28AF7E7D7B44CDC2AC4E2F70DC832AC849F9329BFAE557A467D06AC5CC13EC1FA5B2A9DE1F7F21A87F082A18E7EE9D6CF515275CDE49D2B3F0280A08E5AF29DEC80ABC9E3D8BD4D43279AA985B42CF5BDCEEBA6E60F43CAA478B97C149EB0358FE4F3DC530038197E4ADC77D696B6D89AD29C6AD80F0F402D1965069E1D6566D4010F19493B3DBDC5042AADC4FB6D1EA2107B9204E5CB9E3B4D7582563331F6C323A5252C14FFE95C86EA687D195F7E90B7FD4EB11216E660C194DD8186C952C612C2CDCB16649866EEB640C2B5F861
+017D3CC85F1C5FEF71BFC908C0F165AFDCDF4DC559F851FF149FA50FF82CF588060AC6072264D9F112FAFB2727A5D5D442B8412351A9F781146400E3C76C6E3B141F9DC5CDEDE737B08371DB4491A97F83601C661BCF2EE180D4E4B31439DCA114C139C8C265C378208B2A777973DB7D80E3AFA6DDC7EBF2500BA5C132C3EAF994D49AA066478BE18AD9E38384A8703DA0464F57D14A78D7B36A7C8B1C2E1619BBA952F19FAD79C368375C35B89D06BAC07E65DD12EFF56B2F048CE8969958B813F231B4BE7012BA201ECA9830FE4F47146DD7677F18EEA7F28C40A0DC5035F4817D23B02E2C1AE277EB35A2179F3FDF8C75619DEB80B4537FD8ACA174A9C651F5DF7EB7F123FECE4BFAD267B2623FCAEDDBE9A55A16F37C9F42B29DF86DDFC1EF9A64DAE1CE39461132482A5A69516573596F7C08EC837E521FDE852DC0975869B615D9AB3F216AC7D8ECA831AC8DC3D53EF257F0F649E3A5294C6A14542384601A847E3C4500FC076E31E24E6203B445A179A1FC31C982E4AC8AA74DA0B316C74887D98A5CFEAFD5C408ABF4D70623E860625367088FACD349FF2CD4B865CAA8DB96897A64703D6E578D01AD663CDA576AE0DA2ECEE408E2996B8C761DBCC6B51841F1816327602C6E5073EF834A3411CD4F5C753627025ADAF35081C5EA2D9CA30E79D3AF248875F9F4B03CED77EC8994F50531B14B4E31DE3E42AFC16B9D0C6CF803B72025E6743ED8FDEA84B384750D7C599CF8A6E5E107AF16CB8ADE4240876F089A204CDFB7AA4F98EDE163441BBA639BF2C59649180E0C928EF4504F1CEF41382BDD3E74286E865B1BEC8F811DE7A6AB1C84E6647BD188A3CEC795DB8EFBDA6CFDBD9E02317CEDCC1EAE490233F7302E44991FAB7759222AF70E1AD52A243F570BED22AEEFD521C4726C4ED7F2CA339F42CEE81CC7A74171C3CD2844497A8CF2299BE0AB373AAB9403D8DA06A8CB1E0D7B5B13F73BD3782CA269EAAC30F97781191813C7368105AA5C2EAFEF0D076E20604B19ECDE462F251C1183E955F38CB05D8B1521DBAA47451A595B2E9C301BCEF34E1279755466528EB06227EF72C0CA9F757F8AEA5E9640A761F97DEA0D1E776A8DB86BA1D28C0ED766A3D77145FCDB6F2E38EAC0086B89BB14A62651B506B76C3C8D81A7829CE42AFA91CA15E48D03B761F69B8C3706DA8FF054F870E516243726043F98CE24CA5701F6FFA7C9A8BF2122FA07FA9FCFE8255CE526CCB41B19E46EFFBA83F9EB8B0A279B9B3DDD8E7D2085A27E2F473CE9858DE0249FA00C9C6F233FA0BE791B442A86D72CE4AE8F066183A266D57C8C2B68E36A679DD503C6EA0BAB733C65ADA03A3B73E0BD2B2A21D2BFEE34A8132A1B7091BE054A46EDED29D0C37387B0DD0D9D84956944274729FCFCDD42688BB675D7E82D282E5E4057FE018CCD8599D8DA42F553C2
+082FFB3A1F7F3C8882CAC058234176B18C82A4234CE4ABF18C86413482D355C1FAAA4463578A500153AD143FA467C8307C4D4C865CD14ECF67007B8A7A42D9F0F217D14271C7E129A9E20C97C32CAC3EB173726FF102110AA010CA7A31BD8BC2544C647D5BC271888AA0222588666046DDB7A847F0027FB6AD47D59A74F6D9C114F5810BCACA3DD04D76BBEB82CD8C8085DA28A097C878910B4D2954A1858A8F90DBF8A7677A2BFF69969353C3EC0E806850DB08BB41EE0DDC8EB683B982559D2A0DA0025FC75580346D60348B2BE757BDFD66B2668DE60D5AED1CDA286BDC0D4DDD447C0FD95C55C294E3DA462171D01C408AA78AF276B0516BB3ED53458B1591BC9835F15E6B9166D8B6CEFAAEE0DDB74FA608D5867FFC7A5F6AC79A3277A9CBBE9E6F90881016882BCF5A82B56BF4D7C718081DAB7FC31E6FCEFC56C560B197C3F0776016A74DEE2FA25C9F3AC0243A44AC4438CF2CF3762298D08A621651B674F3C9CB9694461D0E80D312FD8DC57B84E439950F6B65EFEFAB4784B597D9794B4B8F07C782F9F5629592428B3B8421DEB445DF7B4E8F6824201568FACB2B203C5DEF30511D3419571EE339E1C9997449DF8823F5D6A1605CAFD436B24BDC390ADB61B45DF23E3E714AC941F4C4624F21B56D6ADD1BEE2EC27B670213DA951FE5AF269EF7C3260ACDDCDA8751C27E5C065E324AB9BF7C918E3D689273ED6F762F09B872C6A557B0D702E1CAD3597CF4F9405E73CB6ED7BC328A5A7FE3E172687E67131C1E6C068062936C6A25E809F7B0FA4C936425C9D3832B7D14A72759EA5D76BDC4B83EF93579514BDF7D1CC4247515893B497C8DF2BA47447FFEDDB0051E1177378A6FE19A2EFC945B0661256AF549938E2215C50A0624EE680CF61F3C12C8A637E89B7D7E44616AB5C2752447522AEFA0D1F9D4DD88CA3FA3BB052DD00587C3FF72272466C6D95011637767C4F8EE5730F2797706EF2F7E25207A5AC8D22E36690B27966FDCA7994208C52048109D2F555414DD1C3D3D12B65A0D483471F4CCB8F3EEA1A510C1915DE726F38B8D8A598F875CF4523AEEFA7B4EBB3A1DA5291ED81D0FBE075C6573423942E07424A3F49E723D4C6749122C10C934595F81AB0011D26FE26A2E9A84CDAC309D1C0E7AAA271DCAD84BAEDC19EC5E50AAED788818C833643B26EA13A5068861B34056FD4231A274239D4E3054EF3BCA080B18807F078BFF1CF98D86CE893B88984D157498D44A0F060EA105CA71001DAC80FBF8532D880B71C579F036E42A38003043683CF0E60E0DCEB594BE75801F17E1B9AEC361613A6AF93220098D425D13C22E3180879F48BB323BAD3CB762565AE1594B0E999A1814B068CA4FCD34DECDED961FB35CCB0264E487C20186F2FAC6A74BAC4D4C67A72C6E0E73DED0C9B14167674B45145FD607D57066B58DB6FE8E
+A7B7C04C8B8F2C32AAC75EB36F9B0E67AEA048126F08EF1FFA628419B6859E6A51E10C4F10B7F1AC52D2C14CC85F9B1C914A69924938662D8D5296F6D352991AA22A6D4BD646F8EFE06C9471599D2145F5EA66897416FF3C7B49B6A5EED84DE1946ADAA9E368EBF957FBE240BFA78F140FE931D34D193194BFF08B96204675AD4B5382FD4B2AFCB7A3AD9DA721023AC71CF368B8D1819870BB85120CC3AE03A3D2FCFD0156460E22A1D14313F696EC1E2AE1BD81768E059AAD3761253AAFBC3FA1EB936A8DB100802502551F5B1EEF7B8D533601FFEF6C3319EEB61EDD37600F3266912D95C775DA0A4DEE60684095EE75ED5C977B0F689A5E40D952A34012E96FC93F3B1152778B6DD4D81FB165063B9BB57A661D59DA420D2E8F6BB4F9EC12209A5BD8CFADE036546F90F00FFC509D46AF7B9F05F3C31532E424DCB78D6DD218B7890317700DFA55CAE88137AA63890B5DE205F2EC2A384B143BEAF827C0CB9B789B401BE8C4B4F78C74607B872FDD0B5DFB9F70CC075406C885BF4B9363AFB741990C47836AAD8374C6E9B0A6B210144C248FC0A733B3BDBF98B1B9C3959AF3C299172B9A0D9A784B0B9B869B92B867C47B56FA05B2B64919303D6738F104C9355CE92C81BE6831D9561E049CF9DBBAC87EBB604B18FB38E1EBF35ACCCA6FF9D6A7633C64FD0F17DDAE0E141DB3C8A2801E68A815EA317209D0E7B2803E0AA48E8DD05F3AE69B16844D60853C17EC8F493D810F0E022C6F9B75C973DBDA8E2EB02B730C26051C3F296132C0DAE210B8CCA7D9BA3869324588136A3DEE85496F6DF1D2B6E9EE8EE7149742D8C3A6D430AD56F150F93C2D54383F0A67D7A2ACC3BC580F15CA8AE44A51B9E7CBF85E385DA4C1EEA1DE3674730689FC8F6822B4E1D85943838C4A7BFE9D2FFA9EEF69BA6BB72DE8D691A632EAC4CE9EA5C2A55009C50D55C457D4C768CA07244F0FACFDB45551074899949C4BC0B8BE2D17CF679B3B85378E6F7250B856A6B80B0FF3249718A6397A6BE364EC5D7DBE228787DB8F5298B4AB41BD5494B369C18084A3B4977AD317FA26877EB6687053DE299FE10D817087553296850901CD45772630562E1C6566BAA3A022047DCDB17CC5933CD390584E36F9AA41024B91B2C24AAC2E76154955A6FAEE3B1A977BD301A8F82095B480FBE9598DF34949DEF67D912DA592744CFC18706045D0846E11F72FF731569CB21FEA25FE1A48E6E27241671E7B9329F3D447D825B1145E6A3403EE660475595A79BDA064D0439D1A0C87B81AF8728FBC2AEA383D4780EE209CAE9869589C1340CE5CE80C309A929C0987E409FCE6D63D9858FB0C1D22750AAD7D36C149043BD31EFC859CE72A91A260CEB393F234B9AD8F841B7009639695B33FEE923B964043080F4994326CA2684E5AD2760FE637C08551CC61962137D7E188BCB8A5
+3BEEC12D5035804D4D589FAB2A08F4DC06AFB891E575104D5C3DDA2AE3ABEC05188FB614CAC8517C2F575B5A42C34502B4EE0895B6C1AD275B7523D616635965C7472AC5FAB917BAB1038FD36A1050068CA86FE2B271343D4322DB153987B6C5444949B8D17CB723CA3B8E8FA02816097A7AF64592AE8AA2D907D1915F9E8BFE6EACB090CC951FA0070099F943ECFC043138C982B273C2905CB30DF1AA4C7F4FB334D1792344F704AE1DF2F8D3E96D27416AD685F01CC61405BA4F375A353EA54C3BAC032713CD6A450FE1E49003A15D7C0D2A599DE5BB0D36ADE24741621285DD036C358E4B61EE0418B917607994D39E07A7A320A0C84E3590737C98C86750BD5A4EE6245BBE04397FFFC2A92A2EA9282B4C5D3EF828425675C2B78D6DD4312DCDF023D09FB25B83F2950B6901D55BFD7CEDB5E0ACACD2C51C4D678A257C64333042A45504A60FA4F3EA3B46992A510778643077EEC978768B42AFD63A69148F91DB514F5E3F3781C3AF9190884CBD6C26B1D6A545B5C4EE35B9ADE62BB429EF7A5B28A3E8E59619B1967E6D611132BC348EBA27478FB7C20E360B8FC3ACF7ECE7DDAF7ECDCA6CFFADE8CB0752AA0C33FAD669C2B543C3528F6EB05EC28978097FCB009A1E08EE9215DF35368529233E736322783B0A1FCBD9D04BE2DAA04ECB078A715C52D88C9D1C1E1FB70AE6093E76F07A9EACB8755E18E5DE3D3669475C73FEDCB161A99DE99AE1DDEB6754C2364AB9B37D5795A73B57DEFD26F2C2B65C66B02936D7C5206C5B03175EDA8BDE29357848D6C722BADBF71277CC5637CF0584A097A4D87E443B9421B6BE53232697C84B0826BA6D2E3053453A1D2B3D1A8C377ED6697F93CB18EB2F8D62EE3E0058237A1D9016141BAE06457D52DF87E388EDC12B4619FAD2551834096AE10AA895107D134ACAE11658CA2F3888ABBF2D10DD08E4C57A23B5B2FE9AB299A095285BD6DAB3944693E0D126E76379AFE56EA32521D2852027106135B72D546E7E6B86C228B1560B30BEF4297E5289F4E26B108C926EC1B08674BBAF57CFBAB38B77A23EEF96D4CDED20D00F11FFBFF712E0FB9FAF0300EF53A2388F634A6DEE112C1D255689022231B2FC3768E0FCA5C59FEB18B0199ACAC91CDDF3FB1C210499AF98BF91EBB7FECE3EDB8FB35C5C5DE23934A86F601FB628092796BA75EC330172A798961E117341031A5A27FD1CFE9F7A715E3A21E59AF32AE3BC4843EB226504692810B2DC9A7D630AEA2CD0FAA5039A9A2B9A42C14405B8CB62E4826455253A878627A538BEE3A33199EB5B053D2CE1B634CE1C430A1BED8BA8CE85463362BD11E1AB3D257EAA7799EAF23D5A558D99B998A483F3D9AFE94FED0C37F6E237053EE64F7A114EA4D2C9C7289ADCA5D6B78C73B20130924AE448690DD884C63BAAA71170C79C87344099309C9D46076915
+A4FF9929D231424DE7B6553881067335F7E26ABA0FC81242726BE507E8AB513C1F6FDD0999C6AE4025C4A84FD2206FEC473AFA6A2251C711661B9BF6742FED15A3F057C49C21045642E26F5230641321BA39D8D24F62FEB4FBDB157CBEC84126E463ED0AB76FC631474C87B7B00E3DD86F20E0EADD19151FDCD91AE38DBF7E38D27129E1772AFC40C3F8CCEFA06B3A16B946D3D96DC19209DC7FC28E20098447047345AA7C9660298DFB9CFBED7383629C289D6D8483025EAC804AE0724EB7279E170C350E68589C6F8A295EF02821A1E8CB8135D451106C358EE86219A68A9B4EF6244421A88298ABB475E79E8841E760446C9510F3214B017BB100BFB8B4A548B17A9E93EC898BABFCEDC3F447B6B76C023A86D269C094BB5F030E17617198D16AB4132C67CEA070B844EF092D9CA7C53A046196A34486DD395C1D8AD2DAEA19FB732C2E9EA74B0BCA77D07B90992C15D38BEE79DFC1643BF9D0759BE16AB65F3B305BA4DE08E3BC503B3CD47D0363564356375839374C40AB8DE85A57408E0B27BDE15CB10B030604239E8B60A8F5695228385ABDBEBB72C9363C80570C538DA14CB5871D6A61D1924BEBD1A7F57D2A66BAEAC49B7EE896E5DFBA5DE26E65B9D812A56EA0C5D21B607CFE9B88820899680C417B00F15C423838820EFF8F1D0B1F72D2231F5E275C8301761BEED7E0558C96CF4E9C23AAB234A2F98C983F81EE5901B61A55F6C3567983A4EB5C06388FA32F546D308B494127DCB33EA32AA8A33E8070280C3486841F28FFCFE4379CB4819DE80349A2A38CAA26168BC3E4F60FE0058A196402FB723A53EE2BBFADD739AA0F7DEAE55D314EC6480A4AC018EF26A3BCCF1D7C870BCEE95DFECAB0494F0527D63215BFFEB3B6FA9316F711CA04DD2914AAF0F082082B469C72BB867AE528DC067855E2F2C50A152150DA49BA1A3B45FA208FDBCDE9CFBA46D010FC30A8CA45845C159C4B532952613A2AE954A7FFB65CF79232921ED36936BF717103CA83CF789A00C39FF6005397A0537C96AA9A87F6595A13950B066795C20E3EDE529D5D249B784F3F18B6085BB6FDE13BAE0743687D2467732C3FBFB0ACEDF5BE11BAE7C3DA0599F0CA9A23543F5E79ED0B205BED594CAB385DEFD9477E6D970CED9F77B81F33730BF42D5053BF6ABDB40F05064D71CB6F7915D6B54C2C4358DB87190622C56738E3A58F6E2E51F89900784A1E5E11CF9D5FE66DE5179EBB9EFD4E08BE0AA9BD0E573B8EBA4D029906594BA8687A5E0DBC4CE6A0F10BDCC3DEF2017C0D23F5EFA3CFE3049157807785D1F86A012D220EF7394C4A7733D8833F90D083B33C3F96E67F1DEFBC8DCF82EF3684882B05A96CFB00A3DEC27D63FAC8C2B47DDFFB04B26A23192F3D981E16D8ADAA3F07737AD390EDAF8BBFD689EE9C28677B08D9232C8E5938F79A6705F00F3B20
+0196481629CCC1D1DC9F3462A60B90AA93968722E6097A731AD70FD6F8DF57E870DE54ED28DA6A65C3B103106C49EDB2D83009642FB6CBCEEA4DE41C9412D53735D803624199035626CA225D651B657765F8953E0E59EDB226ED8CE6BC9449990459396AF9AEE47A7152F6ABE0FAC74BBD7365CFE54273888B1AC108F7946DBF1FC37B0A1A88A64A9D58207EDF7CE75B0B565753C2AAE98D15454795D5490F713DEB9D649CA5F6BCA1B50679A453F29CE5DF4AE54A5E964C5F409C07B1DFB0D332496DC321E900525372D559AF11E7C5B19DDB3EBCDC2CFA3F4D3D754CF7E83B5E970AE08063F9320442F0DB7C0F81CA0CCEA6DA858B81C7CE43B057617E0393255DE7945E57C0C271B59DBB091776A0E24A1037475C6FACD6CD557DFF8EB6C6F6A26DFEB12C7702F7A36B8CF1A9A334254B4FD9B0654C1C881D0B6A5DB3BE0D8A1F66D41A53FDEE2396C15B9A27953365EAFE48089C696F3FC1F64FDA0809839BDEE30D80C2ECF7E5402728DF8EC29F10889F2F7C698B41EAE792D1F178021B10FF5688987DCC53EAD28C808E1FE71A7E7E38858A48163C5160EFB7C89DC521143ECC4648B74C330674E7AD4C7217C2505F66912A67FAE2A836DDEEFB91759730D8A11944B700995F3589C8945CE4FD5002676624454984454C32C0206B7EC50BF503E94B88B35276D95B7EC636AACA34648F5A9C6627602976212ED2B803F53B2827A975ADAC831A4463A3079F8AF15121A6C58D631BF88AB1CDD7396AF216900A8865DA2D4E3DFEA7A1A353D853DE79FAA5ABA4E859DFDBE72A6F9B4099A189484ACFE000A0C35B9908F8E48254D9D88E7BA22A043DFA0AB0C8E243E6C22C721B75C6AF848A177D8CFE9852D18BC5948F793289A9E82417735C7CE70F979630208F1CD85E229B6415A2DF2425C744326568D7E65796BFF03D824F824CDA0DFC11DD28E9D4E4DD7168458215C1CC29F3969BFB787CC77B35B3B2B08C19FA44F85BF962888A8AEB121A9772B0DEFFC61373FD074FE4C99D4744755794B06A4F44B5488417DE004B8DB7B353074253F42E2BB5F11241EFEC7A35FE90876ED204ACBE85B84CD006FD484B2F33CA41AAE8E018ACD0FBD3BDB50F95B1EFC160FE358BE12518DCBA5A8CC83BC17A14D0304F024DA41F45975499651A1FBA36B8E1F20BBAFB05855CAF51E31E4C3510696A64DB11763B21C5D15EEC6F751C4096966CB9A8DB05AE779B90A2FD6AA817849B6952DBF56B962313825C4C0531D18ACBF4661DC11E65340FCAB2D26F88D85007543A4A1415DA76B53A9CB066BB87E89F1328116578A9864F279BAB66F97E6DF99B2E8B090C903EA40E7040C890D9602306AC877E560E159C05D9825D7CA88F6BD8D1E11BCB46A8A37C0B68C43FAC170B7426209D9D44CC90AA1D141119338F3794BDA9CF041941F4B512DD4D98AF26E4EE
+58C6C478A82F050726F24D60B84D7A00656A68030F08433773BDF158A54FFE340CF0A78AB8217BA80E379D24B81DFED4EF35FF17D3C6CB7B4D8FDDBFD9909EC3B39A9E0AA5CDB3174CBAB6150492308579304A2E71AD93DC3FAD7D98496A151A08266D8AD511A55DDF6ED6E9D84284EA1D807AA58CC46119F723214CD2876538C63A373DBA681EF56CB8B28962CF68A347305AA77942C55C4F30B0CDCEB4B208622021E0A7CEA9F2F4D1860DA96E3EC2F0197A1B1B72BBAC276F29DF8417EB93769E16411221068766C1CA4104A25E9018CED288CDE99EB4CED0511223DB79919B8B56451E53966E184F50D273E1C24ECB73F8B28E75F78CD9430727DEF7A1FD88E274609DC1FC69156F2BA4D2EDA84CED971CF184D772021C47B0DB40193E17BE620A4B936B449B8FA290FE0DA76D6A147E2B6192AEB52CA037BEAD7063CF740C1C8C1F9E883D0230E6F74E672A1AC211CD110E7E76AF71B0D86A11D49AD55EACA01D9C392A9C7EEE57A1673F04FA6B6A10D7BD1847EB59ED0042D7B4BB6257CBBE95743CE5C5493A9C8C297AF6243E4876C5673BAD1A298CFB423CCA0930DA50679A452027C7D96A3AB4AC7AF9DF35E025B4D9AF9857FED0C5A128FB7F2B79C46FAB608D1A723FC0F3175F4E5A00FEF4B0BD2279E3EA23CABD55258CD29153F23E7995A75ED5B6E636A6ABCFFC188ED4B889B72DC370015EC282824FB61A4FF7726654323939C0F58B3EEA9E1D7D1E8FAAD3B19BDB27B06284F8B26A903B21BECB246E8B1DA82ABEA5BE7B217E8028A336ED15CB882932FA2C3970FB57CB59306253B8BEC6F37D7D659CECB2397BB372680F51FB7B9426EC95907AD4A0948CD4630A9F6DFBF9EC875E4D8ECAFC72A4FAC7999A3289DD8B76B3B14E9C07BC56249768D81916E0EFA43FB955E437C595035868256530D449425DBD19E457A08C4656BA6A4B98951167BC250195BF04546B4E627B38C2B01A6C797B5E814C25F83B0FEAE57C34D446F5FDE7EA158A1EDC92A6977C4716941020F5119F5902F9256230B6DA61499D15C3E107B0C89B9C576DA4178C91C53A61A2F98DAED97388D2291AECC14F0E12A7D966BC625EF6E6CEF9C7D1EFAB93D7EAF5D0ABFBA06C20132A2771049A986B272CDF8BD174B6100B2BC9C9DCBF8D766640307374DD7C13B7B5986547C1774247AF2297F58ACEB1FEA58370003F796280A1D125052507319F94C31FA24D38CBE20EA5134A28C039CD6FA32207E581D4869D4497A7CB7BAEC262882D450ADA3E75D65B81D791C9F36B7D3E1DF6033BED4EB5564F5D290E24FFDE29D0C70050A421CCF9389CAC848C8ED0FEDB353DE1EE0F16A7156D2859AF0E701262E49586978ACD7E7D5D414E45D41D85E5DC11F6BC54C72AB5BE47A79B925F11F5608616F22A3D382C4308E2AB39D149C466CE77C04849CC5EF04BAEDDDD
+54C6DBC0F6CE287029E48167504BA3DF95C5EF754748CEA0837FF6898E0A2738F70EA4BDC0279D5BBABC17CFBEC16758E0911A80A35CF5964D9A281B9EC7DBBDC1966791D5A4EA2939C3DBE0C5E28557870DEEE70C9CB551DA153C385D8FCE073BC10E3950B2814E7C6936E7A0DE4B660B02290FE872983382A26E293B20665D6E29853E591B192EC172BCFAF1933ACD295004D80CD95E649D2388EEB8AC3B7FA98C9155B5C5357CE75AD4EA54CAFEF96054619577D94509D95704153741F11D0B2DF23961307D6E109DAC7C2ECE15881BC2E1BE14AD39BD0631CEE6518F0B5C2E1628B3EBD44A050F636B20E84F48CC4F244329A6778CF9C797EED50441935CED54F888EA38188DC4BDF49760C070DBF6C3E9ACFDF2A91F5B6D26571F0467FAFD3E2E440639AB4502A6DB02D2AB116E9309F17BEEF97C51BF4C791D5BF34F65E894A0550F1F5B26CA8AF5FC2E5673E4D2B1703A330373F8BA351335592DDBA9CD2974935CBEFA2EE1F4341F70760156B58A4307BAA1DFBEFC5DD27BB63438F24593F10E93895A5AFAB80E911E89BF796A04AE1FB5F6DF37ACF0828F86A87DC03B69B8F067DB5019E8EFE54AEB445FA9C334D0B044EF32507B026FDA94C39317E0C7BB56790EBD08057DBD21EC0CB0369D019F011271BBF1ED94A0C77BA9E8D6FF291E474C79BCB3763F34F495AFEB6B10330E4FD2ED47443E8180E6AB85518969A7D6389DAA896B53C3EEBA5B6A94B7BEBA479CBB6F1361CA6885642C55C8CBE6246AF2B75D67256188BD355C7964B3598683A39A79717B1E8EAF4F85223732FE2C64621368D8F02078DD5D74ABE19C7FEA56B823B434582F79D47520EB5466246C21538883E7C5F4FF5C38D1147A4D332E7812E19C90E13532E594DCD118C567D539FBDC503585FAC59989A0F891466C44E93A9FC73A7153788816AB5A8C93A3AEE0802359FFC811BB56F4EBDA7704F30CF632E984FBEE1B26BCE78731D9F11E868A9D64ED1B48DBC773C87B1A40B8E140E332B6EDE825E1DD2E0076A05DFADA63C8B5C8384D26C281FD147B4CB8D20FA8AD18A7FBE6C547684082413B205E33EBAA267D5BBCC78C190262E4F62B3645CABF25D275750168AE09F050B02704623F1E576BC6C64B06D0E394D3EB0AB0282729BA7954774BA14057C6937FD29DD22666FABE27B648DDF066EBBEC81447DD7F388DAE780B9B40C7BD3E138FAD8F8A51EB7B36EE001408B8056A178BCC2DC73BD3F61FA96C4D5D20FAAD0B6851A7B2D2EE451822DFE555CA2C1DCF2B897C7AF4BA65D24CB3D8DB3EA2942D90B34A2FD6FC407E284F1C8EAE8BFCAFEC23FDBA9A81D683DC3C1257E4B9767C321FFE98F36CCBC118BCAA9DA311B5C23308BBF34E53B727364DBBE398BA513247FA34A2D790FC26E9C962F836C525D575D53BD6EB206618B3A497A27535BB4FEF6E21
+706510DB029E17059B55BEF81C0D3B51385F6CC750CC3CC17518C0278BDFCACC961B313175F2315AF674E62CED7B4388CF3C99607D32265833697A4FD67804CBD27C3C2A5304446F3291DAFDCBF838FFC59E7F5B6A36C26A3707D6263F899299D74359FCF89499537620C41B459B9507E69A2E8128C55FC1C63EE08B35452A50D0285F06EBDE9DD3C2040B47BE567178859E6EAB579E97B4095FABC011B9FABF835A6AD56A708D4E852F26E907031BAC6F1107D09761A7A4A58AD1733E18C33B813DB3D9446D075250944E5A07CDC7CB300925B794E184A86C63579792B1BD5AA0115FC4514065C0094C74D25CEAF63600293437289A95DC43311583C12716ABDE7F355DA9CEB95110C0F4CCDE59D4DA8620F9F9952ED1963B5EEC1DC5BE6150741527261CEDBE6B2613CE59F1EDFAF01F1E8FD29DF7A7B8D9EEF465A62B98BAA1ED23AAE2BBD933E99CCFF9BF45B3A50DD29CB6FBF7BAED807A6F9178150226051F0EFBBFAD0CFFC38062DC3CA818B6F69C82588C9C47907E02FC99B397DCA71CD8A2F0F00719D90E566AC352CEF91DE48FDDE14778BA09EE5C150155E3EA6F21A36698AF3FA827D33C3A100A770956765D0B206D8DEB655D834646DC7AD0F8F65B781C20066FAF1C7F60780A57E84A6C227986E8912715AC058A173F226518E618BCAD601626CA36585C5AF7AA0D5119113A5E7A45D7B8B79F4DE1CEDAC9C2D9FD8EDD40D8EB57CDCF128D71CA8CFD342578B754D49C502D369A660A82ABD043F67C63E8810F2FC36C7207409608824324A2FEE565C77B6D6B52A255E338338EF81CB4E8935919F45AF37C2A6BBA3BC95A89F28E6A21FD2721DB907E35D67F63A9A45DBE787A315D0A8CB5D4EECC95C080F5820B0B8D95527202594A4046783E421E53C75C87F5D079625E714A6E83157318B84BEE41ED4D043138F8D64AA70CE92129E3AEB1AACE2C68526E704D5B9A9AEC95F733D3D48E2410BA016C213ED8EBB4710ECE2A3AC92962305FCCF517E31C65B9F2D833B90732E634F33784E467B31DBEB64D62B0AE8A4CD5B81BE73AA2C459549496434E7EC73C9A24C5CA19C640FDD6453EB383306E158A8EF1E474E856CFBD1E3C3CD979214D79F7FFE592CC3DDA48809EFC87FBEC4D750FDAAB36CB0C2658FC5AACBF8820FB768FA5959112D7D4CE7BC5B9C00CBE62240507DB94EF08EFA9324E0585FB9D1EE6E37F9AA453EBA264D452B503FBFB184A1BE3E05D81316F1D799261AB64D6E557D4B1191B9CC6A6304FC3C55B8390B7FAFD0D3E62B3BFD2E2EDE1D11F8FFDBBBDC7CA96B4F02B33E5E062BC7F7FA7879E053DE7D33E7C240C587EB57BCB831AEDBE7683E32F2D511A657DF84F7B1340184A6FD4C932A336B00CE82B05F7E2A743CE858CE69458ADD4D2127D2B3383B7357EF83EF7A6A7BE0E5A8CC643C24D03857E6051A5
+CC74499D945114390609B5CE83841D54D7DD15B27788EE2D4D6D4E3094A171BC4A5D2518259AD04450712EBEBC467FF12FB372BE883998AC9862F1421A6CD8602954BC5B4FE13B4C5A1A6B98EEA3AAB983E9C58AA5598229EEBB2DEAE1AE9F79E61C0ECF74F838B71C022796E93D5E29EFFD28DA0A23A8282DEAFF85ED11D56A5E74DC4B18145400278874EF1762768997D0892F19509C7D3D598725486EE738CCE55DFCFDACC49D054DD722108D396F44ACF24698B74D3AC81AEABCAAFCFC4A19EE7C2C30290BA82EF009C6EC63DB9CBF5B645C37411115CBBD9EEA3E5F4EFEC4C0A3F441523EBCDE75DD5AA384909F3F7BB5F0D34190D7BE1B5DAAC374C66D82467A36BDD081C5BB2363827931158454E2923D13CFE622C4EDE83F9D5743DF171E90329DB74B95FB73BCA31E524BEBA8C3E1CBCB840ECEA87DE5524E4F7B414A39D87C7C63866AC431882CBFF4E2CA5391C4D28D26A7DDD87C34D3C4DDA70516A902E5998F6939DC8AE0062A6E1FB8DD0AA3C4C5E0E3A2304CB77F266E2589FE8878E3E91633FECE44E54B2CDEA67055ED31637E410B66735F2075398A218AE93A8D75BF50CC8AAF67905CB3CC0BC9C9BC54426AF1D493A11313A8F180A3936BAF9DF3BA9D1007A07B89623CA04D44952273760B0DD4ACCFCDF9150820A9861B909B3F615B7752595FBBAA600C64C8CCECC7829AA6730FAFD17B3C228DB6AC19045A4A81D8D2B2FA1960E7B97B7CE6F9E8E64C9F31608B769DCE52A3A9C64FE779C28E3EFEFFFAF02DDABCB9F560887A68C2A32A3099C212BEF39B60D7CC372B27516595FFFA7C761F7011C9CB507C016EC70198F5639B8E8D9F3BA748B8F85004179F6B57E0A6F4F0B572A90FAA3989B340B5D52557A32936F0CDC8C724FA38709CDBB081275A922166A72540729C77E8E7EF9770CAEA6E3695155FBBF64982EFE5ECEE3630D91AFA0B72ECA4033F1FFA6AE726BE70E4886E321E1D5BF14C5F93BA89933559292B3D3FB60E9C55E5786A54B361D692A0890F83390EA24A56DA1CCF9890E757EDDF695D155691F01D190A31EAAEA204970A800F8735566C1BD20934B2DADB3B9DC4C3C61B92467AB425606E150A303580B3B8C6CBE6D9DB872F752993674406226B5DF732E30921707A03D628034218AA6D59A89C1547A4735006894BE83C3E739C08AE288A20A65D0F8EDD5FCD0CBB47EBB8E1E4BB11AD3B799BC2B06959F932883D9FE54E8B72E98DAFFD338E5C49B3A234D7038792B448E0A9385F1C7F0D2D0D9144A519B5034A56D388CBF366F635DF10ABBFB9E168E8F96EF6066F2F8E4AE65AA5F2285246F28BC5DFEE711F8E1DF8CB08CAF58D122344AFB04DC8C1958A472B3793EB9871D998BBBE7267C6EF819F08AE8C9DEC4A4B806E48719B679CD0EAF4AF00CA4298BBDCCBA5379DB5E80A4E2FDCD1ED6053CA
+541C2E56C9B7A8B09463856EFDCD680F4D89DD6C95235859250E09C8E05E1E67CB5BC1F9C3E15C119C8F37DABF13BE3FAA3A1A68B2E6A64B8EB90D24199798BBC3482987C1A712BEC5ADEC0AF047C9C942CB3CBC6D45C569265A19A83B86F209780A1792E79E8E8091DB6C3DB99C7D389E53AA9F32E4C30E693FE99342F7E9E011A2FE9F106847E71D230D6C83FC106B1F3708CE3018D39BE22F99A3F2DD181617E0C5DB4FAF0E06016B7473DE20C0FE8DCB6181F7563C4C00802C4819622F8408BC50F4432E4853D7B8AD11742AE32DC061ABD5076E091D377456439A06CDD24A5C0C1927421462156669AB70B9B695DAAA5F7D2EE565D90755DDF6A8D311DCED77542E163061DCF54DEA63EE5B8DA47479B1E596BFF6125FA25154AF520FF0A93E3E0552F8FBE117F86B6B552F5F0DFCD2A09378C9323C9675E614B563159EDAD37D25032D82CEC63083C9C5ECE26341571E6E778239680D1F79407DBAC6DC20245B4268B69BFC1C0C2260A4E900F6382FEF1939631068350031D9880406CA425489AF59DD9ECDCBDED2A53E35FCE21818ECB1B1713F07B472BDC912C65A343C259DD35B2E6026C99BB2C22F19F768BE421CADDA122BE03DE6890BFE4CB0B67D6D1565F3AA243D1BDCAA4F4DEB03006A60196B15BAB3F519665AADF843B4F7B12AF003CA2799B52A5BA2CE11C3AB86B509114E8A947C4E9BBE7B8E62F30718C3621286F5C9A4A90C707205E9E2A5E1095DA089A13E220BC01E7C24C5A2CD27E30A78B76C8BFAF63CEE3CAFEFB5010A86450DE24AD8FEEFE4135156F46C782CA73CC6567D594E4C9C9C9559EA94685830683D68DC59BD81BC4D157E7F1A37F7A47A7E6CED9E0190419276DDBE157EFE1294BB986751EDD9FDD8C06AB75FAC0247BA576C8C7C564E5A08B4ED4F3DBBFCDE42419BFD7407EF87C055D3A99CDAE28E33FC2552B8BD19210C48583EE8035E7D3EB8B4BE8512C4169CFD8087F78AE8A97525446655C268A82832425F7D4325BAF690CB0A64517425BC95551F73BCA359DA295ABFF6E7B1E886D665F76AE356C6E72E4B3584B52F24B0ABDD26FA3CCBE6918F8BAA03C655BA9A9D46C2831B0B9A68756CEEAA38D4C4C7D6EC2B97C14D99E70057756E5CC5AB08347A0EC3268645BDEB2415FAF3FDA8762EFC637A10C20458E6718BEEA00A3C09473D4F8A756B5C1B151295224E0BF6149A73891DC00E078B584E9554692AD2819D1E71826477793738683F60CBECAE51704FFF965C753911021BE6CC29389ECBBF18A76920FF3B852596C73763920E7C2BCCB2B79EB439A94CFEECBC25FA2D21A65EC92B6C644D2A3FA8BED753BBE0B02075BC9CD520219F39B3A148A55D5F58E1EE0E0DB004051A326ED671AFF2612CEEA7871A2F519981BD110C29D25D3498C004342DAF7C45BB3F4C8E20F47EA3D7A3F72FC9A237
+9A7FB782E2B5D3E8E1E4C1A8654A01B0C63A90EDC9F2D3B948F2ACBE2866ECD2D5A41C964FF30EC836E0CB84D304C62DFC7B933061BE1D1CB9B6E76888FFF455D52E58AC9A897D3F86DA5B2A9A624395B09C3A56C52DB7633AFF6D9B6057DEF9EC3EAE26617C0CB99636C28B461818E3D53AFC937EFD5536A4CB33BC5B7C70E3C907ED5F977540B70ABAB3DA4B1608CF8EAD409531042FCF55FB8C15515D64C4BBADE300B5985D87FC70E42839CFDC2467AD591FDE0FF9B4CA6581C503690EED0D97B72ACF90B929C116C6B4984DD3AA7E18EC7BF743685D9E4128F3EFD317A9FCFE1A827586EF6EA3179A7E40B911226E05B36F2C311818B1B0032F46EFC1A224B9FFC588116449FBA40A220809D3AC32DE44BE28AEB08370CF321679500F9A1716A0F818E391699ECB1FDBF1D290EFC09906446BF2CD292F4EE23A44921DA0D139505CA851457EDF847821FB6BF4DF801D74C34A47BDFDE4DBF80430C10D885F92E1EA4F204B206965C68B65F97813AE53EAA84E7D46593E629B144CC946DE91444AF2041CA1963731924178F77A6B502A397806C7CBCD29FD323348FB7831494D3662030E4448308EBB9A4C9CA7D1D52AE483626AA64796364DE2DF820249F7358993AACA52629D1C406DAE677C66558198023D3CA8BF5AAE10C33DACBC0590E3ED51CC94A1B4A8C069574A855744A1FEC4839D3A676CCC4C36CFCF23CEE65CFAB5D2E454C9304C0ED2E0767E95F258E1B380A73804E4A00F21F311CB238618CBB0C79D2D9E738209C733A78F108EE1BF85F566B6041AE8C306956ECA40494B6661ECEB52B6F06BB8C12A24E8144A3A2CB19E62EE4A03AECDCE9282E88CF4BCE846DA90F86A040F96A0FDEC1D6151CF494FF119A45DF92F29990FC23F24A0AE9674B92381C89DAF89CE0E3EEFC3FF2C9DA32B2385F20625E3CF9B32D7F0DCA41793BD4C1DB808D332B509C15A577BE03A462DF4A97E3746543D861DB4FFBF2A0FD79118358F91B81107EE5345F418BB28323F01837F245B7E2525032E0D903985C289C83718C063C9BF01B8ED7577CB5EB5674713DA294796E5395F84BDA352CEABB8D131C59D10E4C5BB320130F5D75F6B14631EEF0A4DA1EFF22BBD4D2F281E9FDD8A611D7B52CE14052DBDA740E92F85E81E4E753537CF2E00B79BB3152C88A0383C5ACDDC2EB5967E6FA3A95DC00030A2FF65E6678F91F21BADA72FF761744AD603CFA2CA2E828C2E5F943A7583D62BEA88B950C0D603245BC78E3B862EAF7128309C21C0FF083029E318BF85177885F99AD2E8E22D6A21735E4548F2655F2B12EB2BD7D4FEA0E6B77FC63A314B065F71E74A29E138BFE6F4BD1059D3AF8C01EAB496627A4078B27ABD68FE30EE6626BF786EDA709A7E943D4AC9D91602867F93E0BA6D593C4DE895B04500F8F3FE8C49729D62A8B7B6F0A4E9680AC1
+E90F7A2AC62C84F0B521F7290C4BA728809670849E749DCF4B10892FC857417C52D5E4BDDB82E6AE745BC2FE63A5E3AC4AF4B9C18912318B3F955883BB09F29A310BE6C297464496ED49E8EE7A76407844B5D07C37D4628E21074F04575D7D217482812EA89719B4831BA4AA59B485556683A26F9BC62ABFC5C2377D8D984BD2985471593F1E05A63463D01B1B260ADFEC6AADB4F1B49A3883F0456EF340841D3882286E98CC9D2BF1CBABFF5028884A6430D90F18356968E08AA75861D2C719CE1126F71E49298E4D098420834C0675D2C717474260FCD86D745C96E9888E6F05D6AE849862BC892C1A8D5ABE8FEA143F0F0E085AA61431B7CE23AC10FF866EDF338A6B8916514829B5539FAB60748BF9C1302D3715E3ED7FC7DFB05FB3E29619F5159231FCCB35B56776E1F57DC547D4DE3E8070E682691D0ECB0A0F869EA7C398954D63918386FDCBE5DE85B85E62D69553EBB107A8B7E172E607D4DC69C39B7216E528D2EC0FA50A5BE0E675F1F126BEB3010B5C1D724986250AC234E944E091AD86A6C2A4D957D4FA3599E56BA1EFF4A5C4F7746BCB89FE4400E84A31FC05E376677530BF610907AFDB10DC2F645841CA4DF2B3CD4CDC20F62D00162CE2DA71F311245DC43CD74EACDA1BC19B34A09AD9304D147E9FB9DB00F8BD0C438E72B8978CED64C4CAB88C50D05368781A2784D3598925E09E2900702FB75CB242D8EEC0AD35A9C0F4D4459F2DAC1710A4FD13A3770C25F1B080C2E96A8840A674DFC71ECCDE3043C25F03026AB6789EBA3358D456E1A90E269721F51186274821D7289100B9463A30BAEFCD45F75CC70DEAC5C2B4D858A794BB58C033E355A8B475FDD30D91EE539AC9299154CDB048F8163F916C009E07EF66F608E4F9A149591E7443A0822730467E2BDF3F79B99C2ABEA7A21D9E63E90663B01AEC37F8758702AEFA7A656CE292AAA03463372568830B60977CD58720C263D7DD42D78C5F088E970AA340007174AC09BE1DE27233F840A7B7A0C2EF984F63086F747142B270AC8AAA4E905E6F0D2B6CA9FB3BA2747359B1ABEA95029B092CB3D5848C0FB12A3603C49FE3BD21819C93AFC7F134FE8EE90AD00B41DE0196316C8AE90CFA8790330896B62D5FCAFD2AB195F3431926A47B7B10317A850BE79F5E607EF193454CED927A0700954C8C8FEFAFFE652909A9B93A625D80B86657DD1486733BE278C5D6A933B15DA263240F0A7B04623ED39F10E4C10264EE0A0F85D6E5C80A4572C28D5DA5710240BDC1AFBD9CB948B70B50F78B15EBB2D4A96F99434466E3E19AE4B9C4D3113B8B5A81CF60E00906BB3116B75D4CFCB0479F48D3DEBE8794E1B9710CAC72995E4BDCD5463A883CB2455BE45129344D3529B70365E92864B719A2EA4BE02E6255CB8B148C78F6990BD385E3CBD68D49F807B618C23047A838A90153
+8C334C43D7B00463473B510AC53BBA14737A6E3173B62A8F3BB165072AE719D1653D02C8161DD305E09B317B7011AA4E230337C0DE8E9DC35BEB9610BEEDAC9883A39EF05645CE40619D0116CA3173726E7CF15DAF90003B54423C879683685F906AAE77D9DD513469E3FD31AD0EB877B7F2DCFB7EBDCF15B9FD0EEFE14076841ECDF85D4FACE25BE66DB0334CD916D5922CAE7CA031A57573B8A07A0625DFAD0F6E6F32CAE6676B7303264FB43F96F4063269022E6AB4FB20C89272C3B7111C5FDBF51A35AB6435781E4D0D816EBDB4CD61C3B39A7C212B925ED90520D92085959BF4B24D67EF62532ABB6F819AC360C0B257ECAB7F9D290F63B735BF72B76D80CC34E27F934E6FBBCD780987CDD16892716182D0E3E1E727AC5B781A6DB80786B5D97A509CDC264102AB0CBE5E32BC2565DF2859580BC27D2CBEEE4B1F5646079E9500BC1103E8ABC314538A6AA62767B65130C1BDB67A3C69530408AD3B90E85DE0D52687C3AFB5378165B57C040723E51EC7931F4BAD22AFA3A0EFBD61EB926020AE32DD6FBC88D9B3A056CAD475A2EDF67EA3F517223030508DDBBFD043BCFCF19760F0C113628B14499DD0B9509415326A7446402015412F3080E21C178BF1977489206D3166CBE08BDB7D4495CE26FD4ACC429FD2BA48AFCFF7AFA197D94C8365C7CD5AEFA52F7D9A5E5585DA53621CA21156931B260C1D0B99E261C0E78A42A85ED752D226CE915312EA275611CB7F389DC22F7380C7F4D3201DAE14E1B49A53A4EAAD7D11A002BF008179959108D0C46892663FF125A20F026335733F40DFB4BB3C7DADC86438C7D8595933EEE96835176816F0FA1769FCC7DE8695B280A5B557F750A6A2BAF913FCC0A0B70806A2DD49076AE289DD88B736B189A68078C3A1ED283FDDE36E06DFA58FEFF9F8477B21E1071AA46A94642BAC7EE101DA8A4865DC4B87CC32AF03BF080C28F56A45EF1A4D7A965720A17059EF7F6A260BD292017F01DA92899C74D6977DBC1749614D1D34A4518677D459F1A3E2915ECEDA442BD6F82DA30C2B158F31C583548AB7B7FBFA43F5AE3F2ADEE777A7A5922E4CC9A7B90874D857CD63821356B4CF8085E27BA39F943A56576982F797E4E90478502AB1EE83C13669721ED1410082A710B63B8EC2F5402CBA772D8BD1F304AFA72F5EF7C40D57B80B7CA516E50541313FC59CC2CA0357AFC1D5DFF72D0B64A03D8ECC4E12BE33587CF1608FD04BA581EC87215843B393A0CF69E3524D902E73C300FFBA64CDA0C8972B9CBA27F0C9058ACE8BB37376A0F61E16E78C86121E9776BFD637350C1DC9DB4EC3745462C738E6715FFBC379E42D3D97E1AA685CC0467D1FDA424ED55FA5D38A72C0C4B350EA5B250CD23B0BFC1E03E68D2A41EA9A3DFC52F89709AD4DDE2D22D2431C2F8D77A617DC3C825E8B9142F97049A1D728
+B194C5B8434E1A74ACD2871A0BAA3EB060382C01D53DD557EA18C18C4A1E94DF1F56DB3BDC26F0016713D45F851F93A42AFE49CFC9978F8C60399321E31A9E88C72EF173BD86A05213232DCBB1102E98A1D8535F07D033BAAE19E5231D259FB49D34318C63ED2A26BD89CEEFE3ECA8A095F335147BAD9773AB72102B7EA5946F01FB2B228205AE966F3CAF57A180B71E60823F3FFD5236992CCDB21F1FF347855461FF17B32C94A9855681443DC5FE9405EE0E78FB58EED570D2568765DCC2E5D4A2584554B63162D98E76E7E2DBBCC95505BD99658B1185D7D8C0154DCB4F035B0A94B4A4B4C2745BFBA1F1F54B253F9881BBEC9ABC46005C0D68C10575B3154D5DA7B82E751B018A0DA494009EDF8D1C0184AD1831DDFF96FAADA8C4098B0137C81390A2FB4A9210EBA96A7777A0001FF790767F1D83C864FA6A2CFCE6F87A51D015F12AD78155DB2881EFF380043DFD7DA0EEA78D8F0197618882CFA4699880E3F3CC89EC5E605586184ACDFE513ACD417DC53A4B50420AEE55E980A6C5FE97A3C97F74FC4F7C7B711E4DB9504AFDA0FB3C065F4CBC999101A9DA89E377AB543374AE765485EB980A5D848F6F10CF18DF9DAC10E8BB3A1080F05B1612EA479EEA112E256FC59520DBC6E5DE574EADE9F572CA738C8A41C82ED02BC3C57F49B58ABE419781D37BF3E327F7480EB2FC29B5697514263B9DF03B0BE63E13374BA853D409E0BE80ADFA34AF1E39F2A8791C21688B2E93A5DCF9FC95630CA239E6833A844E4524925A18B2B5D5FF2B4B8CF13406AA075951D950EB43662978C70F8A8BD7AE7925E53756E0DE906A3618593043936CC5D50DF94400ACDFEDB88F6632BF46BE8CC9F1D3C601A06892B8F6975EBF88997AAEAF51BF0682FEA82D653792033304E485A7D1C1E117EF62CD29FC6BCC63D634151281FD0BB7BB634004272D6CAA8CD596EDF5C7925EB97FD8B235B063432B1F737AFEE7F3630E9D1F89C07DF419E443E748D440C71CF9208112074FA6C8B236B199FE84F7E754337D468DCBF446246B0D97A0EB09CB77636529BDAF873DF88594B307476F29ED642D776150BF487CC4DB47AE8B65774E934AAD255B65D6E37EF3801C48A777AA045D59F5880B5D0ECDEF785F8871601480EFA4C3DF9E1872EBBA7056B8D76B92EE87C9DC1BA8140A0632A06DD0EA289ED4120EBC6CFCBC8F270DBF14B2E8C59AE2B78A98A22899F3F4797123C1382CC41A2A190A142E963E7DC87D53C4E1AE08055BEF59E30C228A2313FE02D858EC668419F9FEB3DE50023241B421D6AD0CEB2FBF9DF8CBD83098080B3B25F75E4C912EFC2D64D9AE5503C9956F33A239508A6E43A85CF04BD76E8FBE928DF44DF63274C983E74DCB37B899846CDB300750C2465CEC0BEB6C02068FE99CC9A03FAFE1BD389498C446F415BA7DDD0BCBE85B01345665C2
+35B8F09B6CD69B35EC9C3E1317915FE87720F3AC3B8B8B0FA5ADE97D996A55435E506D1B4FE49C1F65C5925902B4C52BB2FBC72BFA71EE5E814D070896A7855D873BFD9B45E311A83307D82E27FC9C8FAA54AC756BBFEDAB16A2C82339F6F5774AF9528B52B7AE2459D6CAAAE22AA71FC4B99A858C7C4A4FF81211127C98DE09A19451B104EC07BC791B569CE7B65B6788D317606B494358F06022AF8C2A1043D976B5B67E0B139AAED8096F57ED2E422B8CD26E5BF6AF0651606F97735F67C5494BC4F35F923EA7F29D95A3765659951EE5C3C08885B3F38076920A8085F687EA141C35FB9EC90BE4BCFB42DE95A30DC83E3EAFAC8170A2D93BD85DE4B23B1504821798100646B5DB836E4D8A693FE12CEB7CAAA9BC902D17E827978968A864DA1A8E54BDB429E47CA5C188F3DCA90FCFA1DE33A6AC2D82E4FD27DD2802546BD39C6157C4671703239B88CF44740A1F5DAEE793DA2F0F58A62FCC2E2513EA89EF971E7E39A72A49F2138F9D808D3A105729B2AF41191CBA96F87227182B1A03F9A96D155B9C320B61685C34627BB22E05AD2498C8AE458EB0736EA06079941353C567CF528DBA1D1E3409F4329CF94130EDF5DDDC9A971246EE19705236E61AD3E1F323BB35A46E9C6B58B5874C573FDB8DACD31BAFF7889EC4B6DE0E73088E9A05790FFBF03888FB7DE5ACA360BA04C2A73BF718B15DC50AC027114CC0760672F2138665470D66FA1DDE0C2E4786D3114D6A1C06162DEE62F05FB77C9D5839581A179FF48AE4F3EE7F52295B4680E216070E4B509A17DBDAA4EF4CA9B12C185A51525B8C828486E39C4885F433F2A25D963CE77A994827079741D7D8C0D480584EA88B1D1DD8898F49AD7A79BE48614AA4F04D769DC66AFFFE878EC5A379F01F5BBE88E29BF5FD006A5046B8B96959C08333E74701E6F4AA8629C57F58CA255870C210C617F8A9F6461AE3537C3145C038DFFCAA2BA18754C8F94DF943AFBB5A62940E22CE4BD69459BE4097F5E2797014473AE67BA9A279D73041FD8DC59482540E6BED47D155CC17FF33B072857E2A7672EE66AE9747DCA13EADA03E97FB645F3B9B61DC2B2139DFDA1E16B914555BCD19B9B4AFD7492ADA766ECAA1656121437BA0E6E7C31E4303B68DE43B2151A6C8DC0B250DFBAD43CDC88EA55A9A480971DE90FE51E36D0E804C218FA484FB5D5E73EAA008D2FFAA599C88E8C844A44F155FB1EFA89298B22DEFE272B41BB94930628053F6F674E067EEF8EF812AB5886B5032CE4CD0107FDF6F090E004BB7A7715F3913CC2CD73C1F0C7393986A66BD3C67D6ADFFE30219B3A5298FD7D4E2D5EDA0EC3E89D6612BDC0840C7794EF158AC58521A1AA2D38AA57E7158C7C57FD30CE95535DEAB6E332905A39B07EACAD53B92BD8763C27C70AA59E1B7351CF4B33D41D24DFC299E2D35BC97FDC9FFD6
+23A014C77B24D8D6101F5579EBEA9F1AA6F1050A1CE69C7C08368DC3FAE223A46C76369B7E59671B7404F50B84E51ADE1F3C7E73DCB772D61FDE0D6049467E0B0FA85290A1E2219CA2700AE4D1E733D01DA8080F74825BEA9F3377E0941374FE01D9F2B65652BCF125AF97E4073A0572CC1136444BB60B52B0E746983DA0FC78FEDAEE104900824FC95C20F44FF77C5FF8E297FDD147292BC814D0168BE8F2FA401CD0DFD91792BCF26131A7FECC77797B2A93CE18A09F33E2027D5C22D846E388D8560B96FDC663D4C556F142BADAE002A0FC8DABED068703DAB66B198982DACAA934D91EA2B9462C039040B514FD9E5B57CFD82630258B6DFA270EBD3A7B53E09315250CFE1A4419E65093ABD82EF42DAA81B842D12CC9E6EDED64411945A56011B672A300720FE1D4F5AFE7E93036C964B65FB44C966C90AB77A558D64D85DBFFEB89FDFD84EC1585DE2477686B7768378C1A1D7790C8BEE1C570374F826983E113B08278A01DAB2E0ACD7F3AC4291FCE0877BDCE89DCB8E488CB53005E674CD29D47411FEA7F1714467B013B977BB775DD5B98BC156B39763A4A91CEE7FF54320A5D52CFEA0CD76DE2D0B0D00F84C8CC3AD6569E2F565DC0D87AF5ADB83498D8E57E927F9B9EA9B4737EA5DEE1B52B7561BD892764A3674F7AF770CE295F5B4FFFFAC4723282B6C1401765337565D1F58F8ED795B827530EDBCCE6E6F37C46DD8CAA2B2E38920654114F43A85125B94C1077FD091691E6858EEF76E931C8B97893CFE6C2D31F93F4989C8DDFE46CFFD3678088F8C0534DA8B26622947FA29B251DAA6542B6070F84D8FDCD8A41EB1F3FE200945504984E652F25B48B0A0162F3D828BBA769BD64FBEDB636C1893BF21D9BD66E83563C3AA4CC1FA8E14D3241956E07461F8EBF33B18300DC86BA49D1710BAC292E9A9DB0EA86FD19882A41B2D6AB0F6A880281CECFEA97791BFA0C05F143E8C955ADC8B8F63AA6D663CE2695EC5107051959E3CD2C42DA8708E99E52519F23706A0B19EAE600301FB7B6CD48E4B617F32CC5C7506C59DC607774A75E947C2A798E389317E61713E7C999BC74FCA47DB24A27EEDAED549A88E319B50C91BA23D010CF870E669715FDFA51CBCB4D6087DE1CC5D9EE00778930835747300444D712B153802D72656AF96A6C8946F18F3B15CD434468780970F21DAA7FF31C269CD92FA3E266E433DDFCE331B3437A196EE5E4517EC913BADA917DBECEB4A3F13A9ED11996B8DA1256B5761E6D450B691322F1C09A079B801074C371540832EA90C6E7B249979C99500A262D99A9728DDEFA7520B18CD8EE15A607F49722082E48D567CE4CA87F61946A9914BF39FBE205578CBC3B0195C8D92590FBFFCF5B0FE2F409CEAA3EF5A40DD33F575D8F2845B405368E1CC99096B6DDDA87E9326AE1E19E6E71642D6C1F25918C28D5
+17630FE1A1515F6A341D81161F2F0FD1DA3A83B13FC9CEC0EF57CD9C4AD7E8208A85AFE27477ECDF965D9BE5934A750681026512960564320A1B4BA628C5C432725AE26004D0539623369EA50A3C2D305B8D27EF2AA3594FCB9FDFD5368D14A92358C3F976BBB8BCF239DB66C2C4CEBDFE5626F1330A02F3D6DFF908BADD4B88A4F2018569610E6878CFF25A69CE4C94669E834250892ADE4098C61B227A11CB9D384C6377BA74FE146E571D48510548DE7FFD559FAE449358E7E74C3998D3A3165FE8D76029D736144FAD10DC840808B14BA5BFF94848E3F9A20B9D53D0A793331DE64FBBC4A5ECCC7C7908DD8F73AB964CB26AAE0CBE39BFDA268FF8F022F633443BAA5B0FFE47E7C3BBB73FF2862146ABFA7B4A3C56EDFA23F5EA23CD58211546523FB69EA9D173F7CA4801F69055DBE98F82218767DE0543294BF8919D36CD83605F3DDD2140A2A9EEE26853932A735EBD2E7ABE81C9D7F5ABADA3AB97B80C5D496DA306ED145E3A0E923CECEE730775B723EBB218A61ECAE9DDCAF46B656100EC9F9B81C67A432ABADDC8769383F853899E6B7035E35D0AF88F1CA742DB5BE97887368FC486D845A2E8BBEA2224644B76FB4D705857B25C7A521AE9DFE834B601DC073099BDAE191E2CF8C002A708D85D76E3720393EFB3112C155277E40E6C3B9CFC96A26FA52F9F7C610D1857B9A47B0F304FD928B3BEF60292108C01FA394244A5C6493E738A1F888767DC8B9F162E3D86BD444F35B94CD36773DF8F4ED62AA937836553C86CE6653703F9A818801CBF8B6CB9C5A355E52B96B0E0A4B1EBD4814C252AB3BE7096756618B79119260994894C12B0E61277EE5269D6107F2CFFED493C85CE051507C683F3110DFBAA9920E844B698B7A1B962534191424665E2B78245565AC07196B4B55E8D422BF4B575A109BFF374008D396FFEDC12821ACF370690410374E7705973D92B77E2A16A974741133D7F24AC4041B7BD433E126A2391475280CBF8F532980442D7D0AED5A73B83B836AF20D75BE517D89CEE020E15386A718C39F97FF2CB3B69F6223C6CB211C01D2EEE08A11B9395BB17A189E94EF755FFF51078413B69DBA35C6BA661FB47CE8B1274805384F48EB50D3B0ED577F204B5FD6B036D4105F44581CD52B96718D541930A61CA86FEC20C61279066A57128472D2EDD9BA012D2566788F548F2A50094C01C447032D384CF20A799C4AAC41B2DE57BF91F8D99D414D0A16F628738207B156B48C043CE9113B7B2B7885D5EEAE08843D084E4DC6660C4EE19316D7960B8303922527AC518A90DAC08D9C1C958FD5B74E52139DBE777930FEEF7950052C034AFD83EBF5149A99C2CA520F5AE4ED173C9F53C18D4A9FE7B29DEC4B1B2C4194303984447679D5178E894C2268091869C40C311DCE9282C37CE901365071E9BDDBCD3912724F02E1F
+27B0B102FD18BD02296944DD02F609702192128FABAFE94102D39B02D7FFE36BDEE3E36DABCAA2A16CE2B76A7092EA45E78A57C374BCD7CF4E3A7D316EE6DC8B8A7B73BDA6196977A51D451FF4F4DCB1645E0C1033CC04BCE02BABEB1D22C6ED8851456072CFBC04528158C392DA8364A9FE9D857E41263F828F7747AE29A12962EF18D70B16C307951F1DCDDD4CEF7CFFC4C5EE35B74F424D3A15DD684543D8F01B508A62229F784BCD44557903A9AE05C7A302D85E24FB29C18325AE9BA65271EF2E910764BDF9FE97E63EB7211ABB4A005F80138E307ADD3675CC501F6233536627C994E644285DEECBBBD42D207DC8FC0D939AC7F56D8556F919E45FE0E7C3A2B28F4E215C7000B8ECE47CDB2CB8C705AC2447EBEFFAFC9D6C6824CAE5BA36DC2C2094141F68EF343EAC0D79146CC39E0F1E8712D3498E468B96BFEAEC35B7F48A78C911AE6AA44BCC2FAA405CEAEC959544E65EF8687EECCB744B01157635B81C46EEC013C83FA68B4CD83B26CA4CFE3369888F8BD95E0A4586D07D6869A1D88EB584D861DF68907FEC6F5AD4D7E323260F2B99B0E0F1E40C7FC755DA28F2D2DEC42114C49A7DF3E1A2F2E86A79392398DDACA49E5BD0C64C19CC179CF6EF598E4D0730C6CD69A85A5445B19E79E5BEB108999F2F4C507897B4E34A50374D0314D1D3241F5D18F4783CCAA3DD441067F6C0C0D6FAE5C13BF3FE8722EA51A360236B90D04EB23F6825D38155DBC4A8250B003338A92FD25E0FFDB8C8A7B2B1F856DB1E3BAE41142EBC725938A57E4B673F85AADADBB72100CC02E6A28EF0A736EC2D4CEE747ED1CDD3A8711ED41C82FCAB361957C9A841B903F6E8C27868EF1738542257CBCCDF68FCE74B54893D8300CBDCFC530D140418888675926833C8ABF76D8B585A2A4AA9B9E944C82A6959CE08C5944BD40FAE2511A01B448A705257A7B32770010970AAE1AC355D8C8EE14CD800B399749C122C268FD6D77CB2392CB8EC60114D733EBB4E641DF126E171EEA7C4C8FBC5FF6832E148E0FF860CE2E075BA35D932EEABBEEC6C7E67A9E3DFACE6BAFDDCBDADEF4892EFDDBC457A414AB123CA02B0367841DEEA2560FB6843F6AF33A612F1EA83E46BCC45218C67F87A527A26E04025ADCD3EB9C39E1EBC1D12565C1CB5D04BB3A6D3282D0003B972EF89BDC405398FF1679242CBDAED2AB722C808AACCB6B09E02A9DE6FF8232F5A9AA5E21E5ED6ACFE856B36AE5A49719DB189A20B36365A108E956C0F7A93F0FACD93E636E946DD34B1B0DE7D53747FFE88F1D4C1D3B47B5D0C4A658154CF4CB206014F747B13B9A78B11A3F11A3DF010957FFB308A12078C8054AF9C8CD912F5210241D8F2826FB76E7047148EEE87D2B5CF701601384970C67F3D3BACBB1347A741185C949F7AF03FBF8412F034ED2D2B2C18A5DFFDFF4F8D6EF096994551
+7C2B57788A9E6CEBC2036E4957C05AAE322F83D30CA012CEB0CEC7193E3C7FCD751920264EE1B93EDFA4900034B0B36228D383E49854D9A9C154F6260C84B1DA0D64FF41320D95C3F20C5F5FD09A8EFFCA4240476B6ADC9652CBBFE6C36FDE29E4F50B0D2D85077C13456C3B144874F49423E4ADDE1D27EA75AC52A316455E0F714F7FABB84B19892B1BB0F8A27282C59EFF9522C105356DF1E314E38A470995E36739937445C0D2B7F437BEA82D3ED1DCF40B9DCD5CB0093ACB8D8C1C3D72A7F1C22429497263DD8B2A1C11713273F247B92D833B14DB478E3195D1F02716B50AAD972338047A29FF28A39B2F9BB484700D1A9241C192E4F1D3C691D39E7BCB68B514F3DCF6466874461B5121EC4255A4B92EECC5ED92504B9A798E2CC10F4A20F52086A825D65056544F790752BE2D27C2CE9D9BDABC7DA9A52728D4BBC623BE041D24BB3C89B275217B4928C20433F1D2569DF80CCB157810907A731322E06A1D5D680EA0E8C989CDA0336DCD7F2FEBA53F5F7D16FF3340F1EE223EC40D13B4CB9DDB974693993F22458F1EB37F6A4B19D93B0488FE35EC8D3B225F38F6745CE13337D6FC5B5DF9795C9EA11ED7B410B959C4CCF380CFCA84DA1BFABF6D24B91042D79D5D024266426195BDAE4308F638736B4BB98D5F4448113EF4D7ABF8C534B2D1E255DD841E9104164C661ECD0341EEB5D1B65DE4A64E7A484977C4623B05D0AAD6EEA7101297C1CA15D687EDF09C086DDAB3A231985B629F9FF9D1DA8A9BCC979A927890BE5104D48BADF90D3DD7AE933EBF626C46D670D297D1871547E5BD26ABD203A8B4F9276646A81629137CCEF9F277C608405B2416573F92698EC8BBFD5B1982D6FFE87EDD3353B45444A89DCE0C7468C288C64FB6BF23CC9038E4F50731A3967A77F717C54C30DF911C64B1F5EBF262C1E36D1E65A2BDED7C8D816E9815C206D1A7C9602DD5528FE8AAB60E906BF8B1A66F5E676F8FF138C828FB019928B81A182C98DF57B66FC9C66A3F68AD349F09AA8F3ADC92BF82C103075D95281D8DDD74E3A86DCC7FBBF7DEE98B2FE539BAF411907AE51E591CB8F10AE4E3830F6F07923E0229EA6F0551BC4F82A7673EEF2BEC8E4BD96432F9E04B46F6426A2204EE32C6D1C6DCDF98A09AEDAB646E9C6A4EA701AD3438C57D201A56353CE9B4E57066AF1D4E4934758AB104ACBBD5516CBC4B1D0D73E871D9C5A4A6F57FFD61E7880D4C876D9A95F293483714A6E56832A28C0A42C0F4E97B56995FA0FA6E87725FADE43BF04CA832FF37FFF79A6ADCBF8E605792AC5E020565038100D83B83945EE7E40CF8294FD8D79D284960827B87A536B3784FF0A52B407FCD4A7E5FE271C8FF8FBD2D3FDE9E922D3FB2AC13F4052331AC33168637B1E98AA1D9977C8B96AE40DABEED268792E7A6087789136EA74E5CCC9E42B762AB69BE
+409BDDD47A28EBC021123AD39B24E7FF6A5938F1FBD54B9BBC3089C98EA86CB0D597AB86D9510031A57DE31C73DB04D2EF71873AEE05564C59322BE225BC272C6915D5BCCE6A6D0DA073F1543A30B6BE385C6D18D04805A203A1ABA23495F5A1B7AB4E9BD324F91F658EA9BF9D4C311D0649768EE075CBAF15243180CE0BDC435139EE321E87EB2277EE44A57D70D6074A6643433F9623E14F1F5181B3D46F70B4513E9F11689DC80C65D83FCA31F3AE446CA01F202B15F4D33E233C268AAB11F7BE0946B6C3CCC72307353617DF61A33E75BC708E1869ADD23927ADC77E32BECF099569ACBA2F3099C9B31CA2D4468BFF0F78E73035D9E9F6378B291125FCDAC5536686E2AE7318B2CC36A88EEDEA8775CE15E67C9801FDC89FCC261629140AE2E28D701A12F5637DC5954E6CD972FA7597DFE555D88C62B100C2B2B20C515E9A120DC6854585103B120B4D15D1DC8DB67CC2D7E729A32B021495A1E2519A8275B1B1A0D35C0223F74645CA5FDB48C2A52B592E8F009EDC835077BE9BE4DF6EEC0F5FECBF83F58CC3317F953EEAD0167CCDA6588E579150C18C819A023BC09B1557BCA4D442E3BD28947BA69819F235A2E9C0B74F79E0733EC205F367FDBC93AAF4159DDDC8E7AD968FDE84D4FAA241363131187C83D05E73F135875281F296BFD4296125A88B8CF41C8542AB2AF8B28A1FD64FBFCFA237C2815777D352E1A9B91CA3AE1AF731F05B219E015549DFEC9450307AEDB80AE279D3BD8218FFE5C3C38E6D2FA0D8D71EC03C5D7FDFC36995C39BF4C3C3A06A32982F6286543D8C1AB5C222CEC89EDFA2932E1D7A0424FD19D66DDDE5813CE7B337A8227782308A9BB46C58922B1C1B2A69F1A22CCF5F4AC1E14B4626624FD2B8F6135F7B30126760E9D6D9DD1F1F4B3CA0BD5DCFEC00699DA4324445DFC8EFF0B4E1E28E45AD4E7B0854616B12E0F854500DFAAD65DA4F9375A5772A6164E3635974C014A62BBE683F463D48174AEB423D1AFECFAE8892B41BD2861C4E2DA2C3528B819A19CF2B897C7AF4BA65D2576B42ED04733FF1EB436305B06EF80EE7E25D814D41C4CC980B927AC634D36B8BE3A7B135515E20A69DF40A802C9C0967B73E6E103A6375773FD98F0C1D354FF72598FD41F701B17A97A87BF46B406586BED77FBF3CBE5CA8BA494703B61881D7261D6B726305DFAA90DFB7AEA2A865D19C3991576A03A7E57EB3F3DAE2860086B4B911680737099E2DBCBB1CF211DAB029FAA1C59358FD78CE91563F40F0CE27A6C4EDE6197A24D5E9B1AAD44770D7B915E5395565B523AED0EA7CA0C8FCA35A20F64A093229C6352E3AB1F26E871AD9953A31F3E9065DF8FF85B5BD91910419F9F7DA14FA155EBD0ECD810BCC0406C1021EA1729E4424FEB1D9831E278D7C0D644A999F26C9A972A86297AC1790071AADF41089E22A476FE3
+D8C35C2614456A3B8E6E1F359DC9AA5F6248F219771969869873CE86A33CB0D7CDFF735444656B2ADC0C9BD68C39466009C55A24D2C01AD0A3501CC45A1A5BC8A3530A5B85B35144FA951B98A66B2E7350B2814E7C69169E14071C4C4DE562D35B0C058ED25BE2E894E2DFB00FAB44B7C9C0168F5811BAA9CD1D99DA0A7943CB68DD51A48DDC58146E22C3F69B8D68435FC78453FCDBE55903711187B74EA531707C9B9C0DEF3834552251A5CFEC8C28B3B0A9222EE627DFF1FBC51FEF801260B1CF971B84B28DF04594059C89269FCE5F4D14C92406AA3B72B8B24B65BFD9D7E7BD1D6BB96784A4B84A2C66D9312011F1F7CFC5AE7427662E3C64CB28155B5683152815640DEFE5D60532307386B333DD34A0C244A1402D9F79A201871AD97A31FF13505DA7B19B7CC87D19961801EAA37798F468ABB2483F7F74BDE8D0BC8D28BC80749142F946027728F213EA30F6D792BCFEB46285508FD8809F41F0DB6F7B99545E865381E5901751C88C18C0BE220CBDED996A307F7D924683450C42B6D083A410289CFC0B00A2D7CB7E81FFBBDF2287DE5135201B9AD69D180FD71F83517559AA65510BB5F476A95088FD00C49C1636CFFE0773E7F69AFEE353C82AB8C044BAB9C51B2317FEE3A712C3EC7910612D31876A1C94935615C345F5386FB8E7C7A32F950AF3C91C221B6AE17BE7C98D73A170572C35EC44D59B7BC87BD2BF151587DC96E2D43CD2F63240E883640D917B372297CAB362007A403C84E5F81B52917722B9B1674C8E292BC35A0A8203DF93B7B9B7E76D70F59DC0AF6D68DCEFD6558CB43A378BF4809E513A495AA1DEA93CEB9389AA6171775B6E61ABFEBFFEC2D509E88435864C6AE3D6DA57DF2BC5BA820A0E85FED597688117A3BE01C5F4F2D7DEA308B7818FC054DD414F9A5D00BB4399EECFBD88723E6AD180D0C3DCAE5A0763A6463B261C172E9F10C3DE53B6D1813A176D83EFBFFA53CE5624662DDCEF287D0520D7B3ABC88DBAE77537F358FE8A8E36998B8069018FF2310826EDF4DF93F297E5F12E2BC05418AAED2ED30B6F17F2A376C1AAB8269804EAC5954712FE69EECE1E60FC936732B5029058DEA94EA6833258E8C6738ED4D18659CAC99FD697E6E0D4C6E3E7F41D1A471F87A5E5F4F93F92193C19BA613D237882811BED7EA020A817EBC5B5BD3AEE65FCF865E836C3EE186EED6F27DA91236DA3EFC438A889B8430ACFE0B3864FDB40F8F0BFB1488921AEFE434261790EE601255669099D713A4BDF081D0D7AA8B23C47210AA7A42C4CE705200D9B61C755526068CCFA25C6CBB6D64AF6E318AC62B88F5DC8845BF39E5F27B1083A78ACD342B341BC878FF03F67A2DCBFC4A8004FDF9B6098C5F313D7502FD73C46790AADF00AD7BE23B434582F79D4758F7FB7440A10570E2296AA1924B4420AB59DF3CB59869A426F
+E97365A47B67DDC03C5FB804C6BDF23686750D0FDEEFBFEAB3E6F69F0C6C294850AAE5C510746B33F02F841AA40792183848BAD0546CE15F767C574CFC01B241EE0DE6470436879CC17AC8B68BABFF779E478174B2A8B2F79CA3F53DA578FC7CD259EEE1206013311B8A3A68E8924ED12E85B09D4A239420D83F2321169C60ADE30418F2F5FD5F42FB2FD27278E6990105CDDB3AEF698D7FC50941E7B302B151164783E4B5028ACA0E8D611A58A242CD7844ABB769CE1451A16B2D4444F5318B52DB3F479CA48D0065D35E31077109586D8534E039EEA4B21E6713B9EF4B637F3BEE758B24EE0E2BED2BB8B14E3296491A2A094260769E712375B1B6FC7A5D63432E6631211D5CFFA2222FCDBB2CA2E234ECA1A02C434719C56812A6A82D1FD663209A58AD633DBABB47CF61711E5690538936B4780798EFDA57F2261A5618F6C062EA41669371DF75912C1D5DC5EF018B4DB48DEDAEB2A10A3960F7CBB1502D1B960AB2137F7AE43B7135E79758EC19F3D3D6C9E8BDFE023A7F16DF4DF2148890E582492CB081436AF050D8ECF937B1A5E298798839C16C305128CF5A7241F9E9797261E0C2317D5D50F5DD3C51F0B2C1731187F13556AABFB8605CDB3EEE988604405068969968CBB36F369E03FC96C7BABB2C1FEA5A2B2182AF0FEE35B80EC9B33D81F5B1F53D66DCBD8DD41190ED039048B1E25B4EF0FB89343F95282E97EB4E0EABBB1CB8005FC2925CED9DD1C2951E6EB67D57BFD18CCF9CCC0F8E673ADF2127E1A3CC7204296AA41020049191E6BF9D18EC51999EF03E378FF0273A1725E2BD9E22F08F209BC26EC211376D676F036A3453F1F989F243D6B5A710CE8C02F683331C0F3BA546CF720B5928B86D2A39054593B2D7496A7B86658995F0159703F34AE66C4F053B7A3FBF0B624E664FA96935884A313E05128DBA70FC79859DFF3026CA64DD0643658D754ABD214B6B35A81DF4A7C5A6E1789DF7C165B9EF1341F5DF4F0D84D96D22037A61D955085F034E44781A4D16F5D014AD5938F61C5C6653A80844C65234C71C0D4165BF877C79A041552943225C2E5C5865E9680B353904E837C67758F58A406D3D2D03BDC1725DA370669EE6577EEC50524170359CDCDA88818CCBDC8BFE33012636F0429105DCAEB7B1ED5760E89B44D16B864C01CB4CB541D62BD772C3848A1CF1350592C05A3934D0A5DA05B005182C0A83AC5582FF892769557FD9261842DCA554FADB4881BF7A267DF22567EBA40863CAF9EF8A5084EEF7D2618FC156537050BCD0A926A36211D75F60789A9D85C2AC44844F82D053E6C777276BD15E8E40AE22E67B69402D2EB16E4E913825065E3DF3F192C5E6E4D3CB529B67D822F1FE44368104A90FEE0C8EA1493A3F095ED29C1145E4D56867139B59E9885BE7D2C597A4D8A8B1017F56A20F625A4A10DE99904A05
+B954203C65A6177004863E37A9EBDE17E6A62E1ADD6DBDDED8E85EA46F5F6E87A3403858BD5F5FD6CB4C11F696AE41C2F31400AAA716FBE30C4531D4C7B736A61DD2C2535B66AB660FFB1A411E7C00E3A855BE72251D9F8B48A0AA27868AB27450F1DE01EC0E457A97FAEA3CAE307E97BA3243964081D45CDCF420B5AC44C724AD5D74ABC54F05D4A2C074810890149AB0C969338E39867BD740C6618C5F72F4E759720D94E076463346D4223DE5D3455CD53FB83956211E666721AD8CF08EB76F4608401B72A578A269BD05BDDBE9F38E106F28A95C124B906A08D1879113F6112D24FDBC12ABF61BAE5B5B096F95942090D5ACE4FA3497D929C90E9CFBC4A3BA59BFEFA0A67DD0956AB8FDB862C834E8437A630EBF4740AAB5AB6C8314DAF3FBDD19FE3566A0A59BEC07B688B715F03A5694E081BCD4B9A1D8460A8BEF38585D245E2F4B5E8C6C8EBD3EB48CD2740EDE9A3AA513FCA0C89B294620A7162FC84A7BE80E9D4345538EA5803A075FD532E5C02CEB8117B1A27CCBA3FC58D6410597C2AE166D23BD5815CE2C6B27B29CAF12D39A5EFAB7AF12343318DE8399D9672FF3C2B0C9B503FDD28122916A5B626093D6E56B1BB86CD721F2017E4353F9598F61CBA5D88E644ED94576526C8DDD1841C49B574F8FEE5826B6D8A485DDB4A7A7D57305DC16AF0148A22BA827929239CBBA3397B335013E4CE4A515655DE0E17425C758F398A807522B05E9D65BE176695D9D63D5E649639941E89E3CFC436E3238F50A380C0D51BBDE1B864CE599829815699BEE5128A859AED56647579F4B9F5F46B8D4EDD8A3ABD010B2730757B6266073CBA0852851B5898BD875AF164333375F4BB7307FE4C7D47959004182373ABCFD0E4AEE83CE002847743209909F4D9839F5C6D138A0A8311580DBCD28957023EF41774C45E07D2319EB258B9D94C14ACC4CC1A6DDE7123F1365FE745FFBB54174098185388C1C7738ABD12D926FD44062CE685490012232CC7DB87DF82819F3D11A89E2AD7D5832A9827F6A2875E29C8C7A35087306A8236EC9FD59B376DFE5D94A07FA8636F5E09DAA89F2C908A8855B5703F18A5640F8C0D67378539ED6E65EB04A6C12291751B59B0CB58A0EAB16FD49A38975C98702D57F2F0CC1DEDFBB2A96B84B6702F19A2B8693C711090DF08B74F0AC34F93FEF22BEEC0DA50FDEB2BE56BC9245B4FE89E0774C0BFFC80A7BC5A5F1A91C4AEF7D30DC1579FF682AFFD59E93D6DB6949A191EE83905B68A3457C40920CED2249E5266624533F27D1AB96B5B8C8AE11831771105B305E36E4FE376D729DA7BC50C9EBD80DEBC935A1410481E13FAC33A2DA508F3FC6A49FE93FEBFBCA0FAAC76005FF5D50C88122F3E25A4D43C84EFF4749FC17C40DACD3FF8EAFC6493883F3A09123CFACDE03AA4D1B21F5A861332CA0C6A00EF18DF50F
+F98A01620E267FB72BE797423E5F29484A2F3D97CC3A81F1EC2B9BDF151467914537300556D909519CE320DE788C397C8AEAD995F54B3DD36A7733A49C622678DB9F27A89872947D5EE63B6D41F8E329AA761C5CD7A40418F65A5ABD41FBDBD98AD90F62560ABBC30F87707E6881E5DC1044698292E76D0374F0E398604AD0D21E68F5EC96693980E8D9863127A54D387C8252FFEDED48144344781A4E5E9E7122A9C6709185895761D5A07C3D4A1A7C901163930756FF505BCE7E258E233BBA4D1EE0499A90D4EE9CBEDF3B5542AAB7F501B03E9483E80EEFF2B07BC3378EDD4BB6E613CAA824D61CA5785353E4573370AC5AE7FD816C56A789B910E52A59978A942AE5C8B54AA049B055B7BDD5FC4AA6877AB5B01C81A4A18EC2011496BD455F6A0151B7B546CC398399FAD12C424ADE68F8CDD1A5F022EAEEFC1113CE004D17ED177B1A1F87BB315D1372A008C8E25D20B50A5C79DA98A2BFDD9DE9ACB77A73B36C1504ACA7D352682C20057614086231638558CCC56DAD5D70B1633A188B6DE395BB840659D2EB9F4F01978A4A197151AD404CA320279DBDD3B5F69AABE29111E722DD383588EF8862C8DC02073ACED61F951A61266D00CDC31585032DC84FA6DAA7D427C9F3D6884632DB574B8063E68AB6454B76DF6EE96A88B6CA2D5BD9488B6736897EDFDBE0C53305C823074D483229013B86D677619D822ED8D9519ED6A0A98B89FB40386E360DB4E99D01415BDA8EA59457185D68C263D2ECE921296767AD0AA1C2A471FEF0B663BF6F282D372A9EA3597578E3CE43505A6B0C951CCB7EFF475DFAFBEEED8BBE3612C9ABF3DF86335525678854BB92DBF7B0AB9B187FDB40704DB2DD86BBDFDBD83703957D7BEBDF14E807584272F3ABD8AAFF414D001F6674581D07C79E1750164B3A32B46EFFE372FFC8766B0CB8C8B632498DAFBD262D0665DFEC0F3D60DC4707FB4101BD7344CAFCA17B79AD3741B2D1F88BBDF7D4546A5562FA9D763C96F91DF5D7D2711CB0BC5A1E4EB8B7F6D1E3D3702BBDE233D68EC47CDB224CF1C03B992A482D6B666644B70837675652A4D8BB205DC18A3EB73CFABC84855F371E915AE11370F45DB05B0DCC1FC1626F64274231F94E2F659CE943C4053DC5333E157523A696A4FED76788BD25E76A7A1115AC545684DE9FFCD06B91C143706352B5311BC5591231FE71846C37D49DD80B1DF7BB72750D3891BFFCBFB0FFC252576656AD210A824D3BEA8C2E67D2A53AC510E63800602B30E8268FC663B0E4FD6CC1CC0F17F13B6C721D17E42399646F90C3774C69986624A899DFC8199D4F8E1B79F4AE8F373618117D4F3FC3A426E59E8D62576EB4683DDE59CEB0C94958D578D9E7607431A11F3AC9E0EB29DE97E78844D3F148A42DF3C93D63889A1C58DD676C1BF8BC8213B9BF2335EF9BD9E04971E690ED40
+2B847D867DC55AE86296DFD4DF1DD0D7787F42743FEC3E0A1206BA11DD2F4E4B9E88C8E10520D7D0F597CAE6CCA366A7AB5AF79A398C17FD6E64EA000D7A6AB7511CE64FEDDE4B4342224A91D5925B3A5050C05A48C794A587DC9D96BD1AAA6B9591B2910E634CE8A7014CAD8CEDAFF7FEED2EB510177359A79084827999F500CFA3B4CC0B1A9BAE7AC1460180820E8F0455DD0D7CD9190BAFE9336586BE06B6E00D52F07E9851773C70D04A01B5B71C2C05A8843CD96FD9EA17E4C3E138DF1A3FFC834F8562355A8C03BBDA86C0E7263093F583B45F000F1EB4974DCFF0ACEF6F468992CA58C157DB8CA4F4C7431AB286813C397FEFD6847D0F2230D74A2199C8F45C955865D79470F23AFC376B0B57660A72E86339E363C9036AD19FF7A44A425A0BD519B9CAFA08F4B2F4D8608CCDF92F31448DF2CF1798BE50A1BF9EA44467069DB07AC587D0EDCC6DB4704CFF5B0B29686A9894D0D5D277F6C6DF3255C525FD58AB9A84ED3A67751BBFA56F693CE2A42D7FC5009763E016D2EAB870C8C290243CB765AB00BCF6CC8BB18D213B2DA5A35E0198ED03E6FC1B7DCD2C6C04731660342D0A073F82B4A301B98DCF112BBD7C7747F8F6A1F158A3740EA8ABD995047F083E13D9EE6368B07159E8BEB0018B7C025A383409F19E44FA1B03E7AD73D3C0A19766646C11EF98997E338F6DA2D2BFDAECDD233CDB06F416D4C60274D371D93F49491392E4A54EA17D34B9DA180CBDC2081786F13ADA2A2D281B0099DE80813B22C2AB9DE03E825CE312380CB8CB8EF823E7675F282E56775BABD34E4AE64221EEBF9A2AE8DD1FF34AC06EBE2A8EF3DDB5F7D84829BB6AB09AD34BB26892B45F5B9C3F8953B12A1B7BDB54039641BA2F01A894285F253C552D64FDE0E91347EF89D29E12622764E883661EE847D17B17AECFDB8A476E9A94F6B84EF14AF6
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+ %endType1
+
+end
+
+%%EndFont
+bn
+bu fc
+{}mark T /Helvetica /|______Helvetica 0 rf
+bn
+bu fc
+2 F /|______Helvetica fnt
+bn
+-3.04162 0.(gammatone filtering)ashow
+64 gr
+1481 1626 2081 2669 109 109 1 rr
+13 13 pen
+0 gr
+1481.5 1626.5 2080.5 2668.5 118.5 118.5 0 rr
+64 gr
+1643 1665 1911 2615 1 rc
+8 8 pen
+0 gr
+1643 1665 1911 2615 0 rc
+64 gr
+1675 1733 1750 2550 1 rc
+1733 1734 gm
+F 1 setTxMode
+-3.25660 0.(transmission line filtering)ashow
+64 gr
+1817 1917 1892 2346 1 rc
+1875 1918 gm
+F 1 setTxMode
+-3.88058 0.(compression)ashow
+64 gr
+1750 1821 1825 2475 1 rc
+1808 1822 gm
+F 1 setTxMode
+-2.92906 0.(spectral sharpening)ashow
+64 gr
+1524 1811 1599 2436 1 rc
+1582 1812 gm
+F 1 setTxMode
+1 fs
+bu fc
+2 F /|______Helvetica-Bold fnt
+bn
+(spectral analysis)show
+64 gr
+1957 1674 2032 2657 1 rc
+2015 1675 gm
+F 1 setTxMode
+3 fs
+bu fc
+2 F /|______Helvetica-BoldOblique fnt
+bn
+(basilar membrane motion .)show
+0 gr
+pr
+2119 1494 pl
+2102 1564 pl
+2119 1564 pl
+2137 1564 pl
+2119 1494 pl
+1 ep
+pr
+2119 1699 pl
+2137 1629 pl
+2119 1629 pl
+2102 1629 pl
+2119 1699 pl
+1 ep
+2115 1560 gm
+2115 1625 lin
+64 gr
+2818 542 3418 1581 109 109 1 rr
+13 13 pen
+0 gr
+2818.5 542.5 3417.5 1580.5 118.5 118.5 0 rr
+64 gr
+3291 783 3366 1378 1 rc
+3349 784 gm
+F 1 setTxMode
+(auditory image .)show
+64 gr
+2874 603 2949 1537 1 rc
+2932 604 gm
+F 1 setTxMode
+1 fs
+bu fc
+2 F /|______Helvetica-Bold fnt
+bn
+(time-interval stabilisation)show
+64 gr
+2983 580 3242 1538 1 rc
+8 8 pen
+0 gr
+2983 580 3242 1538 0 rc
+64 gr
+3083 592 3158 1521 1 rc
+3141 593 gm
+F 1 setTxMode
+0 fs
+bu fc
+2 F /|______Helvetica fnt
+bn
+(strobed temporal integration)show
+64 gr
+2822 1633 3420 2667 109 109 1 rr
+0 gr
+2822 1633 3420 2667 117 117 0 rr
+64 gr
+3292 1904 3367 2400 1 rc
+3350 1905 gm
+F 1 setTxMode
+3 fs
+bu fc
+2 F /|______Helvetica-BoldOblique fnt
+bn
+(correlogram .)show
+64 gr
+2982 1671 3242 2621 1 rc
+0 gr
+2982 1671 3242 2621 0 rc
+64 gr
+3083 1917 3158 2417 1 rc
+3141 1918 gm
+F 1 setTxMode
+0 fs
+bu fc
+2 F /|______Helvetica fnt
+bn
+(autocorrelation)show
+64 gr
+2882 1682 2957 2615 1 rc
+2940 1683 gm
+F 1 setTxMode
+1 fs
+bu fc
+2 F /|______Helvetica-Bold fnt
+bn
+(time-interval stabilisation)show
+64 gr
+1054 821 1175 1383 1 rc
+1142 822 gm
+F 1 setTxMode
+bu fc
+
+%%BeginFont: Times-Bold
+%!PS-TrueTypeFont-1-1-1
+25 dict begin
+/FontName /Times-Bold def
+/Encoding 256 array
+0 1 255{1 index exch/.notdef put}for
+dup 0 /.null put
+dup 8 /.null put
+dup 9 /space put
+dup 13 /nonmarkingreturn put
+dup 29 /.null put
+dup 32 /space put
+dup 33 /exclam put
+dup 34 /quotedbl put
+dup 35 /numbersign put
+dup 36 /dollar put
+dup 37 /percent put
+dup 38 /ampersand put
+dup 39 /quotesingle put
+dup 40 /parenleft put
+dup 41 /parenright put
+dup 42 /asterisk put
+dup 43 /plus put
+dup 44 /comma put
+dup 45 /hyphen put
+dup 46 /period put
+dup 47 /slash put
+dup 48 /zero put
+dup 49 /one put
+dup 50 /two put
+dup 51 /three put
+dup 52 /four put
+dup 53 /five put
+dup 54 /six put
+dup 55 /seven put
+dup 56 /eight put
+dup 57 /nine put
+dup 58 /colon put
+dup 59 /semicolon put
+dup 60 /less put
+dup 61 /equal put
+dup 62 /greater put
+dup 63 /question put
+dup 64 /at put
+dup 65 /A put
+dup 66 /B put
+dup 67 /C put
+dup 68 /D put
+dup 69 /E put
+dup 70 /F put
+dup 71 /G put
+dup 72 /H put
+dup 73 /I put
+dup 74 /J put
+dup 75 /K put
+dup 76 /L put
+dup 77 /M put
+dup 78 /N put
+dup 79 /O put
+dup 80 /P put
+dup 81 /Q put
+dup 82 /R put
+dup 83 /S put
+dup 84 /T put
+dup 85 /U put
+dup 86 /V put
+dup 87 /W put
+dup 88 /X put
+dup 89 /Y put
+dup 90 /Z put
+dup 91 /bracketleft put
+dup 92 /backslash put
+dup 93 /bracketright put
+dup 94 /asciicircum put
+dup 95 /underscore put
+dup 96 /grave put
+dup 97 /a put
+dup 98 /b put
+dup 99 /c put
+dup 100 /d put
+dup 101 /e put
+dup 102 /f put
+dup 103 /g put
+dup 104 /h put
+dup 105 /i put
+dup 106 /j put
+dup 107 /k put
+dup 108 /l put
+dup 109 /m put
+dup 110 /n put
+dup 111 /o put
+dup 112 /p put
+dup 113 /q put
+dup 114 /r put
+dup 115 /s put
+dup 116 /t put
+dup 117 /u put
+dup 118 /v put
+dup 119 /w put
+dup 120 /x put
+dup 121 /y put
+dup 122 /z put
+dup 123 /braceleft put
+dup 124 /bar put
+dup 125 /braceright put
+dup 126 /asciitilde put
+dup 128 /Adieresis put
+dup 129 /Aring put
+dup 130 /Ccedilla put
+dup 131 /Eacute put
+dup 132 /Ntilde put
+dup 133 /Odieresis put
+dup 134 /Udieresis put
+dup 135 /aacute put
+dup 136 /agrave put
+dup 137 /acircumflex put
+dup 138 /adieresis put
+dup 139 /atilde put
+dup 140 /aring put
+dup 141 /ccedilla put
+dup 142 /eacute put
+dup 143 /egrave put
+dup 144 /ecircumflex put
+dup 145 /edieresis put
+dup 146 /iacute put
+dup 147 /igrave put
+dup 148 /icircumflex put
+dup 149 /idieresis put
+dup 150 /ntilde put
+dup 151 /oacute put
+dup 152 /ograve put
+dup 153 /ocircumflex put
+dup 154 /odieresis put
+dup 155 /otilde put
+dup 156 /uacute put
+dup 157 /ugrave put
+dup 158 /ucircumflex put
+dup 159 /udieresis put
+dup 160 /dagger put
+dup 161 /degree put
+dup 162 /cent put
+dup 163 /sterling put
+dup 164 /section put
+dup 165 /bullet put
+dup 166 /paragraph put
+dup 167 /germandbls put
+dup 168 /registered put
+dup 169 /copyright put
+dup 170 /trademark put
+dup 171 /acute put
+dup 172 /dieresis put
+dup 173 /notequal put
+dup 174 /AE put
+dup 175 /Oslash put
+dup 176 /infinity put
+dup 177 /plusminus put
+dup 178 /lessequal put
+dup 179 /greaterequal put
+dup 180 /yen put
+dup 181 /mu put
+dup 182 /partialdiff put
+dup 183 /summation put
+dup 184 /product put
+dup 185 /pi put
+dup 186 /integral put
+dup 187 /ordfeminine put
+dup 188 /ordmasculine put
+dup 189 /Omega put
+dup 190 /ae put
+dup 191 /oslash put
+dup 192 /questiondown put
+dup 193 /exclamdown put
+dup 194 /logicalnot put
+dup 195 /radical put
+dup 196 /florin put
+dup 197 /approxequal put
+dup 198 /Delta put
+dup 199 /guillemotleft put
+dup 200 /guillemotright put
+dup 201 /ellipsis put
+dup 202 /nobreakspace put
+dup 203 /Agrave put
+dup 204 /Atilde put
+dup 205 /Otilde put
+dup 206 /OE put
+dup 207 /oe put
+dup 208 /endash put
+dup 209 /emdash put
+dup 210 /quotedblleft put
+dup 211 /quotedblright put
+dup 212 /quoteleft put
+dup 213 /quoteright put
+dup 214 /divide put
+dup 215 /lozenge put
+dup 216 /ydieresis put
+dup 217 /Ydieresis put
+dup 218 /fraction put
+dup 219 /currency put
+dup 220 /guilsinglleft put
+dup 221 /guilsinglright put
+dup 222 /fi put
+dup 223 /fl put
+dup 224 /daggerdbl put
+dup 225 /periodcentered put
+dup 226 /quotesinglbase put
+dup 227 /quotedblbase put
+dup 228 /perthousand put
+dup 229 /Acircumflex put
+dup 230 /Ecircumflex put
+dup 231 /Aacute put
+dup 232 /Edieresis put
+dup 233 /Egrave put
+dup 234 /Iacute put
+dup 235 /Icircumflex put
+dup 236 /Idieresis put
+dup 237 /Igrave put
+dup 238 /Oacute put
+dup 239 /Ocircumflex put
+dup 240 /apple put
+dup 241 /Ograve put
+dup 242 /Uacute put
+dup 243 /Ucircumflex put
+dup 244 /Ugrave put
+dup 245 /dotlessi put
+dup 246 /circumflex put
+dup 247 /tilde put
+dup 248 /macron put
+dup 249 /breve put
+dup 250 /dotaccent put
+dup 251 /ring put
+dup 252 /cedilla put
+dup 253 /hungarumlaut put
+dup 254 /ogonek put
+dup 255 /caron put
+readonly def
+/PaintType 0 def
+/fcheckload{{pop}{save 3 dict begin/mystring 2050 string def exch/endstring exch def{currentfile mystring readline not{stop}if endstring eq{exit}if}loop end restore}ifelse}bind def
+userdict/type42known known not{/type42known systemdict/resourcestatus known{42/FontType resourcestatus{pop pop true}{false}ifelse}{false}ifelse def}if
+/truedictknown userdict/TrueDict known{TrueDict dup /initer known 1 index /render known 2 index /imagemaskwrapper known 4 -1 roll /bander known and and and}{false}ifelse def
+%beginsfnt
+truedictknown type42known or( %endsfnt)exch fcheckload
+/FontMatrix [1 0 0 1 0 0] def
+/FontBBox[2048 -559 1 index div -496 2 index div 2580 3 index div 1986 5 -1 roll div]cvx def
+/FontType type42known{42}{3}ifelse def
+systemdict/product 2 copy known{get dup(LaserWriter IIf)eq exch(LaserWriter IIg)eq or version(2010.113)eq and not}{pop pop true}ifelse{/UniqueID 16#00B99385 def}if/sfnts[<
+
+00010000000900090009000963767420CE11A8C20000009C000004A66670676D2E724DEA00000544000003B7676C7966AE3B0504000008FC0000B5A868656164ACE7D39D0000BEA400000036686865611093071B0000BEDC00000024686D7478275174380000BF00000004286C6F636157382B0C0000C328000002166D617870094B022D0000C540000000207072657035C6D03A0000C5600000063B064E00000610002E0610002E045D001F0000FFD10000FFE10000FFD1FE4EFFE1066D0008FE8C00000377000000BE000000BE0000000000000000003F0108006D003E010800BA00BA00BA00CA007C00D201050046004E00A2003E003E019101080055004D003E004D024D000A004E045D003EFF84001F003E007C00E9009B00AB0162FF5DFFAC005400A30136000F008C00AB00B900E900030022005D00BA01080055000E00550084008E0108012D01F00049005A0084009B01360026004E0065009900A300AA006500F80174003A0040005C009B00CA00E10136FFAA0034003C004E009000A300CAFF08000000010056006500B300BA00CC0108014601F8022F02C6001F0046004E0059009E00AF00D800D90108022E0000000300100045006C007D00B400BA00C20100012F017D01F0024302E8042FFF00002F0036003E006D007300F800F8010801460155035603A3FEF9FF46FFBEFFC2FFCCFFD20026004E006B006D007C00B400BA00BA00D100D200DA00E100E800E900F9012301410146016C017901F6026D038C03BAFE8CFF1FFF8C00070013001B0020002100290036004E004E004E004F0055005D007C007C0092007F0091009700A300AA00C600D900E100F4010801080115011601330145015501690170017C019401BE01C20208021D02AB02E903D9046504D905C2FEAB00E8FF1FFF2FFF56FFD9FFE9000F001400270036003C003E003F004A005D0069008D0090009B00A300BA00C100D100D800DE00E0011E01350146014D021C0227025D027902F9036503A303D204D7052705930610066DFDF1FE4EFF17007B000000020008000F0012001700270029003E005E006C006C007000720072007B008400840092009B009C009D00A000A300A300BD00CA00CA00D800E100E900EC00EF00F50100010101080112012E013601360137013B0165016501AB01B201B301D101E101E101E5020F0217021802260229022F02550284028C029C02A902B202C702D302E9031703210365036503CA03EC03FC040804170417044E045604B204E90517064E066D066D06B20784083EFC14FDB2FDBAFDDAFE1FFEC6FEDEFF69FF93005D0046FFC200090036003E003E004300460056005D005D006C006D006D0074007C007D008C00930093009700A300BA00CA00DD00E500EB00F000F30108010801100117011E011F012201220129012F0136013A
+
+013A013E0143014E015501550168016B017B018401A301B301B801C101C201D101E101E601F101F80200021202360246024E029A029B029B029C02B702C002C202C2030803080338033D034A03550365038403B303BE03C403D103D103EC04170428045E047C04840493049B04BA04E8052705270555057A0584059305BA0600061006100632064E066D069B06E90746076D078407B307C207D507E109E900C300D000C200CA00000000000000000000000000AA006900980087004B010900580104024E01BA01D2011D00A300BE00CE01E3003D00DA000000DB03A2022F012E01010246025402B20117039301A0016502DB03F000000253014F011C027C008600B3005F004D002200CA0236019903A200A401DC00F8031B025503E100B1066B026D008C001C005500E900D902B90365006D045D0009050806BA007C0065008C006C0000403231302F2E2D2C2B2A292827262524232221201F1E1D1C1B1A191817161514131211100F0E0D0C0B0A090807060504030201002C4523466020B02660B004262348482D2C452346236120B02661B004262348482D2C45234660B0206120B04660B004262348482D2C4523462361B0206020B02661B02061B004262348482D2C45234660B0406120B06660B004262348482D2C4523462361B0406020B02661B04061B004262348482D2C0110203C003C2D2C20452320B0CD442320B8015A51582320B08D44235920B0ED51582320B04D44235920B0042651582320B00D44235921212D2C20204518684420B001602045B04676688A4560442D2C01B9400000000A2D2C00B9000040000B2D2C2045B00043617D6818B0004360442D2C45B01A234445B01923442D2C2045B00325456164B050515845441B2121592D2CB00143632362B0002342B00F2B2D2C2045B0004360442D2C01B00743B006430A2D2C2069B04061B0008B20B12CC08A8CB8100062602B0C642364615C58B00361592D2C45B0112BB0172344B0177AE4182D2CB801A65458B00943B801005458B9001AFF80B11980444459592D2C8A03458A8A87B0112BB0472344B0477AE4182D2CB002254661658A46B040608B482D2CB0022546608A46B040618C482D2C01182F2D2C20B0032545B019234445B01A23444565234520B00325606A20B009234223688A6A606120B01A8AB000527921B21A1A40B9FFE0001A45208A54582321B03F1B235961441CB114008A5279B31940201945208A54582321B03F1B235961442D2CB9187E3B210B2D2CB92D412D410B2D2CB93B21187E0B2D2CB93B21E7830B2D2CB92D41D2C00B2D2CB9187EC4E00B2D2C4B525845441B2121592D2C0120B003252349B04060B0206320B000525823B002253823B002256538008A63381B212121212159012D2C4569B00943608A103A2D2C01B005251023208AF500B00160
+
+23EDEC2D2C01B005251023208AF500B0016123EDEC2D2C01B0062510F500EDEC2D2C20B001600110203C003C2D2C20B001610110203C003C2D2CB02B2BB02A2A2D2C00B0064365B007430B2D2C3EB02A2A2D2C352D2C76B01B23701020B01B4520B0005058B00161593A2F182D2C21210C6423648BB84000622D2C21B08051580C6423648BB82000621BB200402F2B59B002602D2C21B0C051580C6423648BB81555621BB200802F2B59B002602D2C0C6423648BB84000626023212D2CB4000100000015B00826B00826B00826B008260F10161345683AB001162D2CB4000100000015B00826B00826B00826B008260F1016134568653AB001162D00000200930000036D06100003000700444009070669010405690302B801F340180000010A04076903001A090506690201190809F2213E41182B2B4EF43C4DFD3C4E10F63C4DFD3C003F3C10FD3CFD3C10FD3C31302901112107211121036DFD2602DA96FE5201AE061096FB1C000200B2FFD101BA063E0003000F00484025025D030301DD0A7C040B1117171A0D40005D015D0A210A0703350D02350D7C0719103FA9182B4E10F44DEDE410E412391A3D10E4E41A184E10456544E6003F4DFDE63FE431300123033703222635343633321615140601543C60F87A364E4D37364E4E0184048A30F9934E36374D4D37364E000200BA03E10346064E00030007003AB10501B80242B306020205B80243B2072504BC0243000601A100010243B2032500B80243B302DD09082FCCF6EDFDEDF6EDFDED003F3CF43C31300123033301230333014C4250DA01674149D503E1026DFD93026D0002001A000005300610001B001F00DC403E0805081C370A380D3818371B381D071613120F0417170E191D1E0C0418180D1A1C1F0B041B1B0A010405080400000911121E1F050506D2100F0C0B080507B8015C4011450914131D1C040503D21516191A010502B8015C401200450A0D0E03090217181B03000A0AD24009B8015C400BC00DD20ED8AF1401146110B8021DB42118D24017B8015C400BC01BD200D8A00601066102B9018F002010F6E45DF4ED1AFD1AED10F6E45DF4ED1AFD1AED003F173C3F173C7610F518173CFD173C1076F518173CFD173C050710173C0710173C0710173C0710173C31015D3313213521132135211333032113330321152103211521032313210313211321AC76FEF8012278FEF801227C5D7B019E7B607D0108FEDF7B0108FEE0756074FE64758F019B7DFE6201BA5D01CA5D01D2FE2E01D2FE2E5DFE365DFE4601BAFE46021701CA000300E1FF6504B206AB0028002F00350140401E4732560A592B592C563153326C0468266A2C0921292F2F220F3035351006B801B6400E0E50105022502F50350400070107B80103402C0605310E0F30103521292F221B2A1620292A0E313021
+
+2004001D1B3335101092122F2F22352F2210041D0E01410B013C0002000E012F0028001D01B90018013C0020012F402219191604280C020C102F012D223533001BCC1CC93717171A25880F335F336F330333B801B5400F0E05C906C91388002D502D602D032DBB01B5001800000104400C170101500E600E020E193637BA01C600210166B1FB182B2B4EF45D3C103C4DFD3CF45DFDE4E410F45DFD4E456544E64DF4E41112393911123939003F3F3F3C10EDE4ED10ED10E411121739870E2E2B7D10C40111123912173911393900111239391112393911123939123939180110ED5D005D10F507103C3C07103C3C3130005D05233523222703331716171633323711272E01353436373533153217132327262511171E011514060703110E0115141713113635342703004E2ABED2174E0317457493081570D485F3D64ECAB323520545FEFC6AC385E1D14E748CCE80E9B79B9B3E0155128A45750102734783986DA4D4169D9D3EFED311FE1EFD9F4178A174A7D21E0398022E13966A7B81FEBEFDCD54CC7F740005002F000006E106130003000F001B0027003300C3403D89058709870B890F891D8721872389270808060808070C070E081E0820072407268901860398059809960B960F981D982196239627B7031340102C2104B8021F400E40162C210A35020102402E2C2122B8021F401540282C1C211C0303000A0000131902022B312B4425B80167B231441FB8014DB213440DB80167B5071396194407B8012EB135342FCCF6FDE610FDEDF6EDFDED1112392F1112392F003F3C103C3D1A10ED181AFD3D1AED181A3F3CF43D1AED181AFD3D1AED181A3130015D005D210133010322023534123332121514022732363534262322061514160122023534123332121514022732363534262322061514160111045A83FBAA089CC5C59C9CC5C59C5866665858666604489CC5C59C9DC4C49D596666595866660610F9F002700104CECE0103FEFDCECEFEFC3FD8BBBBD8D8BBBBD8FD510104CDCE0104FEFCCECDFEFC3ED8BBBBD9D8BCBBD8000003004EFFD1069C063E00280034003D00A64065050E070F053506381638270E23382339080806051306141A0B15390508353C0004270D29121420042E221A1A1EDC1B1B3A2E2C0D053A7802246F256846222727020B08353C00040A291214200425311EE51C5825683F31630A2B4410F10AC0376305193E3FB80179B3212AAC182B2B4EF44DEDF4FDED10ED10F4F4E411121739111739003F3C10CD76F418ED10ED3FFD11392FED392F11121739111217393130015D005D250623220035341237263534363332161514051213363534262B01372107230607163332371506232201363534262322061514171607061114123332370003F6CFE6DAFEE7DFD14BCC9C89BAFE74A9D690493A0D2B02203EDF42
+
+C1CB764859979091FE18F5563F445E3B01A5FBE9A69194FEED8FBE0107CAA9012467B46890BC956FDD87FE7AFF00C974394A7CA3F2D0D9213866043F76C94C657A5758B0058896FEE7B5FF0085013000000100AB03E101C2064E00030037B9000102424015020220002F010270007F01022F030101862F030103B801A9B62F00010086020410DEED71FD71FD715D7118003FED313001230321015C4869011703E1026D00000100CAFE8C02BA066D000B003B401F290A390A020008010001071001120D17171A07E50A6304190C0D572173C7182B2B4EF44DFDF44E456544E6003F3F01393900123939015D313001152600111000371504111002BAD0FEE00120D0FEDAFED549720249013501350249734AF0FD49FD4A000100CAFE8C02BA066D000B004C402B0B060B0A1C061C0A045A086A08020004050B000B020405100B120D17171A086302E504190C0D572173C7182B2B4EF44DF4FD4E456544E6003F3F01111239390011123939015D3130015D132411102535160011100007CA0127FED9D1011FFEE1D1FED5F102B602B7F04A73FDB7FECBFECBFDB7720001004E02EE03C2063E000E00C7402D5A0C680CC901C50ED403DB0CE503EA0CF503FA0C0A05030A0C1503190C0436004600BB02BB0DC504C50B060102B8FFF0B5020D0E100200B8FFF040450A050602010204050B0A0E0D0E0D02010005030B0A0906050406080C0502010304030700060C090E0D0A030B08EE0C03071017171A0BC0085D096F065D07C004190F2A42182B4E10F44DF4F4FDF4F44E456544E6003F3C4DFD0111173911391239113912173900111217391117330110C90010C910C90110C90017383801173817383130005D01715D0103271325370503330325170513070208AF80FAFE7B2A016F2D9C2C016E2AFE7CF97F044EFEA052012D4796A40198FE68A49647FED3520001007C000004D9045D000B003EB30A7E0700B8024A400D06017E040A0D17171A007E0A03B8024A400909047E06190C2639182B4E10F44DF43CFD3CF44E456544E6003F4DF43CFD3CE4313001152111231121352111331104D9FE086DFE0801F86D02656DFE0801F86D01F8FE080001009BFE8C01DD0108000A002DB7650A750A02012100B80230400F064F0B03096C001004200402040C0B2FCCD45DC4F5390010FCFD1AC931305D13353637273633321615109B9C0DA916934356FE8C4263D756AA664FFEFB000001004E022F02BB02BA0003001D400F015300021A0500190405C3212A42182B2B4EE410E6002F4DFD3130133521154E026D022F8B8B0001009BFFD101D10108000B00264013065C000B0D17171A096C03190C0D6C213E41182B2B4EF44DFD4E456544E6003F4DED31300522263534363332161514060136405B5B40405B5B2F5B41405B5B40415B0001003EFFD1046D063E
+
+0003002B4015020303591200000101021003000B030004010205042FDCC6C810C6C8003F3C3F3C87052E2B103C3130170133013E03AE81FC502F066DF9930002005DFFD104F8063E000B0017008D4032890289048708870A980298049608960A08870D8717970D9717E90DE60EE711F602083708129E06050C9E000D0F882F090109B8018840091915886F0301034D1810FE5DED10F65DED003FED3FED31304379402A01170D0B0FC201170115C20011070FC201130515C2000E0A0CC20016020CC200100812C201140412C2012B2B2B2B012B2B2B2B81005D015D05200011100021200011100025321211100223220211101202ABFEF5FEBD0143010B010A0143FEBDFEF6BABABABABABBBB2F01C30174017401C2FE3EFE8CFE8CFE3D3F017C017C017C017CFE84FE84FE84FE840001011F00000446063E0010005DB6010301010F0B0F411201430103000B014F0022000301430103000A014F00230001FFF000100000010300010218B54702050A0C0AB80150400902039210300F010F1110DC5D3CFD3CE4003F3F76F418FD39382B2B011112392F3831300135251114163B0315213532363511011F01F06FC2020202FCD9C86E05423EBEFA9A63373E3E3763049F00000100A30000047C063E0014007E40235909660264036A09C60AD60AE60A070909790D890D980D960E052710011608090A1207B80107B40C05131201B8012F400A129214000C04880FCC13B80247B31609CC12B80219B200611510F4EDF410F6F4ED003F3CEDED103C3FED11393931304379400E0D0E0506060D044001050E0740012B012B818101715D005D333508013534262322073736333216151402012115A3016D017C947DC3ED07CFF4CCF4E8FE04030B4901940258A2748AC683ACC9A895FEBBFDCFC20000010093FFD10474063E002400C2402F371C382249225A065612531566036A06661266148703BA14B922BA230E19232923471C49235B03990E971AAB230813BA01290002013AB42424081E0AB80233B7100B200B300B030BB80196B408AF0D051CBA013A001B0232401A1EAF190D130501CF00000B057910CF217940165F160216B9261CB80231B5100B200B020BB80196400C501B601B701B801BDF1B051BB80139B146251076F45D18E45DE410F65D4DEDF4ED11392FF41139003FEDFDED3FEDF471ED1112392FFDE53130015D005D01373332363534262322073536333216151406071E0115140023202737163332363534262301913C269AE7A675A7B2C5D0B9E0B8B9D5E2FEB5D8FEE3A1868ED88CAFFEFF02F89BC682709E7E5F74AE907DBE4126DFADCAFEC9B388EDC49EBCBB000200550000050F063E000A000D008140120001070A0C05020604090B02060A0C0C0D0DB80104400912020203020C03060DBB019E0007000101C0400E0A03050A0C020D
+
+010C0A92094003B8021BB321040409B801A6B540066F060206B80189B30F014D0E10EE10F65D4DF43C101A3DEE1A1810FD3C113939003F3F10F43CFD3C11393987052E2B047D10C40F0F0F31300121350133112115211123190101034DFD0803753D0108FEF8BAFD6101C2A303D9FC27A3FE3E026502EFFD1100000100A3FFD104750610001900AF4029570567050206100A171E172F17360C361539174607570759176B170B45060110111913110110040505B80130B612000001000506B80232402419461913040492020104139E0E0D0405161003CC1679600B015F0B6F0BEF0B030BB91B00B80196B300010101B8021CB5DF10EF100210B80139B1471A1076F4185DF45DE410F65D71EDE411123939003FED3F3CFD111239762F18ED393987052E2B7D10C4011112390011123939713130005D015D011321152103373204171615140023222737163332363534002101156802D8FD6D332288013B5BA6FEB3E8FAA38C79D787B4FE9BFEDC0374029CB3FEC2017B57A0DDD3FED39F8BE4D29EDE010F0002008CFFD104DA063E001A002600C64009B81F015D0809240721B8010740110F0CAF0C020C0C1B02AF18051B9E120D1AB80129B71E790F0F2F0F020FB80126401428A324B324C324D3240424CF07889F15AF150215B9019A002710F65DFDE45D10FE5DFDE5003FED3FFD11392F5DED0111123931304379400F1C260A170306050604060206031707B80165401A001C111E40012613244000200D1E4001220B2440000A09061602B801654015011D101B400025141B40001F0E214001230A214001002B2B2B2B2B01103C2B2B2B2B2B2A818181005D012623200706021514173E01333212151400232200111000213217013236353426232206151416042F2E37FEFEA15C750A40F996BAF1FECADEFCFEC201C8015E3C41FEC18CABB4909AB6C805E010AA61FEA5AE33459EB8FEFBCBE1FEC801A1014A018601FC0BF9E4E0B6B3DED2B3B2F0000100A3000004AB06100009003A4019060403020509020392050404000C0F052F050205620B098800B801A5B204610A10F6F4ED10E65D003F3F3C4DFD3C01111239001112393130211201213521150200030196660215FC920408F8FF004401F10364BB3BFE71FD62FE5800000300B2FFD104BA063E00160021002D00BCB90008FFF0406E0410161014101C2C4A014A1B4C234326780A781A9A1B08150B1B0D1A2C291A25252A2B3A0D391A35253B2C4A2C5A105813581A54236A046C1A6A1E66256C2B8A1A990099019902A625BB131A2221170C002D06271C9E060527AF120D21170C030F1F00222D032A0319797C090109B8023440102A79400FBF0F020F3E2F1F7972030103B80234B2247915B90240002E10F6EDF45DED10F65DEDF45DED1112173911121739003FED3FED11173931305D015D
+
+38383838012E01353436333216151406071E011514002322243510013635342623220615140507061514163332363534262702059274FFC9BBEAA893EF9AFEBEE4D0FEEE0243CDAA786A94010868D6DFA275A5A3CB035263A26BA8D4B9936CCD46A6BF84B6FEFDEEB50112011272B884BA92689AA5988BF9A3E2A9776FC181000002007CFFD104CA063E001A002600D6401B7C1679178D169C16A114B50ABC0EC90EDC0EE9140A5D080907240CB8010740222146211B021B9E120502AF180DAC24BC24CC24DC240424CF07880F152F15A0150315BB019A0028001A013CB51E799F0F010FB90126002710F65DEDE410F65DFDE45D003FED3FFD111239762F18ED0111123931304379401B1C260A170306050604060206220B2440010A09200D1E4000031707B8016540180126132440011C111E4000230A2140001F0E214000061602B80165400B0025141B40011D101B4001002B2B2B2B2B012B2B2B2B103C2B2A818181005D251633203736123534270E0123220235340033320011100021222701220615141633323635342601272D380101A25B760B3FFA96BAF00135DFFC013EFE37FEA33C41013F8CACB4919AB5C83011AB60015CAE32459DB90106CBE00138FE5FFEB6FE7BFE030B061CDFB7B2DFD3B2B2F0000002009BFFD101D1047C000B00170035401C0C5C1207065C000B1917171A156C0F095C03030F1918196C213E41182B2B4EF43C4D10ED10FD4E456544E6003F4DED3FED31300522263534363332161514060322263534363332161514060136405B5B40405B5B40405B5B40405B5B2F5B41405B5B40415B03755B40405B5B40405B000002009BFE8C01DD047C000A0016005C4025DB04E904F904030B04090819041605190805650A77027704750A8604050B5C110740012100B802304015064F17030904146C0E096C0E0010042004020418172FCCDC5DC4C4FD10FD1112390010FDFD1ACC1A3FFD3130005D727113353637273633321615100322263534363332161514069B9C0DA916934356A7405B5B40405B5BFE8C4263D756AA664FFEFB03F85B40405B5B40405B0001007C000004D9045D00050059B2010202B8024A4009120502030500030202B8024A401C12050201050403040105008A05028A040A0200050403010300F5050610D6FD173C11123900193F18FD3CED1139123987082E2B047D10C487082E182B047D10C4313001150901150104D9FC8D0373FBA3045D72FE44FE4E7D022F000002007C015D04D9030000030007002EBD0003024A000201A10007024A400F0605001A09070219080937212639182B2B4EF43C10F63C002F4DFDF6ED3130011521350115213504D9FBA3045DFBA303006D6DFECA6D6D0001007C000004D9045D00050059B2030202B8024A4009120502010504010202B8024A401C1205020305
+
+0003000305048A05028A000A0205000103040300F5050710D6F6173C11123900193F18FD3CED1139123987082E2B047D10C487082E182B047D10C431303335090135017C0373FC8D045D7301BC01B17DFDD20002003EFFD10346063E001900250075402217126A090205061516040B010D6F0E600B78100301DD1D7C230B1615001306050800B8010C4017015D47207C1A1A0E4908630D1301131A270D5D0E192627B801D3B3213B42182B2B4EF44DE44E10F65D4DED7612392F18ED76F418ED12393911123939003FFDE63FEDFDED111217393130005D01233534363F0136353626232207273633321615140F010E011503343633321615140623222601D9BA3A752985088D7081A820B7F391CD8D217748E04D37374D4D37364E018C4E76879E37B29678756C32979D6E849B2483C1BEFE67374D4D37364E4E00020055FFD10655063E002F003A00BF40555A0758086B2A662C762C88048A2999049925982AA507AB25A42CB926B62CF517F92511020819174408443252085532BC26D926E926F9260A3A1F12033137306F1C09402178210F353778150300D20168402E5E2103B80122401440275E21090301681E123A691E1E3440245E210CB801F1400D06344418C0402B5E2106193B3CB801F1B3212A42182B2B4EF44D1AED1AF4ED10FD1AFD1A11392FFD3C10E4003F1AED1AFD1AED1AF4ED10DCEDF41AED1A10DCED111217393130015D005D251506232000111000212000111402232226270E01232226353437362133111416333236351000212007061110002132032322061514163332363704C2A3D3FEB7FE5201B8015F014D019CE2A56D7F113C8A4D719B7D75010ABE5353698DFE94FED9FE85B69A017E0123BD3738A2A253522F6B3D8C5F5C01D20164016E01C9FE73FEC0C4FEF664635C5CC28CC67E76FE4C7F7FC89601240167FDD4FEE8FEC1FE5E0455B7B77B7C5C5C0002000000000610063E001E00210115406D2721012908280E3B07490748105907580E570F5810D8200A0915011F0F0F00001F21011E2021211D080D091D08161D171D160701061D071510141D15001F210D1E201D7A210E0F200F101025121D1D210E0D0D59120101211D100D01040016211F0F0E031E00331F1F0F200120B8011740194016151508080708010D081D100F0E04231F23012310150115B801D6B51B2183210221B80168B40820082223B80121B3218B75182B2B3C1A1910FD5DFD5D3C5D12173912393900183F3C103C103C1AFD5D3C10FD3C3F3C123911121739870E2E2B057D10C4870E2E182B057D10C42B11393911123939180010ED0110C00010ED0110C00010ED0110C00010ED0110C087107DC4C4073C3C07103C313001715D005D01070615141F01152135333236370133011E013B0115213533323635342F01252101018E5F296710FE
+
+83103C4E3002243F0237353E2C0DFE36113D2A305EFD7B025EFECA01E9E7621A3D09023E3E55760535FACB7C4F3E3E18231D73E04D02DC000003004E000004BB0610001A0024002E00B9407E6704681F7905891A991A050516161617191A2C251626192A2C3822362A4822442A5922572A671F682C7B22772AB326CB02C822C226E41716260C0C1E1D0723220D1E1D1223236F216F2B02001D2E2D1E000321262832072432121D32202E302E502E702E042E472E07120207082193189C2B93031A301B26250D0C192F30B801DBB3212F6D182B2B4EF43C4DFD3C4E10F64DEDF4ED003F3F1239762F5D18ED10ED10ED0111121739001112395D2B2B10C03130005D015D011E01151404232135333236351134262B013521321617161514060111333237363534262303111421323635342423032BBBD5FEEAEEFD971466404066140227C8983C73ACFDFAC064705DBFC072010E7CA4FED3DD035630E89CC1E13E4D7C03FF7E4D3F18284E9086CE0233FD94725F8B8888FD56FDE1CAAD83BBFE0000010055FFD1053E063E001A007E401128123812690E69126714791706090E010BB80113B60AD0103808031AB8011340314000D02116380209090501400A3A0C83210B5140003A1983210F1A3F1A021A1A1C134A0F053F050205191B1CF52130C8182B2B4EF45D4DED4E10F65D4D1A3DEDE41A18F41A3DEDE41A185D003FE91AF41AED3FEDF4ED313000715D25062320001110002132171323272E0123220011100033201337330522F9D5FE9FFE62019C0153FBD51F4B0318D5AAEAFED20135FA015137034E215001BE017B017301C13FFECB128B99FE56FEB5FEA9FE5A012F1100000200550000062606100016002200864059440E45106310691BC710C91FD610070810481002050F3612640E6A20B218C218061810012A1F3A1F021805321D4E1D02051E1D002322061E1D0B23231A320022320B0200085F1F6F1F021D4A111A240618253F050105192324B80178B3212F6D182B2B4EF45D4DED3C4E10F64DED5D003F3FED10ED2B2B5D0010C05D313000715D01715D3335333236351134262B013521041617161110070604210311142132001110272E01235514664040661402410128F48BE9D370FED3FEE0BD014DF80128B269FFE93E4D7C03FF7E4D3F063F61B4FE8FFE9EFB846405D1FB36C10179013C0136CD785B0001004EFFE404940610003300BF4043B402010117171E1D1223220F2D1F2D022D4833337D2E1D2D181E1D1D2323002C102C022C4827277D2B1D2C0E2D0120B725831D27263333004700121D020ABA0483110BB80244402612082D2C472C20254020831E3A211F8C400B3A0983210A1A352501251817193435C4212FAA182B2B4EF43C4DFD3C4E10F64D1A3DEDE41A18F61A3DE4ED1A18111239762F3C18003FE43CFDE43F12
+
+39762F183CFD3C10FDE401111239000110EDEC0010F55D2B0110EDEC0010F55D2B10C03130005D011114163B0132363F0133032623222726232135333236351134262B0135211323272E012B01113332363D01331123353427262301D2A9D52A5D5913034E1FBF5D6386831BFE7C1264443F691204001F4E031371EFD7E8A0594D4D251EB60310FDF1644F5E7713FEAE0D08073E517903FD804C3FFEE015833AFD8C376211FE6D0F58261E000001004E0000046D06100028009240520C1E1D0723220F221F2202224828287D231D22011E1D06BB230D1E1D122323002110210221481C1C7D201D211715B71A83121C1B3328000006120207060822212101151583133A141A2A1A01250D0C19292AB801D9B3212FAA182B2B4EF43C4DFD3C4E10F64DE4ED1112392F3C003F3C3F12392F3CFD3C10FDE4390110EDEC0010F55D2B2B0110EDEC0010F55D2B3130011114163B01152135333236351134262B0135211323272E012B01113332363D01331123353427262301D24A8710FD9B1268403F691204001F4E031371EFD7ED9C584D4D251CB302F0FE1882483E3E4E7C03FD804C3FFEE015833AFD6D376211FE6D0F58261D00010055FFD105F0063E0026009E401E4B045A045B0778168816B8070629143814430768106914AB1406060A0117B8FFF04012261E1D2123221B1E1D20232320212118120CB8011340330BD0123809031A1800D018D502090A0601400B3A0D83210C0C1B250F263F2602261A28154A0F063F060206192728F52130A8182B2B4EF45D4DED4E10F65D4DED3C101A3DEDE41A185D003FEDF410C43FEDF4ED1112392F3C2B2B31303800715D015D2506232003261110002120171323272627262322001110002132371134262B01352115232206150536FDDCFE69C6AB0199014F0109D21E4E03024374DEF2FED6014B01334E7E416712022E0E6A4228570109E60149017101C43FFECB114A5E7DFE58FEA6FEA9FE8F1401627B4D3E3E4D7B000001004E0000061806100033008F40610C1E1D072322181E1D132322261E1D212322321E1D2D2322011E1D0623230D1E1D1223231B1E1D202323271E1D2C23231A19333300470006212020131312022D2C2C070706081B3225265F27010F274F27AF270327A8351801250D3F0C010C2F3410F45D3CFD3C10F45D713CFD3C003F3C103C103C3F3C103C103C1239762F183CFD3C2B2B2B2B2B2B2B2B3130011114163B01152135333236351134262B013521152322061511211134262B01352115232206151114163B01152135333236351101D242690FFDC2106941416910023E0F694202C242690F023E106941416910FDC20F69420308FE007C4E3E3E4D7D04007C4D3F3F4D7CFE4D01B37C4D3F3F4D7CFC007D4D3E3E4E7C0200000001004E0000028C06100017004E402B061E1D01
+
+2322121E1D0D2322131E171D002324071E1D0C23230D0C020100081917171A1213250706191819B801A0B3212FA8182B2B4EF43C4DFD3C4E456544E6003F3C3F3C4D2B2B2B2B3130290135333236351134262B01352115232206151114163B01028CFDC2106941416910023E0F694242690F3E4D7D04007C4D3F3F4D7CFC007C4E0000010000FE8C03740610001E006940100C1B270A560A035C1A6D1A0201E10808B801AC4026021D01171E1D1223220C1E1D1123230008381DE70112110201090C0B25181817011119011F20BA01BB0021014EB1A8182B2B3C4EE410DC3C4D10FD3C003F3F3C10FDED392B2B0110EDEC0010F5313000715D1901331F01161716333236351134262B0135211523220615111406070623224E03090A2D3B566E60416910023E106941273C68C6B0FECF01020F50422936BDD704A37C4D3F3F4D7CFBBBCEB54173000001004E000005E10610002D010340666524791C7A26792D881C9624061A254B2553275528042808270F3426332766266227040C1E1D072322181E1D132322011E1D0623230D1E1D1223230F2001201A442643274328032625002625002D2D25272627265912191A191A591225262526271A251F2B00B80235402619190812232B012B1D2C1F1D20221D21201312022D2C0706081A25211926272D03003F210121B8019A4016462C2C2F01181900250D3F0C010C192E2FF5212F75182B2B4EF45D3C4DFD3C3C3C103C1076E45D1812173911123939003F3C3C3C3F3C3C3CED10ED10ED5D111239192F18E41112393939390705102B10072B0710FD070810FD015D10C05D2B2B2B2B5D31303838005D015D011114163B01152135333236351134262B013521152322061511013635342B0135211523220709011E013B01152101D2416910FDC2136740406713023E10694101CF77570E019B1166C3FE67023A6D773810FEC4030BFDFD7C4E3E3E4E7C04007C4D3F3F4D7CFE2801D97820303F3FC8FE5FFD9E74543E0001004EFFEB04940610001F00764020B319C41902170A0A1E1D052322161E1D1123220B1E1D1023231C011A1C001701B80149B61A830511100202B8024440180508400083023A21011A211617250B0A192021C4212FFC182B2B4EF43C4DFD3C4E10F64D1A3DE4ED1A18003FE43F3C10FDE401111239001112392B2B2B0010C03130015D01330324290135333236351134262B01352115232206151114163B013237363704464E24FEA8FEBAFE7C126840416712023E11684192CD317B233310015DFE8E153E4E7E03FE7C4D3F3F4D7CFC026548304772000001004E0000077D0610002900CE40821A1539134A155A1568158915060C1E1D0723221B1E1D162322271E1D222322011E1D0623230D1E1D1223231C1E1D2123231314142512291415290015141433122914132928292814
+
+000422161515131312022221210707060813011429151C2724295B2994290329292A2B2827251B0F1C011C1A2B0001590D0C192A2BF6212FA8182B2B4EF43C4DFD3C4E10F65D3C4DFD3C191112392F5D1112391239113900183F3C103C103C3F3C103C103C12173987082E2B057D10C487082E182B057D10C4182B2B2B2B2B2B3130015D011114163B01152135333236351134262B01352109012115232206151114163B01152135333236351101016D426A0EFE270E6A42426A0E0169024002110175106942426910FDD10C6B43FDB00508FC007C4E3E3E4E7C04007C4D3FFBA5045B3F4D7CFC27A44D3E3E4D7D0467FB290001004EFFD1063E0610002100BE403B071278117A127821982105000D21210E0C1E1D074822201E1D1B2322011E1D062323120E111D12151E1D1A2323000D12070E131414251221210E21B8FFE0402A0E14071B1A1A1313120207060821090E1213010C141514B22121201A230001B20D700C010CB712192223BC011F00210030012500182B2B4EF44DF45D3CFD3C4E10F63C4D10FD3C391112391239003F3F3C3F3C103C103C123939013887042E2B870E7DC40011123939182B10ED0110C02B2B2B87107DC4C43130015D011114163B01152135333236351127262B013521011134262B0135211523220615110194406812FE1F0C673F1E574A12012903A141691001E012674104B5FC537D4D3E3E4D7D042C29743FFB8B036D7C4D3F3F4D7CFAC90000020055FFD10617063E000D0019008840344904017B01760575077B0D87079707B604BB0CE90A093E08143806030E380009114A100B200B4F0B030B771B174A3F030103301A10F45DED10F65DED003FED3FED3130437940300119090A080A02060F0D113401190117340013071134011505173400100C0E340018020E3400120A14340116041434012B2B2B2B012B2B2B2B2A81005D017105200011100021201716121510002532001110002322001110000336FEBCFE63019D01440125BA778BFE63FEBCDC011CFEE4DCDCFEE4011B2F01CE0169016901CDB070FEA4BAFE97FE323F01AB014D014C01ACFE54FEB4FEB3FE55000002004E000004A30610001B00240077405465156316671F8715C81ADA2106191E4A2256175C228617971597169717E922090C1E1D072322011E1D0687230D1E1D1223232432121B321D1D061202070608204A181A261F26012401250D0C192526C4212FAA182B2B4EF43C4DFD3C4E5D10F64DED003F3C3F12392FED10ED2B2B2B3130015D005D011114163B01152135333236351134262B0135213216171615140021273332363534262B0101D23D6E2EFDA31069414169100249B8A23D75FEA6FED9503ADFDFB6DA680284FE8582493E3E4E7D03FF7C4D3F243668BCF2FEE43EDAD9BD9F0000020055FE8B07F8063E0018002400D6
+
+401E9713B406B40ABA0C040B172917024906450C025B0813140011000E1C2216BB013B00100011020B400C001F3808030E091932000914B8015840141C4A100B200B4F0B030B7726224A3F050105302510F45DED10F65DEDE4003FED3F3FED10F64B5158B0801A59ED011112393900111239393130437940431724011003040204020610170E45000F0E181E091C3401200722340024012234001A0D1C34010F181145001D0A1F340121061F3401230419340001001B0C1934000D0E103C2B103C2B2B2B2B012B2B2B2B3C103C2B2A818101715D005D052427260235100021200011100005160433323715062322242732001110002322001110000334FEDB8D89A4019D01440144019DFEA0FEE1CB0179AEA9C5C5F6AAFE3E9BDD011BFEE5DDDCFEE4011C2F1D6F6C0174CB016901CDFE33FE96FEB9FE3E2559593B3B9CBDC801AB014D014C01ACFE54FEB4FEB3FE550002004E0000058406100024002D00E640647918CC2BD715032B081D1E1E1C0C1E1D072322011E1D0648230D1E1D122323221E211D221924272D252726190329241E1C1C25122424231C1E00232D32122400332625250612022322220707060824011C23291E22299316BA221A2F2D01250D0C192E2FB801E4B3212F75182B2B4EF43C4DFD3C4E10F64DF4ED12391239391139003F3C103C103C3F12392F3CFD3C10ED11123939870E2E2B7D10C401111217390011123912391810ED0110C02B2B2B07100E3C31304379401C272B141827182945032B142945012817264500181927262A152C4501002B103C103C2B012B2B8181015D011114163B01152135333236351134262B0135212016151406071E011F011E013B0115210127333E013534262B0101D2416809FDCA0F6A41416A0F024B0116E5B7B8414D66656A5C340CFED4FE41C7E1818EC3D75602E1FE277C4E3E3E4D7D04007C4D3F8EADA2E342285CA1A3A6623E02E13E27D0959A8C00010055FFD1041F063E002600C1405F37204902491B59105523051C182B0E2A1803190D190E162016212520390D342045084B1B451D5604580B591867046E0A690B6A0D6918121F1E0C0B04061910150115BD14D01938120306382501E700D025090B0C090F1F1E221C4016832114B80244401015510993221A281C930F514002832100B80244B63F010101192728B8016EB32130C8182B2B4EF45D4DE41A3DED1A18F4ED4E10F64DEDF4E41A3DFD1A181112393911123939003FF4ED10FD3FEDF4ED5D111217393130005D01715D370333171E0133323635342F012E013534243332171323270221220615141F011E0115140423226B164E031EBE9284BDF39AE08B0123EEBAC121500550FEE280A8D0DED082FED5FCD2100155109CA9B37E9FA66A9AAB79B4DC42FEDD1001179A76958F988FA97FC4E8000100270000057C062B
+
+001F007A40111F1E1D1A8722141E1D198723060EE90C07B80244401A0912013309021A19080E830D3A0F0C014F0C8F0CEF0CFF0C040CB801164011131425000F1F014F1F8F1FEF1FFF1F041FB80116400D073A05833F06BF06DF0603062010D65DEDF4F45D713CFD3CF45D71F4ED003F3C3FFD3C10F43CFC3C2B2B313001012322060F01231304213320251323272E012B011114163B011521353332363502699EB2881503522601030119D1011901032651041588B29E4D7D0FFD7D0F7E4C05C2608C1401691B1BFE97148C60FB457D4C3E3E4C7D0000010036FFD106070610002A0090405DAB25BB24F623F7240408230A25192503250E360A340E4B1E4B1F4B234B245A24970EA50EAB220B071E1D0223221B1E1D162322271E1D012323101E1D152323090D161515020201020C382109100FB21C1C1B1A2C070825262627192B2CBC017500210147012500182B2B4EF43C4D10FD3C4E10F63C4D10FD3C003FED3F3C103C103C382B2B2B2B3130005D01715D133521152322061511101716333236131134262B013521152322061511140607062122272E01351134262336023D1069427070C3B0C402416A0F01F00D6A43375995FEE6F08D6141426905D13F3F4D7CFD47FEC07F80F4011B02E97C4D3F3F4D7CFD69F3CC548D704DD5EC02B97C4D0000010000FFD106100610001C00CA402A1710171C350745074A1556075B15680F6A1588150A080D091D08151C161D150701061D071410131D1440B8FF86402D000F0E20100F0F251200001C0D0E0E59120000011C100D010005151414080807020F0E09101C0F14010D1E1E08B80168B2003A0FBA018D000E016BB41420141D1EB80121B3218B75182B2B3C1A1910FD18E6F419FD3C1239391112393900183F3C3F3C103C103C173987052E2B0E7D10C487052E182B0E7D10C42B1A180010ED0110C00010ED0110C00010ED0110C00010ED0110C03130015D09013635342F0135211523220607012301262B01352115232206151417033C01A5296711017E113B4E31FDDC3EFDC856480D01CA123C2A300101040C64193C0A013F3F5575FACA0536CA3F3F1823206F00010000FFD1083E06100023013740301615131B1621461B58155816591C6800082701015D005B125B130309100A1D091C211D1D1C0803071D081B151A1D1B40B8FF64B314232220B8FF584060110201209800121320501201120001015912111112030202251211111013002323251214141321222259121414152115141110030007231C1B1B131312120909080223222202020109100302010411082322131204001521251F252F2502251CB80117B620101420140214B801C7B300E94011B801CBB40820082425B8017EB3218B75182B2B3C1A1910FD1A18FDFD5D1A19FD3C5D1239391217391112173900183F3C103C103C
+
+3F3C103C103C103C103C12173987052E2B0E7D10C487052E182B877DC4872E182B0E7D10C487052E182B877DC45D2B2B2B1A180010ED0110C00010ED0110C00010ED0110C00010ED0110C05D313001715D090123012E012B0135211523220615141709013309013635342F013521152322060701230405FE7A43FE732249350F01F0134830140121017F3F01BF011D187713017C11334223FE7B4104C1FB100531715E3F3F25373444FC3404DFFB1C03D05434420A013F3F5B77FAD2000100000000053606100034016240D1032E190018081A28132E2801280E270F271A3807391C382748076422780E7522890F1135133514020E0E0D1313000E0E0F1B1B1A1C1C0D0000342828292727011B1B1C28282729291A0000010E0E0D34340F080D091D08141A151D142327241D232E342F1D2E0701061D07130F121D13221C211D222D292C1D2D281B0E0004132E281B0E0004341A271C0D0D59120101270F1A2929251234340F3429271C1A0F0D01082E232222141413022E2D2D08080708341A3A34451A4A34531A5A34631A073429271C1A0F0D010836082D36083536B8011FB3218B75182B2B3C103C111217395D003F3C103C103C3F3C103C103C121739870E2E2B870E7DC4870E2E182B870E7DC4011112173900111217391810ED0110C00010ED0110C00010ED0110C00010ED0110C00010ED0110C00010ED0110C00010ED0110C00010ED0110C08710087DC408C4871008C408C40710083C083C871008C408C4871008C4313001715D09010615143B01152135333236370901262B0135211523221514171B013635342B013521152322070901163B011521353332353427026FFEF24A7311FE650F3E67490143FEBC7B49110208166738C7CB56480E014E15567EFEFD0172795C11FE100D5F4002B6FE527621333E3E577301FA0209C63F3F3E2E5DFEB001509314223F3FC8FE62FD9BC83E3E34256C0000010000000005270610002700D0400D570A650AA70A03050A130A020AB8FFF040480C0D0D2512000D0E00010E0D0D59121B0D0C1B1A010C0D0E1A05041B81009100020000230407131603041D051514140606050220231D222221080C01050D1B000E1A151CBF050105BE01C80000001501C8001B0029023740091C1C1B2527B0000100BB023700280029011FB3218B75182B2BF65D3CFD3C10E610E410E45D11123939111239123939003F3C10FD3C3F3C103C103C10FD173C191112392F5D183C12173987082E182B0E7D10C487082E182B0E7D10C40138313001715D0901262B01352115232215141709013635342F0135211523220607011114163B01152135333236350236FEB675680F01F015483C010F01033852170177164B4A49FECD4C7C10FD86107C4C02D80232C73F3F312F67FE2801DC66213506013F3F4385FDCFFE307E4C
+
+3E3E4C7E00010055FFE3046C062E00190099B30AE10303B8015DB3091D0A16BB01A900100010015D401A151D16020E0F0F2512010102010F10020E0D0310320003320D0BB80244B20D0217B80244401900080100020F0A0E8C173A161A1B0A9C2F003F000200191A1BB80172B321306D182B2B4EF45D4DE44E10F64DF4E61139391239003FE43FE410ED10ED1112393912393987052E2B877DC4180110EDEC0010F50110EDEC0010F531303335012320070E010F01231105331501212037363F0133032421550315CEFEF05632210F034D036564FCEE01130149382F1E034D17FE47FE763E0593251541671601551E3FFA6D3B339910FE8E1D0000010108FE8C02F8066D0007002540130506360403100007360102120004A40763030810D6FDF43C003F3CFD3C3F3CFD3C3130011521112115211102F8FE1001F0FEABFED94D07E14EF8BA000001003EFFD1046D063E0003002B4015020101591200000302031001000B010005030205042FCCC6C810C6C8003F3C3F3C87052E2B103C313005230133046D7FFC50812F066D0001004EFE8C023E066D0007002540130700360201100605360304120104A40663030910D6FDFD3C003F3CFD3C3F3CFD3C313013352111213521114E01F0FE100155061F4EF81F4D07460001007C01B204D906100005004E401A02010203011F1200000502030201031F12040405020000010304B801E3B2050200BA022000050220B20407062FCCD6F4E4003FF43C3C3C123987052E2B087D10C487052E182B087D10C4313001230901230104D978FE4AFE4C7B022F01B20367FC99045E0001003EFF840517000000030025400D03005302010A021A0501190405B8011EB3213BAB182B2B4EE410E6003F3C4DFD3C3130173521153E04D97C7C7C000001016505080365064E00030024B302A48001BA024D0003021EB7029701D2210005042FDCDC3D1AED18FDED003F1AFC313001230133036556FE56DB050801460002007CFFE10493047C002A003600EE40270B120C18021E40320356080A662B2B352B2000041032140F153F15021510291A07329003256626B80101B42828030B00B8012A40150B3624251E1FF838601401146A49152F6A065238372FCCFEEDD476FD5D1810F43CCCFD3CE5003F3C10F4ED10ED3FFDD45DC41112173919392F18ED31304379403E3031292A0C2204050D0C0E0C0206182631042F27000F1B0B27011C1D1119132700222920270021202A0030053227000C1C1027011217102701212A2327002B2B2B2B01103C103C2B2B103C2B2B2B2A81818181004954794012333501023425350132E404330236E401010001103C2B002B2B8181005D250E01232226353436253735342627262322061D010735343736333217161511141716333237150623222603070E011514163332373635030758
+
+C56E6E92E8010B8918283D595C5CD78B89CCA94B4B20205F1E24626154651F39E8916343705F3DC5727295717DAF4C289D67511C2D4E4F32451E786C6945469CFE26B53C3C053B377201F21249756E486A69457A00020010FFDB04F9066B00140021009D40376B0001A90901171B191D2A0F2A1D3A0F3A1D4C1D570C5617670C6A13A60CB60CFA130E070CA509021411161508031F1901070B14160105BC012A0006020E00070241402A1F5B0B071929110B000B1C6A0E5023071624000030014001021F01200130015001B001C00106015523222FCCF45D713C10FD3C10F6ED003F3FED3FED3F19F418E50111123900111239111217391239313000715D01715D171134262F013525113E013332001510002122262713111E01333212353402232206CA275A39017470D363CA0105FEA9FEF055A954443BB1559ECCCEA34A9D2504D9904E2718108AFD416868FEC7F1FEECFEA31E1D033BFD6E4858010ED1D00105410000010052FFE1042F047C0015006E402B1712251235124A074A104212C805C807C70FD712E8040B18025D0D6E0DA80CB805BA0AD905DA10DA12090BBA020D000C01A2B70E290907009F4001B8010140134314B0030B901701014C0B5017116B065217162FCCFEED10F6E45D003FED1AFC1AED3FFDF4ED3130015D005D251506232200351000213217072623220215141233320407C1B9FEFEC3015A010DD4A28D84B592ACE1C8A68C614A0137FA010E015C7F98D1FEFADDF4FEED00020065FFDD054E066D001A002700A7402E480501182117232C2124232A273A2135233A274A0449279C049A05AA04BA040E0904010F1901192214DE46182019B80106400F1A1B1400031F250D13091B1C141A11BC012A0012020E0013024140221F2909071C255B030B1A0B0D1A24134014B014C0140314F829226AFF0601065229282FCCFE5DED10F65D3CFD3C003F3FEDC83FED3F19F418E50111123939001112391112173910F5ED76FC1801F55D313000715D015D250E01232200351000213216173534262F0135251114163B01150519012E0123220215141233323603D970D263CAFEFB015801133F84462D593C017D4A6808FE8B3AB1559ECCCDA44A9DB168680139F10116015B1111C83F332518108CFA98503A3C62012902924858FEF2D1D0FEFB410000020055FFE10436047C0014001E0070401918052911580503D911D91E029708CC11D9110318041C110211BAFFE000010211400E00001316660E470E131C29090713B8024FB2030B19B8010E40100D8D4F0001005020154B0E6A0652201F2FCCFEFDE410F65DF6ED003FED3FFD1139762F18ED12392FFD38313000715D015D712515062322001134003332121D0121061514123332013332363534262322060436DBCEF8FEC00133E7D0E7FD0201F6B6AEFDABCFE07782667EAD
+
+BC5E7D014C0101FE0150FEEEF520220DC2FEF902362D5583A6E70001002F0000039E066D001F0094401EA40A016609011608001A011F21201A222214212019B823090A0C020C2907B80241401712013102111010030302061A190A0A1109027A1F212011B801B3400F090F1424040F1F1F1F9F1F031F55202FF45D3CFD3CCCF410CC10E4111239003F3C3F3C103C103C10FD3C3FED00111239392B2B015D0031304379400E0D0E05060D060F27000E050C27012B012B8181015D005D1323353335343633321707262322061D012115211114163B0115213533323635E9BABACCCBBF5F8D4A884E4E013EFEC24D7E0FFDB214673F04104D66D5D5639CC18C8DB94DFCF87D4D3E3E4D7D000003005DFE2F0493047B0022002E003A00E140440D013F015B016B016935770187019701D93509224722001F030300150423142F37310017030C0F041504110764230123291414196B290129290A07400E210D06AF190119B8010B400D3A2F2F7F0001000A34291F0F0DB8020EB31137861CB8020EB5266A9F110111BB01A2003C0017010EB40347030731BA010E0022010140092C6A9F070107193B3CBC0170002100DB018A00182B2B4EF45D4DEDF4ED1239762F18ED10F45DEDF4ED10E4003FED3F5D3C103CED5D3F1AC81A3FFD5D11392FED5D011112173911123911123900111239391912392F111239762F183130015D212E0127372E01353436333217211523161514062B010615143B01201514042322262701323635342623220615141603061514163332363534262301414C3008FA849CE7BB6B5E0191FB64EBCF3275DFE60124FECEFCEFFD0D01EE6C7D7D6C6C7D7D5158AF8A94C76E893A4945AC22CC89B3DD1F5D8586BBD5443352EEACD29E9E0238B29B9CB2B29C9BB2FE5D4E6A617B916B55430001004E00000565066D002D00964035C518D618E400E614E61505B92A011F228E229E22030C21200722222721202222220121200622231C212021222300142B220D131711BC012A0012020E0013024140262B5B17072221210707060A27240F1C401CC01C031CF82F1301240D0F0C1F0C9F0C030C552F2E2FCCF45D3CFD3C10F65DED003F3C103C103C3FED3F19F418E5111239111239392B2B2B2B015D3130015D005D011114163B01152135333236351134262F013525113E0133321716151114163B011521353332363511342623220601C2436B0DFDD1126741275A39017478D75E88595B426A0EFDD2106941616E50B00356FDB27D4D3E3E4D7D03AC8F502618108CFD2774745D5FFBFE437D4D3E3E4E7C01C1948445000002004E0000027D06100012001E0069401C090F190F020C21200722220121200622230D000760130113E2190211BA012A0012020E4010000707060A00204F200220F80116E21CB8012A400D000001240D0F0C1F
+
+0C020C551F2FF45D3CFD3C10F4ED10E65D003F3C3F19F418E53FED5D1112392B2B31300071011114163B01152135333236351134262F013513222635343633321615140601C2426910FDD1146640236334F6384C4C38384C4C0477FC917C4E3E3E4D7D01B797452D190F01184C38374D4D37384C00020008FE2F021806100010001C005D401109071B070201050B0060110111E2170209BA012A000A020E40090B07000F010414E21AB8012A40140B001E101E021EF80B0C24040F051F050205551D2FF45D3CFD3CE65D10F4ED10CC003F3F19F418E53FED5D111239393130007113353E01351134262F013525111406070613222635343633321615140608BA71295E3B017C4A609AEB384C4C38374D4DFE2F4951C1EE024E8E4E26190F8BFBF8BAC1406606B64C38374D4D37384C000001004600000500066D002700DF405FB400B614C922E400F4000578227A267827A922BA22DA21DA22D527EA220919211A223822030C21200722221C201D201C0121200622231B151A201B26222520260D131C222121241200002720212131121414152227008DA014011414061B11BC012A0012020E0013024140201C1B062726260707060A27222120151400072926291301240D0F0C010C5529282FCCF45D3CFD3C103C111739003F3C103C103C3F3C3F19F418E5191112392F5D18E61139870E2E2B7D10C4870E2E182B7D10C4001112391810ED0110C00010ED0110C02B10ED0110C02B313001715D005D011114163B01152135333236351134262F01352511253637362B0135211523220F0101163B01152101BA446C0BFDD112684029553C0174012D840202580F018C1149E1DE0173B4500EFEEB0275FE937C4E3E3E4D7D03B18A532318108CFC07FF6F1E1F3E3EBAB8FE5CCB3E0001003E0000026D066D0012004C40100C21200722220121200622230D000711BC012A0012020E00000241401707060A00141014AF140314F801240D0F0C1F0C020C55132FF45D3CFDE65D003F3C3F19F418E51112392B2B3130011114163B01152135333236351134262F013501B2436B0DFDD1126840275A39066DFA9B7D4D3E3E4D7D03AC904E271810000001004E000007D2047C004601154079C618C619C61EC61FD618D619D61ED61FE415E51BF515F61BF61E0D0615061B0210061F28103A030F281F28020F3B1F3B023B28493A0647283A2D353B0640010C21200722222D21202822224021203B22220121200622232221202722233521203A222342340D0004443B1A3540445B17315B1D1D1717133400BD011200130011012A0012020E403813073B3A3A282827270707060A00484F480248F8222E2D2421802290220222F1402434803590350235F11301240D0F0C1F0C9F0C030C55472FF45D3CFD3CFD5D3CEDFD5D3CFD3C10E65D003F3C103C103C103C10
+
+3C3F19F418E510FD3C103C103C10ED10ED0111123900111217392B2B2B2B2B2B011112393911123939762F2F762F2F5D5D71313000715D011114163B01152135333236351134262F013525153E01333216173E0133321716151114163B0115213533323635113426232206071114163B011521353332363511342623220601C2436B0DFDD1116841295839017477C24C6D98157BCE538D4E40416910FDD11367415A61489B53436A0DFDD21168415661429D0355FDB37D4D3E3E4D7D01CF7F4D25190F8CDB6E6D7D6C7574705BE9FE407C4E3E3E4E7C01D2887F4646FDB37D4D3E3E4D7D01D6897A46000001004E00000565047C002D0095400BB92A01C618D618E7140316B8FFFC40261F228F229F22030C21200722222721202222220121200622231C21202122232B5B1700661411BC012A0012020E001401A24026174B13072221210707060A27240F1C401CC01C031CF82F1301240D0F0C1F0C9F0C030C552F2E2FCCF45D3CFD3C10F65DED003F3C103C103C3FE4E419F418E510ED10ED2B2B2B2B015D313038005D015D011114163B01152135333236351134262F013525153E0133321716151114163B011521353332363511342623220601C2436B0DFDD1126741285939017478D75E88595B426A0EFDD2106941616E50B00356FDB27D4D3E3E4D7D01C28A4E26190F8BE774745D5FFBFE437D4D3E3E4E7C01C19484450000020055FFE104C2047C000B0017005B403FD60ED610D914D91604261601440C4B1202340C3B1202240C2B1202122906070C29000BDA02DA0402D508D50A020F6B1009019F090109095019156B035219182FCCFEED10F6D65D71ED5D5D003FED3FED5D5D5D31300071015D052200111000333200111000273212353402232202151412028BF7FEC1013FF7F8013FFEC1F89ABCBC9A99BCBC1F014C01020101014CFEB4FEFFFEFEFEB446011EEAE9011EFEE2E9EAFEE200020036FE4E051F047C001F002C00AE4036591F691F791F881F991FA518B618C618F5220907180122080C21200722220121200622232120140D00052A24202127012A5B17171311BA012A0012020E4020130724291D0B07060E276A3F1AF01A021A502E1301240D0F0C1F0C020C552E2D2FCCF45D3CFD3C10F65DED003F3C3FED3F19F418E5103C10ED011112393900111217392B2B3130437940182529181C251C272E012918272E01261B242E0028192A2E012B2B012B2B818100715D251514163B01152135333236351134262F013525153E0133320015100021222603111E0133321235340223220601AA436B0DFDD1096D4428563C017470D363CA0105FEA7FEEB4084433BB1559ECCCEA34A9D07B27C4D3E3E4D7C03708D5323190F8CD06868FEC7F1FEEAFEA5130363FD6E4858010ED1D001054100020065FE4E054E047C00190026009B
+
+407018201722282027223A113C1235144B115B119A14AA11A514BB110D09111A1129110349114912640063189723054A12012621010C21200722220121200622231B1A0D032419001E19011B1E2916160007245B100B07060E1B4B0C24000F012F0140019F010401F828216A9F130113522710FE5DED10F65D3CFDE4003F3C3FED3F3C10ED01111239001112391217392B2B015D3130715D00715D011114163B0115213533323635110E012322003510002132161703132E012322021514123332360494426B0DFDD112684070D263CAFEFB0156010A5AAA50400244A25D9DCCCDA44A9D047CFAD97C4D3E3E4D7C015C68680139F10112015F1D1DFCC402925050FEF2D1D0FEFB410001004E000003F9047C001F008B4030071A591A691A791A891A991AF90F07080F190F951AA51A040C212007222201212006B8231A1E1A140D00050719171C19B8012AB41C5B170711BA012A0012020E401C130707060A1A1A1E19010F190119211301240D0F0C1F0C020C5521202FCCF45D3CFD3C10C45D111239397C2F003F3C3F19F418E53FFDED1112391217393D2F182B2B313001715D011114163B01152135333236351134262F013525153E0133321707262322070601CA4D7D0FFDAB126D43285E3C017C69AF467E53974B594F90040344FDC47D4C3F3E4D7D01B7944F26190F87DC717080A4818303000001006DFFE10384047C002A00C24039580C680C7704770D8704870D9806970A9928A928C70EC81E0C170E1710270E2711370E3711DA14DA270826060121220D0C04081F081F051C15BA01A30014020FB41C29120701BB011200480000020F400D0529290B0C0D080F2221261F16BA02110015020F4017460886102601D2260126502C1F86DB0FFF0F020F4C4702B80211B6004C4701B12C2B2FCCFE76E418ED76F45D18ED10F65D71ED76F418FD1112393911123939003FEDF476ED183FEDF4ED1112393911121739313000715D015D3703331712333236353427262F01243534363332171523272E0323220615141F011617161514062322851850032BEF67942626925FFEF0C8AB91AD500307182D5250546BD3699A3B3AEAC0CA2C011A14FEED815A382B2A4F3495B7889E3FE8133045352C614C6F753A5548496992B1000001001FFFE10317057900120079401F87089608A508B608C50805250876080213080820090C0831400B0A06009F01B8020FB61143030B008D0CB801524017090E2408070F061F064006B006C006050655B0140114132FCC5DF45D3CCCFD3CF4F6003F1ACDF4ED3F3C1AFD3C333831304379400C041010040E27000F051127002B012B8100715D2515062322263511230111211521111416333203177C88AB92B701710165FE9B69743E815A46CCF002730169FEE44DFDAEC5B30001002FFFE1054E047C0023009C4020
+
+B611010B141B142B143A144914CD04DA04F51E08061E371E0222221DDE212022B8020E400A231D16150800050E121ABF012A001B020E001C000C012A000D020E402A1C0E07125B23030B1623241C0F1D401DC01D031DF8250E0F24070F081F084008C00804085540250125242FCC5DF45D3CFD3C10F65D3CFD3C003F3CED3F3C19F418E51910F418E51112173910F4EDFC01F5313000715D015D250E0123222726351134262F013525111416333236371134262F0135251114163B01150503D265D36EA74E4E265B3901745C725C8F76275A3901744E6C08FE84BD6E6E6B6AE40125944F26190F8CFD60D98F3C5801BA914F26190F8CFC8C533B3C5D00010000FFE104E9045D001C00C340260701070D080F081B1B07190839073A0849074615C70EF80E0C0E0D0E0F0D24120101000E0F0FB80131402E121B1B1C1B0F0E0D0105051C082007161B1720160601052006150F1420161515070706061C000B1B161C01000616BB022D0047001C018C400C430073008300B300E3000500B8022DB647060F0601061D103C5D1076F45D18FC76E418111239111239003F3C3F3C103C103CED0110C00010ED0110C00010ED0110C00010ED1112173907052E2B7D10C407052E182B08107DC43130015D05012E012B01352115232215141709013635342B013521152322060701026DFE564042320F01D1126237012C01062B6C1101750F2F4732FE7E1F03767F493E3E312174FD89027664253E3E3E5473FC890000010000FFE1069B045D00240141409F090006210724180018121713182217242800281227132822272438063912372338244B06441B5800591158135714572185138514862185239A22B8001E1112111023247523012331122322111211101024120100011413141523227723012324121313141415153112202120011011231415200700040720061D201C0420051A201B1C1B1B1313121206060506212224000B201C21232412010005441C011CB801BD4028216630225F2202042244225422802204224613663F125F1202041244125412031244246644000100B801BDB305052526BA01F700210127B176182B2B3C10F45DFD76DC5D7118FD76DC5D7118FDE45D18111239111239111239003F3C3C3C3F3C103C103C103C103C10ED10ED10ED10ED1112173907052E2B7D10C4072E182B5D07087D10C407052E182B7D10D40708182B5D07087D10C43130015D0501262B0135211523221514171617161713013301133635342B013521152322070123090101C0FED0453E0D01AB0D6D090A010D02CE012F400167B71D580F01360F4A41FEEB3FFE93FEC21F0371CD3E3E42121D22063005FDAB0361FC9A025A622C403E3ECEFC900381FC7F000001001000000494045D0035017F40E6081C08284C144A2A4A355C2A5B345C3569076622A60D
+
+A61BA622A629BA1CB41DB421B928B933E92AF90BFA1BF521FA2A18180B2A0B280C2823040D0D0E1B1C1C0C002829292A2828011B292A2A1A292E2E1B000D0D0C0E35350E080C092008141A15201423282420232F3530202F0701062007130E122013221C2120222E2A2D202E291B0003132F291B0003351A28010131120C0C1C1A2A2A241235350E1C1D2806033C0C3C1C3C3503352A281C1A0E0C01082F232222141413062F2E2E0808070A840CA60CA935030F351A352A356A3504352A281C1A0E0C0108082E1A370F080108193637B801E5B3218176182B2B4EE45D10E61217395D5D003F3C103C103C3F3C103C103C1217395D011738870E4D2E2B7D10C4870E2E182B7D10C4011112173900111217391810ED0110C00010ED0110C00010ED0110C00010ED0110C00010ED0110C00010ED0110C00010ED0110C00010ED0110C00087100E3C087DC40E3C07100E3C07100E3C3C871008C40E3C3C87100E3C08C4313001715D01070607063B0115213533323713032E012B01352115232215141F01373635342B013521152322060F0101163B0115213533323534270224AB6702024010FEB21748A1E1EC6C3F231001AB103E6D7F8E773F0F0146102F6765C1010B8F4A0FFE360F3F5701D1CF7E1F273E3EC30110013E913F3E3E261992ABAA8E22223E3E557BEBFE9AC03E3E2B22740000010010FE2F0518045D002900DB407A051E171E5B065B0755156A066A076615C701C70D0A0000010E0E0D29290F070D082007161B1720160601052006150F1420152321242926232A240601000024120E00280E0D1B1C1C311229290F1C261B0F0E0D0100062916151507070606290B2686210F0B0D9E0D02291C1B0F0E0D01000806161A2B06192A2BB80177B3218176182B2B4EE410E61217395D003F4DED3F3F3C103C103C1217391139870E2E2B7D10C487082E182B0E7D10C401113912390011123912391810ED0110C00010ED0110C00010ED0110C00010ED0110C00710083C083C3130015D25012E012B01352115232215141709013635342B0135211523220607010E010706232227371633323637027AFE784044300F01D1126238011C011E32640A01560E32433DFE3944505172874C57624B3A76B03A2303327E4C3E3E322078FDA4025C6820423E3E4D7FFC528E6A3A4417AD127C7C00010065000003F8045D0014006A40127802880202020C0D0D24120101020C026609B80212B50A06010D6613B80212400C000A020D0C010C4B40144C12B80211B313014008B80211B70A4C094B015216152FCCFEF4E4ED1A1810DEEDE41A18E411123939003FEEFDC03FEEFDC087052E2B877DC43130015D333501232207060F0123372115012132363F01330365028BCBEE303911034B200343FD760109B28A130355223E03E928305911F836FC174F7013
+
+FEF0000100D1FE8C02B20675002C008F403945045629760486049604BB08CA01C820C925F609F61D0B0708170802000016361F1701174A170B2240233622100A36210B12001602220B022BB80251B249131AB80251B3470E2607B80251B2491F0EB80250B70016101602162E2D2FCCD65DFC3C76FD183C1076F4183C76F5183CDC3C111239003F3D1AED183F3DED1A18111239762F5DFD393D2F313001715D011615140F010615141617152E0135343F013635342B0135333235342F012635343637150E0115141F01161514019AAC321E2D8663A4D837292CA34E4EA22B2937D8A463862D1E3202807B973A8B537B36538A13290EC4875F825F66517A557952665F825F87C40E29138952387B538B3E9200000100ABFFD1014E063E00030033B900010122400F000517171A02020369000001190405B8013FB3213F41182B2B4EF43C4D10FD3C4E10456544E6002F4DED313017113311ABA32F066DF993000100E1FE8C02C20675002C007B4028451D561078298829982905000017361F1601164A160B2240233622120A36210B10001602220B022BB80251B249131AB80251B3470E2607B80251B2491F0EB80250B51F1601162E2D2FDCD65DFC3C76FD183C1076F4183C76F5183CDC3C111239003F3D1AED183F3DED1A18111239762F5DFD393D2F3130015D012635343F013635342627351E0115140F010615143B0115232215141F011615140607353E0135342F0126353401F9AC321E2D8663A4D837292CA34E4EA32C2937D8A463862D1E3202807C973A8B537B36538A13290EC4875F825F66517A557952665F825F87C40E29138952387B538B3E92000001007C016D04D902E9001B0039B90018024FB5053A400F800AB8024F400F013A13400E5E210F401D005E21011C10D61A3DFD10181AD61A3DFD181A002FE4ED1AD41AF4FD3130132335343633321F01163332363D013315140623222F012623220615CA4EA3745BA84BB1483E744DAA785D9B4EA7484573018C118AC2672E6B8A4B0C1388C263326B814D00FFFF0000000006100788023200240000001601040000000300000000061007880029002C003800DD403E0A2B2C090B2A2C2C0C0209031D021318141D130126001D01120C111D122C092C0C0925122626252C0C2C090C5912181819180C09262C0501190B0A332A2BB80117B40125193230B80247401536381F1312020108092601250C18131925192D3A01B801CBB2223833B80247B21C382DB801CBB31313393AB80121B3218B75182B2B3C10FDEDF6EDFD3C1239391112393911123939003F3C3C3C2FFDF6FD3C10FD3CFD3C11121739870E2E2B087D10C4870E2E182B087D10C4180010ED0110C00010ED0110C00010ED0110C00010ED0110C007103C3C877DC4C431302515213533323635342F0121070615141F01152135
+
+33323637012E0135343633321615140607011E01330121010314163332363534262322060610FE3A113C2A315CFD575F296710FE860C3A5030022844456447466444450233353E2CFBA6025EFECA2E402D2D3F3F2D2D403E3E3E18221C72E3E7621A3D09023E3E5774052D1A533A476464473A531AFAD37C4F01F802DC01CB2C403F2D2E3F4000010055FE4D053E063E002B00BC40264815010F1429233823491459146B146A1F68236725091005120A02022B240D4008801203021CB80113B61BD0213819032BB80113400F4000D02127381302090916010AE710BA01370005019A402B138302022A24401D831B3A1C003A2A83211C510F2B3F2B022B1A2D244A0F163F160216192C2DF52130C8182B2B4EF45D4DED4E10F65D4DE43D1AEDE410E4ED181A1112392FEDF4EDED5D003F3CE91AF41AED3FEDF4ED10D4C41ADC1ACD011112392FDC39DCCD3130005D015D250423071615140623222735163332363534273724001110002132171323272E0123220011100033201337330522FEE5B135C45B5B5B4442283433A54BFEB7FE9701990156FBD51F4B0318D5AAEAFED20135FA015137034E214F62128645461B3D1A292955128E2201A90164017A01C33FFECB128B99FE56FEB5FEA9FE5A012F1100FFFF004EFFE40494078402320028000000170103FF6A0000FFFF004EFFD1063E0784023200310000001601060000FFFF0055FFD106170788023200320000001601042F00FFFF0036FFD106070788023200380000001601044600FFFF007CFFE10493064E0232004400000016008D3200FFFF007CFFE10493064E023200440000001600438100FFFF007CFFE10493064E023200440000001600D8B500FFFF007CFFE1049305D90232004400000016008EDD00FFFF007CFFE104930608023200440000001600D99C00FFFF007CFFE10493065D023200440000001600DD9C0000010055FE4D0432047C002700AC402B49184A2240245F1E6F1E9A15B51EE71CEB1E09172427242325352435259916BA1BB71CC41DD41DE91E0B1CBA020D001D01A2401420291A070E2940098049136646049F14009F4001B80101400A4326B014030B0413030BB80153B2119006BA020E00140211B4030323011DB8020E400B1C4C015029236B175229282FCCFEED10F6F4E41112392FEDF4EDFD113939003F3CED1AFC1AED10F576E5761ADC1A18ED3FFDF5ED3130015D005D2515062307161514062322273516333236353427372600351000213217072E0123220215141233320407D5973DC45B5B5B4441283434A555F1FEF801560111D4A28D3AB75587AAE5C6998C614A71128645461B3D1A292955129D1F011EE60119015F7F985C75FEF3D5F0FEEAFFFF0055FFE10436064E0232004800000016008D7F00FFFF0055FFE10436064E02320048000000160043
+
+B300FFFF0055FFE10436064E023200480000001600D8F400FFFF0055FFE1043605D90232004800000016008EF400FFFF004E000002C2064E023200D700000017008DFF5D0000FFFF00170000027D064E023200D7000000170043FEB20000FFFF002F0000027E064E023200D70100001700D8FEBB0000FFFF00080000028405D9023200D700000017008EFEBA0000FFFF004E000005650608023200510000001600D94E00FFFF0055FFE104C2064E0232005200000017008D008B0000FFFF0055FFE104C2064E02320052000000160043D900FFFF0055FFE104C2064E023200520000001600D80000FFFF0055FFE104C205D90232005200000016008E0000FFFF0055FFE104C20608023200520000001600D90000FFFF002FFFE1054E064E0232005800000017008D00AA0000FFFF002FFFE1054E064E02320058000000160043CF00FFFF002FFFE1054E064E023200580000001600D83300FFFF002FFFE1054E05D90232005800000016008E3300000100F8FE8C045D0610000D00A8403875007A017C037C067409750C0665006A016C036C066409650C0655005A015C035C065409550C06400C5D035D04095D065D05210B04600A05BA0228000101FB40130702400160036006600800600C60096007600BB801B4B60D500860080208B8021EB607500D600D020DBB021E0007000201B4B2040F0E2FCCD6F63CED5D10ED5D10E63D1A10EDEDED10EDEDED1A18003FE4F63CFD3C3D1A10E4E410E4E41A18313001717171012303130535050333032515251302CD405252FE6B019552DC4A0190FE704AFE8C04210159228C1C01BCFE441C8C22FEA7000002004E043E024E063E000B0017005B4046E901E902E304E305E307E308E90AE90BFB01FB02F504F505F507F508FB0AFB0B10040E0B100B140416130E1B101B141316080C2C400097C0122C06030F2C400997C0152C031810D6ED1AFC1AFD003FED1AFD1AED313000715D012226353436333216151406273236353426232206151416014E6A96966A6A96966A50727250507272043E966A6A96966A6A963E725050727250507200000200ABFF65048406AB001B0021008440182D102A112C12031A0415062C1F2621040F0E0B131D660B09BD01520008001802110019020FB61B144B1C9F1B01B801524020020A14140031081C0101201947100E4C194C0F1A23206B05192223F321DBFA182B2B4EF44DED4E10F64DE4E4CD761112392F183C3CFD3C103C002FE43CFDE410F4ED2FE43CFD3C10D4CC3130005D015D0523112600353400371133113216171323272627111633323715062327110602151003004DFAFEF20118F04D4CE335204D0558DA331D8499B5B84D8BA49B015423012EF5F6013E1C015CFEA42817FED90DFA20FC1702355A477D03DA12FEE2E3FE7E0001009B000004B2063E001E
+
+00AB403F68097809A804B809E809F80906361501250A2814740A0318151414190407080803080303911219191419031C0414080B180436150707111C01DC000A0E600DB80197400A112C0B05080314190416B80167B306060D1CB80197400A00C51D680E0D1A201F20B801E1B3213E41182B2B4E10F64DC4F4FDED12392FED1739003FEDFDED3FFD3C11392F3CFD3C12393911123939870E2E2B7D10C40507103C3C07103C3C3130005D01715D3335361337233533371A01333217072E012322060307211521070E010721159BBF492DB9CA1541C5B5A75A74175F364A5434270148FEA9142984B20346A3330172E74D6B014E0109858C5E75B3FEF8C94D68CDCE89A300000200CAFE8B049B063E0032003E00E240884608490A4921462447274937463C57045A0A5515591D562456255B365838553C573D66046B1D870C860D8739893EA60BA738A7391A1B0E1429283738073A0E3429690E69156529652F79120B2C332E3B3911351414353B2E04061F01950058062C31171A9519581F2C17032C332E3B39113514401BD2195D1A02D2005D01211A5D35392A3509442EB801DE400D01224414143B390F3501193F40B801DFB32173A9182B2B4EF44DF4ED3C10ED10FDEDF4EDE43D1A10E4ED10E4ED181A1112393911123939003FEDF4ED10DCEDF4ED1112173911123939111239393130015D005D130333171E0133323635342F012E013534372E013534243332171323272E01232206151417161F011E01151407161514042322013635342627250615141605E1174E031BC48E8AC0F38ADDA67D3E3F0123E8CCB620500319D3877FB63C3B956BE1BF817AFECBF0CD02433AA4CFFED836B90102FECE01511197AD9A707F814975B07589982E784AA6D042FEDD0F799F9266493C3C4D3875C3728E935694A8DA028D4A4A56A072A547525FA889000101000155045504AB000B0020400A06A600091A0D03190C0DB801D8B321899B182B2B4EE410E6002F4DFD313001222635343633321615140602ABB1FAFAB1B1F9F90155FAB1B1FAFAB1B1FA0000010070FE8C04C5061000110035B6064706040E0400B8017D40121103360E0205D20402D20F1101110F130A1210D610D4D45DFDDEED003FFD3CFD3C111239762F3130012311231123112320243534373629011523042A55BA5619FEFCFEC88C88014E01F39BFE8C072EF8D20417EAC3C3807D560001002FFFE10501066D003D0097402A3F0C490AB90CF90A041B0B1A3B280A290B3A0B5A0B6B0B6534081D202421201F222215292A001F1E0A01BA01A300000101B405293C0B1EB8023A400B400266012100461912862DB8014BB70886391A3F33900DB80108B71819242524193E3FB80173B3213DAD182B2B4EF43C4DFD3CF6ED4E10F64DEDF4ED1076DC3D1AD418ED1AE6003FEDF4ED3F3C3FED2B
+
+00103C3130005D015D252733171633323635342F012635343F0136353426232206151114163B0115213533323635113436373633321615140F020615141F011E01151406232202C318460321964566F35DDF562B877A52655B2B4110FE101367403B5568AB9EBF89283756BE6FB178B29D7815EB13CE765184AC419D84536C37AB6D446592A5FC1980533E3E4E7D0394A29C42507B66696A202F493C5C8D5184A5708FA200040055FFD106C2063E0023002C00380044013C404F0C413C413B434B414B43BC3ABC3EB440B444F62EFA380B17411743020A443C3A3B444B3A4B4486158C2E8A2F833183358A378C389D2E9A2F923192359A379D3812173A1744021107011F2301232222B8013D4023121D1C1D1A00231C1D202320060932081232132332F02401242412490821220F070107B80114B72D2C321300140114B80114B5334039D1212DB8017A4014403FD12133031308080D42231A221D1C05210128BA013B0017019AB300210121B80114B2362401B8013DB40EB00D010DB801C8B530403CD12136B8017AB74042D12130194546B8017AB321306D182B2B4EF41A4DED1AFD1AED1A10F45D3CFD3C10F45DF4ED111217391112392F3C003F1AED1A18FD1AED1A10F45D3CED10F45D3C3C3C7611392F5D18ED10ED10FD3C3C111239391112390705102B107DC45D5D313000715D01715D01111416333237172135333236351134262B013521321615140607161F01163B0115230127333E013534262B01132000111000212000111000252000111000212000111000031F1F2C0A1905FE751A3B23233B1A0187B99B6F6F305D41682B17D9FEE1657E50507B7C276CFEABFE1F01E10155015501E2FE1EFEAB013501B4FE4CFECBFECCFE4C01B302F0FEDD443202403F2B4A02904A2B3F617368942B1F9268A53F01D73F1979605958FAFF01E20154015501E2FE1EFEABFEACFE1E4E01B40134013501B4FE4CFECBFECCFE4C00030055FFD106C2063E00190025003100DC404F3A2E3B304B2E4E304E31A904A906B90408052D0A313A273A314B2779118A1C851E85228A249D1C931E93229D24B428BA2AB82BB82DBA2EB4301406070100191019021946150F0B010B0F400F2C2108B80221B58020152C2102B80221B480265E211AB801F64013402C5E212003400CD20A350B186F0035210B19B80157400B23124405C01D40295E2123B801F6B7402F5E211D193233B801F6B3212A42182B2B4EF41A4DED1AFD1AED1A10F4ED10F43C1A3DE4ED10E4ED181A003F1AED1AFD1AED1AFC1A18ED101AFC1AED1A10D45D1076CC5D313000715D015D010623220035340033321F0123272623220215141633323F013301200011100021200011100025200011100021200011100004DA9A8AE5FEF2010DDEB8741746032BCA89B5BF91C724033EFE9AFEABFE
+
+1F01E10155015501E2FE1EFEAB013501B4FE4CFECBFECCFE4C01B3012F37011CF0EC012022E611B8FEEECEBFFCCE13FDBA01E20154015501E2FE1EFEABFEACFE1E4E01B40134013501B4FE4CFECBFECCFE4C0002004E030806DA0610001B004500ED404F1B542D16842210542D15842328542D23842237542D32842243542D3E84221D542D22842329542D2E842338542D3D84232F30305312453031451C313030671245302F45441C443045043D3E22231615B8011A4014070F006F32312F2E0807024717171A3738534443BA022200450222401A1C1D362928DD4008350AD22109E510531B40073505D22106E51BBB02290046004701F4B3212A41182B2BF6F41A3DEDE41A1810FDF41A3DEDE41A18F63CFD3C19F6F63C18FD3C4E456544E6003F3C3C3C3C3C4DFD3C10FD3C3C3C3C3C173987082E2B057D10C487082E182B057D10C4182B2B2B2B2B2B2B2B3130012322060F012337211723272E012B011114163B0115213533323635011114163B01152135333236351134262B01353301133315232206151114163B0115213533323635110101653C4F3A090346160286164603093A4F3C1C3517FEAC17351C028C172C16FEFE162C17172C16C6010BF5CC172B18182B17FED1192C18FEF405CB273D17C0C0173D27FDCB351C3D3D1C3501ACFE54351C3D3D1C3501EB351D3DFDFC02043D1D35FE15351C3D3D1C3501D8FDCF0001016505080365064E00030024B300A48003BA024D0000021EB7019702D2210305042FCCDC3D1AED18FDED003F1AFC313001330123028ADBFE5656064EFEBA0002014E050803CA05D9000B0017002AB612630C0C066300B8024DB215630FB801A1B2096303B801B4B119182FCCF6FDF6ED003FED3C10ED313001222635343633321615140621222635343633321615140601B72C3D3D2C2B3D3D017F2B3D3D2B2C3D3D05083D2B2C3D3D2C2B3D3D2B2C3D3D2C2B3D0001007C007C04D903E1001300924009060302130412070707B8024A400B1208100D0C090408111111B8024AB41212120707B8024A400C120808111211B9101300030FB8024AB40D0201030EB801A1B50B04030C030BB8024A4015050609030AB908071112D604000A0708D60E0A15142FCCDC3CF4C810DC3CF4C8002F3CF4173CFD173C10F6173CFD173CF43C0705102B07102B1007173C102B1007173C3130011521072115210723372135213721352137330704D9FE6BA9023EFD67C192BFFED0018BABFDCA0294B88DB603006DC96DE1E16DC96DE1E100020000FFE407D50610003D004000F4406030403F3F310F101F1002104816167D111D102E1E1D29232238A03C391D38000F100F020F480A0A7D0E1D0F3731361D3730402E31003F313133123D3D00313D301B3F03B70883003E403330302FE90A09331717164716290002383721BA1B
+
+8322B80244402337282908100F0F1803313C38000818253F2E2E4142013A0383028C223A208321423841103C10D6EDF4F6EDF41112392F3CFD3C391239391112392F3C003F3C3CE4FDE4103C3F1239762F183C10FD3CFD3C10FD3C10FDF43911123939870E2E2B87057DC40111123939180010ED0110C010EDEC0010F55D10ED0110F52B0110EDEC0010F55D8710053C7DC4313001211323272E012B01113332363D01331123353427262B011114163B0132363F01330326232227262321353332363D0121070615143B01152135333236370111010449034B1F4D031471EFDCE89F5A4D4D261DB6E8A9D52A5D5913034E1FBF5E6286831BFE7C116544FD8B974A6B12FE900B2C465C0370FDB60610FEE015833AFD8C376211FE6D0F58261EFDF1644F5E7713FEAE0D08073E5179E1E3781A363E3E448401210360FCA00000030055FFD10617063E0013001B002300C540562908020914150A0A010C131C1D0B0B001D1C1514130C090208171F02001D1C15141309061A0C220A0101331200000B173807030B0A031F3811110101000900011A040A220B25224A0E1A251A4A04192425F621306D182B2B4EF44DED4E10F64DED1239123911123939003F3C103C10ED3F3C3FED87052E2B7D10C40111391217391139001112173987100E3CC43CC487100E3CC43CC43130184379401C202118190F100506201022340118061A3400210F1F34001905173401002B2B012B2B81818181172337021110002120173733071611100021202737012623220011100901163332001110B964C6C6019F0147011CC79960C3C3FE62FEBEFEE2C93903349BEDE8FEE903B0FCCBA3E2E4011C2FEF01000144016C01CEBDB5F1FFFEC4FE97FE30B4BE03CAF3FE64FEACFEFD02B5FC36E801A1014F01010003007C00F804D9035500170023002F00564010000C030924182A1E1B5A092D5E0F0F09B80118401803275A15215E15033117171A2A5E12371E5E0619302639182B4E10F44DEDFDED4E456544E6002F3C4DED10ED10FD3C10ED10ED01111239390011123939313001070623222635343633321F01373633321615140623222F022623220615141633323F0117163332363534262322070297268E7D64869A6C7C8B3337738862899675708D6921836241585D455179B631805342565B415A7C01DD31B4A47A83BCA53D49999C7194BCA37B289F7858526E8D5D348C755950709A000002007C000004D90536000B000F0054B30A7E0007B8024AB301067E04BB0132000C000F024A400D0D0E0A1117171A00000D7E0A03B8024A400A09047E0F0619102639182B4E10F43C4DF43CFD3CF43C4E10456544E6003F3C4DFD3CF6F43CFD3CE431300115211123112135211133110115213504D9FE086DFE0801F86D01F8FBA3033E6DFE0801F86D01F8FE08FD2F6D6D0002
+
+007C000004D9053600050009006A40180102021F1205020305000302021F120502010504007F0205BA022000040132401B06091F07080A0207050403010307001A0B0905190A0B37212639182B2B4EF43C10F63C1739111239003F3C4DFD3CF619F43CE587082E182B047D10C487082E182B047D10C431300115090115090115213504D9FC8D0373FBA3045DFBA3053672FE44FE4F7E022FFD656D6D0002007C000004D90536000500090069401502010203011F1200000502030201031F1204040504B80220B302057F00B80132401B06091F07080A0403020104070007051A0B0900190A0B37212639182B2B4EF43C10F63C11121739003F3C4DFD3CF619F53CE4872E182B087D10C487042E182B087D10C43130373509013501111521357C0373FC8D045DFBA3D97301BC01B17DFDD2FD656D6D00000100170000053E0610003500D74055061417140211141314131415137B12080807151414671222141322210813141521050B2207D22504DA2603D22900000B31451D6F1A6F0E6F0B6F1C0C022E316F30302F081B0D210821221C08070C2FB92930B90037BA023E001C0220400A2235252428C02925910CB80220B70735040501C00004BB023E0036003701EBB321CAFD182B2BF63CF43C10E4E4FD3CF43C10E4E4E610E410E411123911123911123939003F3C10FD3C3F3CEDEDEDED761112392F183CFD3CFE3CFD3C11173987082E2B0E7D10C4870E2E182B087D10C40507C43130005D012135213521352101262B01352115232215141709013635342B013521152322060701211521152115211514163B01152135333236350255FEA3015DFEA30155FEB675680F01F015483C01150106355A130175164B4A49FECD015DFE9B0165FE9B4C7D0FFD96107C4C01A34D9C4D0231C73F3F312E68FE1A01E663273D3F3F4286FDD04D9C4D9B7E4C3E3E4C7E0001002AFE8C04FE045D001C0056400A0802070F190128010401B8015240241A0E0D030206130A095B471A0B170C0D0D24120F0E021C0403030000241201020247011D10DC76CC18072B10173C10D43C2B103C3C003F76ED183F3F3C3C3C10E43130015D1323013303061514163332363713330306151723263534370E01232227E4BA012ABA7315725F5BB0568CBAAA1701BD031C5FC2637765FE8C05D1FDBF69466D84919102BFFCAB725C3A1E0B637C93945500020055FFE104E8064E00160022007F4023310800151D001A06042C078A1D2C1506172C0F0B060623241ADF0C1A2420DF12192324B801E6B3212A42182B2B4EF44DED4E10F64DED1112392F003FED3FFDFDED01111239001112393130437940241E2218190D14180E1A800122102028001E14208000190D17800021111728001F131D80012B2B2B012B2B2B818181012627262B01353320171612151000212226351000
+
+213201320011342623220015141603E53A5FA0CB181C0153C46983FE6BFED3D5FC019E011676FEACC2011A8574B5FED587041FD66AB13EC76BFE98B7FEADFE37F7D00116019FFBC2019F011D97ADFE5FFCA6BD000001003EFE7304AB0610001B00B3401E0C0D0D2512020D0E02030D0E0D0C0EB21201010201130E0D070203040C15B80244B2000F0EB8013DB54A00E9134002B8016B402A200B0C330407BD0505040213080E0D0C020405030783053A06153A1383149C061A1D0E019C0C03191C1DBC017200210133018600182B2B4EF4324DF4324E10F64DF4EDE410E4ED11121739003F3F3C10ED10FD3C1A19ED1A1810FD76FD183C10E411123911123911123987052E2B087D10C487082E182B057D10C431301335090135211323272E01232109012132363F0133032623222726233E0238FDFA03F11F4E031A5CF5FEAB01CFFD96025DB56113034E24C4516085841CFE8C9B038B031846FEE0128F31FD33FC323A7513FE8A0A0807000001004EFE8C061806100025006940360C4F2D074E22184F2D134E22244F2D1F4E22014F2D064E230D4F2D124E23194F2D1E4E231300D212021E1F07062717171A18197B2524B801D2400A00017B0D0C1926899B182B4E10F43C4DFD3CF63CFD3C4E456544E6002F3C3C3C3F4DED3C2B2B2B2B2B2B3130011114163B01152135333236351134262B01352115232206151114163B01152135333236351101D242690FFDC210694141691005CA106941416910FDC20F694205C2F9D27C4E3E3E4E7C05747C4D3F3F4D7CFA8C7C4E3E3E4E7C062E000001001FFFE105A3045D001C006EB900140151400B101320140506101B1C0B03B8010B400E0A0906010A1090170B1B1A240C0DB8014B400A0B4B141A1E1C00240201B801B0B305191D1EBC01EE00210081018700182B2B4EF44DF63CFD3C4E10F64DF4F43CFD3C003FED3F3F3CFD3C39391139390110ED0010F53130212311232207353E013321152111141633323637330E01232226351121020FBA177DA26AB7AC03A6FEEA1F2A38600A3C11A57A5F52FE4D03BA5A3F734BA3FDA69368AF78C3E88A9F02B000010055FE8C03F0063F00300055402E002E2920220719111614951B2C0E032C95032C263217171A11DF16DA22351F9107350A0A09DA2EDF296831ED42182B10F4FDF63C10F4FDF4F6FD4E456544E6002F4DEDED3FEDED011112391112391112393130131E0133323736350327351037363332161514062322353436372623220706151317151007062322263534363332151406FC0E221450202005026A639F4F6C402D6C1C1B1F274623230503586BB0526A42306F1DFEE210105C5CE801666FB601F1B6AB6047354C7020300F1A5051A2FE217485FE1EA9CE5B4834486A1C2F000002004E037702D2063E0021002C007540099A08010B0848
+
+130216B8FFF0400900030A00182C105D11B8018F4011226F0A0A290D1D6F1E5D1B5E2020295E03B80167B70D2C15030B2C5318B80138400A1D2E10601135265A062D10D6EDF4ED10D6F6FD3C003FEDFDED3C10EDF4ED1112392FEDF6E4011112390011123901383130015D005D010E012322263534363F01353423221D01073534363332151114163332371506232203070E011514163332363501D7327442455C8DA44D805E92B176C82234141D413C67221988553726405903F33E3E5C464D6A2F15579A5D252D1C527AB6FEE866440531230166072B413E273A60470000020034037702EB063E000B00170024B2122C06B80167400D0C2C0003154403190F440919182FCCDEED10D6ED003FEDFDED3130013216151406232226353436172206151416333236353426019097C4C49798C4C498596D6D59586D6D063EC89C9BC8C89B9CC839A48786A5A58687A400010055000006C2063E00290084B60F382123030905B8019AB300001418BA019A001D019BB615150808008308B8020BB30F1D8315B8020B40220F0F120C4A27D04940073A058321061A2B124A1FD049401883163A2117192A306D182B4E10F41A3D4DE4ED1A1876FC18ED4E10F61A3D4DEDE41A1876FC18ED113910F6ED10F6ED003F3C10FDE43C3C10E43C3F1A3DED3130253332363F0133032135361235100023220011100515210333171E013B0100111037362120171611140204A1AFA4710C034E1FFDA6A3A3FEE0E4E4FEE00147FDA61F4E030B71A5AFFE38B2CD015E015FCCB3E4932F4914FEE19379015CE201330183FE7CFECEFE3BF293011F14492F0115019A011EDFFFFFDFFEE2CDFEA90003007CFFE006CA047C0030003C004600A6400D1522011B0401233D44062F2A01B80211B400002F2A1AB8020F40261B1B163166104B2A663D4A3D2F441629204429252520072F90033890094B030B2306102A4B3DB80140400C31101035416A288D0050481AB801A2400F1B4C356A0F0C1F0C2F0C030C5248472FCCF45DEDF4EC10F6F6ED12392F3CFDE4123939003FF4ED10ED3F3C10ED10ED111239762F18EDF4ED12392FE41112392FED1112391112393130005D015D251506232226270E01232226353436253735342627262322061D01073534373633321617363332121D012106151412333201070E0115141633323736351333323635342623220606CADDDCA1ED4D36F8847494E8010B8918273E585C5CD78B88DC698E2487CCD6EAFD0202F6B894FD0539E7926343715E3DBFCFE07682657FACBC5E7E8E8E7AA192747DAF4C289D67511C2D4E4F32451E786C69404080FEF1F820220DC3FEFA01E7124A746F476A69447B01172D5583A6E700030055FFE104C3047C0013001B002300BF40512908020914150A0A010C131C1D0B0B001D1C1514130C090208171F021300
+
+1D1C1514041A090C220A0101311200000B1729070B0A0A07071F2911110101000B0124001A040A0B226B0E50251A6B045225242FCCFEED10F6FD39391112391239003F3C103C10ED3F3C103C10ED87052E2B7D10C401113939121739113939001112173987100E3CC43C3C87100EC4C43CC43130184379401C202118190F1005062010222E0118061A2E00210F1F2E001905172E01002B2B012B2B81818181172337263510003332173733071615140023222737012623220215140901163332123534B9649694013EF9C5A169659697FEBFF2D19B3F022E639F9CBB027CFDD36A9E98BB1FAFABF50102014A7777ADBDE4FDFEB07AC1027B9FFEE3ED770190FD87A5011EE8A60002005DFE100365047C001900250065401F09120105061516040B010D6F0E600B781000DD207C1A071615001306050800B8010C400C015D47237C1D1D0E47086313B80132B3260D5D0EB9018F002710F6E410F6ED7612392F18ED76F418ED12393911123939003FFDE62FEDFDED1112173931305D01331514060F0106151416333237170623222635343F013E013513321615140623222635343601CABA39772885857081A820B7F490CD8C2178485C374D4D37384C4C02C24E77869E37B3956C816B31979C6F849A2583C1BE021C4C38374D4D37384C00000200B2FE1001BA047C0003000F00424021025D030101DD0A7C040711DD0740005D015D0A210A0D0235070335077C0D6110EDB9012400182B10F4EDE410E412391A3D10E4E41A1810E6003FFDE63FE431300133130713321615140623222635343601183C5FF77A384C4C38384C4C02CAFB752F066C4C38374D4D37384C0001007C015504D9030800050031BB0003024A00000156B2020302B8024A400E0101001A070419060737212639182B2B4EE410F63C4D10FD3C002FFDED313001112311213504D96DFC100308FE4D01466D000001007CFE8C06C2066D00080083B2080000B8024AB71201010204050606B8024A40141203030407080869120202030806030201000607B801FF4018050400000802090701040605027E030309051A0A0119090AB80179B3212642182B2B4EE41910E612392F184DE4123939123911123939003F3CFD1739870E2E2B057D10C4872E182B877DC4870E2E182B7D10C43130132725090133012301AB2F015D0208028061FD4881FDF901CF52CBFC47073AF81F03BA000100E9FE8C0527063E001500A2402D0205060601121511110015031400120A0B0E110205001211060A170B06010124120000110003010611040E2908BB01C30011000101E9B5131304311403B801AE400911061106010004030BB80135B6131A1703191617BC01D70021003D018500182B2B4EE410F64DE6121739003FF43CFD3C10ED10FDED11123911123987052E2B0E7D10C4011112391112391239
+
+3900111239390F0710053C3C87103CC431300123132135213712213217072E012322060F0121152101D3BBE8FEE901271B750174A46F820B5B3E60792E2D0166FE8BFE8C04A34585024576935A71C3E5E4450002007C00B204D903AB001B00370069400C015D131D5D2F2B5D210F5D18B80197B205C10ABD019700130222002600340197B221C126B8019740192F0ED20F0F2AD22B1A3900D201011CD21D19383937212639182B2B4EF44DED3C10ED4E10F64DED3C10ED002FEDFDED10F6EDFDED7DE410E410E410E43130132335343633321F01163332363D013315140623222F012623220615112335343633321F01163332363D013315140623222F012623220615CA4EA3745BA84BB1483E744DAA785D9B4EA74845734EA3745BA84BB1483E744DAA785D9B4EA7484573024E118AC2672E6B8A4B0C1388C263326B814DFE70128AC2672E6B8A4B0C1487C364326A804D0002006D00000600063E000500080079401D08070806077B12040403080608070636120101020806020401DD000203B801EF400E07069105000A0608070305000504BC02480003012E000201CCB4010019090AB80120B3212639182B2B4EF43C4DF4F6F43C11121739003F3CFD3CFD3C10F63C11123987052E2B087D10C487052E182B087D10C431303335013301152521016D02A53502B9FAC70455FDCDAB0593FA6DABAB04830000020055007C040703E10006000D007340110A03FE000B04FE2107000001050D0C0605B80249400B0809020109400C6F21080DBA02210007010C400A0B0A060240056F210106BA02210000010CB304030F0E2FCCD63CFDF43C3D1AFD181A3C10D43CFDF43C3D1AFD181A3C002F3C3C3CF43C3C3C3D1112392F3C3D1AFD3C10FD3C313009012301350133130123013501330116012F3DFE4D01B33D93012F3DFE4D01B33D022FFE4D01943E0193FE4EFE4D01943E01930002004E007C040003E10006000D007340110A03FE000B04FE21070000010502010908B80249400B05060C0D09400C6F21080DBA02210007010C400A0B0A060240056F210106BA02210000010CB304030F0E2FDCD63CFDF43C3D1AFD181A3C10D43CFDF43C3D1AFD181A3C002F3C3C3CF43C3C3C3D1112392F3C3D1AFD3C10FD3C31300901330115012303013301150123033FFED13E01B2FE4E3E93FED13E01B2FE4E3E022F01B2FE6D3EFE6C01B301B2FE6D3EFE6C000300C6FFD107780108000B0017002300414022035C090F5C151B5C21211515090B2517171A1E5C1896125C0C96065C00192473A9182B4E10F44DFDF6FDF6FD4E456544E6003F3C103C4D10ED10ED10ED3130373436333216151406232226253436333216151406232226253436333216151406232226C65A4142595942415A02BE5A4142595942415A02BE5A4142595942415A6D415A5A4142
+
+5A5A42415A5A41425A5A42415A5A41425A5AFFFF00000000061007840232002400000017010200970000FFFF000000000610078402320024000000160106BA00FFFF0055FFD10617078402320032000000160106E90000020055FFD1089B063E0034004100FC40664E054E075A055A07593758385A416D386D40A525A838A8400C0A0406080A3704411901160B49044608B625090F1C1F1C021C4822227D1D1D1C001B101B021B4816167D1A1D1B010B030916153323224722000C393809030EB714830C020F2D012DE72E28832EB80244403100083F3803091D401A831B0D3A0F830E2E3A2C832D211C1B1B242D241425000C35353C0E3A2D1A433C4A3F060106194243B8017EB321306D182B2B4EF45D4DED4E10F64DF411392F3C3CFD3C1112392F3C3D1A10EDE410EDE410FD181A3C003FED3FE4ED10ED5D3FFDE43FED111239762F183CFD3C111239390110EDEC0010F55D0110EDEC0010F55D3130005D015D21350621200011100021201735211323272E012B01113332363D01331123353427262B011114163B0132363F01330326232227262303351002232200111000333212050EA3FEC8FEBFFE63019B012F0129C6034B2256031373F2D2E8A0594D4D251EB6EAA9D329605A13035021C05D6286831CC8F8DEDEFEE4011CDEDEF886B501CE0168015E01D9AC7EFEE015833AFD8C376211FE6D0F58261EFDF163505D7813FEAE0D080702CA7C01490171FE56FEB2FEB2FE5601710000030055FFE107C2047C001D0029003300CE403A4C15461D024A08140F0E03070C00331E2B0014270709332E2A2B66074607113129021E291C1C02070C901124291616110B2A4B096B272734352EB8010E400B068D0E5035216B195235342FCCFEED10F6F6ED1112392FFDE4003F3C10ED10ED3F3C10ED10ED1239762F18ED0111123912391139390011123939111217393130437940362F301F23171B12130A0B03040B12092E0013142317212E001F1B212E0030032E27010A130C2E022218242E00201A1E2E012F043127012B2B2B2B012B2B2B103C2B818181818181005D01362132121D012106151412333237150623222627062122001110003320052202151412333212353402013332363534262322060451A40101D5E9FD0202F6B6ADB5DBBE96EC56AEFEEAF9FEC1013EF7012DFED199BCBC9999BCBC019DCFE07682657FAC03A0DCFEF0F720220DC2FEF95F5E7D6F6FDE014B01030101014C46FEE2E9EAFEE2011EEAE9011EFE5D2D5583A6E70001003E023E03E102AB0003001CB2010003BB018F00050000018FB20405042FCC10E610E6002FCC3130133521153E03A3023E6D6D000001003E023E080002AB0003001CB2010003BB018F00050000018FB20405042FCC10E610E6002FCC3130133521153E07C2023E6D6D00000200AB03F00394
+
+066D000A00150058400E9500950B020E039411060F04DC06B80162401100400C016F210B00030100610461036009B80132400B0F0C0B610F610E601417162FCCD6FDE4F43C10F6FDE4F43C003F3C1A3DFD3C1A1810FDFD3C103CFD3C3130015D0115060717062322263510271506071706232226351003949C0EAA16944257649C0DA916934356066D4264D756AA674F0104C34264D756AA674F0104000200AB03F00394066D000A00150066401D9D009D0B02650A6515750A7515850A8515060F04DC06400C016F210B00B80162400F060E03941106030100610461036009B80132400B0F0C0B610F610E601417162FDCD6FDE4F43C10F6FDE4F43C003F3CFD3C10FD3C1A3DFD3C1A1810FD3C31305D015D13353637273633321615101735363727363332161510AB9C0DA916934356659C0DA91693435603F04363D756AA6650FEFCC34363D756AA6650FEFC000001009003F001D2066D000A0033B795000104DC039406B80162401040016F21000301006104610360090C0B2FCCDCFDE4F43C003F1A3DED1A18FDEDFD3130015D011506071706232226351001D29C0DA916934356066D4264D756AA674F01040001009B03F001DD066D000A0039400E9E0001650A750A840A03016F2100B80162401004DC0394060301006104610360090C0B2FDCD6FDEDFD3C003FEDEDFD1A3DED31305D015D13353637273633321615109B9C0DA91693435603F04363D756AA6650FEFC000003007C008404D903D90003000F001B0043B20A7C04BC01320003024A00020132B3167C1001B80154B7190D7C0707197C13B80154400902191C1D37212639182B2B4EF44DF4ED3C10ED10E4002FFDF6FDF6ED31300115213525222635343633321615140603222635343633321615140604D9FBA3022F384C4C38374C4C37384C4C38374C4C02656D6D6C4D37384C4C38374DFDB34C38374D4D37384C000002007C000004D806100003000700B8B40504050604B8024A400B1200040700030407040507B8024A400B1201070601000506050406B8024A400B1202060702030607060507B8024A400A12010704010207010503B801D4B300040602B801D4400C20010A040006020917171A00B80220B303050701B80220B50219082639182B4E10F4194DF43C3C3CF4184E456544E611331133003F1A194DFE3C3C3CFE32113387082E182B087D10C487082E182B087D10C487082E182B087D10C487082E182B087D10C43130090704D8FDD1FDD3022D01AAFE56FE5801A80308FCF803080308FCF8024DFDB3FDB0FFFF0010FE2F051805D90232005C00000016008E6100FFFF00000000052707880232003C000000160104AB000001FDD1FFD102F8063E00030026B602010300016002B80220B7050360008A0504CAB9018000182B10C4FDED10F4ED002F3C2F3C05013301
+
+FDD104A87FFB602F066DF99300020037009B050E0565001D002900ED40575903590756125616044903490746124616045B00550B570F5B1A044B00450B470F4B1A04030F10100200121111010A161717090719181808101101011F12020210181709091F12080818181710110109081702581E781CB8021F40100D08115824780D18171011010209082BB801A1B71417351161217814B8021FB70502350861277805BB01A1002A002B011EB3213BAC182B2BF6EDF4E410FDEDF4E410E61133113311331133002FED19F43C1810FDED19F43C11333211331133870E2E182B870E7DC4870E2E182B870E7DC4313007100E3C3C87100EC4C407100E3C3C07100E3C3C3130005D5D015D5D01072737263534372737173E01333217371707161514071707270E0123223732363534262322061514160181FC4BFB6362FD50FB45914B978AFA50FC6264FC4CFC42904F9D9D93D1D19394D0D00195FA4CF8859FA377FC4CF736356BF74CFC77A39F85F84CFA2F306DD19494D0D09494D100010055007C024503E100060046400C03FE0004FE21000001050605B80249400902010240056F210106BA02210000010CB3040308072FCCD63CFDF43C3D1AFD181A3C002F3CF43C3D1112392F3D1AFD10FD3130090123013501330116012F3DFE4D01B33D022FFE4D01943E01930001004E007C023E03E100060046400C03FE0004FE21000001050201B80249400905060240056F210106BA02210000010CB3040308072FDCD63CFDF43C3D1AFD181A3C002F3CF43C3D1112392F3D1AFD10FD313009013301150123017DFED13E01B2FE4E3E022F01B2FE6D3EFE6C0001002F00000546066D002C008D402D19091B0A2709031F198F199F19031E21201922222C212027222213212018222321212026B823090A0C120C2907B80241402B1F01311110030206272619180A090A1E211F1E24120F130113F82E027A2C0F2124040F2C1F2C022C552E2D2FCCF45D3CFD3C10E410F65D3CFD3C11123939003F3C3C3C3F3C3C3CFD3C3FED111239392B2B2B2B015D3130005D1323353335343633321707262322061D0121371114163B011521353332363511211114163B0115213533323635E9BABACCCBBF618F4A884E4E022FBA426A0EFDCA116D44FDD14D7E0FFDB214673F04104D66D5D57986C18C8DB91FFC8C7D4D3E3E4D7D0308FCF87D4D3E3E4D7D0001002F000005460674002F008940261F0F8F0F9F0F031421200F22222C21202722220921200E222321212026B82307192F19290408B80241402F1F2E311D000627260F0E0A0609161F1F1421164B1424080F090109F8312F7A2C1C2124010F2C1F2C9F2C032C5531302FCCF45D3CFD3C10E410F65D3CFDE41112392F111239003F3C3C3C3F3CFD3C3F3CED1112392B2B2B2B015D31301335343633321617371114
+
+163B0115213533323635133534262322061D012115211114163B0115213533323635112335E9D2D13AB2789C436B0CFDD211684101D1996363013EFEC24D7E0FFDB214673FBA045D69D7D71F2038FA9B7D4D3E3E4D7D038E4E8EC47E7FDC4DFCF87D4D3E3E4D7D03084D000100F8FE8C045D0610001500D3404E7A027A057A077A0A750D751075127515086A026A056A076A0A650D651065126515085A025A055A075A0A550D5510551255150840125D055D04155D025D03105D075D080D5D0A5D09211304601403B80228B5010F08600E09BA0228000101FB40180B02400260056007600A60111560126010600D6006600E14B801B4B70011500C600C020CB8021EB20B0601B801B4B3090417162FCCD63CF63C3CFD5D3C3CF63C3D1A10EDEDEDED10EDEDEDED1A18003FE4F63CFD3C10F63CFD3C3D1A10E4E410E4E410E4E410E4E41A1831300171717101231305350503130535050333032515251303251525031CDD50FE6901975050FE69019750DD4D018EFE724D4D018EFE72FE8C01C01D8C2201A901C4238C1C01BDFE431C8C23FE3CFE57228C1D000102100193034602CA000B00284010065C000D17171A096C03190C0D6C21EFB9012300182B2B4EF44DFD4E456544E6002F4DED313001222635343633321615140602AB405B5B40405B5B01935B41405B5B40415B000001009BFE8C01DD0108000A003B400E9E0001650A750A850A03016F2100B80162401104DC0394064F0B01006104610360090C0B2FDCD6FDEDFD3C0010FCEDEDFD1A3DED31305D015D13353637273633321615109B9C0DA916934356FE8C4263D756AA664FFEFB00000200ABFE8C03940108000A00150050400F9E009E0B020F040E030C016F210B00B80162401A04DC039411064F1601006104610360090C0B610F610E601417162FDCD6FDEDFD3CD6FDEDFD3C0010FC3CEDEDFD3C1A3DFD3C103C103C3130015D13353637273633321615101735363727363332161510AB9C0DA916934356659C0DA916934356FE8C4263D756AA664FFEFBC24263D756AA664FFEFB000007002B00000A1406100003000F001B00270033003F004B00A6B440402C2134B8021F401340462C3A213A01020240162C0A2E2C2221220AB8021F401A40102C04282C1C211C04040303000A00004349020213192B4425B80167B231441FB80132B213440DB80167B2194407B8014DB243443DB80167B2494437B8012EB14D4C2FCCF6EDFDEDF6EDFDEDF6EDFDED1112392F1112392F003F3C103C103C1A3D10ED10ED1A18FD3C1A3D10ED10ED1A183F3C3C1A3D10ED1A18FD1A3DED1A183130210133012122023534123332121514022732363534262322061514160522023534123332121514022732363534262322061514160122023534123332121514022732363534262322061514160111
+
+045A83FBAA03E89CC5C59C9DC4C49D59666659586666038B9CC5C59C9CC5C59C58666658586666F9319CC5C59C9CC5C59C586666585866660610F9F00104CDCE0104FEFCCECDFEFC3ED8BBBBD9D8BCBBD83E0104CDCE0104FEFCCECDFEFC3ED8BBBBD9D8BCBBD8022F0103CECE0104FEFCCECEFEFD3ED8BBBBD8D8BBBBD8FFFF0000000006100784023200240000001601050000FFFF004EFFE40494078402320028000000160105A000FFFF0000000006100784023200240000001601030000FFFF004EFFE40494078802320028000000170104FF6A0000FFFF004EFFE404940784023200280000001601023200FFFF004E0000032E07840232002C000000170103FE8A0000FFFF00410000030B07840232002C000000170105FE700000FFFF002F000002AB07880232002C000000170104FE650000FFFF00100000028C07840232002C000000170102FF260000FFFF0055FFD10617078402320032000000160103FC00FFFF0055FFD10617078402320032000000160105000000020000FFD10595067C0021002E0062402F100910091A212E2B400205211730141A092E2B02020205211717141A2105141A1A14210504101E0949090D10301E2F10D610D6DC39762F111217393D2F2F2F2F1112392F1112392F1018D4CC003F3C1AC8DC3CD81ADCCC11123939192F2F313000163332363332171617060706151416170607062322262322062322030235341233001615140607060706073E013701E2D5232DCC4B7B6036355025438E5B2658858334B73F3FA7349D9797E7B0027A023C4138372347029BB304F23E46422641443560747FCC1B7B86C94245010A0107FDEB0128017D140A40984137130B0698DE2900FFFF0055FFD10617078402320032000000170102010C0000FFFF0036FFD106070784023200380000001601033200FFFF0036FFD106070784023200380000001601054B00FFFF0036FFD10607078402320038000000170102012300000001004E0000027D0477001200524015090F180F020C21200722220121200622230D000711BA012A0012020E4018000707060A00144F140214F801240D0F0C1F0C020C5514132FCCFD5D3CFDFD5D003F3C3F194DF418E51112392B2B31300071011114163B01152135333236351134262F013501C2426910FDD11466402363340477FC917C4E3E3E4D7D01B797452D190F0000010174050803A3064E000600374009001800060303800602B8024DB6016F02066F4005BA022600000226B220020710DC1A19FDFD1AED10ED18003F3C1ADC11123938313001072313331323028BD93EF83EF93F05B2AA0146FEBA0000010155050803C2060800150037B90014019AB5470C40048009B8019AB247010FB8024D40090B6F0C01006F0147161076D618ED10D6ED003F3C76ED181ADC1A3C76ED313001
+
+23343633321F011633323733140623222F0126232201943F5D50383E2A502D570C405E533B4D2B3E255B0508768A271B33757888301B290000010174050803A3055500030014B10100B8024DB3030500042FCCDCCC003FCC3130013521150174022F05084D4D00010178050803A7064E000D002FB50800BF045A0BB8024D400E400A0C580B0B00072C08012C000E10DEEDDCED12393D2F1ACCCC1A18003FEDFD3C313001331E0133323637330E01232226017840107D4A4A7E10401A94696892064E4E6D6D4E99ADAA0000010208050803100610000B0019B306894700B8024DB4098903470C1076DEFD18003F76ED3130012226353436333216151406028C364E4D37364E4E05084D37364E4E36374D000201E105080336065D000B00170056B11113B8FFF2B6020D170E021416B8FFF2B5020E100E0206B8012FB44012E8C000410B012F000C024D0003012F0040001501B700C00009012FB10F1810DCED1AFD1AED003FED1AFD1AED313001173817380017381738013236353426232206151416172226353436333216151406028C2C403F2D2D40402D476464474664640546402C2D40402D2C403E6446476464474664000101E9FE4D033E00000011003C4011096F085D0B2C0695106F470160110A0809B801A1B4035A0EFE13B8023EB200D211B9016200122FFDFDE6F5EDF63C003FFD76E518FDEDF4ED313021071615140623222735163332363534273702C94FC45B5B5B4442283433A56590128645461B3D1A29295512BC00000201BE050803DD064E00030007003EB50602A4800501BA024D00060136B70704D22105404602B80136B70300D221014709082FCC76DC3D1AED18DCED761ADC3D1AED18DCED003F3C1AFC3C3130012313331323133301FF418F7948408F8005080146FEBA014600000101D5FE4D032A0000000F00484010080507120F0A5E05120F000D020D5A02B8018F400F0F08581117171A00D30F191011D321BA0164018200182B2B4EF44DFD4E456544E64DE410F6FD1738003FED2F3F113931302106151416333237150623222635343702F198543E142B3E4C5675C78E5C3447093D1A634888800000010174050803A3064E00060037B90000FFE8B5000606018004B8024DB6066F05016F4002BA022600000226B220050710DC1A19FDFD1AED10ED18003F1ADC3C123938313001373303230333028BD93FF93EF83E05A3ABFEBA0146000001004EFFEB04940610002700A94017C720010A1E1D0523221A1E1D1523220F1E1D1423231B1EB8FFF84014021E0B1D0C1B0E1C0D1D0C0C33120D0D1C0DB71CB80224B41515140201BA01490022020C40260405080208400083023A21011A291C1DB41A1B1E1F0C0DB41F250E0B0F0A192829C4212FFC182B2B4EF43C3C3C4DEDF43C103C3C3CF43C4E10F63D1A4DE4ED181A00
+
+3F3F3CFDE43F3C10F4F4872E2B7D10C40011123939111239391817382B2B2B3130005D0133032429013533323635110735371134262B0135211523220615113715071114163B013237363704464E24FEA8FEBAFE7C126840BABA416712023E116841BABA92CD317B233310015DFE8E153E4E7E01D247554701D77C4D3F3F4D7CFE73415541FDE465483047720001003E0000026D066D001A0091400E1021200B22220521200A22230104B8FFF84012020411031214011302031212311213130213BF01A20002022500000019012A001A020E402500000B0A0A12137A1002037A001C101CAF1C031CF801040005241411150F101F100210551B10F45D3C3C3CFD3C3C3CE65DF43C10F43C003F3C3F19F418E510F4F4872E2B7D10C40011123939111239391817382B2B313001113715071114163B0115213533323635110735371134262F013501B2BBBB436B0DFDD1126840BABA275A39066DFD0C425244FDE37D4D3E3E4D7D01D54954490183904E271810FFFF0055FFD1041F078402320036000000170109FF330000FFFF006DFFE10384064E023200560000001700E1FF6D0000FFFF0055FFE3046C07840232003D000000170109FF430000FFFF0065000003F8064E0232005D0000001600E1A300000200ABFFD1014E063E000300070048B900050167B204DD01B8016740150000010917171A0202030306076905040401190809B8013FB3213F41182B2B4EF43C103C4DFD3C3C103C4E10456544E6103C002F4DFDF6ED31301711331103113311ABA3A3A32F02DAFD26039402D9FD270000020055000006260610001A002A009C4066282739273A284412441464146828C61408061329272928471256125A26592867136520672368266A28C611C8270E051E1D0023220A1E1D0F23232232002A320F1D08331E074707000F0200081E1E2B2C254A6F2701151A2C08B4051B20250A3F050105192B2CB80178B3212F6D182B2B4EF45D3C4DFD3C10E44E10F65D4DED1112392F003F3F1239762F183CFD3C10ED10ED2B2B3130005D015D333533323635112335331134262B01352120161716111007060421031121152111142132001110272E012355146640BABA40661402410134EF73FAD370FED3FEE0BD0117FEE9014DF80128B269FFE93E4D7C02014D01B17E4D3F355DC8FE8FFE9EFB846405D1FD844DFDFFC10179013C0136CD785B0000020055FFE104BA06B0001B002700B3404C3510491D6A0103460C01251E2A202A24252645124B204B244526531B6A010A050C0D0D04020F0F100E0E03001A220F050203040C0A070F0C050200051F250D0404311203030E04070322291AB8019140200307290A4C0E0003071C29140B0E0D040304251F6B115029099F256B175229282FCCFEFDED10F6ED111739003FED3F3FF4ED10F6ED111239870E2E
+
+2B7D10C4011112173900111239121739111239871008C40E3C07100E3C3C3130005D71015D012627052737262B0135332017371707001110002322003534003332033212353402232202151412039A54B9FEFF35F1A0C42A2D0105C8C633AE01BBFECAF7EFFEB70142EA8B899FBFBAA497BEBE0404E191E23BD35E4E4EB03D96FEAFFDF0FED8FE8D0142E9ED0145FBE10116E6E40101FEEFDADFFEE9FFFF00000000052707840232003C000000170103FF790000FFFF0010FE2F0518064E0232005C00000017008D00B700000002004E000004A306100022002B0072404926263526481A581A042332481D1D22492B321313220E061E1D012322121E1D0D23221E1E221D002324071E1D0C23230D0C02010008274A191A2D231D121E250706192C2DC4212FAA182B2B4EF43C4DFD3C3C3C4E10F64DED003F3C3F3C2B2B2B2B1112392FFD7611392F76ED3130005D290135333236351134262B013521152322061D01333216171615140021231514163B01033332363534262B01028CFDC2106941416910023E0F6942C5B8A23D75FEA6FED95042690FBA3ADFDFB6DA683E4D7D04007C4D3F3F4D7C3E243668BCF2FEE4367C4E013EDAD9BE9F0000020036FE4E0526062F001F002C00974033472257186718A618B51805192519292B252B29392539294318070C212007222201212006222312220D20242A141D170D171111BC012A0012020E0013024140232A5B1707212429001D0B07060E276AF01A011A502E1320210301240D1F0C010C552E2D2FCCF45D3CFD173C10F65DED003F3C3F7CC418FD7DC4183FED3F19F418E51112391112391112390110F52B2B3130015D005D251514163B01152135333236351134262F013525113E0133320015100021222603111E0133321235340223220601B240660DFDD1116D44295D3C017C70D363C90105FEA8FEEB4183433AB2559ECCCEA34A9D07B27C4D3E3E4D7C05228F4E2718108CFD7D6868FEC7F1FEEAFEA5130363FD6E4858010ED1D00105410001007C01F804D902650003001C400E0002001A050219040537212639182B2B4EE410E6002F4DCD31300115213504D9FBA302656D6D0001007C000004D9045D000B007D4015020601030A050601040908070004090B0700030A06B8021D40090AD220070937014000B8024CB704D2032003010A09B8021D400B01D20D17171A0A00370407B8021D400C03580604190C0D37212639182B2B4EF43C4DF4E610FD3C4E456544E64DFDE6003F3C1A1910FD18E51A10FD3C1A19FD18E60F0F0F0F313025070901270901370901170104D952FE24FE1C4B01DFFE214C01E301E24CFE1C464601E1FE1F4F01E001E04EFE1C01E44CFE1E000100A70284029F063E001100374020010A10542D0A4E2203542D094E23110A0A09C50211002D010203130353111012
+
+10DC3CFDCC003FD4FD3910FD3C382B2B0110C43130133525111416333217152135363332363511A7013E1A2C363EFE083C2D3120058E3C74FCD02C1A083C3D041D2C029F00010059028402BE063E00160032B601145300C50E0BB8019740120C68095E0E030644113515010C350B35011710D6F4E410DCF4ED003FEDF4ED10FDED39313013353637361235342623220737363332161514060121155911A96E925442759A058496809A9CFEF101C202843D14C5810103443C4B846F6A7C6756D6FEE18C0000010051026D02C6063E00240057B11301B801974009460049000D191C681BB80197401B1E2C19C50D0AD20B58082C0D031300161B055A105D215A160B581CB80197B11B2510D6EDE4DCEDF4ED11123939003FEDF4ED10FDEDFDE4111239762F76ED39313013373332363534262322073536333216151406071E01151406232227371633323635342623E82E2058865E41647A7E81748D5B5C7373D08AB06B64587D4F619292043E746D473D565A57486C593E6D2E267F597CB97163966C576868000003004EFFD106C2063E00110015002C00B0401810542D0A4E2203542D094E23172A161312121F1215151421B80197403A22681F5E24C52A531615125D160A090AC50214131302002D010205120115031013141C222ADC1735223521212D2E1C5A27352B1A2E0203531001B8010CB5111110192D2EB801F0B3218942182B2B4EF43C4D10ED10FD3C4E10F64DF4ED1112392FE4F4ED111239391112391239003FD4FD103C103C10FD3C3FF43C10EDFDEDF4ED87052E2B7D10C400111239182B2B31301335251114163332171521353633323635110301330125353637361235342623220737363332161514060121154E013E1A2C363EFE083C2D31205304A87FFB61032110AA6E925443749B0683977F9A9BFEF101C1058E3C74FCD02C1A083C3D041D2C029FFA24066DF9932F3D14C5810104433C4B846F6A7C6756D6FEE18C00040061FFD106AF063E001100150020002300D9406F16171D20221B231C1A1F21231C202210542D0A4E2203542D094E231312121F12151514192223236712181819122015182317220919021AC5201C231F1D17E32012155D20020A09C50214131302002D010203120115031013231814191F2018EE222220531A1F611C1A250203531001B8010CB5111110192425B80120B3218942182B2B4EF43C4D10ED10FD3C4E10F64DF43CFD3C10ED111239391239391112391239003FD4FD103C103C10FD3C3FF43C10F43CFD3C10FD1139113911123911123987052E2B877DC4872E182B7D10C4182B2B0F0F0F313013352511141633321715213536333236351103013309012135013311331523112319010161013E1A2C363EFE083C2D31205304A87FFB610438FE36021935A3A384FE96058E3C74FCD02C1A083C
+
+3D041D2C029FFA24066DF99301376D0245FDC274FEF8017C0188FE7800040013FFD106FC063E0024002800330036010C402E292A3033352E362F2D3234362F33351C1B1300011C0B2625251F122828272C35363667122B2B2C2B362A352D1E01B80197B500000D192C2DB801DE400A322F361F302AE3322825B8012EB7320A1C681B1E2C1BBA0197001901DE40330D272626082C0D0AD20B580D051300102528050B26362B272C32332BEE353533532D32612F1A38215A165D10005D01E3055A10B80223B50B581B193738B801F8B321CAFD182B2B4EF47D4DE418FDFDF4E410F4ED4E10F64DF43CFD3C10ED1112393912393911123939111239003FF4ED10ED3C103C10FDEDED10E43FF63C10F43CFD3C10FD3C1112392FED11123911123987052E2B877DC4872E182B7D10C4011239001112390110C90F0F0F313013373332363534262322073536333216151406071E01151406232227371633323635342623130133090121350133113315231123190101AA2E2057865D41647A7D82748D5B5C7372CF8BAF6B64587D4E6292931F04A87FFB610457FE36021935A3A384FE96043E746D473D565A57486C593E6D2E267F597CB97163966C576868FB93066DF99301376D0245FDC274FEF8017C0188FE780001005D000004CA0610003000B44012104F2D0B4E222A853030BE2B702A054F2D0AB8010F402223154F2D1A4E2329852424BE287029242367300000221401D21104040A4922D21A1CB8014DB71B1B1A020B0A0A03B80221B2052A29B8012E401D401DD21B5D211C1A322201040591101312E511151096313237212A39182B2BF63C3CF43C10FD3C3C3C4E10F61A3D4DE4FD1A18F63C10E4003F3C3F3C10EE10FD7611392F183CFD3C11392F3CFD3C0110EDEC0010F52B2B0110EDEC0010F52B313001112115211514163B011521353332363D012135211134262B0135211323272E012B01113332363D013311233534272623022E0127FED94B8610FDAB126840FEE901173F691203F11F4E03146EF1D8EE9C574E4E241DB202F0FEF14E8B82483E3E4E7C8B4E0324804C3FFEE0158538FD6D376211FE6D0F58261DFFFF0055FFD105F007840232002A0000001601070000FFFF005DFE2F0493064E0232004A0000001600DBE100FFFF004E0000028C07C20232002C000000160108000000010055FE4D041F063E003700DD40635B10591856236604690B690C6A1807252035204608451D5604580B5B246E0A081E1F0C0B04061901E700D036303840602B802B022B8035326F2601263616BD14193814D012030638255136090B0C090F1F1E221C33283635022D252522014016832114B80244B715510993221A392EB8019540091C930F514002832100B80244B63F010101193839B8016EB32130C8182B2B4EF45D4DF51A3DED1A18F4FDE64E
+
+10F64DEDF4E41A3DFD1A181112392FDC1739DCCD1112393911123939003FE4ED3FE4ED10ED10D45DE51ADC5D1AED10F4FD111217393130005D015D370333171E0133323635342F012E013534243332171323270221220615141F011E011514060F0116151406232227351633323635342737226B164E031EBE9284BDF39AE08B0123EEBAC121500550FEE280A8D0DECF83ECDD39C45B5B5B4442283433A54CDF100155109CA9B37E9FA66A9AAB79B4DC42FEDD1001179A76958F988FA97EB0DA1F65128645461B3D1A292955128C0001006DFE4D0384047C003B00B9401F760D860D025621680C680D970D04342F392A2921220D0C04081F081F051C15BA01A30014020FB41C29120701BB011200470000020F401505293A290B3A3931372C29290C0D080F2221261F16BA02110015020F4016460886102601D2260126503D1F86DB0FFF0F020F4C02B80211B6004C4701523D3C2FCCFE76E418EDF45DED10F65D71ED76F418FD1112393911123939392FDCCDCC3939003FC0EDF476ED183FEDF4ED111239391112173910D4C4DCCD3130005D015D3703331712333236353427262F01243534363332171523272E01272623220615141F011617161514060F011615140623222735163332363534273722851850032BEF67942626925FFEF0C8AB91AD55030E1527455A546BD369993B3BBBAD41C45B5B5B4542283434A554C52C011A14FEED815A4226254F3495B7889E3FE813572C1E35614C6F753A5548496687A71475128645461B3D1A292955129D00FFFF0055FFD1053E0784023200260000001601030000FFFF0055FFE10432064E0232004603000016008D7000FFFF0055FFD1053E0784023200260000001601090000FFFF0055FFE10432064E023200460300001600E11B0000020065FFDD054E066D0021002E00C4403E49057907F9050349050108042B28252A292E3A28322A3B2E4B044B2E5C246A24BB04FC04F40CF51C0F040C150C4C04030F141F142F140320221BDE1F2020B801064017210C00090322222C262910090109070D0D1A6617171010BC023A0014012A0015020E402316002C5B030B210B197A1B22100D212416401B011BF830296ABF06CF06FF060306522F10FE5DED10F45D3CFD3C3C3C10E4003F3FED3F19F418F5FE2F3C1810FD3C103F5DED1139391112393910F5EDFC01F55D313000715D01715D250E0123220035100021321617352335332E012F013525113315231114163B01150519012E0123220215141233323603D970D263CAFEFB015801133F8446F8F8032A593C017DBABA4A6808FE8B3AB1559ECCCDA44A9DB168680139F10116015B11118A3E432F2518108CFEB53EFC21503A3C62012902924858FEF2D1D0FEFB41000100EA06BA036607840003002DBC0002010C00800000024EB44003BF0201B8010C
+
+B421004905042FDC76D61A3DED18DCFD1A18003F181AED3130012325210366C2FE46013E06BACA000001022806BA04A407840003002BBC0002010C00800000024EB44001BF0203B8010CB3210005042FCCD61A3DED18DCFD1A18003F181AED3130012521050228013E013EFE4606BACACA00000201CA06B704460788000B0017001FB41206630C00B8024EB715630F09630319182FCCD6EDD6ED003F3CFD3C313001222635343633321615140621222635343633321615140602332C3D3D2C2B3D3D017F2B3D3D2B2C3D3D06B73D2B2C3D3D2C2B3D3D2B2C3D3D2C2B3D00000101D106BA049B07840006002FB600200003800602B8024E400C0000050206910501910247071076D4E5DCE51112393D2F18003F3C1A7CDC39383130010723253305230336B2B301463E0146C206F83ECACA00000101E106BA04BB078400150042B90014024FB504400C498009BB024F0001000F024E400F00D2010BD20C1A1701191617F22189B9018400182B2B4EE410F64DED10ED003F3CED1A76DC181A3CED313001233E0133321F0116333237330E0123222F01262322022F4E0D76542E5854442B4E1E4E0C72543B4C4A3B355506BA5B6F1D1B164E5C6E1D1B160001020406BA049F0784000A001FB305010308B8024EB705440601440A0C0B2FCCDCEDDCED003F18DDDC3C313001331633323733062322270204A258535358A376D8D87507843E3ECACA000100E906BA01F107C2000B0019B306894700B8024EB4098903470C1076DEFD18003F76ED3130012226353436333216151406016D384C4C38384C4C06BA4C38384C4C38384C000101D506BA049F078400060033B90000FFE0B50001054A8004B8024E400C0000050201910206910547071076DCE5DCE51112393D2F18003F1A76DC3C3938313001373305232533033AA3C2FEBA3EFEBAB207463ECACA0000010000000100004AB993855F0F3CF50009080000000000A1FE500000000000A3E838CDFDD1FE100A1407C2000000090001000000000000000100000800FE0000AB0A3EFDD1FDD20A1400010000000000000000000000000000010A040000930000000002AB000002AB0000026D00B2040000BA0555003E055500E10710002F06CA004E026D00AB039300CA039300CA0410004E0555007C026D009B0308004E026D009B04AB003E0555005D0555011F055500A30555009305550055055500A30555008C055500A3055500B20555007C026D009B026D009B0555007C0555007C0555007C03A3003E06AB005506100000051F004E05AB0055067C005504D9004E04B2004E062F00550665004E02D9004E03B2000005E1004E04AB004E07CA004E066D004E066D005504D9004E066D0055058C004E0493005505A30027063E003606100000083E0000053600000527000004CA00550346010804AB003E
+
+0346004E0555007C0555003E0517016504BA007C055D001004550052058C0065049300550336002F04D1005D0593004E02BA004E02B200080500004602BA003E0800004E0593004E05170055058400360555006503F0004E03E1006D0346001F0584002F04E90000069B00000493001005170010045D0065039300D101F800AB039300E10555007C061000000610000005AB005504D9004E066D004E066D0055063E003604BA007C04BA007C04BA007C04BA007C04BA007C04BA007C045500550493005504930055049300550493005502BA004E02BA001702BA002F02BA00080593004E05170055051700550517005505170055051700550584002F0584002F0584002F0584002F055500F8029B004E055500AB0555009B055500CA0555010005550070052F002F07170055071700550727004E051701650517014E0555007C08170000066D00550555007C0555007C0555007C0555007C05550017055D002A053600550517003E0665004E0610001F0446005502E9004E031F0034071700550727007C0517005503A3005D026D00B20555007C0727007C055500E90555007C066D006D045500550455004E083E00C6055500000610000006100000066D005508E90055081F0055041F003E083E003E043E00AB043E00AB026D0090026D009B0555007C0555007C051700100527000000CAFDD105460037029300550293004E0584002F0593002F055500F805550210026D009B043E00AB0A3E002B0610000004D9004E0610000004D9004E04D9004E02D9004E02D9000802D9002F02D90010066D0055066D005506520069066D0055063E0036063E0036063E003602BA004E0517017405170155051701740517017805170208051701E1051701E9051701BE051701D50517017404AB004E02BA003E0493005503E1006D04CA0055045D006501F800AB067C005505100055052700000517001004D9004E058C00360555007C0555007C033600A703360059033600510710004E07100061071000130555005D062F005504D1005D02D9004E0493005503E1006D05AB00550455005505AB005504550055058C00650517014D0517014D0517014D051701260517011E0517013E051702070517012600000036003600360036007800AA0152024502F903AA03D4040D044F04D5050C05390554057D05A10619066406C8076007BF084408E7091D09C20A6D0AAE0B020B420B6D0BAB0C1F0CDB0D9E0E420EB30F2F0FD8105B10EA117811C3122612EA135613FB148D1507157A162A16E1177D17ED1874190819E01ADF1B841BFF1C251C481C6D1CA71CC61CE61DAC1E341E911F251F8F200720CB215821BC221A22C6230C23F7248324DE257A2606267D271D277A28002891296F2A7B2B292B832C0B2C312CAF2CF52D002DC52E6B2E772E822E8D2E982EA32EAE
+
+2EB92EC42ECF2EDA2F6D2F782F832F8E2F992FA52FB12FBD2FC92FD42FE02FEB2FF63001300C30183023302E303930AD3101317C320432D332FA333433D434E335AB368336A336DE374A382138C73938398139D03A1D3AD63B303BAC3C383CA23D053D763DF13E293EB13F694005407140B040D9413341AB422B427F42DA4335438B438B439743A243AD448F45484563457E45D046294659468C46DB4750475B47664788483F487648AD493149B74A4E4A794AAD4AFB4BC14BCC4BD74BE24BEE4BF94C054C114C1D4C294C344C3F4CBA4CC64CD14CDC4CE84D314D5F4D9E4DB54DE74E0A4E5B4E974ECB4F0A4F384FC8503B50475053505F506A50A2513351D051DC51E8525F52F0530B536A53A453E4544554E55590566B57095714571F572A57E9589B58A658B158BC58C75971599659BB59F15A1B5A605A855AA85AD4000000010000010A004C0007004F00040002001000100037000007E8017F00060001BF001F024D001F024E002F024E007F024E401004A0E20160066007022F55010022017F410B0243008F0243009F024300AF024300BF024300CF024340250670069006A006B006C006D006E006F0060800061006200630064006500660067006800609B80244400B08551F0908331F0302331FB801DEB2C50D30410A0241007F024100D0024100030010024100200241B202084041140201018B0022000D01510022000D014C0022000D01340022000D01090022000D01050022000D0102B7220DCB220DB8220D410A01B80056000D019C0056000D01990056000D0110B7560DDE560D21560DBE01B10023000D01A90023000D012B4017230DE1230DCD230DBB230DA0230D87230D82230D48230DBE01AC001E000D015D001E000D0139B71E0DB31E0D7D1E0D410A01980020000D01920020000D013E0020000D0103400E200DCE200D70200D2D200D1D200DB80106B40F470F0009B80106B5470D1002291FB801A8B24A351FB801A7B24A431F411501A3004A0401001F01A000250401001F019F00920401001F019E005B0101001F019B005B0101001F0197B25B351F41150140009202AB001F013F005B0101001F013D005B019A001F013B005B0801001F013A005B0401001F0137B25B5A1FB80131B233431FB80130B233791FBC012F00380401001F0112B24A271F410D010E00250125001F010C00920401001F010B005B0101001F0107B2334A1FBA010400380801B61FE24A1B1FDF88B80401B21FDC5BB80101400B1FD95B4A1FD533811FD333B80401B21FD233B80801B21FD133B80801B21FB592B80401400B1FB259541FB033451FAF33B80801400B1FA34A431F9F33411F9E38B80401B61F944A5A1F9392B80101B21F9192B80156400B1F905B451F8692BB1F8333B80801B61F7C4A211F7B25B80401B21F7992B80125B21F6F38B8
+
+0401B21F6A25B80401B21F695BB80401B21F6738B80401B21F6638B80201B21F6325B80801B21F605BB80401B21F5E33B80801400F1F5A5B461F5933211F535B461F445BB80101B21F3633B80801B21F3238B80401B21F3133B80401B21F2C38B8040140121F1F33411F55110911090600000100060201B8022BB40207460090B8016540390790C207909907908F07908007904507904007903407902E07902B079028079027071408120810080E080C080A080808060804080208000814B8FFE04018000001001406100000010006040000010004100000010010B8022BB300000100B8022B40130200000100020000000100000201080200480018B9000101FF858D16763F183F123E113946443E113946443E113946443E113946443E113946443E11394660443E11394660442B2B2B2B2B2B2B2B2B2B2B182B2B2B2B2B2B2B2B2B2B2B2B16763F183F123E11394644014B5079B9001F0148B6071FE4071F49072B2B2B4B5379B900900148B60790E4079049072B2B2B181DB0964B5358B0AA1D59B0324B5358B0FF1D594BB05E53205C58B9008802014544B90201020145445958B902370088455258B9008802374459594BB09353205C58B9020302014544B90202020145445958B9037A0203455258B90203037A4459594BB09353205C58B9002402034544B9006B020345445958B903750024455258B9002403754459594BB09353205C58B9002502024544B9004A020245445958B903B50025455258B9002503B54459594BB8040153205C58B192244544B1242445445958B917400092455258B9009217404459594BB01353205C58B129294544B15B2945445958B12729455258B129274459594BB0C153205C58B129294544B1382945445958B901A40029455258B9002901A44459594BB0DC53205C58B129294544B1332945445958B901DF0029455258B9002901DF4459592B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B65422B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2B2BB32FA8306D456523456023456560234560B08B766818B080622020B130A84565234520B003266062636820B003266165B0A8236544B030234420B12F6D4565234520B003266062636820B003266165B06D236544B02F2344B1006D455458B16D406544B22F402F45236144594569534274732B2B2B2B757473737373747300
+
+00>]def
+
+/CharStrings 266 dict dup begin
+
+/.notdef 0 def/.null 1 def/nonmarkingreturn 2 def/space 3 def/exclam 4 def/quotedbl 5 def/numbersign 6 def
+
+/dollar 7 def/percent 8 def/ampersand 9 def/quotesingle 10 def/parenleft 11 def/parenright 12 def/asterisk 13 def/plus 14 def
+
+/comma 15 def/hyphen 16 def/period 17 def/slash 18 def/zero 19 def/one 20 def/two 21 def/three 22 def
+
+/four 23 def/five 24 def/six 25 def/seven 26 def/eight 27 def/nine 28 def/colon 29 def/semicolon 30 def
+
+/less 31 def/equal 32 def/greater 33 def/question 34 def/at 35 def/A 36 def/B 37 def/C 38 def
+
+/D 39 def/E 40 def/F 41 def/G 42 def/H 43 def/I 44 def/J 45 def/K 46 def
+
+/L 47 def/M 48 def/N 49 def/O 50 def/P 51 def/Q 52 def/R 53 def/S 54 def
+
+/T 55 def/U 56 def/V 57 def/W 58 def/X 59 def/Y 60 def/Z 61 def/bracketleft 62 def
+
+/backslash 63 def/bracketright 64 def/asciicircum 65 def/underscore 66 def/grave 67 def/a 68 def/b 69 def/c 70 def
+
+/d 71 def/e 72 def/f 73 def/g 74 def/h 75 def/i 76 def/j 77 def/k 78 def
+
+/l 79 def/m 80 def/n 81 def/o 82 def/p 83 def/q 84 def/r 85 def/s 86 def
+
+/t 87 def/u 88 def/v 89 def/w 90 def/x 91 def/y 92 def/z 93 def/braceleft 94 def
+
+/bar 95 def/braceright 96 def/asciitilde 97 def/Adieresis 98 def/Aring 99 def/Ccedilla 100 def/Eacute 101 def/Ntilde 102 def
+
+/Odieresis 103 def/Udieresis 104 def/aacute 105 def/agrave 106 def/acircumflex 107 def/adieresis 108 def/atilde 109 def/aring 110 def
+
+/ccedilla 111 def/eacute 112 def/egrave 113 def/ecircumflex 114 def/edieresis 115 def/iacute 116 def/igrave 117 def/icircumflex 118 def
+
+/idieresis 119 def/ntilde 120 def/oacute 121 def/ograve 122 def/ocircumflex 123 def/odieresis 124 def/otilde 125 def/uacute 126 def
+
+/ugrave 127 def/ucircumflex 128 def/udieresis 129 def/dagger 130 def/degree 131 def/cent 132 def/sterling 133 def/section 134 def
+
+/bullet 135 def/paragraph 136 def/germandbls 137 def/registered 138 def/copyright 139 def/trademark 140 def/acute 141 def/dieresis 142 def
+
+/notequal 143 def/AE 144 def/Oslash 145 def/infinity 146 def/plusminus 147 def/lessequal 148 def/greaterequal 149 def/yen 150 def
+
+/mu 151 def/partialdiff 152 def/summation 153 def/product 154 def/pi 155 def/integral 156 def/ordfeminine 157 def/ordmasculine 158 def
+
+/Omega 159 def/ae 160 def/oslash 161 def/questiondown 162 def/exclamdown 163 def/logicalnot 164 def/radical 165 def/florin 166 def
+
+/approxequal 167 def/Delta 168 def/guillemotleft 169 def/guillemotright 170 def/ellipsis 171 def/nobreakspace 172 def/Agrave 173 def/Atilde 174 def
+
+/Otilde 175 def/OE 176 def/oe 177 def/endash 178 def/emdash 179 def/quotedblleft 180 def/quotedblright 181 def/quoteleft 182 def
+
+/quoteright 183 def/divide 184 def/lozenge 185 def/ydieresis 186 def/Ydieresis 187 def/fraction 188 def/currency 189 def/guilsinglleft 190 def
+
+/guilsinglright 191 def/fi 192 def/fl 193 def/daggerdbl 194 def/periodcentered 195 def/quotesinglbase 196 def/quotedblbase 197 def/perthousand 198 def
+
+/Acircumflex 199 def/Ecircumflex 200 def/Aacute 201 def/Edieresis 202 def/Egrave 203 def/Iacute 204 def/Icircumflex 205 def/Idieresis 206 def
+
+/Igrave 207 def/Oacute 208 def/Ocircumflex 209 def/apple 210 def/Ograve 211 def/Uacute 212 def/Ucircumflex 213 def/Ugrave 214 def
+
+/dotlessi 215 def/circumflex 216 def/tilde 217 def/macron 218 def/breve 219 def/dotaccent 220 def/ring 221 def/cedilla 222 def
+
+/hungarumlaut 223 def/ogonek 224 def/caron 225 def/Lslash 226 def/lslash 227 def/Scaron 228 def/scaron 229 def/Zcaron 230 def
+
+/zcaron 231 def/brokenbar 232 def/Eth 233 def/eth 234 def/Yacute 235 def/yacute 236 def/Thorn 237 def/thorn 238 def
+
+/minus 239 def/multiply 240 def/onesuperior 241 def/twosuperior 242 def/threesuperior 243 def/onehalf 244 def/onequarter 245 def/threequarters 246 def
+
+/franc 247 def/Gbreve 248 def/gbreve 249 def/Idot 250 def/Scedilla 251 def/scedilla 252 def/Cacute 253 def/cacute 254 def
+
+/Ccaron 255 def/ccaron 256 def/dmacron 257 def/Grave 258 def/Acute 259 def/Diaeresis 260 def/Circumflex 261 def/Tilde 262 def
+
+/Breve 263 def/Dotaccent 264 def/Caron 265 def end readonly def
+ %endsfnt
+
+%beginsfntBC
+truedictknown type42known not and ( %endsfntBC)exch fcheckload
+/TrueState 271 string def
+TrueDict begin sfnts save 72 0 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt cvi 0 72 matrix defaultmatrix dtransform dup mul exch dup mul add sqrt cvi 3 -1 roll restore TrueState initer end
+/BuildChar{exch begin Encoding 1 index get CharStrings dup 2 index known{exch}{exch pop /.notdef}ifelse get dup xcheck{currentdict systemdict begin begin exec end end}{exch pop TrueDict begin /bander load cvlit exch TrueState render end}ifelse end} bind def
+
+ %endsfntBC
+
+%beginsfntdef
+truedictknown type42known or( %endsfntdef)exch fcheckload
+currentdict dup/FontName get exch definefont pop
+ %endsfntdef
+
+%beginType1
+truedictknown type42known or not( %endType1)exch fcheckload
+/FontMatrix [1 2048 div 0 0 1 2048 div 0 0] def
+
+/FontBBox{-559 -496 2580 1986}def
+/FontType 1 def
+/UniqueID 16#00475945 def
+currentdict
+currentfile eexec
+
+26A8652248745C44A9EC085E968ECE9680E34A6BAC29C353295355E2953CB3AA6676B0771CB60B11FA6E5FC6914ED20F7BF93ED995E9BD67F7D94DEBB5E3D9B18D63552DBDDEAF17916DF1A077A725D93B8E13862B9ED11D705BC74F9AB2AE196F1F58888FCC5A84BEE8105E5986FAD24A3A824C3B2D72B6F7A045A80856CFC086AE8DDA24E7A94D62C059AD86B21A1F368F572886370992270C07EAAA1484F7695ABA81F0260CD5248BE522280D4449F4C6A115BDD0917894F2DC8DAE846D848D45986A4C4A100C524F7B9584A61E6D9CA865E771E1FB98775BD030B3B18C8879C73CA6E4A2AF64F52C61E4FC1B4D86B77E093E2E412DED2745251E8970C5D19F8672D3201DA97D37420BC056DAB4DEF2AA42C74C8A7F12E10A6222D87F159734E806ADDFEA3F35AE64F87F9CF5F65009AD2423BC4CAD6451EB51BAB67E6E34FDD155B40C3080CF362E803B3404EA06986B55AFB59A25DB29366CC367B2E544587794FFBF6BE87A97CB8BC1BF5C49AA86303757FFBC8B7B2CE0F283E21B8D7A7696674812D258B85FBBC1A27E046DB79621232394F31DF6CC2DB113EE57358E39B66C3E7CA2E09911FA3EA7636985A617FBEC8A5BC1DB9CBC77E0273AB6E7737D806E53015AE61A7957364C34CDA722B4B9C1807B3C242045AF5E4044D8D1AA70185576D4B19996A630B86525015155C0C78F230E19E2E9525DAAD9F860C9C78683AA2993E5E3BA64CFE144A2D624C36B3E7D4D321D406B31FBC6E0403D25FDA08066ED002C8ABD4446AC3AD28C735F0A8EE407F36D49521A07747B142A3609EB740D62DEE3BEB48A544BABAFA33A7E81F625253494A85070FC7196C4EC679A6C3A41EA7D289E00540203F96D9DC2950E6586DD56AFB6FB14BFD90ECD55B9379622A9AB098A6D28BB49A24BF104E9D00272181B29D49927E8523720412E6BE7664365202002D0DA0379611D91F9B1D2C1FD1209C9895F6CAEC259EF7BFD0A8A0EDA450C4B44D5A0D49ABDAF582B98580D69964225D1BDC344BD60AAD93B0A8B718D12965E458CE348DA2F864F1E5F2C2209CB2AF7DAC3FED8251A7B1BC59FFDB667B0592F8021168933793269AF0FADAF1E1CF57849B7E010BE5C69BBE0873B32D20A2CC18D6DC2BDE1AA12BF8214C7AAC6259C244D0F8CC28BBEDDF9966A2A017861DE4B19DB5E1337D14F012798B3F663E738DA08F3AE09FE8FCBD95A000766CF74F5C54CDA703DCAB4B8E7FFB341768ED9D5179E23F3D4BB12231DF05156794CD6A7D51914F7A30112BB05837C6A0661EC18AF706DD7E8320082BCC8E499A630A7E86C9B33DF78E17E3738E6870B9D0226085E275679251CC153B752E5C2672B20BA13973DEBE42A8E1D9A975CA6874A43CA1C2DEF057A8A1950A7908644D173E8A6CA254E7B4C035D0F48A3AC73380675EF73A1B5063EB9A9A970D90AF0
+A144D7912510B3E3DF301515A8D044BF48140F4C9CF038D4B40182E5ABE0D8545B363827BFC2033B74E3A1A1252B340C874B291BD75C1EAF9F5F899AACB9113521AE46781EABDB77E169ED5E0E532748B00528E01CA75D32DBCF68355AF66CBC29EBDF5F1F3444395E896E6078256DC795E44F5B95FFBF0DF422CF47C87D35C56FB112427DA957BC1FB16BA80FE3646BCD6806260A51168C1E157539DB46FE5703A67AC2339491EF257453823CC61643B1E590C443C7773BCF5BD6C26C67E2F351F7E1F3B8CD4D5FD503968AD138B2E7C5D3A6AA34CA380799931EC5B09292A914E960AAD3B2DC24AC56113DE6B6580C3F8C58A5A27FF2EBAAE493409A2ACF53F3296BF3E77FEBD1A7629676801426FD7F5958D686484EF28077131EAB154A2E4B91BEB5D2F499D5AE3CC331748B8421D45DE5DF0F9C21C4E3560B76DD9ACF84717A70CFD5F1B784DEF0266DB80F96D2212483BBCAEC597B73CC97150BF1523391BAD890DBCAB62E11A1B35A44077899BE1911362B29F71E55DC583605C18376C5458B93A651EE7FA260D23DA8BE6F0707A15C03CB3339677B9D272AF1B7D6BB2529C875E4EAE9451A366AEB935AFEB56122D357ADE95315584B2B4AA3497DA04FD394F2DD3DC8A8D54BB11A44102CB6126C52F9950B1496A0216C4533EDFF245CD328CB3C8B75299B867F4050DFE1725194CA4AAE4FE180E21D0582692884A4351F5665A5B355A4C2807E2BAEA882F84E509C6E8312DD8C922A89601ACB2EFCFF9F6C948B58F0FE9CFAC8C8F905252C80DD015467D0C5AB08AA91397FC6B5E4D865B8B3A7B20A785813494E67A3BB49337EB40DEB9DCF1C0C3C07FA3234D2793DDEB052ABCF66DFC167651BAD430142C6784217AD8EE6C903833D1C85C93EE61EF2C90E1C14DB00CEBE9EB2344D309AE84E189ACA98AC5FBDED1E46D682ED34F9D18B0731ADB553A8CED368C1A05DD76BAE48FAABC01263BB65855B1B0719AA140B3DCB26B7238E4B0202F7329DD717DCEA951E34A096CD923525C6C9020354986F272A08FA8C4BDE7B6A79C1675DD66B8FEEA90F7CF42B9F6C5F73F907A43F758713D53CEAB531A049D1F811A77B3617F1B45AD2AFD245B6ADC7C9E83E6099B0747EA842BEB172F53E7F59E169B9AEB3EF6A50BB58BB70071111CC49ED2D36F4DD497660EF8934336C2D2ED00D995793F8304FAD059821436A48D6755B798FE110BAF78704A86213F30D9BBFC42E9EDA82EFAE6953047079ECFD4B63DC8174F903F0461097361CE9495150B7721AC3A378131EF634F618C6DFA349B3F50FC0A3E46ABA8D0BA35C4AFF512BFAAA1F91242CC08FF921A16A1AC22663C8864A6D05AB7C333BE8C5BAB41FABB138213FC4A078452FBCCBC59C15595AEF501C2A574611A860D97746B2DCA67C4B83C4A78F7B977E242F10E6F1C16F398B97AB9925
+FC9DB840846A132655113DF4EB7D6505E475D0A8212B45A72ABF8187B06EB493878EB1D71A39A747183449C9B76EFC4838F6C11D8697D5E9A65C45AFDABF20E1E6C93C0EF598E807F53E948D94C1BE2D71B2E1CB2C57FDE2B2D7A55FE8E8CBFFAA292E5A4B47CE05B37CB8D8EF32093DB4F380FD6C708E5112A569E65A98D88B7FEFF4F443F7C1B6E10B3D8A25DDC0A7AAC74DB1996F0EE416B2A03369D13646D74576E11A752B5851BB28E411D2F15C2AAF8A4BBFB9F003308F98B2141936DF416433AA30CEED74C50787F175BC5F84749602E5E7F801085394DA9778D944549F334E7DDA11D7EA4DC53E538A2C75731F10353D5706694FEEED9F28CBDEE102281C4196E48FF931575CD78750AC2390D53D6AD8312405650B31A3439B6C6E476E085D4D3FD82F41BBB71171EA982F62F3EAA3DEBF89931383630F44C2DDAF349036FA68F718B459F3F6A376FB99EC25AC38796C47CD29D7BD0E131BEE0B9B3B8FAE05EE7FD5FE3513EA3FA59948895DFC02134C19072BDF89BBD95C893E44FE6D4E7B438D6F96D6EE610396406BE61B0864955486CA631E4E71042C7B045A92417BDD829B440D5D4338D48AE08B6F0A3BD6359DB2F3A535EB918496BABB39F40AC35C8B69C9F31DDD1A45521F8A5DF964FC097C7A3CB880A9DC93F5C3D1E893E7CE1001940289FEBF7B92661178CEE9BCD518F79CB1DE3C5155C94F25265B360B22803DA566581FFCBD83023F2D961766BD8972AC1F9AAC9BC1919F395C4B2710BF05D9C907A440733D6D6260A1A1DBCD6AA5D7D1F1AC02EF461CAAEFB0EABEFE6C18DB9FB1263FACF91D3A05C702CD1AEA1D83A99CE1E7A234E18F355900659522BF4AC197FEEC3AF2398C3197D8AB34C608FACDC59E6E8C0EFAB25ECF788CAAD748CDCFDA30B2D757FCE7128AD558CCEEF9DE5DDF385D7023AE134D010BC12A98BE707585CB3D969EC4470398FEE19FDE1F4BD0A8B60A202BE30CDFC6C7FA1853E2F698351F7DBC710630776861BF963B549A7B2F3467E72F4D10FB355A8F0F0B451A4B2DB3250B3B4DEB2A2F90461D97A0F9849CE407DD2985ACBDBB705829A108A7119C82AE19DB9F8CA6E3AE1AE563339BC43391F99509037E3C13478AFD68AE7A9066D64CDC7A5BB0B384E162AA2D482774225F2734017807558D6CD6FC982CE4A8896CC3F3C13719A97931239AAC0A5B8A2F9DBF6B0328C326C3135E3E395F33AD6AE750881CD7F3967816C6A1A12409B5A118EC6BADBC134E165057D1FFE381E38636F7153174F306C14C3435460A1C51EAA4C4FD1A0EEBD4C3C1FF984F024644D16D6004B87481205BB3E29020180BB7E938E735DDBF27934F4B088E33A41861A88D56458421CD9A6DC86BB75FBB417404CD06D19155B1E2D8E249A9D360C86954BD9DB44E7BCED30723392C43D7C595DD871E4C111E692E9B600B
+1F365FF4562D7FEAF11DC3C95E6F399FEC0C4D590AFB0737BAC913904F1251C7228787EF380D5E63387F0EF5B7ED24066CED34C9D393A2894FF6A830911B9B70DD5AE4162DA7DC70D74549B427ACD666844D9B36570C64B5D6A278FE1F686F0958CD6F9A09D435D9C341B34A5793C971D2FEF007B1207E5C517C1105FEC3F4C897F94899C1CE4BF072C5D2D5B1D7D0041FCB335FB0FBE1E697F2CA8D7778535B591A183DA814A4AFAB2DBEDB5B8C3D56C651247AE5AE8F1BD773EA5351E2E9F3CDA43218CFB48540DD39B82CF6BE0B22F69A27FC38C74E637A437692B37C22ED9D55B5E32D3DCBE15736B7A38AC5E4961716A42A3BCA93B0748ABE700935235F7E03C8D60D3DFECA7CDC449C072A65CAF622C8A5E6F1440C20A33D3AE952002EA004AFEECAD8729EAB3C7A41C6143C77023703387CCF19D057CD66CFDDD30E5B501AC9AC6B627DAD54BA37E068A3F4C5E07A21A0A169F6AFA8F1607D3C38BADC0BB82B95B71782A2B7510BCF630FD37C10C44054747A64FA9EC35B73D81503980A0C95BDBE0C6237AF2DF2DB9E5C97461F251D155FCB44F70A6B867709D2B777C1554484898967FB8EA4D01275A62B4603851A4D4E9EFE122A07B1A286CAAAB31A9520FB9863DF6B2D74DBD94D7F2065518E126994DE4A81CAE6995E715A02B0393C3449A7F89BB2617F8847EC0F1F37EAB78AC91241404942D4E91903EFAD6391D09CE26C7D9F9714E1BEAC7B2430482071D6D2A49B8943084E021948781B7B969B942C54B9AA2813E44B16C69B3CB3CEBF95DC149F2132560684CE35C7EA8C73273C951F40B0CAB8CB67C90BEC03997F154124163B766FEAD61F8D02766890FB2A6B79C3278F1C90BAEA3DF84A8E23C3AC9AB707B68F39A741ED562A1AEFF384ACE940A6B37ECCBA4BD77530EA7893A43DA125C40945C13C0F9926608F7039F5FC5473D2C70F88469A51B0DA2063F23EF7CAA3C8C73414E03D98739BE9A50ED84212330C430D382D4C321DD3D71F4F9961A6D703541B5FCE9447DF41ADB1FE95F36FD0E860EBCA0B31E2A74F32812CBCA85EEBBFBD66B08C3D90FEAC6FF10BD284ACE0BD4B7237660BDD419C45159998CD8A5E111CC9C693469632F261538F08D0D685B7B4A215556280FBBC0A640A670B87A6F9FA662A234733E8B8CF719B937D60833069BA7B3FABFE1B78EF30879816480E94AC2C56968BC1BC6DE8FD359657481861B687DA7EB3429E57674A8E7248605D1A590CFADF251993F727450ECDDC17120651FF6B62E5AE60188792A978BE01A76521878A6AE9EAE7C648EF704742F0E4BDF3CBA7E02CDB0482E278653B09DAC8D3A52A9F51B294436F69E6DA6415F30DA571AE7EEA7929686BB9F058ECF3848C4E947559A8159E1A94D13CEBCCFA821B5A18FB796378F29D76F797B9BF855C6EEC80913BF9209E9BE5D72648
+99D10D9C7829851C0B4F7754CFEDCBEB85EECC6035B295DCB62FE08BFB1805F9729BA2A78BEC20BD10C87BA6B4625FF32BC740CEFB2AC391F8EEF37D33F002C9672BA2CDCCE3EE3924484233A6FB84A932EAD6CD546F39AB8E44F7528A58BFF7A8C5DAE5A572931D77BA7CD144E35DFDF3E07B231214295A73FE5ED960E1A5FF95F71EE19356D9D6F0C94B66FEDA5EE211835E5FF7732377428E6295584294AC21206070F03E41D36E2FEBA96CD5C7901197887932E07E3502EEC760A455C0AFE95A0131ACF22A07A6A4BCE01A9FCD88D3E224CF90C6B302BEEAB3FE14950A817E9AC2C727F1127C2BCEA5708950E1A12C86026143CDA01E5EBF5FA6EF027DB06803011DE13371CCC34923459A6BE3E065EB9074B9F369319C9D58BF15BD2EC365FB4B1F0441F99857DC841BA2C21AAE443B0BEF437D248D6BCA200EF530F590692805C1E84C6877DC69DB5D926F45977FA662C3E61A0EA826D3BA8D33EDB422B7E97C9561FA208B2489C3D3F53B5A282395EA4E1549C97BCA928EF5C1591C59803D2B422510EC16ABA03F40925290932DD1E0812EB989FFAA9B0996A9B0202775A2A536A3067773EE6C89528C49EF3461C08FFAA923D6807D50A96E12FFC5C33C5A4042A9019A1955CD279F4AE5041B7C46D6FEACF2D3A6D93942D30E2B0ACC625C8463578E15AEFC6F3B6DA5167F8485AAD708B6E0C71B2ACF97CB2547585C4332E87EA1BB7A8651F8B4B80A02049D03852333EE5CE9E84EBF066C8D0F7496601B0A3FCD8C78789EFECB7B3D7324FA3BC71ECEE49887365B159E377A648727AACB3B071576AB110B27A60FD9ED070C05DE1E172DB86BE3F16648632FFDDDB24A9347CD53927B4A064CBD3D1FF07702C25963416107CA6FFB681FF6D11CA61F8A640169C98E1A184423A6375A0836C5C698C0BBD5B2EF67FB02895158F6DE6DD1B52E5383257EDD7B56915BA9A07AAA2E0E0CD6D66E15F3587FA61D9C634C26FFEBCE6F14B08DF3855B89C3324E1601E508AF9E22EAC0BA9F16B46CC5278241FE9C32FEDF1A781BF8FE2E9DF2EA3007059DB00F3311046C0A7277147B984D40A93992481C3A6E043F4F23F3CB31345691477FFF00493F7FAEFCE3A43EA2B56F887BB9E835B8518D263CD8633F79C3943B895F687B12E5C783A9F04C7EC253B9A99B65B64993CB2E36B01621B975E8A207EF19DA353AA9E66ED1CF74D8CAAB52B797BC9234998AFA031EBE311B9FECEC1B28908A3F00CFCE916E070D8BE719495B396089023AB0F9DB14574D6765E3CAFBBBF00A55EF83537AFF02A871DDEAE85EBB674C63F54A574DE13F6E573AC971BE53972AA7803E344AF2DBDAFFC3CA51BE68B0A3B77FC30C7EC468909A0577249E19F71EEB377EE3E02840318517AB2CE11E056D80B309BD5D7460500F7269B89F73726FA87C223E5817FF0747212998
+0E3D5392701F69BE48305CF94FD6C74E15A5F9732CAA96C5B786785192DC9EDCA8DD48EEB4603D450CC66788D56E49EE433D1E7A4FAED050196E7C776C54B7A78C103E0C07527E46B7F16F4EF0128FC916284E6DC651EE426E859A4CCC20901B329B134F270DBD5C79353F348DE9B78525B4D812CC6935CFCA4874F9E42DBD0C21D0DFF8B943CC8397A8CC09C56FDAF8394C842670EAF42663841BC9B7B317489335E174784D495911F790B5E98A0E7BE3E010783F762CC9346CD2308FFD23F12275FF5D7C575808422271302C67EF34CD0FDE050A57B8419C6184CD9CCD3531F36D63EB64E95A426DD0EEA62BD35781796F721D97A10383CFF9A738560557488D65954710435621F22FB497EF4B7AAEACE1B3BD008AA6E8AB78736D0E3CBACA18209377E1270DB4A9EF1FB8775438DD8878B882973173B74DE93192E31300647CF146F99020E3AB0582F4D57E9CD8F1E3D0F298BA7848C9EEAFF2B0E52C423187BB17F8D8B7B192292CEEF2E9045ABCA80941A479CB863608ECBB8896BB78C77C6C771D74A703DB7B10D0BDEECCF575F4A9118D3BE2A646FC618CDA4A3578DFB86846F62C91167EF2D6ACC5E0D9E9A964A082270FBD4BB921A901EEF1F97F2D165D8DEE904665FDDC751B419A3F159AF786ADF653EE6A2CA14C65B1477A05334A899D59F952D5CA51CA4395E8C58A3EAFFE7836C8502E03403CB9619A7895EE40580FAA38C1B269C8F9CF7797D6F030D976DE8B2E8038AB7C23BA39312154A3B32A025BE80F82CECD7CD4845EB11DAE3344895C0969014A791F27BDD066B25141760D3D4FF8C6DA1BF66A17DAD34E9BFAE8F2912A2A6CDEC5A8E43EE98A6100E964205050BCCF0DEF8DA8ACD5916740A80C9D1D3390B476A7E66E970CB5416415FF7A97942A18FB41FD44EA2A0102B2AE9E8568520B9E7372B5889BA0698AC901718465E2085B268D2ED83C9A9A7A80FF364F0D19B1FA9F43FDEC766248F2F8909AE4981933319369504AB2119584DD346CD2BD1B1EAE918EE78C99D9663A7B27D492330FDCFB678147D4DB9BB262D4026F96965EB6FC60C04CD43B3F8B4B2FE963DA951E101D58F41596E073B61074510FFE82B88263F3D5E293D5BF8C8296E1BFB6DF8D458040511381C3BA3410DB6542EE15A01F422D7898480AD87B29F89D2BACB2E5EEF51448660D75A0794B310172ACE8A7A5C7B9D26E3CAA285ED92FDC0F44050DEC35906D6FF0B53E6D1DBA84D7D0F2F13E73C69CD91CAFFAAD2F1FD4F58F04D78D04B3DE5A4383D253C1301A2D47D6573706A53BF98C305A8A2A93BAB898F819ED35D3B84A4561F7CC5BEC61ECA78DD66338B12494172AAE8D8BDDF8475E20F273B11F14FDFCAC8F3BF20D007BA8D34FFF58CF2BBCADEB7911B5EED4528A66473965CCAF94A1D1E088697868BF8311F8067CEDC3701A249548D351
+BE63B25A11662AB8246FFABC8FE69C24C5019EDA83338F960D306766DDFBBFBFC403D314777AB527A4E9A8AF3D793F6C1EA411D76F355995B3FD72F56A62DB1CD1AF23C10AD6F6AA9C2B3CB8CF7A1327DCF9F79AEE119BAAB925F19A20C527786957229177809DFBEF18A969A7A9253548C9B721310DB0BEDC107B074843777868E16C19B72062EC627062394946DE8F0BB5337472B239F675C51B3D1435691CFC67D67F50CF25394FD02BB1B30198F19E88697769B0015B6BF59F0F1FA2CBEBDE571F148D01B025B02F9AB484AFA30C80B7AA5113DC2D040EC2F7DA5274FA21B43DA055B82B22AF2EF6A60351FB6C0E7D37C331FE0F8297C570B588A1B23AEE99E9B10D886F8064AC946174B5B19F6DB6AC2ACE2738DB104FA3E39087014E7EB3846D44BE69CFB81FA677FC62742880F1C2AA46933768A9203569F99D727FCC870B900FEAA1A900CCD9F9664101E656AC54ECA92A73F4EE8712C255F3D0AD6C203D9BC27F388C3764FCB3D89E13D7A3701F6FC943F4ED63A620A7D11859E7F3694FE37DFA93D047079B7E6A0F4E16B038C5B779733D948790F78EA07FF7A21617D87F99692F8DABC743F13153426EBDBE789B266905953099E0898BE5DFEA4230BD8993759412E5EFFFC54D4D58B8B739C389FE693E17169AF3D9A90FD25B82F9EE62E7C81A1227714DCCE28FA51FB6902FB308CB88B45305F713ACFDC4CC5E314DC17972CB9D189F2CE90A98FEE6F4FE1E640DB6C633E5CD3CB9DE9B2BFB6AF89B817998ADA58BDD33CB3E3944742DA598C9322AE2546301D2A0980A9A076BF0A1B3F82195E03213533D43FB13A9FE6926591CC1996C3740EC44715D66E030C09BBDE890985879CA5631C34471A6BA154CF3BF2D03BFF94EFBF51D53787ACCC923925F43F00855535B83B8D808B2FD5E231D22337BC2906BF5C337D652A5876E0AA241769C2F8F406618A8E84D7757AE193CC664C7C5BAF284589864ED0E7FF320D2101CD0CE514BEEE0F07E688D9EACCB457503D24D58F7F60905448E959CD4A0CE904C2AFDB8FD925DE3B94A8415BA165ADDF99DA61FB34C571886DD3467C3AAEB8A7D7D4760DA02A993365DAC1372C1F0D7E106A4365D6309CDCDA3789CCB44D3A0C9E2EB6FAA5E171DC24576978E867EB54F991B7FC6EADB9D351EC5CB677E52BC2E39C1F678A391FF0CEBD8A2BAC8D273654FE2B55EDEC3130069265522D5F963E7B1E558366664F210CF065F90D222881C519B100BD2401787AFCAC17CAAE24EA829AFCD214911B1587C61B92A8E809A9B98D44A2044F01064A9BD517297F86303DDD05B80F94CCA4DAB6EBEBB7FFA1F4CBED12C5B943692660CC0608715AD91956ACE5B199363EB5283F4143A63E179EE235B5C06E821B508AA524529886C50E91C594A1BD77CC1D385EB638062778D2BDB2ACC8A12BCA72B5B15F7
+2C29A6F8D6DE83541D5C18BCA3BB1DE8AC97159C2EE1202FCD305041BA38EDD834F4A1A7E22F31BEB43A318A1AD01892FB64A09D7F71F7A90CBF3690E77770229072F80E2FBF6B7A12D5560EDBF7E82477DB8A04E2AB633F9D75A7CE5CA740E301F1D5D8605ABE3FACEB38C675F0F4081B512FFE3D2CE2689E0109F63E7BB23884DB65F465732E2C51AB2EE9DCAA6F6E8FD66011E1420C2BD90D119B68B2EE1FB49D47009A9CD885C1721A59D0FB1D3787D44CE446D8A8612988DCB0E1C514255D7296D6C041A4AE58112FC666DC25A5E54F5A4A11E8BE9BA78F28ABCD789F82BB76D55D1B9BC16DFBFE3D98D9349538BBCBA14F096F2CE15917B35AAE5B40D7740F763CF9D8F4E760748864662589BBB8533B56506737129FB3645C5FCEDF84C1D4A4769AFC6FF59ABCC2E7CA3B5776F7723CD480C4D90F5E5DC63EEA5798254D3330682E8E9F93508CD6D9AE3D32BF374067688B1B405E4A1FF9823E5B9C4D210216A258C47BA8131EA9C61754EECAFEBA0C7AC90FD88F3D3BE15695D62C04E3920C43DEDAB61393D06437594730A20943B3A54B58E7B65CE5A9E0D54638A3053CFE34692E801B5BD3078FE2F11FBC9E2DB9C242E4EF73E70983733ACFC7B432F45A9CBDEDAFA6E34643DFE6F5A6F4EF4B42DF315C5C35FE62DD05437A46837BD334F02F5B04187D30C4000C476D6B549A9A3F0DC9DBCA59AA9638A321FAB6B4FA6B7FDAD4FFB2C6DDCB80B58DED174880A95CEE5B9722A6D38873EE6ED66CCBA8E08990EBFBC98EF4C8F859D793CE4A46992AC5075CFBEEFBB308C683F69D330C6DBDDEF6A4E997B78CC4CBD41D7E79D4EC31CB25736BE15D35DC537FA26333AF7B058914F891F70FB22E05B71844FFE93C28A2FA5446903234440DF503795ABFCB74C5B28A4E3C082CFAC78137B7D733678FB4F380713DE1BE643D33F828F8C219BB31EDC9AFBAD20431ABC03AC824BDFCE1AE6C66FE0D585949CE2219B2F137405D569AADCACAEDF24DBD8D8987E98F85E7812BD6A8B725C27A1AA3677DA7112AD43C6E1ACFF8D3E64385C9BE89CF2B667ED680657EEFB5E0B7DB27C34B0FE3D801967775BCEC229A4243A2F8C8F090E0BFB25A48B9F3B75D0AD54D94B355164E897C01A57BE88C992CAA19F90BB0364C41050BA99BB5F3CA0C62A84B54BE7ABE255157BC4E239F1FE7705707F07FA7C6ACDFD2DFFF9FEA5B90C8CA016C777E01BD08019456FBC5FE1066B21FF4635D174F30FED3C56DA837ACE6637425ED7D4F28E13370795E9E6BDD947B2324E0B36561A142FCC8B3FF7BF095A98F4440266E3966FA0F18CFEBB5F1CC5EC3A8F7ECDE391E1A2C3BAE0C0874EDFAD1D15D6DAF1D41F4D1C8436C0D252F869F80047E177A651BE4C95F025985880E6A80D1E66BB9B360B03EBF2F3A0FF5D245B631EFE66BF6D16094A24F6A3E4B27EA26
+DD6BA6416FA163F850181F2B02937750D01E7F67166A23E5A1DA9C6382F13B1060914D378C3E8CC52EBF439CCF99209C26F0FC0DE61CCD0C553F4F039E550EE77DAEFB1FDA09AACAC35EB221AC8DE4679E0543922E08079CD4E0E64C03D0E6DC1585715B00706AE8940A411A732F819221CEE004E12A9D828D18C34E6EF5692A53399C0D9F2F184DE93C1100BE57B23C5DDE1EA01CC297F0CD3AB49798F2D1E5F31E64763139A4511B6BB9DB6EFDD21920957C8DFF1A40F2D115BCBD586BA4E85DC9F0AC7824F15550571E81EA137AD788835ECA063B6F30A35D9FF410147A2DB1F24299DF1B1335702B911C2281E4FB2D95DEC2A96C1C1D4711A7C77C145BAC15AB483F72F8B40DD567297E9748937AD8780F6FA65F4BEE6E2B01074B32BE612E8674AFCABB7A166BD05E5D5A3116E082BF6808CF41E013090C1E025EDBCAA16238AF7083736205277A10A7DA23AFE6047628F7991197A1D7E3B3B1B3CB753F61695F2BB378FAB276691BA389AE0E34BADBC6368C50E3B7C3067B582ECDA781489335687FAF20660D86C1171D77823E816110078F2B3C5B754F042C6C1BD6C376E7AB96634C21C3BA2E12501884741DD3EA910D479BA6423E81B42B0B6D47416D58A597FF5415F3358BE6E4B2F4A2312115397E34CC449B238EE862C1FA8D028230EAAA7FFF43A85B297A1D8689F09C56241C0D715A6A9A522BF8CE2E2F0DFCC98AE6C0C9E74730E8CD4BFADC6F2ADC9AB8CA8435787F9740F882F6AFC8FFC7C3EFE486780E3E9B906004466453CBAE0514EDCBC7F88A137095EC77B61F5AA76A323279F856F4D8D7DDEB0297AFD773B7C8FBE4A314CED0B670C29C26A8211AB005BBD7F5695D859098F7AC5FEBC896FC27770858102E74E55798CD79053E70AC474AA0DFE48A80DE6390242CD2AD57E92B02AD4EFD8234144207DC3A981E78A40DB5601BEB04570F071B2A2FF98DD440720FE60BC527D4FDF76B9317A535F849A823B030D22E311D66FCCE187E07922528986BA8D46879FDE887C05C6E186A022E0034615571A0A1AE6961E7B67E9E545456F3A7C7338BBCD75FF5D3C85210E7434D53C95A0EDD332F13E1A5AE167ACEF91800A8D44F48A7F5B6E83F40909C741D847B5094269BA48DEBAB7D9AD1D4E8BB5028A7735213BA3D805B1D3A8ACE2E32114820CE18A7DB7AE23821CE9637BE8D019B79818AF7FBB59DD94BCC1F3BC561330C5E46A27BA9A8B081ACD1EE7FC3FA89021496EDECD9B7BE4B9E815DF2125350F038073C0484C39D8EEE109EF65446E529F0C33AA8E0EFC42DD839D4242D4AC3B988A8A94684BD7A46C290D7F36171D40C2148806076632990F460BAA45EF5BF574FB2045751803B45046367B482CB6828C88B7E1C217E4B5D08087B02C2AE6726A5147F12EBD3A78A74212ED49F4C5FDA6F46CF751AC2AD0D8F14B709
+D92C2EA40A505DDD8EC85024E30F0423391981968FFA370C5E037671C3EBC1AA3D82284C410DC0E760C0419806B6782C7BF4DD158FD336B2A290F68DDDEF9AF499DBEB156A44C4DC9F2BD28B792D592E55C6A63F44C6D9839E16C75DC6F9012C9740D17F01F4CBF3503FB13ED8227D417AAC04B17DD4604E14FA65140D1F170616631FBEAAD4F988A3505DCD8D4F0491C03388579632261BDD6D8813FCAC28A02889CA800FD4AFACCF357974B2EDDD9D4C797BBF9A9C60487082D9FC6DA666CEB7EFB42DB39BBDBAAB7F80DDE941C49B10619F3A3AC6513F5ADC9E720E62151C48458E37536DBDB448E934C34AE94F31CA54000714AE6185705CEBF0652AA954FF089A96645E42877FAD0C485B72BC4A56E8AEB193BF0D6FB7B602943815852E40DCFB855A9572162FDB8CA00BC66D2D80453E4AD6F340A79D912285BD9F767FA052A360DB7C12980BCCC665B93F6F93A38E4C54108ACC653A729FD2262F022F68AE2863D6C082AACA74F05A192815137D899491F35287F82DB0398CCAE687A4519C1260B301F51DE0FAB0079A63C1C72A97D8476D957A071FAD7E53F088453D680F167F912EBF53C8A713F306E6A896F03DA42E5F573CFA68628A84A37E19484216A648042283E787B9A52C0AE6D8FAE4726203BE4DDB176E20DDD3D08E661442ED5797F5C5E44A54F01A4A91182BF8CD6133A73EFD1AA755E500365B47F6227AD891835C520C9D74DAFF0FA0111A615AE125616CC01E80B53F790637320636688F35A32CB515E2B246DD71400DBABAF9A19C1704CA670902703C2D43C7C7C62B91B28DB50283410052CD20AAC255B245C3081CE781CAAB0CA18BB35AC1875610AA84418C3B354FCBCB7E7CB13FC80BF954CB4B976F46D37D25032D82DC83DBA027D92D3C33E1B1C55D5B9EC2163D6EC0C47A9ACDEFACE6E37D79F2F5FE675976B8E7FE7137CC3188493941E483955C5EE2759FDC7242CEF66B0885EB55D48EFDF589B8A0EDC2F082787C8CF8ECDE9B0E3970F040C9FD70267908DF6502172D02CA9780D862A3434AA07398B54F70518D665DACB1891B1484A1328722E51B45A281C27D4B7AE5651BF7AF7E670FAE26AE0BE232CBDCEFC0918515C29D7057A2F375E225CE4C490D32290B8778963CF6163CE1FA4BA9FB487704BD8166DF717070A05D1A73C85925AB7D78BEEC9BA2A2B640B7EE39534F5D52B6A608C6D1A4AA84C798F56C7DA2C43B40C236190C64BE69DF9E5BE523CEC31ECAAC4E6C335D1596722FD2772FD8BCC1C3C89F298A68FADAEA28F009B9A347EF2187FD08AABD487FF8530892A532DC66B94D4A81AE2BA8FF09731C33D66D69A4CF37BD1B7AA99D41032C3DBD9D44F4321ECDA1BCD28E909F6D480B5CA37C2674F38C288BA245B71341C40F0F7A0518A234ECA2027C4F33692CDDC0A5F767C24494A55304E34CEF
+EC347D11DC9EF080FE8ED571F2757042C20E998CEA15C9D0762FA9263392F11CC6E5FE397C8D61D4E57E5359C5F33C920F8F898F5D8980A0036E96754BF6370C7AE2054C0321FAC76708943AACA234C8C32155D43C1ECCDC09A9F129C0727A6D877C6757BE49E7CDEE89D1CD068C4D3AA275A9555A3055097421A1FD24D78A6B62DCCAE52FB4BDB1F64E93520A5919EF9F2A867B0430B4DD08582250A575F4F0FD43F45B7EA975E229776473739784964AB4F96F15629A9583CF3BC1D827ED6F01A528BAB9AB284CB21DEE3935F33982246F24F9E4BC0DE8DBC7E89B80E01AE4A4A0445998A4C4DE05838E5A7A88FA6646DDB25F0458FA665307F9A0B40902D37D67CB64AA355AD0ABE2ECBDD08B16D11D223C62777118AD2CC2F95E6FF0A91D9783F445FDD13C961F8B4A5F41B4831E1941A4392CF436677263006BCD48479BADCEC16C6E97398DBB4C3186E06D1F5630C8FE47E7331267AF8D9BAF6D33E273C25A99B806C4ECE9B671551657C56AF2977F9B730E69EB3DF84B8FD0D45B624AD1C6C4E200AC79C6856895E50DA3BF9CE8754355FE134943777B958B05C9E9A99EB5C2E1A143022D0ED8AFE389320AE5BD9F17B4C87C93ABCF24449E31AB42D08EE1C2366085E5439CC55E7C720CCAD1F0119CC3F2F25CADE4CC445AC964A8BB2A65B7CF11D3ABB09D38FC3DC0A59BD58310EDA1C2A77C2FB5C1D6969F392418446D49DA30E2C9415279E17DBB72957150BF36ADA1A863EA06E04FC563A01F069A8E7B943EFF3B28CC6BED7B93D49C77C9E94AB6029BB490F88934E18CE88FE718F90172485EBC0A0516A4430F665BA194C21E6331AC11E0114587E57BDD3D1F3EBE61DBA4A6799A10E645CEB44346EA2ECD94BB101B040E97CE042B3A990FBF09FD6EBAED03163D2B713BB26D016F60373109E87EDEAD012E77743009090369CB8D3411D753C5810944E8B063B859BD3B61D06F797EBA9D21CA72B94657DEF01481B64974A758D41BE966D3F4E21F5E9A1D3F40E4CAF28BEABC402C400C59201DAD8DC0C46D530D3DB2494A4C48AA457B12F3BEB0A8E7F0BBA1AA7BBE6090C6B606335D9CE9412FC31C96A4392B6B6D22F9E64B8A049EF771DF16D077FC27858E2818ED9EBEFE2F02043F8D639720E7FDFE2E42091D7C3C5642D83E51349BF466CB759B6C5385647ED594DDED2513DB1765F22BD6165D398A64E80576C4E971F28784A6C881E8B90CE707145966EB3FF861AD951EB87EEB4D07DC80832E3656A30E2206B5940E3D692CD5419AEA76EB8E90E48BD4BDB65BB33481FCC99ACDF7D5DED57457E92674EF9CC9BE9A58774AA18828C312B84818E3735C123893145947BE2FF8A44E2C61E687F61FBEFC0292C8F0A5477FA8EDB62A58ED75241A39A79238B877F91EA3E4F7D8CC78816E979CD9E0451E0FBC566DB5A2D759FD1D89F5
+C00F5EFC4FCE1242E0256BED0F680C2D20AD2288A16B4A31985FEE058F9630E4208921C6CA7FADDC8A1FD5C76AA9EEB7957AF5F6739443F452AE842BB84C29510C4424AA4D04005675D1EAA694B49196E171B6F2BCB7797BD918275B72CE8B4239AFE7FE145FD6FE38DCFB0E7554D6C0323811EB4C9230C9A04A04E832145FC248F5B9C5BA96D893671CE9E09BE9E5FE1F2F842E68D30FA12BE1606857CAAFC1FCCBA403DBEDE00B01FABF9B2B668F83123BAD5A8087FDBF8515CA2BB2E665690525C46CDF5113109939EE36B42C04021B6175F7B6C68435A367DE175395F487E10241AC49889828DD1F219C6A83CCB777B9E19FAE1ADDE471A585890C39D6AAEE8FF1332625B1800F0E30923A0F758B1D27DFBC79D21886DFB166EFF678ACB928B0791A4EDF9E952434ACB1E0E60E16EBCF1417BE5B83694689E86372D8B57800AF4D96DA5E19692BFBAE85E10374C3A0E6C5B159BE621D93AE887507CEEF6B7A3FE06D9539323BA690B668DB43F3336D91472CC88879C87DB54AE115E4CD03B84D6DD6E1F678B5AA340A57806D1ACFDCC1BC680F416D346D9C9B80ED6A1BC31E3174FDE86F42DDC608DC2D933F580767C111CDD44FA9798D20DAE42A5BCA3E7B470964040813694729EBCDB83552B57C1FBF0F5B50B50720CA1605995F69A19F59E04305E08BC82B0EC5C395554ED48C9E33DBCA50EFACF7C9242068B2279317570803E01A1216D5C4DE71CFCDAAA53E3F7AD029CAED540193A156D5641ED383F7B85F62B43C53BE2A6A6C6879AFF1E54A0E1999D59F40EFB288812DDD13F30A94E9BC6DAE68BBEDDD960EF6E8EF90B207929626BEDF673892E3E874EA321E0DDE81E0C51AEF417AE693D681E905164A79358E62E6B6CB88AF6F436DDE51A24717FDF907F74E2376D649812C97F62AF5E5B27B9F8FF767F9C81943C5346E39CA2D0480061388197E29B603553B77DEFD32189B1291E004D8A098608937AFDB12F577FFB5EEC50C47E8C506EEBAA877ED36FAADC974A93228693EB8EA0D6BA5EEDE36673D8293A9C275F8EF506F8B7E989373DCFB406F0B32501681663F305141F4DAD2BD5926C2DD54A140A4D8F6A87D423EE125E46FAED2A118FB065AE8476E70F05D8DB2C715073C97FA44C4A650BAFE051751DCB351B9E9D91570B9809B1FCA5F2EEEBAA701B71316EB84B7DEE4AA4EB45A701FD2C098935DD174734272728E9278002B6BE9C61C5D9661E0D7D31B33887CE5C9A5D1CE367964DFA127F4BA91E417FB16A2262215AEB2ADF771F4FD95384D023C88E0A5E6BADD4C12BB46C2034D19FDE630EEE8D4FE7900C14AA33E0E2D7C6E535D9B5B5C9CB0E1753F06CA964A10C9BD0962022C9CCC3B683C5E2F671BD7E4A106EB1023A67E7A825DB2DBE39AF6D370D95F422F7F0E3EEBC3369C5B11F4C4E2F9EDF58A80B5D4F47E71
+F7C63317175A90D4F4912281E0262C87DAE409274019314B94DFD9712032BA20B6ECD9CF425A881A23BF9B9D55EE26138F4FFFD527ED00699AF08CADEB11E280E68EBDE656C4FB9322FAC872DFAEFDBE4438E5AD0411E5206981567592D85C67AC699305FE5650D17C6EBF1754380888BF808860B80C3EFB4D96B4831E3A3473A44A4AB904389EE8E3C7B18EB65F535132D1FB781406012CDB887215B9A439A2EC7D6A9747704FF8C36445E0217E21F8AE38A09E38C5C2284E21D6C2FE4604944C56E9A1A4DD19BB1211573A2F3B30A54070032D00017302E75C2791674F1FDF60BD3135BEEE94106B9E1220CDDCFB4400F9D76175FDE17BE3FFFACF2A97548A4C51D6DCE6FAE73DA0539D2CAAA5D5506385992820F893DAC7C413EB7D12213A7DD0853176AA8BDF4FAD2BDAA13CE5A2DF541B9BAE7A192F79E8AB3BBFED8F1CB2BFA4174407FFBB6753059A48152A79814131123E631EE810B52B1E37FCE99902C91AF4D6FC104CA6824EAABED31C4968FAE5357284770D85FB2011AD881A349618F3AFA56E9FEEC0B605AC750D21B77A8491B5F3E316155F8FAF17CBA6984EC4939FF374C5DAC703A0412FCE3B2686AD939F45FA41B30C59249387DAEECF3460487586D60424A06FEB10185E0AC89ACDD332ED60A9F7166DE69B379E7904FDB58C64E65415EEC62869C19651D83C58852941312EC4D7B59E20F5CFECBCD17B35515035322BF8182ED09CDF698D99DAA3CBCF8587EDD897378A755EB82108E371D2FEFB6DF82204DAAF2AF7E8BAE077A0311FB05011B218713F0AB663FC7021FDA7253BD897C15719C4AA1852D15792E67255F57165708468E77DBE68BCAD5F629EC6617000C24E3AC75C965DE91E1E552FB7CF921968B2980FCDE657E5E2A4C2B9528572D9DF9FA7272A305392179DFF8090536972F92846ECD4687C44A5D00C84D13248772ECC7D65259A21B9A083890C7FFD467794537A1C7C6958ACA40BF0625BD38259B3A2039B9B49A0B13718D56E5D25C840D7ACDDF6CC593C44CD55C167719093057490BF3445189BD8CBA188DD6E8EBBC9E459EAB3E00D2957C04650C88853A7024384F7DAE133659F5AD6275670F0C1C40B71D8637C2FC0C64C7252409C94F4F6658FF75DB71F760FB20615B29BF3B09D6FC53ADD429C7C58052D906006F7931A17585DFDC892BE170E09F714CEA6A54D5399A867ADAC6850B02FB057634183C7A573A74B447A85022AD6293349FA84C36E7B44E357081D85272F22DACE32E52CBD9DF3C778CAF7792B64E869262E2287C34024A9E1042491B297DE3675EFA09304A2116938D7905BD9EBF951C90ECF092B2183D456622997885493213149EC6322C3341B0EF2C7ACDD5A811D6E7385BAA60E7ABC7680BEA33882CAEB2B8FB102381FA3DFAE059DB939A884669018F50722593629C63C54EE198C
+9401490ED72A611CFE562143B33336EFA5847E3CB7496B19BBD92144281179DDF69D03D6E684AA66427752D966D0CFF0DA86859BAAA6BAA5029D4E4056EAFD77EDBC341FB4D465270D3BC74141D1777856E6289283D67D0BF94B71C3BEFFC5C0A9DE4CD264A9FC86D7EAF28B79FD7593B8B32800D531E5B68BA10BE6BF74DB6E377982B6DEBAC613E74195C33A0C3DF917954579B15CC8C2490F0DB0AEB6A2B29A542C1AD5971BA5CB651AB29AB283FCB3950668FFB15D221F38ED5C8390EC2995C4C6251658919636127CA36466E99C0676D8374A6391753833B181E1C049D15E154EA35D23FCA8BC2602EF068D178CB0C91164A2C4ECA8E92202F05E323908E76D4DF12D7A8B46A82AF9771F5452B81D457DC558B1F7A6BDCE1894B9F36B0908BCE12379FC22BF14CD4E5EF2A2CED316ED13B79527559AD49BCC9107934F51CDF6F1B58D3E57FFEB2055ADE33EF7E199E6E8421BF46BD5C1F71F8A96E837A63711FDACE1F82817AB6AD00AABAA268D00B332D8D81AA397772261F511BEECA0D87144B5CB1FAEB5AFBB6C6CCF66AE88A3A70933E6F7C7BBFC8480B7B2F22359B20323EB1DD0387AD1C842A834F1EEA6630CD552CB29A69B274C2F09FB5310B3361CD07C8224A8DC71546E8BC6F206767B351EE2E3D38A875C2E348C8AD9E32EF9752B0C116BD2D2906A3D99A6A690BEBE834A6E2D90DAFC615FDB5E79BD5B6E0AEBAAA6F75549205975E0413A294B0C672856A5F3C69B7DE9FD34D9DAB3226A2FDB728532573697BC1AD01C25228342C6AB92D53489D414917CEA799121F486A471ADDC9DA7C2B4B67B4874C99EA02AAB304CA279B393639435E2DFB6AC074432A2C0B15FEA0DF2956E2A33732D6AA4EBAE6C5D5AEF2E532B5FCB19839905DBED227075C9C60144FC59CAC57FE6624B091E7CDD87C22FE8FCC09C70114D239C13BE96540D70227FFCC29D29B247D98BAB856B2A701CE02DC625BE485660BB215C664B405C52CC8228E4A26C10528A325EB7D39EC57B2EE8B8CA5A1BE3F7EBE41AB81C3615788EC3D1A298E61B08635BEDACDE242B5D03FB3770E43B85F0E524C934C4D594765A0805E0EEA5A9210388614DD9C11800D8FD7740DE90999E57A041077E3AD297BC226C16429548E6588449FECE37DBB020E600E274EDC38787C8507A8BE44FC842F3F95FAEE60D1D73D46C52AFE20918E7624BBD9C956B01B322D5A1A1D99BC89AE4011101D887C535EBDA115FE6D6B91E28764DB1BC80F94AF89F30589E98CC417C0D395E15FCB00553A2D03189A0CFB9101568D223C1A4ACF29AD913851A6C2E225BE90C47CF3734B4FE87E0B7F263F3833E25875048910F4B780B38707FD926E0B20E513D2007FE35CF20736779E788EB87961F18727EA4089FD5AB6B20C79429FCEA6A1E8EDA07A59B5AB23B008C62B356F5795D603DE864
+561C4FFB831763EAFC38A04363DCBBA253744313D8DA38351BBC5EF60D90C07975AE3B3D9F5695059E6BD04502DFAFC8A0C65CF662BDA74404E755E5FC0E24FB6A371F4135EB9A60CF4E6906FEDB60FC71CCB22B2E9F79BE31424BFC0B4339B15B3EE7B896AA7C31A065263F93F3F8EA248313C0B4691B9C0696C2CB4D5FFF30EF9BCCE353FB17EDA2AA19027917D80E81387A4F1C42DFBFC236138963B78F69C44F2D766D6352F752C288C0410F645B05A93D9400B458A4DD833C0CDD1848722AFD5C3CD904AE210D3513EF0CB29BC11DEA452A24D7584DD28673DDD65DA1C425B289B83D2A5BB6D447290E7CF6F88BBC7B1D1BAE6B864EC84B02F2C8B2C065F0655B3FB0BEBC24B8E32ECDF958F4E49CBA28EFDA009A41C86F0E477388C753DE174B2B815ED58E06C1685BFD82CDA203852EF82E760AAA49E09678BFD7FE45A9E88AE041F9255C5C284AEC5AC441FD923675E9A7289B6EE8E656EF576671AF61BD090CFD7763010999632FC8467EB39BD8DC1B13B20FD722CDE64C187C775012DBC8A99416DA2F9A5330C3F2A88D27762118A4BD22986DB981337ECC70F742D29FF5D12DD9159C01BEE348E9A9DECB310C4C299681F1FE414BE25038820DF536E8B4727C17E8D5DE7DDD9DD3A9E0390B7720FE81E8038475ED639B2BF5FEB0490FCFAA57CA04212CA1BC0B8F217460341EF457243CC40E88FA71091D54E2EA4040E6E78FDCEA70028E72D6A278679434FB66CEB97F0D859C32D8009E7BD3125645AA9B813D890145051BB26959F77E5C594716170F3D75FCC71ADC3EAB6DF6555EAAA600FBE3FCF404E5508ED778EC88D1D9FD6FBAD7CF66168151CFFB25E3EE1025BEF42635ACF432808CBBCE778428061CBCE4B4C0EC5D1AA029E4F486FC75E939481DA4C3F619E1A6E82319ED08030F49F91D68106668C074B74234B37662E1873DB5362147D862122CE8001123F7280FF7C2C9D22AF84C0E9EEBB2AC662789518085D2F2C541F0FBB33EECF3DB0E16170D9D34482B4BD8E321158A9D60FCF5D3C9032DB37A231204823696C16692E288365D62634A55742023448CAB1FDA0901427A159511E0740150372EA8C1089473364195C7AA8E93E1807A7B9E59A0158122C008E89351493F19F0DD05F5A5D12940C3CB3986AB9A15685F38BD7E6638901BECE70FFC17D9DF859AD2FA0C09C67BB549AE0CA3181A31EA3AE6AD6083EC18A68CA579B3EA7EE2F5AE63DDC4D6BC5167AC5257AEF9A7810A67A59DD40839454504823F00722B39576E120CB3EA5C14CC81B9EC9A31F2436EC4397CD491BA4CCFD5C9D4B459C8DBA1EE711342A598B2DCE610064EE2CB2A8E37FB4CCF52B7FC024EA7CF75AC29048B0FEF709D416E84FDC4FFA75D51659AD3E55859EBDD41FC0D40A2ABF649DB00C90640A86C6544292E837F0E1F04FCCBE559DF07DD
+6652C8ABAA639A0962A644E272AC377E6D7589E27A5DD33968D1F7BF0F74CF7A14C34E4ABAD99F04300301EF45C164DBBC4DC7FDEC566D320BE4431A4946A0483740276B3FAA4CB20A53166908B3643086B01D57F98BB3435BC2E5A4F27723C7020471850C1E72EFFA32D38C7FE310561CF6A01B6C4935BB6CB5D606C86273C4A50B3ACD21FB1E12F4EC02563DF58DD5CBE45DC79F2260DF16D71F647E601F32344411BE2D8BD87B5AC50AF71C27454ABB55A7DFFD33183B7459F5CB1A04F86A8F3AA3A13C58936FD1AFDFB047F9E9738733B0C3089233A65F6BE7B5FEB656F03383DDD31BE264549574A77B530944B6ADB82D25933B976DC7ED6123037CED11FEB02309C388E8793B15BFF8841D27B018A7469E0FD237227EADF74CC42E6EE6E0EDEBE7CF264BF6FD722121507107D588E298446A56D566225EA3373AF8C39D73A6C75BF1FE1E525D6A663544078D04E5400A2D820EBA697EAB7D001D4E2C0994085FF7BFCC47BDDBC71F8A82B5E20C9B459269F42055119A0FAC5572D60E248E1F5A193D012ADEB449CE0ABBD0C04F4191CE9A32700C0D1543B0648E3D37D8CE0BC48E239B54DA2001477558941CA8A4E383D5E118B8521E7951155823BF848F85775B1E60469A5F71F0A973911BEB5AF7F531EF5EB42D7BCB8575F4B58EB3AB77D792C822F4529DE7F59ACCB2C2798A7BE7E9E1B738C109F9C5A67F07A81B1DEDD047B596FE656C5332265E3045E7A27C72BB26099CA8A822110DE0B603782B3617D015AA4EC57C867FF1943986656CEBAEED863EF81046E08D14F7A12119A4919851B9B9F06562C76CCE1663CB457CAD34BFC6EBA6C37814F1DDDC63DF0F44D0652B1D6A00221B648987BFF426130F7D47614C1C71C594C024BACAD80101C89BF50BAE25C973B6B9F679EFE4F7B9F698FD2B0EA1D8208E50EFD867E638CCA99E9EE68C2DCC572BA56C626E1A5EA6A79003EEFCA258DA6EBF5B97388F8E454467E6A257AC788D705FC7C9B966654AAB02A5FD572E80E11E461488704A191F7A5250AC736FF341CB923A155C0C0624580764F21A5469057AF6996A3836002FE3919BD88CB260513DFC958A8F8D6AB6976B390B2BEDCD91F56C22B26235063D04FFF7CB1FFAACB08ECD91BFBF91B4FAB23A580EB69625FCB86EE96B6DC249413F0A7506A6D0D47CE544E8024C08F88272440271D34C835497F61CBD8820D5D079EE8BDF17BB3DE37A3732B465CAA018624343AA1A95086246F020708587E98FD93342FF8844F5106D6349F99C21EC19A87AEA171CE09E90162D72259F230A9A3DE7260F0330A05060BD7C1606AE50E35C8D64E2CB5F67A5E4BD1F00CE3AF76CCC96082F50B1E6EC3C521CAF3D2D7986273110FC507344454E78803C69C1ED25168578FF969B56712B051A2ACE3D850197E885ED12E07DC8116007F212A9D808
+438A647B50428D6D7492DD97381074737903DE0F8C7AD0E39047903F381F5C5FA6C1B93D9C79F9D0C73139E888078A6C2B942E5C7B9A1EF8AF6C7774D0C17C356F16F0525D85CCFD889154A1004C016A4DC242C06D59C9D4F561283F43D8311713F903C9BB643A615C773FD2130A4A7FD1F672FA54DCD4773302D4A950B0314B06836D9B1D416CE4EDB4E1237DE178F6C048A2EEF73E908C97E624E4B24096FCB61F4C5F753A60D10121AB171998CFB1759D7DEA02E34975866C5181CA287EEEAB83433D3058530DC6F1830E4F7D44E8D0F6C78F4B21EB27E4916B33BBA74F2C4E364E9CF0327EDB6F27C279C4EF5954A1F9DA384ACF4E44236BF1BDB66D18DD1C8A17EB762CB42463FD25F29CF2428BACC3BC9B98164ADA28AD1FBD9BCF2FBD8400FA412A48A3C428A9AB82C0EC23A92C79FA63AC0EE4C8B8DFC86E213D9F428A7E2B2FDABA123883B45F80965C77509E1E403C6431932755904DC78AABE8679C13FE28B1A8B105C84EF69FDB9E032AE2759D0A48CA83A1CD39F4753AC197B22C615A0C2670E83BF609EDB71297CAE4C8025BEA88078D5189EA17925318EC917D91567B5423D0AC738F78A60C550CAF1474D5B4002E2668658F97E2CBEF298E997EB00D7B7DA476C78CE69D8BFCF3C025B3EF1AD1A2A46BFA4A23228FFB920836E19D5D34CC296CD487478DAA7657253E406DE817E2B94F8A6D12D59C1D106FA848DF9000682D9320399D08BD8436E649EAFE1B2639BCFD1333EBAD9B59D5D2A132A65FBE5469E3F6394819FA4EC9A2293CF55C5E031AFD06D05FE091BDFC9735F6F99DD0262CE810E67CDC9C64C4F7DDBBBA70683BAA792E334564173B89EB4DD01AC3A2925E0C69CAE0E9D2114C4453A93BD3B88339FF3C04DB72ED74BC02BEB957C8515F8B1DFE5EC6659C33528B315E5DACF240CD3688D3BB634B167D06A57DBF474A4AC4B8CAA44F9E740C3C6F1A9E0244FE6121CA92E4C328AAE3E400545F1E2315D368FE04BC99EFB8B20C4632CB07429ED63D8CF4D3B665823D0D88DAD57129A11E9D07B238D7194404ECBE684182328D921754E19823AD36A6383F2749778796EA287DA81021271F35081A398404B27B20F22D9C1002AC80F1421ABFFF6490B69837FD59CABE3E1C61B87C483E5736E80FA8C5020CD49DAC6BD221C5ED114ADC262E0BAF2B3C99DF82FB06E432AAADFEE5E95EAF32A157CA09B25E50920DBED4D21EC6CF4909046337FD6125D9252A3DA1382C7E80333D50B4472730380FE175D65CE96A34FE904374111BDE9577C5B1C9EA1018738F7E03B56D0832F7FCD0094360CF4DE6BDD3C9F40531135164DACD6CB8770EECBFB7EE3DECF8438651D1FDE0D770217F8E9B06558B2B5C7AAEBA5CFA259FD957564E2D08D8EFDB57BFD9004706DB1DB3CA80D94C3DF68112EC3D24AE55CE69DC6B65FC16A961
+0AF23F4250D3C4F733217F8611F6B95E9202037273E7F2F0D547C1ECC17F21046150B4156C32330FED205AE3E3E470DC7040110E38ED13A53FE621204CDBC3E122E8B4D0E3F4B0112B95A6DD1431178E8A1686D80B098BF0625625BE6EE27BD30460556336D0D7BC94DB3B48C6181335FB4971C2DAE58505DA35D185FF5FA8E23E7C137F546A892D6CD76BBFC44642B28A84191A4138BFF5D950592B70E6EF63E93B85C4EC623E5821CC3D8E8FB47A2D6E83D38F922201342E8921D7D0137580C11D72C84B1ED7B352BFBE20BD8CC93BB034B054567AF4F0071AD7DCD17D93361C04AF8B84D7BB6D5E4BEEE4D839E6C36CFEFA48E60C863C7BCC425A38F639315BC2F2CA8A3E21604C5DEC5C6829611CE4696061FB493F5FA3BB79BF9536FA829F54C89D9A7102445805FD5CA674A03CB09BC164C21710C56B83AD9ECB0DE0A3C66783F66D81B3ED58A4C945C95FE499DF5AAEFBFBE9BBE95F35021CB4FC3A5F021AE9071081D023858285EC12836E8DC2F8DB0F32D4CAE410137D58A7EB6662314F50784090ACE1CF6866274C39DE4413104692971A4D6231CB5FF2CBFB11628470F321D19474C008B238B8D18905AF5B715374CC0C615BB995F4534B0D102F77A8ED615491733831A3D4797F6A2C8C4D55A918385630BB9F0DEF79B741D41150411A837B3CE37F0FE3C338365321B3D8E9D5B968F81B5CCBA9F0A0FAB3294AF69A26FF195E6CA30A65D7760D3F58F8FA3898451D6720E450CFFEC2B42DBEF24027597032108448765BFC91A044A4489097D61AD2BBDBF53EA2ECEB6E2ED013993882C8C17BAE34CBDF5DCDEF90DE9D99BE823ADFB11C3354ABF1C38093CA8D1D7A899056D4976109734F2A10ADF245B7A521660631DE743A08E3289F4C76E27FEE8905F4131243DBB2FF87D12E6D99C9C7C4EEEB1739A6DDDC2B5F6E1C0285ED719FF22F5C84DC7B6832CE6309E882D83AA11A268439B4EE9EF43CE859736961D44E4E5A835B89A862AF0D4E9DA9D729DEBCCCD10B400B90F866E52E4773A13C61A7C0BA0CDFEFF2B7093B6F2001284C430151B78854D458B4E1BE70E0E36AA18763915C640FE0CAC967C18D80237608D09686D82D4A6E12C8FB3543F3B273602AC23CAFA18C7E22CE5F987350302966DC839B6B139F377AE4698B2BCD8DEBC863DF2AE15D3BD25CF259241065E8F6BDA438968A315DD752B87A3ED115FC6E4A974F769040FA57F57B07AD4EE207CC14BCD03BDD273268385FCC5D17A1566FCC554DD86A47AB523516CAA85B0055E0C45CA7D34783C46B18F5108EE09C0D964B2C77CAC4F12BC4DF508D1BD5E22C3B38809DA7DAB81043B3C74D614D18D15B8A87ECFF2CE6249C7229EFD9250FFFD4FD0AF74CB64587AAD4E73DE38350F1CA029D0B6DFA0749A8D63F9054F40BE1DED953EED03F230DC653373F7883F96EBD
+91125F0A3CA0B4F0CF8D420944EF1A72ECC738D5479DCA93BE6203ED8D503FCED372936F0D6F65E6C69005486FE1416F8F845973CAB9CF48AC427A6BEF97AB516130D04527B03C78A8E0341BB6ADC4CC7F1EB54CC80AF1751E7AB09658818C57382B23767BF3B583F36F484D27869B2A21A00F266EB51BE8D9A65CE4AADDD2BD21E3F9CB1AFFBF7C8B63ED52AA417971E71974E34EF52F2D5FBA5846379EAA1F0B9EDEDADA8C1D80531F745590DADD404ECE7B16C7FEBF119B08AF8C9FFFB215FB8973FEC384BC698ADB2C1E1811BB9E32D2AE5F1040347B7F9B2EA84F4D4143CE6802BDC13775DF14FC0B051008C23149181B452549C2EB21129C60205BB722BEB2B4EE24692AB13A9F49934AF6C5D86E2F5A3F19B4B419FFDEAFDB9D4F27325901D72FDD5E933A33019ABF78FBC4F3EDEB699498399F75817515C53130E366037E4BF17B94383C8F3E14104599BF9B89F44BDB2E2F1C04DBE12E9960E1D24ABAD2DD60C25BAA35F3D662583820C02D7B72C1B99FC34A25F85C9BCD901ACCC625B42BE0DDA52A86FF98CCB1103A70E754A65A444B563A637D36C6F623CC44E46101E4FA7DD0F805636AB358B234525EABE20A4459391F049042AF5F407B27895DE2DF1F97E32B13904E4C7C6FD49A71D034E45871E3F42A4130BBD0DD3892A49E8D338AAF6F67838F123528A3DCC61595BF0D88A5F6C4FFD22E929EEC1103FAE8FA6BBF5038F23135763F7616F372072ECB30E35D15FD94E86C6253785E4DBE16EF6FEFD796EDB7C23466FB1ED9ABB2215075BDDCDB158FB92DC58B0941A8C3F7D915702681F62193B38C9F2FF22F2E22031D7CACFCDC186F515FA2767EB3776AFECBF431B4CBDA2CB2ACD8358D37F6022D01B2BD5D29403879C502033561DF5F9D2F6DD3FF97D922249B2FE4AC0A69EF68B59A1FCFC0C199998C7BD744042B3E608AC8F2F06EFBF4AAF6C76B23ACF9A678723C3C90C34E78B0FEDFA0FD25A3EC9323D2C82145D9E34B32E933290FF7128A0A297644F75E932D171F18A017300643BA93B64714586BA0131AE1785EAC6217C9CB28563F67B67A3ABD81B4490E8412B1B1127B30CCDED5AAC88AA0E24B422BB0BE15AE4749DD232BEC8B8F3F4B3AA001368515A7D62176FC8F427DCB2381630B155AEB99EB1BFB1378BE63631A3F8541C3604C54FD500D372BA2462579BA55D62BCE440A13D80C4BE790C08740EFCE74FD1DC795655B3773E6D14FE01577CB8407183522BBF053B3F816358226A98F89D828DCA13F73B3EAECB1606922BC2EE91B0A82EABF428E7DEFAE2D08D64BDFABAEB493F877266C6D7DBAE88B5F9494BCF9ACC2A476A3A36583ED7FE7080535EAE31C0C637C33E781C93A772E97DFFDF4086A72CECC682ECE085078FF520A6669F5951D50C88344F33B7DD9319FCC4BFF2F12F832B54C189F3875A0D7A1
+F5924A1E3F19451F136B10B523BA0FC0FE6FDB6A1660A2E2BCC89273CFDE8A26E8DA0FADEB47823EE9AD227ED06534D62A7CA354EC8A88A3722FC4596EC6E55DF1B2202FA26A93C43B84A8FE231D3E5228742E3BD0B05D7D58C1179C5D57E19DE6BC8AAB2D168767E522DEDD7A0D493FAA3AB4DF5A95B0C98886876A15408FC790D95B70CF755FF306AD3F96E98BD67E10A5B2DBA0EEE32E2D90587C3D58FE4954D1F72851F50A0C846074010EE301186EE452E832CBC79113346A3736933FF9381C96A1BD21646A58D44F4FDCE6728584DF7CA80C43EF5604E8EF8D735B93F2F99792BBC40C63B30651B15ACEEFC51ABC20E9BC3FDF515DEFADC3791999859223CD0528A32459B0F62A556CC5C4F7B0C984DCBDDAD260985005DB974853A4C6EDBE372CBD975F176F844CEA80328D2C42F89C95B142AF59A4EC0A258218A3A73B571D653E17F8201D87A14205CE078EB4802CF7378C2D0BD5F605E279F40656D9EA898DD686B81EF81FDA851FEC52CCC81D1B79E5EFB3DB8D3CE6D4D87D65C58F9D6AAF54271FE0FAABA89750786CFFA54AF7B7C2E90016B0548317FEF330A4001654FCB9F661001EC3F56FEAD81E6EC4C09A2EC3BED7DD8BD83B75AEAF6AD4587C19F2982792D5057E3D877935B221D125A909AE76C7B172812321A3C36A2F0361D5C432BFA1DEAF3D7F49D06D9779760ADEE163BCB123751E727C6EEF3D0CA4A64CB56FAECA4345FDDE3C94C92AA4859D5FCDF387F90C5CD8783BB2FBA135925C5608B481F53D445804D45351720E01053B6CBB0C12EB28B02C0066C45D81E8505F19556F2111CD91364D0F1E7CA0E0D7A43E2764696AEE73F8577C0434C0BEB808875EF1C94CD5BEFE5AC3219094FB87A2B9B10C1EB151EC1BC5C6A3B166A68604A18F0034100E82EE555A57FDA180D3D1EDA2D425EBA65A6447211181364E252CB5E7B6691D55A4574B603CCC8E1C7D48672A32F43CB9ADD0F3F83A1ECCBF7AA8C2173DDB1033DBF745E8301B6F1D804D6C6F6F0D1F4FC9848E52CD3516A73A11662A3253DF8530472E8D0653E29340F4D43846BC11197C4567ACC441C92EE69A80F8373817932A6958A7DDDD7489060088A82E7CC4AD041EEE2CB847234D85559D2DFE60DC5967B67E87B5C06A65061C68A52C2F0AABB2403432C4C0BF32FB171FBE95FDBDC85EA1EE639ACB36C692328B028D98E396FE7942B4C23C896F3B90B88E79E3B97833E6D058018854F1E887F79CB238FD6712E90FA2C3D63A91D53D218976ECC9D9F580BFA0966038AAE63B74E230115C30A964E36DB44D0DF7E1E07F061F5B227348B912904BBD764A03DB8BE51D9E8AAB1EF77720F8245AF7ECBE95E11FC3AC85D33D90F881D811B0EF9C15B7072ADBB5DE78330D98873770172AAD6AF98B03C78A79C44BA6078A077BC1444AB9EFA8472928A1BC0B3F9A
+1BD0CEC8FCC5188FE9BA453E003AE1DCD1697DF1F04E0966EF1A2990DF7CBAC572F318E5BC91E819A32AF778A51BD2910C07F0D6680AD22AC847A679ED6D4EFF10DB59B4142129E250A2AC7DC13D0C3F25797F11631E4898BCD06E5BD9436AA5C88FC1C8389A2E19F31A27773C44D233283C8A5F55EC91E8CC0783ECDB4FEED1DAFB05255D592606CFB55E159274105C5BDBE554154D8B35F6C026206363A7593722F681D3238478EC97A4D6694297CEE650DB861CC27915CDE0E4F3A47E7CA7170863B4C1538DCB8EEE1E8506E6D23F3F7D704EC7DB1B1B13AEB239D3B18C2CF9BB6289F6348BA419C81044F4A7FE79B2DD7BAA9160774C278CE076D433A691AD302C0372C9245736B59C2F2B06F90CE89A8598D708FA3A1289AE97FF6734D0F97C7E7062B334645EC0F9CE97DBB8C0E1D0A8242DE7271D1014F19383623704D3CD9437A8CEDA0FADBA14D36AA1BBF0D9E3BC7DFC4C80BFD00A1A291001E81750233BAC215B04482876A04E690EA6DB4700C5631B0E10AD7942C6940B5EBB118BF79E674E03210203D0E326209B8CFAB66799AD1BA6B00EC9CC0401E88D427E203ED7484DCB828A38AF11764E03B0AFDC50C5525B1D831ADB67467C482F78FB729BC6F75AF8C5CB83A27BE2AB967DF8DC30BCEEEC40396B7641716911FAA61E44B457D947D718FAE5FF6FA67385EA603588136BF88802D7169B06E02487C6325A706FA3607FEAF44B6F07DC55A6BAEAED79FD707AE9E0E22BE54221F3E103A05F999B2E843C940E900258DBAFA5583CF1B0727366A803E70C63016C9C675A268F28DF9FE702AB6C73D3D8220CAFDA91D30D9E9ACA02D5684F3FA1E3877FE174F7A55563149DD9E24EF2C8F39390BA384DE87BDA55F6FC2B1B05665909B43DF59DA4AD0B9F8E01E0AB7F3C8AB306F2846C3C8EF111A6EC230D487C6F73BFEEFA7D866DF0CB8C3378923AC8CA5D9E33A1101358AD9EF9E47AB766370246FCEA5E667651192AB95FB4CC6DB2A122AAB58CDD439A7EC83ADA8AD741854307AEF1BB54BB744738404C9D861CDE4E8A0EB5EC76C2BFC9B5E6C0E282495531A02F70578123693CEA1207DCC3AA8ADAC3B8173FED505B8D94D66E891B4D65587BFDA1DA297B04D01BE86B774A02C77FEC011FCEA51431ACC489FE6238A9EF9990E38C80FA3D4C45AA59D763198489B38AE5D5A9EF76A5954D5DA7DCB92D57B304E2058A52F3B9835FF02DC94CE1447B0AB5FF44592AA959EA7C3249D68D8138C341E95DC1F3623C9FB9C5511FE658FAC69C9F3920DD15BAE366CEBD18AFE201EED8D89DC35943B1CA6832C3A5581940E58F26C60EE94B561B5CDBA861F934D5ACAC4A7A9305E0E0984300FF203B76FFEF3C06F581CBE4EB185AB6F58ABF3442E27385E8CF93788906B201EEBC879820B538846552FE9536B77F9A00BD7069C33E18A61B
+E427B7E7534F742E6945F94F727B4510895700DCB6431EF5367C8D5A58FF93DDE35B05E8FB9083BB0615E4EC34AB1066151C68B2BBD374B050E91FDF76880E8C2A6E68538EFB8AAB310577ECC95D735E4B5E267E7196120B563F08E011A0444D7DDD72ECD100537738066369B599D2D016A8F4EA6BB8C85738E9A6F8291D16BCD2E1D36B90B39767FD447C2FB6C8D49376BC249612B6D4539F3DC453FB85FC1DA4348D2DBBA5CC771FC7F121B93E65B55DD2EF7D3EBABA1938758047F093433AEBC27935CEBC17CB23B2EC634A71CD0B34D2A8759A88EA9E7EFA8990D63D030DF7594B8973658B14CA0EFDEAA70CBE78DB6948D4C3CF821417C23D569B522088E63DCC60E706B443C23663C14463049B3B1EBC6E2B3AB7359F14D5404B5441A1B1830F490AE038DE4739837D4C0EB6B1977AF87AE42F7E68ECAF43A722D3813AFAFE1CBCB93EC96D8D164DB36FFC3C5B11FA5B47A780B1DFA5AD06AFD8A320B5C09ABA4C642042BC8B644ED82A283D70AF4BC413271ABDAA20CE0E98200D196F63ACC3A47250B2B6E338CAD68EBBCC3331D0B95FCCDC458C6D2CD0BABB613537A5AE9BB39F39E2A250FB21A8FB4337C6EBF76E7D71337A5AE10619ED3CC96A127FE1B7AEF308813C967E77803D610EC8BE708290A4C485FEF1F105B1798B14A09BDD8F360C339647C5AFB09EBCDEAE235378EB276F97535D573182222111044C1AB1D115D21316F315EAB2B37B38A3CB590615203D8BB6EBC6329F53BA95CEB624EE6C29E7318E572E8B4A372E4B133918B801B24920EFEE3BBD726FF694E57D9CE51B74C7D97E3BA3F7599DBD8E5B5E244E9978F89469357CB116936423250229A0533B5046769D2557B834D4693A70124AE3A7A4A3A9B2D0888C27BD3AEBBDF9C9BD4C0363CD24114382A1E346F7E140BE71B26620A55D729F14D90C00E95DD66AFA23F60731EE4256DEE9B14CD979CE2CF701AFA51C1E04AEA11635A9D8C96232A2965C70A6BE2AD66CD2A27E21931432F2998F20746D487AA99D0665DE63D146D755865F5FC30F059E2CD09B17D9AAC414F36F3D229A685F91048E966A21DC47B41D7FEE373A9C5D21BC0E3DF5C9C80D2F6192F07E86CEBE1A8485705E44F908AF2D1F3FFF23C8E4A1658346C89BE5ED38F34328DDDC4CAE74CE6533DF4A4894156955DA7F5D6CEA84E933C14688D0F62EEFA0E83449D5A06F34B6B528A63E1498036032796DF93553AC023BF301A795AD11CACDFE06C4494850D7DBC1E14427A1BDFA70AB32E36093060CBBCE8509C0696A4273E9C0301ABB986D363233216FDF58148B551112B20F244F7AE3370E8518A1962BCEC53EF6889FA077D3370AA00FFB9AE2FF0FC28899F1EF8ABB6720F9FA876568734EA18400090E860B58FD2554C5E2CC04FFF9DEC18AE800D6FBB5FCA17EFDA14A51806421B4AA20ABD5
+B56311801AAB5615A4161D7A76DF79AA43706DB7CB5F3309D1DFEF9BBD2677C71032AD9EABB6D57A4586EF10E7C1C337E4C218A827B5EDFEF353FF24EE7070D3616D987D5E19FB3D6F9747C9E60BBC2FD77B04565F9F184C422EB67F163B905B213E235930CE16540015B4D449366A62B98DCB8C231DE5AA5B5D5AE02DC819E05E1E880C86B1F63D7313B3749331C942DA5782DD76B5BC2E981FF0C36D2EAC739932BD80EDFFB8F3DC17242929F72E016FA2AB33D9A256799D239FA47C00D8300642BEB42A4B04F13EB919A5FBDAC51821F49C02849C5CAD06EE214D6807DF33F2F1D5AEC221E9A34E62FCB90E12660D96BE7ACA560993F26C546052BBA43BAEDB8608E1AC05DFD590A3645A18705BBBC6EFF0BC65AFA250A0622ACF523C320172390F5C936C9024E7C28CB9D5E17D7A8617E61994E9DB0DE93666BBCB658141FBA7AEFBFB8077E3AB6331D2D9F0A3F76208AC7ACF36B890AF1934E475AB59CA994F6798BEE43F4C6CBAD1CC96E5386EC505D0B66816BCC53D81C59244D857AD4B34328E72DA98326A18B7951A77E54B087EA1903039140750EFBE0A455AADDDAC3B7A7644642EFE8B6F90AA8AA490F33AE0F48351CA0CA7FA4A2DA7CF1B702EB81F05FB5A9494211BF574F4C660CFA347A7DB95AEEE43816C67014AE4C8D27D32ED89C65FF42734B278B5AA77FA918D64D78AC63D85DCEDC43B16405FF516EC438BD4F0F56EFAC569C6AB727BE3D768873EA3CB43DA0D9386D6404967BB9AA4C0B6578B464FF00583389975DF528D529D955DE8481BF55571F3893A33C29D516AEE36B7F88D83DB6711167F4A6B5681F5389EF94D2CC4EA21A6C8059629962D73C65469E9F57617880E765D16A6C509BAD885AC4C0596BE7014B614A541410F3F0863CA0963AB89424803DAA490CE95B6DFCCE56D55CA2EF8EAD5DC89502BAAEBC8CA365BC2E279F226EEC7397609D740A4C514C13D326A1CD308FC5920C6270B86BE6550DA39EFED220D4367EE94480D22AAB747AB007CC2EEDC0073F01028C3B9762940939FE8563C4D01AD8E6654C753A41C9818896B1BCB5320C400DD77F628C4398E7C4BF511B3197E2019828A9753FADFE66A9CAC1BE98E73D6AA9D230007022C383AD4229079B65F828F574D5F77BA7CFC89345AEE576645EF50DE669FF7C15B725A234061E007125B07AF98785CEB46543D340C369A4B969B00FC45A956BC3F1B981BF3A0EA0C32247D4BC1DF52DDFCEBFF60EE8EBB85F5B981D36129D1576C452263A22FCF231843C160B81904955FE0EC997ECC87653A186A2217BC582AD8A6B65C3980E15FCE4F97308474C44A5C30026F1AFA41630FF45805B0B213F5775AABBFFC01E2AB609073EB58DB6D158EB1CAA11762F5E150F2176B012ED225943A075F90B71357193F56F1A435859273CB9BBF8F441DB6C2FB8ADD97
+D6000059227239319CF58B24BB179A8EF8689A2EA82A953C08246CEE0CB7E4BE6E927BF56E7F483DF1EF0EEE902B0FA6AC4EE1C229E301D426BD863ECCA890A83EF9E37AC4D582D5F73B50D5152FBE9802CCDACECA5110C9D4B54A979D2A3C431BC6B0CBC5FDAC7702E94CC87CCDE35A54544CCD4CC89F382645E1C9DCE5FC10C12C9337C38C466E81B2C6AF7D604A845392F1969B9AFD54624569993E046E39DE6A94F3AE7D7C3433AB6F1AC1A73ABDD6676EA356C2F4720E7927025020A29C95FD5DE0D282CAA950EA5AA2FB9C84907507FF07848E0F3E2CCCC2620548199FE29709856A0F7F010621241A05FF17EE345F89C61378D3A4ABA769B3AFC030195F6F511EE0833FB084989FF38BB82F216746587DEFFFDDC046BDDE8C8C336D18832F66CA809E19718D82AFFC8C3AA25A2BD98BD0CE25FE1ABF92C3A2D67924334563A28DA16A00216695C1082E502AC83A353EBDEEF85519FCD10B0EFC4CBB126A9955B427357FBF1E10269796C0B3FAAEC6EDED53A14F5E6F22D40573FE647B023A9914D262525D46B6D70ED807B66C64806124683382E9441D40409D35AEAB5BE9B1060617CA855A0EBAB1AE9EABBA77388D920D46B2897E005BEE150354100686BC0362BF0931385E99E36B371A191D30BE356932480E847280D501EAD31117B7976E45BFF7E07CCB17C0AF32A96362F8B7CC2588C7AE6B99DAD0A718A5E777E26DD27FE85F523F5BAADF370E127774470CD74873497F9C3810B793688C40E37F2BF9E3D370AC3DE94BCB25D83DD8F59F4ADBD47C495293D44D2F3965EDFDC08654BE5316133440B5274AB782C2B42608429BA361DB1343F0A95D35D5F91739F15E1690F5BBBA10205F718FEC1D46985A6EC97345E7EDDC49501C5CAC7131B701916E7982AC4094A4CAC05EC1DC7181E9CFA29E0BB3C08B5467D20AA99C803558194198E996DF6511E76C8CF1254ECD377DEF4BC3A4698D4A8BFA9008F7A106CDC6BEF9449C394C5F217410EF46C2404820F244DB2CF84EE40256CD2D6E1482ADE14547EC77F29BE73D6132E2FE41C00FF29C915268A86A9EA01197F8CD75BF07C2B2EF10017D9DFFCC9D87C8A4135658999FEF317A20FD31F384C6FB0D700B188AB00991F39A1A23C45919C18D6FD344BBB8DE2E6D10710521CE9962A6DA61FC0EAC45FA5C670833499E4006ED9C728EF00A34D1F600FC34B9F81C135B34440B208321C30DCA56A8F1BC529D347C0F41AE3A59077DC00F382222C483E9BBF4198FCD68D039CD64DBF6B53E575D5BA664DC0AFA6B105408D954ACD677C4E07CBE164884D3A955A2DB0D62F38258A17DB0C12C39F7E6AE94AB8E3FE0C3B3E3E5900A566D3A296E8876A8FFC3AE6EEBA482870EA55BEBCA1750D6060E8669CD9846EF01C45AC229AAF52E3658898BA3483AFE3ED6788FFF031EA93C718E6E6B
+C6BEB40677B8888B384D106CB271AB11CDD16B946B09C005A6AA861DE9484CA2C2FC40418A9FA5F9D013D95E067A11E361A6D32937F1FAE059F1ABB9E8EFBDC79CFE50ADB30E789501FD141E1447FEEC596AC78B29DE693A284FBE658DCBDD9ABE14937F29F0BFD677E925CC518DB0B3E5B9BE9F509DF752547D750E3CD6907333198E0D4CC6A5CA53F468335130A80227E79A1F75EF0BC9F522127D262EB461BF9E06C511499FF16FE0DCB76CD819C496BD695A9546C03A176AE795B2BB85BC477A19D90DBADB61B32F6F7772DBF03C94FC8D77EE0FD47A03757CFE1B3705CC29EBD68D3FD78C2837830787424A7CADE4927B8CF4214C294D1A18EFEC097510CD7D8C2EB521EFF7DA174714B4376358E53CBBDC568EC1D2ABF1257DA001AB32B8B82154118B195CD5D0B1D836B415DCD9942413FC5057D7F377ED959F02EB7109C1C32DAC609E42CB1317E5FE41B0308D91EE43269FCF8A6FF1159AB957858F880E8BFC2ABCF567498B22265E762FA268F6528E04651292F47E1F1E740315D78D69BD86D497422080E18F4F241F8D08B1FA50A434C19FF3D2EA6FA8F4C90B0C1617A472A8007407F9AAA4DA4AD31DE7335EE0E850B27D16F146AB5B4ECF84ADE699D8D3CD76462297C87FF7825B3570A43084ECA07326C8F2F506BAAB00E3A167400A2B699078B208C2CA84D6E93E0DF113EB1EC38B9F8EA16DAEB74F845AEAEBD2C282F513F8268879B48BC8300BE0B7F342345D57FEB155A3E03B743689A2278D82AB28FF06F88532D86B7365961AC80FE1A956D9C59ECC9E7950A12B4085B634C23E89005C23FE90EAB3AF5B198EB5A18931B4683F02C9DCB5095D6563EF5FBDF2C27909166F772B541D91AC957CF7E25272D141B303FA56B8E89C97E7D65C2054176EF66923310B276F75D2B51A19C787CFC02C80F77351F8B2D78BECFB93CB973BF2A135395852B25569F16D531FDC8CC7244769F75BB83BD3114220C5FC1EACEE65330E3D7434B59913FE65F6656826E71412AAB14B5E52740C9362CAC807F88C93CD2F992773133B021FB3F4D49E894F29A914FF06666D98835E39A7AEC134A059400D69B1D6DB55D9ACA04250D236B5C8EED95992662C3B0237BEB7A61481684BD4CE790B21841E2BD06518138053B8CA27102B2701B5F1A0A71D34D95C34C7C5417603A1CC366B180C5D478926AA68E9D5B1C5379E63538D10F5A3D0F34AE8F5B267C656E35212D0450B1645EEDDF32E6972525F4D88BFE33D7E68D7D99A17EBE3BBBF166EB252D137B3E6D1508B07B89BFFF838361787DFF6C355B12B8E3F0E3FAC463B1B363EEF3D56D4DB4F1B947F960D5F3D8EB14A022DF7A6FDA621806D243934A7FA92BA4C9368A928E3C73FCB6F148829856176E046E5E80DAF2461DE9C0F7A343680EE345E49567B8583C1C76691B704629F444639BE32
+D9CD2B4DFCE88E08B83D5CB05DD07A880F44F180201DE5C938D591E27E5F9A0FE5F1B082396A7FC2EC4233FBC1D7904A83020CB8A715A48BFE79C74A451A7382D8E65E99CFEB38437E5F5CF51959FB57C53811FD42DA87A4453E46419C3DE3291DA66DE68D5D46BFEEA941E8EAAB5FC60220CACCB7BD439720BBE147E5C2EC5410F4DA9A8F83B6CD3CDA3406482EAA5C318A28E61885BC69640999D1C346311617ECA763DCD7AB15DA8920302D8203ED5E5209C1DABEDBADB87948634FEEA31A66DC4843B48AEC9FED2C03030466C1450A166109C92694055B92FE6DB60EC1F5CC53844C513151616871522C058ADBA8E6FEE3F900C39EBE8206C7D01C2860B3A7A743C756E0AFCD192F710C2955A12A22D69E6157E83B1C92627F83C10FC4289C0091BFFDE0311D70C4B1E6DA6339187BE4B03BE01C700DA6834E59EDD24145A0417C61B459BB7D8B9131B23035A9FECED49CC2935C454CA4E3DBC35B8825703BB1506D411430805BB6D3CC21C61D4E3484236A1A69B9F9EA5C3D37DB9C3CE1A630CB478EF89DFB8716687FDB2903CB5A3E81A8B977ACF2C38EC003BF71218C1652F583096A1796A002F8A88F2E30F6D46A699D63709B350B89DF0BF6B6147E5BEFED8E19BA079E8534DDCC075F7D5B271B1B52DA585480552DFCA7C3AA063DB5481D06B1B383065BE3495F4A96358C86661B85A4722D098EF5A59A135020034B6C2AE91A7143249DE316440AFA665F1BF248C408E767EF638BE9D81ACCA53F5CC375E1A65929270C4213A612654C8DA46F489F4D2D3EEEAEE271DF3348C9261FA20222A66D35C8E3361EF23B9E7038FA0DEC5C6A34E1D481D821E6F5FB8AC6679D94584F5FCC0A19E3AC3339131776C9DE9C659A2ACB1F37E713AC49C753051166F60F6C33B6878FE0C0BB13E97168AF1A46AA3D0E639B44643D5D85F4DAA1763BC21C6F8327595E0DFD34424F347407BEA97089C82E4D1FC101A2B0C9E95B6238960C9B16729CBD2371D00A8335CE28E423702D6175B0263ADB881A5BC121244616809F64C8863162824B08029B07F7DB0971B17465B44D3FB92F4E8B36B76C221D5C8B7A47D12BE788E2F0DCB43CC663D2EB027148D0E37914A0E1F9B9E229CB7D16B6C8E334B2B0F3B8CF44E427946A4C49D88936DD17103E37A5DBDDF0BD9D1711AD66C93F5D5E3E68C82589929997E1637C7038DDAB97C84ABCFA44BD41EBCC44F93F3C94B44719FE23E64A8B66D99CE105CE2AA0599288B44D3E00E2A9DB15C9DEBACEEB181CAEEE24D9D8934B38F3BDB4A6DC583DAE1EB45B9E155FD2E695F959471DC6B1EFA997925ED8C7A780D8A31A21749402C8C8D0DF32260904A56F83B6915157ECF512AB8C2CC46B6FE6FBC00FB1616F3D7616F604785F0DBE07019461B007D4D0421817C5BC466F965AB99ED7C0F19E159FFF7079B77473
+571AD051D3340C94B9D527AEB1FC205534C36A4CFC614A8BC64DF47635E9BDE7B237D9407517CAB327C957D5BD3902B2BC29325AE068A17F5C62C590D0B62014DE80A2C345DC10E530EB2B5F11E79C022CD8DFBA48D0B77FA25A800307C6EE385D736DEE9CE80508417198D9F8963B7C00613F7034E575E913CC1D2948ADFC6B53EDEA0C37E1906F02F5CABD743788B49D0BD072FF58FE3B739695F296AD298B4FB8684B451008516F670BFD1A8D5BC3F72588F24102CE49D07B0F1598C73CA8812F211898C89C67572CE7DF20B86F4E82EA89B1742CCC2AA2141E19E641A337668CBFFF2AC03ECEB074FD4AB32105839DAD0587B0E271D4D3C44D14D3D5E6F57D9F3A6F55D7A0A6FF35CF666FBC372F19A28C968ED8C0B38E2E3D85B95FDE8C120B33E032E90179D903D6ADD4CD749E33C76E63F115D87A5AFD4F0A5E4D9A85A66612A77398CB5FE193AE6ADC80D2349DE0551E3FE18040F75772270EB462A11C992A1C686F7B9F238580D5A301E737BD2D974B6C747A2526937E1317C9EE27B8ED5F0C750E601DB18E1D02B09960A531AE46E0BC826C0175772C84D997B0BFB43EE94D88737899C3C1E56F4FB790795F7DF8ECE23ABE644A53FA9F23BA651C8A4D5CF9CCC916B44CF3AEC653EEDD919086615E5CB0F73109358E18FBEB2636210E0728C09414BD9B6B47E81ED8BFCE7AB3665E9268312166E0E4ECC81CCDBB5570F49CD13AA8E7D8AC578C79ECD57EE7C74E41C1C9FC601FEA57367CD4DADA35EAAAE64D4E0CB76AE5AB2E70CF2ECB69F806E7DA256CB6700D4B976192E486BFB7E2493A2CB7C41B2EB1BDB1549CFC9F382063E8033503F5A35F330E86629C3516B7D949EF7AD24475366361D3266496317A907671F974F19D826C9AD3D5E0555916DCDAAFB31F71E639517544F5B8969A520E7F7D6DAA1D103E0FBC688F3941ABA6190CE749BBD2F5C6CA2AF1008914ACE2732A7BA67622A0182D2767696B0FF73BBC43B92FD2B6A4B5FC8F02700E0FABAED71D31A291969A4C2972FEE424FA74249763D405968BC3BBE87014FEA5FB108F3298B1F8F20C3779598B4A04E8EF489A472F85A44C983CE87A7D74EDD36021DA717CA26F092340A2E06BD28FA7431058D3F9140F218DAA45417F354790049FB70A5F0577253714123EA075B4FB4A73CD0B18432D1573AC1CDF776EAD96B775F60E02B37650B43C5F421D9FABE6E366CCD19C1D072A7BE884C26604B7DEF2BC7FB222B7F7CF5477AC9B176BD45C5A4989A7B7B4265902F92CCF4F9C2A30720F802E881C5AF1610D14CEEEC6F0729E3391E31445CB0381654A1A85F0A7EB6FDE8C9C8961050727032C97873BA22411D317D8A9983C8EE511382E722E6057346E576A95799BD4ACBFBBAB30B2FEE7595397E7C21AACE9BFF4ED0F96FFF5418EC3D89590ED4B9879FF8A7726FCE13C
+6D82F4E1EF22C36FD117C9FB3CD4679E8EC57E494C2A8585C6EF71F8620FDA4ED70E737D75B00F8A1E6B5D0C18B09F1250E63E648AB8A7CABA7A52575A14580068D9C5353734A20DD5FE12BE57D614AAF2E761A791ECC13C65E8599ACD3AA5EB461742540734D55FEE9D83D99D40ABF5F87873BBDD830D15817040A89B44BDB929AB7B03A3495B823E3A8B9B5F01AB8700AF64AFC353BE00EDE837DBAE4B57F50923719E5C98241F2B00D05B391F27DAA105D53DEACA2B191B687D708EF9420E48B7F3387A370967589E6EF88FA942DFF153E930685C74DB528EF0D9526123CDB6061A45A01C1188709E5DC070AAB18728A520D886ABCDA334C36F85D1B7330147913A7999499058B317BA40B81F82C37FD44CBEDDE4326A657815FC40BDCC8CB8468876443427372DF6113998536BE27CF011A76557534316A42489F37FB4A6CB6C67B18F07A17425E11569AF8D8353F330D30988195F757F59DB70CB7798B2206097B4F5D8C90E0D93E031201563E54D2438EBCE8185B608C08CBB9D4997952D8B931AAEBAB80DD50CEB93CE2E488C0E0D42E46D7A47E9A0497C370AAF2EE569F101F7987D3B416F92C2A4CA54F38681F08D5926174024D2C0018F6888A93CCDD8946E442843165A6A400210E7E3D6A2715445275E318AD641332F9C2902E445634210C9D98895A37CD6FEE4D2837B7D06A3DE0F85703FE3770E86C9E5C7B18B0C1BB5646C5A4EDDB30F3826DED536F4D18B228C879E3880BD721F6BCC89C38D979E136629D28D5B0E4B2584E7555AE155F254FD471E1B58C2E37207D571C233F26FC894A66DEDFB3FA8CB73FBBCB599A3E678C66C32F139A3AF1E6A7E0FBD5866DA1BFDE03254074D6D82380ACA1CB9C6A6279571232EF7A48C2F9E37988A91BC582E9F920BFD92241AC99688EF9571AFADC36A4534959EB029A86C467717D76ADAFE50C487BCA678F5550B9AFA209DC62CFDF6200B7448CD843B6FBF8FC47FC56891ECE47EF75CED916F4F04FE02842EB7F3FC5D48A9633E72893513C7E432C8577364DCE501E8EE91B68311F9F5A33BA6AC11F7E18C74AAF8E0B1B7BA0E85495C2CAEE5FD5963C0443E1A0993B34EE0142AFB517C384FC803E7BD19AC25F6D920A6EE6605E05AB6C56FD29AAFF96B0DB9E2BFB8B9544EE64622CD68E3861E777EF639EFF2B3677312992225BD25333D12D52B5BA67A1B7B5261B711DA577F2F2A4DC57665303A5BFCB2DBFCFCA44761A7C9C1F2E75F98926081EE92F739A73FC3DB60A8B4F792D3CF819CD7144BAC6B71651C5A0B87C3A7E73495952FC073902850F574E96248E086FD7461F0313DE47EA5D71660FDA5969254C6C51433FD9E64396864A1BE85A45B36DDA06F48C6A308EAC2A8EAE6037AF5C79041C598F7C890DAACCC614330F8BD840F5EE64F02DFC1315A2E5DB11F56FAEFF831C552
+503E1C994D027DD0D7F4273AD905C2B2D006F96B775E126361C09329FEF0EC1A73A1DA70953E9D43C1866DB6B80253340B99A311F84DC46943F46D8E9D92FE8DB7C7CDA990B5BFB82D193D3963F54D11CA32FEE41F352F5AA75968334C9FF37BA0F78B1D8E235B6303F05B45F82CE3C572FF5C13A559A413F4078760BE4C7F6837B0973A7DD93B7D75746E02BF0CAA0148CDECFDEDC37610E650B0498B654543AAC902A0D3A812FB4FE46B2EFC7AD0DF926C443D09F341D336560246F746A146CF73417E9D1A0BB57927C281026F859C23FCDC813E37A2B6166020CC4DA2E6289438B32190CB18ECB780B1282938625EE5E6957B6A9DC47F4405D74A0DE47EF6F1096FF9D193D2FAEA74F54927B38535CC08CD7A1602739A051F4DAA7D321C6D0A107CE402418A359713B694383A3C95C009AD95F9487DE83E4D65149BAF67D01656F3361CA02A55D2D346A73E984246C398913FA3A6D7D3818E49DF9FCEF7B715FFAA5BC86C61B8B4FACCB98D5FEA0156E929C4CEA9AE7646C59907A7B536E7243B4807F42482A618310F745BE12297B900D989CCF4800E8010AA4A69D8106082E4ED64E91F21F1A1700E136F6C85E43A29BD2DB38BAA5B8F261509C5D6692D228A3E5BE9883B1D3B2865A955EA42603FA842B9B777624ADBAE27A26683EC601BAA2375DAF9FFC0B609944B776B1BF9A5AFBEDD4B193799897393DC990F29D81A94B0FA0AFB0C118DE1766CED5744A72A0D9F0877D2F417BAB65520468D0E5BEE0DE204C675512FBB704D77A82F95DB6DEDC556E1028FFBC07C34C665E7F7C10E3342C9FC1DBAD943FCAE745AAFA074FF9C9D863C2F77F767B98E577C201C2E8286A0831C433021B902DCD6CCF3A0756070199BB052381F1B39CA3C1CE00471DDA68A0C18901DB41EC01AF95685BB402809CAE2D1D9D55B356024C31C815EDCB296C9EE4EC1218DE133DE39A7A8D968F9D91E7F73F9090E09C661A9AD073C01A1E688C37F73EE47D0AFBA6FEA196FBBCB9DACDE120FFF59AAC5DEA9E913500244B07A1845FE36E332C4ADC2FD0187323BEE0B9BE1AC76B21E42640F9F0DFC45F99426A850A76B7B83D415862F3F7A1CEC16BB1AD6DCF2E4D0D5A3AF6FB43CCF8A48B362F0D2A3C1CE90AF95AB5D14548264878ABE325CAA56DA5FEF0581C5B5F0D1D626481254A0D3104BCC2758FCE6EA708CD678F9A0C741C784BC3746F04AF43A4C5872E8D3F3910866FA521B46BD92AA76554B4974D82114DAA644148780DB5DF0CE79B6F99602AB6741649D82C242D526567CE84FEC8C8CD5E1A361F0F9DA60D037E604DE2200116479DF335D2731916BBB3A4C18F76ED045DBE217B4BA3F4404602620606FF258BF38DC16DF802C11AF2734E0F0195CA2B8BB3F610D78487256041CC5557F72BE956D6A9AF84E7E6C269446A5D6F31AFA72CC87929171
+5793272038CA8DA12F3D354AEB863BC9BA75B16EF4DC5A00FB6AAEB6CB2C646DEBC623326E66328CB2B7645DAF64FC00604A9495060B7967E9D9CB45B0F493B9FCFA6A715CB8C994961B07BDDA8BC1F22F15141B25A0AB02F237950C01301CBCCDAC05132F441A9AEB893526956DC7729AB7630A0605C053B21D421880E876EE69C97397FDE3E540B549D3287CD459415003AE2C99703AE69031350F23609C183053E7183FFD3C2CF57AAFE0360B31D824C3594E5102EB9722FFA537CC1DB025C5D2DD79F82E12E40FBB9DAF36437650FA47394250F689C1D189EC04F227A25D398BE3618E6E8CEAF2E8C5F02A9E1911A372E7BDB3C67DFD4B210DF9BC6492B839D1EE2AC34CBE2B14563AF92AAD36256F5C1DFF8FD5BE929C24B7CFBEEB35E40327B96864B0909C783A58B67230570C6BBFC18D5CF2980B2773DF5D70163C0A778921E4681DC282ECD9BDA4A3D985BA20DBA68925A119285ECEB0F256DEF86A957F38FB0495E58A9550C6B1458C8EAA035BFB877C185036B66B569AFA82259D9A41F35AEBA8A5D350ED02C1C9CA9E631974F9D8CE763CB27065575DA4E383982C30FA0D1F79D27E9C1589B96645231CBAC210ADC52E63A9DF8792883957B1BEF97D3B2EE75CF852FAC47F14A359EADF697CDC0C2C3A7CA42F96588925094C8A6AFA25E639A4E40A1A377375E1B45F864632858606F51EA41518448376AC7C333A9402AC8933D04817A399D08D0F603563FE4457518BFFB986B47AE5ACA643CD449CFA9779FC7A1E71BB45318C45426138F960091EE9F5B1C8BC88FFE650138DF8F86B15C14F200B111F4E11D0E77834973BD043DF55561E797092B9556AC799DF5DC78295C0B1AFD604962E146A75C3B78DE732299390A4FC3B48B9046E9BECEFC37242DC580775521EDC45D33DF30477DD95218549853E3A1224AB0AEF387E45BC20AAA802E598F70BD2422CAFFE0998038F074F6828418D79FD107FC8544C7D021A60C80C3B46618C43C2E1F91A2293488353ED55C06D600E2D88A52D7C71E394E0DE6E70BEFD240355539049A529232C00C455E068E8F1F8FBEA2BE1ABD53979CDAD42E8FA037D9842B2543420ED5979AAAC3D9B6D3228D286969329562D7D71F4F5ECC56ADD8B7C65A2359EDBC4FC0F351840B87F7371620E3190341DE40B3EDD15491638C0A1F3F5511385079616B85F62A143199BE854E66A8EB19882A558AC3AEECE5C042F2EE69F6EB65362A643768A3D788C02D7197714157561416AD449B5E393913362BBC4611C10A0575494E1A75A1B47A234D233BC7585AEC0E1AF5AA1EFF4342E68636C720D5A769695D4A68A44F1ABA80922E618B777685A8A28280EEEE42F7E39DC3C545E338B92B2797B4D50F6245E3FBDA2BCC253B3D433E543AAD1693FF2B21C43F0ABF9F2DDDCEF84A90C09CF03D28B68C125E43E0E
+2994FA59EE9FDE3BC18A2152BC86920101725DB3E29020180BB7E909BFF0D8B48C35329DC998AFC2BDB74256381F1AFF5C19DD8B47EDAA98D2197480DCA677FF01BE19C5590358CE6F29A3477B71602C35973D1EF3C3E7A5A41858318D2646AE8292F02FEBCF02B41F0E72F5F226E136571ECE008674BE86FFBA2AACC0F7417959F3D49933179D5077E75A917C7BCF0DE7E20238B1A94465046476AD8520E829FD9F2C5C5F4E74E7BC8CFB2841598238B68D0B98C1AC43561BC0DE10768016ED8DEF75F0F263466F5F374CE2DDEA2071411465D7F1D87CB17B038188D7CAC17107C699412F7DE117EAA8CF3ABC86A136E645D2EBF3D8B1F11FE72690A69D42F9662739E8601116058D361D347ECE34B8BF842F8DEB122CD9CFCF3053CD18884C509DD25082F4980F549A3972DD5AC80CF65CA373D645253CCFE7C096FACC3A6172DC1C89ECFF9F84EEC5EC08D1A2C6D25FDFA8A8D99E39B040B9BA2EE715DE91F98748F2E39BE6C6B3B4BD5FCD60DC40C198B71D2FAA940D46AA3987FB75328CC718B7550C9CED4A46FB4C02190773C4BBEA2F3C5A4CC1869508D17ED7EA423EAF3536A566F18EF03143509F85033B681EA1FE42D107C87E7E6B35E98046845099316FEA2BF6847CC8C3EBD1D5914BD623CC293404DA14025C33E2528AF781E5DEE6792462D7A7167C967CE7DAED6917C4FDD8C4C06349CAD816E272024078A5C13BCFD29AF6C53F1F65F9DE20A5609AC5DC1010D6F7994AE872EAECD9DE692600898FD8ABA9905B1876470F1D094CC7AD988C3EE8B6EA53A35B1982C6C7BEC93BE09F8DDCEE223A159F3FB41D5BAD722F4D637A919C601F97AE1CEE1CA91BB8C18C62A97635AA7CC6BD872405B77099E03B0E13BCF569DEF12B934936F3BC47567E344F6F95906EE55CA49E03EDF31A05B81CD7E284094AAD6B429FDCDC7E17701DBD4EF80576A6B29A8E45D1B9EA9120AAD2C5426D6DCE8998B320441D9C273F2B8DCB41EF5C3B1C789DD54B5CC734335C70E6A761A7EFA6C7B43C9BCBFF42AC6A49A2633CE34624F1F0ECD84E2AD3BC669744E9162AFC4088F9D5F3E4DE74599D2B3B95A27B459FA71944A59C78B51AC75329CCCC0A9859CDB717EE1CCE16EA02B40A600514D8B99F2990ECC08D1545E043C972058E08E6FC8ED25D0B9C0682BEA392A8B1C985B9A12B66FD707829AD7C67CC8B8E07E90098A553A06F973C911CF7AF754FBDB6084742EB2EECDE728180538C2B55F27D09B684E97006AFFEF1E017B600389F3E4C8D22D681D4F6C3C04CE0C2EB901304DF8BD886872229F0F88D08F57107D2A6D83AF5068D9823ECA37770B2E9D5FCF4FBF5EBB937D3EA648EC88BB35A958CEC8CAA16C3ECB572C66339FEF12C538EEBC4AAE7E523862D00B682E5C8C94CF87414BDF021A3F2F212E4D6C237F81A6BCDFD40E97F95897C33
+621BFD54220D5E5B9D8682945119B618A4A03B8D6FBD000C1FEB2D65A7961D8D0132102881F75A019583834DDBCD6069FCD2C209431A396EF9A6D9620EF9541DD925BBD07EB4B25CEBFBFB014077B96EAE7BB0BD6E3D7022F6A181C38B02B4E5D2B896F59D57658710314C3BCE3A3393866C37F92E4C8FE3C2DB6AFBB82D457078501986FBEAF69BDCEC9E132DDC5A6AF606F495F9FE94BD2901CF6418D75C8B7BF9257E1F5F87308DC4F7DA38C0AAF6F985F31D0E32568D3FE859AACC981BF33572C2559BF97350966C37060192414BD37757A9B263AD301EE7AE41650D97D9B484DFFFFF16BEEDC3052FAF3976F0017F26718D95AC4F7FA52C4313E935E8D3482AD1F0ED0D56318FFFA41BF6B9D36E88CC49A7713CB9C564CABAC7D0D7A87BA9FA8C9E6088B355C52CF0126EFEE518BADB0FC8E696B9CB3391B15B0CE03BC67B3433C9F8D3FA7061F69397AC080A007BEF7730A111CEC45FC65FA5D4AC3949D6EAA68AD120844D5B242E4CD3C9936391313D14A29943041C6BCACA671C4F75F62C1AB887AE9D4DFFCF318046D7F56E998CA2903C34480F0AE5570F662A1992F6D9DB024606922F3882D19691CF7E4C5D02B5A05857CCB8FB2FDD757AC71B39F73281B87080D7BCD53EDB3D3257D7FCBE665BA6048EC1582DF8303FA9E5374D206948F4BA37D619E4B2F5D6FF6D03B12CFB9EAD8B8A5A833C6638591B5DAC68082032E69931639EF955206AE9FD312AB9E0982DC81067FD7F7969DE8910DFB170799FAF5684B26A430C6AA957851A2E1855774FF176B21EC864BDEB5DAD5868C26818E9590A357AB4C520C95EA4E50FC2F14DBDF80625FA53B56939E379C19D19F9E0E456D9391619F6A39B71FAC9D0E1A370986F7E9B1E9B245C83113247D3FE80284676458E125BAF1299EA177A1F096997467F1CBE279CEB2E95F578BF8F6C491143E17550B5C56987B81CF15B6E38B74CC0A8367261436AB8449F5D3211D9257756AB05A237CF3335DA36AB4B1CC2827F45648EF2A048613596963F8C752E3BC4A184C03FB25152E0B67AC34E6919017EA897EF92C1C339D92B8760DA63F2DDE76E1EA3C6CA9970DD775FBB029335F4A8F4179F578AC8E1313724108DA65B5CFE5D3FC834B77808532E5AD1F85D7A254924E569ADD617F2CB4261A49450CD5E07A3A623EFADB92E2C6B00C6845F0C9CE4D45DD1BF1AC5F03B472734ECFBEC414567AA2BDC4EBC17C9B1441D4E16298E6FF19D417FB860482E939E2A0FEAE8299B20199F90B74D2DBC8ED743651FC05467243C50A300E746307D1957ADCBCC05147A1115663636F1C0F34AC56B702D2D9B9233F735D3BA6BF72F93DB087169EF5A327F9E76498AEFBB30A79567529F3462DDF1EC8371F22A43FCAA64B26BBA47EC1B1FEDF6B5A2B753A5B7E1C50B85D9191A611741846292CA7F1675F87B
+B383B4DC9749EB6A09CBDC412A990BC52F6DF20F9FF0EBB3E496121D437C48C291C8D2C248DB02D69DF918E1003C5225D6C665B7F8619941277901BA4F3B2CBFA9E63E632D8BDE01FB47629814B12EC45C43B28D5B0E773543423EA821C2C363E3BC22E13C850B2F02C220C5C7C219428B8ADD547B372122CA58ACE1694BA5B6989EF46B18CFE58EDA6A24CEF1B56427C79C0AB762C25CC1ECEED4977A765FFCD4DD26BF284757DDE1F6A785CD8AD94F6BF2CF846EB6D5FB8C9594877C38ADAC49BBFB94161E3F00904CBD656F406FC2081B9C7941349FD7E531358254C9B96A1CBD860D27271A78682E326B3BA9F1DE8527194A1C913D6151ECAF92B5079A1FB2DF92203FFFFABC9D7C753A7F368A30FC48F9A080A02003264544E0B11DF6510B210F57B9DC70B6A709F2E26C95AEE1A85E83DE4890FFD612A34294E34AB457905C98F61A3CDDAE51CA0C25807366B78C861A711F25E493DBAF49B6D2FBB2447B7F21D325CC7595B9FFD9DA958CC45C867484445DB9CD7919175C3CC658510C5941F85B06C7642609DE91C1C20261A3961CD9FD1541651A340BE73D998C941BF08FFA9971AC91FDCFB6FF0D1623C4F794BCD8198CEA5AAF6A584E4CD023918F39ED50AADCE9E92B133549C8C3A5AA604016C99750B877C269AE4BD91C6C28E6615D18AC9F2AA3A8DFC02CCA9502C977BDFEFFF6DE5B6F3C5C53B78364CBF5AB59405D357B9DAA8D1FB596E748BBF46A87667B326A81CCE05F4ED3D85D3B6CDFFC10AA44EDA757F009465228AD767A0E3E9BCCC76FADA69907671D190D9F298112C2AB0AC15B75308DF2C875127A5ECF9C03F2FF31AB0DDA517E949FC2E444D64DC73985BE1670B139D78F1E2982DA199FE858DC5F0805D079316F4577210094D747982AE87C5DFD3A488FDAF9689E104F3E6F7B12992F7EF38AB990AF1A6B890ED94E23BC31B49247D73FB579E99E6FBC77FBA0E24C58CAB706A347128ECD2F9EB14DF9F80944C74D609A317E2A95BDF8F6FD97719A0AC738C5277073CB9450E209E9EBE6E6EF1F2543A7C17A6DB69C22722A9A9D1960068B23A3F8A9FC8DD4081C364AF15E766C2064207AF4BE82B9A83A90B5E6F2AA32A34459169DFC522B95079E5091ECE30F5144075689B458D9524728FA4E635C4E1AE687CF832B4E00777DBE7F256CFD253ED04F5283C7490C1BCFAC258D2E317B9CED7487E0710131C7C8EB5CEC6C8CCBB34ECCB8FA18CE333847B8F44FF8CC9918CEB271BF247C043EE935A6F8368D2C480ADC17FA540C962A209EEA50996A437149F2B70CB4E94C546915779D6FB26BE35F98DED360D3A7A608DFCB3A3AFFA8103E8BD6BCDC5BA45F5BC454EAA15BF78A81C486B028D27843DA8242D332245E44B68E9E628EA9142BCF66FB63781740630BE4EFB67A98AF878731B98B10DA7ECEE2477171CC84CC
+8A93BD62DC49F4446FBD13E667236DEE247137AB8ADB2251104262206322127D3565DF00B68C9181C69752F1CD385AC012AE251E435F929CAB21B170DA5A9F70F079FF7DC7B9EB8C7936475A843BBE2F323FCDC60F617D77B05176758214EC2F0AD6B46B0E477E7952E02D7BC1244DCA150BB800FBA0D328193F8215CB61548ACDEA725802F21DF94967A2E7EBE19723B9536846AD4BF61662F65103049BE57C540073AB5EA49FAA26F0E22DEE70C8669E958D798C7E602B7FF0473B729616B1F269CD4D685009D8DDE09F053F3DECA69863E64F46EE84A6B4BE3850E3DD5CC7062F93440A781AEAD837EDCEEE81BFAC425A6C29088396384D605A59DF37131BEB9127DC74029F2C176CEF03215559F5F5E69FCD0B80F84AD40FEE835026217C9D06A723598CDB30E6618731D1058F69A3D2208F707C04449C4B197E397F1D3815F91473795A53A2EDE94B11062A4212257AD8046139BC192CBDADD3EFF8593BBEC0B63398BCB54D2F06EBF1B1D17D80AB27F0D515D047ECBC0EFE10E306FBC2819E890AFF870DB5F1A9C68D4DF3FD752EFEB5B2B3A5A8EFA4E7912ABDC264214F58C5213F6B8583E137A181E13963ACD78FAA055B488FC32E97E20A8B7173336482B7EBB419321A6AF004FC6E853DF0C554619CF9BBA5EE54394D8BD24DAFF32127CCDE1698F984B8D12BA3C1B95E543588FED66A7A3C2AC40E5ACA6E384EC27B6BE63016679146BCCABB4D785370EE5482BCF7031A68261E1FF60A46A3C14E026123DC55374AB36414F76CC7A344A9E5842FA707868409E39A9B2592548080528ED44D4481AC471D5FC3ABC2236721E93DAC2D9E0FA69BC337ACAB3A05429904F96C20F8A473A5D9FB02B1BE256A021A7F2D4713B2D993A330FC898472DAF991DE5C0C2A8B2B99BAB844A9BF4137E93728FF156376C5B8E6C509E8DBE9ED3EEC88058F4C326B7FC648BA8FA5BE8F7D7111A97E12A5DEADBD0A438CA0AE7157460B516188C03D9AF1217B28E807F8AEB4F2A98E41C1C51C0E015607AFBB616A498B681359B949720211E06E842F63DA1418AA523108C57282A4D751B50CDF06992E326F0824D5A568ADBA1D3C3DE4F289E1F2E4B6F9CA7B22CC7076087127D2A0C558CC6829494139F712B0E23F500F29F8F90CD315923239302AEFC6AAADA51AB3E5AA31BAB3DCF3DB816D1D0822C2BD8B4C1621C3DE18D3A7E661F6B33422275FBCE72EDD2A37E836A58EE39541147406EBB1CA965D81F973A95C0EB3078248215680C998E63917CB91E531EC466E7C8FDFB04F35DC8F57ECE244FFD076C097830282C9195F2DE88BDCFAC26888F71D66EB783C7DD75D22C75E26398973E2E9F2FA4615F3A74EFEA79F84C3AB28ADEC55AE10AFB7EB079D1FCED14F615926BC748CABE377A28C68A1F10690678FEA20687FB67E1ED9DB630340B280FBEE04
+EA8C573EAE7E0552008DE8D74E9CD000FAFCD3B916BD5A7661086BF84E989033CE2AC3EDC6BACA255A50FED01165860B3A41BB665657615162ADA1F3FBBC751EAF9A7D63E43A267B5F8630DB00D36D1D44007303429C70FA6924B359CA46732C1973BC884B62A24129A8B9152D52AFAD464CC9A6FB744D4C4C0557B2A13CA41D7BECC79056A4771D54E0AD9C81E9DA5BAA69F5917E970FF3B34425F883602D8E4F7DBC4C60DD21284D76834A3868936C9B454B59DFD968BC1333C9511D43F5901C4985A9E2C8C960FC7B46529635EFEDB296EB4BE47BCFF581E1AFB5A7D92DC7541D404CE60F4B154CE8088781D5A3E6E30FA44889F04DADE2D6C458D0E5F03E1345F90EC0FB5771CB520DC7926FC3E53697554BA1834BD7613D9649FD394B4A4137723B6D5DB4AC961382D489A8400DBEC7F5608F12ECE11A6BA5F4E245E39482FAC290733CA8BFF54E714A90151E983E667559A8179D94CD5BCF93E1AC4B29A9F6D73C49222E6387ACCB152F1EE7E847C57A322D319A6338BDEDDDC2C1FA0E5DCD7E74D826C93DB15C3A81181D177705D05DD6D59238A6C38DE153A50070938654B42475AE6EA9C004B1A7966C1A245C8678D2D04E6FABFBD93E029E368ADEA1059F0D9F257AE36FA9FDFB8473007596C6A12D245E0C76BF08506F84D0022BEF0A9453ECA437A930A6C64B36939597CCA6A35852281412D90099C3249BBECCE22A5762D855430748B6271A0BF52D235A91AB46C4CDF79E87067B4BE518CC356729DEAC7665A25B55891423A862CD37AC4526F6A385B1B87AB64ED10B4DBA674920DC604F4B670661B8EEFABDB80BA2A050FEABE18EFB39B7432F054AB5707C5248838321596C0B4EC919AEA12D5200E64EB7C6B617C6C723108E258C3DA28CB98710FDC02240A6088EBBFBBB800864FE7F91B8149F7A375B7E98311DE72DD74E2821A5522B8FD93671636223F991EA957E651A8EC81BEC610CAFC9C4A631C0D31575696E14079DDCAD1DC8FC2F5CD055C82433AC0863C27CED44CBA7A97B8B612EF56541313FB7D1D8DB8678667F0C238953D337A6F4D75AB5CE1720ACA6C0C4135C5E1970CE013EC342297130E13B9928AA6938FA49791180990979AFCEE0285DE1FEE5874A5BC28E575D75A4DBE27ABD9822D11990B1FB78B856281710EC4D09C3F6692665229B21848476C0812C81FDB9B4DD87960B602B2E9B88DD7570547F85E04CBACC3D0D266C62FEA0996FE90E0725EA41621263262B87D0F4B12D1C5BCEAE78EEB5DA0FE8072CC172A9A6AFA5A23B487B411B5ACB0E33BB5D64C49D0D0169225F35FAD604B11B94068AD7F7AD2BA2D196DE3FB9657B3105B91A13B5FC75CF4285EC8D5D690755547151FED04065D0FBCD94ABB257E6C9DCFE9CDA1E15D912F69821D3835B4319D91670863B5FB9E1D4FE65BC95D203DE91760D16
+3ACF89B2088E3549BB1E132924BA8950C51A634A51F4353A26EFBEC908870874B1D726DB5504D1AC9EE99025D843958DC98B92CB60C637CE02FB81D41DE19B19E8D1014A2523FCEF7AB652D6E8D7E7C6073373E44B92BB4E89999E23D706B4EE3CDE2B449E212D709A5A54EC6F9BECF219676DDF92ACA7F6FA92CFF2319BF0DEDEF5CE93C1820024706A1F291D2FA13DC130B47D890E173C1BA0F08D46923EA9CFF166E4F9EC9AE4C3F0853B5A5BC2C365DF9E04A2D5D061EFEB5554974DF44CB767CE3B4D76D0A87BBC35C4267FDFACA4CA8B2CC09129D8ED83D2E8CBF1F1044BA79B6BABB5F6B8C6AD67E00F47B2542D305CAEE4A45AF7A634E028A0F346616F7E40177E6F3EE125349641A91E2F86BA3BE1215F1FA738EE250E95C40570454A116CC958A3093C10910D43C1CC820D4F29354B5F1DA712B360FA95D136A1B836D3EDBDE0BA3EDC75878AC391E8D16E0874788CCAF52BDBD2AEB8DB2BB4472480196112F972797EB07C7678915FDD1C780C2F1D11BEDF38FA9F48F653FA8191180C51EE019583A067860390E8D2C8B2991EA56B691E47F964F60B8984138D53EEA8C4F57DBAAF09CBD9EE5267223F2E5431BAE5C07AF74ED0CDB5FDE69D8E49429340A1763A4C50480AEC75ED145CAFAC2FBED1C77BF984934589FEFC6DFC6EA659B57A5FA94ACFCECAC3E4B3E41015FC6973C8B45575D10E0DFCBF649200FC34697396CE5B03A5257ADB0CDDF03388A7E69566A600D7316D90095E2C7165B14AF53662494F093028E08BCD6137D8A1C0CC91238C0B461821B32013BAD542468725D0DEB8AF4EE6D4F900B19FF40310CDAE268F916C5822C3AB0174AED19C285BA9F356C040047C767BD6D23CDE98E3813C76E4E944E2EF297D282DF4B244CC0EEEF077B76506E065E11FECF2F583B40EA073F4528ED875B1C152C511EF10E658B4CB555C9201C3253AFE606E2CF986744D1C089EB202DB4FAEB12613F72470BDDFD50B4A852C09F8F970010FAA8509C46280BF728EFA8E52FABBA016F141EA356217D239C7E468D366791F2D71672CE39FA51A174E9F043D18BDAF6DC5B27713648B1799EDF34A964133F68BCC9EEE797484A55F61192389281178DF0D8A45804B87D53FCDD978
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+cleartomark
+ %endType1
+
+end
+
+%%EndFont
+bn
+bu fc
+{}mark T /Times-Bold /|______Times-Bold 0 rf
+bn
+108.70056 fz
+bu fc
+2 F /|______Times-Bold fnt
+bn
+(functional)show
+64 gr
+1050 1788 1171 2513 1 rc
+1138 1789 gm
+F 1 setTxMode
+(physiological)show
+0 gr
+pr
+2785 1502 pl
+2768 1572 pl
+2785 1572 pl
+2803 1572 pl
+2785 1502 pl
+1 ep
+pr
+2785 1706 pl
+2803 1636 pl
+2785 1636 pl
+2768 1636 pl
+2785 1706 pl
+1 ep
+2781 1568 gm
+2781 1632 lin
+64 gr
+2148 539 2747 1573 109 109 1 rr
+13 13 pen
+0 gr
+2148.5 539.5 2746.5 1572.5 118.5 118.5 0 rr
+64 gr
+2152 1630 2751 2664 106.5 106.5 1 rr
+0 gr
+2152.5 1630.5 2750.5 2663.5 118.5 118.5 0 rr
+64 gr
+2199 762 2274 1358 1 rc
+2257 763 gm
+F 1 setTxMode
+75 fz
+bu fc
+2 F /|______Helvetica-Bold fnt
+bn
+(neural encoding)show
+64 gr
+2313 581 2568 1531 1 rc
+8 8 pen
+0 gr
+2313 581 2568 1531 0 rc
+64 gr
+2413 779 2488 1325 1 rc
+2471 780 gm
+F 1 setTxMode
+0 fs
+bu fc
+2 F /|______Helvetica fnt
+bn
+(two-dimensional)show
+64 gr
+2475 708 2550 1421 1 rc
+2533 709 gm
+F 1 setTxMode
+(adaptive thresholding)show
+64 gr
+2628 653 2703 1503 1 rc
+2686 654 gm
+F 1 setTxMode
+3 fs
+bu fc
+2 F /|______Helvetica-BoldOblique fnt
+bn
+(neural activity pattern .)show
+64 gr
+2203 1840 2278 2436 1 rc
+2261 1841 gm
+F 1 setTxMode
+1 fs
+bu fc
+2 F /|______Helvetica-Bold fnt
+bn
+(neural encoding)show
+64 gr
+2312 1667 2572 2617 1 rc
+0 gr
+2312 1667 2572 2617 0 rc
+64 gr
+2629 1729 2704 2579 1 rc
+2687 1730 gm
+F 1 setTxMode
+3 fs
+bu fc
+2 F /|______Helvetica-BoldOblique fnt
+bn
+(neural activity pattern .)show
+64 gr
+2325 833 2400 1263 1 rc
+2383 834 gm
+F 1 setTxMode
+0 fs
+bu fc
+2 F /|______Helvetica fnt
+bn
+-3.88058 0.(compression)ashow
+64 gr
+2408 1767 2483 2546 1 rc
+2466 1768 gm
+F 1 setTxMode
+-3.02992 0.(inner haircell simulation)ashow
+F T cp
+%%Trailer
+cd
+end
+%%Pages: 1 0
+%%EOF
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/ReadMe	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,452 @@
+bin/ReadMe:  
+
+
+	    AN INTRODUCTION TO THE AUDITORY IMAGE MODEL
+
+This is the introduction for those wanting to use AIM to process waves
+once the software package has been compiled, installed and tested.
+The instructions for compiling and installing AIM are in the text file
+ReadMe.First in the top directory of the software package.
+
+
+CONTENTS
+
+I. Overview of Aim:   A description based on Patterson, Allerhand and
+Giguere (1995). It illustrates the instructions used to display waves
+and produce the auditory representations shown in Figures 2 and 3 of
+the paper.
+
+II. aimdemo_* Scripts:   A selection of demonstrations that illustrate
+the range of auditory representations produced by AIM. A complete list
+of demonstrations is contained in docs/aimDemonstrations.
+
+III. Overview of Documentation:   A brief description of the 
+documentation available and how to access it. This information is also
+available in docs/aimDocumentation.
+
+IV. Setting Up Paths for AIM and manaim: The modifications to pathnames
+required to make the AIM instructions and on-line help facilites
+available from all the user's directories.  This information is also
+available in docs/aimPaths.
+
+
+
+______________________________________________________________________
+
+I. OVERVIEW OF AIM (THE AUDITORY IMAGE MODEL)
+
+The Section presents a brief tour of the facilities in AIM based on a
+Letter to the Editor announcing the release of AIM in the Journal of
+the Acoustical Society of America (1995). It introduces the three
+auditory representations that AIM was originally developed to simulate
+-- basilar membrane motion (BMM), neural activty patterns (NAPs), and
+stabilised auditory images (SAIs).  It also introduces the main
+features of the software platform by example; they are the
+instructions and options that control the simulations and the displays
+that present the results.
+
+
+A. Time-Domain Modelling Of Peripheral Auditory Processing:
+	A Modular architecture and a Software Platform
+
+The text of the Letter is in PAG95.doc in aim/docs.  Figure 1 of the
+paper is a schematic of the architecture of the auditory image
+model. It was produced with a drawing package entirely separate from
+the AIM software package.  A postscript version of Figure 1 is
+contained in PAG95_F1.ps. It can be viewed with a postscript previewer
+like ghostview.
+
+The demonstrations are based on the wave for the word 'hat' which is
+stored in the file 'hat' with 'little-endian' byte order. (This is the
+order used in DEC, IBM, and SGI machines.)  A byte reversed version
+with 'big-endian' order is provided in 'hat_br'. (This is the order
+used in SUN, and HP machines.)
+
+For an automated tour type
+
+> aimdemo_hat	or
+> aimdemo_hat_br 
+
+depending on the byte order of your machine.
+
+
+Alternately, you can Execute the instructions individually on the
+command line.
+
+
+B. Displaying Waves Prior to Auditory Analysis:
+
+Waves can be displayed using the initial module of AIM, genwav.
+
+For a display of the complete hat file, use
+
+> genwav samplerate=22.05kHz top=2500 bottom=-2500 input=hat
+
+To restrict the display to the portion of the file with the 'hat'
+sound wave, use
+
+> genwav samplerate=22.05kHz start=110 leng=230 top=2500 bottom=-2500 input=hat
+
+For the BMMs in Figures 2a and 3a, and the NAPs in Figures 2b and 3b,
+we want to restrict the analysis AIM performs to a stationary segment
+of the vowel which is 32 ms in duration and which starts just before a
+glottal pulse. Such a segment can be displayed with 
+
+> genwav samplerate=22.05kHz start=182 leng=32 top=2500 bottom=-2500 input=hat
+
+
+C. The Three Main Auditory Representations Produced by AIM
+ 
+The remainder of this Section presents the AIM instructions used to
+convert the wave for the word 'hat' into the auditory representations
+of the sound presented in the individual panels of Figures 2 and 3 of
+the paper (BMMs, NAPs and auditory images).
+
+Figure 2: The functional version of AIM (panels a, b and c):
+
+a> genbmm samplerate=22.05kHz start=182 leng=32 top=600 bot=-600 input=hat
+
+b> gennap samplerate=22.05kHz start=182 leng=32 top=5000 input=hat
+
+c> gensai samplerate=22.05kHz start=112 leng=100 top=2000 napdecay=3 input=hat
+
+
+Figure 3: The physiological version of AIM (panels a, b and c):
+
+a> genbmm filter=tlf start=182 leng=32 samplerate=22.05kHz top=600 bot=-600 input=hat
+
+b> gennap compress=off transduction=med start=182 leng=32 samplerate=22.05kHz top=5000 input=hat
+
+c> The correlogram version of the auditory image is produced by
+generating a NAP of the sound, converting it into a correlogram with
+acgram, and then displaying it with the facilites in the auditory
+image module, gensai. The instruction sequence is as follows:
+
+> genasi filter=tlf compress=off transduction=med leng=100 samplerate=22.05kHz  output=on
+> acgram start=36ms wid=64ms lag=32ms norm=off frames=1 scale=.000002 hat.nap > hat_acg.sai
+> gensai -useprevious start=0 top=3000 input=hat_acg
+
+
+
+________________________________________________________________________
+
+II. AIMDEMO_* SCRIPTS
+
+The following is a list of demonstration scripts available to
+illustrate the operation of AIM and the different auditory
+representations that it produces. The scripts are stored in
+[aimdirectory]/scripts.
+
+The syntax for the demos can be obtained by typing 
+
+> aimdemo_???_??? help 
+
+where '???_???' is one of the extensions listed below.  The simplest
+way to begin is to copy the wave file "cegc" from the waves directory
+to the current working directory, and type 
+
+> aimdemo_tlf_all cegc
+
+NOTE: The byte order for cegc is "little endian" (used by DEC,
+IBM and SGI machines).  A byte reversed version with "big-endian"
+order is the wave "cegc_br". (This is the order used in SUN and HP
+machines.)
+
+The sound in cegc is a set of stationary and gliding click trains that
+play a lazy major triad (C-E-G) and its octave (C) over 2.1 sec.  The
+click train at the start (C) is a particularly useful test and demo
+stimulus. 
+
+Once one or two of the aimdemos have been shown to work with cegc, you
+should be in a position to try them on your own waves.
+
+
+
+I. The Funcional Version of AIM:
+
+
+1. aimdemo_gtf_all   <wave_file>
+   
+   This script illustrates all stages of the functional version of AIM
+   using the "auditory route". It focuses on landscape displays and
+   the instructions involved are:
+
+	       genwav (display input waveform), 
+               genstp (generate stapes velocity),
+               genbmm (generate basilar membrane motion),
+               gennap (generate neural activity pattern),
+               gensai (generate stabilized auditory image) and
+               genspl (generate spiral version of auditory image).  
+
+
+2. aimdemo_gtf_sai  <wave_file>
+
+   This script presents the wave in <wave_file> using genwav, and
+   then produces its rectangular auditory image using gensai. It is
+   the simplest auditory image demo.
+
+
+3. aimdemo_gtf_spectra   <wave_file>
+   
+   This script illustrates the functional version of AIM using the
+   "spectral route".  It focuses on spactral displays and the
+   instructions involved are:
+
+	       genwav (display input waveform), 
+               genasa (generate auditory spectral analysis), and
+               genepn (generate excitation pattern)
+
+
+4. aimdemo_gtf_2dat  <wave_file>
+
+   The script illustrates 2-dimensional adaptive-thresholding
+   (2D-AT) using genwav, genstp, genbmm and finally gennap. 
+
+
+
+II. The Physiological Version of AIM:
+
+
+1. aimdemo_tlf_all    <wave_file>
+ 
+   This demo script illustrates the entire physiological
+   version of AIM using the "auditory route".  It uses the
+   transmission-line filterbank (option filter=tlf) and the Meddis
+   neural transduction module (option transduction=Meddis).  The
+   instructions involved are:
+
+               genwav (display input waveform), 
+               genstp (generate stapes velocity),
+               genbmm (generate basilar membrane motion),
+               gennap (generate neural activity pattern),
+               acgram (generate autocorrelogram).
+
+   
+2. aimdemo_tlf_med  <wave_file>
+
+   The script illustrates the Meddis Haircell module.  The AIM
+   functions involved are genwav, genbmm and gennap.
+
+
+3. aimdemo_tlf_spectra   <wave_file>
+
+   This script illustrates the "spectral route" through the
+   physiological version of AIM.  It focuses on spectral displays and
+   the instructions involved are genwav, genasa and genepn.
+   
+
+4. aimdemo_tlf_lowhigh <wave_file>
+
+   This script illustrates the level dependancies in the physiological
+   version of AIM, and its ability to simulate cochlear damage. The
+   instructions involved are:
+
+   genwav [display input wave], 
+   genbmm [cochlea level = 30dB], 
+   genbmm [cochlea level = 90dB],
+   gennap [Normal cochlea + Meddis high spont-rate fibre] and
+   genasa [total OHC destruction, with no feedback]
+          Note: - very poor frequency resolution.
+
+
+
+________________________________________________________________________
+
+III. OVERVIEW OF DOCUMENTATION
+
+
+An introduction to the Documentation for the Auditory Image Model of
+Peripheral Auditory Processing
+
+
+A. Initial Contact Points and Aquisition of the Software Package
+
+
+1. WWW Page. 
+
+   Address:   http://www.mrc-apu.cam.ac.uk/aim/
+
+   An overview of AIM on the internet with facilities for acquiring
+   the software package. 
+
+
+2. Journal reference. 
+
+   The software package is described in a recent article entitled
+
+   "Time-domain modelling of peripheral auditory processing:
+	A modular architecture and a software platform"
+
+   by Roy D. Patterson and Mike H. Allerhand and Christian Giguere,
+   Journal of the Acoustical Society of America, 1995 (in press).
+
+   The text of the article is stored in  [aim]/docs/PAG95.doc
+
+
+3. ftp instructions:
+
+   The instructions for obtaining AIM by ftp are stored in
+   [aim]/docs/ftp.doc
+
+
+
+B. Installation and Test
+
+1. ReadMe.First
+
+   This document appears in top directory of aim when the aim.tar file is
+   unpacked.  It is the same file as that in the ftp directory
+   /pub/aim. It contains the instructions for compiling AIM, testing
+   the installation, and setting up paths to the instructions, the
+   aimtools, and the online documentation (manual pages accessed
+   through 'manaim').
+
+
+
+C. Introduction to the Operation of AIM
+
+
+1. bin/ReadMe
+
+   This is the initial ReadMe file for those wanting to use AIM once it
+   has been installed and tested. It begins with a guided tour of AIM and
+   then describes the user documentation and where to find it. 
+
+
+2. Introduction to AIM instructions:   docs/aimInstructions
+
+   An introduction to the instructions and command-line options used to
+   control the auditory model is stored in  docs/aimInstructions.
+   The instructions have the form gen???. The command 'gen -help | more'
+   lists the three letter combinations that may replace ??? and
+   briefly describes the operations they invoke.
+
+
+3. AIM on-line help:	gen??? -help
+
+   The instruction 'gen -help | more' lists the AIM instructions.
+
+   The instructions have the form 'gen??? -options <file_name>'.
+
+   The final three letters of the AIM instruction specify the point
+   in the system where the user chooses to observe the output.
+   Instructions of the form 'gen??? -help' cause AIM to list the
+   options that control AIM up to that output point along with a brief
+   description of the option and its current and default value.
+
+
+4. Manual pages for AIM instructions:	manaim gen???
+
+   The documentation for each instruction and its options is
+   provided in standard manual pages accessed by instructions of the
+   form 'manaim gen???'.  Begin with 'manaim genwav' which describes
+   non-auditory options such as those for the AIM display and for
+   the input and output files.
+
+   A complete listing of the AIM instructions is included in the listing
+   produced by the instruction 'manaim -k all | more'.
+
+   Manual pages can be printed with commands of the form
+   'manaim gen??? | lpr'.
+
+
+5. Manual pages for AIM tools:	 manaim <aimtool_name>
+
+   The software package includes a set of 'aimtools' for generating
+   and manipulating input waves, and for processing the multi-channel,
+   multi-frame output of AIM.
+
+   There are manual pages for the aimtools accessed by instructions of
+   the form 'manaim <aimtool_name>'.
+
+   A complete listing of the aimtools is included in the listing
+   produced by the instruction 'manaim -k all | more'.
+
+
+
+D. Additional Facilities
+
+
+1. Silent Options: 	docs/aimSilentOptions
+
+   AIM includes a number of 'silent options' that are occassionally
+   useful but not sufficiently important to warrant positions on the
+   options lists produced by the on-line help (gen??? -help).
+
+   A list of the silent options is provided in docs/aimSilentOptions
+
+
+2. File Formats: 	docs/aimFileFormats
+
+   A description of the layout of information in the output files
+   produced by AIM is presented in docs/aimFileFormats
+
+
+
+3. AIM list: 	mail aim@mrc-apu.cam.ac.uk
+
+   An email list for AIM users has been set up. The instructions for
+   joining and retiring from the mail list are presented in
+   docs/aimMailList. 
+
+   Note that the list is not moderated. It is a facility whereby users
+   can communicate for their mutual benefit rather than a question
+   answering facility provided by the software developers.
+
+
+
+______________________________________________________________________
+
+IV. SETTING UP PATHS FOR AIM AND MANAIM:
+
+
+As with all applications, the use of AIM is greatly assisted by the
+setting up of appropriate pathnames for the executables and on-line
+help.
+
+In the following ${DIR} is the pathname of the directory in which AIM is
+installed in your file system. For example this might be: /usr/local/aim
+
+
+A. Executables
+
+The executable files of the model, AIM tools and the script files are located
+in the ${DIR}/bin directory.
+
+If the path name is set to this directory, these programs can be executed 
+from anywhere in the system.  The best thing to do is to set the PATH 
+variable of the environment to: 
+
+	   setenv PATH ${DIR}/bin:$PATH
+
+This can be done in the .login, .profile or any other appropriate start-up
+script.
+
+
+B. Manual Pages:
+
+The `manaim' script prints AIM manual pages with appropriate name in the
+Unix man page format.
+
+If the user wishes to view the man pages through "xman", the
+environment variable MANPATH needs to be setup to search the
+[aim]/release/man directory along with the other default man
+directories.
+
+Add the directory which contains the AIM manual pages to the MANPATH
+in your environment, for example by including the following in your
+start-up script:
+
+	  setenv MANPATH ${DIR}/man:${MANPATH}
+
+or, if MANPATH is an undefined variable:
+
+	  setenv MANPATH ${DIR}/man
+
+
+For compatibility with systems which do not conventionally use a
+MANPATH, the pathname of the AIM pages directory must be the first
+pathname in the list.
+
+The AIM man pages will be appear in the "User Commands" section and
+the "Local" section of xman.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/ReadMe.First	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,325 @@
+				AIM R7
+
+The current release of AIM is R6.22. The appropriate files are README
+and aim.tar.Z.
+
+Sometime over the next few months a Letter to the Editor will appear
+in JASA announcing a software package for Time-Domain Modelling of
+Peripheral Auditory Processing. It is based on AIM Release 7 which
+will be released at the time the Letter to the Editor appears. There
+are no changes to the first two stages of AIM (the bmm and nap
+stages); improvements have been made to the third stage (sai) but they
+only affect exotic stimuli like damped and ramped sounds. Most users
+would not notice the differences.
+
+In preparation for the new release, we have set up a WWW page that
+directs readers to this file (ReadMe.First) and AIM R7. The release
+contains an alot of new documentation on all stages of AIM. We are
+setting the new system up now and so pieces of it may appear in this
+directory.
+
+The new release of AIM is R7.0. The appropriate files are ReadMe.First
+(this file) and aimR7.tar.Z.  You are welcome to take them, but the
+ReadMeFirst file may not describe AIM R7 correctly in all details at
+this point in time.
+
+============================================================================
+
+    		AUDITORY IMAGE MODEL (AIM) SOFTWARE PACKAGE
+
+	   	        Medical Research Council, 
+			Applied Psychology Unit
+			Cambridge,  CB2 2EF,  UK
+	     
+
+
+============================================================================
+
+This file contains:
+
+ 1. General information:
+        A. Disclaimer and copyright.
+        B. Acknowledgements.
+        C. Contact addresses.
+        D. Ftp instructions for obtaining the software.
+
+ 2. Getting started:
+        A. Installing the software [compilation].
+        B. Running the model.
+        C. Setting the environment variables PATH and the MANPATH.
+
+3.  Compiling the model - further details.
+        A. X11 libraries.
+        B. Alternative compilers.
+        C. A note on color workstations.
+
+4.  Next step after installing AIM.
+
+
+
+============================================================================
+ 1. GENERAL INFORMATION:
+============================================================================
+
+A. Disclaimer and Copyright
+
+Permission to use, copy, modify, and distribute the software described in
+this document without fee is hereby granted for research purposes, provided
+that this copyright notice appears in all copies and in all supporting
+documentation, and that the software is not redistributed for any fee
+(except for a nominal shipping charge). Anyone wanting to incorporate all or
+part of this software in a commercial product must obtain a license from the
+Medical Research Council.
+
+The MRC makes no representations about the suitability of the software
+described in this document for any purpose. It is provided `as is' without
+express or implied warranty.
+
+The MRC disclaims all warranties with regard to this software, including all
+implied warranties of merchantability and fitness.  In no event shall the
+MRC be liable for any special, indirect or consequential damages or any
+damages whatsoever resulting from loss of use, data or profits, whether in
+an action of contract, negligence or other tortious action, arising out of
+or in connection with the use or performance of this software. 
+
+
+============================================================================
+
+B. Acknowledgements
+
+The AIM software was developed for Unix workstations by John
+Holdsworth and Mike Allerhand of the MRC APU, under the direction of
+Roy Patterson. The physiological version of AIM was developed by
+Christian Giguere. The options handler is by Paul Manson. The revised
+SAI module is by Jay Datta. Michael Akeroyd extended the postscript
+facilites and developed the xreview routine for auditory image
+cartoons.
+
+The project was supported by the MRC and grants from the U.K. Defense
+Research Agency, Farnborough (Research Contract 2239); the EEC Esprit
+BR Porgramme, Project ACTS (3207); and the U.K. Hearing Research Trust.
+
+
+============================================================================
+
+C. Contact Addresses.
+
+    Roy D Patterson, Mike Allerhand, Michael Akeroyd, Jay Datta
+    MRC APU, 15 Chaucer Road, Cambridge CB2 2EF, England.
+    Phone    +44 1223 355294
+    Fax      +44 1223 359062
+
+    Christian Giguere 
+    email:   c.giguere@med.ruu.nl  
+
+ASSISTANCE:
+
+    email:   Mike.Allerhand@mrc-apu.cam.ac.uk   (Software support)
+	     Roy.Patterson@mrc-apu.cam.ac.uk    (Auditory modelling)
+	     Michael.Akeroyd@mrc-apu.cam.ac.uk  (Modelling and graphics)
+	     Jay.Datta@mrc-apu.cam.ac.uk	(Software and documentation)
+             c.giguere@med.ruu.nl  		(tlf, meddis, aimlinux)
+
+============================================================================
+
+D. ftp Instructionsu for Obtaining the Software
+
+Access to the APU site via ftp is by the address:
+ftp.mrc-apu.cam.ac.uk Use <Name>="anonymous" and <Password>=your email
+address.  Once inside the APU ftp system, cd to the AIM directory,
+pub/aim/.  The AIM software is in the compressed archive `aim.tar.Z'.
+The ReadMe.First file contains the text of this document. Copy both.
+
+For example:
+
+	ftp ftp.mrc-apu.cam.ac.uk
+
+	Name (mrc-apu.cam.ac.uk:you): anonymous
+	Password: your email address
+
+	cd pub/aim
+
+	get aim.tar.Z
+	get ReadMe.First
+
+
+Details of machine and address
+
+Name:    sirius.mrc-apu.cam.ac.uk
+Address:  192.18.195.1
+Aliases:  dns0.mrc-apu.cam.ac.uk
+
+
+
+============================================================================
+ 2. GETTING STARTED:
+============================================================================
+
+A. Installing the Software
+
+It is best to make a new directory (e.g. aim) for the software. Put
+aim.tar.Z and ReadMe.First in the directory and unpack the source code 
+using the command:
+
+    zcat aim.tar.Z | tar xvf -
+
+The current directory should then contain a makefile and a set of
+subdirectories. Five of these contain the C source code for AIM
+(filter, glib, model, stitch, and wdf). The tools directory contains C
+code for ancillary routines to construct stimuli and process the
+multi-channel output that AIM produces. The man directory contains
+online manual pages available through MANPATH and the instruction
+'manaim'. The scripts directory contains guided tours of AIM in the
+form of scripts that also serve to test the installation and
+illustrate a typical mode of operation. The waves directory contains
+test waves demonstration waves including 'hat'. These sounds were all
+sampled at 20 kHz and each sample is a 2-byte word in little-endian
+order (i.e. Dec and PC order). The bytes need to be reversed for
+Sun, HP and SGI machines. The bin directory contains executable routines
+and links to executable routines produced by the compilation.
+
+
+Compile the source code using
+
+      make  <machine>
+
+where: <machine> = decstation | vax | sun | sungcc | hp | linux  
+(For other options see: "Compiling the model - further details")
+The file `gen' is the AIM program itself.
+
+
+============================================================================
+
+B. Running the model.
+
+
+To verify that AIM is operational, move to the bin directory and type:
+
+      gen -help
+
+This should print general usage information on the standard output.
+
+
+============================================================================
+
+C. Setting Up the Environment Variables PATH and MANPATH.
+
+
+The software is now ready. Before setting off, however, we recommend
+that you
+
+a) Set your PATH to include [aim_directory]/bin     
+		(instructions in docs/aimPaths)
+b) Set your MANPATH to include [aim_directory]/man  
+		(instructions in docs/aimPaths)
+
+
+
+============================================================================
+ 3.  COMPILING THE MODEL - FURTHER DETAILS.
+============================================================================
+
+In the root directory, the command "make help" prints a list of the
+targets and parameters for compilation.  The machine-specific details
+refer only to the location of the X11 libraries and header files on
+the target machine.
+
+
+============================================================================
+
+A. X11 Libraries
+
+The AIM graphics library is based upon X11, and the library (libX11.a) and
+included header files (X11/X.h and X11/Xlib.h) are expected to be in
+standard places. The command "make <machine>" assigns the paths usually used
+on the particular machine.
+
+For example, the command
+
+      make decstation
+
+assigns paths so that the following files are expected:
+
+      /usr/lib/libX11.a
+      /usr/include/X11/X.h
+      /usr/include/X11/Xlib.h
+
+If the X11 library and header files are in non-standard directories,
+then the path for the directories can be given to the root makefile
+using the parameters X11DIR (for the directory containing the files
+files X11/X.h and X11/Xlib.h) and X11LIB (for the directory containing the
+library libX11.a). These parameters override the default parameters assigned
+for a particular machine.
+For example decstation paths could also be assigned using:-
+
+      make X11DIR=/usr/include  X11LIB=/usr/lib  [<machine>]
+
+sun paths could also be assigned using:-
+
+      make X11DIR=/usr/openwin/include  X11LIB=/usr/lib  [<machine>]
+
+To see what the internal defaults are for a particular machine, type:
+
+      make  TARGET=help  <machine>
+
+This prints a complete list of the makefile targets, arguments, and defaults
+on the standard output. The values of the arguments X11DIR and X11LIB are
+the default paths associated with the specified machine.
+
+
+============================================================================
+
+B. Alternative compilers
+
+The default compiler is the traditional C compiler cc.
+Alternative compilers can be specified by giving the name of the compiler to
+the root makefile, (assuming it exists in the current path).
+For example, the GNU Project C compiler, gcc, is specified as follows,
+(including it's -ansi flag, for compatability with ansi cc):
+
+      make CC=gcc CFLAGS="-O -ansi"  <machine>
+
+We find following produces code which runs significantly faster that the
+traditional cc compiler:
+
+      make CC=gcc CFLAGS=-O2  <machine>
+
+
+============================================================================
+
+C. A Note on Color Workstations
+
+The AIM software X11 interface is designed for monochrome screens, and
+not for multiplane color screens.  The software will run on a color
+screen, except that when bitmaps are created they are the same depth
+as the screen, since they are exact copies of the screen memory.
+This also happens, for example, when the "animate" option is on, or
+when the "xreview" program is used. The symptoms are a very slow
+response time, and huge bitmap files.
+
+There is a hidden option "mono=on" (short for "monochrome") which
+forces the bitmap to be a single plane of the screen memory.  By
+default, it copies plane 1; if this does not work, the plane can be
+varied with the hidden option "planemask=<integer>".
+
+Any queries to: <Mike.Allerhand@mrc-apu.cam.ac.uk>
+
+
+
+============================================================================
+ 4.  Next step after installing AIM.
+============================================================================
+
+
+When the installation is complete go to the 'bin' directory. It
+contains the compiled programs and the user ReadMe file which is the
+start point for the user documentation. bin/ReadMe provides an
+overview of AIM, a set of demonstrations, an overview of the AIM
+documentation, and PATH information.
+
+
+ 
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/aimBibliography	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,329 @@
+aimBibliography
+
+			AIM BIBLIOGRAPHY
+
+A listing of papers that have appeared in papers involving AIM and its
+antecedents. Where there are multiple papers for one author, the
+papers are ordered firstly by year of publication and secondly by the
+names of the second and succeeding authors, as this format seems to
+facilitate retrieval.
+
+
+Aertsen, A. M. J. H. and P. I. M. Johannesma (1980). "Spectro-
+   temporal receptive fields of auditory neurons in the
+   grassfrog," I. Characterisation of tonal and natural stimuli.
+   Biol. Cybern. 38, 223-234.
+
+Akeroyd, M.A. and Patterson, R.D. (1995). "Discrimination of wideband
+   noises modulated by a temporally asymmetric function,"
+   J. Acoust. Soc. Am. (revision submitted May 95).
+
+Allerhand, M., Butterfield, S., Cutler, R. and Patterson, R.D. (1992).
+   "Assessing syllable strength via an auditory model," In Proceedings
+   of the Institute of Acoustics, Vol. 14, Part 6 , 297-304.
+
+Allerhand, M. and Patterson, R. (1992).  "Correlograms and auditory
+   images," In Proceedings of the Institute of Acoustics, Vol. 14, Part
+   6, 281-288.
+
+Anderson, T.R. and Patterson, R.D. (1994). "Speaker recognition with
+   the auditory image model and self-organising feature maps: A
+   comparison with traditional techniques," In: Proc. ESCA meeting on
+   Speaker recognition, identification and verification. Martigny,
+   Switzerland.
+
+Assman, P.F. & Summerfield, A.Q. (1989) "Modeling the perception of
+   concurrent vowels: Vowels with the same fundamental frequency,"
+   J. Acoust. Soc. Am. 85, 327-338.
+ 
+Assman, P. F. and Q. Summerfield (1990). "Modelling the perception of
+   concurrent vowels: Vowels with different fundamental frequencies,"
+   J. Acoust. Soc. Am. 88, 680-697.
+
+Boer, E. de and de Jongh, H. R. (1978). "On cochlear encoding:
+   potentialities and limitations of the reverse-correlation
+   technique," J. Acoust. Soc. Am. 63, 115-135.
+
+Bregman, A.S. (1990). Auditory scene analysis. MIT Press, Cambridge
+   MA.
+
+Brown, G.J. and Cooke, M. (1994). "Computational auditory scene
+   analysis," Computer Speech and Language 8, 297-336.
+
+Carney, L.H. and Yin, C.T. (1988) "Temporal coding of resonances
+   by low-frequency auditory nerve fibers: Single fibre responses
+   and a population model," J. Neurophysiology, 60, 1653-1677.
+
+de Cheveigne, A. (1993). "Separation of concurrent harmonic sounds:
+   Fundamental frequency estimation and a time-domain cancellation
+   model of auditory processing," J. Acoust. Soc. Am. 93, 3271-3290.
+ 
+Cooke, M.P. (1993). Modelling Auditory Processing and Organisation,
+   Cambridge University Press.
+
+Duifhuis, H., Willems, L.F., and Sluyter, R.J. (1982) "Measurement of
+   pitch in speech: an implementation of Goldstein's theory of pitch
+   perception," J. Acoust. Soc. Am. 71, 1568-1580.
+
+Giguere, C., Woodland, P.C., and Robinson, A.J. (1993). "Application
+   of an auditory model to the computer simulation of hearing
+   impairment: Preliminary results," Can. Acoust.  21, 135-136.
+
+Giguere, C., and Woodland, P.C. (1994a). "A computational model of the
+   auditory periphery for speech and hearing research. I. Ascending
+   path," J. Acoust. Soc. Am. 95, 331-342.
+
+Giguere, C., and Woodland, P.C. (1994b). "A computational model of the
+   auditory periphery for speech and hearing research. II: Descending
+   paths,'' J. Acoust. Soc. Am.  95, 343-349.
+
+Giguere, C., Kunov, H., and Smoorenburg, G.F. (1995). "Computational
+   modelling of psycho-acoustic combination tones and
+   distortion-product otoacoustic emissions," 15th Int. Cong. on
+   Acoustics, Trondheim (Norway), 26-30 June.
+
+Glasberg, B. R. and B. C. J. Moore (1990). "Derivation of auditory
+   filter shapes from notched-noise data," Hearing Research, 47,
+   103-138.
+
+Goldstein, J.L. (1973) "An optimum processor theory for the central
+   formation of the pitch of complex tones," J. Acoust. Soc. Am. 54,
+   1496-1516.
+
+Green, D. M. (1988). Profile Analysis: auditory intensity
+   discrimination, Oxford University Press, New York.
+
+Greenwood, D.D. (1961) "Critical bandwidth and the frequency
+   coordinates of the basilar membrane," J. Acoust. Soc. Am. 33,
+   1344-1356.
+
+Greenwood, D. D. (1990). "A cochlear frequency-position function
+   for several species - 29 years later," J. Acoust. Soc. Am. 87,
+   2592-2605.
+
+Henning, G.B. (1967) "Frequency discrimination in noise," J. Acoust. 
+   Soc. Am. 41, 774-777.
+
+Holdsworth, J. (1990). "Two-Dimensional adaptive thresholding,"
+   Annex 4 of AAM-HAP Report 1 (APU Contract Report). (The basic paper
+   on 2D-AT that never managed to get published).
+
+Holdsworth, J.W., and Patterson, R.D. (1991).  "Analysis of
+   waveforms," UK Patent No. GB 2-234-078-A (23.1.91). London: UK
+   Patent Office.
+
+Holdsworth, J., Nimmo-Smith, I., Patterson, R.D. and Rice, P. (1988).
+   Annex C of "Spiral Vos Final Report, Part A: The Auditory
+   Filterbank," APU report 2341. (For historical interest.)
+
+Irino, T. and Patterson, R.D. (1995). "Temporal asymmetry in the
+   auditory system," J. Acoust. Soc. Am. (revised manuscript submitted
+   June 95).
+
+Licklider, J. C. R. (1951). "A duplex theory of pitch perception,"
+   Experientia, 7, 128-133. Reprinted in E. D. Schubert (ed.),
+   Psychological Acoustics. Stroudsburg, P. A., Dowden,
+   Hutchinson and Ross Inc. (1979).
+
+Lutman, M.E. and Martin, A.M. (1979). "Development of an
+   electroacoustic analogue model of the middle ear and acoustic
+   reflex," J. Sound. Vib. 64, 133-157.
+
+Lyon, R.F. (1982). "A computational model of filtering,
+   detection, and compression in the cochlea," In: Proc. IEEE Int.
+   Conf. Acoust., Speech Signal Processing. Paris, France.
+
+Lyon, R.F. (1984). "Computational models of neural auditory
+   processing," In: Proc. IEEE Int. Conf. Acoust. Speech Signal
+   Processing. San Diego, CA. March 1984.
+
+McKeown, D. and Patterson, R.D. (1995). "The time course of auditory
+   segregation: concurrant vowels that vary in duration,"
+   J. Acoust. Soc. Am. (in press).
+
+Meddis, R. (1986). "Simulation of mechanical to neural transduction in
+   the auditory receptor," J. Acoust. Soc. Am. 79, 702-711.
+
+Meddis, R. (1988). "Simulation of auditory-neural transduction:
+   Further studies," J. Acoust. Soc. Am. 83, 1056-1063.
+
+Meddis, R., Hewitt, M. and Shackleton, T. (1990). "Implementation
+   details of a computational model of the inner-haircell/
+   auditory-nerve synapse," J. Acoust. Soc. Am. 87, 1813-1816.
+
+Meddis, R. and M. J. Hewitt (1991a). "Virtual pitch and phase
+   sensitivity of a computer model of the auditory periphery: I
+   pitch identification," J. Acoust. Soc. Am.  89, 2866-82.
+
+Meddis, R. and M. J. Hewitt (1991b). "Virtual pitch and phase
+   sensitivity of a computer model of the auditory periphery: II
+   phase sensitivity," J. Acoust. Soc. Am. 89, 2883-94.
+
+Meddis, R. & Hewitt, M.J. (1992) "Modeling the identification of
+   concurrent vowels with different fundamental frequencies,"
+   J. Acoust. Soc. Am. 91, 233-245.
+
+Moore, B.C.J. (1989). An introduction to the psychology of
+   hearing. Academic Press, London.
+
+Moore, B.C.J and Glasberg, B.R. (1983), "Suggested formulae for
+   calculating auditory filter bandwidths and excitiation patterns,"
+   J. Acoust. Soc. Am. 74, 750-753.
+
+Patuzzi, R., and Robertson, D. (1988) "Tuning in the mammalian
+   cochlea," Physiological Reviews 68, 1009-1082.
+
+Patterson, R. D. (1974). "Auditory filter shape," J. Acoust. Soc. 
+   Am. 55, 802-809.
+
+Patterson, R. D. (1976). "Auditory filter shapes derived with
+   noise stimuli," J. Acoust. Soc. Am. 59, 640-654.
+
+Patterson, R.D., Nimmo-Smith, I., Weber, D.L., and Milroy, R. (1982).
+   "The deterioration of hearing with age: Frequency selectivity, the
+   critical ratio, the audiogram, and speech threshold," J. Acoust. 
+   Soc. Am. 72, 1788-1803.
+
+Patterson, R.D., Peters, R.W. & Milroy, R. (1983). "Threshold duration
+   for melodic pitch," In Hearing - Physiological bases and
+   psychophysics edited by R. Klinke & W. Hartmann (Springer:Berlin)
+   321-325.
+ 
+Patterson, R.D. (1986). "Spiral detection of periodicity and the
+   spiral form of musical scales,"  Psychology of Music 14, 44-61.
+
+Patterson, R. D. and B.C.J. Moore (1986). "Auditory filters and
+   excitation patterns as representations of frequency
+   resolution." In: Frequency Selectivity in Hearing. B.C.J.
+   Moore (Ed.), Academic Press, London. 123-177. 
+
+Patterson R.D. and Nimmo-Smith, I. (1986). "Thinning periodicity
+   detectors for modulated pulse streams,"  In B.C.J. Moore and
+   R.D. Patterson (Eds.)  Auditory Frequency Selectivity (NATO ASI
+   Series A: Life Sciences, Vol. 19), New York:Plenum, 299-307.
+
+Patterson, R.D. (1987a). "A pulse ribbon model of peripheral
+   auditory processing,"  In William A. Yost and Charles, S.
+   Watson, (Eds.) Auditory Processing of Complex Sounds.
+   Hillsdale, N.J., Erlbaum, 167-169.
+
+Patterson, R.D. (1987b). "A pulse ribbon model of monaural
+   phase perception,"  J. Acoust. Soc. Am. 82, 1560-1586.
+
+Patterson, R.D. (1988). "Timbre cues in monaural phase perception:
+   Distinguishing within-channel cues and between-channel cues,"  In
+   H. Duifhuis, J.W. Horst and H.P. (Eds.), Basic Issues in Hearing.
+   Proceedings of the 8th International Symposium on Hearing. London:
+   Academic Press, 351-358.
+
+Patterson, R.D., Nimmo-Smith, I., Holdsworth, J., and Rice, P. (1988).
+   "Spiral Vos Final Report, Part A: The Auditory Filterbank," APU
+   Contract Report (APU 2341). (Of historical interest for the
+   gammatone auditory filterbank.)
+
+Patterson R.D. and Cutler A. (1989). "Auditory preprocessing and
+   recognition of speech,"  In A.D. Baddeley and N.O. Bernsen (Ed.)
+   Research Directions in Cognitive Science 1, London:Erlbaum, 23-60.
+
+Patterson, R.D. & Hirahara, T. (1989). "HMM speech recognition using
+   DFT and auditory spectrograms," ATR HIP Technical Report 10.23.89.
+
+Patterson, R.D. (1990) "The tone height of multi-harmonic sounds," 
+  Music Perception 8, 203-214.  
+
+Patterson, R.D. and Holdsworth, J. (1993). "A functional model
+   of neural activity patterns and auditory images," In: Advances in
+   Speech, Hearing and Language Processing 3, W.A. Ainsworth (ed.),
+   JAI Press, London. (in press since 1991 but never seems to get to
+   the proof stage.)
+
+Patterson, R. D. and Holdsworth, J. (1990) "An introduction to
+   auditory sensation processing," Annex 1 of APU AAM-HAP Report 1.
+   (Of historical interest only. Now obsolete).
+
+Patterson, R.D., Robinson, K., Holdsworth, J., McKeown, D., Zhang,
+   C. and Allerhand M. (1992) "Complex sounds and auditory images,"
+   In: Auditory physiology and perception, Y Cazals, L. Demany,
+   K. Horner (eds), Pergamon, Oxford, 429-446.
+
+Patterson, R. D., Allerhand, M. H. and Holdsworth, J. (1992)
+   "Auditory representations of speech sounds," In Visual
+   representations of speech signals, Eds. Martin Cooke, Steve
+   Beet, and Malcolm Crawford, John Wiley & Sons, Chichester. 307-314.
+
+Patterson, R.D., Holdsworth, J. and Allerhand M. (1992). "Auditory
+   Models as preprocessors for speech recognition," In: The Auditory
+   Processing of Speech: From the auditory periphery to words,
+   M.E.H. Schouten (ed), Mouton de Gruyter, Berlin, 67-83.
+
+Patterson, R.D., Milroy, R. and Allerhand, M. (1993). "What is
+   the octave of a harmonically rich note?"  Contemporary Music Review
+   Vol. 9, Harwood, Switzerland, 69-81.
+
+Patterson, R.D. (1994a). "The sound of a sinusoid: Spectral models,"
+   J. Acoust. Soc. Am.  96, 1409-1418.
+
+Patterson, R.D. (1994b). "The sound of a sinusoid: Time-interval
+   models." J. Acoust. Soc. Am. 96, 1419-1428.
+
+Patterson, R.D., Anderson, T., and Allerhand, M. (1994). "The auditory
+   image model as a preprocessor for spoken language," in Proc. Third
+   ICSLP, Yokohama, Japan, 1395-1398.  
+
+Patterson, R.D. and Akeroyd, M. A. (1995). "Time-interval patterns and
+   sound quality," in: Advances in Hearing Research: Proceedings of
+   the 10th International Symposium on Hearing, G. Manley, G. Klump,
+   C. Koppl, H. Fastl, & H. Oeckinghaus, (Eds). World Scientific,
+   Singapore, (in press).
+
+Patterson, R.D., Allerhand, M., and Giguere, C., (1995). "Time-domain
+   modelling of peripheral auditory processing: A modular architecture
+   and a software platform," J. Acoust. Soc. Am. 98, (in press).
+
+Pickles, J. O. (1988) An introduction to the physiology of
+   hearing. Academic Press, London.
+
+Robinson, A., Holdsworth, J., Patterson, R.D., and Fallside, F (1990).
+   "A Comparison of Preprocessors for the Cambridge Recurrent Error
+   Propagation Network Speech Recognition System," ICSLP, Kobe, Japan,
+   1033-1036.
+
+Robinson, K.L. (1993). Studies in timbre and pitch. Doctoral
+   dissertation. Cambridge University.
+
+Robinson, K.L. & Patterson, R.D. (1995a) "The duration required to
+   identify the instrument, the octave, or the pitch-chroma of a
+   musical note," Music Perception (in press).
+
+Robinson, K.L. & Patterson, R.D. (1995b) "The stimulus duration required to
+   identify vowels, their octave, and their pitch-chroma,"  J. Acoust. Soc.
+   Am 98, (in press).
+
+Scheffers, M. T. M. (1983a). Sifting vowels: Auditory pitch analysis
+   and sound segregation. Doctoral dissertation. University of
+   Groningen, The Netherlands.
+
+Scheffers, M. T. M. (1983b). "Simulation of the auditory analysis of
+   pitch: An elaboration on the DWS meter," J. Acoust. Soc. Am. 74,
+   1716-1725.
+
+Schofield, D. (1985) "Visualisations of speech based on a model of the
+   peripheral auditory system," NPL Report DITC 62/85. (Of historical
+   interest for the gammatone auditory filterbank.)
+
+Slaney, M. and Lyon, R.F. (1990). "A perceptual pitch detector," in
+   Proc. IEEE Int. Conf. Acoust. Speech Signal Processing,
+   Albuquerque, New Mexico.
+
+Slaney, M. (1993). "An efficient implementation of the Patterson-
+   Holdsworth auditory filter bank," Apple Computer Technical Report
+   #35.
+
+Terhardt, E. (1987) "Psychophysics of audio signal processing and the
+   role of pitch in speech," In M.E.H. Schouten (Ed.) The
+   psychophysics of speech perception, Martinus Nijhoff:Leiden,
+   271-283.
+
+Zwicker, E. (1961). "Subdivision of the audible frequency range into
+   critical bands (frequenzgruppen),"  J. Acoust. Soc. Am. 33, 248.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/aimDemonstrations	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,131 @@
+aimDemonstrations
+
+The following is a list of demonstration scripts available to
+illustrate the operation of AIM and the different auditory
+representations that it produces. The scripts are stored in
+[aimdirectory]/scripts.
+
+The syntax for the demos can be obtained by typing 
+
+> aimdemo_???_??? help 
+
+where '???_???' is one of the extensions listed below.  The simplest
+way to begin is to copy the wave file "cegc" from the waves directory
+to the current working directory, and type 
+
+> aimdemo_gtf_all cegc
+
+NOTE: The byte order for cegc is "little endian" (used by DEC,
+IBM and SGI machines).  A byte reversed version with "big-endian"
+order is the wave "cegc_br". (This is the order used in SUN and HP
+machines.)
+
+The sound in cegc is a set of stationary and gliding click trains that
+play a lazy major triad (C-E-G) and its octave (C) over 2.1 sec.  The
+click train at the start (C) is a particularly useful test and demo
+stimulus. 
+
+Once one or two of the aimdemos have been shown to work with cegc, you
+should be in a position to try them on your own waves.
+
+
+
+I. The Funcional Version of AIM:
+
+
+1. aimdemo_gtf_all   <wave_file>
+   
+   This script illustrates all stages of the functional version of AIM
+   using the "auditory route". It focuses on landscape displays and
+   the instructions involved are:
+
+	       genwav (display input waveform), 
+               genstp (generate stapes velocity),
+               genbmm (generate basilar membrane motion),
+               gennap (generate neural activity pattern),
+               gensai (generate stabilized auditory image) and
+               genspl (generate spiral version of auditory image).  
+
+
+2. aimdemo_gtf_sai  <wave_file>
+
+   This script presents the wave in <wave_file> using genwav, and
+   then produces its rectangular auditory image using gensai. It is
+   the simplest auditory image demo.
+
+
+3. aimdemo_gtf_spectra   <wave_file>
+   
+   This script illustrates the functional version of AIM using the
+   "spectral route".  It focuses on spactral displays and the
+   instructions involved are:
+
+	       genwav (display input waveform), 
+               genasa (generate auditory spectral analysis), and
+               genepn (generate excitation pattern)
+
+
+4. aimdemo_gtf_2dat  <wave_file>
+
+   The script illustrates 2-dimensional adaptive-thresholding
+   (2D-AT) using genwav, genstp, genbmm and finally gennap. 
+
+
+
+II. The Physiological Version of AIM:
+
+
+1. aimdemo_tlf_all    <wave_file>
+ 
+   This demo script illustrates the entire physiological
+   version of AIM using the "auditory route".  It uses the
+   transmission-line filterbank (option filter=tlf) and the Meddis
+   neural transduction module (option transduction=Meddis).  The
+   instructions involved are:
+
+               genwav (display input waveform), 
+               genstp (generate stapes velocity),
+               genbmm (generate basilar membrane motion),
+               gennap (generate neural activity pattern),
+               acgram (generate autocorrelogram).
+
+   
+2. aimdemo_tlf_med  <wave_file>
+
+   The script illustrates the Meddis Haircell module.  The AIM
+   functions involved are genwav, genbmm and gennap.
+
+
+3. aimdemo_tlf_spectra   <wave_file>
+
+   This script illustrates the "spectral route" through the
+   physiological version of AIM.  It focuses on spectral displays and
+   the instructions involved are genwav, genasa and genepn.
+   
+
+4. aimdemo_tlf_lowhigh <wave_file>
+
+   This script illustrates the level dependancies in the physiological
+   version of AIM, and its ability to simulate cochlear damage. The
+   instructions involved are:
+
+   genwav [display input wave], 
+   genbmm [cochlea level = 30dB], 
+   genbmm [cochlea level = 90dB],
+   genbmm [total OHC destruction, cochlea level = 60dB],
+   gennap [Normal cochlea + Meddis high spont-rate fibre] and
+   genasa [total OHC destruction, with no feedback]
+          Note: - very poor frequency resolution.
+
+
+5. aimdemo_tlf_std  <wave_file>
+
+   The script illustrates the standard level outputs in the physiological
+   version of AIM.  It shows the simulations of a normal cochlea.
+   The AIM functions involved are:
+
+   genwav [display input wave],
+   genbmm [normal cochlea level = 60dB],
+   gennap [normal cochlea level = 60dB],
+   genasa [norma cochlea, without log compression].
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/aimDocList	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,40 @@
+The following is a structured listing of the aim documentation.
+
+It is assumed that the [aimDirectory] is named 'aim'.
+
+1. Directory	anonftp/pub/aim  (at APU)
+
+ReadMe.First dd	[Has warning to use R6.22 at top]
+
+
+2. Directory	aim/bin
+
+ReadMe dd
+
+
+3. Directory	aim/docs
+
+ReadMe.First dd ReadMe dd
+	 
+PAG95.doc dd	PAG95_F1.ps dd
+
+aimBibliography dd	aimPaths dd
+aimDocumentation dd	aimDemonstrations d
+aimInstructions 	aimSilentOptions 
+aimMailList dd		aimFileFormats
+
+aimdoc.structure dd
+
+
+4. Directory	aim/man
+
+genwav.amp dd	genwav.amp dd	genwav.amp dd
+genbmm.amp dd	gensgm.amp dd	genasa.amp dd
+gennap.amp dd	gencgm.amp dd	genepn.amp dd
+gensai.amp	
+genspl.amp	
+
+xreview.amp dd
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/aimDocumentation	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,144 @@
+docs/aimDocumentation
+
+
+		OVERVIEW OF AIM DOCUMENTATION
+
+
+An introduction to the Documentation for the Auditory Image Model of
+Peripheral Auditory Processing
+
+
+A. Initial Contact Points and Aquisition of the Software Package
+
+
+1. WWW Page. 
+
+   Address:   http://www.mrc-apu.cam.ac.uk/aim/
+
+   An overview of AIM on the internet with facilities for acquiring
+   the software package. The text is stored in aim_html/index.html.
+
+
+2. Journal reference. 
+
+   The software package is described in a recent article entitled
+
+   "Time-domain modelling of peripheral auditory processing:
+	A modular architecture and a software platform"
+
+   by Roy D. Patterson and Mike H. Allerhand and Christian Giguere,
+   Journal of the Acoustical Society of America, 98, 1995 (in press).
+
+   The text of the article is stored in  aim/docs/PAG95.doc
+
+
+3. ftp instructions:
+
+   The instructions for obtaining AIM by ftp are stored in
+   aim/docs/ftp.doc
+
+
+
+B. Installation and Test
+
+1. ReadMe.First
+
+   This document is in top directory of aim when the aim.tar file is
+   unpacked.  It contains the instructions for compiling AIM, testing
+   the installation, and setting up paths to the instructions, the
+   aimtools, and the online documentation (manual pages accessed
+   through 'manaim').
+
+
+
+C. Introduction to the Operation of AIM
+
+
+1. bin/ReadMe
+
+   This is the initial ReadMe file for those wanting to use AIM once it
+   has been installed and tested. It begins with a guided tour of AIM and
+   then describes the user documentation and where to find it. 
+
+
+2. Introduction to AIM instructions:   docs/aimInstructions
+
+   An introduction to the instructions and command-line options used to
+   control the auditory model is stored in  docs/aimInstructions.
+   The instructions have the form gen???. The command 'gen -help | more'
+   lists the three letter combinations that may replace ??? and
+   briefly describes the operations they invoke.
+
+
+3. AIM on-line help:	gen??? -help
+
+   The instruction 'gen -help | more' lists the AIM instructions.
+
+   The instructions have the form 'gen??? -options <file_name>'.
+
+   The final three letters of the AIM instruction specify the point
+   in the system where the user chooses to observe the output.
+   Instructions of the form 'gen??? -help' cause AIM to list the
+   options that control AIM up to that output point along with a brief
+   description of the option and its current and default value.
+
+
+4. Manual pages for AIM instructions:	manaim gen???
+
+   The documentation for each instruction and its options is
+   provided in standard manual pages accessed by instructions of the
+   form 'manaim gen???'.  Begin with 'manaim genwav' which describes
+   non-auditory options such as those for the AIM display and for
+   the input and output files.
+
+   A complete listing of the AIM instructions is included in the listing
+   produced by the instruction 'manaim -k all | more'.
+
+   Manual pages can be printed with commands of the form
+   'manaim gen??? | lpr'.
+
+
+5. Manual pages for AIM tools:	 manaim <aimtool_name>
+
+   The software package includes a set of 'aimtools' for generating
+   and manipulating input waves, and for processing the multi-channel,
+   multi-frame output of AIM.
+
+   There are manual pages for the aimtools accessed by instructions of
+   the form 'manaim <aimtool_name>'.
+
+   A complete listing of the aimtools is included in the listing
+   produced by the instruction 'manaim -k all | more'.
+
+
+
+D. Additional Facilities
+
+
+1. Silent Options: 	docs/aimSilentOptions
+
+   AIM includes a number of 'silent options' that are occassionally
+   useful but not sufficiently important to warrant positions on the
+   options lists produced by the on-line help (gen??? -help).
+
+   A list of the silent options is provided in docs/aimSilentOptions
+
+
+2. File Formats: 	docs/aimFileFormats
+
+   A description of the layout of information in the output files
+   produced by AIM is presented in docs/aimFileFormats
+
+
+
+3. AIM list: 	mail aim@mrc-apu.cam.ac.uk
+
+   An email list for AIM users has been set up. The instructions for
+   joining and retiring from the mail list are presented in
+   docs/aimMailList. 
+
+   Note that the list is not moderated. It is a facility whereby users
+   can communicate for their mutual benefit rather than a question
+   answering facility provided by the software developers.
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/aimFileFormats	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,166 @@
+
+
+Appendix C       Output File Formats
+
+This Appendix describes the format of output from the ASP modules, for
+users who wish to process this output with another program of their own.
+For example, gensai produces a stabilised auditory image which is suitable
+as input to a speech recognition system.  In most cases the output file
+will probably require an additional processing step before it may be used
+by another program.
+
+Each ASP module produces an output file in response to the -output option.
+These output files consist of a header (containing information concerning
+the makeup and history of the file) followed by a series of 16-bit data
+items which represent the actual data contained in the file.
+
+There are two obvious ways in which such a data file may be used as input
+to a user's own program; firstly, the user's program may be adapted to read
+and interpret the header of ASP output files before actually processing the
+data in them, and secondly, the header may be removed and the relevant
+information entered into the user's program manually before it proceeds to
+process the data section of the ASP output file.  The former of these
+techniques is preferable in many ways, providing consistency and insulating
+the user from the details of ASP headers, although it may require some
+effort to alter the user's program to correctly process these headers.  The
+second method may be preferable if the user is merely interested in testing
+the ASP software's suitability as a preprocessor for their program, or if
+the program in question cannot be altered (either because it was purchased
+from someone else, or because it would be too complicated to change it).
+
+The second method merely requires a reliable way to separate an ASP output
+file into header and data sections, and the user must then 'translate' the
+information in the header into the terms understood by the parameters of
+his/her program.  To this end, the ASP package includes two programs called
+head and tail which take an ASP output file as their argument and produce
+another file containing its header and data sections, respectively.  The
+header is adapted to resemble very closely an ASP module's options file,
+and ought to be easily understood by anyone familiar with the ASP modules
+and the way in which they are used.  As far as translation concepts from
+ASP to another program is concerned, we can only volunteer this
+documentation as a guide to the interpretation of each ASP option.
+
+The former of the two methods requires rather more detailed understanding
+of the output file structure, and this discussion will be divided into two
+parts, one on the header and the other on the data itself.
+
+Head and Tail
+
+For users who wish to remove the header part of an ASP output file, the
+software includes two programs called head and tail which take an ASP
+output file as their argument and produce another file containing its
+header and data sections, respectively.  The header is adapted to resemble
+very closely an ASP module's options file, and ought to be easily
+understood by anyone familiar with the ASP modules and the way in which
+they are used.  As far as translation of concepts from ASP to another
+program is concerned we can only volunteer this documentation as a guide to
+the interpretation of each ASP option.
+
+Whichever method the user chooses in combining ASP output files with their
+own programs, some information regarding the types and format of
+information in ASP output modules will be needed.  Discussion of the
+structure of the output files will be divided into two sections, one on the
+header and the other on the data itself.
+
+The header
+
+Each ASP module's output file contains a header which provides information
+about the origin and history of the data in the file.  This information is
+used by subsequent modules in the ASP hierarchy, as described in Appendix
+B.  The header is a sequence of ASCII characters (and is thus readable, so
+even using more on the output file would produce sensible text for the
+duration of the header).  This sequence is divided into three parts.
+
+1	An identifying line.
+
+2	A series of option setting lines.
+
+3	NULL (ASCII 0) character.
+
+The identifying line is a means of determining, from the first few
+characters in a file, whether that file is in fact an ASP output file.  It
+also is used for determining the length of the header as a whole; thus,
+each output file begins with a string such as:
+
+header_bytes=0000709
+
+where header_bytes is the identifying string (which actually descended from
+the 'pipes' signal processing language) and the header is 709 bytes long.
+The length of the header includes the identifying line and the final NULL
+character.
+
+Each option setting line is of the form:
+
+<option name>=<option value>
+
+and these lines taken together will closely resemble a normal ASP options
+file, although there may be some options which are not familiar to even an
+experienced ASP user.  These options are 'hidden' ones which are passed
+between ASP modules, but which are of no interest to users of the software.
+ They may, however, be of interest to programmers who wish to take ASP
+output as input to their own programs, so a complete list of these hidden
+options is given at the end of this Appendix.
+
+The data
+
+The structure of the actual data section of an ASP output file will be
+dependent on the ASP module which produced it.  Since we are then committed
+to describing each of the output structures in detail, we will begin with
+the data structure that ASP modules expect in input waveforms.
+
+Input waveform structure
+
+For convenience, the ASP software assumes that input waveforms do not have
+headers of any form.  The only information about the structure of an input
+waveform that is required relates to the samplerate at which the waveform
+was generated or collected, and the number of significant bits that are in
+the data.  These two attributes are taken as options which must be entered
+by the user, but they could just as easily be viewed as the contents of a
+suitable header for a waveform.  The actual data section of a waveform
+consists of a single stream of (16-bit, or 'short') integers whose length
+determines the actual length, in points, of the waveform.  To view the
+waveform only the user can use genwav.
+
+Basilar membrane motion output structure
+
+The genbmm module takes a waveform of the structure defined above and
+produces the basilar membrane motion corresponding to this input waveform
+by using a gammatone filter bank.  The output data is expressed as the
+multiplexed output of a series of channels, one per channel in the filter
+bank.  Thus the first n data points (where n is the number of channels) in
+the output correspond to the first output data point for each of the n
+channels, beginning with the highest frequency channel and ending with
+lowest.  The second batch of n data points in the output file correspond to
+the second data point for each of the n channels in turn, and so on.  There
+will be m of these n-data item segments, where m is the length of the input
+file in data points, and the length of a sgm output file will thus be the m
+x n, which may obviously be quite large.
+
+Prepended to this data is a header which contains information related to
+the way in which the data was produced.  Some of this information was
+supplied by the user of the genbmm program (eg samplerate, length_wave,
+mincf_afb, etc) and some was derived from other sources (eg channels and
+pointsperchannel, which were computed by genbmm from the mincf_afb,
+maxcf_afb, dencf_afb, and length_wave options).
+
+Cochleogram output structure
+
+The output of gencgm is of identical structure to that of genbmm, although
+of course the header will contain extra information related to how the
+cochleogram was generated.
+
+Stablised auditory image output structure
+
+The output of gensai is a series of 'frames', one per graphical image that
+is displayed by gensai and revsai.  Each of these frames has the structure
+of an entire data section of a genbmm or gencgm output file.  Thus the .sai
+data is structured as a series of multiplexed waveforms.  The size of a
+.sai file will be m x n x f, where f is the number of frames generated by
+gensai, and is thus likely to be huge.  Again, the header will have
+additional information related to the generation of the stabilised auditory
+image.
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/aimInstructions	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,365 @@
+INSTRUCTIONS AND OPTIONS FOR THE AUDITORY IMAGE MODEL.
+
+This is the introduction for those wanting to use AIM to process waves
+once the software package has been compiled, installed and tested. It
+is assumed that the user has read the introductory article by
+Patterson, Allerhand and Giguere (1995) and/or viewed the Overview of
+the Auditory Image Model described at the beginning of ReadMe_bin.
+
+Begin by typing  gen -help  at the prompt in an xterm window.
+
+> gen -help
+
+This prints general usage information on the standard output as follows:
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+"AIM MRC-APU Release R6.28   [gen]    Tue Apr 18 17:35:15 1995"
+
+Usage: gen???  [options]  [file_name]
+
+   where ??? is one of the following abbreviations
+
+   wav     wave                                
+   bmm     basilar membrane motion             
+   nap     neural activity pattern             
+   sai     stabilized auditory image           
+   spl     spiral version of auditory image  
+   sgm     spectrogram                         
+   cgm     cochleogram  
+   asa     auditory spectral analysis          
+   epn     excitation pattern                  
+
+   [file_name] is a headerless wave file (2-byte binary integers).
+
+   [options] are the parameters, options and switches that control
+       the AIM instructions and the AIM tools.
+
+   Help with options:  gen???  [-help | -help=all | -help=option]
+   Path for options files (.gen???rc) = .:~ (or setenv OPTIONSPATH)
+
+
+Processes Applied by AIM and Routes Through the Model: 
+
+   Processes                           Auditory   Speech   Spectral
+                                        Route      Route    Route
+   --------------------------------    --------   ------   -------  
+   Display input wave                   genwav    genwav    genwav  
+   Auditory filtering (gtf/tlf)         genbmm                             
+   Compression and rectification                                    
+   Neural encoding (2D-AT/haircell)     gennap                      
+   Temporal integration (LP filter)               gensgm    genasa
+                                                  gencgm    genepn  
+   Strobed temporal integration         gensai                      
+   Spiral version of auditory image     genspl                      
+
+
+Output:   gen???  output=on  file_name
+                                 
+   Output is written to file:  file_name.???
+    
+   The format for 2-dimensional output is by columns, with the lowest 
+   channel first in each column (bmm, nap, sgm, cgm, asa, epn).
+   The format for auditory image output is by rows, for each image frame
+   in succession, with the row of the lowest channel first (sai, spl).
+
+
+The Auditory Image Model was developed at the Applied Psychology Unit
+of the Medical Research Council, 15 Chaucer Road, Cambridge, U.K.
+
+Copyright(c) Applied Psychology Unit, Medical Research Council, 1988-1995.
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+
+
+I. USAGE: INSTRUCTIONS, WAVE FILES, AND OPTIONS.
+
+Instructions: The auditory processing is performed by a single large
+program (gen) with multiple entry points, having names of the form
+gen???.  The entry-point names function as instructions, so the
+program is run by typing an entry point name on the command line,
+followed by options that control the details of the processing, and
+then the name of the file containing the waveform to be processed.
+The output will be displayed on the screen in a window created by AIM.
+For example, in the directory aim/bin, type:
+
+> genwav samplerate=22.05kHz start_wav=182ms length_wav=64 ../waves/hat
+
+This will display a section of the wave in the file 'hat' which is
+stored in the aim/waves directory. The wave was digitised at a
+sampling rate of 22.05 kHz, so the option 'samplerate' is set to
+22.05kHz. The options 'start_wav' and 'length_wav' determine the
+subset of the wave to be displayed.
+
+Each of the entry points into gen has a name which is an abbreviation
+of the functions provided to that point in the auditroy image model.
+For example, the first module applies spectral analysis to the input
+wave and the output of the analysis is available at entry point
+'genbmm' which stands for 'generate basilar membrane motion'. The
+entry points are listed in the usage section of the gen -help output
+and there is a manual entry for each, accessible via 'manaim
+gen???'. Together this set of manual pages constitute the primary
+documentation for AIM and they are the first place to look for help
+after this document.
+
+Wave Files: The input waves should be in the form of headerless binary
+files (2-byte integers). Use genwav to check that the bytes are in the
+right order. If they are not set option swap=on and AIM will reverse
+the bytes, temporarily, at before beginning the analysis. Alternately,
+use the aimtool 'swab' to switch the bytes in the file permanently.
+
+A. Options: 
+
+The precise behaviour of the program is determined by options.  There
+are AUDITORY OPTIONS which control the operation of the auditory
+processing modules in AIM, such as the number of channels in the
+auditory filterbank (channels_afb) or the decay rate of the auditory
+image (decay_ai).  These options are described in the manual pages for
+the individual instructions (gen???).  There are also NON-AUDITORY
+OPTIONS which a) specify the form of the input wave (e.g. samplerate
+and swap_wav), b) govern the position and characteristics of the
+output display and its contents, and c) specify the form and
+destination of the output.  These options are common to all entry
+points and so they appear at the head of the options list before the
+auditory options. For convenience, they are described in the manual
+entry for genwav, the starting point for any analysis.
+
+The relevant options at any entry point can be listed on the screen by
+typing the entry point name with the -help option.  For example,
+
+> genwav -help
+
+If the screen size is too small to display the entire list you can make the
+display pause between screens by typing:
+
+> genwav -help | more
+
+Alternately, you can print the listing using
+
+> genwav -help | lpr
+
+
+All of the options from title up to dB_wave are for display and flow
+control.  They determine how the program output appears on the screen,
+the source of the program input, and the destination of output. The
+options have default values chosen for 'normal' operation and display
+given the entry point. You can override the default values, either
+temporarily, by supplying a value on the command line when you run the
+program, or permanently by creating a file with your own option
+values. Both the default value and the current value for each option
+are listed by the help option.
+
+
+B. Options Values:
+
+Some of the options take numeric values (as in samplerate), others are
+file names (as in input_wave).  Others act as simple switches or flags
+(e.g. swap_wav); these options can be set/unset using on/off or 0/1.
+
+Numeric options can include appropriate units; so, for example, a
+frequency can be specified either as 20000Hz or as 20kHz. There are
+also default units for options. So, for example, Hz is the default
+unit for frequencies and ms is the defualt unit for times in
+milliseconds, and when these units apply, they need not be specified
+on the command line..
+
+The are also some special option values like 'remainder' which can be
+used to specify 'the rest of the wave' with option 'length_wave', and
+the special value 'centre' used with options x0_win and y0_win, to
+centre the display window on the screen. (This assumes that your
+window manager does not override placement of windows by
+applications.)
+
+
+C. Changing Option Values:
+
+You can alter the value of one or more of the options by specifying it
+and the required value on the command line between the entry point
+name and the name of the input file. For example:
+
+genwav width_win=440 ../waves/hat
+
+will produce a waveform display for the wave in file hat with a width of
+440 screen pixels.
+
+Switches and flags that just take the values on and off, or 0 and 1, can be
+switched on by specifying the option name, prefixed by a minus sign to
+distinguish them from a file name.  For example,
+
+> genwav -swap ../wave/hat_br
+
+  
+
+II. PROCESSES APPLIED BY AIM AND ROUTES THROUGH THE MODEL
+
+There are three routes through AIM depending on the purpose of the
+analysis and the form in which the output is to be displayed. The
+routes and the set of processes they apply are shown in the output of
+gen -help. 
+
+All of the routes through AIM begin with genwav which displays the
+contents of the file to be analysed as a magnitude versus time
+plot. It is recommended that all analyses should begin with genwav in
+order to a) confirm that the file does indeed contain the wave you
+wish to analyse, b) confirm that the file is headerless and that the
+bytes are in the right order, c) choose a subsection of the wave for
+analysis, and d) to check whether it is a 12-bit wave or a 16-bit
+wave. Headers usually appear as a brief bit of black, or noise with a
+large amplitude, at the left-hand edge of the plot. If the bytes are
+in the wrong order the entire wave usually looks like noise with a
+large amplitude.
+
+The AUDITORY ROUTE simulates basilar membrane motion (BMM), neural
+activity patterns (NAPs), and auditory images either in rectangular
+format (SAI) or in spiral format (SPL). Its purpose is to support
+time-domain modelling of peripheral auditory processing; that is, to
+simulate the phase-locked, time-interval patterns produced by the
+cochlea and the conversion of the time-interval patterns into auditory
+images by strobed temporal integration or autocorrelation (Patterson
+et al., 1992; Meddis and Hewitt, 1991).  For demonstrations of the
+functional and physiological versions of the auditory route through
+AIM try
+
+> aimdemo_gtf_all ../waves/cegc      and 
+> aimdemo_tlf_all ../waves/cegc
+
+[[[ Does the SAI work for the physiological route? Does it use acgram? ]]]
+
+
+The SPEECH ROUTE produces auditory spectrograms and cochleograms which
+can be stored and used as input for automatic speech recognition. They
+are 'auditory' spectrograms and cochleograms inasmuch as the centre
+frequencies of the channels in the filterbank are equally spaced on an
+ERB-scale, or Bark scale, rather than being linearly spaced as in
+traditional preprocessor (Robinson et al., 1990; Giguere and Woodland,
+1994; Patterson et al., 1994).  The are currently no aimdemo scripts
+for the speech routes through AIM.
+
+
+The SPECTRAL ROUTE produces representations of the distribution of
+activity across frequency in the auditory system, either at the output
+of the filterbank (genasa) or the output of the full cochlea
+simulation (genepn). These representations have been variously
+referred to as 'excitation patterns' (Zwicker, 1974; Moore and
+Glasberg, 1983), 'central auditory spectra' (Srulovicz and Goldstein,
+1983), or simply 'auditory spectra' (Patterson, 1994). In AIM, to
+distinguish the spectral representation at the output of the
+filterbank, from the representation provided at the output of the full
+cochlea simulation, the former is referred to as an 'auditory spectral
+analysis' (genasa) and the latter is referred to as an 'excitation
+pattern' (genepn).  For demonstrations of the functional and
+physiological versions of the spectral route through AIM, try
+
+> aimdemo_gtf_spectra ../waves/cegc      and
+> aimdemo_tlf_spectra ../waves/cegc
+
+
+
+III. INDIVIDUAL INSTRUCTIONS FOR THE AUDITORY ROUTE THROUGH AIM
+
+The following is a list of the instructions that form the basis of
+aimdemo_gtf_all. They show the output at successive stages of the
+functional version of the auditory route through AIM.
+
+> genwav length=32ms ../waves/cegc
+> genstp length=32ms ../waves/cegc
+> genbmm length=32ms ../waves/cegc
+> gennap length=32ms ../waves/cegc
+> gensai start=200 length=300ms ../waves/cegc
+> genspl start=200 length=300ms pensize=2 ../waves/cegc
+
+
+genwav shows the time waveform,
+genstp shows the pressure wave in the middle ear bone
+       that drives the cochlea (the stapes).
+genbmm shows simulated basilar membrane motion,
+gennap shows a simulated neural activity pattern,
+gensai shows a simulated stabilized auditory image,
+genspl shows a spiral mapping of the auditory image.
+
+
+Each of the instructions should create an X window and present a wave,
+a landscape display, or a spiral display of cegc.  The stimulus files
+were created on a DECstation. On a SUN, swap the bytes on the command
+line. For example:
+
+> genwav swap=on length=32ms ../waves/cegc
+
+The wave in the file 'cegc' is a set of click trains for the notes of
+a major triad and the octave -- hence the name C-E-G-C. We use clicks
+trains as test and demonstration stimuli for several reasons: They
+activate all channels of the model and they do so with roughly equally
+energy. The clicks elicit impulse responses from the model which show
+the processing in its simplest broadband form. The simple temporal
+structure of the click train immediately reveals any temporal
+alignment problems in the software.
+
+For the first 300 ms, the inter-click interval in cegc is 8 ms; then
+for 300 ms, the inter-click interval decreases linearly to (4/5)*8
+ms. For convenience, we refer to the first note as 'C', and so,
+relative to this C, the glide takes the note up to 'E'.  The gliding
+portions of cegc illustrate the dynamic properties of AIM.  The
+inter-click interval stays at (4/5)*8 for 300 ms and then glides
+linearly to (2/3)*8 ms which, relative to the starting C, is the note
+G.  The inter-click interval stays at (2/3)*8 ms for 300 ms and then
+glides linearly to (1/2)*8 ms which is the final note and the octave
+of the original C.
+
+
+IV. INSTRUCTION AND OPTION SYNTAX
+
+> gen??? [-option -option=value option=value ... -update] inputfile
+
+The input file is assumed to be a headerless binary file; that is it
+is assumed to contain in short integers (2-byte words).
+
+
+The options handler accepts the following three formats:
+
+-option       # turns option "on" (Unix convention)
+ option=value # sets option to the string "value" (standard math)
+-option=value # sets option to the string "value" (mixed unix/math)
+
+So, -swap, swap=on, and -swap=on, all have the same effect.
+
+The options handler also recognises two special options: update and help.
+
+-update (or update=on)
+    
+   This causes the options and values on the command line to be stored
+   in an 'options file' that is named according to the Unix convention
+   ".<program_name>rc".  All of the gen??? instructions search for a
+   file of this form when they are executed, so once an option has been
+   'updated' with a specific value, that value will be used in all
+   subsequent occurances of that instruction in that directory. (Note:
+   The .gen???rc are 'hidden' because the unix command 'ls' does not
+   print files beginning with '.' unless the ls option '-a' is
+   present.)
+
+   CAUTION: Be careful with options files in the users home
+   directory. They will be invoked by instructions executed in any
+   directory that does not have its own specific options file for that
+   instruction and this can be very confusing.
+
+-help (or help=on)
+
+   This causes the current options file to be printed on the screen (stdout).
+   
+   The help option accepts any option name as an argument, and prints the
+   value of that single option on the screen. So 
+
+> genbmm help=channels
+
+   will cause the current number of channels to be printed on the screen.
+
+   The help option also accepts the string 'all'.
+
+> genbmm help=all 
+
+   will cause all options required for BMM output to be printed on the
+   screen (stdout).
+
+   The options and values used in an analysis of BMM can be recorded
+   in the file foo by with the following instruction.
+
+> genbmm help=all > foo
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/aimMailList	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,31 @@
+
+aimMailList
+===========
+
+An email list has been set up for AIM users. Information about updates
+and bug will be propogated via the list, but the main reason for the
+list is to provide a forum where users can discuss issues arising from
+the use of AIM.  
+
+Note that the list is not "moderated"; it is a facility whereby users
+can communicate for their mutual benefit rather than a question answer
+facility provided by the software developers.
+
+
+A) To join [or resign from] the AIM mailing list, send an email
+message in the normal way to:
+
+       aim-request@mrc-apu.cam.ac.uk 
+
+This goes directly to the list administrator and not to anyone else in
+the list.  This address can also be used to register problems with the
+list.
+
+
+B) To post a message to all of the list members, send an email
+message in the normal way to:
+
+       aim@mrc-apu.cam.ac.uk 
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/aimPaths	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,52 @@
+
+       The pathnames which are to be modified for using the AIM software.
+       ====================================================================
+
+In the following ${DIR} is the pathname of the directory in which AIM is
+installed in your file system. For example this might be: /usr/local/aim
+
+
+1. Executables.
+--------------
+
+The executable files of the model, AIM tools and the script files are located
+in the ${DIR}/bin directory.
+
+If the path name is set to this directory, these programs can be executed 
+from anywhere in the system.  The best thing to do is to set the PATH 
+variable of the environment to: 
+
+	   setenv PATH ${DIR}/bin:$PATH
+
+This can be done in the .login, .profile or any other appropriate start-up
+script.
+
+
+2. On-line manual.
+-----------------
+
+The `manaim' script prints AIM manual pages with appropriate name in the
+Unix man page format.
+But if the user wishes to get the man pages through "xman", the environment
+variable MANPATH needs to be setup to search the aim/release/man
+directory along with the other default man directories.
+
+Add the directory which contains the AIM manual pages to the MANPATH
+in your environment, for example by including the following in your
+start-up script:
+
+	  setenv MANPATH ${DIR}/man:${MANPATH}
+
+or, if MANPATH is an undefined variable:
+
+	  setenv MANPATH ${DIR}/man
+
+
+For compatibility with systems which do not conventionally use a
+MANPATH, the pathname of the AIM pages directory must be the first
+pathname in the list.
+
+The AIM man pages will be appear in the "User Commands" section and the
+"Local" section of xman.
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/aimSilentOptions	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,128 @@
+SILENT OPTIONS LIST:
+
+Silent options are a subset of the AIM options that are occasionally
+useful but not sufficiently important to be included in the options
+lists put out by the gen??? -help instructions. They are listed below
+with simple one line explanations. This is the full extent of the
+documentation for most of these options currently. Those with ***
+prior to the comment have a man-like entry in the second Section of
+this file.
+
+
+Option Name    Default    Comment
+-----------    -------    -------------------------------------------       
+
+test1          0          Dummy option for test and development    /* MHA */
+test2          0          Dummy option for test and development    /* MHA */
+test3          0          Dummy option for test and development    /* MHA */
+test4          0          Dummy option for test and development    /* MHA */
+
+******** input/output options **********************************************
+useprevious    off    *** Use previously stored output
+framenumber    off        Index of current frame (to stderr)
+review         off        Wait for keyboard <return> between frames
+pstofile       off        Send PostScript output to .ps file
+bytemax
+type
+
+******** display options ***************************************************
+overlap
+headroom
+perspective
+mono_ctn       on         Force monochrome (single plane) cartoons. 
+colour_ctn     off        Force colour (multi-plane) cartoons.      
+planemask_ctn  1          Planemask for creating cartoons.        
+fg_col         black      Foreground Colour.                   
+bg_col         white      Background Colour.                    
+rotateaxes     off        Rotate the axes labels in .ps output  
+
+******** options to assist dtp of postscript (_ps) output ******************
+xstart_ps                 x-axis: start point for ps plots         /* MAA */
+xend_ps                   x-axis: end point for ps plots.          /* MAA */
+ystart_ps                 y-axis: start point for ps plots.        /* MAA */
+yend_ps                   y-axis: end point for ps plots.          /* MAA */
+xtitle_ps                 x-axis: title for ps plots.              /* MAA */
+ytitle_ps                 y-axis: title for ps plots.              /* MAA */
+portrait_ps               Use 'portrait' page format               /* MAA */
+landscape_ps              Use 'landscape' page format              /* MAA */
+fontname_ps    Helvetica  Font for ps plots                        /* MAA */
+fontsize_ps        12     Fontsize for ps plots (points)           /* MAA */  
+fonttitlesize_ps    0     Fontsize for title (points)              /* MAA */
+axislinewidth_ps    1     Linewidth for axes/tick-marks (points)   /* MAA */
+figurelinewidth_ps  1     Linewidth for figures (points)           /* MAA */ 
+xticks_ps           6     Size of x-axis (big) ticks (points)      /* MAA */
+yticks_ps           6     Size of y-axis (big) ticks' (points)     /* MAA */
+outsideticks_ps    on     Print tick-marks 'outside' figure        /* MAA */ 
+axistop_ps         on     Print tick-marks on top side             /* MAA */
+axisbottom_ps      on     Print tick-marks on bottom side          /* MAA */
+axisleft_ps        on     Print tick-marks on left side            /* MAA */
+axisright_ps       on     Print tick-marks on right side           /* MAA */
+xmajorticks_ps      1     Relative *spacing* of ticks              /* MAA */
+xminorticks_ps      1     Relative *spacing* of ticks              /* MAA */
+ymajorticks_ps      1     Relative *spacing* of ticks              /* MAA */
+yminorticks_ps      1     Relative *spacing* of ticks              /* MAA */
+
+******** internal variables for the transmission-line filterbank ***********
+upfactor       auto       Upsampling factor (off auto int)          /* CG */
+cutoff         1.0        LP cutoff as a fraction of Nyquist freq.  /* CG */
+downfactor     auto       Downsampling factor (off auto int)        /* CG */
+nconcha_ear    2          Number of segments in concha              /* CG */
+lconcha_ear    0.90       Total length of concha (cm)               /* CG */
+rconcha_ear    1.00       Radius of concha (cm)                     /* CG */
+kconcha_ear    0.01       Attn. constant of concha (1/cm)           /* CG */
+ncanal_ear     4          Number of segments in ear canal           /* CG */
+lcanal_ear     2.85       Length of ear canal (cm)                  /* CG */
+rcanal_ear     0.35       Radius of ear canal (cm)                  /* CG */
+kcanal_ear     0.04       Attn. constant of ear canal (1/cm)        /* CG */
+interp_afb     off        Levels of interpolation to apply          
+audiogram_afb  off        Audiogram equalisation parameter          /* CG */ 
+
+********* options for lowpass filter between gt afb and 2D-AT **************
+ltup_lpf       0.5ms      Upward time constant in ms                /* JH */ 
+lstages_lpf    off        Stages of integration                     /* JH */ 
+
+linear_sgm     off        Linear frequency axis for spectrograms    /* JH */ 
+power          off        Power of Compression                      /* JH */ 
+
+exponential_decay off     Exponential strobe Decay [ in gensai]    /* AJD */
+    
+q or Q [Return]           Quit animated display mode.
+
+
+
+
+
+	overlap   The overlap of transparent windows of the
+                  individual functions
+                  Scalar: percentage. Default value: 50%
+
+        The fact that the output functions are related means that they fit up
+        under each other in the display in a way that concentrates the lines
+        on the landscape and improves the display.
+
+        headroom  Display with headroom for the uppermost channel
+                  Scalar: percentage. Default value: 0%
+
+        Because of the overlap of the transparent windows, part of the upper-
+        most transparent window is hidden by the upper edge of the display
+        window. This can cause truncation of the waves in the upper channels.
+        To avoid truncation, headroom enables the user to specify that the
+        highest channel ought to be centred below the upper edge of the win-
+        dow.  The value specified is taken to be the percentage of the window
+        between the zero line of the upper channel and the upper edge of the
+        window.
+
+
+                   
+useprevious
+
+Command line options override the non-auditory options in the header
+of a reused file (ie. useprevious=on). 
+
+Note: length=remainder gets the whole of the reused file. Otherwise you get
+the amount you request (or the default length if no option is given).
+
+BUG: AIM will allow you to overwrite of the channels option, but it
+will not act appropriately. It would need it to change the frame size,
+which in turn would require knowledge of the file format which it does
+not currently have.)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/aimStrobeCriterion	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,717 @@
+docs/aimStrobeCriterion (text)
+scripts/aimStrobeCriterion (figures)
+
+
+STROBED TEMPORAL INTEGRATION AND THE STABILISED AUDITORY IMAGE
+
+Roy D. Patterson, Jay Datta and Mike Allerhand
+MRC Applied Psychology Unit
+15 Chaucer Road, Cambridge, CB2 2EF UK
+
+email:  roy.patterson, jay.datta or mike.allerhand  @mrc-apu.cam.ac.uk
+
+2 August 1995
+
+
+ABSTRACT
+
+	This document describes the Strobed Temporal Integration
+mechanism used to convert neural activity patterns into stabilised
+auditory images. The specific version of the Auditory Image Model is
+AIM R7, as described in Patterson, Allerhand, and Giguere (1995)
+
+
+
+INTRODUCTION
+
+	When a periodic sound occurs with a pitch in the musical
+range, the cochlea produces a detailed, multi-channel, time-interval
+pattern that repeats once per cycle of the wave.  The auditory images
+that we hear in response to periodic sounds are perfectly stable.
+That is, despite the fact that the level of activity in the neural
+activity pattern is fluctuating over a large range within the course
+of each cycle, the loudness of the sound is fixed.  This indicates
+that some form of temporal integration is applied to the NAP prior to
+our initial perception of the sound.  The auditory images of periodic
+sounds can have a very rich timbre, or sound quality, that can reveal
+a great deal about the sound source such as the quality of the musical
+instrument or the finesse of the musician.  This suggests that much of
+the detailed time-interval information produced by the cochlea is
+preserved in the stabilised auditory image.
+
+	The fact that we hear stable auditory images with rich sound
+quality presents auditory theorists with a problem.  The temporal
+integration mechanism in traditional auditory models is a low-pass
+filter that removes the fine-grain time-interval information from the
+internal representation of the sound -- time interval information that
+appears to be required for timbre perception.  Strobed temporal
+integration was introduced to solve this problem. At one and the same
+time, it performs the temporal integration necessary to produce stable
+auditory images and it preserved the majority of the time-interval
+information observed in the neural activity pattern (NAP) produced by
+the cochlea.
+
+	It is not a difficult problem to produce a high-resolution,
+stabilised version of the NAP provided you know the moment in time at
+which the pattern in the NAP will repeat.  For example, consider the
+NAP of the first note of the wave CEGC in Figure 0.1 from Patterson et
+al. (1992).  The wave is a train of clicks separated by 8-ms gaps; the
+upper channels of the NAP show that the response is a sequence of
+filter impulse responses spaced at 8 ms intervals.  A stabilised
+representation of the NAP can be produced by setting up an image
+buffer that has the same number of channels as the NAP, and simply
+transferring a copy of the pattern in each channel of the NAP to the
+corresponding channel of the image buffer once every 8 ms.  In the
+NAP, the pattern flows from right to left as time progresses, and
+since the cycles are continually entering the NAP from the right hand
+side and exiting the NAP from the left hand side, the pattern after
+every 8 ms is identical to the pattern 8 ms ago.  So if the transfer
+from the NAP to the auditory image is performed every 8 ms exactly,
+successive contributions from the NAP to the image are all identical.
+
+	In the image buffer, activity does not move from right to
+left, it simply decays into the floor exponentially over time with a
+half life of about 30 ms.  When a new contribution arrives from the
+NAP, it is added point for point with whatever is currently in the
+corresponding channel of the image buffer.  In the current example,
+after a copy of the NAP arrives in the auditory image, and during the
+30 ms over which it would decay to half its original value, three more
+copies of the NAP pattern arrive and are added into the auditory
+image.  Thus, for typical musical notes and typical vowels, the rate
+of temporal integration from the NAP into the auditory image is high
+and there is little time between successive integration events for the
+image itself to decay.  This is the source of the stability of the
+auditory image.
+
+	Provided the integration is performed once per cycle of the
+sound, the majority of the time-interval information in the NAP will
+be preserved in the auditory image, thereby providing a solution to
+the problem of how to produce stable images without removing the
+fine-grain time-interval information associated with sound quality.
+The auditory image produced by this process is shown in Figure 0.2
+from Patterson et al. (1992).  The transfer is performed on each
+channel of the NAP separately and it is performed at the point in the
+cycle where the activity in the NAP is a maximum.  The maximum of the
+most recent cycle to arrive in the NAP is added into the auditory
+image at the 0-ms point, and as a result, the NAP peaks are aligned
+vertically in the auditory image.  This passive alignment process
+explains the loss of global phase information observed empirically
+(see Patterson, 1987, for a review).
+
+	Thus it would appear that the problem of converting the
+oscillating NAP into a stabilised, high-resolution image reduces to
+the problem of finding the pitch of the sound and performing temporal
+integration at multiples of the pitch period.  There are now a number
+of computational auditory models with a proven ability to extract the
+pitch of complex sounds (see Brown and Cook, 1994, for a review) and
+they could be used to direct strobed temporal integration.  However,
+experiments with vowels (McKeown and Patterson, 1995; Robinson and
+Patterson, 1995a) and musical notes (Robinson and Patterson, 1995b)
+indicate that 4 to 8 cycles of the sound are required to produce an
+accurate estimate of the pitch, whereas the sound quality information
+necessary to identify a vowel or a musical instrument can be extracted
+from one cycle of the wave.  This suggests, that if the auditory
+system does use strobed temporal integration to produce a stable, high
+resolution auditory image, it does it with a mechanism that operates
+more locally in time than pitch extraction mechanisms.  This is the
+background that led to the development of the strobed temporal
+integration mechanism in the auditory image model.
+
+	In Sections 1 and 2 of this document, following Allerhand and
+Patterson (1992), we describe two simple criteria for selecting strobe
+points in the NAP and show that they produce auditory images that are
+very similar to the correlograms produced by Assman and Summerfield
+(1990), Slaney and Lyon (1990), or Meddis and Hewitt (1991a, 1991b).
+The structures that arise in this form of auditory image are much more
+symmetric than the corresponding structures in the NAP (Allerhand and
+Patterson, 1992).  There is mounting evidence, however, that the
+auditory system is highly sensitive to temporal asymmetry (Patterson,
+1994a, 1994b; Akeroyd and Patterson, 1995; Irino and Patterson, 1996),
+and so the loss of asymmetry associated with the simple strobe
+criterion seems likely to limit the value of this representation of
+our perceptions.  In the remaining Sections, an ordered sequence of
+restrictions is added to the simple criteria for initiating temporal
+integration, to restore asymmetry to the structures that arise in the
+auditory image.
+
+
+1.  Strobe on Every Non-Zero Point in the NAP.  
+
+	The initial criterion is very simple; temporal integration is
+initiated on each and every non-zero point in the NAP.  In AIM
+software, the option that determines which strobe criterion will be
+used is 'stcrit_ai' and it is set equal to one for this simplest
+strobe criterion. Allerhand and Patterson (1992) showed that when
+temporal integration from the NAP to the auditory image is initiated
+on each and every non-zero point in the NAP function, the result is
+very similar to a correlogram -- a representation that is commonly
+used in time-domain models of hearing to extract the pitch of complex
+periodic sounds (see Brown and Cook, 1994, for a review).  For
+example, compare the auditory image with stcrit_ai=1 (Figure 1.1) and
+the correlogram (Figure 1.2) of the first note of the sound cegc.
+Both figures show stabilised representations of the time-interval
+pattern that the sound produces in the NAP, and in both cases, the
+individual channels have been aligned vertically on the largest peak
+in the NAP function.  The patterns in the auditory image and the
+correlogram both differ from the pattern in the NAP in one important
+way; there is a reflection of the NAP pulses associated with the
+ringing of the auditory filters, on the side opposite to where they
+originally appear.  That is, autocorrelation and STI with stcrit_ai=1
+reduce the temporal asymmetry observed in the NAP.  The asymmetry
+information is not entirely removed but it is largely removed.
+Experiments with sounds that have asymmetric temporal modulation show
+that listeners are sensitive to temporal asymmetry (Patterson, 1994a,
+1994b; Akeroyd and Patterson, 1995; Irino and Patterson, 1996), and so
+the removal of asymmetry information seems likely to prove a
+disadvantage when attempting to explain auditory perception.
+
+	The autocorrelation process is symmetric in time by its very
+nature. Mechanical processes that produce sound in the world are
+typically asymmetric in time because they usually have some inertia.
+Resonators struck impulsively ring after the pulse and not before.
+This principle also applies to the processes that analyse the sound in
+the auditory system.  The impulse response of the auditory filter
+rises faster than it falls; the adaptation process in the inner
+haircell adapts up faster at the onset of a sound than it adapts down
+after the sound passes.  So asymmetry is the norm in the world and it
+is not surprising that the auditory system is sensitive to it.
+
+
+2.  Strobe on the Peak of Each NAP pulse.
+
+	When temporal integration is initiated on every non-zero NAP
+point, the successive NAP functions that are transferred to the
+auditory image are highly correlated.  This suggests that we could
+attain essentially the same auditory image for vastly less computation
+by restricting temporal integration to the larger points on the
+individual NAP pulses.  This leads, in turn, to the suggestion that
+temporal integration be limited to the peak of the individual NAP
+pulses.  The result of this restriction is illustrated in Figure 2.1
+which shows the auditory image of the first note of CEGC with this
+more restricted strobe criterion.  Since the peak restriction greatly
+reduces the rate of temporal integration, the absolute levels of
+structures in this form of auditory image are considerably lower than
+those in the previous form of image.  The pattern of time intervals,
+however, is very similar in the two forms of auditory image.  They
+both preserve a detailed representation of the time-interval pattern
+in the NAP, and, they both loose much of the asymmetry in the NAP.
+
+
+3.  Avoid Strobing in the Temporal Shadow after a large NAP Pulse.
+
+	The loss of asymmetry in the click-train structure of the
+auditory image, arises when temporal integration is initiated on the
+smaller NAP pulses associated with the ringing of the auditory filters
+after each click in the train.  This can be demonstrated by
+introducing a fixed strobe threshold below which NAP peaks do not
+initiate temporal integration, and progressively raising this strobe
+threshold to exclude more and more of the lower level NAP pulses.  (In
+AIM, a fixed threshold is set with option stthresh_ai and
+stcrit_ai=1.)  The auditory image becomes less and less symmetric and
+more and more like the original NAP pattern for the click train as the
+strobe threshold is increased.  Fixed thresholds of this sort are not
+realistic for simulating the operation of auditory system, firstly
+because the strobe threshold eventually exceeds the largest NAP pulse
+and temporal integration ceases entirely, and secondly because, in the
+natural environment, the levels of sounds are constantly changing.
+Nevertheless, the example illustrates how NAP asymmetry is lost with
+simple strobe criteria.  The problem with autocorrelation is similar;
+the correlation values at lags associated with the smaller NAP pulses
+introduce symmetric reflections into structure that appear in the
+correlogram.
+
+	An alternative means of restricting temporal integration to
+the larger pulses in the NAP of the click train is to use an adaptive
+strobe threshold which is temporally asymmetric.  In the simplest
+case, when the strobe unit monitoring a NAP channel encounters a
+pulse, strobe threshold is set to the full height of the NAP pulse.
+But following the peak threshold does not fall as fast as the NAP
+function, rather it is restricted to decaying at a fixed percentage of
+the peak height per ms.  In AIM, the rate of decay is set to 5% per
+ms, so the threshold decays faster after larger peaks, and in the
+absence of further NAP peaks, returns to 0 in 20 ms.  The NAP function
+for the 1.0-kHz channel of the NAP is presented in Figure 3.1 along
+with the adaptive threshold function. Together they illustrate what is
+referred to as the "temporal shadow criterion" for strobed temporal
+integration.
+
+	In the figure, the vertical lines below the abscissa of the
+NAP function mark the NAP pulses that initiate temporal integration.
+They show that the first NAP pulse strobes temporal integration and
+strobe threshold is set to the peak height.  It immediately begins to
+decay, but then it encounters another NAP pulse that exceeds strobe
+threshold and so the process of strobing temporal integration and
+raising strobe threshold is promptly repeated.  At this point,
+however, strobe threshold is high relative to the NAP pulses and,
+strobe threshold is falling more slowly than the NAP pulses, so the
+algorithm proceeds through the rest of the cycle without encountering
+another NAP pulse from the ringing part of the NAP function.  In this
+way, the strobe mechanism is synchronised to the period of the sound
+even though no explicit information about the pitch of the sound is
+provided to the strobe mechanism.  It is the auditory image with the
+temporal shaddow criterion that was presented originally in Figure
+0.2. (stcrit_ai=3).
+
+	The 'temporal shadow criterion' produces stable auditory
+images with accurate, asymmetry for a wide variety of naturally
+occurring sounds like vowels and musical notes.  The reason is that
+the NAPs of these sounds have a restricted range of periods and within
+those periods the asymmetry is typically characterised by the
+rapid-rise/slow-fall form.  There are, however, periodic sounds with
+very low pitch and NAP functions that rise slowly over the course of
+the period and fall rapidly at the end of the period, and the
+perceptions produced by these sounds indicate that the auditory strobe
+mechanism is somewhat more sophisticated than the temporal shadow
+strobe mechanism.  These "ramped" sounds are the subject of the next
+section.
+
+
+4.  Avoid Temporal Integration on NAP Peaks Followed by Larger NAP Peaks.
+
+	A pair of the sounds that illustrate the limitations of the
+temporal shadow criterion are presented in Figures 4.1a and 4.2a; the
+former is an exponentially damped sinusoid that repeats every 25-ms,
+the latter is an exponentially ramped sinusoid with the same envelope
+period.  The carrier frequency in this case is 800 Hz and the half
+life of the exponential is 4-ms.  The half life is on the same order
+as the exponential decay of the impulse response of a gammatone
+auditory filter with a centre frequency in the region of 800 Hz.  The
+example is taken from Patterson (1994a).
+
+	The neural activity patterns produced by the damped and ramped
+sinusoids are shown in Figures 4.1b and 4.2b, respectively.  The
+frequency range of the filterbank is from an octave below the carrier
+frequency to an octave above the carrier frequency.  The highest and
+lowest channels in Figure 4.1b show the transient response of the
+filterbank to the onset of the damped sinusoid, and similarly the
+high- and low-frequency channels in Figure 4.2b show the transient
+response of the filterbank to the offset of the ramped sinusoid.  In
+the high-frequency channels, the onset response of the damped sinusoid
+and the offset response of the ramped sinusoid are composed of impulse
+responses from the individual auditory filters.  The centre section of
+each figure shows the response to the carrier.  Here we see that the
+asymmetry in the waveform is preserved in the NAP: in Figure 4.1b, the
+carrier component is at its highest level just as the transient
+response ends and the carrier component decays away over the course of
+the period; in Figure 4.2b, the carrier activity rises over the course
+of the ramped cycle and ends at its peak level in the transient
+response.
+
+	Auditory images of these damped and ramped sinusoids are
+presented in Figures 4.3 and 4.4, respectively.  The upper rows show
+the images obtained when the strobe initiates temporal integration on
+every peak in the NAP; the middle rows show the images obtained with
+the temporal shadow criterion.  The images in the upper row illustrate
+the problem of preserving NAP asymmetry during temporal integration.
+When the mechanism strobes on every peak, the temporal asymmetry
+observed in the NAP of the damped sinusoid is actually reversed in the
+auditory image of the damped sinusoid (Figure 4.3a).  In the case of
+the ramped sinusoid, the asymmetry observed in the NAP is largely lost
+in the image of the ramped sinusoid (Figure 4.4a); there is activity
+at all time intervals in the central channels, whereas there is a gap
+in activity in the NAP of the ramped sinusoid, once per cycle, just
+after the abrupt reduction in amplitude.  It is also the case that
+there are irregular fringes along the edges of the main structure in
+the auditory image of the ramped sinusoid (Figure 4.4a).  This
+provides further evidence that the time interval pattern in the NAP is
+being disrupted by the temporal integration process in the
+construction of the auditory image.
+
+	The introduction of the temporal shadow criterion for
+initiating temporal integration produces a dramatic improvement in the
+auditory image of the damped sinusoid (Figure 4.3b).  The structure in
+the image is highly asymmetric and, once the alignment process is
+taken into account, the structure in the image is seen to be a very
+faithful reproduction of that in the NAP.  The imposition of the
+temporal shadow criterion improves the auditory image of the ramped
+sound (Figure 4.4b). in as much as it eliminates the fringes seen in
+Figure 4.4a.  But it does not solve the asymmetry problem.  The
+structure in the auditory image of Figure 4.4a is still more symmetric
+than it is asymmetric, whereas the structure in the corresponding NAP
+is highly asymmetric.
+
+	The source of the problem is illustrated in Figures 4.5a and
+4.6a which show the NAPs and adaptive thresholds for 80-ms segments of
+the damped and ramped sinusoids, respectively.  The vertical markers
+below the abscissa in Figure 4.5a show that after the first cycle, the
+strobe mechanism is synchronised to the period of the wave and
+initiates temporal integration once per cycle on the largest NAP peak.
+So this criterion preserves the asymmetry of the damped sound in its
+auditory image.  In contrast, Figure 4.6a shows that on the way up the
+ramped portion of each cycle, the rising NAP pulses repeatedly exceed
+the adaptive threshold resulting in repeated initiation of temporal
+integration.  Since, in this region of the cycle, the mechanism
+initiates temporal integration on every cycle, the auditory image does
+not preserve the asymmetry observed in the corresponding NAP.  The
+irregular fringe is reduced because the mechanism reliably skips the
+portion of the cycle where the level of activity in the NAP is
+changing most rapidly.
+
+	The high rate of strobing revealed in Figure 4.6a means that
+the level of activity in the ramped auditory image of Figure 4.4b is
+considerably greater than that in the damped image (Figure 4.3b).  It
+does not show in those Figures because they have been normalised for
+display purposes.  In terms of the auditory model, however, the
+greater overall level in the image of the ramped sound would lead to
+the prediction that ramped sounds are considerably louder than damped
+sounds, and this is not the case; they have roughly equal loudness.
+All of these observations taken together suggest that the strobe rate
+should be limited and that the limitation should favour larger NAP
+peaks, closer to the local maximum.
+
+	The solution in this case is to delay temporal integration a
+few milliseconds after each suprathreshold NAP pulse, to determine
+whether another, larger, NAP pulse is about to occur.  Specifically,
+when a NAP peak is identified, it is labeled as a potential strobe
+point, but the initiation of temporal integration is delayed for
+several milliseconds.  In AIM, the value is set with option
+'stlag_ai'.  If, during this time, no new larger NAP pulses are
+encountered, the candidate strobe point is used to initiate temporal
+integration.  If a larger NAP pulse is encountered, it becomes the new
+strobe candidate and replaces the previous strobe candidate, the
+strobe lag is reset to stlag_ai ms and the process begins again.  The
+auditory images of damped and ramped sinusoids produced with this
+'local-max' strobe criterion are shown in Figures 4.3c and 4.4c,
+respectively.  The strobe lag restriction has virtually no effect on
+the auditory image of the damped sinusoid, but it improves the image
+of the ramped sinusoid markedly.  The asymmetry observed in the NAP of
+the ramped sinusoid is now preserved in its auditory image.
+
+	The NAP functions and the adaptive thresholds for the damped
+and ramped sinusoids are shown in Figures 4.5b and 4.6b, respectively.
+A comparison of the strobe points for the damped sinusoid under the
+temporal shadow criterion (Figure 4.5a) and the local max criterion
+(Figure 4.5b) shows that there is one small difference; the very first
+strobe point under the temporal shadow criterion is omitted under the
+local max criterion because a larger NAP pulse follows it within
+stlag_ai ms.  So the second NAP pulse replaces the first as the strobe
+candidate.  In the case of the ramped sinusoid, shifting to the local
+max criterion has a dramatic effect.  The NAP functions and adaptive
+thresholds in Figures 4.6a and 7.6b are identical, but most of the
+strobe points identified under the temporal shadow criterion (Figure
+4.6a) are immediately followed by larger NAP pulses as we proceed up
+the ramp.  As a result the majority of the candidate pulses are
+repressed in favour of the one that occurs at the offset of the ramp.
+So, with the exception of the onset of the sound, the mechanism
+synchronises to the period of the sound and there is one strobe per
+cycle of the sound.  The local max criterion also leads to damped and
+ramped auditory images with roughly the same level of activity in the
+auditory image, and so it is also a better predictor of the loudness
+of these sounds. Finally, note that the strobe lag restricts the
+maximum strobe rate of the mechanism. This is important because,
+without it, the level of a sinusoid would increase with its frequency
+in the auditory image.
+
+
+5.  Limiting the Lag of the Local Max Criterion.
+
+	In the second experiment with damped and ramped sinusoids
+(Patterson, 1994b), the longest envelope period was 100-ms, and in
+that condition, the distinction between damped and ramped sinusoids is
+audible for half lives as long as 64 ms.  In channels near the carrier
+frequency, the NAP function produced by the ramped sinusoid is a long,
+slowly rising, sequence of peaks.  The local-max strobe criterion
+delays temporal integration to the end of the ramp and initiates
+temporal integration once per cycle, as previously, with the 25-ms
+envelope stimuli.  The example, however, raises the question of what
+would happen in the case of a very long duration slowly rising tone,
+say a tone that rises from absolute threshold to 80 dB SPL over the
+course of 5 seconds.  A listener would undoubtedly hear the sound
+shortly after it comes on, and hear its loudness increase
+progressively over the course of the 5-second rise.  The local-max
+strobe mechanism would initiate temporal integration once, shortly
+after the onset of the sound, because of overshoot in the neural
+encoding stage of AIM. But thereafter, it would suppress temporal
+integration throughout the rise of the NAP function and strobe once at
+the end of the rise.  Thus the auditory image would be empty at a time
+when we know the listener would hear the tone.  To solve this problem,
+the strobe lag of the local max mechanism is limited to twice the
+stlag_ai value; that is, after a NAP pulse becomes a strobe candidate,
+either that NAP pulse or a larger one must initiate temporal
+integration within the next 2*stlag_ai ms. So the strobe lag restricts
+not only the maximum strobe rate for static sinusoids, but also the
+minimum strobe rate for slowly increasing sinusoids.
+
+
+6. Aperiodic Strobing and Irregularity in the Auditory Image.
+
+	To this point, the discussion of strobe criteria has focussed
+on activity in the carrier channel of the NAP and auditory image, and
+the relationship between strobe criteria and the preservation of NAP
+asymmetry through temporal integration.  It was noted in passing,
+that, away from the carrier channel, auditory images of ramped sounds
+have fringes of irregular activity, for all strobe criteria prior to
+the local max criterion.  We might expect such fringes to impart a
+roughness or noisy quality to the perception of ramped sounds, but
+typically they are static and clear.  In this final Section, the
+activity produced by a ramped sinusoid in the 640 Hz channel of the
+NAP and auditory image is examined, to illustrate the relationship
+between strobe restrictions and the fringe of irregularity in the
+auditory image.
+
+	The NAP produced in the 640 Hz channel of the filterbank by a
+ramped sinusoid with an 800-Hz carrier, a 25-ms envelope period, and a
+4-ms half life is shown in Figure 6.1.  The level of the ramped
+sinusoid rises rapidly, relative to the decay rate of the impulse
+response of the auditory filter and, as a result, the activity in the
+rising part of the NAP is dominated by carrier-period time intervals
+(Patterson, 1994a).  When the amplitude of the ramped sinusoid drops
+abruptly, the energy stored in the filter decays away in a wave with
+periods appropriate to the centre frequency of the channel.  Now
+consider the activity produced by this NAP in the 640-Hz channel of
+the auditory image for strobe criteria 2, 3 and 4, the 'every peak',
+'temporal shaddow,' and 'local max' criteria, respectively.
+
+	Figure 6.2a shows the case where there is no adaptive
+threshold and the mechanism strobes on the peak of every NAP pulse.
+This is the version of STI most similar to autocorrelation.  Strobing
+on every peak causes carrier periods from the ramp to be mixed with
+centre-frequency periods after the offset of the ramp.  This is the
+source of the irregularity in Fig. 6.2a, and the source of the
+irregular fringe in the full auditory image (Fig. 4.5a) (Allerhand and
+Patterson, 1992).
+
+	The activity produced with the temporal shadow criterion is
+shown in the Figure 6.2b. The adaptive threshold function and the
+strobe points shown with the NAP in Fig. 6.1 were generated with the
+temporal shaddow criterion.  In this case, the mechanism initiates
+temporal integration on each peak in the ramped portion of the NAP,
+but it skips the peaks associated with the ringing of the filter after
+the ramp terminates.  Strobing occurs in synchrony with the carrier
+periods in the ramped portion of the NAP and this removes the
+irregularity from the ramped portion of the auditory image between 0
+ms and about 10 ms.  There is still irregularity in the region from 0
+to -10 ms, and in the region from 25 to 15 ms, because strobing in
+synchrony with the carrier period mixes carrier periods and centre
+frequency periods in this region of the image.
+
+	A further improvement occurs when the local max criterion is
+introduced and strobing on successive carrier periods of the ramped
+section of the NAP is suppressed.  The activity in the 640-Hz channel
+of the image is shown in Figure 6.2c.  The irregular activity has been
+removed; the image shows carrier periods to the left of the 0-ms point
+and centre frequency periods to the right of the 0-ms point.  Thus,
+strobing on local maxima synchronises temporal integration to the
+period of the wave and preserves not only the basic asymmetry of the
+NAP, but also the contrasting time interval patterns associated with
+different sections of the NAP cycle. 
+
+
+
+REFERENCES
+
+Akeroyd, M.A. and Patterson, R.D. (1995). "Discrimination of wideband
+   noises modulated by a temporally asymmetric function,"
+   J. Acoust. Soc. Am. (in press).
+
+Assman, P. F. and Q. Summerfield (1990). "Modelling the perception of
+   concurrent vowels: Vowels with different fundamental frequencies,"
+   J. Acoust. Soc. Am. 88, 680-697.
+
+Brown, G.J. and Cooke, M. (1994). "Computational auditory scene
+   analysis," Computer Speech and Language 8, 297-336.
+
+Irino, T. and Patterson, R.D. (1996). "Temporal asymmetry in the
+   auditory system," J. Acoust. Soc. Am. (revision submitted
+   August 95).
+
+McKeown, D. and Patterson, R.D. (1995). "The time course of auditory
+   segregation: concurrant vowels that vary in duration,"
+   J. Acoust. Soc. Am. (in press).
+
+Meddis, R. and M. J. Hewitt (1991a). "Virtual pitch and phase
+   sensitivity of a computer model of the auditory periphery: I
+   pitch identification," J. Acoust. Soc. Am.  89, 2866-82.
+
+Meddis, R. and M. J. Hewitt (1991b). "Virtual pitch and phase
+   sensitivity of a computer model of the auditory periphery: II
+   phase sensitivity," J. Acoust. Soc. Am. 89, 2883-94.
+
+Patterson, R.D. (1987b). "A pulse ribbon model of monaural
+   phase perception,"  J. Acoust. Soc. Am. 82, 1560-1586.
+
+Patterson, R.D., Robinson, K., Holdsworth, J., McKeown, D., Zhang,
+   C. and Allerhand M. (1992) "Complex sounds and auditory images,"
+   In: Auditory physiology and perception, Y Cazals, L. Demany,
+   K. Horner (eds), Pergamon, Oxford, 429-446.
+
+Patterson, R.D. (1994a). "The sound of a sinusoid: Spectral models,"
+   J. Acoust. Soc. Am.  96, 1409-1418.
+
+Patterson, R.D. (1994b). "The sound of a sinusoid: Time-interval
+   models." J. Acoust. Soc. Am. 96, 1419-1428.
+
+Patterson, R.D. and Akeroyd, M. A. (1995). "Time-interval patterns and
+   sound quality," in: Advances in Hearing Research: Proceedings of
+   the 10th International Symposium on Hearing, G. Manley, G. Klump,
+   C. Koppl, H. Fastl, & H. Oeckinghaus, (Eds). World Scientific,
+   Singapore, (in press).
+
+Patterson, R.D., Allerhand, M., and Giguere, C., (1995). "Time-domain
+   modelling of peripheral auditory processing: A modular architecture
+   and a software platform," J. Acoust. Soc. Am. 98, (in press).
+
+Robinson, K.L. & Patterson, R.D. (1995a) "The duration required to
+   identify the instrument, the octave, or the pitch-chroma of a
+   musical note," Music Perception (in press).
+
+Robinson, K.L. & Patterson, R.D. (1995b) "The stimulus duration required to
+   identify vowels, their octave, and their pitch-chroma,"  J. Acoust. Soc.
+   Am 98, (in press).
+
+Slaney, M. and Lyon, R.F. (1990). "A perceptual pitch detector," in
+   Proc. IEEE Int. Conf. Acoust. Speech Signal Processing,
+   Albuquerque, New Mexico.
+
+
+
+
+===========================================================================
+#!/bin/sh
+
+# script/aimStrobeCriterion
+# Annotated script for generating the figures in docs/aimStrobeCriterion
+
+echo "FIGURES FOR SECTION 0"
+
+mv .gennaprc .oldgennaprc # a safety precaution
+mv .gensairc .oldgensairc # a safety precaution
+echo | gennap powc=off -update # make sure that powc is off
+echo | gensai powc=off -update # make sure that powc is off 
+
+echo
+echo "FIGURES FOR SECTION 0"
+echo "Figure 0.1:  Neural Activity Pattern (NAP) of cegc"
+gennap input=cegc_br top=3000 swap=off bits=12 gain_gtf=4 # all default values
+
+echo "Figure 0.2:  Stabilised Auditory Image (SAI) of cegc"
+gensai stcrit=3 input=cegc_br length=100ms frstep_aid=96ms top=2500
+
+echo
+echo "FIGURES FOR SECTION 1"
+
+echo "Figure 1.1  SAI of cegc strobing on every non-zero point in the NAP"
+echo " 			(stcrit_ai=1). This one is slow to calculate."
+gensai stcrit_ai=1 top=17000 input=cegc_br length=100ms frstep_aid=96ms 
+
+# Top has to be raised because this strobe criterion causes constant 
+# temporal integration.
+
+
+echo "Figure 1.2: SAI via autocorrelation -- a correlogram"
+echo | gennap input=cegc_br display=off length=125ms top=3000 output=stdout > cegc_br_gtf.nap
+#gennap -use start=48 display=on cegc_br_gtf # optional display of the NAP
+# After making a NAP with display=off, gennap -use requires you to set display=on.
+
+acgram start=50 wid=70ms lag=35ms frames=1 scale=.02 cegc_br_gtf.nap > cegc_gtf.sai
+gensai -use top=5000 input=cegc_gtf
+
+rm cegc_br_gtf.nap cegc_gtf.sai
+
+echo
+echo "FIGURES FOR SECTION 2"
+
+echo "Figure 2.1:  SAI of cegc strobing on the peak of every NAP pulse" 
+echo "			(stcrit_ai=2)"
+gensai stcrit_ai=2 top=10000 input=cegc_br length=100ms frstep_aid=96ms 
+
+echo
+echo "FIGURES FOR SECTION 3"
+
+echo "Demonstration of preservation of asymmetry when stthresh is elevated"
+# Note stthresh only operates when stcrit_ai=1.
+gensai stcrit_ai=1 top=5000 input=cegc_br length=68ms frstep_aid=66ms stthresh_ai=5000
+
+echo "Figure 3.1:  NAP of cegc with temporal shaddow criterion (stcrit_ai=3)"
+echo "	Single Channel NAP with Strobe Threshold and Strobe Points below NAP"
+StrobeCriterionDisplay cegc_br 1000 100 3 2.5 17000 2000
+
+# Type 'StrobeCriterionDisplay -help' for a listing of the options and
+# 	their order.
+# Control of Xplots:
+#	Click mouse button 1 to display coordinates of points.
+#	Click mouse button 2 to redraw.
+#	Click mouse button 3 to remove the display (i.e. quit).
+
+echo
+echo "FIGURES FOR SECTION 4"
+
+echo "Figure 4.1a:   Waveform of Damped Sinusoid (4 cycles)"
+genwav top=14000 bottom=-14000 length=100ms input=dr_f8_t4_d swap=on
+
+echo "Figure 4.2a:   Waveform of Ramped Sinusoid (4 cycles)"
+genwav top=14000 bottom=-14000 length=100ms input=dr_f8_t4_r swap=on 
+
+echo "Figure 4.1b:   NAP of the Damped Sinusoid (2 cycles)"
+gennap input=dr_f8_t4_d gain_gtf=0.0626 bits=16 top=2000 mincf=400 maxcf=1600 swap=on length=110ms output=stdout display=off > damped.nap
+gennap -use start=50 leng=50 display=on damped
+
+echo "Figure 4.2b:   NAP of the Ramped Sinusoid (2 cycles)"
+gennap input=dr_f8_t4_r gain_gtf=0.0626 bits=16 top=2000 mincf=400 maxcf=1600 swap=on length=110ms output=stdout display=off > ramped.nap
+gennap -use start=60 leng=50 display=on ramped
+
+rm damped.nap ramped.nap
+
+echo "Figure 4.3a:   SAI of the Damped Sinusoid strobing on every NAP peak"
+echo "			(stcrit_ai=2)"
+gensai input=dr_f8_t4_d gain_gtf=0.0625 bits=16 top=7000 mincf=400 maxcf=1600 swap=on length=140ms frstep_aid=135ms stcrit=2  pwid=30ms nwid=-10ms stlag=10ms stdecay=2.5
+
+echo "Figure 4.4a:   SAI of the Ramped Sinusoid strobing on every NAP peak"
+echo "			(stcrit_ai=2)"
+gensai input=dr_f8_t4_r gain_gtf=0.0625 bits=16 top=7000 mincf=400 maxcf=1600 swap=on length=140ms frstep_aid=135ms stcrit=2  pwid=30ms nwid=-10ms stlag=10ms stdecay=2.5 
+
+echo "Figure 4.3b:   SAI of the Damped Sinusoid with temporal shaddow criterion"
+echo "			(stcrit_ai=3)"
+gensai input=dr_f8_t4_d gain_gtf=0.0625 bits=16 top=1000 mincf=400 maxcf=1600 swap=on length=140ms frstep_aid=135ms stcrit=3  pwid=30ms nwid=-10ms stlag=10ms stdecay=2.5 
+
+echo "Figure 4.4b:   SAI of the Ramped Sinusoid with temporal shaddow criterion"
+echo "			(stcrit_ai=3)"
+gensai input=dr_f8_t4_r gain_gtf=0.0625 bits=16 top=2000 mincf=400 maxcf=1600 swap=on length=140ms frstep_aid=135ms stcrit=3  pwid=30ms nwid=-10ms stlag=10ms stdecay=2.5 
+
+echo "Figure 4.3c:   SAI of the Damped Sinusoid with the local max criterion"
+echo "			(stcrit_ai=4)"
+gensai input=dr_f8_t4_d gain_gtf=0.0625 bits=16 top=800 mincf=400 maxcf=1600 swap=on length=140ms frstep_aid=135ms stcrit=4 pwid=30ms nwid=-10ms stlag=10ms stdecay=2.5
+
+echo "Figure 4.4c:   SAI of the Ramped Sinusoid with the local max criterion"
+echo "			(stcrit_ai=4)"
+gensai input=dr_f8_t4_r gain_gtf=0.0625 bits=16 top=800 mincf=400 maxcf=1600 swap=on length=140ms frstep_aid=135ms stcrit=4 pwid=30ms nwid=-10ms stlag=10ms stdecay=2.5
+
+echo | gennap swap=on bits=16 gain_gtf=0.0625 -update 
+echo | gensai swap=on bits=16 gain_gtf=0.0625 -update 
+
+
+echo "Figure 4.5a:  NAP of Damped Sinusoid, temporal shaddow criterion (stcrit_ai=3)"
+echo "	Single Channel NAP with Strobe Threshold and Strobe Points below NAP"
+StrobeCriterionDisplay dr_f8_t4_d 800 120 3 2.5 14000 2400
+
+echo "Figure 4.5b:  NAP of Damped Sinusoid, local max criterion (stcrit_ai=4)"
+echo "	Single Channel NAP with Strobe Threshold and Strobe Points below NAP"
+StrobeCriterionDisplay dr_f8_t4_d 800 120 4 2.5 14000 2400
+
+echo "Figure 4.6a:  NAP of Ramped Sinusoid, temporal shaddow criterion (stcrit_ai=3)"
+echo "	Single Channel NAP with Strobe Threshold and Strobe Points below NAP"
+StrobeCriterionDisplay dr_f8_t4_r 800 120 3 2.5 7500 2400
+
+echo "Figure 4.6b:  NAP of Damped Sinusoid, local max criterion (stcrit_ai=4)"
+echo "	Single Channel NAP with Strobe Threshold and Strobe Points below NAP"
+StrobeCriterionDisplay dr_f8_t4_r 800 120 4 2.5 7500 2400
+
+echo
+echo "FIGURES FOR SECTION 5"
+
+echo
+echo "FIGURES FOR SECTION 6"
+
+echo "Figure 6.1:  NAP of Ramped Sinusoid, temporal shaddow criterion (stcrit_ai=3)"
+echo "	Single Channel NAP with Strobe Threshold and Strobe Points below NAP"
+StrobeCriterionDisplay dr_f8_t4_r 640 120 3 2.5 7000 2000
+
+echo "Figure 6.2a:  SAI of Ramped Sinusoid in channel centred on 640Hz (stcrit_ai=2)" 
+gensai input=dr_f8_t4_r swap=on gain_gtf=0.0625 bits=16 top=32000 mincf=640Hz chan=1 start=10ms length=110ms frstep_aid=100ms stcrit=2 pwid=30ms nwid=-10ms stlag=10ms stdecay=2.5
+
+echo "Figure 6.2b:  SAI of Ramped Sinusoid in channel centred on 640Hz (stcrit_ai=3)" 
+gensai input=dr_f8_t4_r swap=on gain_gtf=0.0625 bits=16 top=10000 mincf=640Hz chan=1 start=10ms length=110ms frstep_aid=100ms stcrit=3 pwid=30ms nwid=-10ms stlag=10ms stdecay=2.5 
+echo "Figure 6.2c:  SAI of Ramped Sinusoid in channel centred on 640Hz (stcrit_ai=4)" 
+gensai input=dr_f8_t4_r swap=on gain_gtf=0.0625 bits=16 top=1200 mincf=640Hz chan=1 start=10ms length=110ms frstep_aid=100ms stcrit=4 pwid=30ms nwid=-10ms stlag=10ms stdecay=2.5 
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/ftp.doc	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,35 @@
+
+============================================================================
+
+FTP INSTRUCTIONS FOR OBTAINING THE SOFTWARE
+
+Access to the APU site via ftp is by the address:
+ftp.mrc-apu.cam.ac.uk Use <Name>="anonymous" and <Password>=your email
+address.  Once inside the APU ftp system, cd to the AIM directory,
+pub/aim/.  The AIM software is in the compressed archive `aim.tar.Z'.
+The ReadMe.First file contains the text of this document. Copy both.
+
+For example:
+
+	ftp ftp.mrc-apu.cam.ac.uk
+
+	Name (mrc-apu.cam.ac.uk:you): anonymous
+	Password: your email address
+
+	cd pub/aim
+
+	get aim.tar.Z
+	get ReadMe.First
+
+
+Details of machine and address.
+------------------------------
+
+Name:    sirius.mrc-apu.cam.ac.uk
+Address:  192.18.195.1
+Aliases:  dns0.mrc-apu.cam.ac.uk
+
+COPYRIGHT MRC-APU, 1995.
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter/all.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,168 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+	     ============================================
+	      all.c - code for recursive filter section.
+	     ============================================
+
+
+		   J. Holdsworth - 23rd February 1988.
+
+
+    Copywright (c) Applied Psychology Unit, Medical Research Council. 1988.
+    =======================================================================
+
+
+
+
+
+*/
+
+#ifdef DSP32
+#include <math.h>
+#else
+
+/* identify object file */
+
+#ifndef lint
+static char *all_sccs_id = "@(#)all.c	1.7  John Holdsworth (MRC-APU) 10/7/89" ;
+#endif
+
+/* short data, integer recursive */
+
+#include "generic.c"
+
+/* short data, floating point recursive */
+
+#define FLOAT float
+#define FILTER_NAME   SingleFilterShortDataArray
+#define MODULE_NAME DoSingleFilterShortDataArray
+
+#include "generic.c"
+
+/* short data, floating point recursive */
+
+#define FLOAT         double
+#define FILTER_NAME   RealFilterShortDataArray
+#define MODULE_NAME DoRealFilterShortDataArray
+
+#include "generic.c"
+
+/* short data, complex integer recursive */
+
+#define COMPLEX
+#define OUTPUT_TYPE   scomplex
+#define FILTER_NAME   ComplexFilterShortDataArray
+#define MODULE_NAME DoComplexFilterShortDataArray
+
+#include "generic.c"
+
+/* int data, integer recursive */
+
+#define  INPUT_TYPE   int
+#define FILTER_NAME   FilterIntDataArray
+#define MODULE_NAME DoFilterIntDataArray
+
+#include "generic.c"
+
+
+/* int data, floating point recursive */
+
+#define FLOAT         double
+#define INPUT_TYPE    int
+#define FILTER_NAME   RealFilterIntDataArray
+#define MODULE_NAME DoRealFilterIntDataArray
+
+#include "generic.c"
+
+
+/* double data, real recursive */
+
+#define FLOAT         double
+#define INPUT_TYPE    double
+#define FILTER_NAME   RealFilterDoubleDataArray
+#define MODULE_NAME DoRealFilterDoubleDataArray
+
+#include "generic.c"
+
+
+#define ENVELOPE
+
+/* short data, integer recursive envelope */
+
+#define FILTER_NAME   EnvelopeShortDataArray
+#define MODULE_NAME DoEnvelopeShortDataArray
+
+#include "generic.c"
+
+
+/* short data, floating Point recursive envelope */
+
+#define FLOAT         double
+#define FILTER_NAME   RealEnvelopeShortDataArray
+#define MODULE_NAME DoRealEnvelopeShortDataArray
+
+#include "generic.c"
+
+#undef ENVELOPE
+
+#endif
+
+
+/* float data, real recursive */
+
+#define FLOAT         float
+#define INPUT_TYPE    float
+#define FILTER_NAME   RealFilterFloatDataArray
+#define MODULE_NAME DoRealFilterFloatDataArray
+
+#include "generic.c"
+
+
+#define ENVELOPE
+
+/* float data, floating Point recursive envelope */
+
+#define FLOAT         float
+#define INPUT_TYPE    float
+#define FILTER_NAME   RealEnvelopeFloatDataArray
+#define MODULE_NAME DoRealEnvelopeFloatDataArray
+
+#include "generic.c"
+
+#undef ENVELOPE
+
+
+/* float data, complex integer point recursive */
+
+#define COMPLEX
+#define FLOAT         float
+#define INPUT_TYPE    float
+#define OUTPUT_TYPE   fcomplex
+#define FILTER_NAME   ComplexFilterFloatDataArray
+#define MODULE_NAME DoComplexFilterFloatDataArray
+
+#include "generic.c"
+
+#undef COMPLEX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter/formulae.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,159 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+
+	formulae.c
+	==========
+
+    Functions from : Moore and Glasberg, Formulae describing frequency
+    selectivity as a function or frequency and level, and their use in
+    calculating excitation paterns. Hearing reserch, 28 (1987) 209-225
+
+*/
+
+#include <math.h>
+#include <stdio.h>
+#include "../glib/options.h"
+
+#ifndef  _FORMULAE_H_
+#include "formulae.h"
+#endif
+
+/* latest erb function circa. 1989 from BBG & CJM */
+
+/* derived from erb = 24.7 * ( 4.37e-3 * f +  1 ) */
+
+
+static double limit = 24.7  ; /* limit = k1 */
+static double Q     = 9.265 ; /* Q = 1. / ( k1 * k2 ) */
+
+
+void SetErbParameters( new_limit, new_Q )
+double new_limit, new_Q ;
+{
+    limit = new_limit ;
+    Q     = new_Q     ;
+
+    return ;
+}
+
+
+double Erb( frequency )
+     double frequency ;
+{
+    return ( limit + frequency / Q ) ;
+}
+
+/* integrate 1/erb(f) to get erb based scale */
+
+double ErbScale( frequency )
+	  double frequency ;
+{
+    return ( log( 1. + frequency / Q / limit ) * Q ) ;
+}
+
+
+double FofErbScale( E )
+	     double E ;
+{
+  return ( ( exp( E / Q ) - 1 ) * Q * limit ) ;
+}
+
+
+double poly( coefts, x )
+double *coefts, x ;
+{
+    double *cptr = coefts ;
+    double power = 1 ;
+    double value = 0 ;
+
+    while( *cptr != 0. ) {
+	value += *cptr++ * power ;
+	power *= x ;
+    }
+
+    return ( value ) ;
+}
+
+double dBAudiogram( frequency )
+	     double frequency ;
+{
+    static double audiogram_polynomial_coeficients[] = {
+	  2661.8, -3690.1, 1917.4, -440.77, 37.706, 0. } ;
+
+    return ( poly( audiogram_polynomial_coeficients, log10( frequency ) ) ) ;
+}
+
+double Audiogram( frequency )
+	   double frequency ;
+{
+    return ( pow( 10., -dBAudiogram( frequency ) / 20. ) ) ;
+}
+
+
+/* old versions of above */
+
+static double erb_a  = {  6.23e-6 },
+	      erb_b  = { 93.39e-3 },
+	      erb_c  = { 28.52    } ;
+
+/* erb rate function coeficients */
+
+static double erb_k1 = {  11.17   },
+	      erb_k2 = {   0.312  },
+	      erb_k3 = {  14.675  },
+	      erb_k4 = {  43.0    } ;
+
+static double     b0 = {  2661.8  },
+		  b1 = {  3690.1  },
+		  b2 = {  1917.4  },
+		  b3 = {  440.77  },
+		  b4 = {  37.706  } ;
+
+double OldErb( f )
+double f ;
+{
+    return ( erb_a * f * f + erb_b * f + erb_c ) ;
+}
+
+double OldErbScale( f )
+double f ;
+{
+    double fkHz ;
+
+    fkHz = f / 1000. ;
+
+    return ( erb_k1 * log( ( fkHz + erb_k2 ) / ( fkHz + erb_k3 ) ) + erb_k4 ) ;
+}
+
+double OldFofErbScale( E )
+double E ;
+{
+    double tmp ;
+
+    tmp = exp( ( E - erb_k4 ) / erb_k1 ) ;
+
+    return ( ( erb_k2 - erb_k3 * tmp ) / ( tmp - 1.0 ) * 1000. ) ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter/formulae.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,42 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+
+    formulae.h
+    ==========
+
+
+*/
+
+#define _FORMULAE_H_
+
+/* The Cambridge brians paramters for specifying filter bandwidth */
+
+extern void SetErbParameters() ;
+
+extern double Erb(), ErbScale(), FofErbScale() ;
+
+/* 2nd order polynomial model of human sensitivity as function of frequency */
+
+extern double dBAudiogram(), Audiogram() ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter/gamma_tone.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,178 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+
+     ====================================================================
+      gamma_tone.c - backward compatable interface to new filter release
+     ====================================================================
+
+		   J. Holdsworth - 28th January 1989.
+
+
+    Copywright (c) Applied Psychology Unit, Medical Research Council. 1989.
+    =======================================================================
+
+
+    Release 2:  5th July 1988.
+    Release 3: 20th September 1988.
+    Release 4: 28th January 1989.
+
+*/
+
+#include  <math.h>
+
+#ifndef   _STITCH_H_
+#include  "stitch.h"
+#endif
+#ifndef   _GAMMA_TONE_H_
+#include  "gamma_tone.h"
+#endif
+#ifndef   _FORMULAE_H_
+#include  "formulae.h"
+#endif
+#ifndef   _RECURSE_H_
+#include  "recurse.h"
+#endif
+#ifndef   _SCALES_H_
+#include  "scales.h"
+#endif
+#ifndef   _PHASE_H_
+#include  "phase.h"
+#endif
+
+/* identify object file */
+
+#ifndef lint
+static char *gt_object_ident = GT_IDENT_STRING ;
+#endif
+
+
+/* base center frequency */
+
+#define   Pi                 ( 3.1415926535 )
+#define   TwoPi              ( 2*Pi )
+
+double bankBaseFrequency   = 1000. ;
+double filterDefaultGain   = 4.    ;
+int filterDefaultInputBits = bits_significant ;
+
+
+/* generate array of filter center frequencies between the frequencies specified */
+
+double *GenerateCenterFrequencies( min_cf, max_cf, erb_density )
+double min_cf, max_cf, erb_density ;
+{
+    return ( GenerateScale( ErbScale( min_cf ), ErbScale( max_cf ), erb_density, ErbScale( bankBaseFrequency ), FofErbScale ) ) ;
+}
+
+int NumberCenterFrequencies( min_cf, max_cf, erb_density )
+double min_cf, max_cf, erb_density ;
+{
+    return ( NumberOnScale( ErbScale( min_cf ), ErbScale( max_cf ), erb_density, ErbScale( bankBaseFrequency ) ) ) ;
+}
+
+double *NumberedCenterFrequencies( min_cf, max_cf, channels )
+double min_cf, max_cf ;
+int channels ;
+{
+    return ( NumberedScale( ErbScale( min_cf ), ErbScale( max_cf ), channels, FofErbScale ) ) ;
+}
+
+/* initialise gamma tone filter code */
+
+FilterBankInfo *InitGammaToneFilterBank( samplerate, order, b_scalar, phase_comp, min_filter_cf )
+double samplerate ;
+int order ;
+double b_scalar ;
+int phase_comp ;
+double min_filter_cf ;
+{
+    DeclareNew( FilterBankInfo *, filter_info ) ;
+    extern int n_using_sin_table ;
+
+    filter_info->samplerate = samplerate ;
+    filter_info->order      = order ;
+    filter_info->b_scalar   = b_scalar ;
+    filter_info->phase_comp = phase_comp ;
+
+    /* store maximum required time shift for whole filter bank */
+    /* originally time advance was implemented as delay of     */
+    /* maximum advance minus desired advance (still supported) */
+
+    if( filter_info->phase_comp >= 0 )
+	filter_info->max_desired_advance_time = 1. / min_filter_cf * filter_info->phase_comp ;
+    else
+	filter_info->max_desired_advance_time = ( filter_info->order - 1. ) / ( TwoPi * filter_info->b_scalar * Erb( min_filter_cf ) ) ;
+
+    return ( filter_info ) ;
+}
+
+FilterChannelInfo *InitGammaToneFilterChannel( filter_info, cf )
+FilterBankInfo *filter_info ;
+double cf ;
+{
+    RecursiveFilterState *filter_state ;
+    double sample_delay ;
+
+    if( filter_info->phase_comp > 0 || filter_info->phase_comp == ENVELOPE_ALIGNMENT || filter_info->phase_comp == FINE_ALIGNMENT )
+	sample_delay = filter_info->max_desired_advance_time * filter_info->samplerate ;
+    else
+	sample_delay = 0. ;
+
+    filter_state = NewRecursiveFilter(
+		       filter_info->samplerate,
+		       cf,
+		       Erb( cf ) * filter_info->b_scalar,
+		       filterDefaultGain,
+		       filter_info->order,
+		       filter_info->phase_comp,
+		       filterDefaultInputBits,
+		       & sample_delay ) ;
+
+    return( ( FilterChannelInfo * ) NewPhaseCompensator(
+				       ( FilterState ) filter_state,
+				       ( FilterModule ) 0,
+				       sample_delay ) ) ;
+}
+
+/* end processing of channel - free state varibales */
+
+void EndChannel( channel_info )
+FilterChannelInfo *channel_info ;
+{
+    FreeCompensatedFilter( ( PhaseCompensatorState * ) channel_info ) ;
+
+    return ;
+}
+
+/* free up filter state variables and sin table if finished with it */
+
+void EndFilter( filter_info )
+FilterBankInfo *filter_info ;
+{
+    Delete( filter_info ) ;
+
+    return ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter/gamma_tone.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,116 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+
+	 ==============================================================
+	  gamma_tone.h - portable recursive auditory filter bank code.
+	 ==============================================================
+
+		   J. Holdsworth - 23rd February 1988.
+
+
+    Copywright (c) Applied Psychology Unit, Medical Research Council. 1988.
+    =======================================================================
+
+
+    Release 2: 5th July 1988.
+    Release 3: 20th September 1988.
+    Rewrite :  21st January 1988.
+
+*/
+
+#define   _GAMMA_TONE_H_
+
+#define   GT_IDENT_STRING    "@(#)gamma_tone.h	1.5 J. Holdsworth (MRC-APU) 1/30/90\n"
+
+
+/* number of bits significant in input data */
+
+#define   bits_significant   12
+
+
+/* structure storing information common to all channels in filter */
+
+typedef struct _bank_info FilterBankInfo, *FilterBankInfoPtr ;
+
+struct _bank_info { double samplerate, b_scalar, max_desired_advance_time ;
+	   int order, phase_comp ; } ;
+
+
+/* structure storing information specific to state of particualr channel's filter */
+
+typedef char FilterChannelInfo, *FilterChannelInfoPtr ;
+
+
+extern double *GenerateCenterFrequencies(
+#ifdef vaxc
+double min_cf, double max_cf, double erb_density
+#endif
+) ;
+
+extern int NumberCenterFrequencies(
+#ifdef vaxc
+int min_cf, double max_cf, double erb_density
+#endif
+) ;
+
+extern double *NumberedCenterFrequencies(
+#ifdef vaxc
+double min_cf, double max_cf, int channels
+#endif
+) ;
+
+extern  double bandwidth_normalisation() ;
+
+
+extern  FilterBankInfo    *InitGammaToneFilterBank() ;
+extern  FilterChannelInfo *InitGammaToneFilterChannel() ;
+extern  void EndChannel() ;
+extern  void EndFilter() ;
+
+extern  int FilterShortDataArray() ;
+extern  int RealFilterShortDataArray() ;
+extern  int FilterIntDataArray() ;
+extern  int RealFilterIntDataArray() ;
+extern  int RealFilterDoubleDataArray() ;
+
+/* envelope functions */
+
+extern  int EnvelopeShortDataArray() ;
+extern  int RealEnvelopeShortDataArray() ;
+
+
+/* for compatability with release 1 */
+
+#define  InitGammaToneFilter InitGammaToneFilterBank
+#define  FilterDataArray     FilterShortDataArray
+#define  erb( _f )           Erb( _f )
+#define  erb_rate( _f )      ErbRate( _f )
+#define  f_of_erb_rate( _E ) FofErbRate( _E )
+#define  bandwidth_divisor   bandwidth_normalisation
+
+/* missing parameters availiable as globl variables */
+
+extern double filterDefaultGain ;
+extern int filterDefaultInputBits ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter/generic.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,481 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+*/
+
+/*
+	 ========================================================
+	  generic.c generic C code for recursive filter section.
+	 ========================================================
+
+
+		   J. Holdsworth - 23rd February 1988.
+
+
+    Copywright (c) Applied Psychology Unit, Medical Research Council. 1988.
+    =======================================================================
+
+
+    Release 2:  5th July 1988.
+    Rewrite  :  21st Jan 1989.
+
+*/
+
+#ifndef  _MATH_H_
+#include <math.h>
+#define  _MATH_H_
+#endif
+
+#ifndef  _STITCH_H_
+#include "stitch.h"
+#endif
+#ifndef  _RECURSE_H_
+#include "recurse.h"
+#endif
+#ifndef  _PHASE_H_
+#include "phase.h"
+#endif
+#ifndef  _GAMMA_TONE_H_
+#include "gamma_tone.h"
+#endif
+
+#ifndef  FLOAT
+
+#define STATE_TYPE long
+
+#define I_SHIFT( _number ) ( ( _number ) << i_shift )
+
+#ifdef  vax
+#define K_SHIFT( _number ) ( ( _number ) << k_shift )
+#define S_SHIFT( _number ) ( ( _number ) << s_shift )
+#else
+#define K_SHIFT( _number ) ( ( _number ) >> k_shift )
+#define S_SHIFT( _number ) ( ( _number ) >> s_shift )
+#endif
+
+#else
+
+#define STATE_TYPE FLOAT
+
+#define I_SHIFT( _number ) ( _number )
+#define K_SHIFT( _number ) ( _number )
+#define S_SHIFT( _number ) ( _number )
+
+#endif
+
+#ifndef INPUT_TYPE
+#define INPUT_TYPE short
+#endif
+
+#ifndef OUTPUT_TYPE
+#define OUTPUT_TYPE INPUT_TYPE
+#endif
+
+#ifndef MODULE_NAME
+#define MODULE_NAME DoFilterShortDataArray
+#define FILTER_NAME   FilterShortDataArray
+#endif
+
+#ifdef DSP32
+
+#define SIN( _PHI ) ( *( (float *) ( (char *) sin_table + istore ) ) )
+#define COS( _PHI ) ( *( (float *) ( (char *) cos_table + istore ) ) )
+
+#else
+
+#define SIN( _PHI ) ( sin_table[ HI( _PHI ) ] )
+#define COS( _PHI ) ( cos_table[ HI( _PHI ) ] )
+
+#endif
+
+/* Code that performs the actual filtering */
+
+PointCount MODULE_NAME( filter_states, delays, input, output, points, channels )
+RecursiveFilterState **filter_states ;
+int *delays ;
+ INPUT_TYPE *input ;
+OUTPUT_TYPE *output ;
+int points, channels ;
+{
+extern char *bstart, *bend ;
+#ifdef DSP32
+    /* do not change the order of these definitions - the "asm()" calls depend on it */
+    register STATE_TYPE k, *states_ptr, *states_out, *states_end, *ptr ;
+#else
+    register STATE_TYPE *states_ptr, *states_end, store, rstore, istore, k ;
+#endif
+    register RecursiveFilterState *filter_state ;
+#ifndef FLOAT
+    register int k_shift, s_shift, i_shift ;
+#endif
+#ifdef DSP32
+    register int istore ;
+#endif
+    register Table sin_table, cos_table ;
+    register STATE_TYPE output_store, input_store ;
+#ifdef COMPLEX
+    register STATE_TYPE ioutput_store ;
+#endif
+    register OUTPUT_TYPE *output_ptr, *end ;
+    register INPUT_TYPE  *input_ptr ;
+    int loop_count, channel ;
+#ifdef DSP32
+#ifndef ASM
+    STATE_TYPE a0, a1 ;
+#endif
+#endif
+    /* set up register pointers for speed of inner loop */
+
+    sin_table = filterSineTable   ;
+    cos_table = filterCosineTable ;
+
+    end = output + points * channels ;
+
+    /* for all channels */
+
+    for( channel=0 ; channel < channels ; channel++ ) {
+
+	filter_state = filter_states[ channel ] ;
+
+#ifndef FLOAT
+	i_shift = 16 - filter_state->input_bits ;
+	k_shift = 16 - 2 ;
+
+	s_shift = filterSineTableShift ;
+#endif
+
+	/* if first time then perform implementation specific initialisation */
+
+	if( filter_state->states == (Pointer) 0 ) {
+
+	    filter_state->states = stitch_ralloc( (unsigned) ( filter_state->order + 1 ) * 2 * sizeof ( STATE_TYPE ), "generic.c for filter states" ) ;
+
+	    /* filter state stored in form of complex phasor for each cascade of filter */
+	    /* real and imaginary state values interleaved in state array */
+
+	    filter_state->states_end = (Pointer) ( (STATE_TYPE *) filter_state->states + ( filter_state->order + 1 ) * 2 ) ;
+
+	    stitch_bzero( filter_state->states, (int) ( filter_state->states_end - filter_state->states ) ) ;
+
+#ifdef  FLOAT
+	    filter_state->output_scale /= ( 1l << filterSineTableShift ) ;
+#ifdef  ENVELOPE
+	    filter_state->post_log = -log10( filter_state->output_scale ) * 2000. ;
+#else
+	    filter_state->output_scale /= ( 1l << filterSineTableShift ) ;
+#endif
+#else
+	    filter_state->ik = filter_state->k * ( 1l << k_shift ) + 0.5 ;
+	    filter_state->post_divisor  = ( 1l << ( filterSineTableShift + i_shift ) ) / filter_state->output_scale + 0.5 ;
+#ifdef  ENVELOPE
+	    filter_state->post_log = imB( (long) filter_state->post_divisor ) - imB( 1l << filterSineTableShift ) ;
+#endif
+#endif
+#ifdef  ENVELOPE
+	    filter_state->post_log -= ( filter_state->over_sample - 1 ) * imB( 2l ) / 2 ;
+#endif
+	}
+
+#ifdef  FLOAT
+	k = filter_state->k  ;
+#else
+	k = filter_state->ik ;
+#ifdef  vax
+	k_shift = -k_shift ;
+	s_shift = -s_shift ;
+#endif
+#endif
+
+
+	/* Eurgh - the price of compatability */
+
+	if( input    == (INPUT_TYPE *) 0 ) {
+	    input_ptr = (INPUT_TYPE *) output ;
+
+	    stitch_bzero( input_ptr, ( end - output ) / channels * sizeof ( *input_ptr ) ) ;
+	}
+	else
+	    input_ptr = input - delays[ channel ] ;
+
+/* not required to test bank.c any more
+	if( (char *) input_ptr < bstart || (char *) ( input_ptr + points ) > bend )
+	    printf( "Filter bank error!! %x %x %x\n", bstart, input_ptr, bend ) ;
+*/
+	states_end   = (STATE_TYPE *) filter_state->states_end ;
+
+#ifdef DSP32
+	/* this section is optimised for DSP32 processor with more registers than instructions */
+
+	for( output_ptr = output + channel ; output_ptr < end ; output_ptr += channels ) {
+
+	    input_store  = I_SHIFT( *input_ptr++ ) ;
+	    output_store = 0 ;
+#ifdef COMPLEX
+	    ioutput_store = 0 ;
+#endif
+
+	    loop_count = filter_state->over_sample ;
+
+	    do
+	    {
+		/* multipy by complex phasor */
+
+		ptr = &input_store ;
+
+		istore = HI( filter_state->phi ) << 1 << 1 ;
+
+#ifdef ASM
+		asm( "r1e =  r6  +  r8" ) ;
+		asm( "a0  = *r10 * *r1" ) ;
+		asm( "r2e =  r7  +  r8" ) ;
+		asm( "a1  = *r10 * *r2" ) ;
+#else
+		a0 = *ptr * COS( filter_state->phi ) ;
+		a1 = *ptr * SIN( filter_state->phi ) ;
+#endif
+
+		/* low pass filter by simple alfa decay difference equation */
+
+		states_ptr  = (STATE_TYPE *) filter_state->states ;
+		states_out  =  states_ptr ;
+
+#ifdef ASM
+		asm( "LOOP:" ) ;
+		    asm( "a0 = a0 - *r13++" ) ;
+		    asm( "a1 = a1 - *r13++" ) ;
+		    asm( "nop" ) ;
+		    asm( "*r12++ = a0 = *r12 + a3 * a0" ) ;
+		asm( "r13e - r11" ) ;
+		asm( "if(cc) goto EXIT" );
+		    asm( "*r12++ = a1 = *r12 + a3 * a1" ) ;
+
+		    asm( "         a2 =  a0  - *r13++ " ) ;
+		    asm( "         a1 =  a1  - *r13++ " ) ;
+		    asm( "         a0 = *r12          " ) ;
+		    asm( "*r12++ = a2 = *r12 + a3 * a2" ) ;
+		    asm( "         a2 =  a1           " ) ;
+		    asm( "         a1 = *r12          " ) ;
+		asm( "r13e - r11" ) ;
+		asm( "if(cs) goto LOOP" );
+		    asm( "*r12++ = a2 = *r12 + a3 * a2" ) ;
+		asm( "EXIT:" ) ;
+#else
+		do
+		{
+		    a0 = a0 - *states_ptr++ ;
+		    a1 = a1 - *states_ptr++ ;
+		    a0 = *states_out++ += k * a0 ;
+		    a1 = *states_out++ += k * a1 ;
+		}
+		while( states_ptr < states_end ) ;
+		/* multiply back up to carrier frequency */
+#endif
+		istore = HI( filter_state->output_phi ) << 1 << 1 ;
+
+#ifndef     ENVELOPE
+#ifdef ASM
+		asm( "r1e = r6 + r8" ) ;
+		asm( "a2  = a2 + a0 * *r1" ) ;
+		asm( "r2e = r7 + r8" ) ;
+		asm( "a2  = a2 + a1 * *r2" ) ;
+#else
+		output_store += a0 * COS( filter_state->output_phi ) ;
+		output_store += a1 * SIN( filter_state->output_phi ) ;
+#endif
+#ifdef COMPLEX
+		ptr = &ioutput_store ;
+#ifdef ASM
+		asm( "       a0 = *r10 + a0 * *r2" ) ;
+		asm( "*r10 = a0 =   a0 - a1 * *r1" ) ;
+#else
+	       ioutput_store += a0 * SIN( filter_state->output_phi ) ;
+	       ioutput_store -= a1 * COS( filter_state->output_phi ) ;
+#endif
+#endif
+#else       ENVELOPE
+#ifdef ASM
+		asm( "a2 = a2 + a1 * a1" ) ;
+		asm( "a2 = a2 + a0 * a0" ) ;
+#else
+		output_store += a0 * a0 ;
+		output_store += a1 * a1 ;
+#endif
+#endif      ENVELOPE
+
+		ALL( filter_state->phi ) += filter_state->delta_phi ;
+	    }
+	    while( --loop_count > 0 ) ;
+	    /* do it again if over sampling */
+
+#else
+	/* this section optimised for generall purpose processor e.g. vax or 68000 */
+
+	for( output_ptr = output + channel ; output_ptr < end ; output_ptr += channels ) {
+
+	    input_store  = I_SHIFT( *input_ptr++ ) ;
+
+	    output_store = 0 ;
+#ifdef COMPLEX
+	    ioutput_store = 0 ;
+#endif
+	    loop_count = filter_state->over_sample ;
+
+	    do
+	    {
+		/* multipy by complex phasor */
+
+		states_ptr = (STATE_TYPE *) filter_state->states + 2 ;
+
+		rstore = input_store * COS( filter_state->phi ) ;
+		istore = input_store * SIN( filter_state->phi ) ;
+
+		do
+		{
+		    rstore = *states_ptr + k * K_SHIFT( rstore - *states_ptr ) ;
+		    *states_ptr++ = rstore ;
+
+		    istore = *states_ptr + k * K_SHIFT( istore - *states_ptr ) ;
+		    *states_ptr++ = istore ;
+
+		    if( states_ptr < states_end ) {
+			store = k * K_SHIFT( rstore - *states_ptr ) ;
+			rstore = *states_ptr ;
+			*states_ptr++ = rstore + store ;
+
+			store = k * K_SHIFT( istore - *states_ptr ) ;
+			istore = *states_ptr ;
+			*states_ptr++ = istore + store ;
+		    }
+		}
+		while( states_ptr < states_end ) ;
+/*
+		*states_ptr++ = input_store * COS( filter_state->phi ) ;
+		*states_ptr++ = input_store * SIN( filter_state->phi ) ;
+
+		do
+		{
+		    store = k * K_SHIFT( states_ptr[ -2 ] - *states_ptr ) ;
+		    *states_ptr++ += store ;
+		    store = k * K_SHIFT( states_ptr[ -2 ] - *states_ptr ) ;
+		    *states_ptr++ += store ;
+		}
+		while( states_ptr < states_end ) ;
+*/
+		/* multiply back up to carrier frequency */
+
+#ifdef     ENVELOPE
+		istore = S_SHIFT( istore ) ;
+		output_store  +=  istore * istore   ;
+		rstore = S_SHIFT( rstore ) ;
+		output_store  +=  rstore * rstore   ;
+#else
+		 output_store += S_SHIFT( istore ) * SIN( filter_state->output_phi ) ;
+		 output_store += S_SHIFT( rstore ) * COS( filter_state->output_phi ) ;
+#ifdef COMPLEX
+		ioutput_store -= S_SHIFT( istore ) * COS( filter_state->output_phi ) ;
+		ioutput_store += S_SHIFT( rstore ) * SIN( filter_state->output_phi ) ;
+#endif
+#endif
+		ALL( filter_state->phi ) += filter_state->delta_phi ;
+		ALL( filter_state->phi ) &= filterSineTableMask ;
+	    }
+	    while( --loop_count > 0 ) ;
+	    /* do it again if over sampling */
+#endif
+
+/* common tail end */
+
+#ifdef ENVELOPE
+#ifdef  FLOAT
+	    if( output_store < 1. )
+		*output_ptr = LOG_ZERO ;
+	    else
+		*output_ptr = log10(      output_store ) * 1000. - filter_state->post_log ;
+
+	    if( *output_ptr < 0. )
+		*output_ptr = 0. ;
+#else
+	    *output_ptr = ( imB( (long)   output_store ) >> 1  ) - filter_state->post_log ;
+
+	    if( *output_ptr < 0 )
+		*output_ptr = 0 ;
+#endif
+#else
+	    /* for non-envelope output */
+
+	    ALL( filter_state->output_phi ) += filter_state->output_delta_phi ;
+#ifndef DSP32
+	    ALL( filter_state->output_phi ) &= filterSineTableMask ;
+#endif
+
+	    /* scale output_ptr back down for output_ptr array compensating for over sampling if ness. */
+
+#ifdef COMPLEX
+#ifdef  FLOAT
+	    output_ptr->real =  output_store * filter_state->output_scale ;
+	    output_ptr->imag = ioutput_store * filter_state->output_scale ;
+#else
+	    output_ptr->real =  output_store / filter_state->post_divisor ;
+	    output_ptr->imag = ioutput_store / filter_state->post_divisor ;
+#endif
+#else
+#ifdef  FLOAT
+	   *output_ptr       =  output_store * filter_state->output_scale ;
+#else
+	   *output_ptr       =  output_store / filter_state->post_divisor ;
+#endif
+#endif
+#endif
+	}
+    }
+
+    return( sizeof ( OUTPUT_TYPE ) ) ;
+}
+
+/* for compatability */
+
+PointCount FILTER_NAME( compensator_state, input_array, output_array, npoints )
+FilterChannelInfo *compensator_state ;
+INPUT_TYPE *input_array ;
+OUTPUT_TYPE *output_array ;
+PointCount npoints ;
+{
+    ( (PhaseCompensatorState *) compensator_state )->filter_module = MODULE_NAME ;
+
+    return( PhaseCompensateFilter( (PhaseCompensatorState *) compensator_state, ( Pointer ) input_array, ( Pointer ) output_array, npoints ) ) ;
+}
+
+
+/* tidy up defines for redefinition */
+
+#undef  STATE_TYPE
+#undef  INPUT_TYPE
+#undef OUTPUT_TYPE
+#undef FILTER_NAME
+#undef MODULE_NAME
+#undef I_SHIFT
+#undef K_SHIFT
+#undef S_SHIFT
+
+#undef SIN
+#undef COS
+
+#ifdef FLOAT
+#undef FLOAT
+#endif
+
+#ifdef COMPLEX
+#undef COMPLEX
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter/imb.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,62 @@
+/*
+    imb.c
+    =====
+
+    integer version of logarithms using units of milliBells.
+
+*/
+
+#include <math.h>
+
+#include "stitch.h"
+
+#define LOG_ZERO (-10)
+
+int imB( number )
+long number ;
+{
+    register int i, out ;
+    register long in ;
+    static int precision = 12 ;
+    static int *table = { ( int * ) 0 } ;
+    static unsigned table_size ;
+    static int inc ;
+    double k ;
+
+    if( table == ( int * ) 0 ) {
+
+	table_size = 1 << precision ;
+
+	k   = 2000. / log( 10. ) ;
+	inc = k     * log(  2. ) + 0.5 ;
+
+	table = (int *) stitch_malloc( table_size * sizeof( *table ), "imb.c for log table" ) ;
+
+	for( i=0 ; i < table_size ; i++ )
+	    table[ i ] = log( (double) ( table_size + i ) / table_size ) * k + 0.5 ;
+    }
+
+    if( number > 0 ) {
+
+	in = number ;
+
+	out = precision * inc ;
+
+	if( number < table_size )
+	    do {
+		in <<= 1 ;
+		out -= inc ;
+	    }
+	    while( in < table_size ) ;
+	else
+	    while( in - table_size >= table_size ) {
+		in >>= 1 ;
+		out += inc ;
+	    }
+
+	return( out + table[ in - table_size ] ) ;
+    }
+    else
+	return ( LOG_ZERO ) ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter/makefile	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,58 @@
+###########################################################################
+#
+#  Makefile for AIM filterbank library:  libfilter.a
+#
+#   (For convenience, this makefile directly calls the root makefile).
+#
+#   @(#)makefile        1.35 J. Holdsworth, (MRC-APU)  6/6/91
+#                            M. Allerhand,  (MRC-APU) 26/1/93
+#
+#
+###########################################################################
+
+
+default : install
+
+SDIR = ../stitch
+
+FLIB = libfilter.a
+
+INCLUDES  =  -I$(SDIR)
+
+.c.o :
+	$(CC) $(CFLAGS) $(INCLUDES) -c $<
+
+
+############################################################################
+# Make filterbank library.
+
+OBJS = gamma_tone.o phase.o recurse.o all.o imb.o scales.o formulae.o
+
+lib $(FLIB) : $(OBJS)
+	ar rc $@ $? ; $(RANLIB) $@
+
+
+############################################################################
+# dependencies
+
+gamma_tone.o:   $(SDIR)/stitch.h gamma_tone.h formulae.h recurse.h scales.h phase.h
+phase.o:        $(SDIR)/stitch.h phase.h
+recurse.o:      $(SDIR)/stitch.h recurse.h
+all.o:          $(SDIR)/stitch.h phase.h generic.c recurse.h gamma_tone.h
+scales.o:       scales.h
+formulae.o:     formulae.h
+
+############################################################################
+# Make targets in root makefile.
+
+TARGETS   = main        install     all         sources \
+	    links       alllinks    demo        tar     \
+	    ftp         tape        mail        clean   \
+	    sccslinks   cleansccs   help        noplot
+
+$(TARGETS) : FORCE
+	@ cd .. ; make $@
+FORCE:
+
+
+############################################################################
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter/phase.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,132 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+	phase.c
+	=======
+
+    looks after phase compensation of all filter types
+
+
+*/
+
+#include "stitch.h"
+#include "phase.h"
+
+
+PhaseCompensatorState *NewPhaseCompensator( filter_state, filter_module, sample_delay )
+FilterState  filter_state ;
+FilterModule filter_module ;
+double       sample_delay ;
+{
+    DeclareNew( PhaseCompensatorState *, compensator_state ) ;
+
+    compensator_state->filter_state  = filter_state  ;
+    compensator_state->filter_module = filter_module ;
+    compensator_state->sample_delay  = sample_delay + 0.5 ;
+
+    compensator_state->delay_buffer  = ( Pointer ) 0 ;
+
+    return( compensator_state ) ;
+}
+
+PointCount PhaseCompensateFilter( compensator_state, input, output, points )
+PhaseCompensatorState *compensator_state ;
+Pointer input ;
+Pointer output ;
+PointCount points ;
+{
+    unsigned output_size ;
+    int byte_delay, bytes ;
+    PointCount process ;
+    Pointer input_ptr ;
+    static int zero = 0 ;
+
+    /* support for new and old zero point transfers to get any remaining
+	data from filters - in short a mess */
+
+    if( compensator_state->sample_delay < 0 && ( input == ( Pointer ) 0 || points == 0 ) ) {
+	process = - ( int ) compensator_state->sample_delay ;
+
+	if( process > points && points != 0 )
+	    process = points ;
+
+	compensator_state->sample_delay = ( int ) compensator_state->sample_delay + process ;
+
+	input_ptr = ( Pointer ) 0 ;
+    }
+    else {
+	process = points ;
+	input_ptr = input ;
+    }
+
+    /* call filter pod */
+
+    output_size = compensator_state->filter_module(
+		      &compensator_state->filter_state,
+		      &zero,
+		      input_ptr,
+		      output,
+		      process,
+		      1
+		  ) ;
+
+    byte_delay = ( int ) compensator_state->sample_delay * output_size ;
+    bytes = points * output_size ;
+
+    if( compensator_state->delay_buffer == ( Pointer ) 0 )
+	if( ( int ) compensator_state->sample_delay < 0 ) {
+	    stitch_bcopy( output - byte_delay, output, bytes - byte_delay ) ;
+	    compensator_state->delay_buffer   = ( Pointer ) 0 + 1 ;
+
+	    return( points + ( int ) compensator_state->sample_delay ) ;
+	}
+	else
+	    compensator_state->delay_buffer = stitch_calloc(
+				 ( unsigned ) compensator_state->sample_delay * 2,
+					      output_size, "phase.c for delay buffer\n" ) ;
+
+    if( byte_delay > bytes ) {
+	stitch_bcopy( output, compensator_state->delay_buffer + byte_delay, bytes ) ;
+	stitch_bcopy( compensator_state->delay_buffer, output, bytes ) ;
+	stitch_bcopy( compensator_state->delay_buffer + bytes, compensator_state->delay_buffer, byte_delay ) ;
+    }
+    else if( byte_delay > 0 ) {
+	stitch_bcopy( output + bytes - byte_delay, compensator_state->delay_buffer + byte_delay, byte_delay ) ;
+	stitch_bcopy( output, output + byte_delay,  bytes - byte_delay ) ;
+	stitch_bcopy( compensator_state->delay_buffer, output, byte_delay ) ;
+	stitch_bcopy( compensator_state->delay_buffer + byte_delay, compensator_state->delay_buffer, byte_delay ) ;
+    }
+
+    return( process ) ;
+}
+
+void FreeCompensatedFilter( compensator_state )
+PhaseCompensatorState *compensator_state ;
+{
+    stitch_free( compensator_state->filter_state ) ;
+    stitch_free( ( Pointer ) compensator_state ) ;
+
+    return ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter/phase.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,55 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    phase.h
+    =======
+
+    defines for phase compensation functionality
+
+*/
+
+#define _PHASE_H_
+
+
+typedef Pointer FilterState ;
+typedef int (*FilterModule)() ;
+typedef int PointCount ;
+
+typedef struct _phase_compensator_state PhaseCompensatorState ;
+
+extern PhaseCompensatorState *NewPhaseCompensator() ;
+extern PointCount PhaseCompensateFilter() ;
+extern void FreeCompensatedFilter() ;
+
+/* private data for phase compensators */
+
+
+struct _phase_compensator_state {
+    FilterState  filter_state  ;
+    FilterModule filter_module ;
+    int          sample_delay  ;
+    Pointer      delay_buffer  ;
+    } ;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter/recurse.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,235 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+             ================================================
+              recurse.c - start-up code for recursive filter
+             ================================================
+
+
+    Copyright (c), 1989  The Medical Research Council, Applied Psychology Unit.
+
+
+    Author  : John Holdsworth
+    Written : 22th March, 1989.
+
+    Edited  :
+
+*/
+
+
+#include <math.h>
+
+#ifndef  _STITCH_H_
+#include "stitch.h"
+#endif
+
+#ifndef  _RECURSE_H_
+#include "recurse.h"
+#endif
+
+#define   Pi                 ( 3.1415926535 )
+#define   TwoPi              ( 2*Pi )
+
+#ifndef  lint
+static char *sccs_id = "@(#)recurse.c	1.8 John Holdsworth (MRC-APU) 11/8/90" ;
+#endif
+
+static void generateSineTable() ;
+static double factorial() ;
+
+#ifdef DSP32
+int filterSineTableBits  =  8 ;
+int filterSineTableShift =  0 ;
+#else
+int filterSineTableBits  = 12 ;
+int filterSineTableShift = 14 ;
+#endif
+unsigned long filterSineTableSize, filterSineTableMask ;
+Table filterSineTable, filterCosineTable ;
+
+char *bstart, *bend ;
+
+
+RecursiveFilterState *NewRecursiveFilter( samplerate, center_frequency, bandwidth, output_scale, order, phase_compensation, input_bits, sample_delay )
+double samplerate, center_frequency, bandwidth, output_scale ;
+int order, phase_compensation, input_bits ;
+double *sample_delay ;
+{
+    DeclareNew( RecursiveFilterState *, filter_state ) ;
+    double omega ;
+
+    if( filterSineTableSize != 1 << filterSineTableBits )
+	generateSineTable() ;
+
+    filter_state->order        = order        ;
+    filter_state->input_bits   = input_bits   ;
+
+    /* compensation for nominal 6dB loss in filter */
+
+    filter_state->output_scale = output_scale * 2. ;
+
+    omega = TwoPi * bandwidth / bandwidth_normalisation( filter_state->order ) ;
+
+    /* delta phi of carrier between sample ticks */
+
+    filter_state->output_delta_phi = center_frequency / samplerate * ( filterSineTableSize << 16 ) + 0.5 ;
+    filter_state->delta_phi        = filter_state->output_delta_phi ;
+
+    /* initialise phases to give rounding */
+
+    ALL( filter_state->phi ) = ALL( filter_state->output_phi ) = 1l << 15 ;
+
+    /* calculate time delay required for phase compensation selected */
+    /* time advance is currently implemented as delay of       */
+    /* maximum advance minus desired advance                   */
+
+    if( center_frequency < samplerate / 4 )
+	filter_state->over_sample = 1 ;
+    else {
+	/* if center frequency is over half the nyquist rate filtering process */
+	/* is performed at twice the sampling rate to avoid aliases */
+
+	filter_state->over_sample = 2 ;
+
+	ALL( filter_state->phi ) -= filter_state->delta_phi / 4 ;
+#ifndef DSP32
+	ALL( filter_state->phi ) &= filterSineTableMask ;
+#endif
+	filter_state->delta_phi /= 2 ;
+
+	/* must amplitude compensate for attenuation of high frequencies introduced by over sampling */
+
+	filter_state->output_scale /= ( filter_state->over_sample * cos( TwoPi * center_frequency / samplerate / 4 ) ) ;
+    }
+
+    filter_state->k = ( double ) 1. - exp( -omega / samplerate / filter_state->over_sample ) ;
+
+    /* fiddle delay time to take into acount half sample  */
+    /* interval advance introduced by difference equation */
+
+#if 0 /* not needed any more as alternate forward and backward differences */
+
+    *sample_delay += filter_state->order / filter_state->over_sample / 2 ;
+
+    /* compensate carrier phase for delay introduced above */
+
+    ALL( filter_state->output_phi ) += filter_state->order / filter_state->over_sample / 2 *
+			    filter_state->delta_phi * filter_state->over_sample ;
+#ifndef DSP32
+    ALL( filter_state->output_phi ) &= filterSineTableMask ;
+#endif
+#endif
+
+    /* munge to sin phase gammatone for mfsais */
+
+    ALL( filter_state->output_phi ) += 3 * filterSineTableMask / 4  ;
+
+    /* perform required phase compensation */
+
+    if( phase_compensation > 0 )
+	*sample_delay -= phase_compensation / center_frequency * samplerate ;
+    else if( phase_compensation < 0 )
+	*sample_delay -= ( filter_state->order - 1. ) / omega * samplerate ;
+
+    /* if phase compensation of type -2 or -4 is asked for the carrier phase */
+    /* is shifted to be aligned with the envelope maxima */
+
+    if( phase_compensation == FINE_ALIGNMENT || phase_compensation <= ACUASAL + FINE_ALIGNMENT ) {
+	ALL( filter_state->phi ) += ( filter_state->order - 1. ) / omega * center_frequency * ( filterSineTableSize << 16 ) + 0.5 ;
+#ifndef DSP32
+	ALL( filter_state->phi ) &= filterSineTableMask ;
+#endif
+    }
+
+    /* new recurse filter coefts */
+
+    filter_state->gain = pow(  2 * omega / samplerate, (double) order ) * output_scale ;
+    filter_state->k1   = exp(     -omega / samplerate ) * cos( TwoPi * center_frequency / samplerate ) ;
+    filter_state->k2   = exp( -2 * omega / samplerate ) ;
+
+    /* flag channel not fully initialised */
+    /* leave filter specific initialisation to specific filter code */
+
+    filter_state->states = ( char * ) 0 ;
+
+    /* generate sin lookup table if necessary */
+
+    return ( filter_state ) ;
+}
+
+double bandwidth_normalisation( order )
+int order ;
+{
+    return( Pi * factorial( 2*order - 2 ) / factorial( order - 1 ) / factorial( order - 1 ) / ( 1 << ( 2 * order - 2 ) ) ) ;
+}
+
+static double factorial( n )
+int n ;
+{
+    double fact ;
+    int i ;
+
+    fact = 1. ;
+
+    for( i = n ; i > 1 ; i-- )
+	fact *= i ;
+
+    return( fact ) ;
+}
+
+
+static void generateSineTable()
+{
+    static double filterTwoPi ;
+    register int i ;
+
+    if( filterSineTableSize != 1 << filterSineTableBits )
+    {
+	if( filterSineTable != ( Table ) 0 )
+	    stitch_free( ( Pointer ) filterSineTable ) ;
+
+	if( filterTwoPi == 0. )
+	    filterTwoPi = atan( 1. ) * 8. ;
+
+	filterSineTableSize = 1l << filterSineTableBits ;
+	filterSineTableMask = ( filterSineTableSize << 16 ) - 1 ;
+
+	/* sin table 5/4 times larger than required for cosine values */
+
+	filterSineTable = ( Table ) stitch_malloc( ( unsigned ) ( filterSineTableSize * 5 / 4 + 1 ) * sizeof( *filterSineTable ), "recurse.c for log table" ) ;
+
+	for( i=0 ; i <= filterSineTableSize/4 ; i++ ) {
+	    filterSineTable[ i ] = sin( filterTwoPi * i / filterSineTableSize ) * ( 1<<filterSineTableShift ) ;
+	    filterSineTable[ filterSineTableSize/2 - i ] =  filterSineTable[ i ] ;
+	    filterSineTable[ filterSineTableSize/2 + i ] = -filterSineTable[ i ] ;
+	    filterSineTable[ filterSineTableSize   - i ] = -filterSineTable[ i ] ;
+	    filterSineTable[ filterSineTableSize   + i ] =  filterSineTable[ i ] ;
+	}
+
+	filterCosineTable = filterSineTable + filterSineTableSize / 4 ;
+    }
+
+    return ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter/recurse.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,138 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+*/
+
+/*
+	recurse.h
+	=========
+
+    defines for modular recursive filterbank system
+
+    J.Holdsworth MRC-APU 17th January 1989.
+
+*/
+
+#define _RECURSE_H_
+
+#define NO_PHASE_COMPENSTAION (0)
+#define ENVELOPE_ALIGNMENT   (-1)
+#define FINE_ALIGNMENT       (-2)
+#define ACUASAL              (-2)
+
+#define LOG_ZERO (-10)
+
+#if !defined( LITTLE_FIRST ) && !defined( BIG_FIRST )
+
+#if defined( vax ) || defined( MIPSEL ) || defined( NICHE ) || defined( IBM )
+#define LITTLE_FIRST
+#endif
+
+#if defined( sun ) || defined( MIPSEB ) || defined( mc68000 ) || defined( THINK_C )
+#define BIG_FIRST
+#endif
+
+#endif
+
+#if defined( LITTLE_FIRST )
+
+typedef union { long all ; struct { short lo, hi ; } shorts ; } Phase ;
+#define ALL( _var ) ( _var.all )
+#define HI(  _var ) ( _var.shorts.hi )
+
+#else
+
+#if defined( BIG_FIRST )
+
+typedef union { long all ; struct { short hi, lo ; } shorts ; } Phase ;
+#define ALL( _var ) ( _var.all )
+#define HI(  _var ) ( _var.shorts.hi )
+
+#else
+
+#ifdef DSP32
+
+typedef union { int all ; struct { short lo, hi ; } shorts ; } Phase ;
+#define ALL( _var ) ( ( _var ).all )
+#define HI(  _var ) ( ( _var ).shorts.hi & 0xff )
+
+#else
+
+typedef long Phase ;
+#define ALL( _var ) ( _var )
+#define HI(  _var ) ( ( _var ) >> 16 )
+
+#endif
+
+#endif
+#endif
+
+#ifdef DSP32
+typedef float *Table ;
+#else
+typedef int   *Table ;
+#endif
+
+typedef struct _recursive_filter_state RecursiveFilterState ;
+
+typedef struct { short  real, imag ; } scomplex ;
+typedef struct { int    real, imag ; } icomplex ;
+typedef struct { long   real, imag ; } lcomplex ;
+typedef struct { float  real, imag ; } fcomplex ;
+typedef struct { double real, imag ; } dcomplex ;
+
+
+extern RecursiveFilterState *NewRecursiveFilter() ;
+extern double bandwidth_normalisation() ;
+extern int imB() ;
+
+extern int     DoFilterShortDataArray() ; extern int     DoEnvelopeShortDataArray() ;
+extern int DoRealFilterShortDataArray() ; extern int DoRealEnvelopeShortDataArray() ;
+
+extern int DoRealFilterFloatDataArray() ; extern int DoRealEnvelopeFloatDataArray() ;
+
+extern int DoFilterIntDataArray() ;
+extern int DoRealFilterIntDataArray() ;
+extern int DoRealFilterDoubleDataArray() ;
+extern int DoComplexFilterShortDataArray() ;
+extern int DoComplexFilterFloatDataArray() ;
+
+extern int DoNewFilterDataArray() ;
+
+/* formuale.h for attempt at safety */
+
+extern double Erb(), ErbScale(), FofErbScale(), dBAudiogram(), Audiogram() ;
+
+extern int filterSineTableBits, filterSineTableShift ;
+extern unsigned long filterSineTableSize, filterSineTableMask ;
+extern Table filterSineTable, filterCosineTable ;
+
+
+/* private data structure for filter */
+
+struct _recursive_filter_state {
+    double k, output_scale ;             /* basic real filter parameters */
+    long ik, post_divisor, post_log ;    /* integer versions of basic parameters */
+    int order, over_sample, input_bits ; /* integer filter parameters */
+    char *states, *states_end ;          /* filter state vector */
+    Phase phi, output_phi ;              /* integer phase of complex sinusiod */
+#ifdef DSP32
+    int  delta_phi, output_delta_phi ;   /* phase increments for filter cf */
+#else
+    long delta_phi, output_delta_phi ;   /* phase increments for filter cf */
+#endif
+    float gain, k1, k2 ;                 /* for new filter algorithimn */
+    } ;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter/scales.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,102 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+	scales.c
+	========
+
+    generates double arrays of numbers spaced on arbitrary frequency scales
+
+*/
+
+#include <math.h>
+
+#ifndef  _STITCH_H_
+#include "stitch.h"
+#endif
+#ifndef  _SCALES_H_
+#include "scales.h"
+#endif
+
+double *GenerateScale( min, max, density, base, inverse )
+double min, max, density, base, (*inverse)() ;
+{
+    unsigned n_scale = NumberOnScale( min, max, density, base ) ;
+    double *scale = NewArray( double, n_scale+1, "for scale in scales.c" ) ;
+    double scale_start ;
+    int i ;
+
+    if( min != max ) {
+
+	scale_start = base - floor( ( base - min ) * density ) / density ;
+
+	/* fill array scale points 1./density apart */
+
+	for( i=0 ; i < n_scale  ; i++ )
+	    scale[ i ] = scale_start + i / density   ;
+
+	scale[ i++ ] = 0. ;
+    }
+    else {
+	scale[0] = min ;
+	scale[1] = 0.  ;
+    }
+
+	/* convert scale space back to units required */
+
+    if( inverse != (double ( * )()) 0 )
+	for( i=0 ; i < n_scale  ; i++ )
+	    scale[ i ] = inverse( scale[ i ] ) ;
+
+    return ( scale ) ;
+}
+
+int NumberOnScale( min, max, density, base )
+double min, max, density, base ;
+{
+    if( min != max )
+	return ( ( int ) ( ( floor( ( base - min ) * density ) + 1. + ( floor( ( max - base ) * density ) ) ) ) ) ;
+    else
+	return ( 1 ) ;
+}
+
+double *NumberedScale( min, max, channels, inverse )
+double min, max ;
+int channels ;
+double (*inverse)() ;
+{
+    DeclareNewArray( double, scale, channels+1, "for scale in scales.c" ) ;
+    int chan ;
+
+    scale[ 0 ] = min ;
+    for( chan=1 ; chan < channels  ; chan++ )
+	scale[ chan ] = min + chan * (max-min) / ( channels - 1 ) ;
+
+    if( inverse != (double ( * )()) 0 )
+	for( chan=0 ; chan < channels  ; chan++ )
+	    scale[ chan ] = inverse( scale[ chan ] ) ;
+
+    scale[ channels ] = 0. ;
+
+    return ( scale ) ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filter/scales.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,35 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    scales.h
+    ========
+
+
+*/
+
+#define _SCALES_H_
+
+extern double *GenerateScale() ;
+extern int     NumberOnScale() ;
+extern double *NumberedScale() ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glib/X.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,1459 @@
+
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee
+    is hereby granted for research purposes, provided that this copyright
+    notice appears in all copies and in all supporting documentation, and that
+    the software is not redistributed for any fee (except for a nominal shipping
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this
+    software for any purpose.  It is provided "as is" without express or implied
+    warranty.
+*/
+
+/*******************************************************************************************
+
+ X.c      A GENERIC X-WINDOWS REAR-END FOR THE WINDOWS.H INTERFACE.
+
+
+ This module is derived from the x10.c module, written by John Holdsworth, and the subsequent
+ x11.c module, which was ported by Paul Manson. It attempts to combine the x10/x11 code in
+ such a way as to provide a single uniform application with the minimal amount of #ifdef
+ "noise". It expects to have either X10 or X11 defined as symbols by the preprocessor -- in the
+ event that neither of these is defined, it produces an error message and causes the compiler
+ to exit; ie. there is NO DEFAULT.
+
+ Written: May 3rd. by Paul Manson (but see credits above)
+
+ Edited:
+
+ 15   May   1989  (Paul Manson) -- Altered the <pixels> argument to use <pixels>-1 in the
+                                   newDisplay window call. On X11, pixels of 0 means "use
+                                   thin lines", which always work correctly. Values greater
+                                   than 0 imply "thick lines", which appear to over-write
+                                   each other.
+
+ 05  June   1989  (Paul Manson) -- Removed the offending "warning" message from axes();.
+
+ 27  July   1989  (Johh Holdsworth) -- put in addition loops to segment line drawing
+				   operations for very long lines and put XFlush() in
+				   before pausing. A bug remains in the segentation of
+				   hidden line removal. The Fill operation Paint to hide
+				   lines lower than that just drawn can remove part of
+				   that line - very tricky to avoid. The same problem
+				   seem to be present in ps.c.
+
+ 18 August  1989  (Paul Manson) -- Altered to accomodate the Pixmap/newWindowWindow entry
+                                   which forces un-resizable windows on us with X11.
+
+ 21 August  1989  (Paul Manson) -- Also altered "Clear" so that it does a FillRectangle in
+                                   preference to a ClearWindow. The latter call doesn't work
+				   for Pixmaps (see newWindowWindow, etc).
+
+ 22 August  1989  (Paul Manson) -- In a similar vein to the above, I have altered X.c so that
+                                   two global variables Foreground and Background are used to
+				   determine the colours for drawing and filling.
+
+ 04 September 1989 (Paul Manson) - Altered so that the GXmodes are used to modify the GC for
+                                   clear, draw, etc operations. This seems to be a much more
+				   reliable way in which to manipulate these settings.
+
+ 31 July 1990 (John Holdsworth)  - Extensive changes to remove previous change. GXcopy
+				   now used with foreground appropiately set. This has
+				   proved more portable particularly for Multiplane displays.
+
+
+ 26th May 1993 (Mitch d'Souza & M Akeroyd) - added an extra include - sys/types.h - so that the
+                                   gcc would work on a decstation.
+
+ 3rd August 1993 (M. Akeroyd)   - Removed the 'XAllPlanes' bist of the XGetImage routines,
+                                  so that monochrome bitmaps could be made on colour 
+				  computers.
+				  Also included new SilentOptions :
+				      mono_ctn
+				      colour_ctn
+				      planemask_ctn
+
+ 20th August 1993 (M.Akeroyd)  - First attempt at colour images: two new options fg_col and 
+                                 bg_col, and a complementary procedure define_colour().
+				 These do NOT work with view=grayscale.
+
+                                 ********************************************************************************************/
+
+
+#if !defined(X11) && !defined(X10)
+#define X11
+#endif
+
+#if !defined(X10) && !defined(X11)
+#include "-- YOU MUST DEFINE EITHER X10 or X11 TO USE THIS MODULE"
+#endif
+
+#include <stdio.h>
+#include <malloc.h>
+#include <sys/types.h>
+#include "options.h"        /* Added: MAA 3-8-1993 */
+#if defined(X11)
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>  /* MAA: 20-8-1993. For colour */
+#include <X11/Xos.h>    /* MAA: 20-8-1993. For colour */
+
+
+#else
+#if defined(X10)
+#include <X/Xlib.h>
+#endif
+#endif
+
+#include "windows.h"
+#include "grey.h"
+
+#define FALSE (0)
+#define TRUE  (1)
+#define MAX_FILES   (20)
+#define MAX_SEGMENT (5000)
+#define MAX_ROW     (100)
+#define MAX_COL     (1000)
+#define MAX_IMAGE   (1500)
+#define DITHER_SIZE (8)
+
+extern char *monostr, *colourstr, *planemaskstr;  /* Added: MAA 3-8-1993 */
+int planemask;
+
+static Display *theDisplay = (Display *) 0;   /* The Display Variable */
+static int      theWidth, theHeight;   /* The Width and Height of the Screen in Pixels     */
+
+#define MIN(X,Y) (((X) < (Y)) ? (X) : (Y))
+
+#define USE_PIXMAPS
+
+#if defined(X11)
+static int      theScreen                 ;   /* The associated screen no. */
+static int      synchronous = FALSE ;
+static unsigned long theForeground, theBackground;
+#else
+static char *marker_font_name = "6x10" ;
+static FontInfo *marker_font = ( FontInfo * ) 0 ;
+#endif
+
+typedef struct {
+  windowEntries *entries ;
+  Window w ;
+  int pixels, width, height, hide ;
+  int x, y ;
+#if defined(X11)
+  GC foregroundGC ;
+  GC backgroundGC ;
+  int isMapped ;
+#ifdef USE_PIXMAPS
+  Pixmap imageData[ MAX_IMAGE ];
+#else
+  XImage *imageData[ MAX_IMAGE ];
+#endif
+  XImage *theImage;                  /* Used only for Read operations; The wind__write */
+                                     /* entry point actually creates & destroys images */
+  XImage *rowImage, *colImage ;
+#else
+  int foreground, background ;
+  short *imageData[ MAX_IMAGE ];
+  short *theImage              ;
+#endif
+  struct _lookup *lookup       ;    /* Dithering */
+  int   **diths                ;    /* Dithering */
+  short  *data                 ;    /* Dithering */
+  int     greylength ;
+  int     imageNum ;
+  int     imageSize;
+} *XWindowObject ;
+
+#ifndef  lint
+static char *sccs_id = "@(#)X.c	1.38 Paul Manson, John Holdsworth (MRC-APU) 5/31/91" ;
+#endif
+
+#if defined(X11)
+
+
+
+
+/* MAA: Added 20-8-1993 
+* Colour ....
+* Copied off example 7.2 of Xlib Vol 1. 
+*/
+
+extern char *fgcolourstr;
+extern char *bgcolourstr;
+
+void define_colours()
+{
+  int default_depth;
+  Visual *default_visual;
+  XColor exact_def;
+  Colormap default_cmap;
+  int i=5;
+  XVisualInfo visual_info;
+
+
+  default_depth = DefaultDepth(theDisplay, theScreen);
+  default_visual = DefaultVisual(theDisplay, theScreen);
+  default_cmap = DefaultColormap(theDisplay, theScreen);
+
+/* MAA: Removed this. */
+/*  if (default_depth == 1) {*/
+    /* Black-White Only */
+/*    theForeground = BlackPixel(theDisplay, theScreen);*/
+/*    theBackground = WhitePixel(theDisplay, theScreen);}*/
+
+  /* i = visual class */
+  while (!XMatchVisualInfo(theDisplay, theScreen, default_depth, i--, &visual_info))
+    ;
+
+  if (i<StaticColor) {
+    theForeground = BlackPixel(theDisplay, theScreen);
+    theBackground = WhitePixel(theDisplay, theScreen);}
+
+  else {
+
+    /* Foreground */
+    if (!XParseColor(theDisplay, default_cmap, fgcolourstr, &exact_def)){
+      fprintf(stderr, "Unable to find colour %s in database. Using Black instead. \n", fgcolourstr);
+      theForeground = BlackPixel(theDisplay, theScreen);}
+    else 
+      if (XAllocColor(theDisplay, default_cmap, &exact_def))
+        theForeground = exact_def.pixel;
+      else {
+        fprintf(stderr, "Unable to alloc colour %s. Using Black instead. \n", fgcolourstr);
+        theForeground = BlackPixel(theDisplay, theScreen);}
+    
+    /* Background */
+    if (!XParseColor(theDisplay, default_cmap, bgcolourstr, &exact_def)){
+      fprintf(stderr, "Unable to find colour %s in database. Using White instead. \n", bgcolourstr);
+      theBackground = WhitePixel(theDisplay, theScreen);}
+    else 
+      if (XAllocColor(theDisplay, default_cmap, &exact_def))
+        theBackground = exact_def.pixel;
+      else {
+        fprintf(stderr, "Unable to alloc colour %s. Using White instead. \n", bgcolourstr);
+        theBackground = WhitePixel(theDisplay, theScreen);}
+  }
+}
+
+
+
+
+extern void InitializeX(display, screen, foreground, background)
+     Display      *display   ;
+     int           screen    ;
+     unsigned long foreground;
+     unsigned long background;
+{
+  if (theDisplay == (Display *) 0) {
+    theDisplay    = display   ;
+    theScreen     = screen    ;
+    theForeground = foreground;
+    theBackground = background;
+  }
+  else {
+    (void) fprintf(stderr, "Error! The X.c Display Variable has already been set...\nIt is invalid to call InitializeX after this has happened (eg. by a call to newDisplayWindow).\n");
+    exit(1);
+  }
+}
+
+/* not a nice routine to wait untill window is actually mapped before returning it's size */
+
+static void waitTillMapped( info )
+XWindowObject info ;
+{
+    XWindowAttributes at ;
+
+    if( !info->isMapped ) {
+	do
+	    XGetWindowAttributes( theDisplay, info->w, &at ) ;
+	while ( at.map_state == IsUnmapped ) ;
+
+	info->isMapped = 1 ;
+
+	info->width  = at.width  ;
+	info->height = at.height ;
+    }
+
+    return ;
+}
+
+/* ---------------- Beware! This function may be the most dangerous thing ---------------
+   ----------------         to ever appear on a DecStation... it makes    ---------------
+   ----------------         sweeping assumptions about the way that data  ---------------
+   ----------------         is stored in the X server. If it EVER happens ---------------
+   ----------------         that the X Consortium write routines for I/O  ---------------
+   ----------------         of Screen Images, THROW THIS AWAY!            --------------- */
+static int ImageSizeInBytes(image)
+     XImage *image;
+{
+
+   /* Cribbed from X11R3/.../xwd.c */
+
+   return(image->bytes_per_line * image->height * image->depth);
+
+}
+
+
+static setupImage( w )
+XWindowObject w ;
+{
+    if( w->theImage == ( XImage * ) 0 ) {
+	w->theImage = XGetImage(theDisplay, w->w, 0, 0, w->entries->width(w),
+			       w->entries->height(w), planemask, XYPixmap);
+	w->imageSize = ImageSizeInBytes(w->theImage);
+    }
+}
+
+
+
+#endif
+
+static short window__x( info )
+XWindowObject info ;
+{
+#if defined(OldX11)
+    XWindowAttributes winfo;
+
+    (void) XGetWindowAttributes( theDisplay, info->w, &winfo );
+
+    return ((short) winfo.x);
+#else
+#if defined(X11)
+    return ((short) info->x);
+#else
+    WindowInfo winfo;
+
+    XQueryWindow(info->w, &winfo);
+
+    return (winfo.x);
+#endif
+#endif
+}
+
+static short window__y( info )
+XWindowObject info ;
+{
+#if defined(OldX11)
+    XWindowAttributes winfo;
+
+    (void) XGetWindowAttributes( theDisplay, info->w, &winfo );
+
+    return ((short) winfo.y);
+#else
+#if defined(X11)
+    return ((short) info->y);
+#else
+    WindowInfo winfo;
+
+    XQueryWindow(info->w, &winfo);
+
+    return (winfo.y);
+#endif
+#endif
+}
+
+static short window__width( info )
+XWindowObject info ;
+{
+#if defined(X11)
+    waitTillMapped(info) ;
+#endif
+
+    return( info->width ) ;
+}
+
+static short window__height( info )
+XWindowObject info ;
+{
+#if defined(X11)
+    waitTillMapped(info) ;
+#endif
+
+    return( info->height ) ;
+}
+
+static void window__draw( info, xs, ys, pointsFlag )
+XWindowObject info ;
+short xs[], ys[] ;
+int pointsFlag ;
+{
+#if defined(X11)
+    XPoint vs[MAX_SEGMENT], *vptr;
+#else
+    Vertex vs[MAX_SEGMENT], *vptr;
+#endif
+    register int point, count ;
+    register int points = abs( pointsFlag ) ;
+    register short h ;
+
+#if defined(X11)
+    if (synchronous) {
+      (void) XSynchronize(theDisplay, FALSE);
+      XFlush(theDisplay);
+      synchronous = FALSE;
+    }
+
+    waitTillMapped(info) ;
+#else
+    int i ;
+#endif
+
+    h = info->entries->height( info );
+
+    for( point = 0 ; point < points - 1 ; point += count - 1 ) {
+
+	vptr = vs ;
+
+	for( count=0 ; count < MAX_SEGMENT && point + count < points ; count++ ) {
+
+	    vptr->x =     xs[ point+count ] ;
+	    vptr->y = h - ys[ point+count ] ;
+#if defined(X10)
+	    vptr->flags = pointsFlag > 0 ? 0 : 0 ;
+#endif
+	    vptr++;
+	}
+
+	if( info->hide && pointsFlag > 0 && vs[0].x == vptr[-1].x &&
+					    vs[0].y == vptr[-1].y )
+#if defined(X11)
+	    XFillPolygon( theDisplay, info->w, info->backgroundGC, vs, vptr-vs, Complex, CoordModeOrigin);
+
+	if( pointsFlag > 0 )
+	    XDrawLines( theDisplay, info->w, info->foregroundGC, vs, vptr-vs, CoordModeOrigin);
+	else
+	    XDrawPoints(theDisplay, info->w, info->foregroundGC, vs, vptr-vs, CoordModeOrigin);
+
+	XFlush(theDisplay);
+#else
+	    XDrawFilled( info->w, vs, vptr-vs, info->background, GXcopy, AllPlanes ) ;
+
+	if( pointsFlag > 0 )
+	    XDraw(info->w, vs, vptr-vs, info->pixels, info->pixels, info->foreground, GXcopy, AllPlanes);
+	else
+	    for( i=0 ; i<count ; i++ )
+		XPixSet( info->w, vs[i].x, vs[i].y, info->pixels, info->pixels, info->foreground ) ;
+#endif
+    }
+
+    return;
+}
+
+static void checkGeometry( info )
+XWindowObject info ;
+{
+#if defined(X11)
+    return;
+#else
+#if defined(OldX11)
+    XWindowAttributes winfo;
+
+    (void) XGetWindowAttributes( theDisplay, info->w, &winfo );
+#else
+    WindowInfo winfo;
+
+    XQueryWindow(info->w, &winfo);
+#endif
+
+    info->width  = winfo.width ;
+    info->height = winfo.height ;
+
+    return ;
+#endif
+}
+
+static void window__clear( info )
+XWindowObject info ;
+{
+
+    checkGeometry( info ) ;
+
+#if defined(OldX11)
+    XClearWindow(theDisplay, info->w);
+    XFlush(theDisplay);
+#else
+#if defined(X11)
+    XFlush(theDisplay);
+    XFillRectangle( theDisplay, info->w, info->backgroundGC, 0, 0, info->width, info->height ) ;
+    XFlush(theDisplay);
+#else
+    XClear(info->w);
+#endif
+#endif
+
+    return ;
+}
+
+static void window__close( info )
+XWindowObject info ;
+{
+    if (info != (XWindowObject )0)
+#if defined(X11)
+	XFreeGC( theDisplay, info->foregroundGC ) ;
+	XFreeGC( theDisplay, info->backgroundGC ) ;
+        XDestroyWindow(theDisplay, info->w);
+#else
+        XDestroyWindow(info->w);
+#endif
+    free( (char *) info ) ;
+
+    return ;
+}
+
+static int window__store( info )
+XWindowObject info ;
+{
+    if (info->imageNum > MAX_IMAGE) {
+      (void) fprintf(stderr,
+		     "windows: Sorry, you can currently store only %i images per window.\n",
+		     MAX_IMAGE);
+      return(FALSE);
+    }
+#if defined(X11)
+    if (!synchronous) {
+      (void) XSynchronize(theDisplay, TRUE);
+      XFlush(theDisplay);
+      synchronous = TRUE;
+    }
+
+    waitTillMapped(info) ;
+
+#ifdef USE_PIXMAPS
+    info->imageData[ info->imageNum ] = XCreatePixmap(theDisplay, info->w, Width( info ), Height( info ), DisplayPlanes( theDisplay, theScreen ) ) ;
+    XCopyArea( theDisplay, info->w, info->imageData[ info->imageNum ], info->foregroundGC, 0, 0, Width( info), Height( info ), 0, 0 ) ;
+#else
+    info->imageData[ info->imageNum ] = XGetImage(theDisplay, info->w, 0, 0,
+					  info->entries->width(info),
+					  info->entries->height(info),
+					  planemask,
+					  XYPixmap);
+#endif
+#else
+    if((info->imageData[info->imageNum] = (short *) malloc(info->imageSize)) == (short *) 0) {
+	(void) fprintf(stderr, "Insufficient memory to store %dth image of size %d\n",
+		       info->imageNum+1, info->imageSize);
+	return(FALSE);
+      }
+    else
+	XPixmapGetXY( info->w, 0, 0, info->entries->width(info),
+		     info->entries->height(info), info->imageData[ info->imageNum ] ) ;
+#endif
+    info->imageNum++;
+
+    return ( info->imageNum ) ;
+}
+
+WindowImage window__current_image( info )
+XWindowObject info ;
+{
+    static struct _window_image image_info ;
+#if defined(X11)
+#if !defined( USE_PIXMAPS)
+    XImage *image_ptr = info->imageData[ info->imageNum-1 ] ;
+
+    image_info.data           = image_ptr->data ;
+    image_info.bytes_per_line = image_ptr->bytes_per_line ;
+    image_info.height         = image_ptr->height ;
+
+    image_info.left_bit  = 1<<0 ;
+    image_info.right_bit = 1<<7  ;
+    image_info.start_bit = image_info.left_bit<<image_ptr->xoffset ;
+#endif
+#else
+    short *image_ptr = info->imageData[ info->imageNum-1 ] ;
+
+    image_info.data = ( char *) image_ptr ;
+    image_info.height = info->height ;
+    image_info.bytes_per_line = ( info->width + 15 ) / 16 * sizeof (*image_ptr) ;
+
+    image_info.left_bit  = 1<<0 ;
+    image_info.right_bit = 1<<7  ;
+    image_info.start_bit = image_info.left_bit ;
+
+#endif
+
+    return ( &image_info ) ;
+}
+
+static void window__recall( info, which )
+XWindowObject info ;
+int which ;
+{
+
+#if defined(X11)
+    if (synchronous) {
+      (void) XSynchronize(theDisplay, FALSE);
+      XFlush(theDisplay);
+      synchronous = FALSE;
+    }
+#endif
+    if( which > info->imageNum )
+	(void) fprintf( stderr, "Invalid Pixmap number %d(%d)\n", which, info->imageNum ) ;
+    else
+#if defined(X11)
+#ifdef USE_PIXMAPS
+        XCopyArea( theDisplay, info->imageData[ which-1 ], info->w, info->foregroundGC, 
+		0, 0, Width( info), Height( info ), 0, 0 ) ;
+#else
+	XPutImage(theDisplay, info->w, info->foregroundGC, info->imageData[which-1], 0, 0, 0, 0,
+		  info->entries->width(info), info->entries->height(info));
+#endif  
+	XFlush(theDisplay) ;
+#else
+	XPixmapBitsPutXY(info->w, 0, 0, info->entries->width(info), info->entries->height(info),
+			 info->imageData[ which-1 ], (Bitmap) 0, GXcopy, AllPlanes);
+#endif
+    return  ;
+}
+
+#define MAX_COLORS 62
+
+static char *cmap( npixels )
+int *npixels ;
+{
+    int plane_masks[1], pix_num ;
+    char *pixvals ;
+#if defined(X11)
+	Visual *visual = DefaultVisual( theDisplay, theScreen ) ;
+    Colormap theColormap = DefaultColormap( theDisplay, theScreen ) ;
+    XColor exact_defs[MAX_COLORS] ;
+    unsigned long colors[MAX_COLORS] ;
+
+	switch( visual->class ) {	
+		case StaticGray :
+		
+			*npixels = 1 << DisplayPlanes( theDisplay, theScreen ) ;
+		    pixvals = malloc( (unsigned) *npixels ) ;
+
+    		for( pix_num=0 ; pix_num < *npixels ; pix_num++ )
+				pixvals[pix_num] = pix_num ;
+
+			break ;
+			
+		case PseudoColor :
+		
+    for( *npixels=MAX_COLORS; *npixels > 2 ; (*npixels)-- ) 
+        if( XAllocColorCells( theDisplay, theColormap, False, plane_masks, 0, colors, *npixels ) ) 
+            break ;
+
+    pixvals = malloc( (unsigned) *npixels + 2 ) ;
+    
+    pixvals[0] = BlackPixel( theDisplay, theScreen ) ;
+    
+    for( pix_num=0 ; pix_num < *npixels ; pix_num++ ) {
+        pixvals[pix_num+1] = 
+        exact_defs[pix_num].pixel = colors[ pix_num ] ;
+ 
+        exact_defs[pix_num].red   = 
+        exact_defs[pix_num].green = 
+        exact_defs[pix_num].blue  = 65535 * ( pix_num + 1 ) / ( *npixels + 1 ) ;
+
+        exact_defs[pix_num].flags = DoRed | DoGreen | DoBlue ;
+   }
+    
+    pixvals[*npixels+1] = WhitePixel( theDisplay, theScreen ) ;
+
+    XStoreColors( theDisplay, theColormap, exact_defs, *npixels ) ;
+
+    XFreeColors( theDisplay, theColormap, colors, *npixels, 0l ) ;
+
+    *npixels += 2 ;
+	
+	break ;
+	}
+#else
+    Color defs[256] ;
+    int pixels[256] ;
+    int planes ;
+    
+    *npixels = ( 1 << DisplayPlanes() ) - 2 ;
+
+    while( !XGetColorCells( 0, *npixels, 0, & planes, pixels ) && *npixels > 0 )
+    	*npixels-- ;
+	
+    pixvals = malloc( (unsigned) *npixels + 2 ) ;
+
+    pixvals[ 0 ] = BlackPixel ;
+           
+    for( pix_num=0 ; pix_num < *npixels ; pix_num++ ) {
+
+	pixvals[pix_num+1]  =
+
+	defs[pix_num].pixel = pixels[pix_num] ;
+
+	defs[pix_num].red   = 0 ;
+	defs[pix_num].green = 65535 * (pix_num+1) / (*npixels+1) ;
+	defs[pix_num].blue  = 0 ;
+
+    }
+
+    pixvals[ *npixels+1 ] = WhitePixel ;
+
+    XStoreColors( *npixels, defs ) ;
+
+    XFreeColors( pixels, *npixels, planes ) ;
+
+    XFlush() ;
+
+    *npixels += 2 ;
+#endif
+    return ( pixvals ) ;
+}
+
+static void ColorColumn( info, col, input, black, white, match, length, row_flag )
+XWindowObject info ;
+int col ;
+short *input ;
+int black, white ;
+int *match, length ;
+int row_flag ;
+{
+    register int i ;
+    char *data ;
+
+    if( info->lookup == 0 || length != info->greylength ) {
+
+	if( info->lookup != 0 )
+	    freeLookup( info->lookup ) ;
+
+	info->lookup = makeLookup( cmap, black, white, length ) ;
+
+#if defined(X11)
+        if( row_flag )
+            info->rowImage = XGetImage( theDisplay, info->w, 0, 0, Width(info),  1, planemask, ZPixmap );
+	else
+            info->colImage = XGetImage( theDisplay, info->w, 0, 0, 1, Height(info), planemask, ZPixmap );
+
+	info->greylength = length ;
+#endif
+    }
+
+    data = Lookup( col, info->lookup, input, match, length ) ;
+
+#if defined(X11)
+     if( row_flag ) {
+	 for( i=0 ; i<Width(info) ; i++ )
+             XPutPixel( info->rowImage, i, 0, (unsigned long) data[i] ) ;
+
+        XPutImage(theDisplay, info->w, info->foregroundGC, info->rowImage, 0, 0, 0, col-1, Width(info), 1 );
+     }
+     else {
+   	 for( i=0 ; i<Height(info) ; i++) 
+            XPutPixel( info->colImage, 0, i, (unsigned long) data[i] ) ;
+
+         XPutImage(theDisplay, info->w, info->foregroundGC, info->colImage, 0, 0, col-1, 0, 1, Height(info) );
+     }
+#else
+    if( row_flag )
+	XPixmapBitsPutZ( info->w, 0, col, length, 1, data, (Bitmap) 0, GXcopy, AllPlanes ) ;
+    else
+	XPixmapBitsPutZ( info->w, col, 0, 1, length, data, (Bitmap) 0, GXcopy, AllPlanes ) ;
+    XFlush() ;
+#endif
+        return ;
+}
+
+static void DitherColumn( info, col, input, black, white, match, length, row_flag )
+XWindowObject info ;
+int col ;
+short *input ;
+int black, white ;
+int *match, length ;
+int row_flag ;
+{
+    register int *mptr = match ;
+    register int *mend = match + length ;
+    register int x, bit, *dptr ;
+#if defined(X11)
+    XPoint pts[2000] ;
+    int count = 0 ;
+#endif
+
+    if( info->data == ( short * ) 0 || length != info->greylength ) {
+
+	if( info->data != ( short * ) 0 ) {
+	    free( ( char * ) info->data ) ;
+	    FreeDithers( info->diths, DITHER_SIZE ) ;
+	}
+
+	info->data  = (short *) malloc( (unsigned) length * sizeof( *info->data ) ) ;
+	info->diths = Dithers( DITHER_SIZE, length, black, white ) ;
+
+	info->greylength = length ;
+    }
+
+    dptr = info->diths[ col%DITHER_SIZE ] ;
+
+#if defined(X11)
+    if( row_flag ) {
+	while( mptr < mend )
+	    if( input[ *mptr++ ] > *dptr++ ) {
+		pts[count].x = mptr - match ;
+		pts[count].y = col-1 ;
+		count++ ;
+	    }
+    }
+    else {
+	while( mptr < mend )
+	    if( input[ *mptr++ ] > *dptr++ ) {
+		pts[count].x = col-1 ;
+		pts[count].y = mptr - match ;
+		count++ ;
+	    }
+    }
+
+    XDrawPoints(theDisplay, info->w, info->foregroundGC, pts, count, CoordModeOrigin ) ;
+#else
+    if( row_flag ) {
+	while( mptr < mend ) {
+
+	    x = mptr - match ;
+
+	    if( x%16 == 0 )
+		info->data[x/16] = 0 ;
+
+	    if( input[ *mptr++ ] <= *dptr++ )
+		info->data[x/16] |= 1<<x%16 ;
+	}
+
+	XPixmapBitsPutXY( info->w, 0, col, length, 1, info->data, (Bitmap) 0, GXcopy, AllPlanes ) ;
+    }
+    else {
+	while( mptr < mend )
+	    info->data[mptr-match] = input[ *mptr++ ] <= *dptr++ ;
+
+	XPixmapBitsPutXY( info->w, col, 0, 1, length, info->data, (Bitmap) 0, GXcopy, AllPlanes ) ;
+    }
+#endif
+
+    return ;
+}
+
+
+static void window__fill( info, col, input, black, white, match, length, row_flag )
+XWindowObject info ;
+int col;
+short *input;
+int black, white ;
+int *match, length ;
+int row_flag ;
+{
+    int chans, chan, y, blacky;
+
+#if defined(X11)
+    waitTillMapped(info) ;
+#endif
+
+    if (info->pixels == 0 || 1 )
+
+#if !defined(X11)
+     if (DisplayPlanes() > 1)
+#else
+     if( DisplayPlanes( theDisplay, theScreen ) > 1 && 
+	     DisplayPlanes( theDisplay, theScreen ) != 4 )
+#endif
+	ColorColumn(  info, col, input, black, white, match, length, row_flag );
+      else
+	DitherColumn( info, col, input, black, white, match, length, row_flag );
+
+    else { /* old line drawing simulation code to be removed */
+      chans = match[length - 1] + 1;
+
+      blacky = length;
+
+      for (chan = 0; chan < chans; chan++) {
+	y = length - length * chan / chans;
+	y -= (input[chan] - black) * length / (white - black) / chans;
+
+	if( y < blacky || !info->hide ) {
+#if defined(X11)
+	  XDrawPoint(theDisplay, info->w, info->foregroundGC, col, y);
+#else
+	  XPixSet(info->w, col, y, info->pixels, info->pixels, info->foreground ) ;
+#endif
+	  blacky = y;
+	}
+      }
+    }
+
+    return;
+}
+
+static void window__fillCol( info, col, input, black, white, match, length)
+XWindowObject info ;
+int col;
+short *input ;
+int black, white ;
+int *match, length ;
+{
+    window__fill( info, col, input, black, white, match, length, 0 ) ;
+
+    return ;
+}
+
+static void window__fillRow( info, col, input, black, white, match, length)
+XWindowObject info ;
+int col;
+short *input;
+int black, white ;
+int *match, length ;
+{
+    window__fill( info, col, input, black, white, match, length, 1 ) ;
+
+    return ;
+}
+
+static void window__function( info, ys, segment, skip, offset, yspan, start, points )
+XWindowObject info ;
+short *ys ;
+int segment, skip ;
+double offset, yspan ;
+int start, points ;
+{
+#if defined(X11)
+    XPoint vs[ MAX_SEGMENT+4 ], *vptr ;
+#else
+    Vertex vs[ MAX_SEGMENT+4 ], *vptr ;
+#endif
+    register long x, dx, yscale ;
+    register int yoffset, point, count ;
+    register short *yptr ;
+    static long shift = 16 ;
+    static long round = 1l << 15 ;
+
+#if defined(X11)
+    if (synchronous) {
+      (void) XSynchronize(theDisplay, FALSE);
+      XFlush(theDisplay);
+      synchronous = FALSE;
+    }
+
+    waitTillMapped(info) ;
+#endif
+
+    points = abs(points);
+
+    if( points <= 1 )
+	return ;
+
+    yoffset = info->entries->height( info ) - offset ;
+
+    dx = (  double ) ( ( info->entries->width(  info ) - 1 ) << shift ) / ( points - 1 ) + 0.5 ;
+    x  = dx * start + ( 1 << shift ) + round ;
+
+    yscale =         ( ( info->entries->height( info )     ) << shift ) / yspan  + 0.5 ;
+
+    yptr = ys ;
+
+    for( point=0 ; point < segment-1 ; point += count-1 ) {
+
+	vptr = vs ;
+
+	for( count=0 ; count < MAX_SEGMENT && point + count < segment ; count++ ) {
+
+	    vptr->x = x >> shift ;
+	    vptr->y = yoffset - ( *yptr * yscale + round >> shift ) ;
+#if defined(X10)
+	    vptr->flags = 0;
+#endif
+	    vptr++ ;
+
+	    if( count+1 < MAX_SEGMENT && point + count+1 < segment ) {
+		x    += dx   ;
+		yptr += skip ;
+	    }
+	}
+
+	if( info->hide ) {
+
+	    vptr->x = vptr[-1].x ;
+	    vptr->y = 1 + yoffset ;
+#if defined(X10)
+	    vptr->flags = 0 ;
+#endif
+	    vptr++ ;
+
+	    vptr->x = vs[0].x ;
+	    vptr->y = vptr[-1].y ;
+#if defined(X10)
+	    vptr->flags = 0 ;
+#endif
+	    vptr++ ;
+
+	    vptr->x = vs[0].x ;
+	    vptr->y = vs[0].y ;
+#if defined(X10)
+	    vptr->flags = 0 ;
+#endif
+	    vptr++ ;
+
+#if defined(X11)
+	    XFillPolygon(   theDisplay, info->w, info->backgroundGC, vs, vptr-vs, Complex, CoordModeOrigin);
+	}
+
+	XDrawLines(theDisplay, info->w, info->foregroundGC, vs, count, CoordModeOrigin);
+	XFlush(theDisplay);
+#else
+	    XDrawFilled( info->w, vs, vptr-vs, info->background, GXcopy, AllPlanes ) ;
+	}
+
+	XDraw( info->w, vs, count, info->pixels, info->pixels, info->foreground, GXcopy, AllPlanes ) ;
+#endif
+    }
+
+    return ;
+}
+
+typedef struct {
+    FILE *imageFilePtr                ;     /* The File Pointer       */
+    int   imageFilePreviousFrame      ;     /* The last image read    */
+} ReadingData;
+
+static ReadingData readingFiles[MAX_FILES], *current;
+static int         numReadingFiles = 0              ;
+static int         window__writing = 1              ;
+
+/* --------------------------------------------------------------------
+
+   Search in the readingFiles[] array for the given filePtr. If found,
+   return its index; otherwise return FAILURE (-1).
+
+   -------------------------------------------------------------------- */
+
+static int findReadingFile( filePtr )
+FILE *filePtr;
+{
+	int i;
+
+    for (i = 0; i < numReadingFiles; i++)
+    	if (readingFiles[i].imageFilePtr == filePtr)
+    		return (i);
+
+	return (-1);
+
+}
+
+static int window__read(w, filePtr, which)
+XWindowObject w    ;
+FILE        *filePtr;
+int          which  ;
+{
+  int    readingFileIndex ;
+  long   filePosBeforeSeek;
+
+#if defined(X11)
+  if (!synchronous) {
+    (void) XSynchronize(theDisplay, TRUE);
+    XFlush(theDisplay);
+    synchronous = TRUE;
+  }
+
+    waitTillMapped(w) ;
+
+    setupImage( w ) ;
+#else
+    if( w->theImage == (short *) 0 ) {
+	if((w->theImage = (short *) malloc(w->imageSize)) == NULL) {
+	    (void) fprintf(stderr, "windows: Insufficient memory to malloc %i bytes for a Pixmap.\n",
+		     w->imageSize);
+	    exit(1);
+	}
+    }
+#endif
+
+  if (numReadingFiles == 0 || current->imageFilePtr != filePtr) {
+    if (numReadingFiles > 0 &&
+       (readingFileIndex = findReadingFile(filePtr)) >= 0)
+    	current  = &readingFiles[readingFileIndex];
+    else {
+    	/* The First Read Operation (on this file) */
+        if (numReadingFiles >= MAX_FILES) {
+        	fprintf(stderr,
+			"windows: Sorry, you can only have %i files open for reading at once.\n",
+			MAX_FILES);
+        	fprintf(stderr, "         Hit <return> to exit.\n");
+        	getchar();
+        	exit(1);
+        }
+        current = &readingFiles[numReadingFiles] ;
+       	current->imageFilePtr           = filePtr;
+       	current->imageFilePreviousFrame = 0      ;
+     	numReadingFiles++;
+    }
+  }
+
+  filePosBeforeSeek = ftell(current->imageFilePtr);
+
+  /* Now Read and Display it */
+
+  if (fseek(current->imageFilePtr,
+          ((long) which - current->imageFilePreviousFrame - (long) 1) * w->imageSize, 1))
+            return (FALSE);
+
+#if defined(X11)
+  if (fread(w->theImage->data, 1, w->imageSize, current->imageFilePtr) != w->imageSize) {
+#else
+  if (fread(w->theImage, 1, w->imageSize, current->imageFilePtr) != w->imageSize) {
+#endif
+        /* Reposition the filePointer to enable future Reads */
+        if (fseek(current->imageFilePtr, filePosBeforeSeek, 0)) {
+        	(void) fprintf(stderr,
+			       "windows: Unable to reposition the file after a failed Read.\n");
+        	exit(1);
+        }
+    	return (FALSE);
+      }
+
+#if defined(X11)
+  XPutImage(theDisplay, w->w, w->foregroundGC, w->theImage, 0, 0, 0, 0, w->entries->width(w),
+	    w->entries->height(w));
+#else
+  XPixmapBitsPutXY(w->w, 0, 0, w->entries->width(w), w->entries->height(w),
+		   w->theImage, (Bitmap) 0, GXcopy, AllPlanes);
+#endif
+
+  current->imageFilePreviousFrame = which;
+
+  return (TRUE);
+}
+
+
+static void window__write(w, filePtr)
+XWindowObject w;
+FILE        *filePtr;
+{
+#if defined(X11)
+    int    imageSize;
+    XImage *theImage;
+
+    theImage = XGetImage(theDisplay, w->w, 0, 0, w->entries->width(w), w->entries->height(w),
+			 planemask, XYPixmap);
+
+    imageSize = ImageSizeInBytes(theImage);
+
+    if (fwrite(theImage->data, 1, imageSize, filePtr) != imageSize) {
+    	fprintf(stderr,
+		"window: WARNING! Failed to write %i bytes to Image File as image number %i.\n",
+     	        imageSize, window__writing);
+    	fprintf(stderr, "        Hit <return> to continue.\n");
+    	getchar();
+    }
+
+    window__writing++;
+
+    (void) XDestroyImage(theImage);
+#else
+    if( w->theImage == ( short * ) 0 ) {
+	if((w->theImage = (short *) malloc(w->imageSize)) == NULL) {
+	    (void) fprintf(stderr, "windows: Insufficient memory to malloc %i bytes for a Pixmap.\n",
+		     w->imageSize);
+	    exit(1);
+	}
+    }
+
+    XPixmapGetXY(w->w, 0, 0, w->entries->width(w), w->entries->height(w), w->theImage) ;
+
+    (void) fwrite((char *) w->theImage, 1, (int) w->imageSize/DisplayPlanes(), filePtr) ;
+#endif
+
+    return;
+}
+
+
+static char window__pause(info)
+XWindowObject info ;
+{
+  char line[256];
+
+#if defined(X11)
+    XFlush(theDisplay);
+#else
+    XFlush();
+#endif
+
+  (void) gets(line);
+
+  if (line[0] == '\000' || line[0] == '\r' || line[0] == '\n')
+    return (' ');
+  else
+    return (line[0]);
+}
+
+static void window__axes(info, title, xmin, xmax, xtitle, ymin, ymax, ytitle)
+XWindowObject info;
+     char *title, *xtitle, *ytitle;
+     char *xmin, *xmax, *ymin, *ymax;
+{
+  return;
+}
+
+static void window__marker( info, label, p, points )
+XWindowObject info ;
+char *label ;
+int p, points ;
+{
+    short pos = ( info->entries->width( info ) * p + points / 2 ) / points ;
+
+#if defined( X11 )
+    XDrawLine(theDisplay, info->w, info->foregroundGC, pos, 1, pos, info->entries->height(info));
+#else
+    XLine( info->w, pos, 1, pos, info->entries->height( info ), info->pixels, info->pixels, info->foreground, GXcopy, AllPlanes ) ;
+
+    if( marker_font == ( FontInfo * ) 0 )
+	marker_font = XOpenFont( marker_font_name ) ;
+
+    if( marker_font == ( FontInfo * ) 0 )
+	(void) fprintf( stderr, "Unable to use font %s for marker %s\n", marker_font_name, label ) ;
+    else
+	XTextMaskPad( info->w, pos - 1 - XQueryWidth( label, marker_font->id ), 1,
+	      label, strlen( label ), marker_font->id, 0, 0, info->foreground, GXxor, AllPlanes ) ;
+#endif
+
+    return ;
+}
+
+static int window__special( info, code, data )
+XWindowObject info ;
+int code ;
+char *data ;
+{
+    return 0 ;
+}
+
+
+WindowObject newWindowWindow( window, default_x, default_y, default_width, default_height, pixels )
+Window window ;
+int default_x, default_y, default_width, default_height ;
+int pixels ;
+{
+    static windowEntries entries = { window__x, window__y, window__width, window__height,
+				     window__draw, window__clear, window__close, window__store,
+				     window__recall, window__fillRow, window__fillCol,
+				     window__function, window__read, window__write,
+				     window__pause, window__axes, window__marker, window__special } ;
+    XWindowObject info ;
+#if defined( X11 )
+    XGCValues GCTemplate;
+#endif
+
+    if ((info = (XWindowObject ) malloc( sizeof(*info) )) == (XWindowObject )0) {
+      (void) fprintf(stderr, "windows: Insufficient memory to allocate WindowObject.\n");
+      exit(1);
+    }
+
+    info->entries = &entries ;
+    info->w       = window   ;
+
+    if( pixels < 0 )
+	info->pixels = -pixels ;
+    else
+	info->pixels = pixels ;
+
+    info->hide    = pixels < 0 ;
+
+#if defined(X11)
+    info->isMapped = 1 ;
+
+    /* Initialise a Graphics Context for lines and points */
+
+    GCTemplate.function   = GXcopy ;
+
+    GCTemplate.foreground = theForeground ;
+    GCTemplate.background = theBackground ;
+
+    GCTemplate.line_width = info->pixels ;
+
+    if( GCTemplate.line_width == 1 )
+	GCTemplate.line_width =  0 ; /* use "thin" lines */
+
+    info->foregroundGC = XCreateGC( theDisplay, info->w,
+	 GCFunction|GCForeground|GCBackground|GCLineWidth, &GCTemplate ) ;
+
+    /* A second GC for clearing and hiding lines */
+
+    GCTemplate.foreground = theBackground ;
+    GCTemplate.background = theForeground ;
+
+    info->backgroundGC = XCreateGC( theDisplay, info->w,
+	 GCFunction|GCForeground|GCBackground|GCLineWidth, &GCTemplate ) ;
+
+#else
+    info->foreground = WhitePixel ;
+    info->background = BlackPixel ;
+    info->lookup = 0;
+#endif
+
+    info->data = (short *) 0 ;
+    info->greylength = 0 ;
+
+    /* update width and height fields */
+
+    info->x      = default_x     ;
+    info->y      = default_y     ;
+    info->width  = default_width ;
+    info->height = default_height;
+
+    checkGeometry( info ) ;
+
+    /* Initialise the Image Data Structure for later read operations */
+
+#if defined(X11)
+    info->theImage = info->rowImage = info->colImage = (XImage *) 0 ;
+#else
+    info->imageSize = XYPixmapSize(info->entries->width(info), info->entries->height(info), DisplayPlanes());
+    info->theImage = ( short * ) 0 ;
+#endif
+
+    info->imageNum = 0 ;
+
+    /* MAA: 3-8-1993 
+     * The planemask bits might as well go here as anywhere else 
+     */
+
+    if ( isON(colourstr) ) 
+      planemask = AllPlanes;
+    else
+      planemask = atoi(planemaskstr);
+
+    return ( (WindowObject) info ) ;
+}
+
+    /* Since the <name> argument is always passed to newDisplayWindow as NULL, and
+       the ASP modules don't have any concept of a configurable <display> option (the
+       display is either ON or OFF), the <name> argument is redundant. The <name> argument
+       still has a sensible use as the name of the Window which is being created, and
+       its use has been modified as such in genbmm, revbmm, gensai and revsai... */
+
+
+WindowObject newXWindow( name, default_x, default_y, default_width, default_height, pixels )
+char *name ;
+int default_x, default_y, default_width, default_height ;
+int pixels ;
+{
+    Window w ;
+    XWindowObject info;
+
+#if defined(X11)
+
+    if (theDisplay == (Display *) 0) {
+      if ((theDisplay = XOpenDisplay(NULL)) == (Display *) 0) {  /* Was name */
+	(void) fprintf(stderr, "X11: Unable to do XOpenDisplay of display %s.\n",
+		       getenv("DISPLAY"));
+	exit(1);
+      }
+
+      theScreen  = XDefaultScreen( theDisplay ) ;
+      
+      /* MAA: 20-8-1993 
+       * lets put the colour bits here */
+      
+      define_colours();
+
+#ifndef SLAVE
+      if (!synchronous) {
+        (void) XSynchronize(theDisplay, TRUE);
+        XFlush(theDisplay);
+        synchronous = TRUE;
+      }
+#endif
+    }
+
+    /* Need to reset these every time, in case the screen is initialized
+       independently via InitializeX */
+
+    theWidth  = XDisplayWidth (theDisplay, theScreen);
+    theHeight = XDisplayHeight(theDisplay, theScreen);
+
+    /* Perform "centering" calculations */
+
+    if (default_x < 0) {
+      /* Center in the x dimension */
+      default_width = (MIN(default_width, theWidth));
+      default_x     = (theWidth - default_width) / 2;
+    }
+
+    if (default_y < 0) {
+      /* Center in the y dimension */
+      default_height = (MIN(default_height, theHeight));
+      default_y      = (theHeight - default_height) / 2;
+    }
+
+    /* End of "centering" calculations */
+#else
+    if( theDisplay == (Display *) 0 )
+	if( ( theDisplay = XOpenDisplay(NULL) ) == (Display *) 0  ) {
+	  (void) fprintf(stderr, "Could not open DISPLAY \"%s\"\n", getenv("DISPLAY"));
+	  exit(1);
+	}
+
+#endif
+
+
+
+#if defined(X11)
+    if( default_width == 0 && default_height == 0 )
+	w = XDefaultRootWindow(theDisplay);
+    else
+	if ((w = XCreateSimpleWindow(theDisplay, XDefaultRootWindow(theDisplay),
+				 default_x, default_y,
+				 (unsigned) default_width, (unsigned) default_height, 1,
+				 theForeground, theBackground)) != (Window) 0) {
+/*
+         XSizeHints hints ;
+
+	hints.flags = PPosition | PSize ;
+
+	hints.x = default_x ;
+	hints.y = default_y ;
+	hints.width  = default_width ;
+	hints.height = default_height ;	
+	XSetStrandardProperties( theDisplay, w, name, name, None, name, 1, &hints ) ;
+*/
+	XStoreName(theDisplay, w, name);
+	XMapRaised(theDisplay, w);
+	XFlush(    theDisplay);
+	}
+#else
+    if( default_width == 0 && default_height == 0 )
+	w = RootWindow ;
+    else
+	if( ( w = XCreateWindow( RootWindow, abs( default_x ), abs( default_y ),
+				      default_width, default_height, 0, WhitePixmap,
+				      BlackPixmap ) ) != ( Window ) 0 ) {
+	    XStoreName( w, name ) ;
+	    XMapWindow( w ) ;
+	    XFlush() ;
+	}
+#endif
+	else {
+		(void) fprintf( stderr,
+			  "Could not create window of size %dx%d at position %d,%d\n",
+			   default_width, default_height, default_x, default_y ) ;
+	}
+
+    info = (XWindowObject) newWindowWindow(w, default_x, default_y, default_width, default_height, pixels);
+#if defined(X11)
+    info->isMapped = 0 ;
+#endif
+    info->entries->clear(info);
+
+    return((WindowObject)info);
+
+}
+
+#ifndef SLAVE
+WindowObject newDisplayWindow( name, default_x, default_y, default_width, default_height, pixels )
+char *name ;
+int default_x, default_y, default_width, default_height ;
+int pixels ;
+{
+    return ( newXWindow( name, default_x, default_y, default_width, default_height, pixels ) ) ;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glib/axes.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,123 @@
+static char *axes_postscript[] = {
+ "%! simple postscript axes",
+ "% @(#)axes.h	1.10 John holdsworth 5/31/91",
+ "",
+ "/Axes { % title xmin xmax xtitle ymin ymax ytitle Axes -",
+ "/AxesDict 50 dict def",
+ "AxesDict begin",
+ "",
+ "  /ytitle exch def",
+ "  /ymax   exch def",
+ "  /ymin   exch def",
+ "  /xtitle exch def",
+ "  /xmax   exch def",
+ "  /xmin   exch def",
+ "  /title  exch def",
+ "",
+ "  newpath clippath pathbbox /height exch def",
+ "			    /width  exch def",
+ "			    pop pop",
+ "",
+ "  /tagsize  0.05 height mul neg def",
+ "  /fontsize 0.05 height mul def",
+ "  /space    0.10 height mul def",
+ "",
+ "  /Times-Roman findfont fontsize scalefont setfont",
+ "",
+ "  /midprint { % str x y midprint -",
+ "    moveto",
+ "    dup",
+ "    stringwidth pop 2 div neg 0 rmoveto",
+ "    show",
+ "  } def",
+ "",
+ "  /leftprint { % str x y leftprint -",
+ "    moveto",
+ "    dup",
+ "    stringwidth pop neg fontsize 0.4 mul neg rmoveto",
+ "    show",
+ "  } def",
+ "",
+ "  /ticks { % min max ticker -",
+ "    /ticker  exch def % procedure to draw ticks",
+ "    /max exch cvr def % axis maximum",
+ "    /min exch cvr def % axis minimum",
+ "",
+ "    /maxsubticks 50 def",
+ "",
+ "    max min ne {",
+ "",
+ "	% calculate order of magnitude",
+ "",
+ "	/delta max min sub log ceiling 1 sub 10 exch exp def",
+ "",
+ "	% do ticks",
+ "",
+ "	min delta div ceiling delta mul",
+ "	delta",
+ "	max delta div floor   delta mul",
+ "	{",
+ "		min sub max min sub div 0.5 exch ticker",
+ "	}",
+ "	for",
+ "",
+ "	% do sub ticks",
+ "",
+ "	max min sub delta div dup",
+ "	10 mul maxsubticks lt {.1} {5 mul maxsubticks lt {.2} {.5} ifelse } ifelse",
+ "	delta mul /delta exch def",
+ "",
+ "	min delta div ceiling delta mul",
+ "	delta",
+ "	max delta div floor   delta mul",
+ "	{",
+ "		min sub max min sub div 0.25 exch ticker",
+ "	}",
+ "	for",
+ "",
+ "    } if",
+ "",
+ "  } def",
+ "",
+ "  width 0.20 mul  0.15 height mul  translate  0.75 0.75 scale",
+ "",
+ "  gsave",
+ "",
+ "  height 0.002 mul setlinewidth",
+ "  currentlinewidth 2 div neg dup translate",
+ "",
+ "  newpath",
+ "  tagsize 0      moveto  width 0      lineto width  tagsize lineto",
+ "  tagsize height moveto  0     height lineto 0      tagsize lineto",
+ "  stroke",
+ "",
+ "",
+ "  title  width 2 div    height  tagsize  sub midprint",
+ "",
+ "  xmin   0              tagsize fontsize sub midprint",
+ "  xmax   width          tagsize fontsize sub midprint",
+ "",
+ "  0 height moveto width height lineto width 0 lineto stroke",
+ "",
+ "  xmin xmax {width  mul      0 moveto tagsize     mul 0 exch rlineto stroke} ticks",
+ "  xmin xmax {width  mul height moveto tagsize neg mul 0 exch rlineto stroke} ticks",
+ "",
+ "  xtitle width 2 div    tagsize fontsize sub midprint",
+ "",
+ "",
+ "  ymin   tagsize        0                    leftprint",
+ "  ymax   tagsize        height               leftprint",
+ "",
+ "  ymin ymax {height mul     0 exch moveto tagsize     mul 0      rlineto stroke} ticks",
+ "  ymin ymax {height mul width exch moveto tagsize neg mul 0      rlineto stroke} ticks",
+ "",
+ "  90 rotate",
+ "  ytitle height 2 div   space                midprint",
+ "",
+ "",
+ "  grestore",
+ "",
+ "  newpath 0 0 moveto width 0 lineto width height lineto 0 height lineto closepath clip",
+ "",
+ "end } def",
+ ( char * ) 0 } ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glib/grey.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,258 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    grey.c
+    ======
+
+    Greyscale routines for mapping arrays of shorts into
+    columns of pixel values (dithered if necessary).
+
+
+    Copyright (c), 1989  The Medical Research Council, Applied Psychology Unit.
+
+
+    Author  : John Holdsworth
+    Written : 11th May, 1989.
+
+    Edited  :
+
+*/
+#if defined( NeXT )
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+#include "grey.h"
+
+
+#ifndef lint
+static char *sccs_id = "@(#)grey.c	1.9     J. Holdsworth (MRC-APU)  11/8/90" ;
+#endif
+
+/* standard recursive dither patterns for grey scales */
+
+static int dither(n,x,y)
+int n,x,y;
+{
+    static int seed[2][2] = {{ 0, 2 } , { 3, 1 }};
+
+    if( n==2 )
+	return ( seed[y][x] ) ;
+    else
+	return ( dither(n/2,x%(n/2),y%(n/2))*4 + seed[y%n/(n/2)][x%n/(n/2)] );
+
+}
+
+int *DitherLine( size, line, length, min, max )
+int size, line, length, min, max ;
+{
+    int i, *dither_line = (int *) malloc( (unsigned) length * sizeof ( *dither_line ) ) ;
+
+    if( dither_line != (int *) 0 ) {
+	for( i=0; i < size && i < length ; i++ )
+	    dither_line[ i ] = min + (double) dither( size, i, line ) * ( max - min ) / ( size * size ) + 0.5  ;
+
+	/* repeat for rest of line */
+
+	for( ; i < length ; i++ )
+	    dither_line[ i ] = dither_line[ i%size ] ;
+    }
+
+    return ( dither_line ) ;
+}
+
+int **Dithers( size, length, min, max )
+int size, length, min, max ;
+{
+    int i, **diths = (int **) malloc( (unsigned) size * sizeof ( *diths ) ) ;
+
+    if( diths != (int **) 0 )
+	for( i=0 ; i<size ; i++ )
+	    diths[i] = DitherLine( size, i, length, min, max ) ;
+
+    return ( diths ) ;
+}
+
+void FreeDithers( diths, size )
+int **diths, size ;
+{
+    int i ;
+
+    for( i=0 ; i<size ; i++ )
+	free( (char *) diths[i] ) ;
+
+    free( (char *) diths ) ;
+
+    return ;
+}
+
+/*
+
+    makeLookup prepares 64k byte lookup table for mapping shorts to pixel values.
+    setmap is a routine to be called to locate the window system's color map
+    and set it up returning  the number of pixels availiable and allocating an
+    array containing these values in order of increasing blackness.
+
+*/
+
+#define GREY_DITHER_SIZE 8
+
+#define PIXEL_TABLE_SIZE ((1l<<16)-1)
+
+struct _lookup *makeLookup( getgreyscale, black, white, height )
+char *(*getgreyscale)() ;
+int black, white ;
+int height ;
+{
+    register char *tableptr, *end, pixval ;
+    char *greyscale  ;
+    struct _lookup *lookup ;
+    int npixels, pix, min, diff ;
+
+    if( ( lookup = (struct _lookup *) malloc( (unsigned) sizeof (*lookup) ) ) != 0 &&
+	( lookup->pixeltable =        malloc( (unsigned) PIXEL_TABLE_SIZE ) ) != 0 &&
+	( lookup->output     =        malloc( (unsigned) height + 1       ) ) != 0 ) {
+
+	/* output null terminated for potential printing out */
+
+	lookup->output[height] = '\000' ;
+
+	/* get black to white greyscale */
+
+	greyscale = getgreyscale( &npixels ) ;
+
+
+	if( black < white ) {
+	    min  =         black ;
+	    diff = white - black ;
+	}
+	else {
+	    min  =         white ;
+	    diff = black - white ;
+	}
+
+	lookup->dithers = Dithers( GREY_DITHER_SIZE, height, min, min + diff / ( npixels - 1 ) ) ;
+
+	tableptr = lookup->pixeltable ;
+
+	for( pix=0 ; pix<npixels ; pix++ ) {
+
+	    if( black < white )
+		pixval = greyscale[          pix] ;
+	    else
+		pixval = greyscale[npixels-1-pix] ;
+
+	    if( pix < npixels-1 )
+		end = lookup->pixeltable + diff * pix / ( npixels - 1 ) + 1 ;
+	    else
+		end = lookup->pixeltable + PIXEL_TABLE_SIZE ;
+
+	    while( tableptr < end )
+		*tableptr++ = pixval ;
+	}
+
+	return ( lookup ) ;
+    }
+
+    return ( 0 ) ;
+}
+
+/*
+    doLookup just performs the lookup of pixel values to convert an
+    array of short values into the corresponding pixels for output.
+    when few pixel values are availiable dithering is used to make the
+    most of them.
+
+*/
+
+char *lookup( col, lookup, input, match, height )
+int col ;
+struct _lookup *lookup ;
+short *input ;
+int *match, height ;
+{
+    register int diff ;
+    register int *mptr = match ;
+    register int *mend = match + height ;
+    register char *dptr = lookup->output ;
+    register char *lookuptable = lookup->pixeltable ;
+    register int *ditherptr = lookup->dithers[ col%GREY_DITHER_SIZE ] ;
+
+    while( mptr < mend ) {
+
+	diff = input[ *mptr++ ] - *ditherptr++ ;
+
+	if( diff > 0 )
+	    *dptr++ = lookuptable[ diff ] ;
+	else
+	    *dptr++ = lookuptable[   0  ] ;
+    }
+
+    return ( lookup->output ) ;
+}
+
+void freeLookup( lookup )
+struct _lookup *lookup ;
+{
+    if( lookup != 0 ) {
+
+	free( lookup->pixeltable ) ;
+
+	free( lookup->output ) ;
+
+	FreeDithers( lookup->dithers, GREY_DITHER_SIZE ) ;
+
+	free( (char *) lookup ) ;
+    }
+}
+
+/* for compattability */
+
+void doLookup( col, lookup, input, match, height, data )
+int col ;
+struct _lookup *lookup ;
+short *input ;
+int *match, height ;
+char *data ;
+{
+    register int diff ;
+    register int *mptr = match ;
+    register int *mend = match + height ;
+    register char *dptr = data ;
+    register char *lookuptable = lookup->pixeltable ;
+    register int *ditherptr = lookup->dithers[ col%GREY_DITHER_SIZE ] ;
+
+    while( mptr < mend ) {
+
+	diff = input[ *mptr++ ] - *ditherptr++ ;
+
+	if( diff > 0 )
+	    *dptr++ = lookuptable[ diff ] ;
+	else
+	    *dptr++ = lookuptable[   0  ] ;
+    }
+
+    return ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glib/grey.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,44 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    grey.h
+    ======
+
+    yet another include file for dither patterns and grey scales.
+
+*/
+
+
+extern int *DitherLine(), **Dithers() ;
+extern void FreeDithers() ;
+
+extern struct _lookup *makeLookup() ;
+extern char *lookup() ;
+extern void doLookup() ;
+extern void freeLookup( /* struct _lookup lookup */ ) ;
+
+struct _lookup { char *pixeltable, *output ; int **dithers ; } ;
+
+#define Lookup( _col, _lookup, _input, _match, _height ) \
+	lookup( _col, _lookup, _input, _match, _height )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glib/makefile	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,58 @@
+###########################################################################
+#
+#  Makefile for AIM graphics  library:  libglib.a
+#
+#   (For convenience, this makefile directly calls the root makefile).
+#
+#   @(#)makefile        1.35 J. Holdsworth, (MRC-APU)  6/6/91
+#                            M. Allerhand,  (MRC-APU) 26/1/93
+#
+#
+###########################################################################
+
+
+default : install
+
+GLIB = libglib.a
+OLIB = libopts.a
+
+.c.o :
+	$(CC) $(CFLAGS)  -c $<
+
+############################################################################
+# Make graphics library.
+
+OBJS = X.o null.o ps.o grey.o
+
+lib $(GLIB) : $(OBJS)
+	ar rc $@ $? ; $(RANLIB) $@
+
+$(OLIB) : options.o
+	ar rc $@ $? ; $(RANLIB) $@
+
+
+############################################################################
+# dependencies
+
+X.o:       windows.h grey.h
+null.o:    windows.h
+ps.o:      windows.h grey.h axes.h
+grey.o:    grey.h
+options.o: options.h
+
+
+############################################################################
+# Make targets in root makefile.
+
+TARGETS   = main        install     all         sources \
+	    links       alllinks    demo        tar     \
+	    ftp         tape        mail        clean   \
+	    sccslinks   cleansccs   help        noplot
+
+$(TARGETS) : FORCE
+	@ cd .. ; make $@
+FORCE:
+
+
+############################################################################
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glib/null.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,188 @@
+/*
+    null.c
+    ======
+
+    dummpy null window.
+
+
+    Copyright (c), 1989  The Medical Research Council, Applied Psychology Unit.
+
+
+    Author  : John Holdsworth
+    Written : 22nd March, 1989.
+
+    Edited  :
+
+
+
+
+*/
+
+#include <stdio.h>
+#include <malloc.h>
+
+#include "windows.h"
+
+#ifndef lint
+static char *sccs_id = "@(#)null.c	1.1     J. Holdsworth (MRC-APU)  11/8/90" ;
+#endif
+
+static short null__x( info )
+WindowObject info ;
+{
+    return( 0 ) ;
+}
+
+static short null__y( info )
+WindowObject info ;
+{
+    return( 0 ) ;
+}
+
+static short null__width( info )
+WindowObject info ;
+{
+    return( 1 ) ;
+}
+
+static short null__height( info )
+WindowObject info ;
+{
+    return( 1 ) ;
+}
+
+static void null__draw( info, xs, ys, points )
+WindowObject info ;
+short xs[], ys[] ;
+int points ;
+{
+    return ;
+}
+
+static void null__clear( info )
+WindowObject info ;
+{
+    return ;
+}
+
+static void null__close( info )
+WindowObject info ;
+{
+    return ;
+}
+
+static int null__store( info )
+WindowObject info ;
+{
+    return ( 1 ) ;
+}
+
+static void null__recall( info, which )
+WindowObject info ;
+int which ;
+{
+#ifdef lint
+    info, which ;
+#endif
+    return ;
+}
+
+static void null__fillRow( info, row, pixels, width )
+WindowObject info ;
+int row, *pixels, width ;
+{
+#ifdef lint
+    info, row, pixels, width ;
+#endif
+    return ;
+}
+
+static void null__fillCol( info, col, input, min, max, match, height )
+WindowObject info ;
+int col ;
+short *input ;
+int min, max, *match, height ;
+{
+    return ;
+}
+
+static void null__function( info, ys, segment, skip, offset, yspan, start, points )
+WindowObject info ;
+short *ys ;
+int segment, skip ;
+double offset, yspan ;
+int start, points ;
+{
+    return ;
+}
+
+static int null__read( info, fp, which )
+WindowObject info ;
+FILE *fp ;
+int which ;
+{
+#ifdef lint
+    info ; fp ; which ;
+#endif
+    return ;
+}
+
+static void null__write( info, fp )
+WindowObject info ;
+FILE *fp ;
+{
+#ifdef lint
+    info ; fp ;
+#endif
+    return ;
+}
+
+static char null__pause( info )
+WindowObject info ;
+{
+#ifdef lint
+    info ;
+#endif
+    return ;
+}
+
+
+static void null__axes( info, title, xmin, xmax, xtitle, ymin, ymax, ytitle )
+WindowObject info ;
+char *title ;
+double xmin, xmax ;
+char *xtitle ;
+double ymin, ymax ;
+char *ytitle ;
+{
+    return ;
+}
+
+static void null__marker( info, label, p, points )
+WindowObject info ;
+char *label ;
+int p, points ;
+{
+    return ;
+}
+
+static int null__special( info, code, data )
+WindowObject info ;
+int code ;
+char *data ;
+{
+    return 0 ;
+}
+
+static windowEntries entries = { null__x, null__y, null__width, null__height, null__draw, null__clear, null__close,
+				     null__store, null__recall, null__fillRow, null__fillCol,
+				     null__function, null__read, null__write,
+				     null__pause, null__axes, null__marker, null__special } ;
+static struct _window_object dummy_obj = { &entries, { 0 } } ;
+WindowObject NullWindowObject = &dummy_obj ;
+
+WindowObject newNullWindow()
+{
+    return ( NullWindowObject ) ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glib/options.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,1624 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/* -------------------------------------------------------------------------------
+
+   The Leanest Resource Manager in the West.
+
+   Options may be supplied as defaults (actually in the code), as command line
+   arguments, and in a option file. The default arguments may be overridden by
+   the option-file contents, which may be overridden from the  command line.
+
+   Copyright (c), 1989  The Medical Research Council of the United Kingdom.
+
+   Author  :    Paul Manson
+   Written :    March 1st 1989
+
+   Edited  :    
+
+    2nd March 1989 (Paul Manson) Added the facility of searching the HOME directory
+                                 for a option file if one is not found in the 
+                                 working directory.
+
+    8th March 1989 (Paul Manson) Enhanced the above by providing a OPTIONPATH
+                                 search strategy for Unix. Currently MSDOS only
+                                 searches for a option file in the directory
+                                 where the program was found.
+
+    8th March 1989 (Paul Manson) Added the ability to refer to options via 
+                                 abbreviations of their names. At present, an abbrev.
+                                 will match if it is exactly the same as precisely one
+                                 option, or if it is the same as the first <n> chars
+                                 of that option (where <n> is the length of the 
+                                 abbrev) and it matches no other option name.
+
+    9th March 1989 (Paul Manson) Added the readopts and writeopts calls, to implement
+                                 option headers for files. Also altered the form
+                                 of command line options accepted: See getopts.h for
+                                 details. 
+
+   10th March 1989 (Paul Manson) Added the "help" facility to provide a simple
+                                 self-documentation facility. Also altered the 
+                                 Option type to put defaults and comments in 
+                                 the code.
+
+   16th March 1989 (Paul Manson) Altered the final argc/argv shuffling in getopts
+                                 so that argv simply points at the first argument 
+                                 after the options. Also added fileopts.
+
+   29th March 1989 (Paul Manson) Altered ".res" to ".opt" to coincide with the new
+                                 naming r'egime. Also added the spitOptionsFile call
+                                 to automatically produce an options file with
+                                 comments. To enable this facility, compile getopts
+                                 with -DSPITHELP; to use it, type <prog> -spit.  Do 
+                                 NOT distribute a spitting version of getopts! Altered
+                                 Options-file scanning to permit trailing comments.
+
+   30th March 1989 (Paul Manson) Completely eradicated the blockWriteToFile used by
+                                 writenopts. This is now done on a non-aligned basis,
+                                 as this is likely to be quicker and less complex.
+
+   03rd April 1989 (Paul Manson) Added the calll to outputopt.
+
+   06th April 1989 (Paul Manson) Oh Joy! Oh Bliss! The once-much-maligned SPIT option
+                                 is recieved into decent society, albeit in the guise
+                                 of an options "editor" called 'update'.
+
+   10th April 1989 (Paul Manson) The 'update' option no longer exit(1)s, but
+                                 carries on to execute the program. Also changed
+                                 OptionFileName so that it correctly gets the
+                                 cwd on the PC.
+
+   11th April 1989 (Paul Manson) Altered the OptionFileName routines to be EITHER 
+                                 for the PC or for Unix.
+
+   26th April 1989 (Paul Manson) Put in a temporary delta to the PC version so that it
+                                 only looks for option files (and hence only creates
+                                 option files) in the current directory. This will be
+                                 abandoned when we determine a better search strategy.
+
+   15th  June 1989 (Paul Manson) Altered SilentOption so that it is alterable, but is
+                                 NOT visible in any way (ie. not printed by help or
+                                 spit, and not output to headers).
+
+   11th  July 1989 (Paul Manson) Altered so that "help" (and "update") only display
+                                 (or output) the options which were either read in
+				 from the options file, or have been subsequently
+				 altered on the command line. The current implementation
+				 simply checks to see whether the default and current
+				 values for a particular option differ (either in value
+				 OR address!).
+			       
+   27th  July 1989 (Paul Manson) Altered so that isON == !isOFF, and not the other way
+                                 around -- this allows "2", "3", etc to masquerade as
+                                 "1" while only "0" is "off". Also changed so that no
+                                 quotes are output to file headers.
+
+
+  July  1994 (MAA)               Allowed spaces in strings, by adding double-quotes
+                                 to the arguments. Bit of a hack, though.
+   ------------------------------------------------------------------------------- */
+
+#include "options.h"
+#include <stdio.h>
+#include <string.h>
+#if defined( NeXT)
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+#include <ctype.h>
+
+#if !defined( lint )
+static char *sccs_id = "@(#)options.c	1.14 Paul Manson (MRC-APU) 5/2/89";
+#endif
+
+char defversion[64] = "not set yet" ,  *versionstr = defversion ;
+
+#if defined( PC )
+#include <direct.h>
+#define DOT '.'
+#define BACKSLASH_CHAR '\\'
+#define SLASH_CHARACTER '/'
+#define OPTION_FILE_PREFIX ""
+#define OPTION_FILE_SUFFIX ".opt"
+#else
+#ifndef THINK_C
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+#define OPTION_FILE_PREFIX "."
+#define OPTION_FILE_SUFFIX "rc"
+#define OPTION_PATH "OPTIONSPATH"
+     /* Environment variable for path */
+#define DEFAULT_OPTION_PATH "."
+     /* Path is first . then ~ (ie home) */
+#endif
+
+#define MAX_LINE_LENGTH (256)
+#define MAX_NAME_LENGTH (128)
+#define FALSE (0)
+#define TRUE  (1)
+#define HYPHEN_CHARACTER '-'
+#define BLANK_CHARACTER ' '
+#define TAB_CHARACTER '\t'
+#define NEWLINE_CHARACTER '\n'
+#define DOUBLE_QUOTE_CHAR '\"'
+#define ERROR_RESULT (1234)
+#define EQUALS_CHARACTER '='
+#define COMMENT_CHARACTER '#'
+#define NULL_CHARACTER '\000'
+#define CARRIAGE_RETURN '\r'
+
+/* Options-specific definitions for "ON", "OFF" and "NULL" */
+
+#define ON_STRING   (ON_OPTION)
+#define ON_ALIAS    "1"
+
+#define OFF_STRING  (OFF_OPTION)
+#define OFF_ALIAS   "0"
+
+#define NULL_STRING (NULL_OPTION)
+#define NULL_ALIAS  "null"
+
+#define NOT_USED    "Not_used"
+
+/* For the search_path and Ambiguity procedures */
+
+#define LINE_CHARS 200
+#define AMBIGUOUS  (-2)
+#define NO_MATCH   (-1)
+#define DEFAULT_TOGGLE_VALUE (ON_STRING)
+
+/* For the readopts and writeopts procedures */
+
+#define OPTION_HEADER_SIZE ( sizeof ( head_string_start ) - 1 + size_digits + 1 )
+#define OPTION_HEADER_HEADER "header_bytes="
+#define OPTION_HEADER_DIGITS (7)
+
+#define min(X,Y) (((X) < (Y)) ? (X) : (Y))
+
+static char OptionHeaderHeader[] = OPTION_HEADER_HEADER;
+static char LineFeedArray[] =   "\n";
+static char EqualsArray[] =     "=";   /* Was " = " */
+static char QuotesArray[] =     "\"";
+
+/* For the OnLine Help Facility */
+
+#define HELP_STRING             "help"
+#define UPDATE_STRING           "update"
+#define ALL_STRING              "all"
+
+static int helpOnAllRequired =  FALSE;
+static int helpOnOneRequired =  FALSE;
+static int helpOnOneLocation =      0;
+static int updateAllRequired =  FALSE;
+
+extern void exit();
+static int thereWasAnOptionsFile = FALSE;
+static char *theOptionFileName = NULL;
+
+
+
+
+#ifndef PC
+/* -----------------------------------------------------------------------
+
+    search_path( file, path )
+    =========================
+
+    jwh - 4th jan 1987
+
+    searches through string path for file and returns full file name if it 
+    finds it. Returns NULL if file is not found. Path is specified in normal 
+    path format i.e. "dir1:dir2:dir3...". Works for "~" and "~/dir.." - 
+    substitutes HOME for "~". ~ only works for current user!!
+
+    ----------------------------------------------------------------------- */
+
+
+static char *search_path( file, path )
+char *file, *path ;
+{
+#ifdef THINK_C
+    return ( file ) ;
+#else
+    char file_name[ LINE_CHARS ] ;
+    int len_next      ;
+    struct stat buf ;
+    extern getenv();
+    char *home_directory = (char *)getenv("HOME");
+
+    if( file[ 0 ] == '/' || file[ 0 ] == '.' && file[ 1 ] == '/' )
+      return ( strcpy( malloc((unsigned)(strlen(file) + 1)), file) );
+
+    do
+    {
+      len_next = ( strchr( path, ':' ) == NULL ) ?
+	strlen( path ) : strchr( path, ':' ) - path ; 
+
+	if( *path == '~' )
+	{
+	    (void) strcpy( file_name, home_directory ) ;
+	    (void) strncpy( file_name + strlen( home_directory ), path+1,
+		    len_next-1 ) ;
+	    (void) sprintf( file_name + strlen( home_directory ) + len_next - 1 ,
+		    "/%s", file ) ;
+	}
+	else
+	{
+	    (void) strncpy( file_name, path, len_next ) ;
+	    (void) sprintf( file_name + len_next , "/%s", file ) ;
+	}
+
+	if( stat( file_name, &buf ) >= 0 && ( buf.st_mode & S_IFDIR ) == 0 )
+  	    return ( strcpy( malloc((unsigned)(strlen(file_name) + 1)), file_name) );
+
+	path = path + len_next + 1 ;
+    }
+    while( path[ -1 ] != '\0' ) ;
+
+    /* return( NULL ) ; */  return( file );   /*  If PATH is NULL, return FILE */
+#endif
+}
+
+/* ---------------------------------------------------------------------------------
+
+   Return the Option File Name, given the Name of the Application (Unix Version)
+
+   Edited: 
+
+   --------------------------------------------------------------------------------- */
+char *UnixOptionFileName(appn)
+     char *appn     ;
+{
+  char *temp;
+
+  temp = malloc((unsigned) (strlen(appn) + strlen(OPTION_FILE_SUFFIX) +
+		strlen(OPTION_FILE_PREFIX) + 1));
+
+  temp = strcpy(temp,OPTION_FILE_PREFIX);
+  temp = strcat(temp,appn);
+  temp = strcat(temp,OPTION_FILE_SUFFIX);
+
+
+  return (temp);
+}
+#endif /* Unix Option File Stuff */
+
+#if defined( PC )
+
+/* ---------------------------------------------------------------------------------
+
+   Return the Option File Name, given the Name of the Application (PC Version)
+
+   Edited: 
+
+   --------------------------------------------------------------------------------- */
+char *PCOptionFileName(appn, onlyLocal)
+     char *appn     ;
+     int   onlyLocal;
+{
+  char *temp;
+  int   i               ;
+  char *temp2, *lastPart;
+
+
+  temp = malloc((unsigned) (strlen(appn) + strlen(OPTION_FILE_SUFFIX) +
+		strlen(OPTION_FILE_PREFIX) + 1));
+
+  temp  = strcpy(temp, appn);
+
+  for (i = 0; temp[i] != NULL_CHARACTER; i++)
+    if (temp[i] == BACKSLASH_CHAR)
+      temp[i] = SLASH_CHARACTER;
+
+  /* Strip Back to the Application Name */
+  if ((lastPart = strrchr(temp, SLASH_CHARACTER)) == NULL)
+    lastPart = temp;
+  else
+    lastPart++; /* Skip over the actual "/" */
+
+  /* lastPart points to the tail name of the path */
+	
+  if ((temp2 = strchr(lastPart,DOT)) == NULL)
+    temp = strcat(temp,OPTION_FILE_SUFFIX);
+  else
+    temp2 = strcpy(temp2, OPTION_FILE_SUFFIX);
+
+  if (onlyLocal)         /* Remove the full path to give only a local name */
+    return( lastPart);
+  else
+    return (temp);
+}
+#endif /* PC Version of OptionFileName */
+
+
+/* ---------------------------------------------------------------------------------
+
+   Check that there is no ambiguity in the (possibly abbreviated) <name>. If there is
+   no match whatever, return NO_MATCH. If there is a single exact match, or a single
+   abbreviating match, return the index of the matched option; otherwise return
+   AMBIGUOUS.
+
+   --------------------------------------------------------------------------------- */
+int Ambiguity(options, numOptions, name)
+     Option options[] ;
+     int      numOptions;
+     char     *name       ;
+{
+  int i, matched, matchedExactly, matchedWhere, moreThanOneInexactMatch;
+
+  matched                 = FALSE;
+  matchedExactly          = FALSE;
+  moreThanOneInexactMatch = FALSE;
+
+  for (i = 0; i < numOptions; i++)
+    if (options[i].classification != OutputOption &&
+	strncmp(name, options[i].name, strlen(name)) == 0) {
+      if (matched) {
+	if (matchedExactly) {
+	  if (strcmp(name, options[i].name) == 0) {
+	    /* TWO Exact Matches */
+	    return AMBIGUOUS;
+	  }
+	}
+	else {
+	  if (strcmp(name, options[i].name) == 0) {
+	    /* THIS is an exact match */
+	    matchedExactly = TRUE;
+	    matchedWhere   =    i;
+	  }
+	  else {
+	    /* There are two inexact matches ... if there are no exact ones we
+	       have AMBIGUITY */
+	    moreThanOneInexactMatch = TRUE;
+	  }
+	}
+      }
+      else {
+	if (strcmp(name, options[i].name) == 0) {
+	  /* This is an exact match */
+	  matchedExactly = TRUE;
+	}
+	matched      = TRUE;
+        matchedWhere = i   ;
+      }
+    }
+
+  if (moreThanOneInexactMatch)
+    return (AMBIGUOUS);
+  else {
+    if (matched)
+      return (matchedWhere);
+    else
+      return (NO_MATCH);
+  }
+      
+}
+
+
+/* ---------------------------------------------------------------------------------
+
+   Search for the named option in the list of options. If it is found, return its
+   location (index) in the options array. Otherwise, return NO_MATCH.
+
+   --------------------------------------------------------------------------------- */
+int LookUp(options, numOptions, name)
+     Option options[] ;
+     int    numOptions;
+     char  *name      ;
+{
+  int i;
+
+  for (i = 0; i < numOptions; i++)
+    if (options[i].classification != OutputOption && strcmp(name, options[i].name) == 0) {
+      return (i);
+    }
+
+  return (NO_MATCH);
+
+}
+
+extern helpRoutine *onLineHelpHandler;
+extern void updateOptionsFile();
+
+/* ---------------------------------------------------------------------------------
+
+   Search for the named option in the list of options. If it is found, set its
+   new value as indicated and return TRUE. If not, return either FALSE or AMBIGUOUS.
+
+   Edited:
+
+    8th March 1989 (Paul Manson) Changed the call to LookUp to call Ambiguity instead,
+                                 thus achieving the matching of abbreviated options.
+
+   15th March 1989 (Paul Manson) Reinstated the call to LookUp in the case that
+                                 abbreviations (and hence ambiguity) are/is not
+                                 permitted (ie. in option Header Files).
+
+   --------------------------------------------------------------------------------- */
+int LookUpAndStore(options, numOptions, name, value, permitAbbrevs, programName)
+     Option   options[]    ;
+     int      numOptions   ;
+     char     *name, *value;
+     int      permitAbbrevs;
+     char    *programName  ;
+{
+  int   loc ;
+  char *temp;
+
+  /* Account for specific references to the "help" option, with different
+     treatment of the "help=all" command */
+  if (strcmp(name, HELP_STRING) == 0) {
+    /* Check whether it is asking for ALL help */
+    if (strcmp(value, ALL_STRING) == 0) {
+      helpOnAllRequired = TRUE;
+      helpOnOneRequired = FALSE;
+      (*onLineHelpHandler)(options, numOptions, programName);
+      exit(0);
+    }
+    /* Check for other specific kinds of help request */
+    /*    else if (strcmp(value, _STRING) == 0) {     */
+
+
+    else {
+      /* Expand the (possibly abbreviated) option name */
+      if ((permitAbbrevs && ((loc = Ambiguity(options, numOptions, value)) >= 0)) ||
+	  (!permitAbbrevs && ((loc = LookUp(options, numOptions, value)) >= 0))) {
+	helpOnOneRequired = TRUE;
+	helpOnAllRequired = FALSE;
+	helpOnOneLocation = loc ;
+	(*onLineHelpHandler)(options, numOptions, programName);
+	exit(0);
+      }
+      else {
+	if (loc == AMBIGUOUS) {
+	  (void) fprintf(stderr, "WARNING: The option name %s is AMBIGUOUS; please be more specific.\n", value);
+	  exit(1);
+	}
+	else {
+	  (void) fprintf(stderr, "WARNING: The %s program does not have an option named %s.\n",
+			 programName, value);
+	  exit(1);
+	}
+      }
+    }
+  }
+  else if (strcmp(name, UPDATE_STRING) == 0) {
+    /* Check whether it is asking for ALL updated */
+    if (strcmp(value, ALL_STRING) == 0) {
+      updateAllRequired = TRUE ;
+      updateOptionsFile(options, numOptions, programName, theOptionFileName);
+      updateAllRequired = FALSE;
+      helpOnAllRequired = TRUE ;
+      helpOnOneRequired = FALSE;
+      return (TRUE);
+    }
+    else {
+      /* At present there is no use for a specific update call */
+      (void) fprintf(stderr, "options: The update option may not be altered!\n");
+      exit(1);
+    }
+  }
+  else if ((permitAbbrevs && ((loc =  Ambiguity(options, numOptions, name)) >= 0)) ||
+	   (!permitAbbrevs && ((loc = LookUp(options, numOptions, name)) >= 0))) {
+    /* It is a conventional "LookUpAndStore" operation */
+    temp = malloc((unsigned)(strlen(value) + 1));
+    temp = strcpy(temp, value);
+    *(options[loc].value) = temp;
+    return (TRUE);
+  }
+  else {
+    if (loc == AMBIGUOUS) {
+#if defined( PC )
+      (void) fprintf(stderr,
+		     "ERROR: The name %s is AMBIGUOUS, and the value %s has not been assigned to any option\n", name, value);
+      exit(1);
+#else
+      (void) fprintf(stderr,
+		     "WARNING: The name %s is AMBIGUOUS, and the value %s has not been assigned to any option\n", name, value);
+      return (AMBIGUOUS);
+#endif
+    }
+    else
+      return (FALSE);
+  }
+
+      
+}
+
+
+/* ---------------------------------------------------------------------------------
+
+   Skip Blanks and Tabs. Stop at a printable character or a newline or null.
+
+   --------------------------------------------------------------------------------- */
+char *skipBlanks (ptr)
+     char *ptr;
+{
+  while ((*ptr == BLANK_CHARACTER) || (*ptr == TAB_CHARACTER)) ptr++;
+
+  return (ptr);
+}
+
+
+/* ---------------------------------------------------------------------------------
+
+   Ensure that the next character is an '='. If it is, return a pointer to the first
+   character after the '='; otherwise, return NULL.
+
+   --------------------------------------------------------------------------------- */
+char *skipEquals (ptr)
+     char *ptr;
+{
+  if (ptr[0] == EQUALS_CHARACTER)
+    return (++ptr);
+  else
+    return (NULL);
+}
+
+
+/* ---------------------------------------------------------------------------------
+
+   Read a name (ie. a token, a contiguous sequence of nonblank characters, or a 
+   quoted string) from the string pointed to by ptr, and copy it the buffer pointed
+   to by <name>. If successful, return a pointer to the character after the token;
+   otherwise, return NULL.
+
+   --------------------------------------------------------------------------------- */
+char *getName (ptr, name)
+     char *ptr, *name;
+{
+  char *temp, *i, *namePtr;
+  char stopChar;
+
+  if (ptr[0] == DOUBLE_QUOTE_CHAR) {
+    ptr++;
+    stopChar = DOUBLE_QUOTE_CHAR;
+  }
+  else
+    stopChar = BLANK_CHARACTER;
+
+  temp = ptr;
+
+  while (*temp != NULL_CHARACTER &&
+	 *temp != NEWLINE_CHARACTER &&
+	 *temp != CARRIAGE_RETURN &&
+	 ((stopChar == DOUBLE_QUOTE_CHAR && *temp != stopChar) ||
+	  (stopChar == BLANK_CHARACTER &&
+	   (*temp != stopChar && *temp != TAB_CHARACTER && *temp != EQUALS_CHARACTER))))
+    temp++;
+
+  if (stopChar == DOUBLE_QUOTE_CHAR && *temp != DOUBLE_QUOTE_CHAR) {
+    (void) fprintf(stderr, "options: Improperly closed quoted string %s\n", --ptr);
+    return (NULL);
+  }
+
+  namePtr = name;
+
+  for (i = ptr; i < temp; )
+    *namePtr++ = *i++;
+
+  *namePtr = NULL_CHARACTER;
+
+  if (stopChar == DOUBLE_QUOTE_CHAR)
+    temp++;
+
+
+  return (temp);
+
+}
+
+
+/* ------------------------------------------------------------------------------
+
+   Read lines from the specified file, updating option settings as appropriate.
+
+   Edits: 29th March 1989 (Paul Manson) Altered so that trailing comments allowed.
+
+   ------------------------------------------------------------------------------ */
+void processOptionFile (options, numOptions, OptionFile, theOptionFileName,
+			  limitedChars, checkOptions, programName)
+     Option options[]           ;
+     int      numOptions        ;
+     FILE     *OptionFile       ;
+     char     *theOptionFileName;
+     int      limitedChars      ;
+     int      checkOptions      ;
+     char    *programName       ;
+{
+  int   result                  ;
+  char   name[MAX_NAME_LENGTH]  ;
+  char  value[MAX_NAME_LENGTH]  ;
+  char *line,           *linePtr;
+  int   maxCharsToRead          ;
+  int   totalCharsRead          ;
+
+  result         = EOF;
+  totalCharsRead = 0  ;
+  line           = malloc((unsigned) MAX_LINE_LENGTH + 1);
+
+  maxCharsToRead = ((limitedChars) ? (min(MAX_LINE_LENGTH, limitedChars)) :
+		                     MAX_LINE_LENGTH);
+
+  while (maxCharsToRead > 0 && ((line = fgets(line, maxCharsToRead + 1,
+					      OptionFile)) != NULL)) {
+    
+    if (line[0] == NULL_CHARACTER)
+      break; /* In the case of a Option Header */
+    else
+      if (limitedChars) {
+	totalCharsRead += strlen(line);
+	maxCharsToRead = min(MAX_LINE_LENGTH, limitedChars - totalCharsRead);
+      }
+
+    linePtr = skipBlanks(line);
+
+    /* Check for Comments and Blank Lines */
+    if ((linePtr[0] == COMMENT_CHARACTER) ||
+	(linePtr[0] == NEWLINE_CHARACTER) ||
+	(linePtr[0] == CARRIAGE_RETURN  ) ||
+	(linePtr[0] == NULL_CHARACTER))
+      continue;
+
+    if ((linePtr = getName(linePtr, name)) == NULL) {
+      (void) fprintf(stderr, "options: Missing or Invalid name\n");
+      result = ERROR_RESULT;
+      break;
+    }
+    linePtr = skipBlanks(linePtr);
+    if ((linePtr = skipEquals(linePtr)) == NULL) {
+      (void) fprintf(stderr, "options: Expected an '=' after the name %s\n", name);
+      result = ERROR_RESULT;
+      break;
+    }
+    linePtr = skipBlanks(linePtr);
+    if ((linePtr = getName(linePtr, value)) == NULL) {
+      (void) fprintf(stderr,
+		     "options: Missing or Invalid value; name is %s\n", name);
+      result = ERROR_RESULT;
+      break;
+    }
+    linePtr = skipBlanks(linePtr);
+    if ((*linePtr != NEWLINE_CHARACTER) &&
+	(*linePtr != NULL_CHARACTER)    &&
+        (*linePtr != COMMENT_CHARACTER) &&
+	(*linePtr != CARRIAGE_RETURN)) {
+      (void) fprintf(stderr,
+		     "options: Detected Trailing Garbage in the line %s = %s\n",
+		     name, value);    
+      result = ERROR_RESULT;
+      break;
+    }
+
+    if (!LookUpAndStore(options, numOptions, name, value, checkOptions, programName) &&
+	checkOptions) {
+      (void) fprintf(stderr, "options: Could not find Option Called %s\n",
+	      name);
+      result = ERROR_RESULT;
+      break;
+    }
+
+  }
+  
+  if (result != EOF) {
+    (void) fprintf(stderr,"options: Error reading the Option File %s\n",
+	    theOptionFileName);
+    (void) fprintf(stderr,"options: Remainder of File is as follows;\n");
+    (void) fputs(line, stderr);
+    while ((line = fgets(line, MAX_LINE_LENGTH, OptionFile)) != NULL)
+      (void) fputs(line, stderr);
+    exit(1);
+  }
+}
+
+
+/* ------------------------------------------------------------------------------
+
+   OnLine Help Facility. This is simply the default handler which is to be called
+   if the user specifies no replacement handler.
+
+   ------------------------------------------------------------------------------ */
+static void defaultHelpHandler(options, numOptions, progName)
+     Option options[] ;
+     int      numOptions;
+     char    *progName    ;
+{
+  register int help, res;
+
+  if (helpOnOneRequired) {
+    res = helpOnOneLocation;
+    (void) fprintf(stdout, "%-13s %-9s %-9s %s\n", options[res].name,
+		   ((*(options[res].value) == NULL) ? ("") : (*(options[res].value))),
+		   ((options[res].defaultValue == NULL) ? ("") : (options[res].defaultValue)),
+		   ((options[res].comment  == NULL) ? ("") :   (options[res].comment)));
+    return;
+  }
+  
+  help = -1;
+  for (res = 0; res < numOptions; res++)
+    if (strcmp(options[res].name, HELP_STRING) == 0) {
+      help = res;
+      break     ;
+    };
+
+
+/************* Print head of help menu *****************/
+  if (help < 0) {
+    (void) fprintf(stdout, "The Rotter who wrote the `%s' program hasn't provided any \n",
+		   progName);
+    (void) fprintf(stdout, "form of on-line 'help' documentation, tsk tsk!\n\n");
+    (void) fprintf(stdout,
+		   "We can, however, provide you with the list of available options:\n\n");
+  }
+  else {
+
+    (void)fprintf(stdout,"%s\n", versionstr);
+    (void) fprintf(stdout,
+	"Usage: %s  [options] %s\n\n", progName, options[help].comment);
+  }
+
+  (void) fprintf(stdout, "Option Name   Current   Default   Comment\n");
+  (void) fprintf(stdout, "-----------   -------   -------   -------\n");
+
+  for (res = numOptions-1 ; res >= 0 ; res-- )
+    if (options[res].classification < OutputOption &&
+	(!thereWasAnOptionsFile || helpOnAllRequired ||
+	 strcmp(*(options[res].value), options[res].defaultValue) != 0 ||
+	 *(options[res].value) != options[res].defaultValue))
+      (void) fprintf(stdout, "%-13s %-9s %-9s %s\n", options[res].name,
+		     ((*(options[res].value) == NULL) ? ("") : (*(options[res].value))),
+		     ((options[res].defaultValue == NULL) ? ("") : (options[res].defaultValue)),
+		     ((options[res].comment  == NULL) ? ("") :   (options[res].comment)));
+
+  (void) fprintf(stdout, "\n");
+  return;
+}
+
+/* ----- Declare the handlerHolder variable ----- */
+
+static helpRoutine *onLineHelpHandler = defaultHelpHandler;
+
+
+/* ------------------------------------------------------------------------------
+
+   Spit out the options to a file (with the appropriate option file name).
+
+   Edits: 29th March 1989 (Paul Manson). For the sake of IBM/PC users, this routine
+                                         will now spit lines with CR/LF pairs.
+          06th April 1989 (Paul Manson). This routine is no-longer conditionally
+                                         compiled, but is now more widely accepted.
+
+   ------------------------------------------------------------------------------ */
+
+void updateOptionsFile(options, numOptions, programName, resFileName)
+     Option   options[]  ;
+     int      numOptions ;
+     char    *programName;
+     char    *resFileName;
+{
+  int   res ;
+  FILE *fptr;
+
+  if ((fptr = fopen(resFileName, "w")) == NULL) {
+    (void) fprintf(stderr, "Unable to Update Options File called %s.\n", resFileName);
+    exit(1);
+  }
+
+#if defined( PC ) || defined( THINK_C )
+  (void) fprintf(fptr ,"# %s\n", versionstr);
+  (void) fprintf(fptr, "#\r\n# Options file for the %s program.\r\n#\r\n\r\n", programName);
+  (void) fprintf(fptr, "#Option Name    Current     Default   Comment\r\n");
+  (void) fprintf(fptr, "#-----------    -------     -------   -------\r\n\r\n");
+#else
+  (void) fprintf(fptr ,"# %s\n", versionstr);
+  (void) fprintf(fptr, "#\n# Options file for the %s program.\n#\n\n", programName);
+  (void) fprintf(fptr, "#Option Name    Current     Default   Comment\n");
+  (void) fprintf(fptr, "#-----------    -------     -------   -------\n\n");
+#endif
+
+  for (res = numOptions-1; res >=0 ; res-- )
+    if (options[res].classification < OutputOption && *(options[res].value) != NULL &&
+	(updateAllRequired ||
+	 strcmp(*(options[res].value), options[res].defaultValue) != 0 ||
+	 *(options[res].value) != options[res].defaultValue)) {
+#if defined( PC )
+      (void) fprintf(fptr, "%-13s = %-9s # %-9s %s\r\n", options[res].name,
+		     ((*(options[res].value) == NULL) ? ("") : (*(options[res].value))),
+		     ((options[res].defaultValue == NULL) ? ("") : (options[res].defaultValue)),
+		     ((options[res].comment  == NULL) ? ("") :   (options[res].comment)));
+#else
+      (void) fprintf(fptr, "%-13s = %-9s # %-9s %s\n", options[res].name,
+		     ((*(options[res].value) == NULL) ? ("") : (*(options[res].value))),
+		     ((options[res].defaultValue == NULL) ? ("") : (options[res].defaultValue)),
+		     ((options[res].comment  == NULL) ? ("") :   (options[res].comment)));
+#endif
+    }
+
+  if (fclose(fptr) == EOF) {
+    (void) fprintf(stderr, "options: fclose failed on the options file %s.\n", resFileName);
+    exit(1);
+  }
+
+  thereWasAnOptionsFile = TRUE; /* Cos there is one now! */
+
+  return;
+}
+
+
+/* ------------------------------------------------------------------------------
+
+   Process the option file and then the command line options supplied.
+
+   Edited: 
+
+    2nd March 1989 (Paul Manson). Changed the calls to OptionFileName (ie.
+                                  added a <prefix> argument) to facilitate
+                                  searching of HOME (etc) directories. Note
+				  that this is IGNORED for IBM/PCs.
+
+    8th March 1989 (Paul Manson). Ignore the above, as OPTIONSPATH is now
+                                  used (in conjunction with search_path) to
+                                  enable proper paths for Unix.
+
+   10th March 1989 (Paul Manson). Added the "help" facility and the default
+                                  and comment stuff.
+
+   16th March 1989 (Paul Manson). Altered the final argc/argv shuffling so that
+                                  argv simply points at the first argument after
+                                  the options.
+
+   July 1994 (MAA).               Mended to allow spaces in command-line strings.
+
+   ------------------------------------------------------------------------------ */
+
+
+
+
+/* Assign the default options */
+
+void default_nopts( options, numOptions )
+Option options[]  ;
+int    numOptions ;
+{
+    int i ;
+
+    for (i = 0; i < numOptions; i++)
+	*(options[i].value) = options[i].defaultValue ;
+}
+
+
+
+/****************************************************************************
+*   Assign options from the rc file.
+*
+*   The option file is called ".genxxxrc", where the "xxx" is determined
+*   by the name of the application, (which is in argv[0]).
+*   Here "rc" stands for "resource control".
+*   The file-name is assigned to a string ptr "theOptionFileName".
+*   On Unix, the path for the file-name is determined as follows:
+*      if environment variable OPTION_PATH is set, then use this path.
+*      else  the default path is:
+*          `.' (the current directory)
+*          `~' (the users home directory)
+*   The DEFAULT_OPTION_PATH for the option file is defined "."  (see above).
+*   This means look first in the current directory, and failing that in the
+*   users home directory.
+*   But these defaults can be overridden by setting an environment variable,
+*   which is defined as OPTIONSPATH (see above). Thus the user could set a
+*   new default path for option files by, eg:
+*       setenv OPTIONSPATH ".:~/rcbin"
+*   This would look first in the current directory, and failing that in a
+*   directory ~/rcbin
+*****************************************************************************/
+
+void rcfile_nopts( options, numOptions, file )
+Option  options[]  ;
+int     numOptions ;
+char   *file       ;
+{
+    FILE *OptionFile    ;
+    char *OptionPathPtr ;
+
+
+#if defined( PC )
+  if (((OptionFile = fopen(theOptionFileName =
+			     PCOptionFileName( file, TRUE ), "r")) != NULL)) {
+/* -------------------------------------------------------------------------------------
+      Removed temporarily so the PC version ONLY examines and creates option files
+      in the cwd. This will be changed when we determine a better strategy for 
+      PC directory PATH searches.
+    
+      ((OptionFile = fopen(theOptionFileName =
+			     PCOptionFileName( file, FALSE), "r")) != NULL)) {
+---------------------------------------------------------------------------------------*/
+#else
+  if ((OptionPathPtr = (char *)getenv(OPTION_PATH)) == NULL)
+    OptionPathPtr = DEFAULT_OPTION_PATH;
+
+  if ((OptionFile = fopen(theOptionFileName =
+			    search_path(UnixOptionFileName( file ),
+					OptionPathPtr), "r")) != NULL) {
+#endif
+
+    /* Process the Option File */
+
+    (void) processOptionFile(options, numOptions, OptionFile,
+			       theOptionFileName, FALSE, TRUE, file ) ;
+    (void) fclose(OptionFile);
+  
+    thereWasAnOptionsFile = TRUE;
+
+  }
+}
+
+
+/* Assign options from the command line */
+
+void cmd_line_nopts( options, numOptions, argc, argv )
+Option options[]  ;
+int    numOptions ;
+int    *argc      ;
+char   ***argv    ;
+{
+  int   i,         currentArg   ;
+  int   finalArg,  wasAHyphen   ;
+  char   name[MAX_NAME_LENGTH]  ;
+  char  value[MAX_NAME_LENGTH]  ;
+  char *line,           *linePtr;
+  char *tempstring;                    /* MAA 23-4-1994 */
+  char *tempstring2;                   /* MAA 23-4-1994 */
+  int count=0;
+
+
+  /* MAA: next 3 lines */
+  linePtr = (char *) calloc((size_t) MAX_NAME_LENGTH, (size_t) sizeof(char));
+  tempstring = (char *) calloc((size_t) MAX_NAME_LENGTH, (size_t) sizeof(char));
+  tempstring2 = (char *) calloc((size_t) MAX_NAME_LENGTH, (size_t) sizeof(char));
+
+
+  finalArg = currentArg = 1;  /* Ignore the Program Name */
+  line     = malloc((unsigned) MAX_LINE_LENGTH);
+
+  while (currentArg < *argc) {
+    wasAHyphen = FALSE;
+    linePtr = strcpy(line, (*argv)[currentArg]);
+    if (linePtr[0] == HYPHEN_CHARACTER) {
+      wasAHyphen = TRUE;
+      linePtr++;         /* Skip any leading hyphen */
+    }
+
+    /* MAA: force doublequotes onto beg & end . A rather big hack ...*/
+    if (strchr(linePtr, BLANK_CHARACTER) != NULL){
+      strncpy(tempstring, linePtr, (int) strcspn(linePtr, "="));
+      strcat(tempstring, "=\"");
+      tempstring2 = (char *) strrchr(linePtr, EQUALS_CHARACTER);
+      tempstring2++;
+      strcat(tempstring, tempstring2);
+      strcat(tempstring, "\"");
+      linePtr=tempstring;}
+  
+
+    if ((linePtr = getName(linePtr, name)) == NULL) {
+      break;
+    }
+
+    if ((linePtr = skipEquals(linePtr)) == NULL) {
+      if (!wasAHyphen) {
+	break;           /* Don't interpret <name> <value> as being options */
+      }
+      if (strcmp(name, HELP_STRING) == 0) {
+#ifdef PC
+	if (strncmp((*argv)[0]+strlen((*argv)[0])-strlen("gen.exe"), "gen", strlen("gen")) == 0)
+#else
+	if (strcmp((*argv)[0], "gen") == 0)
+#endif
+	  /* Special case of gen -help */
+	  usageHelp();
+	else
+	  /* Case of gen??? -help */
+	  (*onLineHelpHandler)(options, numOptions, (*argv)[0]);
+    	exit(0);
+      }
+
+      if (strcmp(name, UPDATE_STRING) == 0) {
+        /* Do the Update and Then Goto the Top of the Loop Again */
+    	updateOptionsFile(options, numOptions, (*argv)[0], theOptionFileName);
+        finalArg = ++currentArg;
+        continue;
+      }
+
+      (void) strcpy(value, DEFAULT_TOGGLE_VALUE);
+    }
+    else {
+      if ((linePtr = getName(linePtr, value)) == NULL) {
+	break;
+      }
+    }
+
+    if(!LookUpAndStore(options, numOptions, name, value, TRUE, (*argv)[0])) {
+      (void) fprintf(stderr,"options: Could not find an Option called %s\n", name);
+      exit(1);
+    }
+
+    finalArg = ++currentArg;
+  }
+  
+  /* Reset the Command Line argc and argv */
+  /* The Original Version actually cut the options out of the argv array (by
+     shifting the remaining arguments left), but the new version simply lets
+     argv point to the next argument to be processed. 
+
+  if (finalArg > 1) {
+    for (i = finalArg; i < *argc; i++)
+      (*argv)[i - finalArg + 1] = (*argv)[i];
+    *argc = *argc - finalArg + 1;
+  }
+
+  */
+
+  *argv+= finalArg;
+  *argc = *argc - finalArg;
+
+  return;
+}
+
+
+
+/* Assign options using defaults, then the rc file, then the command line */
+
+void getnopts (options, numOptions, argc, argv)
+Option options[]  ;
+int    numOptions ;
+int    *argc      ;
+char   ***argv    ;
+{
+    default_nopts( options, numOptions ) ;
+    rcfile_nopts( options, numOptions, (*argv)[0] ) ;
+    cmd_line_nopts( options, numOptions, argc, argv ) ;
+}
+
+
+
+/* -------------------------------------------------------------------------------
+
+   Read an option header from the specified file into the given options array.
+
+   ------------------------------------------------------------------------------- */
+void readnopts(options, numOptions, filePointer)
+     Option options[] ;
+     int      numOptions;
+     FILE    *filePointer ;
+{
+  long filePosition     ;
+  char first[200]       ;
+  int  headerLength     ;
+
+  filePosition = ftell(filePointer);   /* Save the Original Position */
+
+  /*  Read the first line of the first block, or as much of it as possible */
+
+  if ((!fread(first, 1, strlen(OptionHeaderHeader) + OPTION_HEADER_DIGITS
+	      + strlen(LineFeedArray), filePointer)) ||
+      (strncmp(first, OptionHeaderHeader, strlen(OptionHeaderHeader)) != 0)) {
+	       /* Assume that this is NOT a option header */
+	       if (fseek(filePointer, filePosition, 0)) {
+		 (void) fprintf(stderr, "options: Error fseeking Option Header File\n");
+		 exit(1);
+	       }
+	       return;
+	     }
+
+  /* Extract the Header Length in Bytes */
+
+  headerLength = atoi(first + strlen(OptionHeaderHeader));
+
+  /* Now, process the stuff. Need to "seek" past the first line before
+     attempting to read anything, and shorten the headerLength accordingly */
+
+  (void) processOptionFile(options, numOptions, filePointer,
+			     "Unknown Option File",
+			     (headerLength - strlen(OptionHeaderHeader) -
+			      OPTION_HEADER_DIGITS - strlen(LineFeedArray)),
+			     FALSE, "???");
+
+  /*  Make sure that the file pointer is set to the data area */
+  
+  if (fseek(filePointer, filePosition + headerLength, 0)) {
+    (void) fprintf(stderr, "options: Error fseeking Option Header File\n");
+    exit(1);
+  }
+
+}
+
+
+/* -------------------------------------------------------------------------------
+
+   Count the number of bytes which will be written by writenopts, given the
+   options array.
+
+   ------------------------------------------------------------------------------- */
+static int countBytesToWrite( options, numOptions )
+     Option   options[] ;
+     int      numOptions;
+{
+  int sum, i;
+
+  sum = 0;
+
+  for (i = 0; i < numOptions; i++)
+    if((options[i].classification == OutputOption ||
+	options[i].classification == InOutOption)    &&
+       *(options[i].value) != NULL &&
+       strcmp(*(options[i].value), NULL_STRING) != 0)
+      sum += strlen(options[i].name) + strlen(EqualsArray) +
+	strlen(*(options[i].value))  + strlen(LineFeedArray); /* + (2 * strlen(QuotesArray)); */
+
+  return (sum);
+}
+
+/* -------------------------------------------------------------------------------
+
+   The descendent of the lost and lamented blockCopyStrToFile... writes a string
+   to the indicated file. 
+
+   ------------------------------------------------------------------------------- */
+static void WriteStringToFile(str, filePtr)
+     char *str;
+     FILE *filePtr;
+{
+  if (!fwrite(str, 1, strlen(str), filePtr)) {
+    (void) fprintf(stderr, "WriteStringToFile: Error printing %s to file.\n", str);
+    exit(1);
+  }
+
+  return;
+}
+
+
+/* -------------------------------------------------------------------------------
+
+   Write an option header to the specified file from the information contained
+   in the given options array. Remove the comments to get debugging info.
+
+   ------------------------------------------------------------------------------- */
+void writenopts(options, numOptions, filePointer)
+     Option options[] ;
+     int      numOptions;
+     FILE    *filePointer ;
+{
+/*int  bytesWritten     ;*/
+  int  i                ;
+  long filePosition     ;
+  int  bytesToWrite     ;
+  int  oddHeaderLength  ;
+  char DigitString[OPTION_HEADER_DIGITS + 2];
+
+  filePosition = ftell(filePointer);
+
+  bytesToWrite = countBytesToWrite(options, numOptions) +
+    strlen(OptionHeaderHeader) + OPTION_HEADER_DIGITS +
+      strlen(LineFeedArray) + 1;
+
+  if (oddHeaderLength = (bytesToWrite % 2))
+    bytesToWrite++;
+
+  (void) WriteStringToFile(OptionHeaderHeader, filePointer);
+
+  (void) sprintf(DigitString, "%0*d", OPTION_HEADER_DIGITS, bytesToWrite);
+
+/*(void) printf("bytesToWrite is %i.\n", bytesToWrite);*/
+
+  (void) WriteStringToFile(DigitString, filePointer);
+
+  (void) WriteStringToFile(LineFeedArray, filePointer);
+		       
+  /* Copy all of the Options */
+
+  for (i = 0; i < numOptions; i++) {
+
+    if((options[i].classification == OutputOption ||
+	options[i].classification == InOutOption)    &&
+       *(options[i].value) != NULL &&
+       strcmp(*(options[i].value), NULL_STRING) != 0) {
+
+      (void) WriteStringToFile(options[i].name, filePointer);
+  
+      (void) WriteStringToFile(EqualsArray, filePointer);
+
+/*    (void) WriteStringToFile(QuotesArray, filePointer);  */
+
+      (void) WriteStringToFile(*(options[i].value), filePointer);
+  
+/*    (void) WriteStringToFile(QuotesArray, filePointer);  */
+
+      (void) WriteStringToFile(LineFeedArray, filePointer);
+    }
+  }
+
+  if (fputc(NULL_CHARACTER, filePointer) == EOF) {
+    (void) fprintf(stderr, "writenopts: Error doing fputc of the last NULL character.\n");
+    exit(1);
+  }
+
+  if (oddHeaderLength && fputc(NULL_CHARACTER, filePointer) == EOF) {
+    (void) fprintf(stderr, "writenopts: Error doing fputc of the odd-pad NULL character.\n");
+    exit(1);
+  }
+  
+  if (fflush(filePointer)) {
+    (void) fprintf(stderr, "options: Error while flushing the option header\n");
+    exit(1);
+  }
+
+  /* seek the fileptr to after the last byte of the header */
+
+  if (filePointer != stdout) {
+      if (fseek(filePointer, filePosition + (long)bytesToWrite, 0)) {
+	(void) fprintf(stderr, "options: Error fseeking Option Header File\n");
+	exit(1);
+      }
+  }
+
+}
+
+
+/* ----------------------------------------------------------------------------
+
+   A Little Routine to Count the Options in a Options Array .... This MUST
+   Be NULL-Terminated ...... OR ELSE! 
+
+   ---------------------------------------------------------------------------- */
+
+static int countOptions(options)
+     Option options[];
+{
+  int numoptions;
+
+  for (numoptions = 0;
+       options[numoptions].name != NULL;  /* DEATH TO ALL WHO TREAD HERE! */
+       numoptions++);
+
+  return (numoptions);
+
+}
+
+
+/* -------------------------------------------------------------------------------
+
+   The Counting version of getnopts -- you MUST null-terminate the options array.
+
+   ------------------------------------------------------------------------------- */
+
+void getopts (options, argc, argv)
+     Option options[] ;
+     int      *argc        ;
+     char     ***argv      ;
+{
+  (void) getnopts(options, countOptions(options), argc, argv);
+}
+
+
+void cmd_line_opts(options, argc, argv)
+Option options[]  ;
+int    *argc      ;
+char   ***argv    ;
+{
+    (void) cmd_line_nopts( options, countOptions(options), argc, argv ) ;
+}
+
+
+
+/* -------------------------------------------------------------------------------
+
+   The Counting version of readnopts -- you MUST null-terminate the options array.
+
+   ------------------------------------------------------------------------------- */
+void readopts(options, filePointer)
+     Option options[] ;
+     FILE    *filePointer ;
+{
+  (void) readnopts(options, countOptions(options), filePointer);
+}
+
+/* -------------------------------------------------------------------------------
+
+   The Counting version of writenopts -- you MUST null-terminate the options array.
+
+   ------------------------------------------------------------------------------- */
+void writeopts(options, filePointer)
+     Option options[] ;
+     FILE    *filePointer ;
+{
+  (void) writenopts(options, countOptions(options), filePointer);
+}
+
+
+/* -------------------------------------------------------------------------------
+
+   Packaging for convenience -- Guaranteed to be Listeria-free!
+
+   ------------------------------------------------------------------------------- */
+
+FILE *fileopts( res, argc, argv )
+Option *res   ;
+int      *argc  ;
+char    **argv[];
+{
+    FILE *ifp ;
+    int numOptions;
+#if defined( PC )
+    char *progName ;
+
+    progName = (*argv)[0];
+#endif
+
+    numOptions = countOptions(res);
+    
+    getnopts( res, numOptions, argc, argv ) ;
+
+    if( *argc > 0 ) {
+      if((ifp = fopen( **argv, "r" )) == NULL) {
+	(void) fprintf(stderr, "Unable to open the file %s.\n", **argv);
+	exit(1);
+    	}
+    }
+    else
+#if defined( PC )
+        {
+        /* PCs cannot take binmode files through standard input */
+        (void) (*onLineHelpHandler)( res, numOptions, progName );
+        exit(1);
+        }
+#else
+	ifp = stdin ;
+#endif
+
+    (*argv)++ ;
+    (*argc)-- ;
+
+    readopts( res, ifp ) ;
+
+    return( ifp ) ;
+
+}
+
+
+/* -------------------------------------------------------------------------------
+
+   Packaging for convenience -- Guaranteed to be Listeria-free!
+
+   ------------------------------------------------------------------------------- */
+FILE *optoutput(str)
+     char *str;
+{
+  FILE *f;
+
+  if (str == NULL)
+    return (NULL);
+  else if (str == DEFAULT_TOGGLE_VALUE)
+    return (stdout);
+  
+  if ((f = fopen(str, "w")) == NULL) {
+    (void) fprintf(stderr, "options: Could not open the file %s for output.\n", str);
+    exit(1);
+  }
+  return (f);
+}
+
+
+/* -------------------------------------------------------------------------------
+
+   OnLine Help from the user program.
+
+   ------------------------------------------------------------------------------- */
+void helpnopts(res, numRes, name)
+     Option res[];
+     int     numRes;
+     char     *name ;
+{
+  (void) (*onLineHelpHandler)(res, numRes, name);
+}
+     
+/* -------------------------------------------------------------------------------
+
+   OnLine Help from the user program. (counting version)
+
+   ------------------------------------------------------------------------------- */
+void helpopts(res, name)
+     Option res[];
+     char     *name ;
+{
+#ifdef PC
+  if (strncmp(name+strlen(name)-strlen("gen.exe"), "gen", strlen("gen")) == 0)
+#else
+  if (strcmp(name, "gen") == 0)
+#endif
+    /* Special case of gen */
+    usageHelp();
+  else
+    /* Case of gen??? */
+    (void) (*onLineHelpHandler)(res, countOptions(res), name);
+}
+
+     
+/* ---------------------------------------------------------------------------------
+
+   Allows an application program to install its very own helpHandler routine to
+   override the default help-message handler. The behaviour of such a routine is
+   implicitly trusted by <options>, so you should only install your own handler 
+   when you are quite familiar with the Options structure format. This routine
+   returns the address of the previously installed handler (which is initially the
+   default handler) so that this may be reinstated at a later point.
+
+   ---------------------------------------------------------------------------------- */
+
+helpRoutine *helpOptsHandler(aHelpRoutine)
+     helpRoutine *aHelpRoutine;
+{
+  helpRoutine *temp;
+
+  temp = onLineHelpHandler;
+
+  onLineHelpHandler = aHelpRoutine;
+
+  return (temp);
+}
+
+
+/* ---------------------------------------------------------------------------------
+
+   A convenience call which returns TRUE (1) if the optionStr is what options thinks
+   of as "ON", "YES", "TRUE", or "1".... This merely allows us to hide the actual
+   implementation of "ON" from the application programs.
+      
+   --------------------------------------------------------------------------------- */
+
+int isOFF(optionStr)
+     char *optionStr;
+{
+  return (strcmp(OFF_STRING, optionStr) == 0 ||
+	  strcmp(OFF_ALIAS , optionStr) == 0 ||
+	  strcmp(NOT_USED  , optionStr) == 0);
+}
+
+
+/* ---------------------------------------------------------------------------------
+
+   A convenience call which returns TRUE (1) if the optionStr is what options thinks
+   of as "NULL", "NONE", nothing, zip, etc... This merely allows us to hide the actual
+   implementation of "NULL" from the application programs.
+      
+   --------------------------------------------------------------------------------- */
+
+int isNULL(optionStr)
+     char *optionStr;
+{
+  return (optionStr == NULL ||
+	  strcmp(NULL_STRING, optionStr) == 0 ||
+	  strcmp(NULL_ALIAS , optionStr) == 0);
+}
+
+
+/* ---------------------------------------------------------------------------------
+
+   A routine to reduce the load on the application programmer by providing a simple
+   boolean check for string equality WITHOUT CASE SIGNIFICANCE. This allows applications
+   to leave case and typing problems within "options" reliably.
+      
+   --------------------------------------------------------------------------------- */
+
+static char *stringToLowerCase(str)
+     char *str;
+{
+  register int i;
+
+  if (str == NULL)
+    return (str);
+  else {
+    for (i = 0; str[i] != NULL_CHARACTER; i++)
+      if (isupper((char) str[i]))
+	str[i] = (char) tolower((char) str[i]);
+    return (str);
+  }
+}
+  
+extern int OptionStringsEqual(str1, str2)
+     char *str1, *str2;
+{
+  /* This routine copies the strings into two local buffers, converts them to
+     lower case, and then compares them for equality. This local copy ensures
+     that they are automatically deallocated on function return */
+
+#define MAX_COPY_LENGTH (256)
+
+  char lc1[MAX_COPY_LENGTH], lc2[MAX_COPY_LENGTH];
+
+  if (strlen(str1) < MAX_COPY_LENGTH &&
+      strlen(str2) < MAX_COPY_LENGTH)
+    return (strcmp(stringToLowerCase(strcpy(lc1, str1)),
+		   stringToLowerCase(strcpy(lc2, str2))) == 0);
+  else {
+    (void) fprintf(stderr, "options: OptionStringsEqual() could not compare the strings %s and %s becaues one was more that %i characters long.\n", str1, str2, MAX_COPY_LENGTH);
+    exit(1);
+  }
+}
+
+
+
+/* Print general usage information in response to:  gen -help */
+usageHelp()
+{
+  (void)fprintf(stdout,"%s\n\n", versionstr);
+
+  (void) fprintf(stdout, "Usage: genXXX  [options]  [file_name]\n");
+  (void) fprintf(stdout, "       where XXX  is one of the following abbreviations:\n\n\
+    wav     waveform                            \n\
+    bmm     basilar membrane motion             \n\
+    nap     neural activity pattern             \n\
+    sai     stabilized auditory image           \n\
+    spl     spiral version of auditory image    \n\
+    sgm     spectrogram                         \n\
+    cgm     cochleogram  " ) ;
+  (void) fprintf(stdout, "\n\
+    asa     auditory spectral analysis          \n\
+    epn     excitation pattern                  \n\n");
+
+  (void) fprintf(stdout, "    [file_name] is a headerless wave file (2-byte binary integers).\n");
+  (void) fprintf(stdout, "    [options]   are parameters, options and swtiches that control\n");
+  (void) fprintf(stdout, "                the AIM instructions and the AIM tools.\n\n");
+
+  (void) fprintf(stdout, "    Help with options:  genXXX  [-help | -help=all | -help=option]\n");
+#if !defined( PC )
+  (void) fprintf(stdout, "    Path for options file, (.genXXXrc) = .     (or setenv OPTIONSPATH)\n\n");
+#endif
+
+  (void) fprintf(stdout, "Processes Applied by AIM and Routes Through the Model: \n\n\
+    Process                             Auditory   Speech   Spectra  \n\
+    --------------------------------    --------   ------   -------  \n\
+    Display input wave                   genwav    genwav    genwav  \n\
+    Auditory filtering (gtf/tlf)         genbmm                      \n\
+    Compression and rectification                  gensgm    genasa  " ) ;
+
+  (void) fprintf(stdout, "\n\
+    Neural encoding (2D-AT/haircell)     gennap                      \n\
+    Temporal integration (LP filter)               gencgm    genepn  \n\
+    Strobed temporal integration         gensai                      \n\
+    Spiral mapping of auditory image     genspl                      \n\n");
+
+  (void) fprintf(stdout, "Output:   genXXX  output=on  file_name    \n");
+  (void) fprintf(stdout, "          output is written to file: file_name.XXX    \n");
+
+  (void) fprintf(stdout, "\n\
+    The format for 2-dimensional  output format  is by columns,  with the \n\
+    lowest channel first  in each  column  (bmm, nap, sgm, cgm, asa, epn).\n\
+    The format for auditory image output is by rows, for each image frame \n\
+    in succession,  with the row  of the lowest channel first  (sai, spl).\n\n");
+
+  (void) fprintf(stdout, "The Auditory Image Model was developed at the Applied Psychology Unit\n");
+  (void) fprintf(stdout, "of the Medical Research Council, 15 Chaucer Road, Cambridge, U.K.\n\n");
+
+  (void) fprintf(stdout, "Copyright(c) Applied Psychology Unit, Medical Research Council, 1988-1995.\n");
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glib/options.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,313 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/* ---------------------------------------------------------------------------------
+
+                                            *
+   The Leanest Resource Manager in the West
+   -----------------------------------------
+                                           
+
+                                   (*) is no more! The gallant <getopts.[ch]> has
+                                       given way to a new daring duo! Henceforth,
+                                       read "options" for "getopts". The new features
+                                       include classified options and user-supplied
+                                       "Help" information. See <options.c> for edit
+                                       history.
+
+   Copyright (c), 1989  The Medical Research Council of the United Kingdom.
+
+   Author  :    Paul Manson
+   Written :    March 1st 1989  [See options.c for modifications history]
+
+   Options may be supplied as defaults (actually in the code), as command line
+   arguments, and in an option file. The default arguments may be overridden by
+   the option-file contents, which may be overridden in turn by command line
+   arguments. The syntax of a option file is as follows:
+
+   <option file> ::= { <option line> <linefeed> }
+
+   <option line> ::= <option specification> | <comment line> | <blank line>
+
+   <option specification> ::= <name> "=" <option value> [ <comment line> ]
+
+   <option value> ::= <contiguous character string> | 
+                        """ <any printable chars except """> """
+
+   <comment line> ::= "#" <absolutely anything>
+
+   where spaces are not considered significant except that the <value> ought to
+   be a quoted string if it contains spaces. On Unix, the OPTIONSPATH path in the
+   users' environment is used to search for a option file, but if this path is
+   absent, the current working directory will still be searched. On an IBM PC, the
+   the directory in which the application program was found is searched for the
+   option file. [In the future, this will be modified so that the current directory
+   is searched first].
+
+   Command line arguments may take any of the following forms;
+
+   1.     -name
+   
+   2.     -name=value
+
+   3.     name=value
+
+   where it should be noted that spaces ARE significant, and that the first of these
+   formats effects a set/toggle operation on the named option, by setting its 
+   value to some system-defined default value (at present, this is "1").
+
+   If a user specifies -help on the command line then getopts uses the "help" option
+   (if there is one) to print a message detailing the options available to the
+   user. Specifying -update on the command line causes a new version of the currently
+   read option file to be written, incorporating any alterations which have been
+   effected by previous command line options.
+
+   Abbreviations are permitted for options, but it must be noted that only
+   unambiguous option specifications will have any effect (ambiguous specifications
+   are rejected with a warning message). If a option specification uses a name which
+   is an abbreviation for two options, but matches one of these options EXACTLY,
+   this is not considered to be ambiguous (the exact match being taken as the intended
+   one). Abbreviations are NOT permitted in option headers (see readopts and writeopts
+   below).
+
+   --------------------------------------------------------------------------------- */
+
+#include <stdio.h>
+
+#define InputOption (1)
+#define OutputOption (2)
+#define InOutOption (0)
+#define SilentOption (3)
+
+typedef struct {
+  char *name          ;    /* The name of the option,                      */
+  char *defaultValue  ;    /* its default value,                             */
+  char **value        ;    /* The place where its current value is stored    */
+  char *comment       ;    /* Something to print when the user types "-help" */
+  short classification;    /* What form of option it is.                     */
+} Option, *OptionPtr;
+
+/* ---------------------------------------------------------------------------------
+
+   This structure may be used to build a database of option handles, as indicated
+   in the following sample program;
+
+   static char *samplerate, *inputfile;
+
+   static Option res[] = {
+        { "Sample Rate", "10000.0",    &samplerate, "The Rate of Sampling", InOutOption },
+        { "Input File ", "input.data", &inputfile , "A File to Read From ", InOutOption }};
+
+   which declares two options, <samplerate> and <inputfile>, and gives them 
+   default values. These defaults may later be overwritten by the function
+   getopts(), either from the option file or from the command line.
+
+   --------------------------------------------------------------------------------- */
+
+
+#define NumOptions(res) (sizeof(res) / ((sizeof(char *) + (sizeof(char **)))))
+
+/* ---------------------------------------------------------------------------------
+
+   Provides a macro for determining how many options are present in a res[]
+   declaration such as that shown above. eg. NumOptions(res) == 2. This macro
+   should be used on calls to getopts, etc.
+
+   --------------------------------------------------------------------------------- */
+
+
+extern void getnopts(); /* (options, numOptions, &argc, &argv) */
+
+/* ---------------------------------------------------------------------------------
+
+   This function should be called before an application program examines its arguments
+   (this is because it butchers them!). First of all, it reads the appropriate option
+   file and interprets the options specified therein (the name of the option file
+   is given by the name of the application, ie. argv[0]). After redefining the options
+   specified by the option file, it examines the arguments (given by argc and argv) 
+   and scans them for additional options. Finally, it resets argc and argv for the
+   remainder of the program (if any) to deal with. NOTE THAT argc AND argv _MUST_ BE
+   PASSED AS POINTERS TO THIS ROUTINE!.
+
+   --------------------------------------------------------------------------------- */
+
+
+extern void getopts();          /* (options, &argc, &argv) */
+extern void cmd_line_opts() ;   /* (options, &argc, &argv) */
+
+/* ---------------------------------------------------------------------------------
+
+   Some fussy people don't like to count their own option lists, so this routine
+   does the necessary dirty-work before passing the result(s) to getnopts(). You MUST
+   remember to null-terminate your options array; ie.
+
+   static char *samplerate, *inputfile;
+
+   static Option res[] = {
+        { "Sample Rate", "10000.0",    &samplerate, "The Rate of Sampling", InOutOption },
+        { "Input File ", "input.data", &inputfile , "A File to Read From ", InOutOption },
+	NULL};
+
+   and upon your own head (or lesser, more sensitive, appendages) be it if you forget
+   to do this!
+
+   --------------------------------------------------------------------------------- */
+
+
+extern void readnopts(); /* (options, numOptions, filePointer) */
+extern void readopts() ; /* (options, filePointer)               */
+
+/* ---------------------------------------------------------------------------------
+
+   Try to read a options header from the specified <file>, with reference to the
+   array of <options>. The header layout is specified below (see writenopts), and
+   the operation, if successful, will leave the filePointer set to the first byte
+   after the (padded) option header. Unsuccessful readnopts will cause en error
+   message and will terminate the program. If there does not appear to be a header
+   on the file at all, readnopts does nothing. The routine readopts counts the
+   options in <options> for you, and you MUST null-terminate your options
+   array if you use this routine. 
+
+   WARNING: readopts and readnopts do NOT require that a option name found in a 
+   header be an actual option of the calling program, and will IGNORE any such 
+   option assignments.
+
+   --------------------------------------------------------------------------------- */
+
+
+extern void writenopts(); /* (options, numOptions, filePointer) */
+extern void writeopts() ; /* (options, filePointer)               */
+
+/* ---------------------------------------------------------------------------------
+
+   Write the current option settings as specified by <options> into the 
+   specified file. The options are written as an ASCII header, in the same form
+   as is required by getopts (and consequently, readopts). This header will begin
+   with some suitable comment (line beginning with a # character) to indicate that
+   it is in fact a option header. Following this comment will be information 
+   concerning the size of the option file header. This information is used to tell
+   subsequent calls to readnopts the length of the option header; this header will 
+   actually be padded to a block boundary to avoid disturbing the following data
+   unnecessarily. As might be expected, writeopts is a counting version of writenopts;
+   remember to NULL-terminate your option array if you use this routine.
+   
+   --------------------------------------------------------------------------------- */
+
+
+extern FILE *fileopts();   /* (options, &argc, &argv ) */
+
+/* ---------------------------------------------------------------------------------
+
+   A packaging function which performs getopts(options, &argc, &argv), then fopens
+   the next argument and does readopts on it. It returns a file handle to this file
+   with the header removed (ie. it points at the first byte of data).
+   
+   --------------------------------------------------------------------------------- */
+
+extern FILE *optoutput(); /* (String) */
+
+/* ---------------------------------------------------------------------------------
+
+   Simply open a file for output (depending on the value of String)... a NULL string
+   returns NULL, the default String (at present this is "1") sends to stdout, and
+   anything else is taken as being a path name for a file to create for writing.
+   
+   --------------------------------------------------------------------------------- */
+
+extern void helpnopts(); /* (options, numOptions, program_name) */
+extern void helpopts(); /* (options, program_name) */
+
+/* ---------------------------------------------------------------------------------
+
+   Allows application programs to invoke the online help (ie. usage) information at
+   any point. The helpopts call counts the number of options for you, BUT ONLY IF
+   you remember to NULL-TERMINATE IT!
+      
+   --------------------------------------------------------------------------------- */
+
+typedef void helpRoutine( /* (options, numOptions, program_name) */ );
+
+extern helpRoutine *helpOptsHandler(); /* (helpRoutine) */
+
+/* ---------------------------------------------------------------------------------
+
+   Allows an application program to install its very own helpHandler routine to
+   override the default help-message handler. The behaviour of such a routine is
+   implicitly trusted by <options>, so you should only install your own handler 
+   when you are quite familiar with the Options structure format. This routine
+   returns the address of the previously installed handler (which is initially the
+   default handler) so that this may be reinstated at a later point.
+
+   ---------------------------------------------------------------------------------- */
+
+
+#define isON(_STR) (!isOFF(_STR))
+
+extern int isOFF();
+     /* char *optionStr; */
+
+/* ---------------------------------------------------------------------------------
+
+   A convenience call which returns TRUE (1) if the optionStr is what options thinks
+   of as "ON", "YES", "TRUE", or "1".... This merely allows us to hide the actual
+   implementation of "ON" from the application programs.
+      
+   --------------------------------------------------------------------------------- */
+
+extern int isNULL();
+     /* char *optionStr; */
+
+/* ---------------------------------------------------------------------------------
+
+   A convenience call which returns TRUE (1) if the optionStr is what options thinks
+   of as "NULL", "NONE", nothing, zip, etc... This merely allows us to hide the actual
+   implementation of "NULL" from the application programs.
+      
+   --------------------------------------------------------------------------------- */
+
+#define ON_OPTION "on"
+#define OFF_OPTION "off"
+#define NULL_OPTION "none"
+
+/* ---------------------------------------------------------------------------------
+
+  NOTE: The above definitions allow the expression of constant option settings
+  via static option[] arrays... they do so at the risk of allowing some klutz
+  to alter them... the only solution to this problem (other than forcing
+  application programmers to read .h files) is to return copies of these
+  strings via procedure calls, and this precludes static initialisation.
+      
+   --------------------------------------------------------------------------------- */
+
+extern int OptionStringsEqual();
+     /* char *str1, *str2; */
+
+/* ---------------------------------------------------------------------------------
+
+   A routine to reduce the load on the application programmer by providing a simple
+   boolean check for string equality WITHOUT CASE SIGNIFICANCE. This allows applications
+   to leave case and typing problems within "options" reliably.
+      
+   --------------------------------------------------------------------------------- */
+
+extern char *versionstr;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glib/ps.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,810 @@
+/*
+  Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+  ===========================================================================
+  Permission to use, copy, modify, and distribute this software without fee 
+  is hereby granted for research purposes, provided that this copyright 
+  notice appears in all copies and in all supporting documentation, and that 
+  the software is not redistributed for any fee (except for a nominal shipping 
+  charge). Anyone wanting to incorporate all or part of this software in a
+  commercial product must obtain a license from the Medical Research Council.
+  The MRC makes no representations about the suitability of this 
+  software for any purpose.  It is provided "as is" without express or implied 
+  warranty.
+
+  THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+  A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+  DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+  ps.c
+  ====
+  primitive PostScript interface ala windows.h interface.
+  Copyright (c), 1989  The Medical Research Council, Applied Psychology Unit.
+  Author  : John Holdsworth   22nd March, 1989.
+            Michael Akeroyd   Summer 1994.
+
+  Edited  : Roy P 27-11-92: commented out two if statements with this->hidden
+            in them to force hiddenline.
+            Also added '(void)' at start of line after second of the lines
+	    commented out to make it symmetric with similar lines.
+
+          : MAA. Summer 1994. rebuild. Notes:
+          (1) don't print windows bigger than 800 pixels wide; they aren't scaled 
+              properly. 
+          (2) all windows get drawn in the centre of the page.
+          (3) because of the 'fill's in drawing the data, the tick-marks can
+              get blanked out. To avoid this, the whole frame+marks are drawn
+              twice, at the begining (to get the coorect clipppath) and at the 
+              end
+          : MAA. Autumn 1994. rebuilt to avoid note (3).
+
+*/
+
+
+#include <stdio.h>
+#if defined(THINK_C) || defined(NeXT)
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+#include "windows.h"
+#include "grey.h"
+#include "options.h"   /* MAA: 23-4-1994: required for isON() */
+#include "string.h"    /* MAA: Summer 1994: required for atof() */
+#ifndef NeXT
+/* extern int fprintf() ;       */      /* mha 8/4/97:  sgi stops here */
+#endif
+
+static char *sccs_id = "@(#)ps.c	1.31     J. Holdsworth (MRC-APU)  7/7/93  Revised MAA 1994" ;
+
+
+/* resolution parameters for line width */
+#define POINTS_PER_INCH 72     /* standard definition of "points" */
+#define PIXELS_PER_INCH 300    /* laserwriterII */
+#define PIXELS_PER_POINT ( ( double ) PIXELS_PER_INCH / POINTS_PER_INCH )
+
+
+/* limitation on graphics path lengths */
+#define MAX_PATH 350 
+
+
+typedef struct {
+ windowEntries *entries ; /* pointers to method routines below */
+ char *xptr ;             /* general pointer to postscript device */
+ int (*sender)(), (*closer)() ;       /* function to transmit postscript */
+ int (*storer)(), (*recaller)(), (*reader)(), (*writer)(), (*pauser)() ; /* functions which may be used */
+ int x, y, width, height, pixels, hidden, page ; /* window paramaters */
+ enum { False, True } drawn, showpage ; /* if drawn and if clear not used and
+			                 window can be included in document */
+ struct _lookup *lookup ; /* state structure for dithering routines in grey.c*/
+ } *psWindowObject ;
+ 
+static windowsClass psClass ;
+
+
+
+/* MAA: lots of new options */
+extern *rotateaxesstr;
+extern char *xstartstr, *ystartstr, *xendstr, *yendstr;
+extern char *xnewtitlestr, *ynewtitlestr;
+extern char *portraitstr, *landscapestr;
+extern char *fontnamestr, *fontsizestr, *titlesizestr;
+extern char *xticksstr, *yticksstr, *outsidestr;
+extern char *axistopstr, *axisbottomstr, *axisleftstr, *axisrightstr;
+extern char *xmajorticksstr, *xminorticksstr;
+extern char *ymajorticksstr, *yminorticksstr;
+extern char *axislinewidthstr, *figurelinewidthstr; 
+extern char *boxstr;
+static double temp_xmin;
+static double temp_xmax;
+static double temp_ymin;
+static double temp_ymax;
+
+
+/*-----------------------------------------------------------------------*/
+
+
+WindowObject newPostScriptWindow( xptr, default_x, default_y, default_width, default_height, pixels, sender, closer, storer, recaller, reader, writer, pauser, pshidden )
+     char *xptr ;
+     int default_x, default_y, default_width, default_height, pixels ;
+     int (*sender)(), (*closer)() ;
+     int (*storer)(), (*recaller)(), (*reader)(), (*writer)(), (*pauser)() ;
+     int pshidden;            /* =0 if off, =1 if on */
+{
+  psWindowObject this = ( psWindowObject ) malloc( sizeof ( *this ) ) ;
+  char psfontstr[30];
+  char **ptr ;
+
+  if( psClass.super == (windowsClass *) 0 )
+    (void) initPostScriptClass( &psClass ) ;
+  this->entries = &psClass.entries ;
+  this->xptr     = xptr ;
+  this->sender   = sender ;
+  this->storer   = storer ;
+  this->recaller = recaller ;
+  this->reader   = reader ;
+  this->writer   = writer ;
+  this->pauser   = pauser ;
+  this->closer   = closer ;
+  this->x       = default_x ;
+  this->y       = default_y ;
+  this->width   = default_width ;
+  this->height  = default_height ;
+  this->hidden  = pshidden ;
+  this->pixels  = abs( pixels ) ;
+  this->lookup  = 0 ;
+  this->drawn   = False ;
+
+  (void) this->sender( this->xptr, "%%!PS-Adobe-2.0 EPSF-1.2\n");
+  (void) this->sender( this->xptr, "%%%%Title: Windows postscript file\n");
+  (void) this->sender( this->xptr, "%%%%Creator: %s\n", sccs_id);
+  (void) this->sender( this->xptr, "%%%%BoundingBox: %d %d %d %d\n", this->x, this->y, this->x+this->width, this->y+this->height);
+  (void) this->sender( this->xptr, "%%%%Pages: (atend)\n", this->y);
+/*  (void) this->sender( this->xptr, "%%%%DocumentFonts: Times-Roman\n");*/
+  (void) this->sender( this->xptr, "%%%%EndComments\n") ;
+  
+  if ( this->hidden == 0 ) {
+    (void) this->sender( this->xptr, "\n%%/fill workaround: no hidden lines. MAA. 22-1-1993\n" );
+    (void) this->sender( this->xptr, "/fill {} def\n\n" );}
+  else ;
+
+  /* Fonts. The only allowed ones are Times-Roman, Helvetica and Courier,
+   * because they are the only three you get in the Adobe Red Book, and
+   * so are presumably the onyl three you get in all printers.*/
+  if      (!strcmp(fontnamestr, "Times")) {strcpy(psfontstr, "Times-Roman");}
+  else if (!strcmp(fontnamestr, "times")) {strcpy(psfontstr, "Times-Roman");}
+  else if (!strcmp(fontnamestr, "Roman")) {strcpy(psfontstr, "Times-Roman");}
+  else if (!strcmp(fontnamestr, "roman")) {strcpy(psfontstr, "Times-Roman");}
+  else if (!strcmp(fontnamestr, "times-roman")) {strcpy(psfontstr, "Times-Roman");}
+  else if (!strcmp(fontnamestr, "Times-Roman")) {strcpy(psfontstr, "Times-Roman");}
+  else if (!strcmp(fontnamestr, "timesroman")) {strcpy(psfontstr, "Times-Roman");}
+  else if (!strcmp(fontnamestr, "RimesRoman")) {strcpy(psfontstr, "Times-Roman");}
+  else if (!strcmp(fontnamestr, "TimesBold")) {strcpy(psfontstr, "Times-Bold");}
+  else if (!strcmp(fontnamestr, "timesbold")) {strcpy(psfontstr, "Times-Bold");}
+  else if (!strcmp(fontnamestr, "timesbold")) {strcpy(psfontstr, "Times-Bold");}
+  else if (!strcmp(fontnamestr, "times-bold")) {strcpy(psfontstr, "Times-Bold");}
+  else if (!strcmp(fontnamestr, "Times-Bold")) {strcpy(psfontstr, "Times-Bold");}
+						
+  else if (!strcmp(fontnamestr, "Helvetica")) {strcpy(psfontstr, "Helvetica");}
+  else if (!strcmp(fontnamestr, "helvetica")) {strcpy(psfontstr, "Helvetica");}
+  else if (!strcmp(fontnamestr, "Hel")) {strcpy(psfontstr, "Helvetica");}
+  else if (!strcmp(fontnamestr, "hel")) {strcpy(psfontstr, "Helvetica");}
+  else if (!strcmp(fontnamestr, "HelveticaBold")) {strcpy(psfontstr, "Helvetica-Bold");}
+  else if (!strcmp(fontnamestr, "Helveticabold")) {strcpy(psfontstr, "Helvetica-Bold");}
+  else if (!strcmp(fontnamestr, "helveticabold")) {strcpy(psfontstr, "Helvetica-Bold");}
+  else if (!strcmp(fontnamestr, "Helvetica-Bold")) {strcpy(psfontstr, "Helvetica-Bold");}
+  else if (!strcmp(fontnamestr, "helvetica-bold")) {strcpy(psfontstr, "Helvetica-Bold");}
+  else if (!strcmp(fontnamestr, "helbold")) {strcpy(psfontstr, "Helvetica-Bold");}
+  else if (!strcmp(fontnamestr, "HelBold")) {strcpy(psfontstr, "Helvetica-Bold");}
+
+  else if (!strcmp(fontnamestr, "Courier")) {strcpy(psfontstr, "Courier");}
+  else if (!strcmp(fontnamestr, "courier")) {strcpy(psfontstr, "Courier");}
+  else if (!strcmp(fontnamestr, "Cou")) {strcpy(psfontstr, "Courier");}
+  else if (!strcmp(fontnamestr, "cou")) {strcpy(psfontstr, "Courier");}
+  else if (!strcmp(fontnamestr, "Courier-Bold")) {strcpy(psfontstr, "Courier-Bold");}
+  else if (!strcmp(fontnamestr, "courier-bold")) {strcpy(psfontstr, "Courier-Bold");}
+  else if (!strcmp(fontnamestr, "courierbold")) {strcpy(psfontstr, "Courier-Bold");}
+  else if (!strcmp(fontnamestr, "CourierBold")) {strcpy(psfontstr, "Courier-Bold");}
+  else if (!strcmp(fontnamestr, "CouBold")) {strcpy(psfontstr, "Courier-Bold");}
+  else if (!strcmp(fontnamestr, "coubold")) {strcpy(psfontstr, "Courier-Bold");}
+  
+  else {
+    fprintf(stderr, "WARNING: Unknown font %s. (allowed time, helvetica or courier.)\n", fontnamestr);
+    fprintf(stderr, "WARNING: Stopping here; no Postscript generated\n");
+    exit(-1);}
+
+
+  /* copy postscript code for axes into output file */
+  (void) this->sender( this->xptr, "%%! simple postscript axes\n");
+  (void) this->sender( this->xptr, "%% v1.10 John Holdsworth (5/31/91).\n");
+  (void) this->sender( this->xptr, "%% Revised M Akeroyd (Summer, Autumn 1994)\n");
+  (void) this->sender( this->xptr, "\n");
+  (void) this->sender( this->xptr, "  /midprint { %% str x y midprint -\n");
+  (void) this->sender( this->xptr, "    moveto\n");
+  (void) this->sender( this->xptr, "    dup\n");
+  (void) this->sender( this->xptr, "    stringwidth pop 2 div neg 0 rmoveto\n");
+  (void) this->sender( this->xptr, "    show\n");
+  (void) this->sender( this->xptr, "  } def\n");
+  (void) this->sender( this->xptr, "\n");
+  (void) this->sender( this->xptr, "  /leftprint { %% str x y leftprint -\n");
+  (void) this->sender( this->xptr, "    moveto\n");
+  (void) this->sender( this->xptr, "    dup\n");   
+  (void) this->sender( this->xptr, "    stringwidth pop neg fontsize 0.4 mul neg rmoveto\n");
+  (void) this->sender( this->xptr, "    show\n");  
+  (void) this->sender( this->xptr, "  } def\n");
+  (void) this->sender( this->xptr, "\n");
+  (void) this->sender( this->xptr, "  /ticks { %% min max <float> <float> ticker -\n");
+  (void) this->sender( this->xptr, "    /ticker  exch def %% procedure to draw ticks\n");
+  (void) this->sender( this->xptr, "    /fmax exch cvr def %% relative spacing of max ticks (0.5x, etc)\n");
+  (void) this->sender( this->xptr, "    /fmin exch cvr def %% relative spacing of min ticks (0.5x, etc)\n");
+  (void) this->sender( this->xptr, "    /max exch cvr def %% axis maximum\n");
+  (void) this->sender( this->xptr, "    /min exch cvr def %% axis minimum\n");
+  (void) this->sender( this->xptr, "    /maxsubticks 50 def\n");
+  (void) this->sender( this->xptr, "    max min ne {\n");
+  (void) this->sender( this->xptr, "	%% calculate order of magnitude\n");
+  (void) this->sender( this->xptr, "	/delta max min sub log ceiling 1 sub 10 exch exp def\n");
+  (void) this->sender( this->xptr, "	%% do ticks\n");
+  (void) this->sender( this->xptr, "	min delta div ceiling delta mul\n");
+  (void) this->sender( this->xptr, "	delta fmax mul\n");
+  (void) this->sender( this->xptr, "	max delta div floor   delta mul\n");
+  (void) this->sender( this->xptr, "	{\n");
+  (void) this->sender( this->xptr, "		min sub max min sub div 1.333333 exch ticker\n");
+  (void) this->sender( this->xptr, "	}\n");
+  (void) this->sender( this->xptr, "	for\n");
+  (void) this->sender( this->xptr, "	%% do sub ticks (but only if fmin != 0)\n");
+  (void) this->sender( this->xptr, "	fmin 0 ne {");
+  (void) this->sender( this->xptr, "      max min sub delta div dup\n");
+  (void) this->sender( this->xptr, "	  10 mul maxsubticks lt {.1} {5 mul maxsubticks lt {.2} {.5} ifelse } ifelse\n");
+  (void) this->sender( this->xptr, "	  delta mul /delta exch def\n");
+  (void) this->sender( this->xptr, "	  min delta div ceiling delta mul\n");
+  (void) this->sender( this->xptr, "	  delta fmin mul \n");
+  (void) this->sender( this->xptr, "	  max delta div floor   delta mul\n");
+  (void) this->sender( this->xptr, "	  {\n");
+  /* MAA: This used to be 0.25; I've changed it (0.25 * 1.33), so its in real points.*/
+  (void) this->sender( this->xptr, "		  min sub max min sub div 0.666666 exch ticker\n");
+  (void) this->sender( this->xptr, "	  }\n");
+  (void) this->sender( this->xptr, "	  for\n");
+  (void) this->sender( this->xptr, "      } if\n");
+  (void) this->sender( this->xptr, "    } if\n");
+  (void) this->sender( this->xptr, "  } def\n");
+  (void) this->sender( this->xptr, "\n");
+  (void) this->sender( this->xptr, "/Axes { %% title xmin xmax xtitle ymin ymax ytitle Axes -\n");
+  (void) this->sender( this->xptr, "/AxesDict 50 dict def\n");
+  (void) this->sender( this->xptr, "AxesDict begin\n");
+  (void) this->sender( this->xptr, "  /ytitle exch def\n");
+  (void) this->sender( this->xptr, "  /ymax   exch def\n");
+  (void) this->sender( this->xptr, "  /ymin   exch def\n");
+  (void) this->sender( this->xptr, "  /xtitle exch def\n");
+  (void) this->sender( this->xptr, "  /xmax   exch def\n");
+  (void) this->sender( this->xptr, "  /xmin   exch def\n");
+  (void) this->sender( this->xptr, "  /title  exch def\n");
+  (void) this->sender( this->xptr, "  newpath clippath pathbbox /height exch def\n");
+  (void) this->sender( this->xptr, "			    /width  exch def\n");
+  (void) this->sender( this->xptr, "			    pop pop\n");
+  (void) this->sender( this->xptr, "  /tagsize  0.05 height mul neg def\n");
+  if (isOFF(xticksstr))
+    (void) this->sender( this->xptr, "  /xtagsize tagsize 1.33 mul def\n");
+  else
+    (void) this->sender( this->xptr, "  /xtagsize %s neg 1.33 mul def\n", xticksstr);
+  if (isOFF(yticksstr))
+    (void) this->sender( this->xptr, "  /ytagsize tagsize 1.33 mul def\n");
+  else
+    (void) this->sender( this->xptr, "  /ytagsize %s neg 1.33 mul def\n", yticksstr);
+  if (isOFF(fontsizestr))
+    (void) this->sender( this->xptr, "  /fontsize 0.05 height mul def\n");
+  else {
+    /* note 1.333 multiplier: required to get rid of the 0.75 later on */
+    (void) this->sender( this->xptr, "  /fontsize %s 1.333 mul def\n", fontsizestr);}
+  (void) this->sender( this->xptr, "  /space    0.10 height mul def\n");
+  (void) this->sender( this->xptr, "  /%s findfont fontsize scalefont setfont\n", psfontstr);
+  /* MAA: What do these 0.75/0.75 do? Quite a lot: they seem to be a screen -> paper multiplu constant*/
+  (void) this->sender( this->xptr, "  width 0.20 mul  0.15 height mul  translate  0.75 0.75 scale\n");
+  (void) this->sender( this->xptr, "  gsave\n");
+  (void) this->sender( this->xptr, "  gsave\n");
+  (void) this->sender( this->xptr, "  %s setlinewidth\n", axislinewidthstr);
+  /* MAA: I do  not knwo why this (2,2) translation is here, but it seems to get in the way */
+  /*  (void) this->sender( this->xptr, "  currentlinewidth 2 div neg dup translate\n");*/
+  (void) this->sender( this->xptr, "  newpath\n");
+  if (isOFF(titlesizestr))
+    (void) this->sender( this->xptr, "  title  width 2 div    height  tagsize  1.75 mul sub midprint\n");
+  else {
+    (void) this->sender( this->xptr, "  gsave\n");
+    /* note 1.333 multiplier: required to get rid of the 0.75 later on */
+    (void) this->sender( this->xptr, "  /%s findfont %s 1.333 mul scalefont  setfont\n", psfontstr, titlesizestr);
+    (void) this->sender( this->xptr, "  title  width 2 div    height  tagsize  1.75 mul sub midprint\n");}
+  if (isON(axisbottomstr)){
+    (void) this->sender( this->xptr, "  xmin   0              xtagsize fontsize sub midprint\n");
+    (void) this->sender( this->xptr, "  xmax   width          xtagsize fontsize sub midprint\n");
+    (void) this->sender( this->xptr, "  xmin cvr 0 lt  \n");
+    (void) this->sender( this->xptr, "    {xmax cvr 0 ge \n");
+    (void) this->sender( this->xptr, "       {(0) width xmin cvr neg xmin cvr neg xmax cvr add div mul xtagsize 1.0 mul fontsize sub midprint \n");
+    (void) this->sender( this->xptr, "        /xtitleconstant 2.0 def} \n");
+    (void) this->sender( this->xptr, "       {/xtitleconstant 1.0 def} \n");
+    (void) this->sender( this->xptr, "       ifelse}\n");
+    (void) this->sender( this->xptr, "    {/xtitleconstant 1.0 def} \n");
+    (void) this->sender( this->xptr, "    ifelse\n");
+    (void) this->sender( this->xptr, "  xtitle width 2 div    xtagsize xtitleconstant mul fontsize sub midprint\n");
+  }
+  if (isON(axisleftstr)) {
+    (void) this->sender( this->xptr, "  ymin   ytagsize  2.0 mul  0                    leftprint\n");
+    (void) this->sender( this->xptr, "  ymax   ytagsize  2.0 mul  height               leftprint\n");
+    (void) this->sender( this->xptr, "  ymin cvr 0 lt { \n");
+    (void) this->sender( this->xptr, "    ymax cvr 0 ge {\n");
+    (void) this->sender( this->xptr, "       (0) ytagsize  2.0 mul  height ymin cvr neg ymin cvr neg ymax cvr add div mul leftprint} \n");
+    (void) this->sender( this->xptr, "       if}\n");
+    (void) this->sender( this->xptr, "    if\n");}
+  (void) this->sender( this->xptr, "  90 rotate\n");
+  (void) this->sender( this->xptr, "  ytitle height 2 div   space   1.75 mul             midprint\n");
+  (void) this->sender( this->xptr, "  grestore\n"); 
+  (void) this->sender( this->xptr, "  grestore\n");
+  (void) this->sender( this->xptr, "end } def\n");
+  
+  
+  
+  /* MAA: New procedure AxesBox, which draws the box ... This is actually a revised workaround
+   * for the 'borderframe' problem. */
+  (void) this->sender( this->xptr, "\n\n" ) ;  
+  (void) this->sender( this->xptr, "/AxesBox { %% xmin xmax ymin ymax AxesBox -\n");
+  (void) this->sender( this->xptr, "/AxesBoxDict 50 dict def\n");
+  (void) this->sender( this->xptr, "AxesBoxDict begin\n");
+  (void) this->sender( this->xptr, "  /ymax   exch def\n");
+  (void) this->sender( this->xptr, "  /ymin   exch def\n");
+  (void) this->sender( this->xptr, "  /xmax   exch def\n");
+  (void) this->sender( this->xptr, "  /xmin   exch def\n");
+  (void) this->sender( this->xptr, "  newpath clippath pathbbox /height exch def\n");
+  (void) this->sender( this->xptr, "			    /width  exch def\n");
+  (void) this->sender( this->xptr, "			    pop pop\n");
+  (void) this->sender( this->xptr, "  /tagsize  0.05 height mul neg def\n");
+  if (isOFF(xticksstr))
+    (void) this->sender( this->xptr, "  /xtagsize tagsize def\n");
+  else
+    (void) this->sender( this->xptr, "  /xtagsize %s neg def\n", xticksstr);
+  if (isOFF(yticksstr))
+    (void) this->sender( this->xptr, "  /ytagsize tagsize def\n");
+  else
+    (void) this->sender( this->xptr, "  /ytagsize %s neg def\n", yticksstr);
+  (void) this->sender( this->xptr, "  /space    0.10 height mul def\n");
+  (void) this->sender( this->xptr, "  width 0.20 mul  0.15 height mul  translate  0.75 0.75 scale\n");
+  (void) this->sender( this->xptr, "  gsave\n");
+  (void) this->sender( this->xptr, "  %s setlinewidth\n", axislinewidthstr);
+  (void) this->sender( this->xptr, "  newpath\n");
+  if (isON(outsidestr)){
+    (void) this->sender( this->xptr, "  /toptagsize xtagsize neg def\n");
+    (void) this->sender( this->xptr, "  /bottomtagsize xtagsize def\n");
+    (void) this->sender( this->xptr, "  /lefttagsize ytagsize def\n");
+    (void) this->sender( this->xptr, "  /righttagsize ytagsize neg def\n");}
+  else{
+    (void) this->sender( this->xptr, "  /toptagsize xtagsize def\n");
+    (void) this->sender( this->xptr, "  /bottomtagsize xtagsize neg def\n");
+    (void) this->sender( this->xptr, "  /lefttagsize ytagsize neg def\n");
+    (void) this->sender( this->xptr, "  /righttagsize ytagsize def\n");}
+  if (isON(axisbottomstr)){
+    (void) this->sender( this->xptr, "  0     bottomtagsize  moveto  0     0  lineto stroke\n");
+    (void) this->sender( this->xptr, "  width bottomtagsize  moveto  width 0  lineto stroke\n");}
+  if (isON(axistopstr)){
+    (void) this->sender( this->xptr, "  0     height moveto 0   toptagsize rmoveto  0      height lineto stroke\n");
+    (void) this->sender( this->xptr, "  width height moveto 0   toptagsize rmoveto  width  height lineto stroke\n");}
+  if (isON(axisleftstr)){
+    (void) this->sender( this->xptr, "  0     0      moveto lefttagsize  0 rmoveto  0      0      lineto stroke\n");
+    (void) this->sender( this->xptr, "  0     height moveto lefttagsize  0 rmoveto  0      height lineto stroke\n");}
+  if (isON(axisrightstr)){
+    (void) this->sender( this->xptr, "  width 0      moveto righttagsize 0 rmoveto  width  0      lineto stroke\n");
+    (void) this->sender( this->xptr, "  width height moveto righttagsize 0 rmoveto  width  height lineto stroke\n");}
+  if (isON(axisbottomstr))
+    (void) this->sender( this->xptr, "  xmin xmax %s %s {width  mul      0 moveto bottomtagsize mul 0 exch rlineto stroke} ticks\n", xminorticksstr, xmajorticksstr);
+  if (isON(axistopstr))
+    (void) this->sender( this->xptr, "  xmin xmax %s %s {width  mul height moveto toptagsize mul 0 exch rlineto stroke} ticks\n", xminorticksstr, xmajorticksstr);
+  if (isON(axisleftstr))
+    (void) this->sender( this->xptr, "  ymin ymax %s %s {height mul     0 exch moveto lefttagsize  mul 0      rlineto stroke} ticks\n", yminorticksstr, ymajorticksstr);
+  if (isON(axisrightstr))
+    (void) this->sender( this->xptr, "  ymin ymax %s %s {height mul width exch moveto righttagsize mul 0      rlineto stroke} ticks\n", yminorticksstr, ymajorticksstr);
+  (void) this->sender( this->xptr, "  grestore\n");
+  (void) this->sender( this->xptr, "  newpath 0 0 moveto width 0 lineto width height lineto 0 height lineto closepath stroke clip\n");
+  (void) this->sender( this->xptr, "end } def\n");
+  (void) this->sender( this->xptr, "\ngsave\n\n" ) ;
+
+  /* rotate for landscape mode */ 
+  if( this->width > this->height ) {
+    (void) this->sender( this->xptr, "%% shift orgin and rotate for landscape mode\n" ) ;
+    (void) this->sender( this->xptr, "newpath clippath pathbbox pop exch translate pop 90 rotate %% notstand\n" ) ; }    
+  (void) this->sender( this->xptr, "%% center image on page\n" ) ;
+  (void) this->sender( this->xptr, "newpath clippath pathbbox exch %d sub 2 div exch %d sub 2 div translate pop pop %%notstand\n", this->width, this->height ) ;
+  
+  /* set clippath - used by axis routine */
+  (void) this->sender( this->xptr, "newpath 0 0 moveto %d 0 rlineto 0 %d rlineto %d neg 0 rlineto closepath clip\n", this->width, this->height, this->width ) ;
+/*  (void) this->sender( this->xptr, "%f setlinewidth\n/l { lineto } def\n", this->pixels / PIXELS_PER_POINT ) ;*/
+  (void) this->sender( this->xptr, "%s setlinewidth\n/l { lineto } def\n", figurelinewidthstr) ;
+
+  (void) this->sender( this->xptr, "1 setlinecap\n/pt {moveto 0 0 rlineto stroke} def\n" ) ;
+  (void) this->sender( this->xptr, "106 45 { dup mul exch\n dup mul add 1.0\n exch sub } setscreen\n" ) ;
+  
+  this->page = 1 ;
+  (void) this->sender( this->xptr, "%%%%EndProlog\n%%%%Page %d %d\ngsave\n", this->page, this->page ) ;
+  this->showpage = False ;
+  return ( ( WindowObject ) this ) ;
+}
+
+
+
+/*---------------------------------------------------------------*/
+
+
+
+WindowObject newFILEWindow( fp, default_x, default_y, default_width, default_height, pixels, pshidden)
+     FILE *fp ;
+     int default_x, default_y, default_width, default_height, pixels ;
+     int pshidden;
+{
+  extern int fflush() ;
+  
+  return ( newPostScriptWindow( fp, default_x, default_y, default_width, default_height, pixels, fprintf, (int (*)())0, (int (*)())0, (int (*)())0, (int (*)())0, (int (*)())0, fflush, pshidden )) ;
+}
+
+
+
+WindowObject newPSWindow( name, default_x, default_y, default_width, default_height, pixels, pshidden )
+     char *name ;
+     int default_x, default_y, default_width, default_height, pixels ;
+     int pshidden ;
+{
+  extern int fclose() ;
+  FILE *fp = stdout ;
+  
+  if( name != ( char * ) 0 && name[0] != '\000' )
+    if( ( fp = fopen( name, "w" ) ) == ( FILE * ) 0 ) {
+      (void) fprintf( stderr, "Could not open file \"%s\" for output\n", name ) ;
+      exit( 1 ) ;}
+  
+  return ( newPostScriptWindow( fp, default_x, default_y, default_width, default_height, pixels, fprintf, fclose, (int (*)())0, (int (*)())0, (int (*)())0, (int (*)())0, (int (*)()) 0  , pshidden )  ) ;
+}
+
+
+
+static short ps__x( this )
+     psWindowObject this ;
+{
+  return( this->x ) ;
+}
+
+
+static short ps__y( this )
+     psWindowObject this ;
+{
+  return( this->y ) ;
+}
+
+
+static short ps__width( this )
+     psWindowObject this ;
+{
+  return( this->width ) ;
+}
+
+
+static short ps__height( this )
+     psWindowObject this ;
+{
+  return( this->height ) ;
+}
+
+
+static void ps__draw( this, xs, ys, points )
+     psWindowObject this ;
+     short xs[], ys[] ;
+     int points ;
+{
+  int path, point ;
+  
+  (void) this->sender( this->xptr, "newpath\n" ) ;
+  if( points > 0 )
+    for( point=1 ; point < points ; point+=path ) {
+      (void) this->sender( this->xptr, "%d %d moveto\n", xs[point-1], ys[point-1] ) ;
+      for( path=0 ; point+path < points && path < MAX_PATH ; path++ )
+	(void) this->sender( this->xptr, "%d %d l\n", xs[point+path], ys[point+path] ) ;
+      if( this->hidden && xs[point+path] == xs[point-1] &&
+	 ys[point+path] == ys[point-1] )  /*Roy 27-11-92 */
+	(void) this->sender( this->xptr, "gsave 1 setgray fill grestore\n" ) ;
+      (void) this->sender( this->xptr, "stroke\n" ) ;}
+  else {
+    (void) this->sender( this->xptr, "gsave currentlinewidth 10. mul setlinewidth\n" ) ;
+    for( point=1 ; point < abs(points) ; point++ )
+      (void) this->sender( this->xptr, "%d %d pt\n", xs[point], ys[point] ) ;
+    (void) this->sender( this->xptr, "grestore\n" ) ;}
+  
+  this->drawn = True ;
+  return ;
+}
+
+
+
+static void ps__clear( this )
+psWindowObject this ;
+{
+  if( this->drawn ) {
+    ++this->page ;
+    (void) this->sender( this->xptr, "grestore\n") ;
+    (void) this->sender( this->xptr, "%s setlinewidth\n", axislinewidthstr) ;
+    if (isON(boxstr))
+      (void) this->sender( this->xptr, "(%g)  (%g) (%g)  (%g) AxesBox\n", temp_xmin, temp_xmax, temp_ymin, temp_ymax) ;
+    (void) this->sender( this->xptr, "showpage\ngrestore\n%%%%Page: %d %d\ngsave\n", this->page, this->page ) ; }
+  (void) this->sender( this->xptr, "gsave clippath 1 setgray fill grestore\n" ) ;
+  this->showpage = True ;
+  return ;
+}
+
+
+
+static void ps__close( this )
+     psWindowObject this ;
+{
+  (void) this->sender( this->xptr, "grestore\n") ;
+  (void) this->sender( this->xptr, "%s setlinewidth\n", axislinewidthstr) ;
+  if (isON(boxstr))
+    (void) this->sender( this->xptr, "(%g)  (%g) (%g)  (%g) AxesBox\n", temp_xmin, temp_xmax, temp_ymin, temp_ymax) ;
+  if( this->showpage )  
+    (void) this->sender( this->xptr, "showpage %% notstand\n" ) ;
+  else
+    this->page = 0 ;
+  (void) this->sender( this->xptr, "grestore\n%%%%Trailer\ngrestore\n%%%%Pages: %d\n", this->page ) ;
+  if( this->closer != 0 )
+    this->closer( this ) ;
+  free( (char *) this ) ;
+  return ;
+}
+
+
+
+static int ps__store( this )
+     psWindowObject this ;
+{
+  if( this->storer != 0 )
+    return ( this->storer( this->xptr ) ) ;
+  else
+    (void) fprintf( stderr, "Invalid call to restore postscript image from memory!!" ) ;
+  return 0 ;
+}
+
+
+
+static void ps__recall( this, which )
+     psWindowObject this ;
+int which ;
+{
+  if( this->recaller != 0 )
+    this->recaller( this->xptr, which ) ;
+  else
+    (void) fprintf( stderr, "Invalid call to store postscript image in memory!!" ) ;
+  return ;
+}
+
+
+
+static char *cmap( npixels )
+     int *npixels ;
+{
+#ifdef NeXT
+  static char ps_grey_scale[] = "04bf" ;
+#else
+  static char ps_grey_scale[] = "0123456789abcdef" ;
+#endif
+  
+  *npixels = sizeof ( ps_grey_scale ) - 1 ;
+  return ( ps_grey_scale ) ;
+}
+
+
+
+static void ps__fill( this, col, input, black, white, match, length, row_flag )
+     psWindowObject this ;
+     int col ;
+     short *input;
+     int black, white ;
+     int *match, length ;
+     int row_flag ;
+{
+  int chans, chan, y, blacky ;
+  
+  if( this->lookup == 0 ) {
+    this->lookup = makeLookup( cmap, black, white, length ) ;
+    (void) this->sender( this->xptr, "/picstr %d string def\n", length ) ;}
+  if( col == 1 ) {
+    if( row_flag )
+      (void) this->sender( this->xptr, "%d %d 4\n[1 0 0 -1 0 %d]\n", this->width, this->height, this->height ) ;
+    else
+      (void) this->sender( this->xptr, "%d %d 4\n[0 1 -1 0 %d 0]\n", this->height, this->width, this->height ) ;
+        (void) this->sender( this->xptr, "{currentfile\npicstr readhexstring pop}\nimage\n" ) ;}
+  
+  (void) this->sender( this->xptr, "%s\n", Lookup( col, this->lookup, input, match, length ) ) ;
+  this->drawn = True ;
+  return ;
+}
+
+
+
+static void ps__fillRow( this, row, input, black, white, match, width )
+     psWindowObject this ;
+     int row ;
+     short *input ;
+     int black, white ;
+     int *match, width ;
+{
+  ps__fill( this, row, input, black, white, match, width, 1 ) ;
+  return ;
+}
+
+
+
+static void ps__fillCol( this, col, input, black, white, match, height )
+     psWindowObject this ;
+     int col ;
+     short *input ;
+     int black, white ;
+     int *match, height ;
+{
+  ps__fill( this, col, input, black, white, match, height, 0 ) ;
+  return ;
+}
+
+
+
+static void ps__function( this, ys, segment, skip, offset, yspan, start, points )
+     psWindowObject this ;
+     short *ys ;
+     int segment, skip ;
+     double offset, yspan ;
+     int start, points ;
+{
+  int stop = start + abs( segment ) ;
+  int point, path = MAX_PATH, count, miny ;
+  short *yptr = ys ;
+  
+  for( point = start ; point < stop-1 ; point += path-1 ) {
+    if( path > stop - point ) 
+      path = stop - point ;
+    /* too-wide windows: something to do with Width( this) / (points -1.): 
+     * next line.  No fix attempted. MAA, 22-1-1993. 
+    */		
+    this->sender( this->xptr, "newpath 0 0 moveto %d 0 rlineto 0 %d rlineto %d neg 0 rlineto closepath clip\n", this->width, this->height, this->width ) ;
+    this->sender( this->xptr, "matrix currentmatrix [0 %g %g 0 0 %g] concat newpath %d %d moveto\n",
+		 Height( this ) / yspan, Width( this ) / ( points - 1. ), offset, miny = yptr[0], point ) ;
+    this->sender( this->xptr, "%s setlinewidth\n", figurelinewidthstr) ;
+
+#if defined(NeXT)
+    this->sender( this->xptr, "[\n" ) ;
+    for( count=1 ; count < path ; count++ ) {
+      yptr += skip ;
+      (void) this->sender( this->xptr, "%d\n", yptr[0]-yptr[-skip] ) ;
+      if( miny > yptr[0] )
+	miny = yptr[0] ;}
+    this->sender( this->xptr, "] {1 rlineto} forall\n" ) ;
+
+#else
+    this->sender( this->xptr, "/r {1 rlineto} bind def\n" ) ;
+    for( count=1 ; count < path ; count++ ) {
+      yptr += skip ;
+      (void) this->sender( this->xptr, "%d r\n", yptr[0]-yptr[-skip] ) ;
+      if( miny > yptr[0] )
+	miny = yptr[0] ;}
+#endif
+
+    if( this->hidden ) /* roy 27-11-92 */
+      this->sender( this->xptr, "gsave %d 0 rlineto 0 -%d rlineto closepath 1 setgray fill grestore\n", miny-yptr[0], path-1 ) ;
+    (void) this->sender( this->xptr, "setmatrix stroke\n" ) ;}
+  return ;
+}
+
+
+
+static int ps__read( this, fp, which )
+     psWindowObject this ;
+     FILE *fp ;
+     int which ;
+{
+  if( this->reader != 0 )
+    this->reader( this->xptr, fp, which ) ;
+  else
+    (void) fprintf( stderr, "Invalid call to read postscript image from file!!" ) ;
+  return ;
+}
+
+
+
+static void ps__write( this, fp )
+     psWindowObject this ;
+     FILE *fp ;
+{
+  if( this->writer != 0 )
+    this->writer( this->xptr, fp ) ;
+  else
+    (void) fprintf( stderr, "Invalid call to write postscript image to file!!" ) ;
+  return ;
+}
+
+
+
+static char ps__pause( this )
+     psWindowObject this ;
+{
+  if( this->pauser != (int (*)()) 0 )
+    return this->pauser( this->xptr ) ;
+  return '\000' ;
+}
+
+
+static void ps__axes( this, title, xmin, xmax, xtitle, ymin, ymax, ytitle )
+     psWindowObject this ;
+     char *title ;
+     double xmin, xmax ;
+     char *xtitle ;
+     double ymin, ymax ;
+     char *ytitle ;
+{
+  if (strcmp(xstartstr, "")) xmin = atoi(xstartstr);
+  if (strcmp(xendstr, ""))   xmax = atoi(xendstr);
+  if (strcmp(ystartstr, "")) ymin = atoi(ystartstr);
+  if (strcmp(yendstr, ""))   ymax = atoi(yendstr);
+  if (!strcmp(xnewtitlestr, "")) xnewtitlestr=xtitle;
+  if (!strcmp(ynewtitlestr, "")) ynewtitlestr=ytitle;  
+
+  temp_xmin = (double) xmin;
+  temp_xmax = (double) xmax;
+  temp_ymin = (double) ymin;
+  temp_ymax = (double) ymax;
+
+  if ( isOFF (rotateaxesstr) )
+    (void) this->sender( this->xptr, "(%s)   (%g)  (%g)  (%s)    (%g)  (%g)  (%s) Axes\n", title, xmin, xmax, xnewtitlestr, ymin, ymax, ynewtitlestr ) ;
+  else
+    (void) this->sender( this->xptr, "(%s)   (%g)  (%g)  (%s)    (%g)  (%g)  (%s) Axes\n", title, ymin, ymax, ytitle, (xmax * -1), (xmin * -1), xtitle ) ;
+  this->drawn = True ;
+  return ;
+}
+
+
+
+static void ps__marker( this, label, p, points )
+     psWindowObject this ;
+     char *label ;
+     int p, points ;
+{
+  short pos = ( this->entries->width( this ) * p + points / 2 ) / points ;
+  
+  (void) this->sender( this->xptr, "newpath %d %d moveto %d %d rlineto stroke\n", pos, 0, 0, this->entries->height( this ) ) ;
+  
+  this->drawn = True ;
+  return ;
+}
+
+static int ps__special( this, code, data )
+     psWindowObject this ;
+     int code ;
+     char *data ;
+{
+  this->drawn = True ;
+  switch( code ) {
+  case 1 :
+    (void) this->sender( this->xptr, "%s\n", data ) ;
+    return 1 ;
+  }
+  return 0 ;
+}
+
+
+
+windowsClass *initPostScriptClass( class )
+     windowsClass *class ;
+{
+  class->super    = &psClass ;
+  class->entries.x        = ps__x ;
+  class->entries.y        = ps__y ;
+  class->entries.width    = ps__width ;
+  class->entries.height   = ps__height ;
+  class->entries.draw     = ps__draw ;
+  class->entries.clear    = ps__clear ;
+  class->entries.close    = ps__close ;
+  class->entries.store    = ps__store ;
+  class->entries.recall   = ps__recall ;
+  class->entries.fillRow  = ps__fillRow ;
+  class->entries.fillCol  = ps__fillCol ;
+  class->entries.function = ps__function ;
+  class->entries.read     = ps__read ;
+  class->entries.write    = ps__write ;
+  class->entries.pause    = ps__pause ;
+  class->entries.axes     = ps__axes ;
+  class->entries.marker   = ps__marker ;
+  class->entries.special  = ps__special ;
+  
+  if( psClass.super == (windowsClass *) 0 )
+    (void) initPostScriptClass( &psClass ) ;
+  return ( &psClass ) ;
+}
+
+
+
+/* The End */
+/*----------------------------------------------------------------------*/
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/glib/windows.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,182 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    windows.h
+    =========
+
+    A rather wave drawing oriented interface to window systems
+
+
+
+    Authors : John Holdsworth, Paul Manson.
+    Written : 22nd March, 1989.
+
+    Edited  :
+
+    04 April 1989 (Paul Manson) -- Altered the axes entry point to also pass
+                                   the WindowObject (it is needed so that the
+                                   axes have something to attach to)
+
+    06 July  1989 (Paul Manson) -- Altered the <name> argument of newDisplayWindow()
+                                   to refer to the name of the window to be created,
+                                   rather than the display to use. 
+
+    01 April 1990 (John Holdsworth) -- function operation changed to more general
+				   segment operation to draw part of a wave.
+				   The macro Function() preforms as before.
+
+*/
+
+/* allowed extry pointy for a generic window object */
+
+typedef struct _window_entries {
+    short (*x       )( /* WindowOjbect info                              */ ) ;
+    short (*y       )( /* WindowOjbect info                              */ ) ;
+    short (*width   )( /* WindowOjbect info                              */ ) ;
+    short (*height  )( /* WindowOjbect info                              */ ) ;
+    void  (*draw    )( /* WindowOjbect info, short *xs, *ys, int points  */ ) ;
+    void  (*clear   )( /* WindowOjbect info                              */ ) ;
+    void  (*close   )( /* WindowOjbect info                              */ ) ;
+    int   (*store   )( /* WindowOjbect info                              */ ) ;
+    void  (*recall  )( /* WindowOjbect info, int which                   */ ) ;
+    void  (*fillRow )( /* WindowOjbect info, int row, pixels[], width    */ ) ;
+    void  (*fillCol )( /* WindowOjbect info, int col, pixels[], height   */ ) ;
+    void  (*function)( /* WindowOjbect info, short *ys, int segment, skip ;
+				double offset, scale ; int start, points */ ) ;
+    int   (*read    )( /* WindowObject info, FILE *fptr, int which       */ ) ;
+    void  (*write   )( /* WindowObject info, FILE *fptr                  */ ) ;
+    char  (*pause   )( /* WindowObject info                              */ ) ;
+    void  (*axes    )( /* WindowObject info, char  *title ;
+			 double xmin, xmax ; char *xtitle ;
+			 double ymin, ymax ; char *ytitle                */ ) ;
+    void  (*marker  )( /* WindowObject info, char *text, int start, pts  */ ) ;
+    int   (*special )( /* WindowObject info, int code, char *data        */ ) ;
+    } windowEntries    /* windowMethods */ ;
+
+typedef struct _window_class {
+    struct _window_class *super ;
+    windowEntries entries ;
+    } windowsClass ;
+
+/* external interface to window object */
+
+typedef struct _window_object {
+    windowEntries *entries ;
+    char window[4] ; /* Window may be accessed as *( (Window) &window_object->window ) */
+    /* struct { user data goes here in sub-class 1st item of which is window } ; */
+    } *WindowObject ;
+
+
+/* best guess at image structure for portable drawing optimisation */
+
+typedef struct _window_image {
+   char *data ; int bytes_per_line, height, left_bit, right_bit, start_bit ;
+  } *WindowImage ;
+
+extern WindowImage window__current_image( /* WindowObject window */ ) ;
+
+/* #define prototypes to simulate operation as objects and check types */
+
+
+#define           Width(    _w                         ) \
+ ( _w )->entries->width(    _w                         )
+
+#define           Height(   _w                         ) \
+ ( _w )->entries->height(   _w                         )
+
+
+#define           Draw(     _w,            _xs ,            _ys ,         _points  ) \
+ ( _w )->entries->draw(     _w, (short *) (_xs), (short *) (_ys), (int)  (_points) )
+
+#define           Plot(     _w,            _xs ,            _ys ,         _points  ) \
+ ( _w )->entries->draw(     _w, (short *) (_xs), (short *) (_ys), (int) -(_points) )
+
+
+#define           Clear(    _w                         ) \
+ ( _w )->entries->clear(    _w                         )
+
+#define           Close(    _w                         ) \
+ ( _w )->entries->close(    _w                         )
+
+
+#define           Store(    _w                         ) \
+ ( _w )->entries->store(    _w                         )
+
+#define           Recall(   _w,         _which         ) \
+ ( _w )->entries->recall(   _w, (int) ( _which )       )
+
+
+#define           FillRow(  _w,        _row ,            _input ,        _black ,        _white ,          _match ,        _height  ) \
+ ( _w )->entries->fillRow(  _w, (int) (_row), (short *) (_input), (int) (_black), (int) (_white), (int *) (_match), (int) (_height) )
+
+#define           FillCol(  _w,        _col ,            _input ,        _black ,        _white ,          _match ,         _height ) \
+ ( _w )->entries->fillCol(  _w, (int) (_col), (short *) (_input), (int) (_black), (int) (_white), (int *) (_match), (int) (_height) )
+
+
+/* function provided for backward compatability */
+
+#define           Function( _w,             _ys  ,              _points    ,         _skip  ,            _offset  ,            _scale                         ) \
+ ( _w )->entries->function( _w, (short *) ( _ys ), abs( (int) ( _points ) ), (int) ( _skip ), (double) ( _offset ), (double) ( _scale ), (int)0, (int)_points )
+
+#define            Segment( _w,             _ys  ,         _segment  ,         _skip  ,            _offset  ,            _scale  ,         _start  ,         _points   ) \
+ ( _w )->entries->function( _w, (short *) ( _ys ), (int) ( _segment ), (int) ( _skip ), (double) ( _offset ), (double) ( _scale ), (int) ( _start ), (int) ( _points ) )
+
+
+#define           Read(     _w, _file,        _which   ) \
+ ( _w )->entries->read(     _w, _file, (int) (_which)  )
+
+#define           Write(    _w, _file                  ) \
+ ( _w )->entries->write(    _w, _file                  )
+
+
+#define           Pause(    _w                         ) \
+ ( _w )->entries->pause(    _w                         )
+
+#define           Axes(     _w,           _title ,           _xmin ,           _xmax ,           _xtitle ,           _ymin,            _ymax ,           _ytitle  ) \
+ ( _w )->entries->axes(     _w, (char *) (_title), (double) (_xmin), (double) (_xmax), (char *) (_xtitle), (double) (_ymin), (double) (_ymax), (char *) (_ytitle) )
+
+#define           Marker(   _w,           _label ,       _p,       _points ) \
+ ( _w )->entries->marker(   _w, (char *) (_label), (int) _p, (int) _points )
+
+#define           Special(   _w,           _code ,           _data  ) \
+ ( _w )->entries->special(   _w, (char *) (_code), (char *) (_data) )
+
+
+/* standard window object creation routines */
+
+#define NewDisplayWindow( _name, _default_x, _default_y, _default_width, _default_height, _pixels ) \
+	newDisplayWindow( _name, _default_x, _default_y, _default_width, _default_height, _pixels )
+
+#define    NewFILEWindow( _name, _default_x, _default_y, _default_width, _default_height, _pixels ) \
+	   newFILEWindow( _name, _default_x, _default_y, _default_width, _default_height, _pixels )
+
+#define      NewPSWindow( _name, _default_x, _default_y, _default_width, _default_height, _pixels ) \
+	     newPSWindow( _name, _default_x, _default_y, _default_width, _default_height, _pixels )
+
+#define    NewNullWindow( ) \
+	   newNullWindow( )
+
+extern WindowObject newDisplayWindow(), newPSWindow(), newPostScriptWindow(), newFILEWindow(), newNullWindow(), NullWindowObject ;
+
+extern windowsClass *initPostScriptClass(), *initDisplayPostScriptClass() ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/makefile	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,695 @@
+###########################################################################
+#
+# ROOT MAKEFILE FOR AIM         M. Allerhand,  (MRC-APU) 7/7/93
+#                               C. Giguere,             24/3/94
+#                               A. J. Datta,   (MRC-APU)31/8/95
+#				R. Patterson   (MRC-APU)09/4/97
+#
+###########################################################################
+###########################################################################
+#
+# INTRODUCTION AND TABLE OF CONTENTS
+#
+# This is the Root makefile for the AIM software package which
+# consists of the AIM program itself, signal processing tools,
+# documentation, demonstrations and a Matlab interface.  Part I
+# describes the file system, Part II the makefile itself and
+# Part III the make help option.
+#
+#
+# PART I: THE AIM FILE SYSTEM 
+#
+# The file system for AIM itself is organised into five directories,
+# $(DIRS): filter, glib, model, stitch, and wdf. The root makefile
+# calls a nested makefile in each of the five directories to build
+# libraries, $(LIBS).  These are then linked to form main programs,
+# $(MAIN).  The signal processing tools are divided into basetools (in
+# directory tools) and auxtools (in directories xaim and saitools).
+# There are two directories for documentation (man and docs), one for
+# demonstrations scripts (scripts) and one for digitised sounds
+# (waves).
+#      
+# I.A. Directories and Directory Links
+#      
+# I.B. AIM_FILES: For AIM Executables, Basetools and Auxtools.
+#      I.B.1. Makefiles  
+#      I.B.2. AIM Sources:            SRC_AIM 
+#      I.B.3. Basic Tools:            basetools
+#      I.B.4. Auxillary Tools:        auxtools
+#      I.B.5. Libraries:
+#      I.B.6. Executables:
+#      I.B.7. Links to Executables:      
+#
+# I.C. DOC_FILES: For Documentation, Man, Demonstrations and Matlab.
+#      I.C.1. Manual Entries:         man/man1
+#      I.C.2. Demonstration Scripts:  scripts
+#      I.C.3. Documentation	      docs
+#      I.C.4. Waves		      waves
+#      I.C.5. Matlab Interface	      matlab
+#      
+#      
+# PART II:   THE ROOT MAKEFILE ITSELF
+# 
+# II.A. Arguements and Flags
+# 
+# II.B. Targets
+#      II.B.1. General Targets
+#      II.B.2. Link and Build Libraries and Targets 
+#      II.B.3. Create Directories and Pull Sources 
+#      II.B.4. Create AIM Links (genXXX) 
+#      II.B.5. Make tar files
+#      II.B.6. Maintenance Targets
+# 
+# II.C. Machines
+# 
+# 
+# PART III:  MAKE HELP
+# 
+# III.A. ARGS
+# III.B. TARGETS
+# III.C. MACHINES
+# 
+
+###########################################################################
+###########################################################################
+# 
+# PART I: THE AIM FILE SYSTEM 
+#
+# The signal processing tools are divided into basetools (in
+# directory tools) and auxtools (in directories xaim and saitools).
+# There are two directories for documentation (man and docs), one for
+# demonstrations scripts (scripts) and one for digitised sounds
+# (waves).
+#      
+###########################################################################
+#
+# I.A. Directories and SCCS Links
+#
+
+DIRS      = model         glib            stitch            filter          \
+	    wdf           tools           xaim              bin             \
+	    waves         man             man/man1          scripts         \
+	    docs          saitools        matlab
+
+SCCSLINKS = model/SCCS      glib/SCCS       stitch/SCCS     filter/SCCS     \
+	    wdf/SCCS        tools/SCCS      xaim/SCCS                       \
+	    man/SCCS        scripts/SCCS    docs/SCCS       saitools/SCCS   \
+	    matlab/SCCS
+
+
+###########################################################################
+#
+# I.B. AIM_FILES: For AIM Executables, Basetools and Auxtools.
+#
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# I.B.1. Makefiles  
+#
+# The root makefile calls a nested makefile in each of the five AIM
+# directories to build libraries, $(LIBS).  These are then linked to
+# form main programs, $(MAIN). 
+
+MAKEFILES = model/makefile  glib/makefile  stitch/makefile  filter/makefile  \
+	    wdf/makefile    tools/makefile xaim/makefile    saitools/makefile
+
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# I.B.2. AIM Sources:  SRC_AIM 
+#
+# The file system for AIM itself is organised into five directories,
+# $(DIRS): filter, glib, model, stitch, and wdf. 
+
+SRC_AIM   = glib/null.c    glib/ps.c      glib/grey.c      glib/options.c    \
+	    glib/windows.h glib/axes.h    glib/grey.h      glib/options.h    \
+	    glib/X.c                                                         \
+	    model/model.c  model/bank.c   model/corti.c    model/image.c     \
+	    model/model.h  model/bank.h   model/corti.h    model/image.h     \
+	    model/units.c  model/defaults.c model/integrate.c model/spiral.c \
+	    model/units.h  model/defaults.h model/integrate.h model/spiral.h \
+	    model/calc.h   model/atan.c   model/interp.c   model/faster.c    \
+	    model/new.c    model/table.c  model/gen.c      model/review.c    \
+	    model/version.c                                                  \
+	    filter/formulae.c filter/phase.c filter/gamma_tone.c             \
+	    filter/formulae.h filter/phase.h filter/gamma_tone.h             \
+	    filter/scales.c   filter/all.c   filter/generic.c   filter/imb.c \
+	    filter/scales.h   filter/recurse.c filter/recurse.h              \
+            wdf/upsample.c    wdf/fir.c       wdf/ear.c      wdf/wdf_ear.c   \
+            wdf/upsample.h    wdf/fir.h       wdf/ear.h      wdf/wdf_ear.h   \
+            wdf/formulae_tl.c wdf/scales_tl.c wdf/bank_tl.c  wdf/wdf_tl.c    \
+            wdf/formulae_tl.h wdf/scales_tl.h wdf/bank_tl.h  wdf/wdf_tl.h    \
+            wdf/meddis.c      wdf/calc_tl.h   wdf/meddis.h                   \
+	    stitch/buffer.c   stitch/io.c     stitch/draw.c stitch/funcs.c   \
+	    stitch/buffer.h   stitch/io.h     stitch/draw.h stitch/funcs.h   \
+	    stitch/pullable.c stitch/stitch.c stitch/fill.c stitch/srcio.c   \
+	    stitch/pullable.h stitch/stitch.h stitch/fill.h stitch/srcio.h   \
+	    stitch/fillable.c stitch/source.c stitch/wrap.c stitch/stypes.c  \
+	    stitch/fillable.h stitch/source.h stitch/wrap.h stitch/stypes.h  \
+	    stitch/ops.c      stitch/ops.h
+
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# I.B.3. Basic Tools:    basetools
+#
+
+SRC_TOOLS = tools/options.h tools/units.h   tools/strmatch.h  tools/header.h  \
+	    tools/sigproc.h tools/x11coord.h                                  \
+	    tools/acf.c     tools/acgram.c  tools/header.c    tools/atob.c    \
+	    tools/audim.c   tools/btoa.c    tools/bufwave.c  tools/bufframe.c \
+	    tools/chi.c     tools/conv.c    tools/convert.c   tools/cosine.c  \
+	    tools/edframe.c                                                   \
+	    tools/edwave.c  tools/fbank.c   tools/fft.c       tools/filt1.c   \
+	    tools/freqs.c   tools/ftgram.c  tools/ftoa.c      tools/ftos.c    \
+	    tools/gate.c    tools/gauss.c   tools/hdr.c    tools/integframe.c \
+	    tools/loudness.c tools/merge.c  tools/naptosai.c  tools/noise.c   \
+	    tools/op.c  tools/options.c tools/pitch_strength.c tools/ptrain.c \
+	    tools/racf.c    tools/ramp.c    tools/saitonap.c  tools/scale.c   \
+	    tools/sigproc.c tools/smooth.c  tools/sp_weights.c tools/stats.c  \
+	    tools/step.c    tools/stof.c    tools/strmatch.c  tools/swab.c    \
+	    tools/tone.c    tools/units.c   tools/x11coord.c tools/x11fonts.c \
+	    tools/x11gram.c tools/x11play.c tools/x11plot.c
+
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# I.B.4. Auxillary Tools:        auxtools
+#
+
+SRC_XAIM  = xaim/synthirn.c       xaim/synthdramp.c   xaim/buttons.c          \
+	    xaim/cartoon.c        xaim/graphics.c     xaim/initialise.c       \
+	    xaim/stipple_a        xaim/switch_axes.c  xaim/switch_buttons.c   \
+	    xaim/switch_control.c xaim/xreview.bitmap xaim/xreview.c          \
+	    xaim/xreview.h      xaim/disclaimer.text  xaim/releasenotes.text
+
+SRC_SAITOOLS = saitools/changeheader.c  saitools/findintervals_nap.c         \
+	     saitools/findpeaks.c  saitools/header.c  saitools/inout.c       \
+	     saitools/napgraph.c saitools/napheader.c saitools/removepeaks.c \
+	     saitools/saicut.c   saitools/saigraph.c  saitools/saiinfo.c     \
+	     saitools/sairotate.c  saitools/saisummary.c  saitools/tip.h     \
+	     saitools/trigger.c saitools/findintervals_sai.c                 \
+	     saitools/matrix.c 
+
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# I.B.5. Libraries:
+#
+
+MLIB      = model/libmodel.a
+GLIB      = glib/libglib.a
+SLIB      = stitch/libstitch.a
+FLIB      = filter/libfilter.a
+WLIB      = wdf/libwdf.a
+OLIB      = glib/libopts.a
+LIBS      = $(MLIB) $(GLIB)  $(SLIB) $(FLIB) $(WLIB) $(OLIB)
+
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# I.B.6. Executables: 
+#
+
+MAIN      = model/gen         model/review
+XAIM      = bin/synthirn      bin/synthdramp      bin/xreview
+SAITOOLS  = bin/saisummary    bin/sairotate   bin/saiinfo     bin/saigraph   \
+	    bin/saicut        bin/napgraph
+
+WTOOLS    = bin/hdr       bin/atob      bin/btoa        bin/bufwave          \
+	    bin/bufframe                                                     \
+	    bin/chi       bin/convert   bin/edframe     bin/edwave           \
+	    bin/fbank     bin/filt1     bin/ftoa        bin/ftos             \
+	    bin/gate                                                         \
+	    bin/integframe    bin/loudness  bin/merge       bin/naptosai     \
+	    bin/noise     bin/op        bin/pitch_strength  bin/ptrain       \
+	    bin/ramp      bin/saitonap  bin/scale       bin/sp_weights       \
+	    bin/stats     bin/step      bin/stof        bin/swab             \
+	    bin/tone
+
+SPTOOLS   = bin/acf       bin/acgram    bin/audim       bin/conv             \
+	    bin/cosine    bin/fft       bin/ftgram      bin/gauss            \
+	    bin/racf      bin/smooth
+
+XTOOLS    = bin/x11fonts  bin/x11gram   bin/x11play     bin/x11plot
+
+TOOLS     = $(WTOOLS)  $(SPTOOLS)  $(XTOOLS)
+
+
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# I.B.7. Links to Executables:
+#
+
+LINK_GEN1 = bin/genwav    bin/genstp                                        \
+            bin/genbmm    bin/gennap    bin/gensgm                          \
+	    bin/genasa    bin/genepn    bin/gensep      bin/gensai          \
+	    bin/gencgm    bin/genspl    bin/gensas      bin/gen
+
+LINK_GEN2 = bin/gentst    bin/genfcr    bin/genfcp      bin/genfbm          \
+	    bin/genfbc    bin/genfbu    bin/genfbs      bin/genfbl          \
+	    bin/genfba    bin/genfbh    bin/genfbi      bin/genfbd          \
+	    bin/genfeu    bin/genfes    bin/genfel      bin/genfet          \
+	    bin/genfeh    bin/genfei    bin/genfed      bin/gensie          \
+	    bin/genfbr    bin/genfbt    bin/genfec      bin/genfea          \
+	    bin/gensse
+
+LINK_SCRIPTS = bin/manaim   bin/aimdemo_gtf_all  bin/aimdemo_gtf_2dat         \
+	     bin/aimdemo_gtf_spectra bin/aimdemo_gtf_sai bin/aimdemo_tlf_all  \
+	     bin/aimdemo_tlf_lowhigh bin/aimdemo_tlf_med bin/aimdemo_tlf_std  \
+	     bin/aimdemo_tlf_spectra bin/aimdemo_hat     bin/aimdemo_hat_br   \
+             bin/scale_wav  bin/equate_energies  bin/StrobeCriterionDisplay   \
+	     bin/aimStrobeCriterion  bin/dp_ms bin/dp_pc  bin/aimR8demo
+
+LINK_AIM1    = $(LINK_GEN1)   $(LINK_SCRIPTS)   bin/review
+LINK_AIM2    = $(LINK_GEN1)   $(LINK_GEN2)      bin/review
+
+
+#
+#######################################################################
+#
+# I.C. DOC_FILES: For Documentation, Man, Demonstrations and Matlab.
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# I.C.1. Manual Entries:         man/man1
+#
+
+MANWHATIS = man/whatis
+MANPAGES  = man/man1/manaim.1                                                 \
+	  man/man1/genbmm.1  man/man1/gennap.1  man/man1/gensai.1             \
+	  man/man1/genwav.1  man/man1/gensgm.1  man/man1/genepn.1             \
+	  man/man1/genasa.1  man/man1/xreview.1 man/man1/genspl.1             \
+	  man/man1/acf.1 man/man1/acgram.1 man/man1/atob.1 man/man1/gencgm.1  \
+	  man/man1/audim.1   man/man1/btoa.1    man/man1/bufwave.1            \
+	  man/man1/chi.1     man/man1/conv.1    man/man1/convert.1            \
+	  man/man1/edframe.1 man/man1/bufframe.1 man/man1/cosine.1            \
+	  man/man1/edwave.1  man/man1/fbank.1 man/man1/fft.1 man/man1/filt1.1 \
+	  man/man1/ftgram.1  man/man1/ftoa.1   man/man1/ftos.1  man/man1/op.1 \
+	  man/man1/gate.1    man/man1/gauss.1 man/man1/hdr.1 man/man1/racf.1  \
+	  man/man1/integframe.1 man/man1/loudness.1                           \
+	  man/man1/merge.1   man/man1/naptosai.1 man/man1/noise.1             \
+	  man/man1/options.1 man/man1/pitch_strength.1  man/man1/ptrain.1     \
+	  man/man1/ramp.1    man/man1/saitonap.1 man/man1/scale.1             \
+	  man/man1/smooth.1  man/man1/sp_weights.1  man/man1/stats.1          \
+	  man/man1/step.1    man/man1/stof.1   man/man1/swab.1                \
+	  man/man1/tone.1    man/man1/x11fonts.1                              \
+	  man/man1/x11gram.1 man/man1/x11play.1   man/man1/x11plot.1
+MAN       = $(MANPAGES) $(MANWHATIS)
+
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# I.C.2. Demonstration Scripts:  scripts
+
+SCRIPTS   = scripts/manaim                scripts/unpack                    \
+	    scripts/aimdemo_gtf_all       scripts/aimdemo_gtf_2dat          \
+	    scripts/aimdemo_gtf_spectra   scripts/aimdemo_gtf_sai           \
+	    scripts/aimdemo_tlf_all       scripts/aimdemo_tlf_std           \
+	    scripts/aimdemo_tlf_lowhigh   scripts/aimdemo_tlf_med           \
+	    scripts/aimdemo_tlf_spectra   scripts/aimdemo_hat               \
+	    scripts/aimdemo_hat_br        scripts/StrobeCriterionDisplay    \
+	    scripts/scale_wav             scripts/equate_energies           \
+	    scripts/aimStrobeCriterion    scripts/make-demo-waves           \
+	    scripts/dp_ms  scripts/dp_pc  scripts/aimR8demo
+
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# I.C.3. Documentation files:	      docs
+
+DOCS      = docs/ReadMe.First      docs/ReadMe   docs/aimBibliography        \
+	    docs/aimDocList        docs/aimDocumentation docs/aimFileFormats \
+	    docs/aimInstructions   docs/aimMailList      docs/aimPaths       \
+	    docs/aimSilentOptions  docs/ftp.doc          docs/PAG95.doc      \
+	    docs/aimStrobeCriterion docs/makefile  docs/aimDemonstrations    \
+	    docs/aimMeddisHewitt
+
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# I.C.4. Demonstration Waves      waves
+
+WAVES     = waves/leo         waves/cegc     waves/hat       bin/hat        \
+	    waves/leo_br      waves/cegc_br  waves/hat_br    bin/hat_br     \
+	    waves/dr_f8_t16_d waves/dr_f8_t4_d  waves/dr_f8_t1_d            \
+	    waves/dr_f8_t16_r waves/dr_f8_t4_r  waves/dr_f8_t1_r            \
+	    waves/irns_16_1_1 waves/irns_16_1_4 waves/irns_16_1_16
+
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# I.C.5. Matlab Interface	      matlab
+
+MATLAB    = matlab/mktstr.m matlab/dB.m matlab/showSummarySAI.m matlab/amd_sumsai.m                  \
+	    matlab/amd_sai.m matlab/amd_bmm_nap.m matlab/amd_waves.m matlab/envelope.m               \
+	    matlab/squaretone.m matlab/damp_env.m matlab/damp_sin.m matlab/taper.m matlab/showBMM.m  \
+	    matlab/ssave.m matlab/sload.m matlab/showNAP.m matlab/showSAI.m matlab/repeat_cycle.m    \
+	    matlab/redrawAIM.m matlab/set_input_wave_GUI.m matlab/setFrameChooser.m                  \
+	    matlab/searchAimHeaderInfo.m matlab/save_genrc.m matlab/save_as_genrc.m matlab/sappend.m \
+	    matlab/revert_genrc.m matlab/readAIMHeader.m matlab/showAverageSAI.m matlab/puretone.m   \
+	    matlab/hilitChan.m matlab/getAimHeaderInfo.m matlab/outputChanData.m matlab/erb.m        \
+	    matlab/getAimResInfo.m matlab/openOptionGUI.m matlab/get_erb_param.m matlab/illuminate.m \
+	    matlab/popupShowFig.m matlab/openOptionGUI_page.m matlab/fchan_info.m                    \
+	    matlab/exec_save_genrc.m matlab/XTickShowSAINAP.m matlab/add_sound.m                     \
+	    matlab/FofErbScale.m matlab/ErbScale.m 
+
+#
+# all files for archiving
+
+FILES_IN_SCCS     = $(MAKEFILES)  $(SRC_AIM)  $(SRC_TOOLS)  $(SRC_XAIM) $(SRC_SAITOOLS)
+FILES_NOT_IN_SCCS = makefile
+
+AIM_FILES         = $(FILES_IN_SCCS)  $(FILES_NOT_IN_SCCS)
+DOC_FILES         = $(DOCS) $(MAN) $(SCRIPTS) $(MATLAB) $(WAVES)
+
+ 
+
+###########################################################################
+###########################################################################
+#      
+# PART II:   THE ROOT MAKEFILE ITSELF
+# 
+#
+
+###########################################################################
+#
+# II.A. Arguments and Flags
+#
+# The form of c compiler is passed by the flag CC.
+# Locations of X11 libraries and includes on various machines are
+# passed via the CFLAGS and LDFLAGS.
+#
+
+CC        = cc
+CFLAGS    = -O  -DX11 -I/usr/openwin/include
+LDFLAGS   = -L/usr/openwin/lib  -lXmu -lX11 -lm
+
+TARFILE1   = aimR8.tar.Z
+TARFILE2   = aimR8docs.tar.Z
+
+# Defaults for APU system.
+MOUNT     = /net/sound1
+MASTER    = $(MOUNT)/aim/master
+RELEASE   = $(MASTER)/release
+MAIL_SCRIPT = scripts/unpack
+
+
+#################################################################################
+#
+# II.B. Targets
+# 
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# II.B.1. General Targets.
+#
+
+MAKE = make CC=$(CC)             CFLAGS="$(CFLAGS)"   LDFLAGS="$(LDFLAGS)"    \
+	    LIBS="$(LIBS)"       MAIN="$(MAIN)" LINK_AIM1="$(LINK_AIM1)"      \
+	    TARGET="$(TARGET)"
+
+install   : 
+	  $(MAKE) $(MAIN) $(LINK_AIM1) basetools
+
+main      :  FORCE
+	@ $(MAKE) $(MAIN)
+
+basetools  : tools bin tools/makefile
+	@ $(MAKE) $(TOOLS)
+
+# release operates from sccs so it won't work elsewhere.
+
+release   : install $(WAVES) $(MAN) $(SCRIPTS) $(LINK_SCRIPTS) $(DOCS) $(MATLAB)
+
+auxtools  : saitools bin saitools/makefile xaim xaim/makefile waves
+	@ $(MAKE) $(SAITOOLS) $(XAIM) NWAVES
+
+sources   : $(DIRS) $(MAKEFILES) $(SRC_AIM) $(SRC_TOOLS) $(WAVES) $(MAN) $(SCRIPTS) $(DOCS) $(MATLAB)
+
+demo      : $(WAVES)
+
+links     : $(LINK_AIM1)
+alllinks  : $(LINK_AIM2)
+
+FORCE:
+
+
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# II.B.2. Link and Build Libraries and Targets 
+#
+# 	Link libraries into main programs.
+
+INCLUDES  = -Istitch  -Iglib  -Ifilter  -Imodel -Iwdf
+
+$(MAIN)   :  $(LIBS)  $$@.c
+	$(CC) $(CFLAGS) $(INCLUDES) -o $@  $@.c $(LIBS) $(LDFLAGS)
+
+
+#
+# Build libraries.
+
+$(LIBS) : $(DIRS) $(MAKEFILES) $(SRC_AIM) FORCE
+	@ cd $(@D) ; $(MAKE) $(@F)
+
+#
+# Build basetools.
+
+W_UTILS  = tools/strmatch.o tools/options.o tools/units.o tools/header.o
+SP_UTILS = tools/sigproc.o
+X_UTILS  = tools/x11coord.o
+
+$(WTOOLS) : $(SRC_TOOLS) tools/$$(@F).c
+	@ cd tools ; $(MAKE) $(@F)
+	$(CC) $(CFLAGS) -o $@ $(W_UTILS) tools/$(@F).o  $(LDFLAGS)
+
+$(SPTOOLS) : $(SRC_TOOLS)
+	@ cd tools ; $(MAKE) $(@F)
+	$(CC) $(CFLAGS) -o $@ $(W_UTILS) $(SP_UTILS) tools/$(@F).o  $(LDFLAGS)
+
+$(XTOOLS) :
+	@ cd tools ; $(MAKE) $(@F)
+	$(CC) $(CFLAGS) -o $@ $(X_UTILS) tools/$(@F).o  $(LDFLAGS)
+
+
+#
+# Build auxillary tools.
+#
+# Build xaim.
+
+$(XAIM) : $(SRC_XAIM)
+	@ cd xaim ; make $(@F) ; mv $(@F) ../bin
+
+
+# Build saisummary.
+
+$(SAITOOLS) : $(SRC_SAITOOLS)
+	    @ cd saitools ; make $(@F) ; mv $(@F) ../bin
+
+
+# Build waves
+
+NWAVES : 
+	 @ cd scripts ; make-demo-waves ; mv irns* ../waves ; mv dr_f8_* ../waves
+
+
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# II.B.3. Create Directories and Pull Sources 
+#
+# Create directories
+
+$(DIRS)   :
+	@ mkdir $@
+
+# Pull files from sccs: makefiles, sources, docs, etc..
+
+$(MAKEFILES) $(SRC_AIM) $(SRC_TOOLS) $(SRC_XAIM) $(SRC_SAITOOLS) $(DOCS) $(MATLAB) $(MANWHATIS) :
+	@ echo "$@"
+	@ cd $(@D) ; sccs -p$(RELEASE)/$(@D) get -c$(DATE) $(@F); chmod u+rw $(@F)
+
+# Scripts are a special case to be chmod'd.
+
+$(SCRIPTS) :
+	@ echo "$@"
+	@ cd $(@D) ; sccs -p$(RELEASE)/scripts get -c$(DATE) $(@F) ; chmod 755 $(@F)
+
+# Man pages are a special case needing a name change (for location in man1)
+
+$(MANPAGES) :
+	@ cd $(@D) ; sccs -p$(RELEASE)/man get -p -c$(DATE) `echo $(@F) | sed -e 's/\.1/.amp/g'`  > $(@F)
+
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# II.B.4. Create AIM Links (genXXX) 
+#
+# Create symbolic links to model entry points (eg. genXXX).
+
+$(LINK_GEN1) $(LINK_GEN2) :
+	ln -s  ../model/gen  $@
+bin/review :
+	ln -s  ../model/review  $@
+
+$(LINK_SCRIPTS) :
+	ln -s  ../scripts/$(@F)  $@
+
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# II.B.5. Make tar files for AIM_FILES and/or DOC_FILES
+#
+
+tar :
+	@ make $(TARFILE1)
+$(TARFILE1) : $(AIM_FILES)
+	@ tar cvf - $(AIM_FILES) | compress > $(TARFILE1)
+
+doc :
+	@ make $(TARFILE2)
+$(TARFILE2) : $(DOC_FILES)
+	@ tar cvf - $(DOC_FILES) | compress > $(TARFILE2)
+
+#
+### - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# II.B.6. Maintenance Targets
+#
+
+# Remove object files, libraries, main programs, and links, leaving the source code.
+
+clean :
+	rm -f */*.o */*.a  $(MAIN)  $(TOOLS)  bin/gen*  bin/review
+
+
+# Create symbolic links in each sub-directory to SCCS directories in $(RELEASE).
+
+sccslinks   : $(DIRS) $(SCCSLINKS)
+$(SCCSLINKS):
+	@ cd $(@D) ; ln -s $(RELEASE)/$(@D) SCCS
+cleansccs:
+	rm -f $(SCCSLINKS)
+
+
+# Copy demonstration stimuli.
+
+$(WAVES) :
+	@ cp  $(RELEASE)/$@  $(@D)
+
+
+# Mail model to given address.
+
+mail : $(TARFILE1)
+	@ uuencode $(TARFILE1) $(TARFILE1)  | split -700 - AIM.
+	@ echo ; echo "mail  $(ADDRESS)"
+	@ cat $(MAIL_README) | mail -s "AIM software: ReadMe"  $(ADDRESS) ; echo "    $(MAIL_README)"
+	@ cat $(MAIL_SCRIPT) | mail -s "AIM software: UnPack"  $(ADDRESS) ; echo "    $(MAIL_SCRIPT)"
+	@ for i in AIM.* ; do     \
+	    echo "start----" > tmp ; cat $$i >> tmp ; echo "----end" >> tmp ;  \
+	    mail -s "AIM software: $$i"  $(ADDRESS) < tmp ;   echo "    $$i" ; \
+	  done
+	@ rm  tmp AIM.*
+
+#
+###########################################################################
+# 
+# II.C. Machines  
+#
+#  These targets are machine-specific defaults that set CFLAGS and
+#  LDFLAGS appropriately for various machines.  The default machine is
+#  sun (see CFLAGS and LDFLAGS at top of makefile).  The include
+#  directory (-I in CFLAGS) must contain X11/X.h and X11/Xlib.h.  The
+#  lib directory (-L in LDFLAGS) must contain libX11.a.
+#
+#  Eg:
+#      make sun     makes the default target `install' with flags for sun.
+#      make TARGET=install sgi   makes the target 'install' for an SGI machine.
+
+TARGET    = install
+
+sun :
+	@ make CC=cc   CFLAGS="-O  -DX11 -I/usr/openwin/include" LDFLAGS="-L/usr/openwin/lib  -lX11 $(STUB) -lm" RANLIB=ranlib  $(TARGET)
+
+sungcc :
+	@ make CC=gcc  CFLAGS="-O2 -fwritable-strings -DX11 -I/usr/openwin/include" LDFLAGS="-L/usr/openwin/lib  -lXmu -lX11 $(STUB) -lm" RANLIB=ranlib   $(TARGET)
+
+sgi :
+	@ make CC=cc   CFLAGS="-O  -DX11 -I/usr/include"         LDFLAGS="-L/usr/lib          -lX11 $(STUB) -lm" RANLIB=echo    $(TARGET)
+
+dec vax :
+	@ make CC=cc   CFLAGS="-O  -DX11 -I/usr/include"         LDFLAGS="-L/usr/lib          -lX11 $(STUB) -lm" RANLIB=ranlib  $(TARGET)
+
+hp :
+	@ make CC=cc   CFLAGS="-O  -DX11 -I/usr/include/X11R4"   LDFLAGS="-L/usr/lib/X11R4    -lX11 $(STUB) -lm"  RANLIB=ranlib  $(TARGET)
+
+linux :
+	@ make CC=gcc  CFLAGS="-O  -fwritable-strings -ansi -DLINUX -DX11 -I/usr/include"   LDFLAGS="-L/usr/lib   -lXmu -lX11 $(STUB) -lm" RANLIB=ranlib  $(TARGET)
+
+
+apucc  :
+	@ make CC=cc   CFLAGS="-O  -DX11 -I/usr/local2/include"  LDFLAGS="-L/usr/local2/lib   -lX11 $(STUB) -lm"  RANLIB=ranlib  $(TARGET)
+
+apugcc :
+	@ make CC=gcc  CFLAGS="-O2 -fwritable-strings -DX11 -I/usr/local2/include"  LDFLAGS="-L/usr/local2/lib   -lXmu -lX11 $(STUB) -lm"      RANLIB=ranlib  $(TARGET)
+
+make :
+	@ apugdb CC=gcc  CFLAGS="-fwritable-strings -g  -DX11 -I/usr/local2/include"  LDFLAGS="-L/usr/local2/lib   -lXmu -lX11 $(STUB) -lm -lg"  RANLIB=ranlib  $(TARGET)
+
+
+#  AIM without X11 displays.
+#  A noplot version for compilation on a machine without X11 windows.
+#  The defaults: CC=cc  CFLAGS=-O  LDFLAGS=-lm exclude Xlibs and -DX11,
+#  i.e. X11 is undefined so that ifdef's in gen.c omit the X11 code.
+#  The LIBS list excludes libglib.a, the MAIN list excludes model/review,
+#  the LINKS list excludes the link /bin/review, and the TOOLS list excludes
+#  the XTOOLS.
+#  Eg:
+#      make noplot                      gets default target `install'.
+#      make TARGET=basetools noplot     gets target `basetools'.
+
+noplot :
+	@ make CC=cc CFLAGS=-O LDFLAGS=-lm  LIBS="$(MLIB) $(SLIB) $(FLIB) $(WLIB) $(OLIB)"  MAIN=model/gen LINK_AIM1="$(LINK_GEN1)"  TOOLS="$(WTOOLS) $(SPTOOLS)"  $(TARGET)
+
+
+###########################################################################
+########################################################################### 
+# 
+# PART III:  MAKE HELP
+# 
+# Help target
+
+help : FORCE
+	@ echo "Root makefile for AIM."
+	@ echo "Usage:  1. make  [Args]  [Targets] "
+	@ echo "        2. make  [Args]  [TARGET=Targets]  [Machine] "
+	@ echo "        3. make  [Args]  [TARGET=Targets]  noplot"
+	@ echo
+	@ echo "ARGS:      Current value:"
+	@ echo "CC         $(CC)                                  C compiler."
+	@ echo "CFLAGS     $(CFLAGS)    Compiler flags."
+	@ echo "LDFLAGS    $(LDFLAGS) Loader flags."
+	@ echo "STUB       $(STUB)                                    Additional libs to resolve names."
+	@ echo "MOUNT      $(MOUNT)                         Mount for AIM sccs."
+	@ echo "RELEASE    $(RELEASE)      Source dir for AIM sources in sccs."
+	@ echo "DATE       $(DATE)                                    Sccs get by date [year/month/day]."
+	@ echo "TARFILE    $(TARFILE1) $(TARFILE2)         Filenames for tar files."
+	@ echo "ADDRESS    $(ADDRESS)                                    Address(es) for email."
+	@ echo "TARGET     $(TARGET)
+	@ echo
+	@ echo "TARGETS:   GENERAL (Default target is \`install'). "
+	@ echo "main       Make main AIM executable, gen."
+	@ echo "install    Make 'main' plus common links and basetools."
+	@ echo "basetools  Make the basetool executables and put them in bin."
+	@ echo "auxtools   Make the auxillary tools executables and put them in bin."
+	@ echo "links      Install the most useful model links."
+	@ echo "alllinks   Install all model links."
+	@ echo "tar        Create compressed tar file of AIM file system."
+	@ echo "doc        Create compressed tar file of AIM documentation. "
+	@ echo "noplot     Install in X11-free environment: no graphics."
+	@ echo
+	@ echo "TARGETS:   APU     (For system maintenance at APU)"
+	@ echo "release    Make 'install' with docs and demos from scratch (sccs)."
+	@ echo "sources    Get sources from local sccs."
+	@ echo "clean      Remove all objects, libraries, main programs, and links."
+	@ echo "sccslinks  Create SCCS symbolic links to local sccs directories."
+	@ echo "cleansccs  Remove SCCS symbolic links."
+	@ echo "demo       Install demo stimuli files."
+#	@ echo "mail       Email AIM file system to given address(es)."
+	@ echo
+	@ echo "MACHINE    (Default machine is \`sun'). "
+	@ echo "sun	   SparcStation with cc and X11 in -I/usr/openwin/include"
+	@ echo "sungcc     SparcStation with optimised gcc and X11 in -I/usr/openwin/include"
+	@ echo "sgi        sgi Indy with cc and X11 in -I/usr/include/"
+	@ echo "hp	   hp with cc and X11 in -I/usr/include/X11R4"
+	@ echo "dec vax    Dec/Vax Station with cc and X11 in -I/usr/include/"
+	@ echo "apucc	   SparcStation at APU with cc and X11 in -I/usr/local2/include/"
+	@ echo "apugcc 	   SparcStation at APU with optimised gcc and X11 in -I/usr/local2/include/"
+	@ echo "linux	   PC with gcc and X11 in -I/usr/include/"
+	@ echo
+###########################################################################
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/acf.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,85 @@
+.TH ACF 1 "15 September 1993"
+
+.SH NAME
+acf \- autocorrelation function of contiguous frames.
+.nf
+i/p and o/p data in binary shorts, (o/p data n/2 points per frame).
+.fi
+
+.SH SYNTAX 
+acf  [arguments]  [file]
+
+
+.SH DESCRIPTION
+The autocorrelation function (acf) is computed using the fft.
+The output framewidth is the given maximum acf lag, which must not be
+greater than the input framewidth.
+Each input frame is padded with zeroes to the next power of 2 larger than
+either the input framewidth, or twice the required max acf lag, (whichever
+is  the larger).
+If necessary, extra padding can be enforced using the (silent) padding option
+to add extra zeroes, padding to a larger power of 2.
+The amount of extra padding is "exponential", expanding the basic size to:
+   
+      ( framesize + padding ) * 2**n
+
+where the padding option is n.
+
+
+(n=0 by default, so that no extra padding is added. When n=1 then padding is
+added to double the size, and when n=2 the size is quadrupled, etc.).
+The input and output frame sizes in sample points may be printed using the
+"size" option.
+
+
+.SH EXAMPLES
+.nf
+1. To print the input and output frame sizes in sample points, 
+   eg for a subsequent plotting program, use the size option:
+
+acf ... size=on
+
+
+2. An acf of a waveform sampled at 10kHz, computed to a max lag 
+   of 12.8ms within a frame of 12.8ms, plotting the 2nd frame in 
+   a sequence of frames with frameshift 12.8ms.
+
+acf samp=10kHz width=12.8ms frstep=12.8ms frame=2 lag=12.8ms file 
+    | x11plot
+
+3. An animated plot of successive acf's of a waveform sampled at 
+   10kHz, each computed within a frame of 12.8ms, and shifted by 
+   2 sample points.
+
+acf samp=10kHz width=12.8ms frstep=2p lag=12.8ms file 
+    | x11play -n128
+
+.fi
+
+.SH COPYRIGHT 
+.LP 
+Copyright (c) Applied Psychology Unit, Medical
+Research Council, 1995 .LP Permission to use, copy, modify, and
+distribute this software without fee is hereby granted for research
+purposes, provided that this copyright notice appears in all copies
+and in all supporting documentation, and that the software is not
+redistributed for any fee (except for a nominal shipping
+charge). Anyone wanting to incorporate all or part of this software in
+a commercial product must obtain a license from the Medical Research
+Council.  .LP The MRC makes no representations about the suitability
+of this software for any purpose.  It is provided "as is" without
+express or implied warranty.  
+.LP 
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/acgram.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,104 @@
+.TH ACGRAM 1 "1 September 1993"
+
+.SH NAME
+acgram \- Autocorrelogram auditory image.
+
+.SH SYNTAX 
+acgram  [arguments]  [file]
+
+
+.SH DESCRIPTION
+Short-time autocorrelation function applied to each row of input frames.
+Output frames consist of row-wise autocorrelation coefficients.
+The autocorrelation function (acf) is computed using the fft. Strictly
+speaking this generates an autocovariance function, but an optional
+normalization (dividing each coefficient by the zeroth coefficient) produces
+the autocorrelation function.
+
+The program expects to read an AIM header, and interprets input as one large
+frame in column-wise format (eg output from genbmm, gennap, etc.), to be
+divided into input frames, each to be processed as an autocorrelogram.
+A new header is constructed, and each autocorrelogram frame is output in
+row-wise format (eg as if output from gensai).
+
+The input is divided into frames according to the given options.
+The options 'start' and 'length' specify the input file.
+The special option value length=max specifies all the input file from
+the given start to its end.
+The options 'width' and 'frstep'  specify the input frames.
+The width option is the framewidth of each input frame and the frstep
+option is the frameshift between input frames in the input file.
+The special option value width=max specifies the input framewidth as equal
+to the given input file length, (and if this is also 'max', then the
+input framewidth is the remainder of the input file).
+
+Most options in the input header are copied to the output header.
+This enables options which are needed for the eventual display
+to pass straight through. Some options are set so that they can override
+the input header. For example, the display option is set on to enable
+display even when input has display=off. The animate option can be set on
+even when the input has animate=off.
+Some parts of the header are changed for the output format:
+(frames, frameshift, framewidth, frameheight, framebytes).
+
+Each row of each input frame is padded with zeroes to the next
+power of 2 larger than either the original input framewidth or twice the
+max acf lag (whichever is  the larger).
+If necessary, extra padding can be enforced using the (silent) padding option
+to add extra zeroes, padding to a larger power of 2.
+The amount of extra padding is 'exponential', expanding the basic size to:
+.nf
+      ( framewidth + padding ) * 2**n
+
+where the padding option is n.
+.fi
+
+(n=0 by default, so that no extra padding is added. When n=1 then padding is
+added to double the size, and when n=2 the size is quadrupled, etc.).
+
+.SH EXAMPLES
+
+1. Autocorrelogram of a NAP, animated and normalized, with max lag 16ms:
+
+gennap len=128ms output=stdout display=off file | acgram lag=16ms norm=on \
+anim=on > file.sai
+
+gensai useprev=on headr=5 top=1000 file             -(for landscape plot)
+
+genspl useprev=on headr=5 top=1000 pensize=2 file   -(for spiral plot)
+
+2. Autocorrelogram of an SAI:
+   (gensai removes file.sai, so you must use some other name, eg foo.sai).
+
+gensai len=64 pwidth=64 nwidth=0 output=stdout display=off file |  \
+saitonap frame=3 | acgram lag=32ms frame=1 > foo.sai
+
+gensai useprev=on top=1000 headr=5 mag=2 foo
+
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/atob.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,57 @@
+.TH ATOB 1 "2 September 1993"
+
+.SH NAME
+atob \-  ascii to binary conversion.
+
+.SH SYNTAX
+atob  [options]  [file]
+
+.SH DESCRIPTION
+Read ascii numbers (one per line) from the input stream until eof.
+Write each number on the stdout in the given data type.
+
+.SH OPTIONS
+
+1. type
+
+The output data type, which may be one of the list: char, short, int,
+float, double, ascii.
+
+Silent options for short, int and float are retained for compatibility with
+earlier versions. If used, these override the type option.
+
+.SH BUGS
+
+When converting binary doubles or floats to ascii, and then back to
+binary, there will be some difference between the binary files because
+the ascii output is printed with limited precision.
+
+.SH "SEE ALSO"
+options btoa ftos stof
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/audim.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,116 @@
+.TH AUDIM 1 "1 September 1993"
+
+.SH NAME
+audim  \- Auditory images.
+
+.SH SYNTAX 
+audim [options] [file]
+
+.SH DESCRIPTION
+
+This program provides
+methods of constructing time-varying auditory images from the output of the
+cochlear model which are alternatives to the gensai (stabilized auditory
+image) program. Correlograms (ie. row-wise autocorrelation) and row-wise
+Fourier transform are provided.
+
+The program reads an AIM
+header and the output from the genbmm (basilar membrane motion) or gennap
+(neural activity pattern) programs. This is divided into contiguous
+time frames and written on the stdout with an appropriate header as if output
+from the gensai program. This enables genbmm or gennap output to be divided into time
+frames and replayed as a time-varying cartoon by gensai using the "useprevious" option.
+
+Additional processing to each frame is optionally available to compute
+alternative forms of auditory image according to the "image" option.
+
+.SH OPTIONS
+
+The options "start" and "length" specify the size of the input.
+The options "width" and "frstep"  specify the frames which are output.
+The input is divided into frames according to the width option and the
+frstep option.
+
+Special option values are:
+
+.nf
+  length=max      Read all the input from the given start to its end.
+  width=max       Output framewidth is set equal to the given input
+		  length, and if this is also "max", then the
+		  framewidth is the remainder of the input.
+  frames=1-max    Select the 1st to the last frame inclusively.
+  frame=4         Select the 4th frame only.
+
+  image=off       Divide the input into frames for replay as a cartoon.
+  image=acgram    Compute correlogram of each frame.
+  image=ftgram    Compute power spectrum of each channel of each frame.
+  image=phgram    Compute phase spectrum of each channel of each frame.
+.fi
+
+Most options in the input header are copied to the output header.
+This enables options which are needed for the eventual display
+to pass straight through. Some options are set so that they can override
+the input header. For example, the display option is set on to enable
+display even when input has display=off. The animate option can be set on
+even when the input has animate=off.
+Parts of the header are changed for the new sai format:
+(frames, frameshift, framewidth, frameheight, framebytes).
+
+Certain display parameters have different default values for different
+applications. The gensai display parameters should be set to the appropriate
+values, in order to plot the cartoon on the same scale. For example:
+when the source application is gennap, set gensai top=1000,
+when the source application is genbmm, set gensai bottom=-100.
+
+
+.SH EXAMPLES
+
+.nf
+
+1. To convert gennap output to multiple animated frames:
+
+gennap len=16ms display=off output=stdout file | \
+    audim image=off width=8ms frstep=0.2ms anim=on > file.sai
+gensai useprev=on file             -(for landscape plot)
+genspl useprev=on pensize=2 file   -(for spiral plot)
+
+(Note: spirals look better in a square box, so you might use options:
+    dencf=1 width=500 height=500 )
+
+2. An animated normalized correlogram from gennap output:
+
+gennap len=64ms output=stdout display=off file | \
+    audim norm=on anim=on > file.sai
+gensai useprev=on top=1000 file             -(for landscape plot)
+genspl useprev=on top=1000 pensize=2 file   -(for spiral plot)
+
+.fi
+
+.SH "SEE ALSO"
+
+acgram ftgram edframe naptosai
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/btoa.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,59 @@
+.TH BTOA 1 "7 September 1993"
+
+.SH NAME
+btoa \-  binary to ascii conversion.
+
+.SH SYNTAX
+btoa  [options]  [file]
+
+.SH DESCRIPTION
+Read numbers of the given type from the input stream until eof.
+Print each number on the stdout (one number per line) to the given precision.
+
+.SH OPTIONS
+
+1. type
+
+The input data type, which may be one of the list: char, short, int, float,
+double, ascii.
+
+Silent options for short, int and float are retained for compatibility
+with earlier versions. If used, these override the type option.
+
+2. precision
+
+The number of decimal places for ascii output. Setting precision=0 gives
+(truncated) integer output.
+
+.SH BUGS
+
+When converting binary doubles or floats to ascii, and then back to binary,
+there will be some difference between the binary files because the ascii
+output is printed with limited precision.
+
+.SH "SEE ALSO"
+options atob ftos stof
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/bufframe.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,146 @@
+.TH BUFFRAME 1 "1 September 1993"
+
+.SH NAME
+bufframe \- a shifting AIM output frame buffer.
+
+.SH SYNTAX 
+bufframe [options] [file]
+
+.SH DESCRIPTION
+
+The program reads an AIM header and the output from the genbmm (basilar
+membrane motion) or gennap (neural activity pattern) programs. This is
+divided into contiguous time frames using the optional arguments and written
+on the stdout with an
+appropriate header as if output from the gensai program. This enables
+genbmm or gennap output to be divided into time frames and replayed as a
+time-varying cartoon by gensai using the "useprevious" option.
+
+Certain display parameters have different default values for different
+applications. The gensai display parameters should be set to the
+appropriate values, in order to plot the cartoon on the same scale. For
+example: when the source application is gennap, set gensai top=1000,
+when the source application is genbmm, set gensai bottom=-100.
+
+
+.SH OPTIONS
+
+1. width, frstep.
+
+The input is divided into frames according to the width option and the
+frstep option. The width option sets the width of the output frames.
+The frstep option sets the step or shift between successive output frames.
+With no units, the values of width and frstep are in samples.
+Both width and frstep may take time units (s or ms), in which case the values
+are converted to samples using the given `samplerate' option.
+
+2. frame.
+
+A range of sequential frames may be selected for output by:
+
+.nf
+	  frame=a[-b]
+.fi
+
+The upper limit `b' is optional, and when it is missing then the range
+is a single frame, otherwise `a' and `b' are inclusive range limits.
+The strings "min" and "max" are recognised as extreme limits constrained
+by the given width and frstep and the input size,
+otherwise the values of `a' and `b' are frame numbers: 0,1,2,...
+
+The frame selector may also take time units (s, or ms) to specify frames
+"closest" to the given time, being the frame number which is the
+greatest integer multiple of the framestep (frstep) which does not
+exceed the given time measured from the
+start of the input file.
+
+3. Transpose.
+
+The option flag:
+
+.nf
+  Transpose=on
+.fi
+
+causes a matrix transpose (swap rows and columns) of each output frame.
+When a frame has a height greater
+than it's width then setting "Transpose=on" may provide
+a preferable display orientation. For example, this enables a very narrow
+(eg. single column) time-slice to be plotted horizontally, so that a
+time-slice of filterbank output may be plotted as a spectrum on a horizontal
+frequency axis.
+
+4. Header.
+
+The option flag:
+
+.nf
+      Header=off
+.fi
+
+causes the header to be suppressed from the output.
+
+5. display, animate.
+
+Most options in the input header are copied to the output header.  This
+enables options which are needed for the eventual display to pass
+straight through. Some options are set so that they can override the
+input header. For example, the `display' option is set on to enable
+display even when input has "display=off". The `animate' option can be set
+on even when the input has "animate=off".
+
+
+.SH EXAMPLES
+
+1. To convert gennap output to multiple animated frames:
+
+.nf
+gennap len=16ms display=off output=stdout file1 |
+	bufframe width=8ms frstep=0.2ms anim=on > file2.sai
+gensai useprev=on top=1000 file2             -(for landscape plot)
+genspl useprev=on top=1000 pensize=2 file2   -(for spiral plot)
+.fi
+
+
+2. To view the basilar membrane from a cross section, animating the waves on it.
+
+.nf
+genbmm mincf=220 maxcf=660 len=8ms output=stdout display=off file1 |
+	bufframe width=1p frstep=1p Tran=on display=on anim=on > file2.sai
+gensai bott=-100 useprev=on mag=.2 file2
+
+    or:
+
+genbmm mincf=220 maxcf=660 len=32ms output=stdout display=off file1 |
+	bufframe width=1p frstep=1p Tran=on Header=off > file2
+x11play -n75 -a500 file2
+.fi
+
+
+.SH "SEE ALSO"
+options edframe
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/bufwave.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,98 @@
+.TH BUFWAVE 1 "1 September 1993"
+
+.SH NAME
+bufwave \-   a shifting waveform buffer.
+
+.SH SYNTAX 
+bufwave [options] [file]
+
+.SH DESCRIPTION
+A buffer (or window) is shifted along the input, and the
+contents of the buffer are written to the stdout on each shift.
+
+.SH OPTIONS
+
+1. width, frstep.
+
+Input is buffered in frames of size `width' samples, and the buffer is
+shifted along the input in steps of `frstep' samples.
+Both `width' and `frstep' may be given with time units (s or ms), in which
+case the they are converted to a number of samples using the given
+`samplerate' option.
+
+2. type.
+
+The `type' option sets the size of a binary sample in bytes.
+Standard type names are recognised (char, short, int, float, double).
+For example, type=1 is synonymous with type=char, both specifying a
+binary sample of 1 byte.
+
+The special case of type=ASCII sets a sample to be a line of ASCII text
+(delimited by a CR), of size up to a maximum number of characters set by
+the `length' option.
+
+3. frame.
+
+The `frame' option selects a sequence of contiguous frames for output by:
+
+.nf
+	      frame=a[-b]
+.fi
+
+where `a' and `b' are frame numbers: 1,2,3,...
+The upper limit `b' is optional, and when it is missing then the frame
+sequence is a single frame, otherwise `a' and `b' are inclusive limits.
+The strings "min" and "max" are recognised as extreme limits.
+
+4. start.
+
+The `start' option is an offset to the start of the first frame in samples.
+If given with time units, the start is converted to samples using the
+given `samplerate' option.
+
+5. reverse.
+
+The `reverse' option causes each buffer to be written out in reverse order
+of its samples.
+
+.SH EXAMPLES
+
+1. A half-frame overlapping rectangular window of size 10ms.
+
+.nf
+	bufwave width=10ms frstep=5ms file
+.fi
+
+2. Reverse the contents of each frame of a given sequence of 75-sample frames.
+
+.nf
+	bufwave rev=on width=75 frstep=75 file
+.fi
+
+.SH "SEE ALSO"
+options edwave
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/chi.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,54 @@
+.TH CHI 1 "1 September 1993"
+
+.SH NAME
+chi \-       repetitative chi-squared curve.
+
+.SH SYNTAX 
+chi [options]
+
+.SH DESCRIPTION
+Generate samples of a repeated chi-squared waveform at a given sample
+rate.  Samples are written on the stdout in binary shorts or floats
+according to the `datatype' option.
+
+.SH OPTIONS
+
+1. period, amplitude, duration.
+
+The `period' option sets the period of repetition of the waveform in
+samples.  The `duration' option sets the total duration of the output
+waveform in samples.  Both may be given with time units (s or ms) in
+which case the time is converted to samples using the given `samplerate'
+option.  The `amplitude' option sets the height of the waveform.
+
+2. asymmetry
+
+The asymmetry parameter ( >= 1 ) controls the assymmetry of the repeated curve.
+
+.SH "SEE ALSO"
+options ramp tone noise ptrain
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/conv.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,78 @@
+.TH CONV 1 "1 September 1993"
+
+.SH NAME
+conv \-  Convolution.
+
+.SH SYNTAX 
+conv [options]  signal_file  impulse_response_file
+
+.SH DESCRIPTION
+The response of a linear filter to an arbitiary input signal is the
+convolution of the signal with the filter's impulse response.
+The `impulse_response_file' contains the impulse response which characterises the
+filter, and the result of the convolution operation is the response of
+that filter to the signal contained in the `signal_file'.
+
+The `signal_file' must consist of binary 16-bit numbers (ie. shorts).
+The `impulse_response_file' must consist of binary floats.
+The output signal is the same length as the input signal and is written on
+the stdout in binary 16-bit numbers.
+
+If the `signal_file' consists of an impulse train, then the output should
+be a repeated impulse response, ie. should be a repeated version of the
+`response_file'.
+
+
+
+.SH OPTIONS
+
+1. length
+
+The amount of the signal file to convolve in time units (s or ms) or in
+samples (no units). Time units are converted to samples using the given
+`samplerate' option. The string "max" is recognised as the remainder of
+input.
+
+2. domain
+
+Select algorithm for convolution.  In the time domain ("domain=time") the
+discrete convolution formula is applied directly as a local averaging
+operation on the input signal with weights obtained by time-reversing and
+shifting the impulse response. The impulse response is assumed to be zero
+for all time outside the given file. In the frequency domain
+("domain=frequency") the FFT of the whole input signal is multiplied by a
+frequency response function (the FFT of the impulse response), and
+the result inverse FFT'd.
+
+3. scale
+
+A scale factor for scaling the output.
+
+
+.SH "SEE ALSO"
+options smooth fft acf
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/convert.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,61 @@
+.TH CONVERT 1 "15 September 1993"
+
+.SH NAME
+convert \- Convert units: frequency, time, and sample numbers.  
+
+.SH SYNTAX 
+convert [options] arguments
+
+
+.SH DESCRIPTION
+Convert time to samples and vice verca. Options of the general form:
+
+        -to<units>  |  to=<units>
+
+may be intersperced with arguments, which are treated as values to convert
+into the units given by the previous option on the command line.
+Time in seconds or milliseconds is converted to and from sample points using
+the given samplerate. Time (in seconds, miliseconds or samples) is converted
+to and from frequency by reciprocal.
+
+.SH EXAMPLES
+
+.nf
+1. Convert 100 samples to time in ms, and the 10ms to a number of 
+   samples, both at the default sample-rate of 20kHz. Then at a 
+   sample-rate of 10kHz print the number of samples in 32ms.
+
+
+convert to=ms 100p to=p 10ms samplerate=10kHz to=p 32ms
+.fi
+
+.nf
+2. Convert 0.1 seconds to sample points.
+
+convert -topoints 0.1sec
+.fi
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/cosine.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,71 @@
+.TH COSINE 1 "1 September 1993"
+
+.SH NAME
+cosine \- generate a cosine window.
+
+.SH SYNTAX 
+cosine [options]
+
+.SH DESCRIPTION
+Generate a cosine window on the stdout in binary shorts or floats for
+a given size.
+
+.SH OPTIONS
+
+1. size
+
+The size of the window can be given with time units (ms or s) or samples (no
+units).  Time units are converted to samples using the given
+`samplerate' option.
+
+2. Hamming
+
+The default ("Hamming=off") is a Hann or raised cosine window:
+
+.nf
+	w[n] = 0.5 [ 1 - cos( TWOPI . n/(N-1) ) ]
+.fi
+
+The "Hamming=on" window is:
+
+.nf
+	w[n] = 0.54 - 0.46 cos( TWOPI . n/(N-1) )
+.fi
+
+Both windows are defined for 0 <= n <= N-1 and are assumed to be zero otherwise.
+
+3. scale
+
+A scale factor for the output.
+
+4. type
+
+Output datatype ("type=short" or "type=float").
+
+.SH "SEE ALSO"
+options gauss
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/edframe.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,347 @@
+.TH EDFRAME 1 "1 September 1993"
+
+.SH NAME
+ edframe \-  Edit AIM output files.
+
+.SH SYNTAX 
+edframe  [[-]frame=a[-b]]  [[-]time=a[-b]]  [[-]freq=a[-b]]  [file]
+
+.SH DESCRIPTION
+Read an AIM output file which must include a header.
+Edit the file using the prescription given in the optional arguments to the
+edframe program, and write the result on the stdout as a new AIM output file
+with an appropriately modified header.
+
+AIM output consists of one or more frames. AIM programs such as genwav, genbmm,
+gennap, gensgm, gencgm, and gensas all generate a single frame of output
+which may be graphically displayed as a single image. AIM programs such as
+genasa, genepn, gensep, gensai, and genspl all generate multiple frames of
+output which may be graphically displayed as a sequence of images in a time-varying
+cartoon.
+
+AIM output may be generated by:
+.nf
+  genXXX  output=on  file1
+.fi
+which creates a file called file1.XXX. This can be edited to create a new
+AIM output file by:
+.nf
+  edframe  [options]  file1.XXX  >  file2.XXX
+.fi
+Alternatively the AIM output can be edited in situ by:
+.nf
+  genXXX  output=stdout  file1  |  edframe  [options]  >  file2.XXX
+.fi
+Edited output may be displayed using the "useprevious" option, for example:
+.nf
+  genXXX  useprevious=on file2
+.fi
+Note that that file2.XXX must have a different base-name to the genXXX input
+(file1) because genXXX will remove any file1.XXX as a side-effect.
+
+Each frame is a matrix of numbers consisting of one or more rows and columns.
+Rows and cols are numbered 0,1,2,..., with the origin (0,0) at the bottom-left
+corner of the graphical image of each frame.
+Editing functions select sub-sequences of frames (when the file consists of
+multiple frames), and partition each of the selected frames using the
+prescription given as program arguments.
+The edited output consists of the selected sub-sequence of partitioned
+sub-matrices. The format of the edited output file corresponds to that of the
+respective input file, and the header is modified to describe the new frame
+size.
+
+.SH OPTIONS
+
+1. time, freq.
+
+These options prescribe the partition of each frame.
+The partition output for each frame is a sub-matrix with width, height, and
+origin with respect to the frame origin described in terms of rows and columns.
+The time and freq options are ranges in the respective dimensions which are
+converted to rows and columns internally. The ranges are given as:
+.nf
+  time=a[-b]
+  freq=a[-b]
+.fi
+The upper limit `b' is optional,
+and when it is missing then the range is a single value,
+otherwise `a' and `b' are inclusive range limits.
+The strings "min" and "max" are recognised as extreme limits, otherwise
+the values of `a' and `b' are numbers with optional units.
+
+The units of the time selector are s or ms
+(seconds and milliseconds respectively), or samples (numbered 0,1,2...)
+if no units are given. Options with time units are converted to samples internally using
+the `samplerate' option.
+
+The units of the freq selector are Hz or kHz
+or filterbank channel (numbered 0,1,2...) if no units are given.
+Options with frequency units are converted to channel numbers internally using the
+filterbank parameters `mincf_afb', `maxcf_afb', `dencf_afb', and `channels_afb'
+given in the AIM header. The channel number which is "closest" in terms of
+centre frequency to the given frequency is chosen.
+
+For most gen programs the time option controls the width of the partition in terms of
+cols (or samples along the horizontal axis of the frame image) and the freq option
+controls the height of the partition in terms of rows
+(or filterbank channels up the vertical axis of the frame image).
+The exceptions to this are
+genwav (where the vertical axis contains just one wave), and the excitation
+patterns genasa, genepn, and gensep in which frequency is measured
+along the horizontal axis of the image, so that it is more appropriate for the
+freq option to control the width of the partition in terms of cols
+(or filterbank channels along the horizontal axis of the frame image).
+
+In the case of gensai (and genspl) the horizontal (or spiral) axis measures
+lag rather than absolute time, but the time option is used to control this
+axis. (Note that time is measured from the left end of the frame image, which
+is actually the maximum lag).
+
+2. frame.
+
+When the input consists of a cartoon of multiple frames
+then single frames or a range of sequential frames may be selected from the
+input using:
+.nf
+  frame=a[-b]
+.fi
+The upper limit `b' is optional,
+and when it is missing then the range is a single frame,
+otherwise `a' and `b' are inclusive range limits.
+The strings "min" and "max" are recognised as extreme limits, otherwise
+the values of `a' and `b' are frame numbers: 0,1,2,...
+
+The frame selector may also take time units (s, or ms) to specify frames
+"closest" to the given time, being the frame number which is the greatest
+integer multiple of the framestep (`frstep_epn' or `frstep_aid') which does
+not exceed the given time, measured from the start of the input file.
+
+3. info.
+
+The option flag:
+.nf
+  -info
+.fi
+causes frame size information to be printed on the stdout.
+The option flag:
+.nf
+  info=fbank
+.fi
+causes channel centre-frequency information to be printed on the stdout for
+those channels selected by the `freq' option.
+This may be used to discover the exact centre-frequency occupied by a given
+channel number within a given filterbank, (as specified by
+the filterbank parameters given in the input header).
+
+4. Header.
+
+The option flag:
+.nf
+  Header=off
+.fi
+causes the modified header to be suppressed from the output.
+
+5. Transpose.
+
+The option flag:
+.nf
+  Transpose=on
+.fi
+causes a matrix transpose (swap rows and columns) of the output
+partition of each input frame.
+When a frame partition has a height greater than it's width
+(ie. cols < rows) then setting Transpose=on may provide a
+preferable display orientation. For example, this enables
+a very narrow (eg. single column) time-slice to be plotted
+horizontally, so that a time-slice of filterbank output may
+be plotted as a spectrum on a horizontal frequency axis.
+In general the transpose option changes the file format of each frame
+from column wise to row wise and vice versa.
+A row wise format (ie. consecutive channels) may be a more useful form of
+output from programs such as genbmm or gennap which normally use a column
+wise output format.
+
+.SH EXAMPLES
+
+.nf
+Selecting particular frames from AIM output.
+.fi
+
+1. Plot gennap output and its transpose.
+
+.nf
+  gennap output=stdout ... | edframe         >  file1.sai
+  gennap output=stdout ... | edframe Tran=on >  file2.sai
+  gensai useprevious=on file1
+  gensai useprevious=on file2
+.fi
+
+2. Select and plot frame 2 (ie. the 3rd frame) of gensai output.
+
+.nf
+  gensai output=stdout ... | edframe frame=2  >  file.sai
+  gensai useprevious=on file
+.fi
+
+3. Select the frames of gensai output which start between 16ms and 47ms from
+the start of it's input. (When the option frstep_aid=16ms then this would
+select the 2nd and 3rd frames).
+
+.nf
+  gensai output=stdout ... | edframe frame=16ms-47ms >  file.sai
+.fi
+
+4. Select the 5th to the last frame inclusively of gensai output.
+
+.nf
+  gensai output=stdout ... | edframe frame=4-max  >  file.sai
+.fi
+
+5. Select the first frame of genepn output and plot the spectrum.
+
+.nf
+  genepn output=stdout ... | edframe frame=min > file1.epn
+  genepn useprevious=on file1
+.fi
+
+
+.nf
+Editing frames to select particular frequency ranges or channels (ie rows).
+.fi
+
+6. Select and plot the channel with centre-frequency closest to 1kHz from
+gennap output.
+
+.nf
+  gennap output=stdout ... | edframe freq=1kHz  >  file.nap
+  gennap useprevious=on file
+.fi
+
+7. Select and plot channel 40 then the channel with the lowest and then
+the highest centre-frequency over all frames of gensai output.
+
+.nf
+  gensai output=stdout ... | edframe freq=40  >  file.sai
+  gensai useprevious=on file
+
+  gensai output=stdout ... | edframe freq=min  >  file.sai
+  gensai useprevious=on file
+
+  gensai output=stdout ... | edframe freq=max  >  file.sai
+  gensai useprevious=on file
+.fi
+
+8. Select and plot all channels of genbmm output from channel 10 to
+the channel with centre-frequency closest to 1kHz inclusively.
+
+.nf
+  genbmm output=stdout ... | edframe freq=10-1000Hz  >  file.bmm
+  genbmm useprevious=on file
+.fi
+
+9. Select and plot a portion of the spectrum from the first frame of genepn
+output between 1kHz and 2kHz.
+Note: frequency controls the horizontal (ie cols) dimension for genepn.
+
+.nf
+  genepn output=stdout ... | edframe frame=min freq=1kHz-2kHz > file.epn
+  genepn useprevious=on file
+.fi
+
+
+.nf
+Editing frames to select particular time slices (ie cols).
+.fi
+
+10. Plot column (ie sample) 100 of the 3rd frame of gensai output as a row.
+
+.nf
+  gensai output=stdout ... | edframe frame=2 time=100 Tran=on >  file.sai
+  gensai useprevious=on file
+.fi
+
+11. Plot column of sample at 20ms from start of gennap output as a row
+
+.nf
+  gennap output=stdout ... | edframe time=20ms Tran=on >  file.nap
+  gennap useprevious=on file
+.fi
+
+12. Edit a wave to select the stretch between 4ms and 16ms, strip the
+header and plot the resulting wave.
+
+.nf
+  genwav output=stdout ... | edframe time=4ms-16ms Header=off > file
+  genwav file
+.fi
+
+
+.nf
+Editing frames to select partitions.
+.fi
+
+13. Plot a partition of channels 40 to 44 over the last 5ms (ie near the
+trigger point on the right of the image) of all frames of gensai output.
+Then plot a partition of frequency range 1kHz to 1.5kHz over the first
+20ms (on the left of the image) of all frames of gensai output.
+
+.nf
+  gensai pwidth=35ms nwidth=0 output=stdout ... | edframe time=30ms-max > file.sai
+  gensai useprevious=on file
+  gensai output=stdout ... | edframe freq=1kHz-1.5kHz time=min-20ms > file.sai
+  gensai useprevious=on file
+.fi
+
+14. Plot the highest-frequency channel over the last 20ms of gennap output.
+
+.nf
+  gennap output=stdout ... | edframe freq=max time=20ms-max > file.sai
+  gennap useprevious=on file
+.fi
+
+
+.nf
+Changing the aim output format.
+.fi
+
+15. Convert the genbmm output format (column wise) to row wise format, and
+strip the aim header.
+The resulting file will consist of consecutive blocks of N samples, where
+N = length * samplerate.
+The first block is the output from the lowest centre frequency channel,
+the second is from the second channel, and so on.
+By default the whole frame is transposed, but any partition of the frame
+could be selected using the time and frequency options.
+(Note: the transpose takes place after the partition has been made).
+
+.nf
+  genbmm output=stdout ... | edframe Tranpose=on Header=off > file
+.fi
+
+
+.SH "SEE ALSO"
+options hdr fbank
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/edwave.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,85 @@
+.TH EDWAVE 1 "1 September 1993"
+
+.SH NAME
+edwave \-  Edit a given range of a wave.
+
+.SH SYNTAX 
+edwave [options] [filename]
+
+.SH DESCRIPTION
+Editing operations extract or delete a given time range of a given wave,
+and the results are written on the stdout.
+
+.SH OPTIONS
+
+1. range.
+
+The range option specifies the stretch of the wave for the editing operation
+by:
+
+.nf
+	    range=a[-b]
+.fi
+
+The upper limit `b' is optional, and when it is missing then the range
+is a single sample of the given type, otherwise `a' and `b' are inclusive range limits.
+The strings "min" and "max" are recognised as extreme limits
+("min" = start of file, "max" = end of file),
+otherwise the values of `a' and `b' are sample numbers: 0,1,2,...
+Values given with time units (ms or s) are converted to samples using
+the given samplerate option.
+
+2. operation.
+
+The `operation' option sets the edit operation to either:
+
+.nf
+	    operation=extract
+or
+	    operation=delete
+.fi
+
+The extract operation outputs the part of the input which is inclusively
+within the given range.
+The delete operation outputs the part of the input which is NOT inclusively
+within the given range.
+
+3. type.
+
+The datatype of input and output. Known types are in the list:
+char, short, int, float, double, ascii. The ascii type is interpreted as one
+sample per line.
+
+4. size.
+
+Print the size of the wave on the stdout in given units.
+Units are seconds ("size=s"), milliseconds ("size=ms"), or samples ("size=on").
+Sizes in time units are calculated using the given `samplerate' option.
+
+.SH "SEE ALSO"
+options bufwave
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/fbank.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,71 @@
+.TH FBANK 1 "1 September 1993"
+
+.SH NAME
+fbank \-    Print centre-frequency and bandwidth information for a given
+gammatone filterbank.
+
+.SH SYNTAX 
+fbank [options] [file]
+
+.SH DESCRIPTION
+Print centre-frequency and bandwidth information for a given
+gammatone filterbank on the stdout.
+
+Parameters specifying a filterbank may be given as arguments
+(channels, mincf, maxcf, dencf, bwmin, quality), or may be read from
+an AIM output header if the option `input=on'.
+
+Centre-frequency and bandwidth information is printed for a selected range of
+filterbank channels, specified using the `freq' option:
+
+.nf
+	    freq=a[-b]
+.fi
+
+where `a' and `b' are channel numbers: 0,2,3,... (the lowest centre-frequency
+channel has the lowest channel number, 0).
+The upper limit `b' is optional, and when it is missing then the range of
+channels is a single channel, otherwise `a' and `b' are inclusive limits.
+The strings "min" and "max" are recognised as extreme limits
+("min" is the lowest frequency channel, "max" is the highest frequency channel).
+Either range limit can take frequency units (Hz or kHz), in which case it
+is converted to a channel number using the "closest" channel number
+in the filterbank to the specified centre-frequency.
+
+.nf
+For example:
+
+	freq=5         channel 5
+	freq=1kHz      channel number with centre-freq closest to 1kHz
+	freq=max       highest centre-freq channel
+	freq=10-max    channel 10 to the highest centre-freq channel
+	freq=min-15    channel 0 to 15
+.fi
+
+.SH "SEE ALSO"
+options hdr edframe
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/fft.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,103 @@
+.TH FFT 1 "15 September 1993"
+
+.SH NAME
+fft \- Fast Fourier transform of contiguous frames.
+
+
+.SH SYNTAX 
+fft  [arguments]  [file]
+
+
+.SH DESCRIPTION
+Several forms of fft processing are provided, according to the "spectrum"
+option. Unless verbose output is requested, all input and output is in
+binary shorts.
+
+Each input frame is padded with zeroes to the next power of 2 larger than
+the input framewidth.
+If necessary, extra padding can be enforced using the (silent) padding option
+to add extra zeroes, padding to a larger power of 2.
+The amount of extra padding is "exponential", expanding the basic size to:
+
+      ( framewidth + padding ) * 2**n
+
+where the padding option is n.
+
+(n=0 by default, so that no extra padding is added. When n=1 then padding is
+added to double the size, and when n=2 the size is quadrupled, etc.).
+The input and output frame sizes in sample points may be printed using the
+"size" option.
+
+
+.SH OPTIONS
+
+The spectrum option selects a form of processing from the list:
+
+1. magnitude: magnitude spectrum
+
+2. log: log10 of magnitude spectrum
+
+3. phase: phase spectrum.
+
+4. complex: full complex spectrum, in <real,imag> pairs.
+
+5. inverse: inverse fft, reading framewidth numbers which are interpreted as
+<real,imag> pairs, (ie framewidth/2 complex numbers),
+and outputs the inverse transform scaled by 1/framewidth.
+
+6. verbose: prints the spectrum in ASCII on the stdout.
+
+.SH EXAMPLES
+.nf
+1. To print the input and output frame sizes in sample points,  
+   eg for a subsequent plotting program, use the size option:
+
+fft ... size=on
+
+
+2. An fft of a waveform sampled at 10kHz, computed within a 
+   frame of 12.8ms, plotting the 2nd frame in a sequence of 
+   frames with half-frame overlap.
+
+fft samp=10kHz width=12.8ms frstep=6.4ms frame=2 file | x11plot
+
+
+3. An animated plot of successive fft spectra of a waveform 
+   sampled at 10kHz, each computed within a frame of 12.8ms, 
+   and shifted by 2 sample points.
+
+fft samp=10kHz width=12.8ms frstep=2p file | x11play -n64
+
+
+4. Using the complex output from fft, and inverse transform 
+   without windowing to recover original input.
+
+fft samp=10kHz frame=2 spec=complex window=off file > foo
+fft samp=10kHz frame=1 spec=inverse window=off foo | x11plot
+
+.fi
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/filt1.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,76 @@
+.TH FILT1 1 "1 September 1993"
+
+.SH NAME
+filt1 \- 1st order LP filter using an exponential smoother.
+
+.SH SYNTAX 
+filt1 [options] [file]
+
+.SH DESCRIPTION
+A recursive "leaky integrator" 1st order low-pass filter which is a shifting
+exponential window which decays into the past values.
+
+.SH OPTIONS
+
+1. tc
+
+The time-constant parameter which controls the rate of decay and so the
+size of the exponential window. For a given time constant of T seconds:
+
+.nf
+	0.7T secs   is the window half--life.
+	4.6T secs   is 99% of the window's life.
+.fi
+
+When the time-constant parameter is given with time units (s or ms) then
+it is converted to a decay constant using  a = exp(-Ts/T),
+where Ts is the sample interval in seconds from the given `samplerate' option,
+and T  is decay time-constant in seconds.
+Otherwise the time-constant parameter is taken to be the decay constant directly.
+
+With decay constant a=1 there is infinite memory because it does not decay.
+With 0 < a < 1 there is a finite decaying memory.
+The smaller `a', the smaller the memory (it decays faster).
+With a = 0 the filter output is identical with its input.
+
+2. de
+
+Two optional difference equations are provided which repsectively compute
+a recursive sum (when "de=sum") and mean (when "de=mean").
+The n'th recursive update is respectively:
+
+.nf
+	y[n] = a.y[n-1] + x[n]                recursive sum
+	y[n] = a.y[n-1] + (1-a).x[n]          recursive mean
+.fi
+
+where decay constant a = exp(-Ts/T),
+Ts is the sample interval in seconds, and T  is decay time-constant in seconds.
+
+.SH "SEE ALSO"
+options smooth
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/ftgram.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,97 @@
+.TH FTGRAM 1 "1 September 1993"
+
+.SH NAME
+ftgram \- Autocorrelogram auditory image.
+
+.SH SYNTAX 
+ftgram  [arguments]  [file]
+
+.SH DESCRIPTION
+Short-time Fourier transform applied to each row of input frames.
+Output frames consist of row-wise magnitude spectra, computed using fft.
+
+The program expects to read an AIM header, and interprets input as one large
+frame in column-wise format (eg output from genbmm, gennap, etc.), to be
+divided into input frames, each to be processed by row-wise fft.
+A new header is constructed, and each fft-gram frame is output in
+row-wise format (eg as if output from gensai).
+
+The input is divided into frames according to the given options.
+The options "start" and "length" specify the input file.
+The special option value length=max specifies all the input file from
+the given start to its end.
+The options "width" and "frstep"  specify the input frames.
+The width option is the framewidth of each input frame) and the frstep
+option is the frameshift between input frames in the input file.
+The special option value width=max specifies the input framewidth as equal
+to the given input file length, (and if this is also "max", then the
+input framewidth is the remainder of the input file).
+
+Most options in the input header are copied to the output header.
+This enables options which are needed for the eventual display
+to pass straight through. Some options are set so that they can override
+the input header. For example, the display option is set on to enable
+display even when input has display=off. The animate option can be set on
+even when the input has animate=off.
+Some parts of the header are changed for the output format:
+(frames, frameshift, framewidth, frameheight, framebytes).
+
+Each row of each input frame is padded with zeroes to the next power of 2
+larger than the original input framewidth.
+If necessary, extra padding can be enforced using the (silent) padding option
+to add extra zeroes, padding to a larger power of 2.
+The amount of extra padding is "exponential", expanding the basic size to:
+
+      ( framewidth + padding ) * 2**n
+
+where the padding option is n.
+
+(n=0 by default, so that no extra padding is added. When n=1 then padding is
+added to double the size, and when n=2 the size is quadrupled, etc.).
+The output framewidth (and hence the frequency resolution) depends upon the
+input framewidth and the padding.
+
+
+.SH EXAMPLES
+1. ftgram of a NAP, animated, with framewidth 16ms
+
+gennap len=128ms output=stdout display=off file | ftgram width=16ms \
+animate=on > file.sai
+
+gensai useprev=on headr=5 top=1000 file         -(for landscape plot)
+
+genspl useprev=on headr=5 top=1000 pensize=2 file   -(for spiral plot)
+
+2. ftgram of an SAI:
+  (gensai removes file.sai, so you must use some other name, eg foo.sai).
+
+gensai len=64 pwidth=64 nwidth=0 output=stdout display=off file |  \
+saitonap frame=3 | ftgram width=32ms frame=1 > foo.sai
+
+gensai useprev=on top=1000 headr=5 mag=2 foo
+
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/ftoa.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,43 @@
+.TH FTOA 1 "7 September 1993"
+
+.SH NAME
+
+ftoa \-  Frames to ASCII triples (x,y,z).
+
+.SH SYNTAX
+
+Usage  ftoa  [arguments]  [file]
+
+.SH DESCRIPTION
+
+Convert AIM binary output to ASCII. Either column-wise (format=nap) or row-wise
+(format=sai) format is understood.
+Each data point is output as a triple: (x,y,z)
+where (x,y) specify the coordinate in terms of a pointwise coordinate
+system with the origin (0,0) in the bottom-left of the display.
+The output is in space-separated ASCII numbers with one triple per line.
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/ftos.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,58 @@
+.TH FTOS 1 "7 September 1993"
+
+.SH NAME
+
+ftos \-  float to short data-type conversion.
+
+.SH SYNTAX
+
+Usage:  ftos  [arguments]  [file]
+
+.SH DESCRIPTION
+
+Binary float-to-short conversion.
+
+.SH OPTIONS
+
+1. error
+
+When error=on then the maximum and the mean quantization error is printed on
+the stderr. The quantization error for each floating point number x under the
+truncating operation int(x) is defined as
+the absolute quantization error as a proportion of the range:
+
+.nf
+	(x-int(x)) / int(1+x)
+.fi
+
+16-bit under or overflow is also reported if it occurs.
+
+
+.SH "SEE ALSO"
+.LP
+options stof btoa atob
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/gate.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,145 @@
+.TH GATE 1 "15 September 1993"
+
+.SH NAME
+gate \- gate specific numbers from the input stream.
+
+.SH SYNTAX 
+gate  [options]  [file]
+
+.SH DESCRIPTION
+
+Numbers in the input stream within given gate ranges are replaced by a
+particular <value>. Both time and amplitude ranges may be specified.
+The <value> may be a real number or the result of a particular <operation>.
+Results are written on the stdout in numbers of the same type as that
+selected for input.
+
+.SH OPTIONS
+
+1. xrange, yrange
+
+The `xrange' specifies the time range and the `yrange' specifies the
+amplitude range for the gating operation. Ranges are specified:
+
+.nf
+	xrange=a[-b]
+	yrange=a[-b]
+.fi
+
+The upper limit `b' is optional, and when it is missing then the range
+is a single number, otherwise `a' and `b' are inclusive range limits.
+The xrange limits are in samples (no units) or may take time units (s or ms),
+in which case they are converted to samples using the given `samplerate'
+option. The yrange limits are real numbers.
+The strings "min" and "max" are recognised as extreme limits: the start and
+end of the input stream for the xrange, and the most positive and negative
+amplitudes for the yrange.
+
+2. value
+
+The <value> may be a real number or an <operation>,
+in which case all input numbers within the gate range are operated on as
+appropriate. Abbreviated forms of the operation names are allowed.
+
+.nf
+<operation>:
+    exclude     exclude numbers in gate range from output
+    negate      negate numbers in gate range
+    count       print count of numbers in gate range on the stderr
+.fi
+
+3. type
+
+The input and output datatype may be: char, short, int, float, double, ASCII.
+Ascii input is taken to be one number per line.
+
+.SH EXAMPLES
+
+1. Replace all numbers <=0 by value 0  (ie. half-wave rectification).
+
+.nf
+	gate yrange=min-0 val=0  file
+.fi
+
+2. Replace all numbers <=0 by their inverse (ie. full-wave rectification).
+
+.nf
+	gate yrange=min-0 val=neg  file
+.fi
+
+3. Gate the onset of a signal: replace the first 20ms with zeroes.
+
+.nf
+	gate xrange=0-20ms yrange=min-max val=0 file
+.fi
+
+4. Exclude all numbers <=0
+
+.nf
+	gate yrange=min-0  val=exclude file
+.fi
+
+5. Exclude all numbers >0
+
+.nf
+	gate yrange=1-max val=exclude file
+.fi
+
+6. Delete lines 4 to 8 inclusive from ascii input (lines numbered 0,1,2,...)
+
+.nf
+    gate type=ASCII xrange=4-8 yrange=min-max val=exclude  file
+.fi
+
+7. Replace all numbers in the yrange -1 to +1 inclusive by 0
+
+.nf
+	gate yrange=-1-1 val=0  file
+.fi
+
+8. Replace all instances of number 10 by -10
+
+.nf
+	gate yrange=10 val=-10  file
+.fi
+
+9. Print a count of all numbers = 0
+
+.nf
+	gate yrange=0 val=count file
+.fi
+
+10. Print a count of all numbers < 0
+
+.nf
+	gate yrange=min--1  val=count file
+.fi
+
+
+.SH "SEE ALSO"
+.LP
+options edwave step merge
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/gauss.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,68 @@
+.TH GAUSS 1 "1 September 1993"
+
+.SH NAME
+gauss \- generate a Gaussian window.
+
+.SH SYNTAX 
+gauss [option]
+
+.SH DESCRIPTION
+Generate a Gaussian window on the stdout in binary shorts or floats for a
+given variance over a given range of standard deviations.
+
+.SH OPTIONS
+
+1. variance, range
+
+The variance of the Gaussian window and its ordinal range in standard
+deviations either side of the mode.
+The size of the window in samples is given by:
+
+.nf
+	[ 2 * range * sqrt( variance ) ] samples   +  1 sample
+.fi
+
+The variance can be given with time units (ms or s) or samples (no
+units).  Time units are converted to samples using the given `samplerate'
+option.
+
+2. normalize
+
+If "normalize=off" then the window has unit amplitude at the mode.
+If "normalize=on" then the window is scaled for unit area.
+
+3. scale
+
+A scale factor for the output.
+
+4. type
+
+Output datatype ("type=short" or "type=float").
+
+.SH "SEE ALSO"
+options smooth
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/genasa.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,198 @@
+.TH GENASA 1 "11 May 1995" 
+.LP 
+.SH NAME 
+.LP 
+genasa \- generate auditory spectral analysis 
+.LP 
+.SH SYNOPSIS 
+.LP 
+genasa [ option=value | -option ] [ filename ] 
+.LP 
+.LP
+.SH DESCRIPTION 
+.LP 
+The genasa module of the AIM software performs a time-domain spectral
+analysis on the input wave using a bank of auditory filters, and
+summarises the information in a sequence of auditory spectra. The
+spectral analysis converts the input wave into an array of filtered
+waves, one for each channel of a gammatone auditory filterbank. The
+surface of the array of filtered waves is AIM's representation of
+basilar membrane motion (BMM) as a function of time. The sequence of
+auditory spectra is produced by calculating the envelope of the BMM
+and extracting spectral slices from the envelope every 'frstep_epn'
+ms. The envelope is calculated continuously, by rectifing,
+compressing, and lowpass filtering the individual BMM waves as they
+flow from the filterbank.
+.LP
+The auditory spectrum produced by genasa is intended to simulate the
+spectral representation of a sound as it occurs in the peripheral
+auditory system just prior to neural transduction.  As a result, the
+frequency resolution of the analysis varies with the center frequency
+of the channel, and the distribution of channels across frequency is
+chosen to match that in the auditory system.  The auditory spectrum is
+a plot of the activity in each channel as a function of the centre
+frequency of the auditory filter (in ERB's).  The representation is
+referred to as an auditory spectrum to distinguish it from the Fourier
+energy spectrum (Patterson, 1994a). The suffix 'asa' is short for
+'auditory spectral analysis'; it is used to distinguish this spectral
+representation from three other spectral representations provided by
+the AIM software ('epn' excitation pattern, 'sgm' auditory
+spectrogram, and 'cgm' cochleogram).
+.LP
+The spectral analysis performed by genasa is the same as that
+performed by genbmm. The primary differences are in the display
+defaults and the inclusion of the Compression and Leaky Integration
+modules used to construct the spectral slices from the BMM.  As a
+result, this manual entry is restricted to describing the option
+values that differ from those in genbmm and the additional options
+required to control the Compression and Leaky Integration.
+.LP
+.SH DISPLAY DEFAULTS
+.LP
+The default values for three of the display options are reset to
+produce a spectral format rather than a landscape; specifically,
+display=excitation, bottom=0 and top=2500. The number of channels is
+increased to 128 to ensure reasonable frequency resolution in the
+spectral display.
+.LP
+.SH COMPRESSION AND LEAKY INTEGRATION
+.LP
+Compression and lowpass filtering are activated and the neural
+encoding stage that comes between them is turned off:
+.LP
+.LP
+.SS "Compression"
+.PP
+Auditory spectra are usually produced via the functional route in
+AIM. In this case, compress is set on
+.LP
+.TP 13
+compress
+Logarithmic compressor switch
+.RS
+Switch. Default: on.
+.RE
+.RS
+.LP
+Note: The compressor in the functional route of AIM is logarithmic and
+it screens out negative BMM values before compression. This rectifies
+the wave during the compression process and so the separate rectify
+option is left off. 
+.RE
+.LP
+.RS
+.LP
+Note: The compressor in the physiological route of AIM is an integral
+part of the tlf module, so when using this route to produce auditory
+spectra, turn off the logarithmic compressor (i.e. compress=off). The
+compressor in tlf does not screen out negative values so it is also
+important to set rectify=on.
+.RE
+.RS
+.LP
+Full wave rectification is produced if rectify is set to 2. This is
+useful when calculating envelopes with genasa.
+.RE
+.LP
+.LP
+.SS "Transduction"
+.PP
+.LP
+.TP 13
+transduction
+Neural transduction switch (at, meddis, off)
+.RS
+Switch. Default: off.
+.RE
+.LP
+.LP
+.SS "Leaky Integration"
+.PP
+.LP
+.TP 13
+stages_idt
+Number of stages of lowpass filtering
+.RS
+Default unit: scalar. Default value: 2
+.RE
+.TP 13
+tup_idt
+The time constant for each filter stage
+.RS
+Default unit: ms. Default value: 8 ms.
+.RE
+.LP
+The Equivalent Rectandular Duration (ERD) of a two stage lowpass
+filter is about 1.6 times the time constant of each stage, or
+12.8 ms in the current case.
+.TP 13
+frstep_epn
+The time between successive spectral frames
+.RS
+Default unit: ms. Default value: 10 ms.
+.RE
+.LP
+With a frstep_epn of 10 ms, genasa will produce
+spectral frames at a rate of 100 per second. 
+.LP
+.TP 13
+downsample
+The time between successive spectral frames. 
+.RS
+Default unit: ms. Default value: 10 ms.
+.RE
+.LP
+Downsample is simply another name for frstep_epn, provided to
+facilitate a different mode of thinking about time-series data.
+.RE
+.LP
+.SH FILES
+.LP
+.TP 13
+ .genasarc 
+The options file for genasa.
+.LP
+.SH SEE ALSO
+.LP
+genbmm, gensgm
+.LP
+.SH BUGS
+.LP
+None currently known.
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+.LP
+.SH ACKNOWLEDGEMENTS
+.LP
+The AIM software was developed for Unix workstations by John
+Holdsworth and Mike Allerhand of the MRC APU, under the direction of
+Roy Patterson. The physiological version of AIM was developed by
+Christian Giguere. The options handler is by Paul Manson. The revised
+SAI module is by Jay Datta. Michael Akeroyd extended the postscript
+facilites and developed the xreview routine for auditory image
+cartoons.
+.LP
+The project was supported by the MRC and grants from the U.K. Defense
+Research Agency, Farnborough (Research Contract 2239); the EEC Esprit
+BR Porgramme, Project ACTS (3207); and the U.K. Hearing Research Trust.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/genbmm.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,750 @@
+.TH GENBMM 1 "11 April 1994"
+.LP
+.SH NAME
+.LP
+genbmm \- generate basilar membrane motion
+.LP
+.SH SYNOPSIS
+.LP
+genbmm [ option=value | -option ] [ filename ]
+.LP
+.SH DESCRIPTION
+.LP
+The genbmm module of the AIM software simulates the spectral analysis
+performed by the auditory system using a bank of auditory filters.
+Specifically, genbmm converts an input wave into an array of filtered
+waves, one for each channel of the filterbank. The surface of the
+array of filtered waves is AIM's representation of basilar membrane
+motion (BMM) as a function of time.  AIM provides two alternative
+methods for generating the BMM, linear, gammatone filterbank
+(Patterson et al, 1988; Slaney 1993, Cooke, 1993), or a nonlinear,
+transmission-line filterbank (Giguere and Woodland, 1994). For
+convenience, they are referred to as the 'functional' filterbank and
+the 'physiological' filterbank, respectively.
+.LP
+.SH OPTIONS
+.LP
+There are three sets of options for genbmm; they are grouped by
+function and identified by the suffixes _afb, _gtf and _tlf. The first
+set controls the distribution of the filtered waves across frequency
+(suffix _afb); the second specifies the shape of the gammatone filter
+(suffix _gtf); and the third specifies the shape of the transmission
+line filter (suffix _tlf). These three groups of options are the
+subject of this manual entry, together with an option that specifies
+the filter choice (gtf or tlf), and an option that specifies whether a
+middle ear function should be used with the gtf filterbank.
+.LP
+.SS "The Outer/Middle Ear function: middle_ear "
+.PP
+In the auditory system the middle ear causes a progressive attenuation
+of sound energy in the region below about 500 Hz and a progressive
+attenuation in the region above about 4000 Hz.  There is also a
+primary auditory canal resonance around 2700 Hz that provides a boost
+in sound transmission. The resulting transfer function is a normal
+aspect of auditory processing and preceeds spectral analysis. If the
+functional filterbank is chosen (gtf), the outer/middle ear filter
+acts directly on the input wave, and the stapes velocity wave it
+generates is the input to the spectral filtering stage. If the
+physiological filterbank is chosen (tlf), the outer/middle ear and
+cochlear filter are performed simultaneously as in the auditory
+system. The only parameter associated with this function is the
+middle_ear switch which makes it possible to turn the outer/middle ear
+filtering off when the functional filterbank is chosen.
+.LP
+.TP 13
+middle_ear
+Outer/middle ear switch
+.RS
+Switch. Default: on. 
+.RE
+.RS
+.LP
+It is also possible to specify a floating point number, in which 
+case the middle ear output is multiplied by that value.
+.RE
+.LP
+Note: The middle_ear option is ignored if option filter (see below) 
+is set to tlf. This is because the outer/middle stage and the 
+cochlear stage are bidirectionally coupled in the transmission 
+line filter implementation, and cannot be separated. 
+.RE
+.LP
+.SS "The Auditory FilterBank options: _afb "
+.PP
+The distribution of the filters across frequency and the total 
+number of output filters in the bank are determined by four parameters: 
+channels_afb, mincf_afb, maxcf_afb, and dencf_afb. 
+.LP
+.TP 13
+channels_afb
+The number of channels in the filterbank. 
+.RS
+Default unit: filters. Default value: 75 
+.RE
+.TP 13
+mincf_afb
+The minimum centre frequency 
+.RS
+Default unit: Hz. Default value: 100 Hz. 
+.RE
+.TP 13
+maxcf_afb
+The maximum centre frequency 
+.RS
+Default unit: Hz. Default value: 6000 Hz. 
+.RE
+.TP 13
+dencf_afb
+The density of the filters in the filterbank. 
+.RS
+Units: filters/critical band. Default: off 
+.RE
+.RS
+.LP
+dencf_afb provides an alternative method of specifying the number of channels 
+in terms of the density of filters along the frequency scale. 
+.RE
+.LP
+Note: channels_afb overrides dencf_afb whenever it has a non-zero 
+value.  The values of dencf_afb and channels_afb may conflict at 
+this point, in which case dencf_afb is ignored.
+.RE
+.LP
+WARNING: When using the transmission line filter (filter=tlf), the
+channel density should be 3 or more filters/erb.  Using a lower
+density may lead to excessive spatial discretization errors (see
+Giguere and Woodland (1994) for a discussion).  To view a small number
+of channels, use a reasonable density and reduce the number of
+displayed channels using option downchannel.
+.LP
+.TP 14
+audiogram_afb
+The audiogram 
+.RS
+Units: none. Default: off. Status: obsolete.
+.RE
+.LP
+Note: In the versions up to and including AIM R6.15, this parameter
+was used as a means of approximating equal loudness contours, as well
+as middle ear attenuation. It applies a spectral weighting function at
+the output of the filterbank. With the addition of the outer/middle
+ear transfer function, this parameter is obsolete, and so the default
+value is off. Users who wish to use the audiogram parameter instead of
+the new outer/middle filter as a loudness equilisation function can
+still do so by setting audiogram_afb=on and middle_ear=off. As before,
+audiogram_afb is applied as a power function and so as the value of
+audiogram_afb decreases from 1 to 0, the degree of attenuation
+decreases.  Values greater than unity are allowed but their
+interpretation is unclear.
+.RE
+.LP
+The ERB scale for the gammatone auditory filterbank
+is specificed with three options: bwmin_afb, quality_afb, 
+and mmerb_afb. 
+.LP
+.TP 13
+bwmin_afb
+The minimum bandwidth for an auditory filter. 
+.RS
+Default unit: Hz. Default value: 24.7 
+.RE
+.TP 13
+quality_afb
+The limiting quality factor for high frequency auditory filters. 
+.RS
+Units: scalar. Default: 9.265 
+.RE
+.TP 13
+mmerb_afb
+The length of one erb-rate unit along the basilar membrane.
+.RS
+Units: mm. Default: 0.89
+.RE
+.LP 13
+A listing of the parameters for the filter in the bank can be directed
+to the terminal at run time by setting info_afb=on.
+.RE
+.TP
+info_afb
+Print filterbank information to stderr.
+Switch. Default: off.
+.RE
+.LP
+The physiological data on human cochlear frequency-position 
+function (Greenwood, 1990) and the psychoacoustic data on auditory 
+filter bandwidth (Patterson and Moore, 1986) indicate that the 
+spectral analysis performed in the cochlea is like a 'constant Q' 
+system (quality_afb) that asymptotes to a minimum filter bandwidth 
+(bwmin_afb) at low centre frequencies. That is,
+.PD 0
+.LP
+.PD 4
+.LP
+	erb = bwmin_afb + centre-frequency/quality_afb.  
+.PD 0
+.LP
+.PD 4
+.LP
+If we assume, as Greenwood suggests, that each filter bandwidth
+corresponds to a constant distance (mmerb_afb) along the basilar
+membrane, it is possible to scale frequency in terms of erb units (or
+position along the basilar membrane) by integrating the inverse of the
+erb function above.
+.RE
+.LP
+Glasberg and Moore (1990) have reviewed the available human filter
+shape data and concluded that the optimum values for bwmin_afb and
+quality_afb are 24.7 and 9.265, respectively, together with mmerb_afb
+of 0.89.  (As a rule of thumb for rapid estimation, erb = 25 + 10% of
+cf ). The auditory scale used by Greenwood (1990) can be specified by
+setting bwmin_afb=22.85, quality_afb=7.238 and mmerb_afb=1.0. A
+reasonable approximation to the Bark scale (Zwicker, 1961) is obtained
+by setting bwmin_afb=80, quality_afb=6.5 and mmerb_afb=0.89.
+.RE
+.LP
+.SS "Auditory filter design: filter "
+.PP
+The choice of filterbank -- linear gammatone or nonlinear transmission
+line -- is determined by option filter.
+.LP
+.TP 13
+filter
+The auditory filter design
+.RS
+Default: gtf. Choices: gtf, tlf, off.
+.RE
+.LP
+When gtf is specified, the options below with suffix _gtf apply, and
+when tlf is specified, the options below with suffix _tlf apply. When
+off is specified, the input wave (or the stapes velocity) is passed on
+directly to the next stage. This provides for non-auditory use of the
+modules following the filterbank with their associated displays. For
+example, the envelope of the input wave (or stapes velocity) can be
+extracted using the rectification and integration modules that follow
+genbmm. The entry point genasa has the most convenient default
+settings for this purpose. The default value for the filter option is
+gtf.
+.RE
+.LP
+.SS "The GammaTone Filter options: _gtf "
+.LP
+.TP 13
+order_gtf
+The order of the gammatone filter 
+.RS
+Units: none. Default: 4 
+.RE
+.RS
+.LP
+The order of the filter, order_gtf, determines the number of filtering
+stages and so it determines the slope of the skirts of the attenuation
+function and their extent. The default value is 4 and the range of
+useful values is from about 2 to 8.  The processing time increases
+linearly with order above about order 2.
+.RE
+.LP
+Note that the bandwidth calculation takes account of the fact that
+changes in order_gtf affect bandwidth. Thus, as long as bwmin_afb is
+fixed, changing the order will not affect the bandwidths of the
+resulting filters.  Increasing the order of the filter increases the
+delay of the onset of the impulse response but it has little effect on
+the shape of the envelope of the impulse response for orders greater
+than three. The human auditory system is not sensitive to small phase
+changes between filter channels (Patterson, 1987) and so filter order
+is not well constrained by human experimental data.  The default value
+(4) is used because this value provides the best match between the
+amplitude characteristics of the gammatone and roex filters for humans
+(Patterson et al., 1988).
+.LP
+.TP 13
+gain_gtf
+Filter output amplification 
+.RS
+Units: scalar. Default: 4.
+.RE
+.RS
+.LP
+The ratio of input to output level across the auditory filter 
+when the input is a sinusoid at the cf of the filter.
+.RE
+.TP 13
+phase_gtf
+The phase of the impulse response (obsolete)
+.RS
+Units: none. Default: 0. 
+.RE
+.LP
+In the absence of phase compensation, the surface of basilar membrane
+motion has a strong rightward skew in the low-frequency channels
+because the filters get progressively narrower as centre frequency
+decreases, and this narrowing is accompanied by a slower filter
+response. There are occassionally non-auditory reasons for wanting to
+align the channels across frequency in one way or another. The
+software provides four alignment systems which are discussed at the
+end of this entry just before the references under the title Phase
+Alignment.
+.RE
+.LP
+.SS "The Transmission Line Filter options: _tlf "
+.LP
+.TP 13
+motion_tlf
+The basilar membrane output motion variable
+.RS
+Default: vel. Choices: vel, disp.
+.RE
+.RS
+.LP
+If vel (velocity) is specified, the output of genbmm
+is the basilar membrane velocity. If disp (displacement)
+is specified, the output of genbmm is the basilar membrane
+displacement. The default value is vel.
+.RE
+.TP 13
+outdencf_tlf
+The density of the filters outside the display
+range. 
+.RS
+Units: filters/critical band. Default: 4.
+.RE
+.RS
+.LP
+In the transmission line filter implementation, it is necessary to
+simulate the basilar membrane over its entire length.  The option
+outdencf_tlf provides a means of specifying the number of additional
+channels that must be computed at the basal and apical ends of the
+cochlea, ie. outside the range specified by mincf_afb and maxcf_afb
+(see above).  These additional channels are only computed for internal
+use and are not passed to the next stage of processing.
+.RE
+.TP 13
+qref_tlf
+The local quality factor of each basilar membrane channel
+.RS
+Units: scalar. Default: 2. 
+.RE
+.RS
+.LP
+Note: With the transmission line filter, the bandwidth is not
+determined by options bwmin_afb and quality_afb at high levels but
+rather by option qref_tlf (see above).
+.RE
+.TP 13
+feedback_tlf
+The feedback gain of the outer hair cell circuit
+.RS
+Units: scalar. Default: 0.99
+.RE
+.RS
+.LP
+WARNING: A value for feedback_afb greater than or equal to 1.0 can
+lead to unstable behaviour at low-levels (ie. oscillation).  However,
+the model output will not grow unbound. The growth of the oscillations
+will be limited by the saturating nonlinearity of the outer hair cell
+circuit, and the model output will go into a kind of limit-cycle.
+These model oscillations have not yet been studied in detail and are
+likely to deviate substantially from real cochlear emissions.
+.RE
+.TP 13
+dsat_tlf
+The basilar membrane displacement at the half-saturation point 
+of the outer hair cell circuit
+.RS
+Units: cm. Default: 5.75e-6
+.RE
+.TP 13
+gain_tlf
+Filter output amplification 
+.RS
+Units: scalar. Default: 4.
+.RE
+.RS
+.LP
+Note: There is an internal gain of 4.0 within the software of
+the transmission line model itself. The total gain is therefore
+4.0 times the value for gain_tlf.
+.RE
+.LP
+Note: A linearized version of the transmission line filter with
+roughly the same bandwidth as the gammatone filter can be obtained by
+setting feedback_tlf=0 and qref_tlf to about 10.  The main difference
+is that the low-frequency skirt of the transmission line filter is
+less steep than that of the gammatone.
+.LP
+.SH FURTHER DESCRIPTION
+.LP
+.SS "The distribution of filter centres along the ERB scale. "
+.LP
+Given values for mincf_afb maxcf_afb and channels_afb (or 
+dencf_afb), the program creates an array of centre frequencies 
+in three steps:
+.LP
+1. It centres a filter at 1.0 kHz.
+.RE
+.LP
+2. Then it centres filters below 1.0 kHz, one after another, 
+until it encounters mincf_afb. (Thus, mincf_afb is actually the 
+frequency below which no filters are centred). The step size, 
+that is the distance between centre frequencies, is determined 
+by dencf_afb. When dencf_afb is equal to one, the centre 
+frequencies are 1 ERB apart. The ERB is the Equivalent 
+Rectangular Bandwidth of the filter (about 14% larger than the 3 
+dB bandwidth of the filter). The function relating the ERB to the 
+centre frequency of the filter is taken from a `critical band' 
+equation introduced by Greenwood (1961) and adapted to human 
+auditory masking by Glasberg and Moore (1990).
+.RE
+.LP
+3. Finally, the program centres filters one after another in 
+the region above 1 kHz until it encounters maxcf_afb (which is, 
+actually, the frequency above which no filters are centred). When 
+dencf_afb is increased, say to two, the program allocates two 
+filters per critical band and spaces them at half ERB steps.
+.RE
+.LP
+Note: It is not the bandwidths of the filters that are 
+controlled by dencf_afb but rather the density of filters along 
+the frequency axis. Thus, doubling dencf_afb does not cause the 
+bandwidth of the filters to be halved; rather it results in more 
+overlap between adjacent filters. With regard to the images 
+produced by genbmm, dencf_afb determines the density of lines on 
+the surface rather than the shape of the features that appear on 
+the surface.
+.LP
+.SH MOTIVATION
+.LP
+The motivation for adopting the gammatone filter shape is 
+threefold:
+.LP
+1. It provides an excellent summary of physiological data 
+concerning the impulse response of primary auditory neurons in 
+small mammals such as cats (de Boer and de Jongh, 1978; Carney and 
+Yin, 1989)
+.RE
+.LP
+2. The amplitude characteristic of the gammatone filter is very 
+similar to that of the Roex filter commonly used to represent the 
+human auditory filter (Patterson, et al, 1982; Schofield, 1985; 
+Patterson et al, 1988) .
+.RE
+.LP
+3. There are recursive gammatone filters that make the calculation
+particularly fast both on general purpose computers and special
+purpose DSP chips (Holdsworth et al, 1988; Cooke, 1993; Slaney, 1993).
+.RE
+.LP
+In summary, the gammatone filter is designed to provide a reasonable
+trade-off between accuracy in simulating basilar membrane motion, and
+computational load.
+.RE
+.LP
+The motivation for adopting the transmission line filter is 
+as follows:
+.LP
+1. The outer hair cell circuit of the transmission line filter is
+level dependent and so this design produces level-dependent basilar
+membrane tuning curves (Giguere and Woodland, 1994). There is now
+ample evidence that the basilar membrane motion is indeed highly
+nonlinear and a major source of level compression (eg. Johnstone et
+al., 1986).
+.LP
+2. The internal structure of the transmission line filter model is
+based on the physics of the auditory periphery and therefore provides
+a more realistic cochlear simulation than parallel filterbanks. It
+generates combination tones of the form 2f1-f2 as observed in the
+auditory system and it has the potential to generate cochlear echoes.
+.LP
+3. The wave-digital-filter implementation of the transmission line
+filterbank is only about twice as slow as the gammatone filterbank
+for an equivalent number of channels.
+.RE
+.LP
+.SH "Phase Alignment"
+.LP
+There is no question that the output of the cochlea has a phase lag
+corresponding to the strong rightward skew. However, perceptual
+evidence indicates that this phase lag has to be enormous (> 4ms) to
+affect what we hear; indeed, reversing the phase lag with synthetic
+stimuli does not change what we hear (Patterson, 1987).  Phase
+information that appears in the basilar membrane motion but which we
+do not hear, is removed in the third module by the strobe mechanism of
+the temporal integration process. As a result, the stabilised auditory
+images are always phase aligned even though the basilar membrane
+motion and the neural activity patterns are not.
+.RE
+.LP
+Prior to discovering the integration mechanism, we wanted to find 
+a way of reducing the skew from the basilar membrane image, in 
+order to provide a visual representation that was more like what 
+we hear. The genbmm program provides the following options for 
+phase aligning the responses of successive filters, determined 
+by the value of the option phase_gtf:
+.RE
+.LP
+Value Effect
+.PP
+.TP 7
+-1
+Envelope alignment. 
+.RS
+Shift the channels of output horizontally so that the points of 
+maximum response to an impulse (ie the envelope maxima) will be aligned. 
+.RE
+.TP 7
+-2
+Envelope plus fine structure alignment. 
+.RS
+Perform envelope-peak alignment as in option -1 and then shift the 
+fine structure phase in each channel so that a fine- structure peak 
+coincides with the envelope peak. 
+.RE
+.TP 7
+-4
+Envelope plus peak alignment, `left justified'. 
+.RS
+Align the envelopes and fine structure of all of the impulse responses 
+along the left edge of the image. 
+.RE
+.TP 6
+0
+No phase compensation. 
+.TP 7
++n
+Advance each channel by n cycles of the centre frequency of the channel. 
+Approximate envelope alignment is achieved using phase_gtf = 3 
+or 4.
+.RE
+.LP
+We experimented with a number of phase compensation schemes 
+(Patterson et al., 1989) and concluded that the best option was 
+envelope plus peak alignment which corresponds to a value of 
+phase_gtf = -4. Accordingly, we recommend the use of phase_gtf 
+values of 0 (ie no phase compensation) or -4 (envelope plus peak 
+alignment). The remaining options are occasionally useful and so 
+they have been left in the software.
+Note that for any phase compensation option other than 0 the time 
+scale is strictly correct only for the lowest channel. For any 
+other channel, the origin of the abscissa is offset to the right 
+by an amount equal to the difference between `the envelope peak 
+time of the lowest-frequency channel' and `the envelope peak time 
+of the given channel'.
+.RE
+.LP
+.SH REFERENCES
+.LP
+.RE
+.TP 4
+de Boer, E., and de Jongh, H.R. (1978). On cochlear encoding:
+potentialities and limitations of the reverse-correlation
+technique, J. Acoust. Soc. Am., 63, 115-135.
+.RE
+.LP
+.TP 4
+Carney, L.H. and Yin, C.T. (1988) 'Temporal coding of resonances
+by low-frequency auditory nerve fibers: Single fibre responses
+and a population model', J.Neurophysiology, 60, 1653-1677.
+.RE
+.LP
+.TP 4
+Cooke, M.P. (1993). Modelling Auditory Processing and
+Organisation, Cambridge University Press.
+.RE
+.LP
+.TP 4
+Giguere, C. and Woodland, P.C. (1994). A computational model of
+the auditory periphery for speech and hearing research. I. Ascending
+path. J.Acoust. Soc. Am. 95: 331-342.
+.RE
+.LP
+.TP 4
+Glasberg, B.R. and B.C.J. Moore (1990). Derivation of auditory
+filter shapes from notched-noise data. Hearing Research, 47,
+103-138.
+.RE
+.LP
+.TP 4
+Greenwood, D.D. (1961)  'Critical bandwidth and the frequency
+coordinates of the basilar membrane', J. Acoust. Soc. Am. 33,
+1344-1356.
+.RE
+.LP
+.TP 4
+Greenwood, D.D. (1990). A cochlear frequency-position function
+for several species - 29 years later. J. Acoust. Soc. Am., 87,
+2592-2605.
+.RE
+.LP
+.TP 4
+Holdsworth, J., Nimmo-Smith, I., Patterson, R.D. and Rice, P.
+(1988) Annex C of 'Spiral Vos Final Report, Part A: The
+Auditory Filterbank,' APU report  2341.
+.RE
+.LP
+.TP 4
+Johnstone, B.M. et al. (1986). Hear Res. 22: 147-153.
+.RE
+.LP
+.TP 4
+Moore, B.C.J and Glasberg, B.R. (1983), "Suggested formulae for
+calculating auditory filter bandwidths and excitiation patterns,"
+J. Acoust. Soc. Am. 74, pp 750-753.
+.RE
+.LP
+.TP 4
+Patuzzi, R., and Robertson, D. (1988) "Tuning in the mammalian
+cochlea," Physiological Reviews 68, 1009-1082.
+.RE
+.LP
+.TP 4
+Patterson, R.D. (1976). Auditory filter shapes derived with
+noise stimuli. J. Acoust. Soc. Am., 59, 640-654.
+.RE
+.LP
+.TP 4
+Patterson, R.D. (1987). A pulse ribbon model of monaural phase
+perception. J. Acoust. Soc. Am., 82, 1560-1586.
+.RE
+.LP
+.TP 4
+Patterson, R.D., Nimmo-Smith, I., Weber, D.L., and Milroy, R.
+(1982).  The deterioration of hearing with age:  Frequency
+selectivity, the critical ratio, the audiogram, and speech
+threshold.  J. Acoust. Soc. Am., 72, 1788-1803.
+.RE
+.LP
+.TP 4
+Patterson, R.D., Allerhand, M.H. and Holdsworth, J. (1992)
+'Auditory representations of speech sounds', In Visual
+representations of speech signals, Eds. Martin Cooke and Steve
+Beet, John Wiley & Sons. 307-314.
+.RE
+.LP
+.TP 4
+Patterson, R. D., Holdsworth, J., Nimmo-Smith, I., and Rice, P.
+(1988). SVOS Final Report: The Auditory Filterbank. APU report 2341.
+.RE
+.LP
+.TP 4
+Patterson, R.D. and B.C.J. Moore (1986). Auditory filters and
+excitation patterns as representations of frequency
+resolution. In: Frequency Selectivity in Hearing (B. C. J.
+Moore, ed.), pp. 123-177. Academic Press, London.
+.RE
+.LP
+.TP 4
+Schofield, D. (1985) 'Visualisations of speech based on a model
+of the peripheral auditory system', NPL Report DITC 62/85.
+.RE
+.LP
+.TP 4
+Slaney, M. (1993) An efficient implementation of the Patterson-
+Holdsworth auditory filter bank. Apple Computer Technical
+Report #35.
+.RE
+.LP
+.TP 4
+Zwicker, E. (1961) Subdivision of the audible frequency range into
+critical bands (frequenzgruppen).  J. Acoust. Soc. Am.  33, 248.
+.LP
+.SH EXAMPLES
+.LP
+The following command generates basilar membrane motion using the
+gammatone filter design (the default) for an input filename cegc:
+.RE
+.LP
+example% genbmm cegc
+.RE
+.LP
+The following command generates basilar membrane motion using the
+gammatone filter design (the default) for a filterbank with cf from
+200 Hz to 5000 Hz at a density of 4 filters/critical band for the same
+input filename:
+.RE
+.LP
+example% genbmm channels=0 mincf=200 maxcf=5000 dencf=4. cegc
+.RE
+.LP
+The following command generates basilar membrane motion using the
+gammatone filter design (the default) and the audiogram function
+instead of the outer/middle ear filter:
+.RE
+.LP
+example% genbmm middle_ear=off audiogram=on cegc
+.RE
+.LP
+The following command generates the basilar membrane motion using the
+transmission line filter design instead of the default gammatone
+filter:
+.RE
+.LP
+example% genbmm filter=tlf cegc
+.RE
+.LP
+The following command generates the basilar membrane motion using the
+transmission line filter design and the auditory scale of Greenwood
+(1990):
+.RE
+.LP
+example% genbmm filter=tlf bwmin=22.85 quality=7.238 mmerb=1.0 cegc
+.RE
+.LP
+The following command generates the basilar membrane motion using the
+transmission line filter design, but with the nonlinear outer hair
+cell feedback mechanism turned off:
+.RE
+.LP
+example% genbmm filter=tlf feedback=off cegc
+.LP
+.SH FILES
+.LP
+.TP 13
+ .genbmmrc 
+The options file for genbmm.
+.LP
+.SH SEE ALSO
+.LP
+genasa, gensgm
+.LP
+.SH BUGS
+.LP
+There is a bug in the hiddenline plotting of genbmm. It shows up when
+the surface has deep valleys and there is a large phase delay. The
+negative peaks show through on surfaces where they should be hidden.
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+.LP
+.SH ACKNOWLEDGEMENTS
+.LP
+The AIM software was developed for Unix workstations by John
+Holdsworth and Mike Allerhand of the MRC APU, under the direction of
+Roy Patterson. The physiological version of AIM was developed by
+Christian Giguere. The options handler is by Paul Manson. The revised
+SAI module is by Jay Datta. Michael Akeroyd extended the postscript
+facilites and developed the xreview routine for auditory image
+cartoons.
+.LP
+The project was supported by the MRC and grants from the U.K. Defense
+Research Agency, Farnborough (Research Contract 2239); the EEC Esprit
+BR Porgramme, Project ACTS (3207); and the U.K. Hearing Research Trust.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/gencgm.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,201 @@
+.TH GENCGM 1 "11 May 1995" 
+.LP 
+.SH NAME 
+.LP 
+gencgm \- generate a cochleogram 
+.LP 
+.SH SYNOPSIS 
+.LP 
+gencgm [ option=value | -option ] [ filename ] 
+.LP 
+.SH DESCRIPTION 
+.LP
+
+Gencgm converts the input wave into a simulated neural activity
+pattern (NAP) and summarises the NAP as a sequence of excitation
+patterns (EPNs) that collectively form a 'cochleogram' (CGM). The
+operation takes place in three stages: spectral analysis, neural
+encoding, and temporal integration. In the spectral analysis stage,
+the input wave is converted into an array of filtered waves, one for
+each channel of a gammatone auditory filterbank. The surface of the
+array of filtered waves is AIM's representation of basilar membrane
+motion (BMM) as a function of time (manaim genbmm). In the neural
+encoding stage, compression, adaptation and suppression, are used to
+convert each wave from the filterbank into a simulation of the
+aggregate neural response to that wave. The array of responses is
+AIM's simulation of the neural activity pattern (NAP) in the auditory
+nerve at about the level of the cochlear nucleus (manaim gennap).
+Finally, the NAP is converted into a sequence of excitation patterns
+(EPNs) by calculating the envelope of the NAP and extracting spectral
+slices from the envelope every 'frstep_epn' ms. The envelope is
+calculated continuously, by lowpass filtering the individual channels
+of the NAP as they flow from the cochlea simulation.  
+.LP
+When the sequence of excitation patterns is presented in spectrogram
+format, it is referred to as a 'cochleogram' (CGM). The spectrogram
+format has time on the abscissa (x-axis), filter centre-frequency on
+the ordinate (y-axis), and activity level as the degree of black in
+the display.  In AIM, the suffix 'cgm' is used to distinguish this
+spectral representation from the other spectral representations
+provided by the software ('asa' auditory spectral analysis, 'sgm'
+auditory spectrogram, and 'epn' excitation pattern).
+.LP 
+The NAP generated by gencgm is the same as that produced by gennap
+(manaim gennap).  The primary differences are in the display defaults
+and the inclusion of the Leaky Integration used to construct the
+excitation patterns that form the cochleogram.  As a result, this
+manual entry is restricted to describing the option values that differ
+from those in gennap and the additional options required to control
+the Leaky Integration.
+.LP
+.SH DISPLAY DEFAULTS
+.LP
+The default values for three of the display options are reset to
+produce a spectrographic format rather than a landscape. Specifically,
+display=greyscale, bottom=0 and top=2500. The number of channels is
+set to 128 for compatibility with the auditory spectrum modules,
+genasa and genepn.  When using AIM as a preprocessor for speech
+recognition the number of channels would typically be reduced to
+between 24 and 32.  Use option 'downsample' if it is necessary to
+reduce the output to less than 24 channels across the speech range.
+.LP
+.SH COMPRESSION AND LEAKY INTEGRATION
+.LP
+Compression and lowpass filtering are activated after the neural
+encoding stage:
+.LP
+.SS "Compression"
+.PP
+Cochleograms are usually produced via the functional route in AIM. In
+this case, compress is set on
+.LP
+.TP 13
+compress
+Logarithmic compressor switch
+.RS
+Switch. Default: on.
+.RE
+.RS
+.LP
+Note: The compressor in the functional route of AIM is logarithmic and
+it screens out negative BMM values before compression. This rectifies
+the wave during the compression process and so the separate rectify
+option is left off. 
+.RE
+.LP
+.RS
+.LP
+Note: The compressor in the physiological route of AIM is an integral
+part of the tlf module, so when using this route to produce a
+cochleogram, turn off the logarithmic compressor
+(i.e. compress=off). The compressor in tlf does not screen out
+negative values so it is also important to set rectify=on.
+.RE
+.RS
+.LP
+Full wave rectification is produced if rectify is set to 2. This will
+lead to a smoother cochleogram from both the physiological and the
+functional versions of AIM.
+.RE
+.LP
+.SS "Transduction"
+.PP
+.LP
+.TP 13
+transduction
+Neural transduction switch (at, meddis, off)
+.RS
+Switch. Default: at.
+
+.RE
+.LP
+.SS "Leaky Integration"
+.PP
+.LP
+.TP 13
+stages_idt
+Number of stages of lowpass filtering
+.RS
+Default unit: scalar. Default value: 2
+.RE
+.TP 13
+tup_idt
+The time constant for each filter stage
+.RS
+Default unit: ms. Default value: 8 ms.
+.RE
+.LP 
+The Equivalent Rectandular Duration (ERD) of a two stage lowpass
+filter is about 1.6 times the time constant of each stage, or
+12.8 ms in the current case.
+.TP 13
+frstep_epn
+The time between successive spectral frames
+.RS
+Default unit: ms. Default value: 10 ms.
+.RE
+.LP
+With a frstep_epn of 10 ms, gencgm will produce spectral frames at a
+rate of 100 per second.
+.LP
+.TP 13
+downsample
+The time between successive spectral frames. 
+.RS
+Default unit: ms. Default value: 10 ms.
+.RE
+.LP
+Downsample is simply another name for frstep_epn, provided to
+facilitate a different mode of thinking about time-series data.
+.LP
+.SH FILES
+.LP
+.TP 13
+.gencgmrc 
+The options file for gencgm.
+.LP
+.SH SEE ALSO
+.LP
+gensgm, genasa, genepn, gennap, genbmm
+.LP
+.SH BUGS
+.LP
+None currently known.
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+.LP
+.SH ACKNOWLEDGEMENTS
+.LP
+The AIM software was developed for Unix workstations by John
+Holdsworth and Mike Allerhand of the MRC APU, under the direction of
+Roy Patterson. The physiological version of AIM was developed by
+Christian Giguere. The options handler is by Paul Manson. The revised
+SAI module is by Jay Datta. Michael Akeroyd extended the postscript
+facilites and developed the xreview routine for auditory image
+cartoons.
+.LP
+The project was supported by the MRC and grants from the U.K. Defense
+Research Agency, Farnborough (Research Contract 2239); the EEC Esprit
+BR Porgramme, Project ACTS (3207); and the U.K. Hearing Research Trust.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/genepn.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,148 @@
+.TH GENEPN 1 "11 May 1995" 
+.LP 
+.SH NAME 
+.LP 
+genepn \- generate excitation pattern 
+.LP 
+.SH SYNOPSIS 
+.LP 
+genepn [ option=value | -option ] [ filename ] 
+.LP 
+.SH DESCRIPTION 
+.LP
+Genepn converts the input wave into a simulated neural activity
+pattern (NAP) and summarises the NAP as a sequence of excitation
+patterns (EPNs). The operation takes place in three stages: spectral
+analysis, neural encoding, and temporal integration. In the spectral
+analysis stage, the input wave is converted into an array of filtered
+waves, one for each channel of a gammatone auditory filterbank. The
+surface of the array of filtered waves is AIM's representation of
+basilar membrane motion (BMM) as a function of time (see genbmm). In
+the neural encoding stage, compression, adaptation and, optionally,
+suppression, are used to convert each wave from the filterbank into a
+simulation of the aggregate neural response to that wave. The array of
+responses is AIM's simulation of the neural activity pattern (NAP) in
+the auditory nerve at about the level of the cochlear nucleus (see
+gennap). Finally, the NAP is converted into a sequence of excitation
+patterns (EPNs) by calculating the envelope of the NAP and extracting
+spectral slices from the envelope every 'frstep_epn' ms. The envelope
+is calculated continuously, by lowpass filtering the individual
+channels of the NAP as they flow from the cochlea simulation.
+.LP 
+The excitation pattern produced by genepn is intended to simulate the
+spectral representation of a sound as it occurs in the peripheral
+auditory system after neural transduction at about the level of the
+cochlea nucleus.  As a result, the frequency resolution of the
+analysis varies with the center frequency of the channel, and the
+distribution of channels across frequency is chosen to match that in
+the auditory system. (For details, see the manual entry for genbmm.)
+The excitaion pattern is a plot of the activity in each channel as a
+function of the centre frequency of the auditory filter that defines
+the channel. In AIM, the suffix 'epn' is used to distinguish this
+spectral representation from the other spectral representations
+provided by the software ('asa' auditory spectral analysis, 'sgm'
+auditory spectrogram, and 'cgm' cochleogram).
+.LP 
+The NAP generated by genepn is the same as that produced by gennap.
+The primary differences are in the display defaults and the inclusion
+of the Leaky Integration used to construct the excitation patterns
+from the NAP.  As a result, this manual entry is restricted to
+describing the option values that differ from those in gennap and the
+additional options required to control the Leaky Integration.
+.LP
+.SH DISPLAY DEFAULTS
+.LP
+The default values for three of the display options are reset to
+produce a spectral format rather than a landscape.  Specifically,
+display=excitation, bottom=0 and top=2500. The number of channels is
+increased to 128 to ensure reasonable frequency resolution in the
+excitation pattern display. 
+.LP
+.SH LEAKY INTEGRATION
+.LP
+.TP 13
+stages_idt
+Number of stages of lowpass filtering
+.RS
+Default unit: scalar. Default value: 2
+.RE
+.TP 13
+tup_idt
+The time constant for each filter stage
+.RS
+Default unit: ms. Default value: 8 ms.
+.RE
+.LP
+The Equivalent Rectandular Duration (ERD) of a two stage lowpass
+filter is about 1.6 times the time constant of each stage, or
+12.8 ms in the current case.
+.TP 13
+frstep_epn
+The time between successive spectral frames
+.RS
+Default unit: ms. Default value: 10 ms.
+.RE
+.LP
+With a frstep_epn of 10 ms, genepn will produce
+spectral frames at a rate of 100 per second. 
+.LP
+.TP 13
+downsample
+The time between successive spectral frames. 
+.RS
+Default unit: ms. Default value: 10 ms.
+.RE
+.LP
+Downsample is simply another name for frstep_epn, provided to
+facilitate a different mode of thinking about time-series data.
+.RE
+.LP
+.LP
+.SH FILES
+.LP
+.TP 13
+.genepnrc 
+The options file for genepn.
+.LP
+.SH SEE ALSO
+.LP
+genasa, gennap, genbmm, gensgm, gencgm
+.LP
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+.LP
+.SH ACKNOWLEDGEMENTS
+.LP
+The AIM software was developed for Unix workstations by John
+Holdsworth and Mike Allerhand of the MRC APU, under the direction of
+Roy Patterson. The physiological version of AIM was developed by
+Christian Giguere. The options handler is by Paul Manson. The revised
+SAI module is by Jay Datta. Michael Akeroyd extended the postscript
+facilites and developed the xreview routine for auditory image
+cartoons.
+.LP
+The project was supported by the MRC and grants from the U.K. Defense
+Research Agency, Farnborough (Research Contract 2239); the EEC Esprit
+BR Porgramme, Project ACTS (3207); and the U.K. Hearing Research Trust.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/gennap.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,405 @@
+.TH GENNAP 1 "8 April 1994"
+.LP
+.SH NAME
+.LP
+gennap \- generate neural activity pattern
+.LP
+.SH SYNOPSIS
+.LP
+gennap [ option=value | -option ] [ filename ]
+.LP
+.SH DESCRIPTION
+.LP
+The gennap module of the AIM software converts an input wave into a
+simulated neural activity pattern (NAP), which is AIM's representation
+of the pattern of information in the auditory nerve at about the level
+of the cochlear nucleus.  Gennap begins by calculating the basilar
+membrane motion (BMM) associated with the input wave using the genbmm
+module, and then it applies several additional transforms that we know
+occur in some form during the neural transduction process.  AIM
+provides two alternative methods for generating the NAP, a
+two-dimensional adaptive thresholding mechanism (Holdsworth and
+Patterson, 1993), and an array of inner haircell simulators based
+(Meddis et al., 1990; Giguere and Woodland, 1994).  The adaptive
+thresholding mechanism applies rectification, log compression,
+adaptation in time, and suppression across frequency; its purpose is
+to stabilise the level of the membrane activity with compression and
+then sharpen the features that appear in the compressed membrane
+motion.  Together, the gammatone filterbank and adaptive thresholding
+form a 'functional' cochlea simulation.  The Meddis module applies
+level-dependant compression and adaptation that simulate the response
+of inner haircells to membrane motion.  The cells are not coupled and
+so there is no frequency sharpening in this module.  Together, the
+transmission-line filterbank and the Meddis module form a
+'physiological' cochlea simulation.
+.LP
+.SH OPTIONS
+.LP
+The options for gennap are grouped according to the functions they
+control. The adaptive thresholding options are identified by the
+common suffix _at; the Meddis module options are identified by the
+common suffix _med.  These two groups of options are the subject of
+this manual entry, together with two additional options that specify
+whether rectification and compression operations are required before
+the transduction stage.  There is also an option to specify the choice
+of the transduction function.
+.LP
+.SH  RECTIFICATION AND COMPRESSION
+.LP
+The adaptive thresholding process begins with rectification and log
+compression of the BMM.  It is occasionally useful to have these
+functions available separately and so the options 'rectify' and
+'compress' are presented separately in the options list before the
+neural transduction options.
+.RE
+.LP
+.TP 13
+rectify
+Rectification switch
+.RS
+Switch. Default value: off. 
+.RE
+.RS
+.LP
+If rectify is on, the BMM is half-wave rectified.
+The compression operation also performs half-wave rectification (to
+avoid taking logs of negative numbers).  So the rectify option is
+really here just to provide for rectified BMM in the absence of
+compression.  As a result, the default for option rectify is
+off. (Note: Full wave rectification is produced if rectify is set to
+2.  This is useful when calculating envelopes with genasa.)
+.RE
+.LP
+.TP 13
+compress
+Compression switch
+.RS
+Switch. Default value: on. 
+.RE
+.RS
+.LP
+The compressor is strictly logarithmic and so to this point, the
+functional cochlea simulation is level independent.  In the auditory
+system, the compressor is logarithmic over the lower part of its range
+and then it asymptotes to a soft limit. The default for option
+compress is on (note that the compressor also performs half-wave
+rectification).
+.RE
+.LP
+Important: The default value for option compress is 'on' which assumes
+that the transduction module is adaptive thresholding (the default for
+the transduction option described below).  If the Meddis transduction
+module is selected (transduction=med), compress should be set to 'off'
+to obtain the operation described in Giguerre and Woodland
+(1994). This can be done on the command line (see EXAMPLES) or in the
+appropriate .gen???rc files.
+.RE
+.LP
+.SH NEURAL TRANSDUCTION
+.LP
+The neural transduction is performed either by two-dimensional
+adaptive thresholding or an array of Meddis haircells. The choice is
+controlled by the option 'transduction'.
+.LP
+.TP 13
+transduction
+The transduction function
+.RS
+Switch. Default value: at. Choices: at, med, off.
+.RE
+.LP
+If adaptive thresholding is specified (at), the options with suffix
+_at below apply; if the Meddis module is specified (med), the options
+with suffix _med below apply. If off is specified, no transduction
+function is applied.  The default is at.
+.RE
+.LP
+.SS "Two-dimensional adaptive thresholding: _at "
+.PP
+The adaptive thresholding mechanism is a functional model of neural
+encoding. Its purpose is to enhance the contrast of the larger
+features that appear in the surface of the BMM and reduce those
+aspects of the representation which are just a direct consequence of
+the filtering and compression processes (Holdsworth and Patterson,
+1993).  The process begins with rectification and compression of the
+BMM.  The tail of the envelope of the impulse response of the
+gammatone filter is exponential. As a result, logarithmic compression
+is used, since this makes the filter decay function linear in NAP
+coordinates. Following compression, adaptation is applied in time and
+suppression is applied across frequency.
+.LP
+Briefly, an adaptive threshold value is maintained for each channel
+and updated at the sampling rate. The new value is the largest of a)
+the previous value reduced by a fast-acting temporal decay factor
+(t1recovery_at), b) the previous value reduced by a longer-term
+temporal decay factor (t2recovery_at), c) the adapted level in the
+channel immediately above, reduced by a frequency spread factor
+(frecovery_at), d) the adapted level in the channel immediately below,
+reduced by the same frequency spread factor, or e) a floor level that
+precludes the mechanism listening to its own internal noise
+(reclimit_at).  The mechanism produces output whenever the input
+exceeds the adaptive threshold, and the output level is the difference
+between the input and the adaptive threshold. The adaptation and
+suppression are coupled, and they jointly sharpen features like vowel
+formants which appear smeared in compressed BMM.
+.LP
+.TP 13
+trise_at
+Threshold rise rate 
+.RS
+Default value: 1000. 
+.RE
+.RS
+.LP
+Upward Adaptation: This option specifies the rate at which the
+adaptive threshold will rise in response to a rise in signal
+level. The default value, 1000, means that the adaptive threshold
+responds very quickly to increases in the input wave; essentially, it
+follows the envelope of any rise in signal amplitude.
+.RE
+.LP
+Downward Adaptation: Following the cessation of sound, or a rapid drop
+in input level, temporal adaptation occurs in two stages as determined
+by t1recovery_at, t2recovery_at and propt2t1_at: If the default values
+are used, the mechanism initially adapts at a rate slightly slower
+than the decay rate of the gammatone filter in the given channel, and
+this represses much of the ringing of the impulse response of the
+filter.  Later the adaptation switches to a slower rate more in line
+with data on auditory forward masking.  The option propt2t1_at
+determines the point at which the initial fast rate of decay gives way
+to the slower limiting decay rate.
+.RE
+.LP
+.TP 13
+t1recovery_at
+The initial rate of threshold recovery relative to filter decay rate 
+.RS
+Default value: 0.6. 
+.RE
+.RS
+.LP
+This option determines the initial rate of decay of the adaptive
+threshold relative to the rate of decay of the auditory filter,
+provided propt2t1_at is less than unity.  Values of t1recovery_at less
+than unity cause the adaptive threshold to decay more slowly than the
+auditory filter and thereby to remove the filter response from the
+representation when it is the sole reason for BMM activity.  The rate
+of decay is linear with respect to the log-compressed BMM, so it is
+like an exponential decay with respect to the BMM.
+.RE
+.LP
+.TP 13
+t2recovery_at
+The secondary threshold recovery rate
+.RS
+Default value: 0.2. 
+.RE
+.RS
+.LP
+This option determines the limiting rate of decay of the adaptive
+threshold when the sound ceases provided propt2t1_at is less than
+unity.  The default value causes the adaptive threshold to decay more
+slowly than the initial rate as observed in auditory forward masking.
+Note, however, that the system to this point is level independent,
+whereas auditory forward masking is level dependent.
+.RE
+.LP
+.TP 13
+propt2t1_at
+The point at which t1recovery_at gives way to t2_recovery_at
+.RS
+Default value: 0.5. 
+.RE
+.RS
+.LP
+This option determines the point at which the initial fast rate of
+decay (t1recovery_at) gives way to the slower limiting decay rate
+(t2recovery_at).  The nomanclature assumes that propt2t1_at is a value
+less than unity.  Otherwise the the roles of the initial and limiting
+decays are reversed.
+.RE
+.LP
+.TP 13
+frecovery_at
+Recovery rate across frequency 
+.RS
+Default value: 20. 
+.RE
+.RS
+.LP
+This parameter specifies the rate at which a threshold value in one channel 
+propagates to influence threshold in neighbouring channels. 
+.RE
+.LP
+.TP 13
+reclimit_at
+Limitation on recovery level 
+.RS
+Default units: mB. Default value: 500 mB. (mB=milliBells)
+.RE
+.RS
+.LP
+In order to prevent the mechanism from encountering system noise, 
+or alternately, to reduce sensitivity to stimulus noise, there is a 
+limit placed on the recovery that the adaptive threshold can achieve. 
+The limit, reclimit_at, is the limit of the sensitivity of the system. 
+.RE
+.LP
+.TP 13
+gain_at
+Output gain 
+.RS
+Default units: scalar. Default value: 1. 
+.RE
+.LP
+.SS "Meddis haircell model: _med "
+.PP
+The purpose of the Meddis module is to simulate neural transduction of
+BMM as performed by the inner haircells of the cochlea.  There is one
+haircell simulation unit for each output channel of the filterbank.
+The haircell equations (Meddis et al., 1990) are solved using the wave
+digital filter algorithm described in Giguere and Woodland (1994). The
+characteristics of the haircell are controlled by options: fiber_med,
+thresh_med, and gain_med.
+.LP
+.TP 13
+fiber_med
+The spontaneous-rate of the simulated fiber
+.RS
+Default value: medium. Choices: medium, high.
+.RE
+.RS
+.LP
+If medium is specified, a medium spontaneous-rate haircell fiber is
+simulated. If high is specified, a high spontaneous-rate 
+fiber is simulated. The properties of these two types of fibers 
+are listed in Table II in Meddis et al. (1990).
+The default value is medium.
+.RE
+.LP
+.TP 13
+thresh_med
+The threshold shift of the fiber
+.RS
+Default Units: dB. Default value: 0.   
+.RE
+.RS
+.LP
+This option shifts the entire rate-intensity function of the haircell
+fiber horizontally to a higher or lower level, to accomodate changes
+in the scaling of the input wave.  A positive (negative) value
+increases (decreases) the rate- and saturation-thresholds of the fiber
+by that amount.  This operation does not change the dynamic range, the
+spontaneous and saturation rates, or the adaptation time constants or
+synchronization index of the fiber.
+.RE
+.LP
+.TP 13
+gain_med
+Output gain 
+.RS
+Default units: scalar. Default value: 1. 
+.RE
+.RS
+.LP
+Note: There is an internal gain of 20.0 within the software of
+the Meddis haircell model itself. The total gain is therefore
+20.0 times the value for gain_med.
+.RE
+.LP
+.SH REFERENCES
+.LP
+.RE
+.TP 4
+Giguere, C. and Woodland, P.C. (1994).  A computational model of
+the auditory periphery for speech and hearing research. I. Ascending
+path. J.Acoust. Soc. Am. 95: 331-342.
+.RE
+.LP
+.TP 4
+Holdsworth, J. (1990). Two-Dimensional adaptive thresholding.
+Annex 4 of AAM-HAP Report 1, APU contract Report.
+.RE
+.LP
+.TP 4
+Holdsworth, J. and Patterson, R.D. (1993). "Analysis of waveforms,"
+UK Patent GB 2234078B.
+.LP
+.TP 4
+Meddis, R., Hewitt, M. and Shackleton, T. (1990). Implementation
+details of a computational model of the inner-haircell/auditory-nerve
+synapse. J.Acoust. Soc. Am. 87: 1813-1816.
+.RE
+.LP
+.SH EXAMPLES
+.LP
+The following command generates the neural activity pattern using the
+gammatone auditory filterbank (the default) and the adaptive
+thresholding (the default) for an input file named cegc:
+.RE
+.LP
+example% gennap cegc
+.RE
+.LP
+The following command generates the neural activity pattern using the
+gammatone filterbank (the default) and Meddis haircell
+transduction for input cegc:
+.RE
+.LP
+example% gennap compress=off transduction=meddis cegc
+.RE
+.LP
+The following command generates the neural activity pattern using the
+transmission line filterbank and Meddis haircell transduction for cegc:
+.RE
+.LP
+example% gennap filter=tlf compress=off transduction=meddis cegc
+.LP
+.SH FILES
+.LP
+.TP 13
+ .gennaprc 
+The options file for gennap.
+.LP
+.SH SEE ALSO
+.LP
+genepn, gencgm, genbmm
+.LP
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+.LP
+.SH ACKNOWLEDGEMENTS
+.LP
+The AIM software was developed for Unix workstations by John
+Holdsworth and Mike Allerhand of the MRC APU, under the direction of
+Roy Patterson. The physiological version of AIM was developed by
+Christian Giguere. The options handler is by Paul Manson. The revised
+SAI module is by Jay Datta. Michael Akeroyd extended the postscript
+facilites and developed the xreview routine for auditory image
+cartoons.
+.LP
+The project was supported by the MRC and grants from the U.K. Defense
+Research Agency, Farnborough (Research Contract 2239); the EEC Esprit
+BR Porgramme, Project ACTS (3207); and the U.K. Hearing Research Trust.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/gensai.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,643 @@
+.TH GENSAI 1 "26 May 1995"
+.LP
+.SH NAME
+.LP
+gensai \- generate stabilised auditory image
+.LP
+.SH SYNOPSIS/SYNTAX
+.LP
+gensai [ option=value  |  -option ]  filename
+.LP
+.SH DESCRIPTION
+.LP
+
+Periodic sounds give rise to static, rather than oscillating,
+perceptions indicating that temporal integration is applied to the NAP
+in the production of our initial perception of a sound -- our auditory
+image. Traditionally, auditory temporal integration is represented by
+a simple leaky integration process and AIM provides a bank of lowpass
+filters to enable the user to generate auditory spectra (Patterson,
+1994a) and auditory spectrograms (Patterson et al., 1992b). However,
+the leaky integrator removes the phase-locked fine structure observed
+in the NAP, and this conflicts with perceptual data indicating that
+the fine structure plays an important role in determining sound
+quality and source identification (Patterson, 1994b; Patterson and
+Akeroyd, 1995). As a result, AIM includes two modules which preserve
+much of the time-interval information in the NAP during temporal
+integration, and which produce a better representation of our auditory
+images. In the functional version of AIM, this is accomplished with
+strobed temporal integration (Patterson et al., 1992a,b), and this is
+the topic of this manual entry.
+
+.LP
+
+In the physiological version of AIM, the auditory image is constructed
+with a bank of autocorrelators (Slaney and Lyon, 1990; Meddis and
+Hewitt, 1991).  The autocorrelation module is an aimTool rather than
+an integral part of the main program 'gen'.  The appropriate tool is
+'acgram'.  Type 'manaim acgram' for the documentation. The module
+extracts periodicity information and preserves intra-period fine
+structure by autocorrelating each channel of the NAP separately. The
+correlogram is the multi-channel version of this process. It was
+originally introduced as a model of pitch perception (Licklider,
+1951). It is not yet known whether STI or autocorrelation is more
+realistic, or more efficient, as a means of simulating our perceived
+auditory images. At present, the purpose is to provide a software
+package that can be used to compare these auditory representations in
+a way not previously possible.
+
+.RE
+.LP
+.SH STROBED TEMPORAL INTEGRATION
+.PP  
+
+In strobed temporal integration, a bank of delay lines is used to form
+a buffer store for the NAP, one delay line per channel, and as the NAP
+proceeds along the buffer it decays linearly with time, at about 2.5
+%/ms. Each channel of the buffer is assigned a strobe unit which
+monitors activity in that channel looking for local maxima in the
+stream of NAP pulses. When one is found, the unit initiates temporal
+integration in that channel; that is, it transfers a copy of the NAP
+at that instant to the corresponding channel of an image buffer and
+adds it point-for-point with whatever is already there. The local
+maximum itself is mapped to the 0-ms point in the image buffer. The
+multi-channel version of this STI process is AIM's representation of
+our auditory image of a sound. Periodic and quasi-periodic sounds
+cause regular strobing which leads to simulated auditory images that
+are static, or nearly static, but with the same temporal resolution as
+the NAP.  Dynamic sounds are represented as a sequence of auditory
+image frames. If the rate of change in a sound is not too rapid, as is
+diphthongs, features are seen to move smoothly as the sound proceeds,
+much as objects move smoothly in animated cartoons.
+
+.LP
+It is important to emphasise, that the triggering done on a 
+channel by channel basis and that triggering is asynchronous 
+across channels, inasmuch as the major peaks in one channel occur 
+at different times from the major peaks in other channels.  It 
+is this aspect of the triggering process that causes the 
+alignment of the auditory image and which accounts for the loss 
+of phase information in the auditory system (Patterson, 1987).
+
+.LP
+
+The auditory image has the same vertical dimension as the neural
+activity pattern (filter centre frequency).  The continuous time
+dimension of the neural activity pattern becomes a local,
+time-interval dimension in the auditory image; specifically, it is
+"the time interval between a given pulse and the succeeding strobe
+pulse". In order to preserve the direction of asymmetry of features
+that appear in the NAP, the time-interval origin is plotted towards
+the right-hand edge of the image, with increasing, positive time
+intervals proceeding to towards the left.
+
+.LP
+.SH OPTIONS
+.LP
+.SS "Display options for the auditory image"
+.PP
+
+The options that control the positioning of the window in which the
+auditory image appears are the same as those used to set up the
+earlier windows, as are the options that control the level of the
+image within the display.  In addition, there are three new options
+that are required to present this new auditory representation. The
+options are frstep_aid, pwid_aid, and nwid_aid; the suffix "_aid"
+means "auditory image display". These options are described here
+before the options that control the image construction process itself,
+as they occur first in the options list. There are also three extra
+display options for presenting the auditory image in its spiral form;
+these options have the suffix "_spd" for "spiral display"; they are
+described in the manual entry for 'genspl'.
+
+.LP
+.TP 17
+frstep_aid
+The frame step interval, or the update interval for the auditory image display 
+.RS
+Default units:  ms. Default value:  16 ms. 
+.RE
+.RS
+
+Conceptually, the auditory image exists continuously in time.  The
+simulation of the image produced by AIM is not continuous; rather it
+is like an animated cartoon. Frames of the cartoon are calculated at
+discrete points in time, and then the sequence of frames is replayed
+to reveal the dynamics of the sound, or the lack of dynamics in the
+case of periodic sounds.  When the sound is changing at a rate where
+we hear smooth glides, the structures in the simulated auditory image
+move much like objects in a cartoon.  frstep_aid determines the time
+interval between frames of the auditory image cartoon. Frames are
+calculated at time zero and integer multiples of segment_sai.
+
+.RE
+
+The default value (16 ms) is reasonable for musical sounds and speech
+sounds.  For a detailed examination of the development of the image of
+brief transient sounds frstep_aid should be decreased to 4 or even 2
+ms.
+.LP
+.TP 16
+pwidth_sai
+
+The maximum positive time interval presented in the display of the
+auditory image (to the left of 0 ms).
+
+.RS
+Default units:  ms. Default value: 35 ms. 
+.RE
+.LP
+.TP 16
+nwidth_sai
+
+The maximum negative time interval presented in the display of the
+auditory image (to the right of 0 ms).
+
+.RS
+Default units:  ms. Default value: -5 ms. 
+.RE
+
+.LP
+.TP 12
+animate
+Present the frames of the simulated auditory image as a cartoon. 
+.RS
+Switch. Default off. 
+.RE
+.RS
+
+With reasonable resolution and a reasonable frame rate, the auditory
+cartoon for a second of sound will require on the order of 1 Mbyte of
+storage. As a result, auditory cartoons are only stored at the
+specific request of the user.  When the animate flag is set to `on',
+the bit maps that constitute the frames the auditory cartoon are
+stored in computer memory. They can then be replayed as an auditory
+cartoon by pressing `carriage return'. To exit the instruction, type
+"q" for `quit' or "control c". The bit maps are discarded unless
+option bitmap=on.
+
+.RE
+.LP
+.SS "Storage options for the auditory image "
+.PP
+
+A record of the auditory image can be stored in two ways depending on
+the purpose for which it is stored.  The actual numerical values of
+the auditory image can be stored as previously, by setting output=on.
+In this case, a file with a .sai suffix will be created in accordance
+with the conventions of the software.  These values can be recalled
+for further processing with the aimTools.  In this regard the SAI
+module is like any previous module.
+
+.LP
+It is also possible to store the bit maps which are displayed on 
+the screen for the auditory image cartoon.  The bit maps require 
+less storage space and reload more quickly, so this is the 
+preferred mode of storage when one simply wants to review the 
+visual image.  
+.LP
+.TP 10
+bitmap
+Produce a bit-map storage file 
+.RS
+Switch. Default value: off. 
+.RE
+.RS
+
+When the bitmap option is set to `on', the bit maps are stored in a
+file with the suffix .ctn. The bitmaps are reloaded into memory using
+the commands review, or xreview, followed by the file name without the
+suffix .ctn. The auditory image can then be replayed, as with animate,
+by typing `carriage return'. xreview is the newer and preferred
+display routine. It enables the user to select subsets of the cartoon
+and to change the rate of play via a convenient control window.
+
+
+
+.LP
+The strobe mechanism is relatively simple.  A trigger threshold 
+value is maintained for each channel and when a NAP pulse exceeds 
+the threshold a trigger pulse is generated at the time associated 
+with the maximum of the peak.  The threshold value is then reset 
+to a value somewhat above the height of the current NAP peak and 
+the threshold value decays exponentially with time thereafter.
+
+
+
+There are six options with the suffix "_ai", short for
+'auditory image'. Four of these control STI itself -- stdecay_ai,
+stcrit_ai, stthresh_ai and decay_ai. The option stinfo_ai is a switch
+that causes the software to produce information about the current STI
+analysis for demonstration or diagnostic purposes.  The final option,
+napdecay_ai controls the decay rate for the NAP while it flows down
+the NAP buffer. 
+
+.LP
+.TP 17
+napdecay_ai
+Decay rate for the neural activity pattern (NAP)
+.RS
+Default units: %/ms. Default value 2.5 %/ms. 
+.RE
+.RS
+
+napdecay_ai determines the rate at which the information in the neural
+activity pattern decays as it proceeds along the auditory buffer that
+stores the NAP prior to temporal integration.
+.RE
+
+
+.LP
+.TP 16
+stdecay_ai
+Strobe threshold decay rate 
+.RS
+Default units: %/ms. Default value:  5 %/ms. 
+.RE
+.RS
+stdecay_sai determines the rate at which the strobe threshold decays. 
+.RE
+.LP
+General purpose pitch mechanisms based on peak picking are 
+notoriously difficult to design, and the trigger mechanism just 
+described would not work well on an arbitrary acoustic waveform.  
+The reason that this simple trigger mechanism is sufficient for 
+the construction of the auditory image is that NAP functions are 
+highly constrained.  The microstructure reveals a function that 
+rises from zero to a local maximum smoothly and returns smoothly 
+back to zero where it stays for more than half of a period of the 
+centre frequency of that channel.  On the longer time scale, the 
+amplitude of successive peaks changes only relatively slowly with 
+respect to time.  As a result, for periodic sounds there tends 
+to be one clear maximum per period in all but the lowest channels 
+where there is an integer number of maxima per period.  The 
+simplicity of the NAP functions follows from the fact that the 
+acoustic waveform has passed through a narrow band filter and so 
+it has a limited number of degrees of freedom.  In all but the 
+highest frequency channels, the output of the auditory filter 
+resembles a modulated sine wave whose frequency is near the 
+centre frequency of the filter.  Thus the neural activity pattern 
+is largely restricted to a set of peaks which are modified 
+versions of the positive halves of a sine wave, and the remaining 
+degrees of freedom appear as relatively slow changes in peak 
+amplitude and relatively small changes in peak time (or phase). 
+.LP
+.LP
+When the acoustic input terminates, the auditory image must 
+decay.  In the ASP model the form of the decay is exponential and 
+the decay rate is determined by decayrate_sai.  
+.LP
+.TP 18
+decay_ai
+SAI decay time constant 
+.RS
+Default units:  ms. Default value 30 ms. 
+.RE
+.RS
+decay_ai determines the rate at which the auditory image decays. 
+.RE
+.RS
+
+In addition, decay_ai determines the rate at which the strength of the
+auditory image increases and the level to which it asymptotes if the
+sound continues indefinitely. In an exponential process, the asymptote
+is reached when the increment provided by each new cycle of the sound
+equals the amount that the image decays over the same period.
+
+.RE
+.SH MOTIVATION
+.LP
+.SS "Auditory temporal integration: The problem "
+.PP
+Image stabilisation and temporal smearing.
+.LP
+When the input to the auditory system is a periodic sound like 
+pt_8ms or ae_8ms, the output of the cochlea is a rapidly flowing 
+neural activity pattern on which the information concerning the 
+source repeats every 8 ms.  Consider the display problem that 
+would arise if one attempted to present a one second sample of 
+either pt_8ms or ae_8ms with the resolution and format of Figure 
+5.2.  In that figure each 8 ms period of the sound occupies about 
+4 cm of width.  There are 125 repetitions of the period in one 
+second and so a paper version of the complete NAP would be 5 
+metres in length.  If the NAP were presented as a real-time flow 
+process, the paper would have to move past a typical window at 
+the rate of 5 metres per second!  At this rate, the temporal 
+detail within the cycle would be lost.  The image would be stable 
+but the information would be reduced to horizontal banding.  The 
+fine-grain temporal information is lost because the integration 
+time of the visual system is long with respect to the rate of 
+flow of information when the record is moving at 5 metres a 
+second.
+.LP
+Traditional models of auditory temporal integration are similar 
+to visual models.  They assume that we hear a stable auditory 
+image in response to a periodic sound because the neural activity 
+is passed through a temporal weighting function that integrates 
+over time.  The output does not fluctuate if the integration time 
+is long enough.  Unfortunately, the simple model of temporal 
+integration does not work for the auditory system.  If the output 
+is to be stable, the integrator must integrate over 10 or more 
+cycles of the sound.  We hear stable images for pitches as low 
+as, say 50 cycles per second, which suggests that the integration 
+time of the auditory system would have to be 200 ms at the 
+minimum.  Such an integrator would cause far more smearing of 
+auditory information than we know occurs.  For example, phase 
+shifts that produce small changes half way through the period of 
+a pulse train are often audible (see Patterson, 1987, for a 
+review).  Small changes of this sort would be obscured by lengthy 
+temporal integration.
+.LP
+Thus the problem in modelling auditory temporal integration is 
+to determine how the auditory system can integrate information 
+to form a stable auditory image without losing the fine-grain 
+temporal information within the individual cycles of periodic 
+sounds.  In visual terms, the problem is how to present a neural 
+activity pattern at a rate of 5 metres per second while at the 
+same time enabling the viewer to see features within periods 
+greater than about 4 ms.
+.LP
+.SS "Periodic sounds and information packets. "
+.PP
+Now consider temporal integration from an information processing 
+perspective, and in particular, the problem of preserving formant 
+information in the auditory image.  The shape of the neural 
+activity pattern within the period of a vowel sound provides 
+information about the resonances of the vocal tract (see Figure 
+3.6), and thus the identity of the vowel.  The information about 
+the source arrives in packets whose duration is the period of the 
+source.  Many of the sounds in speech and music have the property 
+that the source information changes relatively slowly when 
+compared with the repetition rate of the source wave (i.e. the 
+pitch).  Thus, from an information processing point of view, one 
+would like to combine source information from neighbouring 
+packets, while at the same time taking care not to smear the 
+source information contained within the individual packets.  In 
+short, one would like to perform quantised temporal integration, 
+integrating over cycles but not within cycles of the sound. 
+.LP
+.SH EXAMPLES
+.LP
+This first pair of examples is intended to illustrate the 
+dominant forms of motion that appear in the auditory image, and 
+the fact that shapes can be tracked across the image provided the 
+rate of change is not excessive.  The first example is a pitch 
+glide for a note with fixed timbre.  The second example involves 
+formant motion (a form of timbre glide) in a monotone voice (i.e. 
+for a relatively fixed pitch).
+.LP
+.SS "A pitch glide in the auditory image "
+.PP
+Up to this point, we have focussed on the way that TQTI can 
+convert a fast flowing NAP pattern into a stabilised auditory 
+image.  The mechanism is not, however, limited to continuous or 
+stationary sounds.  The data file cegc contains pulse trains that 
+produce pitches near the musical notes C3, E3, G3, and C4, along 
+with glides from one note to the next.  The notes are relatively 
+long and the pitch glides are relatively slow.  As a result, each 
+note form a stabilised auditory image and there is smooth motion 
+from one note image to the next.  The stimulus file cegc is 
+intended to support several examples including ones involving the 
+spiral representation of the auditory image and its relationship 
+to musical consonance in the next chapter.  For brevity, the 
+current example is limited to the transition from C to E near the 
+start of the file.  The pitch of musical notes is determined by 
+the lower harmonics when they are present and so the command for 
+the example is:
+.LP
+gensai mag=16 min=100 max=2000 start=100 length=600 
+duration_sai=32 cegc
+.LP
+In point of fact, the pulse train associated with the first note 
+has a period of 8 ms like pt_8ms and so this "C" is actually a 
+little below the musical note C3.  Since the initial C is the 
+same as pt_8ms, the onset of the first note is the same as in the 
+previous example; however, four cycles of the pulse train pattern 
+build up in the window because it has been set to show 32 ms of 
+'auditory image time'.  During the transition, the period of the 
+stimulus decreases from 32/4 ms down to 32/5 ms, and so the image 
+stabilises with five cycles in the window.  The period of E is 
+4/5 that of C.  
+.LP
+During the transition, in the lower channels associated with the 
+first and second harmonic, the individual SAI pulses march from 
+left to right in time and, at the same time, they move up in 
+frequency as the energy of these harmonics moves out of lower 
+filters and into higher filters.  In these low channels the 
+motion is relatively smooth because the SAI pulse has a duration 
+which is a significant proportion of the period of the sound.  As 
+the pitch rises and the periods get shorter, each new NAP cycle 
+contributes a NAP pulse which is shifted a little to the right 
+relative to the corresponding SAI pulse.  This increases the 
+leading edge of the SAI pulse without contributing to the lagging 
+edge.  As a result, the leading edge builds, the lagging edge 
+decays, and the SAI pulse moves to the right.  The SAI pulses are 
+asymmetric during the motion, with the trailing edge more shallow 
+than the leading edge, and the effect is greater towards the left 
+edge of the image because the discrepancies over four cycles are 
+larger than the discrepancies over one cycle.  The effects are 
+larger for the second harmonic than for the first harmonic 
+because the width of the pulses of the second harmonic are a 
+smaller proportion of the period.  During the pitch glide the SAI 
+pulses have a reduced peak height because the activity is 
+distributed over more channels and over longer durations.
+.LP
+The SAI pulses associated with the higher harmonics are 
+relatively narrow with regard to the changes in period during the 
+pitch glide.  As a result there is more blurring of the image 
+during the glide in the higher channels.  Towards the right-hand 
+edge, for the column that shows correlations over one cycle, the 
+blurring is minimal.  Towards the left-hand edge the details of 
+the pattern are blurred and we see mainly activity moving in 
+vertical bands from left to right.  When the glide terminates the 
+fine structure reforms from right to left across the image and 
+the stationary image for the note E appears.  
+.LP
+The details of the motion are more readily observed when the 
+image is played in slow motion.  If the disc space is available 
+(about 1.3 Mbytes), it is useful to generate a cegc.img file 
+using the image option.  The auditory image can then be played 
+in slow motion using the review command and the slow down option 
+"-".  
+.LP
+.LP
+.SS "Formant motion in the auditory image "
+.PP
+The vowels of speech are quasi-periodic sounds and the period for 
+the average male speaker is on the order of 8ms.  As the 
+articulators change the shape of the vocal tract during speech, 
+formants appear in the auditory image and move about.  The 
+position and motion of the formants represent the speech 
+information conveyed by the voiced parts of speech.  When the 
+speaker uses a monotone voice, the pitch remains relatively 
+steady and the motion of the formants is essentially in the 
+vertical dimension.  An example of monotone voiced speech is 
+provided in the file leo which is the acoustic waveform of the 
+word 'leo'.  The auditory image of leo can be produced using the 
+command 
+.LP
+gensai mag=12 segment=40 duration_sai=20 leo
+.LP
+The dominant impression on first observing the auditory image of 
+leo is the motion in the formation of the "e" sound, the 
+transition from "e" to "o", and the formation of the "o" sound.
+.LP
+The vocal chords come on at the start of the "l" sound but the 
+tip of the tongue is pressed against the roof of the mouth just 
+behind the teeth and so it restricts the air flow and the start 
+of the "l" does not contain much energy.  As a result, in the 
+auditory image, the presence of the "l" is primarily observed in 
+the transition from the "l" to the "e".  That is, as the three 
+formants in the auditory image of the "e" come on and grow 
+stronger, the second formant glides into its "e" position from 
+below, indicating that the second formant was recently at a lower 
+frequency for the previous sound.
+.LP
+In the "e", the first formant is low, centred on the third 
+harmonic at the bottom of the auditory image.  The second formant 
+is high, up near the third formant.  The lower portion of the 
+fourth formant shows along the upper edge of the image.  
+Recognition systems that ignore temporal fine structure often 
+have difficulty determining whether a high frequency 
+concentration of energy is a single broad formant or a pair of 
+narrower formants close together.  This makes it more difficult 
+to distinguish "e".  In the auditory image, information about the 
+pulsing of the vocal chords is maintained and the temporal 
+fluctuation of the formant shapes makes it easier to distinguish 
+that there are two overlapping formants rather than a single 
+large formant.
+.LP
+As the "e" changes into the "o", the second formant moves back 
+down onto the eighth harmonic and the first formant moves up to 
+a position between the third and fourth harmonics.  The third and 
+fourth formants remain relatively fixed in frequency but they 
+become softer as the "o" takes over.  During the transition, the 
+second formant becomes fuzzy and moves down a set of vertical 
+ridges at multiples of the period.  
+.LP
+.LP
+.SS "The vowel triangle: aiua "
+.PP
+In speech research, the vowels are specified by the centre 
+frequencies of their formants.  The first two formants carry the 
+most information and it is common to see sets of vowels 
+represented on a graph whose axes are the centre frequencies of 
+the first and second formant.  Not all combinations of these 
+formant frequencies occur in speech; rather, the vowels occupy a 
+triangular region within this vowel space and the points of the 
+triangle are represented by /a/ as in paw /i/ as in beet, /u/ as 
+in toot.  The file aiua contains a synthetic speech wave that 
+provides a tour around the vowel triangle from /a/ to /i/ to /u/ 
+and back to /a/, and there are smooth transitions from one vowel 
+to the next.  The auditory image of aiua can be generated using 
+the command
+.LP
+gensai mag=12 segment=40 duration=20 aiua
+.LP
+The initial vowel /a/ has a high first formant centred on the 
+fifth harmonic and a low second formant centred between the 
+seventh and eighth harmonics (for these low formants the harmonic 
+number can be determined by counting the number of SAI peaks in 
+one period of the image).  The third formant is at the top of the 
+image and it is reasonably strong, although relatively short in 
+duration.  As the sound changes from /a/ to /i/, the first formant 
+moves successively down through the low harmonics and comes to 
+rest on the second harmonic.  At the same time the second formant 
+moves all the way up to a position adjacent to the third formant, 
+similar to the "e" in leo.  All three of the formants are 
+relatively strong.  During the transition from the /i/ to the /
+u/, the third formant becomes much weaker;.  The second formant 
+moves down onto the seventh harmonic and it remains relatively 
+weak.  The first formant remains centred on the second harmonic 
+and it is relatively strong.  Finally, the formants return to 
+their /a/ positions.
+.LP
+.LP
+.SS "Speaker separation in the auditory image "
+.PP
+One of the more intriguing aspects of speech recognition is our 
+ability to hear out one voice in the presence of competing voices 
+-- the proverbial cocktail party phenomenon.  It is assumed that 
+we use pitch differences to help separate the voices.  In support 
+of this view, several researchers have presented listeners with 
+pairs of vowels and shown that they can discriminate the vowels 
+better when they have different pitches (Summerfield & Assman, 
+1989).  The final example involves a double vowel stimulus, /a/ 
+with /i/, and it shows that stable images of the dominant 
+formants of both vowels appear in the image.  The file dblvow 
+(double vowel) contains seven double-vowel pulses.  The amplitude 
+of the /a/ is fixed at a moderate level; the amplitude of the /
+i/ begins at a level 12 dB greater than that of the /a/ and it 
+decreases 4 dB with each successive pulse, and so they are equal 
+in level in the fourth pulse.  Each pulse is 200 ms in duration 
+with 20 ms rise and fall times that are included within the 200 
+ms.  There are 80 ms silent gaps between pulses and a gap of 80 
+ms at the start of the file.  The auditory image can be generated 
+with the command
+.LP
+gensai mag=12 samplerate=10000 segment=40 duration=20 dblvow
+.LP
+The pitch of the /a/ and the /i/ are 100 and 125 Hz, respectively.  
+The image reveals a strong first formant centred on the second 
+harmonic of 125 Hz (8 ms), and strong third and fourth formants 
+with a period of 8 ms (125 Hz).  These are the formants of the /
+e/ which is the stronger of the two vowels at this point.  In 
+between the first and second formants of the /i/ are the first 
+and second formants of the /a/ at a somewhat lower level.  The 
+formants of the /a/ show their proper period, 10 ms.  The 
+triggering mechanism can stabilise the formants of both vowels 
+at their proper periods because the triggering is done on a 
+channel by channel basis.  The upper formants of the /a/ fall in 
+the same channels as the upper formants of the /i/ and since they 
+are much weaker, they are repressed by the /i/ formants.
+.LP
+As the example proceeds, the formants of the /e/ become 
+progressively weaker.  In the image of the fifth burst of the 
+double vowel we see evidence of both the upper formants of the /
+i/ and the upper formants of the /a/ in the same channel.  
+Finally, in the last burst the first formant of the /i/ has 
+disappeared from the lowest channels entirely.  There is still 
+some evidence of /e/ in the region of the upper formants but it 
+is the formants of the /a/ that now dominate in the high frequency 
+region.
+.LP
+.SH SEE ALSO
+.LP
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+.LP
+.SH ACKNOWLEDGEMENTS
+.LP
+The AIM software was developed for Unix workstations by John
+Holdsworth and Mike Allerhand of the MRC APU, under the direction of
+Roy Patterson. The physiological version of AIM was developed by
+Christian Giguere. The options handler is by Paul Manson. The revised
+SAI module is by Jay Datta. Michael Akeroyd extended the postscript
+facilites and developed the xreview routine for auditory image
+cartoons.
+.LP
+The project was supported by the MRC and grants from the U.K. Defense
+Research Agency, Farnborough (Research Contract 2239); the EEC Esprit
+BR Porgramme, Project ACTS (3207); and the U.K. Hearing Research Trust.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/gensgm.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,200 @@
+.TH GENSGM 1 "11 May 1995" 
+.LP 
+.SH NAME 
+.LP 
+gensgm \- generate auditory spectrogram 
+.LP 
+.SH SYNOPSIS 
+.LP 
+gensgm [ option=value | -option ] [ filename ] 
+.LP 
+.SH DESCRIPTION 
+.LP 
+The gensgm module of the AIM software performs a time-domain spectral
+analysis using a bank of auditory filters, and summarises the
+information in an auditory spectrogram, that is, a spectrogram with
+auditory frequency resolution and temporal resolution, rather than the
+fixed frequency and temporal resolution of traditional speech
+preprocessors.  The spectral analysis converts the input wave into an
+array of filtered waves, one for each channel of a gammatone auditory
+filterbank. The surface of the array of filtered waves is AIM's
+representation of basilar membrane motion (BMM) as a function of
+time. The auditory spectrogram is a plot of a sequence of spectral
+slices extracted from the envelope of the BMM every 'frstep_epn'
+ms. The envelope is calculated continuously, by rectifing,
+compressing, and lowpass filtering the individual BMM waves as they
+flow from the filterbank.
+.LP
+The frequency resolution of the analysis varies with the center
+frequency of the channel as in the auditory system, and the
+distribution of channels across frequency is chosen to match that in
+the auditory system (Patterson and Moore, 1986).  Thus, the auditory
+spectrogram is a greyscale plot of the activity in each channel
+(shades of black) as a function of time (the abscissa) and the centre
+frequency of the auditory filter (the ordinate) in ERB's.  The
+representation is referred to as an auditory spectrogram (SGM) to
+distinguish it from more traditional spectrograms based on Fourier,
+LPC or cepstral analysis. In AIM, the suffix 'sgm' is used to
+distinguish this spectral representation from the other spectral
+representations provided by the software ('asa' auditory spectral
+analysis, 'cgm' cochleogram, and 'epn' excitation pattern).
+.LP
+The spectral analysis performed by gensgm is the same as that
+performed by genbmm (manaim genbmm). The primary differences are in
+the display defaults and the inclusion of the Compression and Leaky
+Integration modules used to produce the spectral slices that form the
+spectrogram. As a result, this manual entry is restricted to
+describing the option values that differ from those in genbmm and the
+additional options required to control the Compression and Leaky
+Integration.
+.LP
+.SH DISPLAY DEFAULTS
+.LP
+The default values for three of the display options are reset to
+produce a spectrographic format rather than a landscape. Specifically,
+display=greyscale, bottom=0 and top=2500. The number of channels is
+set to 128 for compatibility with the auditory spectrum modules,
+genasa and genepn.  When using AIM as a preprocessor for speech
+recognition the number of channels would typically be reduced to
+between 24 and 32.  Use option 'downsample' if it is necessary to
+reduce the output to less than 24 channels across the speech range.
+.LP
+.SH COMPRESSION AND LEAKY INTEGRATION
+.LP
+Compression and lowpass filtering are activated and the neural
+encoding stage that comes between them is turned off:
+.LP
+.SS "Compression"
+.PP
+Auditory spectra are usually produced via the functional route in
+AIM. In this case, compress is set on
+.LP
+.TP 13
+compress
+Logarithmic compressor switch
+.RS
+Switch. Default: on.
+.RE
+.RS
+.LP
+Note: The compressor in the functional route of AIM is logarithmic and
+it screens out negative BMM values before compression. This rectifies
+the wave during the compression process and so the separate rectify
+option is left off. 
+.RE
+.LP
+.RS
+.LP
+Note: The compressor in the physiological route of AIM is an integral
+part of the tlf module, so when using this route to produce auditory
+spectra, turn off the logarithmic compressor (i.e. compress=off). The
+compressor in tlf does not screen out negative values so it is also
+important to set rectify=on.
+.RE
+.RS
+.LP
+Full wave rectification is produced if rectify is set to 2. This
+option value leads to smoother spectrograms. It is also useful when
+calculating envelopes with genasa.
+.RE
+.LP
+.SS "Transduction"
+.PP
+.LP
+.TP 13
+transduction
+Neural transduction switch (at, meddis, off)
+.RS
+Switch. Default: off.
+.RE
+.LP
+.SS "Leaky Integration"
+.PP
+.LP
+.TP 13
+stages_idt
+Number of stages of lowpass filtering
+.RS
+Default unit: scalar. Default value: 2
+.RE
+.TP 13
+tup_idt
+The time constant for each filter stage
+.RS
+Default unit: ms. Default value: 8 ms.
+.RE
+.LP 
+The Equivalent Rectandular Duration (ERD) of a two stage lowpass
+filter is about 1.6 times the time constant of each stage, or
+12.8 ms in the current case.
+.TP 13
+frstep_epn
+The time between successive spectral frames
+.RS
+Default unit: ms. Default value: 10 ms.
+.RE
+.LP
+With a frstep_epn of 10 ms, gensgm will produce spectral frames at a
+rate of 100 per second.
+.LP
+.TP 13
+downsample
+The time between successive spectral frames. 
+.RS
+Default unit: ms. Default value: 10 ms.
+.RE
+.LP
+Downsample is simply another name for frstep_epn, provided to
+facilitate a different mode of thinking about time-series data.
+.LP
+.SH FILES
+.LP
+.TP 13
+ .gensgmrc 
+The options file for gensgm.
+.LP
+.SH SEE ALSO
+.LP
+genasa, genbmm, genepn, gencgm
+.LP
+.SH BUGS
+.LP
+None currently known.
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+.LP
+.SH ACKNOWLEDGEMENTS
+.LP
+The AIM software was developed for Unix workstations by John
+Holdsworth and Mike Allerhand of the MRC APU, under the direction of
+Roy Patterson. The physiological version of AIM was developed by
+Christian Giguere. The options handler is by Paul Manson. The revised
+SAI module is by Jay Datta. Michael Akeroyd extended the postscript
+facilites and developed the xreview routine for auditory image
+cartoons.
+.LP
+The project was supported by the MRC and grants from the U.K. Defense
+Research Agency, Farnborough (Research Contract 2239); the EEC Esprit
+BR Porgramme, Project ACTS (3207); and the U.K. Hearing Research Trust.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/genspl.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,401 @@
+.TH GENSPL 1 "8 September 1993"
+.LP
+.SH NAME
+.LP
+genspl \- spiral auditory image of a pulse train
+.LP
+.SH SYNOPSIS/SYNTAX
+.LP
+genspl [ option=value  |  -option ]  filename
+.LP
+.SH DESCRIPTION
+.LP
+Since the spiral auditory image is just a different view of the 
+auditory image, it includes all of the flags associated 
+previously with the gensai command.  In the ASP software, the 
+spiral auditory image is presented in cartoon form, similar to 
+the presentation of the linear auditory image. The spiral view 
+of the auditory image is a global view of the sound that 
+emphasises pitch and de-emphasises timbre.  It is a distant 
+perspective taken in order to view the longer term correlations 
+that arise in periodic sounds.  It is difficult to represent the 
+functions of the SAI visually in a spiral form; the fine detail 
+of the functions wouldbe lost in the spiral perspective.  
+Accordingly, in the spiral perspective each of the separate SAI 
+pulses is replaced by a dot positioned at the time of the peak 
+of the pulse.  Previously, this representation was referred to 
+as a pulse ribbon (Patterson, 1987a).
+.LP
+Conceptually, the spiral auditory image is a set of concentric 
+spirals one for each channel of the auditory image.  The highest 
+frequency channel is on the inside with the smallest radius; the 
+lowest frequency channel is on the outside with the largest 
+radius.  The spirals lines are omitted for clarity, leaving just 
+the dots.  The presence of bars shows that the same period exists 
+in a range of filter channels.  Note, however, that this 
+information about correlation across channels appears on the same 
+spoke as the information indicating that the pattern repeats on 
+the auditory image in time.  Thus the multi-channel spiral maps 
+both spectral and temporal information concerning the 
+periodicity of the sound onto a single spatial vector -- a spoke 
+of the spiral.  It is this property that enables the spiral 
+representation to explain octave perception (Patterson, 1990).  
+.LP
+.SS "A pitch glide in the spiral auditory image "
+.PP
+The spiral auditory image, like its linear counterpart, is not 
+limited to periodic sounds.  When the pitch of a sound glides 
+smoothly from one note to another the pattern on the spiral 
+auditory image rotates smoothly from one position to another, and 
+when the pitch changes abruptly from one note to another, the 
+spiral pattern dissolves at the end of the first note and forms 
+again in a different orientation at the start of the second note.  
+.LP
+The spiral spokes grow from the centre outwards as the 
+correlation across cycles grows.  For the note C3, four spokes 
+form:  the vertical spoke contains information about periods 
+separated by 1, 2, 4 and 8 cycles; the spoke at 25 minutes past 
+the hour contains information about periods separated by 3 and 6 
+cycles; the remaining two spokes at 40 and 10 minutes past the 
+hour contain information about periods separated by 5 and 7 
+cycles, respectively.  
+.LP
+	As the pitch of the note changes from C3 to E3, the pattern 
+rotates 20 minutes, and the spoke that was previously at 40 
+minutes moves into the vertical position.  Then, as the pitch 
+glides from E3 to G3, the spoke which was at  25 minutes in C3, 
+moves into the vertical position. As the pitch glides on up from 
+G3 to C4 the longest spoke of the pattern returns to the vertical 
+position completing one revolution as the pitch rises an octave.  
+Note, however, that each of the spokes has been extended by one 
+circuit towards the centre of the spiral.  Thus, in the ASP model, 
+octaves are perceived to be similar because they produce spoke 
+patterns with the same orientation on the spiral auditory image 
+and the notes of the major triad are those with a spoke that 
+coincides with the main spoke of the tonic.  A theory of musical 
+consonance based on the coincidence of spokes in spiral auditory 
+images is presented in Patterson (1986).
+.LP
+.LP
+.SH OPTIONS
+.LP
+.SS "Display options for the spiral auditory image "
+.PP
+The options that control the position of the spiral image window 
+on the screen are the same as for all previous windows.  
+Furthermore, since the spiral auditory image is a cartoon just 
+like the linear auditory image, it may be generated, stored, 
+animated, and reviewed in the same way as the linear auditory 
+image.  In addition, there are six new display options for the 
+spiral view of the auditory image.
+.LP
+.TP 11
+spiral
+Switch to spiral auditory image 
+.RS
+Switch: Default, off. 
+.RE
+.RS
+When spiral is set to "on" the time dimension of the auditory image is plotted as a spiral and the SAI function is replaced with dots positioned at the peaks of the pulses in the SAI function. 
+.RE
+.TP 13
+form_spl
+The form of the spiral time line 
+.RS
+Switch: Default, archimedian. 
+.RE
+.RS
+The software offers two visual representations of the underlying logarithmic spiral, both of which have the base 2. 
+.RE
+Both representations gather doublings in time onto a specific 
+spoke of the spiral, and so both have the general property that 
+.LP
+	q = log2(t/T) 	(6.1)
+.LP
+q is the angle between the horizontal axis and the radius drawn 
+to point on the spiral.  T is the period of the sampling rate and 
+t is "auditory image time", both in seconds.  Every time t doubles 
+q increases by 1, and so the integer part of q (the characteristic 
+of the logarithm) specifies the circuit of the spiral.  The 
+fractional part of the logarithm (the mantissa) specifies the 
+angle within the circuit, and in this case, the angle is measured 
+in revolutions, or circuits.
+.LP
+The archimedian spiral is like a coil of rope; that is, the radius 
+increases by the thickness of the rope on each successive 
+circuit.  The form of the archimedian spiral is 
+.LP
+	r = aq = a log2(t/T)	(6.2)
+.LP
+where r is the radius from the centre of the spiral to a point 
+on the spiral.  The logarithmic spiral has the form 
+.LP
+	r = 2q = 2log2(t/T) = t/T	(6.3)
+.LP
+The logarithmic version of the spiral has the advantage that 
+image time is linear along the path of the spiral.  However, it 
+has the disadvantage that it expands rapidly, and so the current 
+default is archimedian.  
+.LP
+.LP
+.TP 16
+dotsize_spl
+The size of the dots on the spiral 
+.RS
+Default units, pixels: Default value, 2 pixels. 
+.RE
+.RS
+The dots plotted on the spiral are actually small squares and the value dotsize_spl determines the number of pixels along the side of the square. 
+.RE
+.TP 13
+axis_spl
+Spiral axis, or time line 
+.RS
+Switch: Default, off 
+.RE
+.RS
+When the axis_spl switch is set to "on", a spiral axis, or time line is plotted. It is presented on the outside of the circuit, one channel below the lowest filter channel, just as in the linear image. The default value for axis_spl is "off" because the spiral axis contains a large number of points and it is slow to calculate and plot. 
+.RE
+Note:  The length of spiral displayed in the window is determined 
+by duration_sai.  This is the same duration_sai as for the linear 
+image.  The size of the spiral display is scaled so that the 
+radius associated with duration_sai fits inside the rectangle 
+specified for the window.  The spiral does not have to be 
+presented in a square window and in some instances rectangular 
+windows are quite effective for giving a sense of depth.
+.LP
+.TP 13
+zero_spl
+Spiral start point and spiral orientation 
+.RS
+Default units: revolutions. Default value 4.072 revolutions. 
+.RE
+.RS
+This parameter determines the minimum "auditory image time" that appears on the spiral, and thus it determines the zero point on the spiral. 
+.RE
+The parameter zero_spl has two primary uses:  Firstly, it enables 
+the user to determine the orientation of the main spoke of the 
+spiral for a given combination of sampling rate and stimulus 
+period.  Without the parameter zero_spl, the orientation of the 
+spiral would be fixed by the sampling rate and period of the 
+sound.  Periods that are an exact power-of-2 times the base 
+period, 1/T, would appear on the spoke preceding horizontally 
+from the centre of the spiral towards the right.  By removing a 
+portion of a circuit the orientation of the spiral can be set to 
+suit the user.  A reduction in zero_spl of 0.25 will rotate the 
+main spoke from horizontal to vertical. 
+.LP
+The second purpose of zero_spl is to enable the user to adjust 
+the image to the period being displayed; that is, to focus on the 
+octave of the current sound.  For example, when the sound has a 
+long period, like 8 ms, the activity produced by the sound falls 
+in the outer circuits of the spiral.  If zero_spl is set to a 
+small value (<2) the centre of the display will be largely blank.  
+The short circuits associated with higher octaves can be removed 
+by setting zero_spl to a larger value, say 4, in which case a 
+sound with an 8 ms period will fill the display.  
+.LP
+The one parameter zero_spl can be used to both scale and rotate 
+the spiral simultaneously; integer changes in the parameter cause 
+a scaling without rotation.  The default value, 4.072, assigns a 
+vertical spoke to a period of 8 ms (and its base-2 relatives) 
+when the sampling rate is 20 kHz (or a base-2 relative).
+.LP
+.TP 18
+dotthresh_spl
+Threshold value for the production of a spiral dot 
+.RS
+Unit: SAI strength. Default value, 50 SAI units. 
+.RE
+.RS
+This threshold specifies the value that a pulse in the SAI must reach, or exceeds in order for it to be presented as a dot in the spiral image. 
+.RE
+.LP
+.SH EXAMPLES
+.LP
+In order to understand the spiral mapping, look at the auditory 
+image of C3 and imagine the pulse ribbon that would be formed by 
+replacing each SAI pulse with a dot and extending the duration 
+of the image to 70 ms so that it will accommodate eight cycles 
+of the note.  The spiral view is produced by compressing the pulse 
+ribbon vertically, stretching it horizontally, and then wrapping 
+it counterclockwise into a spiral, with the right-hand edge at 
+the centre of the spiral and the left-hand edge at the end of the 
+outer circuit.  The dots from vertical columns of pulses in the 
+linear auditory image, merge into short bars in the spiral view 
+because of the vertical compression; the bars fall along  spokes 
+radiating from the centre of the spiral.  The dots from the arches 
+of pulses on either side of the vertical column in the linear 
+auditory image appear in a stretched form like "wings" in the 
+spiral auditory image.
+.LP
+In the case of C3 four of the bars are aligned on one spoke of 
+the spiral (the vertical spoke); they represent the strong 
+correlations that  occur in the auditory image for cycles of the 
+original sound separated by 1, 2, 4, and 8 cycles.  In this way, 
+much of the information that is distributed across the temporal 
+dimension of the linear auditory image is gathered together into 
+a single spatial vector.
+.LP
+.LP
+The wave cegc provides an example of how the spiral auditory 
+image follows pitch glides from one note to another.  One 
+reasonable version of the spiral pitch glide is provided by the 
+command
+.LP
+.LP
+genspl width=600 height=550 duration_sai=70 zero_spl=5.072 cegc
+.LP
+.LP
+.SS "The separation of pitch and timbre in the auditory image. "
+.PP
+The file vowgld contains a synthetic speech waveform that 
+combines both formant motion and pitch motion; the formant motion 
+is a rapid tour around the vowel triangle as in aiua, and the 
+pitch motion is C3, E3, G3 and C4.  A linear auditory image of 
+vowgld can be generated with the command 
+.LP
+.LP
+gensai width=420 height=420 mag=12 segment=40 duration_sai=20 
+spiral=off vowgld
+.LP
+.LP
+The motion in the linear auditory image is similar to that 
+observed with aiua in Chapter 5.  That is, the formants move 
+vertically as the vowels change from one to the next.  In this 
+example, however, there is pitch motion and the period decreases 
+by a factor of 2 as the example proceeds.  The pitch change is 
+observed primarily as horizontal motion that is largely 
+independent of the formant motion.  In point of fact, the 
+resolved harmonics in the lower half of the auditory image are 
+rising in frequency as the example proceeds but this does not 
+seem to interfere with the perception of either the vertical 
+motion of the formants or the horizontal   shrinking of the 
+period.
+.LP
+Although the rise in pitch can be observed in the linear auditory 
+image it is not the dominant perception; rather, it is the 
+formant motion that dominates in this microscopic view of the 
+auditory image.  A spiral auditory image of vowgld can be 
+generated with the command
+.LP
+.LP
+gensai width=420 height=420 segment=40 duration_sai=70 spiral=on 
+zero_spl=5.072 vowgld
+.LP
+.LP
+The motion in the spiral auditory image is dominated by the 
+rotation of the spokes, that is, the pitch motion.  The motion 
+of the formants is represented in the spiral image in the sense 
+that there is more sparkle in the information that is not on the 
+main spoke pattern.  This sparkle is caused by the formant energy 
+changing channels as the formants move from channel to channel 
+within one circuit of the spiral.  But the fact that the motion 
+in successive circuits is coordinated is not apparent in this 
+macro view of the auditory image.
+.LP
+A more dramatic example of the enhancement pitch and the 
+repression of timbre can be produced by generating a spiral 
+auditory image for aiua  in which the pitch is fixed and the 
+vowels range around the vowel triangle.  The formant information 
+on the spokes changes as the vowel tour proceeds but the position 
+of the spokes remains fixed.  The vowel information of the spokes 
+rushes around in three discrete transitions but there is no 
+particular pattern to the motion. 
+.LP
+Thus, in the ASP model, pitch and timbre are just two views of 
+the same auditory image; pitch effects are observed when we stand 
+back and take a macroscopic view of the auditory image; timbre 
+details are observed when we move in close and take a microscopic 
+view of the auditory image. 
+.LP
+.LP
+The review program has the capacity to present two auditory 
+images simultaneously.  If linear and spiral auditory images of 
+vowgld are generated and stored using image=on, they can be 
+replayed simultaneously and compared using the command 
+.LP
+review vowgld_l vowgld_s
+.LP
+Caution: this requires the user to produce separate image files 
+(vowgld_l.img, vowgld_s.img) either by producing the images from 
+copies of vowgld with different names, or by renaming the 
+auditory images as they are produced.  If two different auditory 
+images are produced from the same file, the second will overwrite 
+the first even though one has a linear format and one a spiral 
+format.  
+.LP
+.SS "Multiple pitches in the spiral auditory image "
+.PP
+It is generally assumed that when two people are speaking at the 
+same time, the listener uses the differences in the pitches of 
+the two voices to assist in separating the speakers.  The final 
+example in this chapter shows that the pitches of the /a/ and the 
+/o/ in dblvow appear separately in the spiral auditory image, and 
+that it would be reasonable to use the spiral to separate the 
+channels associated with the two vowels and thereby assist 
+speaker tracking.  The spiral auditory image can be generated by 
+the command
+.LP
+.LP
+gensai width=600 height=550 samplerate=10000 spiral=on 
+duration=90 dblvow
+.LP
+.LP
+The main spokes of the /a/ and the /i/ appear at angles of 40 and 
+0 minutes past the hour, respectively, corresponding to periods 
+of 10 and 8 ms.  Over the course of the example, the main spoke 
+of the /i/ fades considerably while the main spoke of the /a/ 
+increases somewhat.
+.LP
+The second spoke of the /a/ and /i/ patterns appear at 5 and 25 
+minutes, respectively, and their strength  changes predictably 
+as the example proceeds.  If either vowel were presented on its 
+own there would be more than two spokes in the pattern of each 
+vowel.  The presence of the second vowel represses spokes beyond 
+the second in the patterns of both vowels.
+.LP
+.LP
+.SH BUGS
+.LP
+Note:  the current vrsion of the software (release 3, June 1990) 
+incorrectly adds linear axes to hardcopy figures.  Apologies.
+.LP
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+.LP
+.SH ACKNOWLEDGEMENTS
+.LP
+The AIM software was developed for Unix workstations by John
+Holdsworth and Mike Allerhand of the MRC APU, under the direction of
+Roy Patterson. The physiological version of AIM was developed by
+Christian Giguere. The options handler is by Paul Manson. The revised
+SAI module is by Jay Datta. Michael Akeroyd extended the postscript
+facilites and developed the xreview routine for auditory image
+cartoons.
+.LP
+The project was supported by the MRC and grants from the U.K. Defense
+Research Agency, Farnborough (Research Contract 2239); the EEC Esprit
+BR Porgramme, Project ACTS (3207); and the U.K. Hearing Research Trust.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/genwav.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,594 @@
+.TH GENWAV 1 "11 May 1995"
+.LP
+.SH NAME
+.LP
+genwav \- display the wave in filename.
+.LP
+.SH SYNOPSIS
+.LP
+genwav [ option=value | -option ] [ filename ]
+.LP
+.SH DESCRIPTION
+.LP 
+
+Genwav sets up and Xwindow and displays a segment of the input wave
+in the window. The size of the window and the size of the wave are
+determined by options, as are a number of other input/output
+functions. These options have no direct bearing on the auditory
+processing performed by AIM. For convenience, these Non-Auditory
+options are associated with the instruction genwav (the one
+non-auditory instruction), and they are listed at the top of the
+options tables prior to the auditory options.
+
+.LP
+There are three classes of Non-Auditory options: 
+.LP
+I)   DISPLAY OPTIONS that determine the format of the auditory representations 
+of sound on the screen, or on paper when printed.
+.LP  
+II)  OUTPUT OPTIONS that determine the format and content of files used
+to store the auditory representations of sounds.
+.LP 
+III) INPUT OPTIONS that determine how the wave in the input file should
+be interpreted.
+.LP
+The output options are presented before the input options so that the
+input options will be adjacent to the filterbank options in the
+options tables produced by genbmm and subsequent instructions.
+
+.SS 
+I. DISPLAY OPTIONS
+.LP
+
+The AIM modules produce output in the form of a set of functions, one
+for each channel of the auditory filterbank.  For example, the output
+of genbmm is a set of functions that simulate basilar membrane motion
+produced in response to the input wave.  By default, the AIM software
+puts an Xwindow up on the computer screen and displays the output in
+the window. This section describes the options that control these
+displays.
+
+.LP
+The display options are: title, display, x0-win, y0-win, width_win,
+height_win, display, view, top, bottom, overlap, headroom,
+magnification, pensize, hiddenline.
+.LP
+A. The Display Window Title, Position, and Size
+.RS 3
+
+.LP
+title	Title of output display.
+.RS 5
+	Character string. Default: input file name.
+.RE
+.LP
+The title of the output being displayed.  If no title is given, the
+display bears the name of the file of the input wave.
+
+.LP
+display	Display output on screen
+.RS 5
+	Switch.  Default: on.
+.RE
+.LP
+
+Normally this switch is on and a bitmap of the output is displayed in
+a graphical window on the computer screen.  The switch is provided
+because the time taken to create the displays is considerable, and it
+is useful to turn it dsiplay off using AIM as a preprocessor for
+speech recognition.
+
+.LP
+x0_win	Left edge of window
+.RS 5
+	Unit: pixels.  Default: centre.
+.RE
+.LP
+The left edge of the window into which the display will be drawn,
+relative to the left edge of the screen (i.e. the x-coordinate of the
+window within the screen).  A value of centre will cause centring in
+the horizontal dimension (provided the window manager does not
+override).
+.LP
+y0-win    Lower edge of window
+.RS 5
+	Unit: pixels.  Default: centre.
+.RE
+.LP
+The lower edge of the window into which the display will be drawn,
+relative to the lower edge of the screen (i.e. the y-coordinate of the
+window within the screen).  A value of centre will cause centring in
+the vertical dimension (provided the window manager does not
+override).
+.LP
+Taken as a pair x0_win and y0-win determine the origin of the window,
+relative to the screen origin which is assumed to be the lower left
+corner of the screen.
+.LP
+width_win Window width
+.RS 5
+	Unit: pixels.  Default: 640.
+.RE
+.LP
+The width of the window into which the display will be drawn.
+.LP
+height_win Window height
+.RS 6
+	Unit: pixels.  Default: 480.
+.RE
+.LP
+The height of the window into which the display will be drawn.
+.RE
+
+
+.LP
+B. Display Controls
+.RS 3
+.LP
+top	The largest postive value visible in the display
+.LP
+	Scalar. Default value: 1024 (for genwav) 
+.LP
+Each of the functions in the multi-channel output of a module is
+displayed in a transparent window. Provided the channel density is not
+too low, the functions are related and the set of functions produces a
+display that looks like a complex landscape. Top determines the
+largest positive value that will appear in the transparent windows of
+the individual functions, so top must be as large as the largest value
+in the full set of functions. Increasing top has the effect of moving
+the viewer farther up above the landscape.
+.LP
+bottom	The largest negative value visible in the
+.RS 5 
+	display 
+.RE
+.RS 5
+	Scalar. Default value: -1024 (for genwav) 
+.RE
+.LP
+Bottom determines the largest negative value that will appear in the
+transparent windows of the individual functions, so bottom must be as
+large in the negative direction as the largest negative value in the
+full set of functions. Increasing bottom in the negative direction has
+the effect of depeening the valleys in the landscape.
+.LP
+overlap   The overlap of transparent windows of the 
+.RS 5
+	individual functions
+.RE
+.RS 5
+	Scalar: percentage. Default value: 50%
+.RE
+.LP 
+The fact that the output functions are related means that they
+fit up under each other in the display in a way that concentrates the
+lines on the landscape and improves the display.
+.LP
+headroom  Display with headroom for the uppermost channel 
+.RS 5
+	Scalar: percentage. Default value: 0%
+.RE
+.LP
+Because of the overlap of the transparent windows, part of the
+uppermost transparent window is hidden by the upper edge of the
+display window. This can cause truncation of the waves in the upper
+channels.  To avoid truncation, headroom enables the user to specify
+that the highest channel ought to be centred below the upper edge of
+the window.  The value specified is taken to be the percentage of the
+window between the zero line of the upper channel and the upper edge
+of the window.
+.LP
+magnification Display magnification
+.RS 9
+	Scalar.  Default: 1.0.
+.RE
+.LP
+The degree to which the amplitude of the functions in the display
+should be magnified before being displayed.  This parameter is merely
+for adjusting the visual contrast of the display.  The magnification
+option is a multiplier, so a value of 1 implies drawing to scale,
+while a value of 10 implies ten times (10x) the size of values in the
+module output and 0.1 implies one tenth of the output size.
+Magnification is related to, but separate from, the gain options which
+affect the values of the output functions and the values stored in any
+output files. Magnification is an alternative means of controlling the
+size of the functions in the display -- alternative to top and bottom.
+.LP
+pensize	The size of the lines in the displays and the 
+.RS 5
+	dots on the spiral
+.RE
+.RS 5
+	Unit: pixels.  Default: 1. 
+.RE
+.LP
+This option allows the user to specify the thickness of the lines in
+the display and the size of the dots on spiral auditory images.  It
+also affects the lines and dots in postscript plots.  It is provided
+primarily for use with printers which have much more resolution than
+computer screens.  On laser printers a value of 3-5 gives reasonable
+line thickness.  On the screen, a linewidth greater than 1 produces
+slow drawing, and a gagged, blurred display.
+.LP
+hiddenline  Draw with overlapping parts of functions 
+.RS 5 
+	  hidden 
+.RE
+.RS 5
+	  Switch.  Default: on.
+.RE
+.LP
+This switch specifies whether or not a 'hidden line' algorithm should
+be used when drawing the display.  It also affects printed displays.
+In almost all cases, hiddenline results in more attractive displays of
+waveforms, and it often makes complex displays easier to understand,
+so the default is 'on'.  Note: hiddenline almost doubles the drawing
+time so it is sometimes useful to switch it off on slower machines.
+.LP
+
+.SS 
+II. OUTPUT OPTIONS
+.RS 3
+.LP
+The output options are listed and described before the input options
+so that the input options will be adjacent to the filterbank options
+in the listings produced by genbmm and subsequent modules.  The output
+options are downchannel, erase_ctn, animate_ctn, bitmap_ctn,
+postscript, output, and header.
+.LP
+downchannel Average adjacent channels of multichannel 
+.RS 7
+	representations 
+.RE
+.RS 7
+	Units: Number of averagings. 
+.RE
+.RS 7
+     Default value: 0.
+.RE
+.LP
+
+There is interaction between channels in the transmission-line
+filterbank of the physiological version of AIM, and in the neural
+encoding of the functional version of AIM.  The minimum channel
+density for these processes to operate properly is four channels per
+ERB and 2 channels per ERB, respectively.  For broadband signals like
+speech this means that the minimum number of channels is on the order
+of 128 and 64, respectively.  This channel density can produce
+cluttered displays, and more importantly, it is far too many channels
+for current speech recognition systems which typically use 12-24
+channels.  This is not just a computer power problem; the recognition
+systems actually perform less well with extra channels.  Accordingly,
+the option 'downchannel' provides the option of reducing the channel
+density at output, so that AIM can operate with the appropriate
+channel density and still provide output that is compatible with
+displays and speech recognition systems.
+
+.LP
+Downchannel averages pairs of adjacent channels and the option value
+specifies how many times it should execute the averaging process. Each
+averaging reduces the number of channels by a factor of 2, so for
+proper transmission-line filtering and an output file with 16
+channels, set channels_afb=128 and downchannel=3 (three successive
+halvings of the number of channels).
+
+
+.LP
+A. Animated Cartoons
+.LP
+.RS 3
+Four of the AIM instructions produce output in the form of sequences
+of spectral frames (gensgm, gencgm, genasa and genepn).  Bitmap
+versions of the displays of the frames can be stored by AIM and
+replayed by review and xreview.  When the sequence of frames is played
+rapidly, it appears as an animated cartoon that shows the dynamic
+behaviour of the spectrum of the sound.
+.LP
+Similarly, the AIM instructions for auditory images (gensai and
+genspl) produce sequences of landscape frames, and bitmap versions of
+the landscape displays can also be stored by AIM and replayed by
+review and xreview.  Indeed, it was the desire to produce auditory
+image cartoons that led to the development of much of the AIM software
+package. The animated cartoons or auditory images show the dynamic
+behaviour of features in the images, like the motion of formants in
+diphthongs and the motion of notes in a melody.
+.LP
+This section describes the options that control the construction and
+storage of sequences of bitmaps; there is a separate manual entries for
+the xreview routine that replays the bitmaps ( 'manaim xreview').
+
+
+.LP
+erase_ctn   Erase the current frame before presenting  
+.RS 7 
+	the next frame
+.RE
+.RS 7
+	Switch. Default value: on.
+.RE
+.LP
+
+Normally, when presenting a sequence of frames as an animated cartoon,
+one wants to erase the current frame before presenting the next. When
+the frames are spectra, however, the set of frames can together form a
+meaningful display; for example, the set of rising spectra produced at
+the onset of a sound produces a contour map of the onset. The option
+erase_ctn enables the user to observe the full set of spectra
+simultaneously. (See aimdemo_gtf_spectra or aimdemo_tlf_spectra ).
+
+.LP
+animate_ctn Store frames in memory and replay all of 
+.RS 7
+	them as a cartoon
+.RE
+.RS 7
+	Switch. Default value: off.
+.RE
+.LP
+When this option is on, AIM stores the bitmaps of the frames it
+produces in the memory of the machine and replays them rapidly when
+the instruction is complete. Type RETURN to animate the cartoon again;
+type 'q RETURN' to exit the instruction.  (This option was important
+when machines were slower and before the availability of review and
+xreview. It is now largely obsolete.)
+.LP
+bitmap_ctn  Store bitmaps of frames in a file for  
+.RS 7 
+	replay as a cartoon 
+.RE
+.RS 7
+	Switch. Default value: off.
+.RE
+.LP
+When this option is on, bitmaps of the frames produced for the input
+in file_name will be stored in file_name.ctn.  The sequence of frames can later be replayed using either 
+.LP
+> review file_name  or
+.LP
+> xreview file_name	
+.LP
+Both of these programs enable the user to vary the rate of animation,
+the section of the sequence to be view, etc. The xreview version has a
+window interface with useful information and is the preferred version
+in most cases.
+.RE
+
+.RS 3
+B. Output Files for Printing and Postprocessing
+
+.LP
+Postscript  Produce printer-ready output
+.RS 7
+	Switch.  Default value:  off.
+.RE
+.LP
+This switch causes AIM to produce a printer-ready version of the
+displays it presents on the computer screen.  For example, the NAP of
+a 32-ms section of cegc can be printed using
+.LP
+> gennap length=32 postscript=on cegc | lpr -Plw
+.LP
+where 'lpr' is the Unix printer-driver and the 'lw' of -Plw specifies
+the destination printer.  You may need to check the name of your
+system's printer driver and laser printer.
+.LP
+Alternately the postscript version of the display may be directed to a
+file using an instruction like
+.LP
+> gennap length=32 postscript=on cegc > cegc_nap.ps
+.LP
+and printed later at the users convenience. In this example, the file
+name cegc_nap.ps is not generated by AIM; the '_nap.ps' suffix is
+added by the user following standard conventions to indicate that the file
+contains a NAP in postscript form.
+
+.RS 3
+.LP
+THREE POSTSCRIPT CAUTIONS: 
+.LP
+Postscript files of landscape displays from AIM are very large. As a
+result, we recommend
+.LP
+a) that you NOT switch postscript on without redirecting the output to
+a file, as it will cause the output to be display on the screen in a
+seemingly endless display,
+.LP
+b) that you be careful NOT to print postscript files on a printer
+which does not understand the Postscript language, as it can cause the
+printer to put out an extremely long file, one column per page!
+.LP
+c) that you NOT set postscript=on in an options file as it will
+generate large files in the directory without your noticing.
+.RE
+
+.LP
+output  Generate an output file
+.RS 3
+	Switch.  Default value:  off.
+.RE
+.LP
+This switch causes the array of functions that defines AIM's
+simulation of basilar membrane motion, or a neural activity pattern,
+or an auditory image, to be stored in a file for subsequent processing
+by the aimtools or other, user defined, operators. By convention, the
+file is given the same name as the input file, but with a suffix
+reflecting the entry point, to distinguish it from the input file on
+the one hand and from other output files on the other hand. The naming
+system enables the user to construct and store a set of output files
+for one input file without the need to specify a sequence of file
+names.  The suffixes are those used to identify the modules in the
+listing produced by 'gen -help'.  So, for example, the following
+command line:
+.LP
+> gennap output=on length=32 cegc
+.LP
+will produce an output file named cegc.nap containing a multiplexed
+version of the functions that define the NAP of the first 32 ms of
+cegc.  
+.LP
+The spectrographic representations produced by gensgm and gencgm can
+be stored in the same way, as can the sequences of spectra produced by
+genasa and genepn. It is the output files of genasa and gencgm that
+are used to interface AIM with speech recognition systems (Robinson et
+al., 1990; Patterson et al., 1995; Giguere and Woodland, 1994a).
+Details of the file formats are presented in docs/aimFileFormat.
+.LP
+Header  Put a header on the output file
+.RS 3
+	Flag.  Default value:  on.
+.RE
+.LP
+By default, a header is prepended to each output file so that
+subsequent processors have access to the history of the file.  Details
+of the header structure are presented in docs/aimFileFormat.
+.LP
+.RE 
+
+.SS 
+III. INPUT OPTIONS
+.LP
+The input options enable the user to process a subsection of the input
+wave, and to specify characterisitcs of the wave.
+.LP
+The input options are: input_wave, start_wave, length_wave,
+samplerate, swap_wave, bits_wave, dB_wave.
+.LP
+input_wave   Default input wave name
+.RS 13
+Filename.  Default value: none.
+.RE
+.LP
+The name of the wave file to process.  This option permits simple
+repetitive processing of the same input file without repetitive typing.  It
+also enables one to circumvent the Unix convention of having the filename
+last on the command line.  This option is overridden if the user supplies a
+wave file name at the end of the command line.
+.LP
+start_wave   Start point in wave
+.RS 13
+Default unit: ms.  Default value: 0.
+.RE
+.LP
+The point in the input wave at which processing should begin.  The
+start_wave option is expressed in milliseconds and its default value is the
+beginning of the file (i.e. 0 ms into the file).
+.LP
+length_wave  Length of wave
+.RS 13
+Default unit: ms.  Default value: remainder.
+.RE
+.LP
+The number of milliseconds of the wave that ought to be processed,
+beyond the start point.  The special value 'remainder' indicates that
+the entire length of the wave from the start point to the end of the
+file should be processed.
+.LP
+samplerate   Input wave sample rate
+.RS 13
+Default unit:  Hertz.  Default value:  20,000 Hz.
+.RE
+.LP
+The rate at which the input wave was sampled.
+.LP
+swap_wave    Swap the bytes in each binary pair of the 
+.RS 13 
+input file
+.RE
+.RS 13
+Switch. Default: off.
+.RE
+.LP
+The order of the bytes in short integers varies between manufacturers.
+Specifically the order for Sun and HP is opposite that for DEC SGI and
+IBM.  The default setting (off) is for the latter byte order.
+.LP
+bits_wave    Bits in the input wave
+.RS 13
+Unit:  bits.  Default:  12. (Only alternate: 16.)
+.RE
+.LP
+The number of significant bits in each (16-bit) word of the input
+wave.  Note that gain_gtf or gaim_tlf should be changed to 0.0625 when
+the number of bits is set to 16 to avoid overflow.
+.LP
+dB_wave      Scaling of the input wave 
+.RS 13
+(for physiological route only)
+.RE
+.RS 13
+Units: dB. Default: 60 dB
+.RE
+.LP
+This option enables the user to specify the relative level of
+the input wave in decibels. It is particularly useful for 
+investigating the level-dependent properties of the 
+physiological version of AIM.
+.LP
+The functional route is level-independent and dB_wave is 
+ignored no matter what its value.
+.LP
+dB_wave can also be used to scale the input wave in absolute 
+units, i.e sound-pressure level (dB SPL), using the following 
+equation:
+.LP
+dB_wave = dBSPL - 20log(RMS/200)
+.LP
+where RMS is the root-mean-square amplitude of the input wave, 
+or the portion of the wave or interest, and  dBSPL is the 
+desired sound-pressure level scaling (in dB). For 
+example, to scale to 60 dB SPL a wave with an RMS amplitude
+of 467.3, dB_wave should be set to 52.6.
+.LP 
+Note: The RMS value of a stored input wave can be calculated using 
+the tools provided with the AIM software. 
+
+
+.LP
+.RE
+
+.SH FILES 
+.LP
+ .genwavrc  The options file for genwav.
+.SH SEE ALSO 
+.LP
+genbmm
+.SH BUGS 
+.LP
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+.LP
+.SH ACKNOWLEDGEMENTS
+.LP
+The AIM software was developed for Unix workstations by John
+Holdsworth and Mike Allerhand of the MRC APU, under the direction of
+Roy Patterson. The physiological version of AIM was developed by
+Christian Giguere. The options handler is by Paul Manson. The revised
+SAI module is by Jay Datta. Michael Akeroyd extended the postscript
+facilites and developed the xreview routine for auditory image
+cartoons.
+.LP
+The project was supported by the MRC and grants from the U.K. Defense
+Research Agency, Farnborough (Research Contract 2239); the EEC Esprit
+BR Porgramme, Project ACTS (3207); and the U.K. Hearing Research Trust.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/hdr.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,77 @@
+.TH HDR 1 "1 September 1993"
+
+.SH NAME
+hdr \- Operations on AIM header.
+
+.SH SYNTAX 
+hdr [options] [file]
+
+.SH DESCRIPTION
+Read an AIM output file. If no filename is given then input is expected
+on the stdin. The input from AIM is expected to consist of an AIM header
+followed by some data.
+The header operations are: stripping, querying, or modifying.
+
+.SH OPTIONS
+Options take the form:  <name>=<value>
+and abbreviated option names are recognised provided they are unambiguous
+wrt other names in the input header.
+
+.nf
+
+1. Stripping. If no options are given, then strip the header
+   and write the data which follows the header on the stdout.
+   Eg:
+	gensai output=stdout ... | hdr | ...
+
+2. Querying. An empty value field (ie. <name>=) is interpreted
+   as a query, and the corresponding option value found in the
+   header is printed on the stderr.
+   Eg., to query the value of option pwidth_aid:
+
+	hdr pwid=  file
+
+   Special option names are:
+
+	"all"       causes all option values to be printed.
+	"format"    causes the format of the AIM output file to be printed.
+
+3. Modifying. Each option of the form <name>=<value> is
+   substituted for the corresponding option found in the input
+   header. A new header is constructed using the input header
+   and all given substitutions, and the new header is written
+   on the stdout, followed by the data which follows the input
+   header.
+   Eg., to change the value of pwidth_aid to 32ms:
+
+	hdr pwid=32ms  file >  file2
+
+.fi
+
+.SH "SEE ALSO"
+edframe, fbank
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/integframe.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,89 @@
+.TH INTEGFRAME 1 "1 September 1993"
+
+.SH NAME
+integframe \-   Integrate gensai frames over time or frequency.
+
+.SH SYNTAX 
+integframe [options] [file]
+
+.SH DESCRIPTION
+Read a gensai output file which must have a header.
+Integrate the whole of every input frame in either time or frequency
+by averaging the frame across the appropriate dimension.
+The integration limits for particular frame sequences can be set by limiting
+the size of input frames using the `edframe' program prior to `integframe'.
+Write each integrated frame on the stdout as an array in the given output
+data type. The output does not have a header.
+
+.SH OPTIONS
+
+1. variable
+
+The `variable' option sets the variable of integration. The strings "time"
+and "frequency" are recognised, (which may be abbreviated back to the first letter
+if required).
+
+2. average
+
+When average=on then the average integrated frame is calculated over all input
+frames, and this average integrated frame only is written on the stdout as an
+array in the given output data type.
+
+3. type
+
+The output data type. Recognised types include: char, short, int, double,
+float, ascii. The ascii type means one number string per line of output.
+The input data type is binary shorts, preceded by a gensai header.
+
+4. info
+
+When info=on print the input frame size on the stderr.
+
+.SH  EXAMPLES
+
+1. Integrate the 2nd gensai frame over time from 10ms to 20ms.
+
+.nf
+    gensai output=stdout ... | edframe frame=1 time=10ms-20ms  |  integframe var=time  >  ...
+.fi
+
+2. Integrate the 2nd gensai frame over frequency from channels 5 to 8 inclusive.
+
+.nf
+    gensai output=stdout ... | edframe frame=1 freq=5-8  |  integframe var=freq  >  ...
+.fi
+
+3. Calculating the average summary gensai frame.
+
+.nf
+    gensai output=stdout ... | integframe var=freq av=on  >  ...
+.fi
+
+
+.SH "SEE ALSO"
+options edframe
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/loudness.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,43 @@
+.TH LOUDNESS 1 "1 September 1993"
+
+.SH NAME
+loudness \- Loudness measure from spiral sector-weights contour.
+(Input and output in binary shorts).
+
+.SH SYNTAX 
+loudness  [arguments]  [file]
+
+.SH DESCRIPTION
+Loudness measure from spiral sector-weights contour.
+For each frame (of m sector-weights) compute one binary short loudness
+measure.
+
+.SH EXAMPLES
+echo q | genspl output=stdout file  |  sp_weights  >  file.wts
+
+loudness file.wts > file.l
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/manaim.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,89 @@
+.TH MANAIM 1 "18 May 1994"
+
+.SH NAME 
+manaim \- Displays help/manual documentations on-line.
+
+.SH SYNTAX
+manaim 
+.IR page-title
+
+manaim -k 
+.IR keyword  
+
+manaim -F
+.IR filename
+
+.SH DESCRIPTION
+This command uses the standard Unix man command.  The path for searching man
+pages is the ~release/man directory. 
+
+The basic function of manaim is to provide on-line displays of AIM reference 
+pages.  The manaim command formats (using Nroff) and displays one or more
+specified reference/manual pages.  
+
+For keyword search the 
+.IR -k 
+option will display one line summary of each command where the string of
+keyword is matched by identical strings in the aim/release/man/whatis file.
+
+For filename search the
+.IR -F 
+option attempts to locate manual pages related to any of the given filenames, 
+and then prints one-line summaries containing the resulting names.
+This option also uses the whatis database.
+ 
+
+.SH "EXTENDED OPTION DESCRIPTION"
+Manaim command provides help information about the AIM tools and other
+options.  There is another command called listdoc 
+.IR file-name, 
+which displays long documents on-line (e.g. bibliography), which are not 
+necessarily help pages. 
+
+.SH FILES
+/home/cedar/local/aim/release/script/manaim
+
+.SH "SEE ALSO"
+createman(1), enterman(1), editman(1), delman(1) and listscript(1).
+
+.SH BUGS
+No bugs yet.
+
+.SH EXAMPLES
+For screenful of text:
+
+manaim 
+.IR ptrain; 
+manaim 
+.IR fft.
+
+For keywords (an apropos command):
+
+manaim 
+.IR -k 
+.IR atob
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/merge.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,154 @@
+.TH MERGE 1 "15 September 1993"
+
+.SH NAME
+merge \- Merge N streams onto stdout using a given operator.
+
+.SH SYNTAX 
+merge [options] file1 file2 ... fileN
+
+.SH DESCRIPTION
+
+Extract items of given data type from file1 to fileN, merge them
+N-wise using the given operation, and write the result on the stdout as
+items of the same type as that selected for input.
+
+.SH OPTIONS
+
+1. type
+
+The input/output data type. Allowable types are: char, short, int, float,
+double, ASCII (one number per line).
+
+2. operator
+
+For each vector of items (p1,p2,...,pN) read from file1, file2,...,fileN
+respectively write the result of a merging operation on the stdout.
+The operation is selected using the
+option "operator=<op>". The <op> may be one of the following strings
+(which may be abbreviated provided this is unambiguous):
+
+.nf
+    <op>                comment
+
+    cat                 concatenate p1,p2,p3,...,pN
+    add                 p1+p2+p3+...+pN
+    subtract            p1-p2-p3-...-pN
+    abs                 |...||p1-p2|-p3|-...-pN|
+    multiply            p1*p2*p3*...*pN
+    divide              p1/p2/p3/.../pN
+    max                 max(p1,p2,p3,...,pN)
+    min                 min(p1,p2,p3,...,pN)
+    mean                ( p1+p2+p3+...+pN ) / N
+    norm                sqrt( p1*p1 + p2*p2 + p3*p3 + ... + pN*pN )
+.fi
+
+
+3. range
+
+The `range' option sets the start and duration of the merge process.
+Samples in a file are numbered 0,1,2,...,max, and the range option delimits
+input from all input files inclusively. Its arguments are of the form:
+
+.nf
+    range=a-b           setting start=a and duration=b-a+1
+    range=a             setting start=a and duration=1
+.fi
+
+The arguments can be in time units (ms, s) or samples (no units), and both
+"min" (start of file) and "max" (end of file) are recognised.
+Arguments with time units are converted to samples using the given
+`samplerate' option.
+
+4. phase
+
+The `phase' option shifts the origin to introduce a phase difference between
+files. The `phase' option takes a comma-separated list of
+arguments which must be the same length as the number of file arguments.
+Each argument can be in time units (ms, s) or samples (no units).
+Arguments with time units are converted to samples using the given
+`samplerate' option.
+
+All files are interpreted as functions sampled with origin at the point in
+the file given by the first argument of the `range' option.
+The functions are assumed to be zero for all samples beyond those specified
+in the files.
+A positive phase advances the origin into the file,
+and this initial lead is skipped before the merging process begins.
+A negative phase retards the origin, and this lag is included at the
+beginning of the merging process.
+If a negative phase in combination with
+the start of the file as set by the `range' option shifts the origin
+outside the specified file, then the difference is padded with zeroes.
+
+5. weights
+
+The weights option takes as argument a comma-separated list of real numbers
+which must be the same length as the number of file arguments.
+These number are applied as weighting factors to each item prior to the
+merging operation.
+
+6. scale
+
+Internal processing is in floating point. A scale factor is included to
+avoid overflow when casting output data.
+If 16-bit over or under-flow occurs a warning is printed on the stderr.
+
+
+.SH EXAMPLES
+
+1. Pairwise concatenation to form coordinate (x,y) pairs from two files.
+
+.nf
+	merge op=cat  file.x file.y  > file.xy
+.fi
+
+2. Pooling data to form an average.
+
+.nf
+	merge op=mean file1 file2 ... fileN  >  Pool
+.fi
+
+3. Weighted linear combination of three files using weight vector (1.0,-2.4,0.05).
+
+.nf
+	merge op=add weights=1.0,-2.4,0.05  file1 file2 file3
+.fi
+
+4. Modulation of one signal file by another. In this example the second file
+is given a 20ms lag with respect to the first, and this lag will be padded
+with zeroes.
+
+.nf
+	merge op=mult phase=0,-20ms  file1 file2
+.fi
+
+
+
+.SH "SEE ALSO"
+
+options op
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/naptosai.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,116 @@
+.TH NAPTOSAI 1 "14 September 1993"
+
+.SH NAME
+naptosai \-  NAP to SAI format conversion.   
+
+.SH SYNTAX 
+naptosai  [arguments]  [file]
+
+.SH DESCRIPTION
+
+The program expects to read an AIM header, and interprets input as one large
+frame in column-wise format (eg output from genbmm, gennap, etc.), to be
+divided into input frames according to the given options.
+Each frame is output in row-wise format (eg as if output from gensai).
+
+The options "start" and "length" specify the input file.
+The special option value length=max specifies all the input file from
+the given start to its end.
+The options "width" and "frstep"  specify the framing.
+The width option is the width of each frame and the frstep option is the
+frameshift between successive frames in the input file.
+The special option value width=max specifies the input framewidth as equal
+to the given input file length, (and if this is also "max", then the
+input framewidth is the remainder of the input file).
+If frstep=0, then the output is one frame of given width from the given start
+of the input file. For example, use naptosai with width=max and frstep=0
+to produce one SAI frame the same size as the input NAP.
+
+A new header is constructed, and most options in the input header are copied
+to the output header. Some parts of the header are changed for the output
+format: (frames, frameshift, framewidth, frameheight, framebytes).
+
+
+.SH EXAMPLES
+
+.nf
+1. To convert a nap or a bmm output to a single frame of sai output:
+
+gennap length=64 output=stdout file | naptosai width=32ms frstep=0 > file.sai
+gensai top=1000 useprevious=on file
+
+genbmm output=stdout file | naptosai  > file.sai
+gensai bottom=-100 useprevious=on file
+
+
+  This uses special case of zero frstep to generate one frame of output with
+  the given width. The default width is the given length, and the default
+  length is the remainder of the input file. If the width=length, then the
+  frstep is zero by default, and therefore the default process, (ie with no
+  arguments), converts the whole of the input to a single SAI frame.
+
+  Note, certain display parameters have different default values for different
+  applications. The SAI display parameters should be set to the appropriate
+  values, in order to plot the SAI on the same scale. For example:
+
+    When the source application is NAP, set gensai top=1000
+    When the source application is BMM, set gensai bottom=-100
+
+2. To convert a nap output to multiple frames of sai output:
+
+gennap length=40 output=stdout file | naptosai width=32ms frstep=0.2ms > file.sai
+gensai top=1000 useprevious=on file
+
+   The sai output can be plotted as a spiral, but it is best to set the
+   display parameters as follows:
+
+gennap length=40 output=stdout dencf=1 width=500 height=500 file |
+       naptosai width=32ms frstep=0.2ms > file.sai
+genspl useprevious=on pensize=2 file
+
+
+
+3. To convert a nap output to a sai format bitmap, to display an animated
+   stream:
+
+gennap length=40 output=stdout file | naptosai width=32ms frstep=0.2ms > file.sai
+gensai top=1000 useprevious=on bitmap=on file
+review file
+
+  The same can be done for the spiral display:
+
+gennap length=40 output=stdout dencf=1 width=500 height=500 file |
+       naptosai width=32ms frstep=0.2ms > file.sai
+genspl useprevious=on pensize=2 bitmap=on file
+review file
+
+  The plots show the nap moving though 8ms (40-32), in steps of 0.2ms,
+  first in rectangular display, then in spiral-mapped display.
+.fi
+
+.SH BUGS
+None yet.
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/noise.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,58 @@
+.TH NOISE 1 "1 September 1993"
+
+.SH NAME
+noise \-   generate samples of a normally distributed deviate (white noise)
+in binary shorts or floats.
+
+.SH SYNTAX 
+noise [options]
+
+.SH DESCRIPTION
+Generate uniformly distributed numbers in the range [0,1] and then convert
+these to normally distributed numbers with zero mean
+and unit variance, using the Box-Muller method described in Numerical
+Recipes [p203].
+The period of the random sequences is claimed to be infinite,
+[Numerical Recipes, p196].
+The random sequence is written to the stdout in binary numbers which are
+either shorts or floats depending upon the `type' option.
+The `duration' options sets the duration of the output sequence in samples,
+converted from time units (s or ms) using the given `samplerate' option.
+
+.SH OPTIONS
+
+1. mean, variance.
+
+Each sample is scaled using the given mean and variance parameters so that
+samples are drawn from a normal distribution of given mean and variance.
+
+2. seed
+
+When seed=off the system call getpid() is used to supply a new seed each run.
+Otherwise the seed can be set in order to give the same initialization to
+generate the same random sequence on different runs.
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/op.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,130 @@
+.TH OP 1 "14 September 1993"
+
+.SH NAME
+op \- Ordered sequence of operations on input stream.
+
+.SH SYNTAX 
+op  [options]  [file]
+
+.SH DESCRIPTION
+
+A sequence of operations is done on each item in the input stream.
+The operations are done in the order they appear on the
+command line. Operations can be repeated as many times as needed on the
+command line.
+
+Input items may be binary numbers (short or float) or ascii lines
+(terminated by CR) according to the type option.
+
+.SH OPTIONS
+
+1. Operations.
+
+The list of operations is as follows. Some operations take valued
+arguments (which are real numbers), others are flags, as indicated:
+
+.nf
+    operation           result for each input item x
+
+    add=<value>         x+<value>
+    negate=on           -x
+    multiply=<value>    x*<value>
+    divide=<value>      x/<value>
+    remainder=<value>   real remainder of x/<value>
+    inverse=on          1/x
+    round=on            x rounded to nearest integer
+    absolute=on         |x|
+    power=<value>       x^<value>
+    exponent=<value>    <value>^x
+    e-exponent=on       e^x
+    log=<value>         log(x) to base <value>
+    e-log=on            log(x) to base e.
+    sin=on              sin(x)
+    cos=on              cos(x)
+    tan=on              tan(x)
+    threshold=<value>   if ( x  <value> ) 0 else if ( x = <value> ) 1
+    diff1=on            first difference
+    diff2=on            second difference
+    diff3=on            third difference
+    cusum=on            cumulative sum
+    cumean=on           cumulative (recursive) mean an
+    cumin=on            cumulative min
+    cumax=on            cumulative max
+.fi
+
+
+2. type.
+
+The `type' option sets the data type for all input and output items.
+Recognised data types are: short, float, ascii.
+
+Ascii data is read in line-by-line, and comment lines are allowed.
+The following operation apply only to ascii input items, enabling
+comment lines to be stripped or echoed directly to the output.
+
+.nf
+    strip=<value>       ignore lines beginning with <value> string
+    echo=<value>        echo lines beginning with <value> string
+    number=on           number output lines
+.fi
+
+If number=on then stripped lines are not numbered; they simply dissappear.
+If there are no operations, (other than comment stripping/echoing or line
+numbering), then ascii lines are echoed.
+
+
+.SH EXAMPLES
+
+1. Specify the following ordered sequence of operations on each binary
+float in the input stream: invert (take reciprocal), scale up by 100,
+square (raise to power 2), invert (take reciprocal), square root (raise to
+power 0.5).
+
+op type=float inverse=on multiply=100 power=2 inverse=on power=.5  file
+
+2. Increase dynamic range by powering up and scaling down.
+(Note that internal calculating is done in floating point; the short datatype
+applies only to input and output).
+
+op type=short power=4 divide=3e8 file
+
+3. Print out the result of log2(17/16).
+
+echo 17 | op type=ascii -div16 -log2
+
+4. For each input number x output exp(-0.2x)
+
+op mult=-0.2 e-exp=on
+
+5. Read ascii data ignoring any comment lines defined as beginning with the
+string "**". Read one ascii number per line and for each number x output 149-x.
+
+op type=ascii strip="**" neg=on add=149  file
+
+.SH "SEE ALSO"
+
+options merge
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/options.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,289 @@
+.TH OPTIONS 1 "1 September 1993"
+
+.SH NAME
+options \- a general description of the AIM tools options handler.
+
+.SH SYNTAX
+
+.nf
+    command line  ::=  <program name>  [<options>]  [<filename>]
+
+    option        ::=  <flag option> | <valued option>
+
+    flag option   ::=  -<name> | [-]<name>=on|off
+
+    valued option ::=  -<name>[=]<value> | [-]<name>=<value>
+.fi
+
+.SH DESCRIPTION
+
+A program may take one or more files as input, and several options to set
+internal parameters. The function of the options handler is to parse the
+command line and interpret options according to the defined syntax,
+to assign internal default values to the internal parameters represented by
+each option, and then to override these using any corresponding options
+found on the command line.
+
+
+.SH "Command line syntax"
+
+Programs which do not read input from files have a command line:
+
+.nf
+    <program name>  [<options>]
+.fi
+
+Programs which expect to read input from one or more files have command line syntax:
+
+.nf
+    <program name>  [<options>]  [<filenames>]
+.fi
+
+The command line parser assumes that each space-separated token on the command
+line is either an option or a filename.
+The strategy is to parse the command
+line until either it is empty or a token with invalid option syntax is found.
+All tokens remaining on the command line after parsing are assumed
+to be input filenames.
+Programs which read from one or more files expect the filenames to be given as
+the final arguments on the command line.
+If the command line is empty after parsing the options, but a file is expected,
+then input is read from the standard input, (eg. via re-direction or a pipe).
+The filename `-' is also interpreted as the standard input.
+
+Typographical errors which cause options to have bad syntax are therefore treated as
+potential filenames.
+The program reports the error as if it were a file not found, by printing a message
+on the stderr:
+
+.nf
+    <program name>: can't open <option>
+.fi
+
+and quits with an exit status of 1.
+In the (unlikely) event that a file with a name matching the error is found
+then this file will be opened for input to the program.
+
+.SH "Option syntax"
+
+The general syntax for flag options (which do not take a <value> part) is:
+
+.nf
+    -<name> | [-]<name>=on|off
+.fi
+
+The general syntax for valued options is:
+
+.nf
+    -<name>[=]<value> | [-]<name>=<value>
+.fi
+
+The usual Unix notation is observed, (characters within square brackets
+are optional and the bar sign denotes exclusive OR) so that flag options
+may take any of the forms:
+
+.nf
+    -<name>
+    -<name>=on
+     <name>=on
+    -<name>=off
+     <name>=off
+.fi
+
+Similarly, valued options may take any of the forms:
+
+.nf
+    -<name><value>
+    -<name>=<value>
+     <name>=<value>
+.fi
+
+Option syntax is designed to be compatible between a Unix options
+style and a more declarative style. This is facilitated by allowing the <name>
+part of each option to be given in abbreviated form provided this
+is unambiguous with other options for the program.
+
+The general option syntax in Unix and the declarative style respectively is:
+
+.nf
+    -<name><value>
+    <name>=<value>
+.fi
+
+An example of the same option in both styles respectively would be:
+
+.nf
+    -t10
+    time=10
+.fi
+
+
+In many cases the option names are designed to be unambiguous from the first
+letter to allow for complete compatibility, but in some cases the need for
+declarative option names was felt to override the need for absolute compatibility.
+If necessary any option name can easily be changed by changing the name
+given in the first field of the static Options structure defined near the
+top of each program source code, and then re-compile the program.
+The change affects only the user interface via the options handler and has
+no other side effects.
+
+An exact match for option <name> is unambiguous even if the <name> matches
+the head of another option <name>.
+
+If insufficient of the <name> part is given to disambiguate it from other
+options, then the program prints a message on the stderr:
+
+.nf
+    <program name>: ambiguous option [<option>]
+.fi
+
+and quits with an exit status of 1.
+
+For example, if a program takes options with names `frames' and `frameshift'
+then the following are synonymous for setting the frameshift to 20:
+
+.nf
+    frameshift=20
+    framesh=20
+    -framesh20
+.fi
+
+but the following would be ambiguous:
+
+.nf
+    -f20
+    -frame20
+.fi
+
+However an exact match is allowed to be unambiguous, so that the following would
+set the frames option to 3:
+
+.nf
+    frames=3
+    -frames3
+.fi
+
+.SH "Option values"
+
+The <value> part may take the form of a number with optional units.
+Time variables may be given in s (seconds) ms (milliseconds) and p (sample points).
+The default with no units is interpreted as sample points.
+For example:
+
+.nf
+    10      10 samples
+    10p     10 samples
+    10s     10 seconds
+    10ms    10 milliseconds
+.fi
+
+Values given with time units are converted to a number of samples internally
+using the given `samplerate' option.
+
+Frequency variables take Hz (Hertz) and kHz (KiloHertz).
+The default with no units is interpreted as Hertz..
+For example:
+
+.nf
+    20000   20000 Hertz
+    20000Hz 20000 Hertz
+    20kHz   20000 Hertz
+.fi
+
+A <value> may be given as a hyphen-separated range of values with the general syntax:
+
+.nf
+    <value> = a[-b]
+.fi
+
+where `a' and `b' are both values or the strings "min" or "max".
+For example, the `frame' option is used to select a range of frames for
+processing:
+
+.nf
+    frame=a      Select just the a'th frame.
+    frame=a-b    Select frames from the a'th to b'th inclusive.
+    frame=min    Select the first frame.
+    frame=max    Select the last frame.
+    frame=a-max  Select frames from the a'th to the last inclusive.
+    frame=min-b  Select frames from the first to the b'th inclusive.
+.fi
+
+Values which specify a time or frequency range take units as appropriate.
+For example:
+
+.nf
+    range=10ms-40ms
+.fi
+
+
+.SH "On-line help"
+
+All tools take an option called `help' which causes the program to print
+help information on the stdout.
+The following are usually synonymous calls for help:
+
+.nf
+    <program name>  -h
+    <program name>  -help
+    <program name>   help=on
+.fi
+
+In some cases the abbreviation `-h' will be ambiguous with another option
+name, however `-help' and `help=on' are always unambiguous.
+The help printed on the stdout includes a summary of the program's
+application, it's command-line syntax or usage, and a list of the program
+options with their default values and a brief comment about the use of each option.
+The option syntax for each option is printed in place of
+option comment line when the call for help takes the form:
+
+.nf
+    <program name>  help=syntax
+.fi
+
+Help with particular named options can be called with:
+
+.nf
+    <program name>  help=<name>
+.fi
+
+where the <name> part can be abbreviated provided it is unambiguous.
+Certain options are `silent' in the sense that they are not printed in the
+options list by the standard call for help because they are considered to
+be rarely used. However they can be included in the options list by the call:
+
+.nf
+    <program name>  help=all
+.fi
+
+Silent options are assigned on the command line in the same way as ordinary
+options.
+
+.SH BUGS
+
+A filename which matches a typographical error in option name would be
+opened for input, leading to unexpected results.
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/pitch_strength.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,48 @@
+.TH PITCH_STRENGTH 1 "1 September 1993"
+
+.SH NAME
+pitch_strength \- Pitch-strength measure from spiral sector-weights contour.
+(Input and output in binary shorts).
+
+.SH SYNTAX 
+pitch_strength  [arguments]  [file]
+
+
+.SH DESCRIPTION
+Pitch strength measure from spiral sector-weights contour.
+For each frame (of m sector-weights) compute one binary short pitch
+strength measure.
+
+The number of sectors (see sector_weights.c) is fixed at 64.
+The default projection vector in pitch_strength.c is designed for 64 sectors.
+This cannot be reset without re-training.
+
+.SH EXAMPLES
+echo q | genspl output=stdout file  |  sp_weights  >  file.wts
+
+pitch_strength file.wts > file.ps
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/ptrain.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,63 @@
+.TH PTRAIN 1 "14 September 1993"
+
+.SH NAME
+ptrain  \-  generate a pulse train of binary shorts.
+
+.SH SYNTAX 
+ptrain  [arguments]  [file]
+
+
+.SH DESCRIPTION
+Generate periods of a pulse train in binary 2-byte numbers to the given
+waveform duration.
+A period in samples is computed (using the "period" option in samples or in
+time units, in which case the period also depends upon the given samplerate),
+and "width" samples at the start of every period are output with the given
+"amplitude", the remaining samples in the period having zero amplitude.
+The pulse amplitude is the pulse height above the zero level, which is
+set by the offset option. The offset is "0" by default so that pulses
+of any given amplitude are non-negative by default.
+
+The default output is 12 periods of an 8ms pulse train at 20KHz (ie with 160
+samples per period), with pulse width 4 samples and pulse amplitude 1024.
+
+If a filename argument is given, then the period of the output pulse train
+is taken from the file. Binary shorts read from the file are successive
+periods in samples, and periods are output until the file is empty.
+This enables pulse trains with modulated periods.
+
+.SH EXAMPLES
+
+
+1. A pulse train with period 100 samples and pulse width 1 sample:
+
+ptrain period=100p width=1p
+
+2. A pulse train with period 8ms at 20KHz and pulse width 4 samples
+
+ptrain period=8ms samplerate=20000Hz width=4p
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/racf.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,63 @@
+.TH RACF 1 "1 September 1993"
+
+.SH NAME
+racf \- recursive autocorrelation function of contiguous frames.
+
+.SH SYNTAX 
+racf  [arguments]  [file]
+
+.SH DESCRIPTION
+Autocorrelation function using a recursive "leaky integrator" filter.
+For the m'th lag, the n'th recursive update is:
+
+.nf
+      y[n] = a.y[n-1] + (1-a).f[n].f[n-m]
+.fi
+
+where decay constant a = exp(-Ts/T),
+Ts is the sample interval in seconds, and T  is the decay time constant in seconds.
+
+The recursion computes the mean value of the product f[n].f[n-m]
+within an exponential window which weights past values.
+The window width parameter (eg. corresponding with the width of the
+fft analysis window) is the time constant parameter.
+The half life of the exponential window is given by -T.ln(0.5) = 0.693T
+ie. for a given time constant, T secs, the window decays to half of its
+current value in a period of 0.693T secs.
+Similarly, the window decays by 99% of its initial value in about 4.6T secs.
+So T can be set to accomodate an expected period.
+
+The routine generates the autocovariance function.
+An optional normalization (dividing each coefficient by the zeroth
+coefficient) produces the autocorrelation function,
+(and this is then scaled up to the range [0-1000]).
+
+The output framewidth is the given maximum acf lag.
+
+.SH "SEE ALSO"
+options acf acgram
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/ramp.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,124 @@
+.TH RAMP 1 "1 September 1993"
+
+.SH NAME
+ramp \-    generate an exponential sawtooth waveform
+
+.SH SYNTAX 
+ramp [options]
+
+.SH DESCRIPTION
+Generate samples of an exponential sawtooth waveform at a given sample rate.
+Samples are written on the stdout in binary shorts or floats according to
+the `type' option.
+
+.SH OPTIONS
+
+1. period, amplitude, duration.
+
+The `period' option sets the period of repetition of the waveform in samples.
+The `duration' option sets the total duration of the output waveform in
+samples.
+Both may be given with time units (s or ms) in which case the time is converted to
+samples using the given `samplerate' option.
+The `amplitude' option sets the height of the waveform.
+
+2. polarity
+
+The `polarity' option is used to set the direction of the ramp:
+
+.nf
+    polarity=ramp   growing exponential:   A.exp(t-T)   0<=t<=T
+    polarity=damp   decaying exponential:  A.exp(-t)    0<=t<=T
+.fi
+
+3. decay
+
+The argument of the exponential is calibrated so that the decay factor is
+a half-life period.
+The wave grows/decays to half its given amplitude in the given decay time.
+
+.SH EXAMPLES
+
+1. Growing exponentials
+
+.nf
+	    ramp polarity=ramp dec=1ms
+.fi
+
+2. Decaying exponentials
+
+.nf
+	    ramp polarity=damp dec=1ms
+.fi
+
+3. Half a cycle of an 8ms decaying exponential.
+
+.nf
+	    ramp polarity=damp dec=1ms dur=4ms
+.fi
+
+4. Modulating a tone with a damped exponential.
+Note: modulating can be done in floating point using a ramp with unit
+amplitude, or it can be done in integer arithmetic as below.
+The scale factor in the `merge' program is used to avoid 16-bit overflow.
+
+.nf
+	    tone period=.5ms      > foo1
+	    ramp pol=damp dec=1ms > foo2
+	    merge op=mult factor=0.01 foo1 foo2 > foo3
+.fi
+
+5. Modulating a tone with a ramped exponential.
+The 800Hz tone is modulated with a unit ramped exponential with a 25ms
+repetition rate and a 4ms half life.
+
+.nf
+	    tone freq=800Hz amp=10000 type=float   > foo1
+	    ramp pol=ramp period=25ms dec=4ms amp=1 type=float > foo2
+	    merge op=mult type=float foo1 foo2  | ftos > foo3
+.fi
+
+6. Modulating a tone with a damped exponential, and half-wave rectifying to
+generate damped pulses.
+
+.nf
+    tone period=.5ms amp=500 type=float    > foo1
+    ramp pol=damp dec=1ms amp=1 type=float > foo2
+    merge op=mult type=float foo1 foo2 | ftos | gate range=min-0 op=0 > foo3
+.fi
+
+7. Modulating white noise with a ramped exponential.
+
+.nf
+	    noise type=float  > foo1
+	    ramp pol=ramp dec=1ms amp=1 type=float > foo2
+	    merge op=mult type=float foo1 foo2 | ftos > foo3
+.fi
+
+.SH "SEE ALSO"
+options tone ptrain noise
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/saitonap.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,43 @@
+.TH SAITONAP 1 "14 September 1993"
+
+.SH NAME
+saitonap \- SAI to NAP format conversion.
+
+.SH SYNTAX 
+saitonap  [arguments]  [file]
+
+.SH DESCRIPTION
+
+Convert the format of AIM binary output from row-wise (ie SAI) to column-wise
+(ie NAP). The program expects to read an AIM header, and interprets input as
+a succession of frames in row-wise format (eg output from gensai), each to be
+output in row-wise format (eg as if output from genbmm, gennap, etc.).
+A new header is constructed, and most options in the input header are copied
+to the output header. Some parts of the header are changed for the output
+format: (frames, frameshift, framewidth, frameheight, framebytes).
+Each frame output is preceeded by the header.
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/scale.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,117 @@
+.TH SCALE 1 "1 September 1993"
+
+.SH NAME
+scale \-  Shift and scale a binary stream by given constants or to
+fit a given range (top - bottom).
+
+.SH SYNTAX 
+scale [options] [file]
+
+scale -h        -for help with options and their defaults.
+
+.SH DESCRIPTION
+Shifting and scaling is done for all input x using the formula:
+.nf
+      y = ( x - shift ) * scale
+.fi
+
+.SH OPTIONS
+
+1. top, bottom.
+
+If neither shift nor scale factor are given (ie. both options are "off"),
+then values are
+chosen so that the output fits the range specified by `top' and `bottom'.
+For an input file which ranges between extreme values of `max' and `min', the
+shift and scale factors to give a required range between `top' and `bottom'
+are found by simultaneously solving:
+.nf
+      top    = ( max - shift ) * scale
+      bottom = ( min - shift ) * scale
+.fi
+
+If top < bottom then the input is inverted in the resulting range.
+
+2. normalize.
+
+Values of shift and scale are chosen so that the data is normalized for
+zero mean and unit standard deviation.
+
+.nf
+      shift = mean
+      scale = 1 / sqrt( variance )
+.fi
+
+3. shift, scale.
+
+In either or both shift and scale are given (ie. are not "off") then
+the formula is applied directly irrespective of any given top or bottom
+parameters.
+If only a shift term is given, then the default scale becomes 1.0.
+If only a scale factor is given, then the default shift becomes 0.
+
+4. type.
+
+The input and output data type are selected using "type=<type>", where
+<type> = { char, short, int, float, double, ASCII }.
+The ASCII type is interpreted as one number per line.
+
+5. output.
+
+If no filename arguments are given to the program then one input file is
+expected on the stdin, otherwise each given filename is input and scaled in
+turn.
+If "output=off" then program output overwrites each
+respective input file. (The respective output for the stdin is the stdout).
+If the `output' option is given a value (eg. output=filename) then this is
+used as a filename and all scaled input files are written to this output file.
+(The default output filename is the stdout).
+Special value "output=print" suppresses output and prints the shift and
+scale parameters on the stdout.
+
+6. range.
+
+The range option specifies the stretch of the wave for scaling and output by:
+
+	range=a[-b]
+
+The upper limit `b' is optional, and when it is missing then the range
+is a single sample, otherwise `a' and `b' are inclusive range limits.
+The strings "min" and "max" are recognised as extreme limits ("min" =
+start of file, "max" = end of file), otherwise the values of `a' and `b'
+are sample numbers: 0,1,2,...  Values given with time units (ms or s)
+are converted to samples using the given samplerate option.
+
+.nf
+	range=min-10ms    -the first 10ms of each input file.
+	range=128-max     -from the 128'th sample to the end of each file.
+	range=8ms-16ms    -between 8ms and 16ms inclusive for each file.
+.fi
+
+.SH "SEE ALSO"
+options op merge
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/smooth.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,79 @@
+.TH SMOOTH 1 "1 September 1993"
+
+.SH NAME
+smooth  \- Data smoothing by convolution with Gaussian window.
+
+.SH SYNTAX 
+smooth [options] [file]
+
+.SH DESCRIPTION
+Low-pass filter by convolving the input with a unit area Gaussian window
+in the time or frequency domain.
+The transform between domains uses the FFT.
+
+
+.SH OPTIONS
+
+1. length
+
+The amount of input to smooth in time units (ms or s) or samples (no units).
+Time units are converted to samples using the given `samplerate' option.
+The string "max" is recognised as the remainder of input.
+
+2. domain
+
+Select algorithm for smoothing.
+In the time domain ("domain=time") the discrete convolution formula is applied
+directly as a local averaging operation on the input with weights obtained
+by time-reversing and shifting a Gaussian window.
+In the frequency domain ("domain=frequency") the FFT of the whole input is
+multiplied by a Gaussian frequency response function (the FFT of the
+Gaussian window), and the result inverse FFT'd.
+
+3. variance, range
+
+The variance of the Gaussian window and its
+ordinal range in standard deviations either side of the mode.
+The window is assumed to be zero for all time outside the specified range.
+These parameters control the size of the window and consequently the amount
+of smoothing. The larger the variance, the more smoothing.
+The size of the window is given by:
+
+.nf
+	[ 2 * range * sqrt( variance ) ] samples   +  1 sample
+.fi
+
+The variance can be given with time units (ms or s) or samples (no units).
+Time units are converted to samples using the given `samplerate' option.
+
+4. type
+
+The input and output data type. Recognised types are "short" and "float".
+
+.SH "SEE ALSO"
+options gauss filt1 conv
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/sp_weights.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,50 @@
+.TH SP_WEIGHTS 1 "1 September 1993"
+
+.SH NAME
+sp_weights \- Map auditory image frames onto spiral sector-weights contours.
+(Input and output in binary shorts).
+
+.SH SYNTAX 
+sp_weights  [arguments]  [file]
+
+
+.SH DESCRIPTION
+Map auditory image onto spiral sector-weights contour.
+Read auditory image frames (using "output" model option so that frames
+have a pipes header for frame dimensions).
+Use either gensai or genspl output, (but remember that their
+default options are different, particularly pwidth, nwidth, and dencf).
+For each frame, write a sector-weights contour on the stdout, consisting
+of m binary shorts, where m is the given number of sectors.
+
+The sector-weights are an economical representation of each frame (just
+64 numbers per frame) from which both loudness and pitch-strength can be
+computed.
+
+.SH EXAMPLES
+.LP 
+echo q | genspl output=stdout file  |  sp_weights  >  file.wts
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/stats.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,132 @@
+.TH STATS 1 "1 September 1993"
+
+.SH NAME
+stats \-     calculate some statistics.
+
+.SH SYNTAX 
+stats [options] [file]
+
+.SH DESCRIPTION
+Calculate statistics for given frames of each input file and write the
+results on the stdout.
+If no filenames are given, one input file is expected on the stdin.
+Otherwise each given filename is processed in turn.
+
+.SH OPTIONS
+
+1. frame, width, samplerate
+
+The `frame' option selects a sequence of contiguous frames for processing by:
+
+.nf
+	frame=a[-b]
+.fi
+
+where `a' and `b' are frame numbers: 1,2,3,...,max  The upper limit `b' is
+optional, and when it is missing then the frame sequence is a single
+frame, otherwise `a' and `b' are inclusive limits.  The strings "min"
+and "max" are recognised as extreme limits.
+Each frame has size `width' samples which
+may be given with time units (s or ms), in which case the they
+are converted to a number of samples using the given `samplerate' option.
+The special option value "width=max" is interpreted as a single frame covering
+the whole file.
+
+2. type
+
+Datatype for both input and output. Binary types are char, short, int, float, double.
+Ascii input (one number per line) is recognised with "type=ascii".
+
+3. stat
+
+The statistics available to the `stat' option are:
+
+.nf
+    n           sample (ie. data set) size
+    sum         area
+    ss          sum of squares
+    mean        sum/n
+    rms         root mean square: square root of ss/n
+    variance    computed with n-1 degrees of freedom
+    stddev      standard deviation: square root of variance
+    min         minimum value
+    max         maximum value
+    absmax      maximum absolute value, ie. max( |max|, |min| )
+    range       max-min
+.fi
+
+
+The variance is the average squared deviation from the mean value, where the
+average is computed by dividing by n-1 for a data set of n samples.
+The stddev is the square root of this variance.
+The stddev would be equal to the rms value for a data set with zero mean,
+except that the average squared value is computed using ss/n, while the
+average squared deviation from a zero mean value is computed using ss/(n-1).
+
+Statistics may be given in a comma separated list, for example:
+
+.nf
+	stats stat=mean,variance,min,max
+.fi
+
+For each frame of each input file this will output the four statistics in the
+data type selected by the `type' option.
+
+4. line
+
+When line=on (or -l) output is forced to be ascii irrespective of the `type' option,
+and for each file argument in turn stats prints the statistics  requested,
+in the order they were requested, on one line.
+This makes a table (one line per file), and also helps subsequent operations
+between statistics. For example, the standard error of the mean (the stddev
+divided by the square root of the sample size) can be computed:
+
+.nf
+	stats -l stat=stddev,n  |  awk '{ print $1 / sqrt($2) }'
+.fi
+
+Tables can be formatted using field-width and precision arguments which are
+included as silent options. For example, to format columns with a precision
+of 4 decimal places with each number right-justified in a field-width of
+12 characters:
+
+.nf
+	stats -l fieldwidth=12 precision=4
+.fi
+
+The columns may be left-justified by making the fieldwidth parameter negative.
+Output is truncated to integers by setting the precision parameter 0.
+For example, to print the sample size of each file as an integer without
+setting in a field:
+
+.nf
+	stats -l fieldwidth=0 precision=0  stat=n  [files]
+.fi
+
+.SH "SEE ALSO"
+.LP
+options
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/step.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,68 @@
+.TH STEP 1 "1 September 1993"
+
+.SH NAME
+step \- generate a step waveform.
+
+.SH SYNTAX 
+step [options]
+
+.SH DESCRIPTION
+Generate a step up or down of given amplitude at a given shift from the origin
+(start of waveform), and write the resulting waveform on the stdout in the
+given datatype.
+
+.SH OPTIONS
+
+1. shift
+
+The position of the step (up or down) relative to the start of the waveform.
+The shift can be in samples (no units) or can take time units
+(using the samplerate option).
+
+2. amplitude
+
+The height of the step.
+
+3. polarity
+
+The direction of the step: up (zero before the step and `amplitude' after)
+or down (`amplitude' before the step and zero after).
+
+4. duration
+
+The duration of the output wave, including the shift to the step.
+The duration can be in samples (no units) or can take time units
+(using the samplerate option).
+
+5. type
+
+The output datatype. This may be any of: char, short, int, float, double,
+ascii (meaning one ascii number per line).
+
+.SH "SEE ALSO"
+.LP
+options  ptrain  merge
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/stof.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,38 @@
+.TH STOF 1 "7 September 1993"
+
+.SH NAME
+
+stof \-  short to float data-type conversion.
+
+.SH SYNTAX
+
+Usage:  stof  [arguments]  [file]
+
+.SH DESCRIPTION
+
+Binary short-to-float conversion.
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/swab.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,48 @@
+.TH SWAB 1 "14 September 1993"
+
+.SH NAME
+swab \- Swap byte order of binary 2-byte data.
+
+.SH SYNTAX 
+swab   [options]  [files]
+
+.SH DESCRIPTION
+
+For each input file in turn,
+read and write binary shorts (2-bytes), swapping the byte order of each.
+With no filename arguments, data is expected on the stdin.
+
+.SH OPTIONS
+
+output.
+
+The `output' option specifies the name of a single output file to be the
+destination for swapped data from all input files.
+The name "stdout" is recognised as the standard output.
+When the "output=off" the output overwrites each respective input file.
+(The respective output for the stdin is the stdout).
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/tone.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,121 @@
+.TH TONE 1 "1 September 1993"
+
+.SH NAME
+tone \-    generate a pure tone.
+
+.SH SYNTAX 
+tone [options]
+
+.SH DESCRIPTION
+Generate samples of a sine wave at a given sample rate.
+Specify wave amplitude, and frequency (in Hz or kHz), or alternatively
+period (in s, ms, or p (sample points) ). If both period and frequency
+are specified, then the given period takes precedence.
+If S is the given samplerate so that Ts=1/S is the sample interval,
+and phi is the given phase (in samples or time units),
+then each sample of a sine wave of frequency f [Hz] is given by:
+
+.nf
+	sin( TWOPI.f ( n.Ts + phi ) ) ,  n = 0,1,2,...
+.fi
+
+Write samples to the stdout in the given datatype for the given waveform duration.
+
+
+.SH OPTIONS
+
+1. period, frequency
+
+The frequency (in Hz or kHz) and the period (in s, ms, or p (sample points) )
+of the output waveform. Either may be specified, but if both period and frequency
+are specified, then the given period takes precedence.
+
+2. amplitude
+
+The amplitude of the output waveform.
+
+3. phase
+
+The phase offset of the output sine wave with respect to the origin.
+This may be specified as a time (with units s or ms) or as a number of
+samples (with units p or no units), or in degrees (with units deg),
+or the following strings are recognised
+(and may be abbreviated provided this is unambiguous):
+sine (0 phase offset), cosine (1/4 cycle phase offset),
+antisine (1/2 cycle phase offset), anticosine (3/4 cycle phase offset).
+
+4. type
+
+The datatype of the output waveform. The following strings are recognised
+types: char, short, int, float, double, ascii (meaning one ascii number per
+line).
+
+.SH EXAMPLES
+
+1. Sine wave with period 10ms sampled at 10kHz, (100 sample points per period)
+
+.nf
+	    tone period=10ms samplerate=10kHz
+.fi
+
+2. Sine wave with frequency 100Hz sampled at 20kHz
+
+.nf
+	    tone frequency=100Hz
+.fi
+
+3. Sine wave with period 100 sample points, with dc-offset set equal to
+amplitude of 500 so that waveform is just non-negative.
+
+.nf
+	    tone period=100p amplitude=500 offset=500
+.fi
+
+4. Quarter cycle of a sine wave with 8ms period.
+
+.nf
+	    tone period=8ms duration=2ms
+.fi
+
+5. Cosine wave with 8ms period.
+
+.nf
+	    tone period=8ms phase=cos
+.fi
+
+This is equivalent to:
+
+.nf
+	    tone period=8ms phase=2ms
+.fi
+
+
+
+
+.SH "SEE ALSO"
+options ptrain
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/x11fonts.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,123 @@
+.TH X11FONTS 1 "1 September 1993"
+
+.SH NAME
+x11fonts \- search and display fonts.
+
+.SH SYNTAX 
+x11fonts [options] [name_patterns]
+
+.SH DESCRIPTION
+
+Display the font for each font name found in the current font search path
+which matches a given name_pattern.
+Each name_pattern may contain wild-card (*) characters, (but
+names with wild-cards should be quoted to escape the shell).
+The default name_pattern is "*", meaning all fontnames.
+
+Each font is displayed in an X window in the form:
+
+.nf
+    [m/n]   <full fontname>
+
+     <alphabet>
+.fi
+
+showing the m'th font out of n fonts which match the current name_pattern.
+The pointer is used to click through the fonts which match each given name_pattern
+as follows:
+
+.nf
+    left button
+.fi
+
+Clear the last font displayed and
+display the font for the next fontname in its place.
+
+.nf
+    centre button
+.fi
+
+Display the font for the next fontname beneath the last font
+displayed. This is used to store particular fonts for comparison with others.
+When successive fonts have filled the window
+it is cleared and the last font is re-displayed at the top of
+the window.
+
+.nf
+    right button
+.fi
+
+Begin the next name_pattern.
+The program quits when there are no more name patterns.
+
+.SH OPTIONS
+
+.nf
+    -n
+.fi
+
+Print on the stdout a count of the fonts found in the search
+path which match each name_pattern.
+
+.nf
+    -l
+.fi
+
+Print on the stdout a list of the font names found in the
+search path which match each name_pattern.
+
+.nf
+    -P
+.fi
+
+Print on the stdout the current font search path
+(see: XGetFontPath XSetFontPath).
+
+
+.SH EXAMPLES
+
+1. Print a count of how many fonts match the name_pattern "-adobe*" and then
+list their names on the stdout.
+
+.nf
+	x11fonts -n "-adobe*"
+	x11fonts -l "-adobe*"
+.fi
+
+2. Compare fonts "fixed" and "variable" (use button sequence: right, centre).
+
+.nf
+	x11fonts  fixed variable
+.fi
+
+3. Display the alphabet of a particular font name "7x14", then of all fonts
+ending with the pattern "x16", and then of all bold fonts.
+
+.nf
+	x11fonts  7x14  "*x16" "*bold*"
+.fi
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/x11gram.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,49 @@
+.TH X11GRAM 1 "1 September 1993"
+
+.SH NAME
+
+x11gram \- Landscape plot of successive frames.
+
+.SH SYNTAX 
+
+x11gram [arguments] [file]
+
+.SH DESCRIPTION
+
+Read successive frames and plot them as a landscape.
+
+.SH EXAMPLES
+
+1. Landscape plot of successive fft spectra
+
+.nf
+	fft width=128 frstep=2 file  |  x11gram -n64
+.fi
+
+.SH "SEE ALSO"
+x11play
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/x11play.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,62 @@
+.TH X11PLAY 1 "1 September 1993"
+
+.SH NAME
+x11play \- animated plot of sets of n points, read as binary shorts.
+
+.SH SYNTAX 
+a) x11play  [options]  filename
+
+b) cat filename  |  x11play  [options]
+
+where filename is an input stream of 16-bit binary numbers (shorts)
+
+.SH DESCRIPTION
+
+Animate successive plots of n points, read as binary shorts.
+
+Quit program with left mouse button.
+
+With the -S flag (ie step-mode), single-step through frames using the mouse
+as follows:
+
+.nf
+    left -   quit
+    centre - freeze animation (successive centre
+             buttons give single successive frames).
+    right  - continue animation
+.fi
+(animation is slower in step-mode because XSynchronise has to be on).
+
+.SH EXAMPLES
+
+1. To animate successive fft spectra
+
+fft samp=10kHz width=12.8ms frstep=2p file | x11play -n64
+
+.SH "SEE ALSO"
+.LP
+x11plot x11gram x11fonts
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/x11plot.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,51 @@
+.TH X11PLOT 1 "1 September 1993"
+
+.SH NAME
+x11plot \- plot n points, read as binary shorts.
+
+.SH SYNTAX 
+a) x11plot   [options]  filename1  [filename2 ...
+
+b) cat filename  |  x11plot  [options]
+
+where filename is an input stream of 16-bit binary numbers (shorts) 
+
+.SH DESCRIPTION
+A no-scale plot for X11 windows. Single files are plotted as waveforms, or
+multiple files are overplotted.
+
+The mouse is used to control the window:
+.nf
+    left button   = print plot coordinates of cursor at
+                    its screen coordinate.
+    centre button = re-draw plot, clearing any printed coordinates.
+    right button  = exit program (destroy windows).
+.fi
+
+.SH "SEE ALSO"
+.LP
+x11play x11gram x11fonts
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/man1/xreview.1	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,312 @@
+.TH XREVIEW 1 "12 May 1995"
+.LP
+.SH NAME
+.LP
+xreview \- display of AIM cartoons for X Window System
+.SH SYNOPSIS
+.LP
+xreview [options] [filename]
+.LP
+.SH OVERVIEW
+.LP
+xreview is a program for displaying bitmap cartoons produced by the AIM
+software. All frames of a cartoon or a subset of frames can be played.
+The speed may be slowed and it is possible to step through
+a cartoon frame-by-frame. It has been tested under X11R4 and above. 
+.SS GENERATION OF BITMAP CARTOONS
+.LP
+Any AIM module that creates a sequence of pictures, or "frames", may be used
+to generate a cartoon. The frames are saved as bitmaps; that is, a copy
+of the screen memory for the frame.  The bitmaps are created using the option "bitmap". For example,
+.RS 4
+  gensai [options] -bitmap [options] waveform
+.RE
+.LP
+This creates a file called "waveform.ctn", which can be used as input
+to xreview.
+.LP
+xreview reads and plays the sequence of bitmaps. The bitmap option
+is available for AIM modules genasa, genepn, gensai and genspl.
+.LP
+Because the bitmaps are an exact copy of the screen memory, it is impossible
+to change either the size of the cartoon or any AIM display parameters 
+within xreview. In addition, if the cartoons are generated on a mulitplane
+screen (e.g. 8 bits deep) then the bitmaps are very big, even though only
+two colours are used by the AIM display software.  The hidden option "mono_ctn=on" 
+may be used to copy only a 1-bit plane from the screen to the bitmaps.
+On some machines the incorrect plane may be copied, in which case the 
+cartoon displayed by xreview looks completely different to the cartoon
+as it was generated by the AIM software. If this occurs, then
+the option "planemask_ctn" may be used to specify which plane is copied.
+This is best done by trial-and-error.  The hidden option "colour_ctn=on" forces
+all planes to be copied to the bitmaps.
+.RE
+
+.SS DISPLAY OF BITMAP CARTOONS
+.LP
+The basic xreview command is 
+.LP
+	xreview [options] waveform.ctn
+.LP
+This loads the entire cartoon and displays the first frame.  
+There are two control modes: 
+.LP
+ (a) keyboard and mouse-buttons within the Cartoon Window, 
+.LP
+.RS 1
+or
+.RE
+.LP
+ (b) a separate "Controls Window".
+
+
+.SS KEYBOARD CONTROL (cursor in the Cartoon Window)
+.LP
+space/return: animate cartoon once (leaving the last 
+.RS 35
+frame displayed).
+.RE
+.LP
+.RS 4
+n:     move to and display next frame
+.LP
+p:     move to and display previous frame
+.LP
+q:     quit xreview.
+.RE
+
+
+.LP
+left mouse button:    animate cartoon once (leaving the  
+.RS 30
+last frame displayed).
+.RE
+.LP
+right mouse button:   quit xreview.
+.LP
+middle mouse button:  display Controls Window.
+.RE
+
+.SH CONTROLS WINDOW
+.LP
+'Buttons' in the Controls Window set the start frame and end frame of the 
+animation, the framestep in the animation (e.g., skip every 2nd frame) and
+the speed of the animation; the number indicates the delay between
+frames in ms.  The buttons in the bottom panel move to and display a single
+frame:
+.LP
+<<       back 10 frames
+.LP
+<        previous frame
+.LP
+>        next frame
+.LP
+>>       forward 10 frames
+.LP
+first    first frame
+.LP
+middle   middle frame
+.LP
+last     last frame
+.LP
+The numbers in the bottom-right corner indicate the current frame and the
+total number of frames.
+.LP
+Unlike AIM displays from gen??? instructions, the cartoons may be
+moved, iconified, hidden, etc. in the normal way.  The gen???
+instructions are from an earlier are when few graphical tools were
+available.
+
+.SH OPTIONS
+.LP
+There are a number of command-line options; special purpose
+abbrievations are indicated in parentheses.  (The instructions are in
+a slightly different form to the gen??? instructions.)
+.LP
+.SS   Control Window Options
+.LP
+.RS 5
+-controls   automatically display controls window 
+.RE
+.RS 17
+(-con)
+.RE
+.RS 5
+-controls_x <int>  x-position of controls window 
+.RE
+.RS 24 
+in pixels   (-cx)  
+.RE
+.RS 5
+-controls_y <int>  y-position of controls window 
+.RE
+.RS 24
+in pixels (-cy)    
+.RE
+.RS 5
+-controls_size <string>  size of controls window:  
+.RE
+.RS 30
+(-csize)  
+.RE
+.RS 30
+"tiny", "small" or "normal"
+.RE
+
+.SS   Cartoon Options
+.LP  
+.RS 5 
+-image_x <int>  x-position of cartoon in pixels  (-ix)          
+.RE
+.RS 5
+-image_y <int>  y-position of cartoon in pixels  (-iy)          
+.RE
+.RS 5
+-speed   <int>  delay between frames in ms; default = 1 
+.RE
+.RS 21
+(-speed)
+.RE
+.RS 5
+-start   <int>  start frame of animation; 
+.RE
+.RS 21
+default = first  (-start)
+.RE
+.RS 5
+-stop    <int>  stop frame of animation; 
+.RE
+.RS 21
+default = last    (-stop)
+.RE
+.RS 5
+-skip    <int>  framestep in animation; 
+.RE
+.RS 21
+default = 1        (-skip)
+.RE
+.RS 5
+-frame   <int>  intial frame to display; 
+.RE
+.RS 21
+default = first   (-frame)
+.RE
+.RS 5
+-help   generate the help page   (-h)
+.RE
+.RS 5
+-verbose  send some running information 
+.RE
+.RS 15
+to stderr    (-v)
+.RE
+
+.LP
+.SS   Cartoon Window Options
+.LP  
+.RS 5
+-display <string>  X display server to use   -d
+.RE
+.RS 5
+-font <font>       font used in controls window 
+.RE
+.RS 24
+(default = Times) -f
+.RE
+.RS 5
+-point <int>       fontsize (default depends upon 
+.RE
+.RS 24
+size of controls window)
+.RE
+.RS 5
+-title <string>    title of cartoon window 
+.RE
+.RS 24
+(and of its icon)
+.RE
+.RS 5
+-mono              assume monochrome (single-plane)   
+.RE
+.RS 24
+cartoons; default
+.RE
+.RS 5
+-colour            assume colour (multi-plane) 
+.RE
+.RS 24
+cartoons
+.LP
+.RE
+.RS 5
+The following options should not be necessary if cartoons are generated and
+displayed on the same CPU architecture and screen hardware.  They are of use,
+however, if the CPU or screen differ.
+.RE
+.RS 5
+-rv                reverse-video the cartoon 
+.RE
+.RS 24
+window
+.RE
+.RS 5
+-planemask <int>   value of planemask for displaying 
+.RE
+.RS 24
+bitmaps; default = 1
+.RE
+.RS 5
+-lsb               assume bit and byte order of 
+.RE
+.RS 24
+cartoon is LSBFirst
+.RE
+.RS 5
+-msb               assume bit and byte order of 
+.RE
+.RS 24
+cartoon is MSBFirst
+.RE
+.RS 5
+-dec               alias for '-lsb -rv'
+.RE
+.RS 5
+-sun               alias for '-msb'
+.RE
+
+.SH SEE ALSO
+.LP
+review
+
+.SH BUGS
+.LP
+None currently.
+
+.SH COPYRIGHT
+.LP
+Copyright (c) Applied Psychology Unit, Medical Research Council, 1993-1995
+.LP
+Permission to use, copy, modify, and distribute this software without fee 
+is hereby granted for research purposes, provided that this copyright 
+notice appears in all copies and in all supporting documentation, and that 
+the software is not redistributed for any fee (except for a nominal 
+shipping charge). Anyone wanting to incorporate all or part of this 
+software in a commercial product must obtain a license from the Medical 
+Research Council.
+.LP
+The MRC makes no representations about the suitability of this 
+software for any purpose.  It is provided "as is" without express or 
+implied warranty.
+.LP
+THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+SOFTWARE.
+.LP
+
+.SH AUTHOR
+.LP
+M. Akeroyd, MRC Applied Psychology Unit, Cambridge, UK.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/man/whatis	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,52 @@
+acf           - Autocorrelation function of contiguous frames.
+acgram        - Autocorrelogram auditory image.
+atob          - ASCII to binary conversion.
+audim         - Auditory images.
+btoa          - Binary to ASCII conversion.
+bufframe      - Shifting AIM output frame buffer.
+bufwave       - Shifting waveform buffer.
+chi           - Repetitative chi-squared curve.
+conv          - Convolution.
+convert       - Convert units: frequency, time, and sample numbers.
+cosine        - Generate a cosine window.
+edframe       - Edit AIM output files.
+edwave        - Edit a given range of a wave.
+fbank         - Print filterbank centre-frequency and bandwidth information.
+fft           - Fast Fourier transform of contiguous frames.
+filt1         - First-order LP filter using an exponential smoother.
+ftgram        - Autocorrelogram auditory image.
+ftoa          - Frames to ASCII triples (x, y, z).
+ftos          - Float to short data-type conversion.
+gate          - Gate specific numbers from the input stream.
+gauss         - Generate a Gaussian window.
+genbmm        - Generate basilar membrane motion.
+gennap        - Generate neural activity pattern.
+gensai        - Generate stabilised auditory image.
+genspl        - Generate spiral map of stabilised auditory image.
+hdr           - Operations on AIM header.
+integframe    - Integrate gensai frames over time or frequency.
+loudness      - Loudness measure from spiral sector-weights contour.
+manaim        - Displays help/manual documentations on-line.
+merge         - Merge two streams onto stdout using given operator.
+naptosai      - NAP to SAI format conversion. 
+noise         - Generate samples of white noise.
+op            - Ordered sequence of operations on each item in input stream.
+options       - A general description of the AIM tools options handler.
+pitch_strength - Pitch-strength measure from spiral sector-weights contour.
+ptrain        - Generate a pulse train of binary shorts.
+racf          - Recursive autocorrelation function of contiguous frames.
+ramp          - Generate an exponential sawtooth waveform.
+saitonap      - SAI to NAP format conversion.
+scale         -  Shift and scale a binary stream.
+smooth        - Data smoothing by convolution with Gaussian window.
+sp_weights    - Map auditory image frames onto spiral sector-weights contours.
+stats         - Calculate some statistics.
+step          - Generate a step waveform.
+stof          - Short to float data-type conversion.
+swab          - Swap byte order of binary 2-byte data.
+tone          - Generate a pure tone.
+x11fonts      - Search and display fonts.
+x11gram       - Landscape plot of successive frames.
+x11play       - Animated plot of sets of n points.
+x11plot       - Plot n points.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/atan.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,103 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#include <stdio.h>
+#include <math.h>
+
+#include "stitch.h"
+
+#define OUTPUT_SCALE 360
+
+#ifdef TEST
+
+#define TwoPi (3.1415926535*2)
+
+
+main( argc, argv )
+int   argc ;
+char *argv[] ;
+{
+    double deg ;
+
+    printf( "hello\n" );
+
+    for( deg = 0 ; deg < TwoPi/2 ; deg += TwoPi/90001. )
+	if( (int) ( atan2( sin( deg ), cos( deg ) )/TwoPi*OUTPUT_SCALE + 0.5 ) != iatan2( (int) ( sin(deg)*1000 ), (int) ( cos(deg)*1000 ) ) )
+	    printf( " %f %d\n", atan2( sin( deg ), cos( deg ) )/TwoPi*OUTPUT_SCALE, iatan2( (int) ( sin(deg)*1000 ), (int) ( cos(deg)*1000 ) ) ) ;
+
+    for( ; deg < TwoPi ; deg += TwoPi/90001. )
+	if( (int) ( atan2( sin( deg ), cos( deg ) )/TwoPi*OUTPUT_SCALE - 0.5 ) != iatan2( (int) ( sin(deg)*1000 ), (int) ( cos(deg)*1000 ) ) )
+	    printf( " %f %d\n", atan2( sin( deg ), cos( deg ) )/TwoPi*OUTPUT_SCALE, iatan2( (int) ( sin(deg)*1000 ), (int) ( cos(deg)*1000 ) ) ) ;
+
+
+}
+
+#endif
+
+iatan2( y, x )
+int     y, x ;
+{
+    static int table_bits = 14 ;
+    static unsigned table_size ;
+    static short *atan_table = ( short * ) 0 ;
+    double two_phi ;
+    int i ;
+
+    if( atan_table == ( short * ) 0 ) {
+
+	table_size = 1 << table_bits ;
+
+	atan_table = ( short * ) stitch_malloc( sizeof ( *atan_table ) * ( table_size + 1 ), "Making atan lookup table" ) ;
+
+	two_phi = atan( 1. ) * 8. ;
+
+	for( i=0 ; i <= table_size ; i++ )
+	    atan_table[ i ] = atan( ( double ) i / ( table_size ) ) / two_phi * OUTPUT_SCALE + 0.5 ;
+    }
+
+    if( x != 0 || y != 0 )
+	if( y > 0 )
+	    if( x > 0 )
+		if(  x >  y )
+		    return(                          atan_table[ ( (  y << table_bits + ( table_size >> 1 ) ) ) /  x ] ) ;
+		else
+		    return(  ( OUTPUT_SCALE >> 2 ) - atan_table[ ( (  x << table_bits + ( table_size >> 1 ) ) ) /  y ] ) ;
+	    else
+		if( -x <  y )
+		    return(  ( OUTPUT_SCALE >> 2 ) + atan_table[ ( ( -x << table_bits + ( table_size >> 1 ) ) ) /  y ] ) ;
+		else
+		    return(  ( OUTPUT_SCALE >> 1 ) - atan_table[ ( (  y << table_bits + ( table_size >> 1 ) ) ) / -x ] ) ;
+	else
+	    if( x < 0 )
+		if( -x > -y )
+		    return( -( OUTPUT_SCALE >> 1 ) + atan_table[ ( ( -y << table_bits + ( table_size >> 1 ) ) ) / -x ] ) ;
+		else
+		    return( -( OUTPUT_SCALE >> 2 ) - atan_table[ ( ( -x << table_bits + ( table_size >> 1 ) ) ) / -y ] ) ;
+	    else
+		if(  x < -y )
+		    return( -( OUTPUT_SCALE >> 2 ) + atan_table[ ( (  x << table_bits + ( table_size >> 1 ) ) ) / -y ] ) ;
+		else
+		    return(                        - atan_table[ ( ( -y << table_bits + ( table_size >> 1 ) ) ) /  x ] ) ;
+    else
+	return( 99 ) ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/bank.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,268 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+*/
+
+/*
+    bank.c
+    ======
+
+    long awaited proper generic multiplexed filter bank with phase compensation!
+
+
+    Copyright (c), 1989  The Medical Research Council, Applied Psychology Unit.
+
+
+    Author  : John Holdsworth
+    Written : 10th March, 1989.
+
+    Edited  :
+              Christian Giguere, March 1994
+              - Provided facilities to print filterbank information to stderr
+              - To locate changes, search for "CG"
+
+*/
+
+#include <math.h>
+#include <stdio.h>       /* CG */
+
+#include "stitch.h"
+#include "source.h"
+#include "recurse.h"
+#include "formulae.h"
+
+#include "bank.h"
+
+#ifndef  lint
+static char *sccs_id = "@(#)bank.c	1.16 John Holdsworth (MRC-APU) 6/6/91" ;
+#endif
+
+
+/* interpolation */
+
+struct _interp_state { struct _fillable_source parent ; Source source ; unsigned ichans ; int (*interp)() ; } ;
+
+static Pointer interp_callback( state, bytes, buffer )
+struct _interp_state *state ;
+ByteCount *bytes ;
+short *buffer ;
+{
+    register int last = *bytes == 0 ;
+    register int ipointer, points = ToPoints( short, *bytes ) ;
+    register int ipoints = points / (state->ichans*2-1) * state->ichans ;
+    short *input = PullShorts( state->source, ipoints ) ;
+
+    if( !last ) {
+	for( ipointer=0 ; ipointer < ipoints ; ipointer += state->ichans )
+	    state->interp( input+ipointer, buffer+ipointer/state->ichans*(state->ichans*2-1), state->ichans, state->ichans*2-1 ) ;
+
+	return ( (Pointer) buffer ) ;
+    }
+    else
+	return ( DeleteFillableSource( state ) ) ;
+}
+
+Source InterpSource( source, ichans )
+Source source ;
+int ichans ;
+{
+    DeclareNew( struct _interp_state *, state ) ;
+    extern int interp() ;
+
+    state->source = source ;
+    state->ichans = ichans ;
+    state->interp = interp ;
+
+    return ( SetFillableSource( state, interp_callback, "bank.c interpolating" ) ) ;
+}
+
+Source LinterpSource( source, ichans )
+Source source ;
+int ichans ;
+{
+    DeclareNew( struct _interp_state *, state ) ;
+    extern int linterp() ;
+
+    state->source = source ;
+    state->ichans = ichans ;
+    state->interp = linterp ;
+
+    return ( SetFillableSource( state, interp_callback, "bank.c linterpolating" ) ) ;
+}
+
+static int segsize = 50 ;
+
+#ifdef DSP32
+#define BUFFSIZE 256
+#else
+#define BUFFSIZE 2048
+#endif
+
+/* multiplexed filter bank */
+
+struct _bank_state {
+ struct _fillable_source parent ;
+ Source source ; char *input ; unsigned chans ;
+ int active, pointer, iptr, *delays, (*proc)(), input_size, output_size ;
+ RecursiveFilterState **states ;
+ } ;
+
+static Pointer bank_callback( state, bytes, buffer )
+struct _bank_state *state ;
+ByteCount *bytes ;
+char *buffer ;
+{
+extern char *bstart, *bend ;
+    register int last = *bytes == 0 ;
+    static int segment = BUFFSIZE ;
+    int points, bytecount ;
+
+    if( state->input == ( char * ) 0 ) {
+
+	if( state->delays[0] < 0 )
+	    state->pointer = state->delays[0] ;
+	else
+	    state->pointer = 0 ;
+
+	if( segment < state->delays[state->chans-1] - state->delays[0] )
+	    segment = state->delays[state->chans-1] - state->delays[0] << 1 ;
+
+	state->input = Pull( state->source, segment * state->input_size ) ;
+	state->iptr   = state->pointer ;
+	state->active = 0 ;
+
+	bstart = state->input - segment * state->input_size ;
+	bend   = state->input + segment * state->input_size ;
+    }
+
+    if( !last ) {
+	for( bytecount=0 ; bytecount<*bytes ; ) {
+
+	    if( state->iptr + segsize - state->delays[0] >= segment ) {
+		state->input = Pull( state->source, segment * state->input_size ) ;
+		state->iptr -= segment ;
+
+	    bstart = state->input - segment * state->input_size ;
+	    bend   = state->input + segment * state->input_size ;
+
+	    }
+
+	    while( state->active < state->chans && state->delays[ state->active ] <= state->pointer )
+		state->active++ ;
+
+	    if( state->pointer < 0 || state->active < state->chans || state->output_size == 0 ) {
+
+		points = 1 ;
+
+		state->output_size = state->proc( state->states, state->delays, state->input + state->iptr * state->input_size, buffer+bytecount, points, state->active ) ;
+
+		stitch_bzero( buffer+bytecount+state->active*state->output_size, (int) ( ( state->chans - state->active ) * state->output_size ) ) ;
+	    }
+	    else {
+		points = ( *bytes - bytecount ) / state->chans / state->output_size ;
+
+		if( points > segsize )
+		    points = segsize ;
+
+		state->output_size = state->proc( state->states, state->delays, state->input + state->iptr * state->input_size, buffer+bytecount, points, state->active ) ;
+	    }
+
+	    state->iptr += points ;
+
+	    if( ++state->pointer > 0 )
+		bytecount += points*state->chans*state->output_size ;
+	}
+
+	return ( buffer ) ;
+    }
+    else {
+	Pull( state->source, 0 ) ;
+
+	for( last=0 ; last<state->chans ; last++ )
+	    Delete( state->states[last] ) ;
+
+	Delete( state->states ) ;
+	Delete( state->delays ) ;
+
+	return ( DeleteFillableSource( state ) ) ;
+    }
+
+}
+
+
+Source GenericFilterBank( source, interps, chans, samplerate, center_frequencies, bandwidth_function, scale_function, output_scale, audio_power, order, phase_compensation, input_bits, frames, proc, input_size, info )
+Source source ;
+int interps, *chans ;
+double samplerate, *center_frequencies, (*bandwidth_function)(),  (*scale_function)() ;    /* CG: 23-03-94 */
+double output_scale, audio_power ;                                                         /* CG: 23-03-94 */
+int order, phase_compensation, input_bits ;
+long frames ;
+int (*proc)(), input_size, info ;                                                          /* CG: 23-03-94 */
+{
+    DeclareNew( struct _bank_state *, state ) ;
+    double sample_delay, max_delay, freq ;
+    extern Source Interp() ;
+    Source out ;
+    int chan ;
+
+    state->chans  = *chans >> interps ;
+
+    state->states = NewArray( RecursiveFilterState *, state->chans, "bank.c for states" ) ;
+    state->delays = NewArray( int,                    state->chans, "bank.c for delays" ) ;
+
+    state->input_size = input_size ;
+
+    if( info )                                                        /* CG: 23-03-94 */
+       fprintf( stderr, "\nGTF filterbank information:\n" ) ;
+
+    for( chan=0 ; chan < state->chans ; chan++ ) {
+	sample_delay = 0 ;
+
+	freq = center_frequencies[ chan<<interps ] ;
+ 
+        if( info )                                                   /* CG: 23-03-94 */
+           fprintf( stderr, "%3d -- cf:%7.1f Hz =%6.2f ERBs -- bwidth=%5.1f Hz\n",
+		   chan + 1 , freq, scale_function( freq ), bandwidth_function( freq ) ) ; 
+
+	state->states[ chan ] = NewRecursiveFilter( samplerate, freq, bandwidth_function( freq ),
+					    output_scale * pow( Audiogram( freq ), audio_power ),
+					    order, phase_compensation, input_bits, &sample_delay ) ;
+
+	if( chan == 0 )
+	    max_delay = sample_delay ;
+
+	if( phase_compensation == FINE_ALIGNMENT || phase_compensation == ENVELOPE_ALIGNMENT )
+	    state->delays[ chan ] = sample_delay - max_delay ;
+	else
+	    state->delays[ chan ] = sample_delay ;
+    }
+
+    state->output_size = 0 ;
+
+    state->source = NewRetainingSource( source, BUFFSIZE * state->input_size ) ;
+
+    state->input  = ( char * ) 0 ;
+    state->proc   = proc ;
+
+    out = SetFillableSource( state, bank_callback, "bank.c filter" ) ;
+
+    for( chan = state->chans ; interps-- > 0 ; chan = chan*2-1 )
+	out = InterpSource( out, chan ) ;
+
+    *chans = chan ;
+
+    return ( out ) ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/bank.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,31 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    bank.h
+    ======
+
+
+*/
+
+extern Source Interp(), Linterp(), GenericFilterBank() ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/calc.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,60 @@
+/*
+    calc.h
+    ======
+
+    definitions to make model source portable across calculation type.
+    Used fixed point representation for real numbers in integer machines.
+
+    Type names:
+	DataType - type used to pass results between modules
+		   EG. usually a short.
+	StoreType - type used to store an intermediate result within a module
+	ScalarType - type used to store fixed-point multipliers
+
+    Integer arithmetic:
+
+	SCALE - convert to fixed point
+	SCALAR- float to fixed to fixed point multiplier
+		(Used to create a value for a ScalarType).
+	DESCALE - convert back to int (opposite of SCALE).
+
+	UNSCALE - convert fixed point back to float.
+
+	Use int instead float to get fixed point arithmetic, but shift
+	numbers to preserve the significant digits, EG for multiplication:
+		use SCALAR on one operand (which will then be a ScalarType)
+		use DESCALE on the result
+*/
+
+#if 1                   /* Switch to convert whole model to floating point */
+#define FLOAT float     /* version (default uses integer arithmetic)       */
+#endif
+
+#ifdef  DSP32
+#define FLOAT float
+#endif
+
+
+#ifdef  FLOAT
+
+typedef FLOAT ScalarType ;
+typedef FLOAT  StoreType ;
+typedef FLOAT   DataType ;
+
+#define   SCALE( _num ) (          _num                         )
+#define  SCALAR( _num ) (          _num                         )
+#define DESCALE( _num ) (          _num                         )
+#define UNSCALE( _num ) (          _num                         )
+
+#else
+
+typedef long ScalarType ;
+typedef long  StoreType ;
+typedef short  DataType ;
+
+#define   SCALE( _num ) ( (long) ( _num )                << 16l         )
+#define  SCALAR( _num ) (        ( _num ) *         ( 1l << 16l ) + 0.5 )
+#define DESCALE( _num ) ( (long) ( _num )                >> 16l         )
+#define UNSCALE( _num ) (        ( _num ) / (float) ( 1l << 16l )       )
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/corti.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,453 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+*/
+
+/*
+    corti.c
+    =======
+
+    attempt at model of organ of corti
+
+
+    Copyright (c), 1989  The Medical Research Council, Applied Psychology Unit.
+
+
+    Author  : John Holdsworth
+    Written : 30th November, 1988.
+
+    Edited  : 
+
+              Christian Giguere, March 1994. 
+	      - Changed option "scale_at" into "gain_at".
+	      - That option is now passed to newCorti() as a double instead of an integer
+	      - In Corti(), this meant multiplying *optr by state->scale
+              - To locate changes, search for "CG"
+
+*/
+#include <stdio.h>
+#include  <math.h>
+
+#include "stitch.h"
+#include "source.h"
+#include  "corti.h"
+#include   "calc.h"
+
+#if 0
+#define DEBUG
+#endif
+
+#ifndef  lint
+static char *sccs_id = "@(#)corti.c	1.15     J. Holdsworth (MRC-APU)  5/31/91" ;
+#endif
+
+/* calmB is the mB of the magnitude where the slope of temporal recovery is calculated */
+/* 5497 corresponds to a magnitude of 500 units */
+
+static double calmB = 5497. ;
+
+struct _cell_state {
+StoreType microphonic, rapid_limit, absolute_limit ;
+ScalarType rapid_rise, fast_rise, rapid_decay, fast_decay ;
+double compensate ;             /* Changed to double from StoreType (mha:22/1/93) */
+} ;
+
+struct _corti_state {
+struct _cell_state *cell_states ;
+StoreType scale ;
+ScalarType t_lat ;
+unsigned cells, times ;
+} ;
+
+
+/* global variable for spectral tilt control to compensate for differences */
+/* between channels in terms of mean firing rate                           */
+
+double compensate = 1. ;
+
+
+char *newCorti( cells, samplerate, center_frequencies, bandwidth_function, t_rise, t_lat, t_rapid, t_fast, prop, absthresh, times, scale )
+int cells ;
+double samplerate, *center_frequencies, (*bandwidth_function)(), t_rise, t_lat, t_rapid, t_fast, prop, absthresh ;
+int times ;
+double scale ;   /* CG: 22/03/94 */
+{
+    DeclareNew( struct _corti_state *, state ) ;
+    struct _cell_state *cell_ptr ;
+    double ratio, k_rise ;
+    double expected_rate, expected_reference ;
+
+    /* parameters that are constant across cells */
+
+    state->t_lat = SCALAR( t_lat  / ( samplerate * times ) ) ;
+
+    state->cells  = cells ;
+    state->times  = times ;
+    state->scale  = scale ; 
+
+    state->cell_states = NewArray( struct _cell_state, state->cells, "corti.c for cell states" ) ;
+
+    for( cell_ptr = state->cell_states ; cell_ptr < state->cell_states + cells ; cell_ptr++ ) {
+
+	/* corti states */
+
+	cell_ptr->microphonic    = SCALAR( absthresh ) ;
+	cell_ptr->rapid_limit    = SCALAR( absthresh ) ;
+	cell_ptr->absolute_limit = SCALAR( absthresh ) ;
+
+	/* recovery time constants */
+
+	cell_ptr->rapid_decay = SCALAR( bandwidth_function( center_frequencies[cell_ptr-state->cell_states] ) *
+				 t_rapid * calmB / ( calmB - absthresh ) / samplerate /* / ( 1. - prop ) */ ) ;
+
+	cell_ptr->fast_decay  = SCALAR( 1. / t_fast / samplerate ) ;
+
+	 /* adaptation time constants */
+
+	ratio = prop / ( 1. - prop ) / cell_ptr->rapid_decay * cell_ptr->fast_decay ;
+
+	if( t_rise > 0 )
+	    k_rise = t_rise / ( samplerate * times ) ;
+	else
+	    k_rise = 1. ;
+
+	cell_ptr->rapid_rise = SCALAR( k_rise * 1.    / ( 1. + ratio ) ) ;
+	cell_ptr->fast_rise  = SCALAR( k_rise * ratio / ( 1. + ratio ) ) ;
+
+	/* introduce variable amount of compensation w.r.t expected firing rate variation */
+
+	expected_rate = UNSCALE( cell_ptr->rapid_decay ) * ( calmB - absthresh ) ;
+
+	if( cell_ptr == state->cell_states )
+	    expected_reference = expected_rate ;
+
+	/* New formula for computing cell_ptr->compensate  (mha: 20/1/93)  */
+	/* Parameters chosen to flatten pulse-train spectrum.              */
+	/* _cell_state member "compensate" changed to double.              */
+	/* The exponent used is 1.128*compensate so that the given         */
+	/* parameter (compensate_at) can be set as "on" (ie 1.0) for       */
+	/* optimal compensation (instead of a magic number)                */
+	/* The value for "compensate_at=off", (calmB - absthresh) was      */
+	/* chosen as similar to the original, and because the results      */
+	/* were appropriate for an un-compensated spectrum.                */
+
+	if (compensate)
+	    cell_ptr->compensate =  pow(center_frequencies[cell_ptr - state->cell_states], 1.128*compensate) + 800. ;
+	else
+	    cell_ptr->compensate =  calmB - absthresh ;
+
+	/* Originally, compensate used the SCALAR macro, and so it failed  */
+	/* for a floating-point version (defined in calc.h).               */
+	/* To fix this, the new compensate formula is scaled up using the  */
+	/* original integer version of the UNSCALE macro (see calc.h).     */
+
+#ifdef FLOAT
+	cell_ptr->compensate /=  (float) ( 1l << 16l ) ;
+#endif
+
+#ifdef DEBUG
+	(void) fprintf( stderr, "rapid_decay:%f fast_decay:%f ratio:%f k_rise:%f rapid_rise:%f fast_rise:%f compensation:%f\n",
+			  UNSCALE(cell_ptr->rapid_decay), UNSCALE(cell_ptr->fast_decay),
+	    ratio, k_rise, UNSCALE(cell_ptr->rapid_rise), UNSCALE(cell_ptr->fast_rise),
+			1./UNSCALE(cell_ptr->compensate) ) ;
+#endif
+    }
+#ifdef DEBUG
+    (void) fprintf( stderr, "times:%d t_lat:%f\n", times, UNSCALE( state->t_lat ) ) ;
+#endif
+
+    return( (char *) state ) ;
+}
+
+int Corti( state_ptr, bytes, out, end, in )
+char *state_ptr ;
+ByteCount *bytes ;
+DataType *out, *end, *in ;
+{
+    register struct _corti_state *state = (struct _corti_state *) state_ptr ;
+    register struct _cell_state *cell_ptr, *cell_end = state->cell_states + state->cells ;
+    register DataType *iptr, *optr, *eptr = end ;
+    register StoreType delta, old_last_mic ;
+    register int time ;
+
+    while( out < eptr ) {
+
+	for( time=0 ; time < state->times ; time++ ) {
+
+	    cell_ptr = state->cell_states ;
+
+	    iptr = in  ;
+	    optr = out ;
+
+	    /* raise threhsolds */
+
+	    for( cell_ptr = state->cell_states ; cell_ptr < cell_end ; cell_ptr++ ) {
+
+		if( time == 0 )
+		    *optr = 0 ;
+
+		delta = *iptr++ - DESCALE( cell_ptr->microphonic ) ;
+
+		if( delta > 0 ) {
+
+		    cell_ptr->microphonic += delta * cell_ptr->rapid_rise ;
+		    cell_ptr->rapid_limit += delta * cell_ptr->fast_rise  ;
+
+		    *optr                 += delta ;
+		}
+
+		optr++ ;
+	    }
+
+	    /* leak thresholds symetrically across channels */
+
+	    old_last_mic = state->cell_states->microphonic ;
+
+	    for( cell_ptr = state->cell_states+1 ; cell_ptr < cell_end ; cell_ptr++ ) {
+
+		delta = DESCALE( old_last_mic - cell_ptr->microphonic ) * state->t_lat ;
+		old_last_mic = cell_ptr->microphonic ;
+
+		if( cell_ptr-1 != state->cell_states )
+		    (cell_ptr-1)->microphonic -= delta ;
+
+		if( cell_ptr+1 != cell_end )
+		    (cell_ptr  )->microphonic += delta ;
+	    }
+	}
+
+	/* decay potentails */
+
+	for( cell_ptr = state->cell_states ; cell_ptr < cell_end ; cell_ptr++ )
+	    cell_ptr->microphonic -= DESCALE( cell_ptr->microphonic - cell_ptr->rapid_limit ) * cell_ptr->rapid_decay ;
+
+	for( cell_ptr = state->cell_states ; cell_ptr < cell_end ; cell_ptr++ )
+	    cell_ptr->rapid_limit -= DESCALE( cell_ptr->rapid_limit - cell_ptr->absolute_limit ) * cell_ptr->fast_decay ;
+
+	/* generate output */
+
+	iptr = in ;
+	optr = out ;
+
+	if( state->scale >= 0 )                                               /* CG: 22/3/94 */
+	    for( cell_ptr = state->cell_states ; cell_ptr < cell_end ; cell_ptr++ ) {
+		delta = SCALE( *iptr++ ) - cell_ptr->microphonic ;
+		if( delta > 0 )
+		    *optr++ = state->scale * delta / cell_ptr->compensate ;   /* CG: 22/3/94 */
+		else
+		    *optr++ = 0 ;
+	    }
+	else if( state->scale < 0 )
+	    switch( (int) state->scale ) {
+
+		/* output internal states */
+
+		case -1 :
+		    for( cell_ptr = state->cell_states ; cell_ptr < cell_end ; cell_ptr++ )
+			*optr++ = DESCALE( cell_ptr->microphonic ) ;
+
+		    break ;
+
+		case -2 :
+		    for( cell_ptr = state->cell_states ; cell_ptr < cell_end ; cell_ptr++ )
+			*optr++ = DESCALE( cell_ptr->rapid_limit ) ;
+
+		    break ;
+
+		default :
+		    for( cell_ptr = state->cell_states ; cell_ptr < cell_end ; cell_ptr++ )
+			*optr++ = ( *iptr++ - DESCALE( cell_ptr->microphonic ) ) * -state->scale ;
+
+		    break ;
+
+	    }
+	/* else leave value as is */
+
+
+	/* next frame */
+
+	in  += state->cells ;
+	out += state->cells ;
+    }
+
+    /* return amount processed */
+
+    return ( *bytes ) ;
+}
+
+/* for compatability */
+
+int OldCorti( state_ptr, cells, in, out )
+char *state_ptr ;
+unsigned cells ;
+DataType *in, *out ;
+{
+    ByteCount bytes = ToBytes( DataType, cells ) ;
+
+    return ( ToPoints( DataType, Corti( state_ptr, &bytes, out, out+cells, in ) ) ) ;
+}
+
+void closeCorti( state )
+struct _corti_state *state ;
+{
+    Delete( state->cell_states ) ;
+    Delete( state ) ;
+
+    return ;
+}
+
+
+/* experimental corti  simulation */
+
+
+struct _corti2_state { int *working, *falls, slope, scale ; short *forward, *backward ; } ;
+
+char *newCorti2( cells, samplerate, center_frequencies, bandwidth_function, bandwidth_scalar, t_slope, scale, forward, backward )
+int cells ;
+double samplerate, *center_frequencies, (*bandwidth_function)(), bandwidth_scalar, t_slope, scale ;
+short *forward, *backward ;
+{
+    DeclareNew( struct _corti2_state *, state ) ;
+    int i ;
+
+    state->working =       NewArray( int, cells, "corti.c for works" ) ;
+    state->falls   = NewZeroedArray( int, cells, "corti.c for falls" ) ;
+
+    for( i=0 ; i < cells ; i++ )
+	state->falls[i] = bandwidth_function( center_frequencies[i] ) * bandwidth_scalar /
+				 samplerate * t_slope ;
+
+    state->forward  = forward  ;
+    state->backward = backward ;
+
+    state->scale = scale ;
+
+    return( ( char * ) state ) ;
+}
+
+int Corti2( state_ptr, cells, in, out )
+char *state_ptr ;
+unsigned cells ;
+short *in, *out ;
+{
+    struct _corti2_state *state ;
+    register int i, when ;
+
+    state = ( struct _corti2_state * ) state_ptr ;
+
+    for( i=0 ; i<cells ; i++ ) {
+	state->working[i] -= state->falls[i] ;
+	out[i] = in[i] - state->working[i] ;
+	if( out[i] > 0 )
+	    state->working[i] += out[i] ;
+    }
+
+    when = 0 ;
+
+    for( i=1 ; i<cells ; i++ )
+	if( state->working[i] < state->working[ when ] + state->forward[  i - when ] ) {
+	    state->working[i] = state->working[ when ] + state->forward[  i - when ] ;
+	    out[i] = 0 ;
+	}
+	else
+	    when = i ;
+
+    when = cells-1 ;
+
+    for( i=cells-2 ; i>=0 ; i-- )
+	if( state->working[i] < state->working[ when ] + state->backward[ when - i ] ) {
+	    state->working[i] = state->working[ when ] + state->backward[ when - i ] ;
+	    out[i] = 0 ;
+	}
+	else
+	    when = i ;
+
+    for( i=0 ; i<cells ; i++ )
+	if( state->scale != 0 )
+	    out[i] = out[i] * state->scale / state->falls[i] ;
+	else
+	    out[i] = state->working[i] ;
+
+    return ;
+}
+
+void closeCorti2( state )
+struct _corti2_state *state ;
+{
+    stitch_free( ( char * ) state->working ) ;
+    stitch_free( ( char * ) state->falls ) ;
+
+    Delete( state ) ;
+
+    return ;
+}
+
+#if 0
+
+/* obsolete code stored here for now.. stitch entry points */
+
+
+struct _stx_state { Source source ; unsigned cells ; char *corti ; int (*model)() ; } ;
+
+static void stx_callback( state, bytes, buffer )
+struct _stx_state *state ;
+ByteCount bytes ;
+DataType *buffer ;
+{
+    int points      = ToPoints( DataType, bytes ) ;
+    DataType *input = PullItems( state->source, points, DataType ) ;
+    int pointer ;
+
+    for( pointer=0 ; pointer < points ; pointer += state->cells )
+	(void) state->model( state->corti, state->cells, input+pointer, buffer+pointer ) ;
+
+    return ;
+}
+
+Source Stx( source, chans, samplerate, center_frequencies, bandwidth_function, bandwidth_scalar, t_rise, t_lat, t_rapid, absthresh, times, scale )
+Source source ;
+int chans ;
+double samplerate, *center_frequencies, (*bandwidth_function)(), bandwidth_scalar, t_rise, t_lat, t_rapid, absthresh ;
+int times, scale ;
+{
+    DeclareNew( struct _stx_state *, state ) ;
+
+    state->source = source ;
+    state->cells  = chans ;
+
+    state->corti = newCorti( chans, samplerate, center_frequencies, bandwidth_function, t_rise, t_lat, t_rapid, absthresh, times, scale ) ;
+    state->model = OldCorti ;
+
+    return ( stdAutoSource( ( Pointer ) state, stx_callback ) ) ;
+}
+
+Source Stx2( source, chans, samplerate, center_frequencies, bandwidth_function, bandwidth_scalar, rapid_rises, scale )
+Source source ;
+int chans ;
+double samplerate, *center_frequencies, (*bandwidth_function)(), bandwidth_scalar, rapid_rises, scale ;
+{
+    DeclareNew( struct _stx_state *, state ) ;
+    short *forward = ( short * ) 0, *backward = ( short * ) 0 ;
+
+    state->source = source ;
+    state->cells  = chans ;
+
+    state->corti = newCorti2( chans, samplerate, center_frequencies, bandwidth_function, bandwidth_scalar, rapid_rises, scale, forward, backward ) ;
+    state->model = Corti2 ;
+
+    return ( stdAutoSource( ( Pointer ) state, stx_callback ) ) ;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/corti.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,21 @@
+/*
+    corti.h
+    =======
+
+
+    entry point definitions for organ of corti simulation.
+
+*/
+
+extern char *newCorti() ;
+extern int  Corti() ;
+extern int  Croti() ;
+extern void closeCorti() ;
+
+/* experimiental */
+
+extern char *newCorti2() ;
+extern int  Corti2() ;
+extern void closeCorti2() ;
+
+extern double compensate ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/defaults.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,96 @@
+/*
+	defaults.c
+	==========
+
+
+	override the optiuons table defaults
+
+*/
+
+#include <string.h>
+#include <stdio.h>
+
+#include "options.h"
+#include "stitch.h"
+#include "source.h"
+#include "model.h"
+
+/**************************************************************************
+* constructOptions( which )
+* Return an options table, (an array of Option structs).
+* This table is used by getopts(), helpopts(), readopts(), and writeopts().
+* (These are all called from gen.c, and defined in options.c).
+*
+* The display options particular to the current application (given by "which")
+* are listed at the end of the table.
+* The rest of the options table is ordered with the
+* earliest options at the end of the table. The earliest options are those
+* corresponding to the earliest processing stages (at the bottom of the stage
+* table). Note that the options table is printed in reverse order by the
+* help-handler routine in options.c, so that the earliest options appear at
+* the top of the help menu.
+* The option defaults (as defined in displayopts and in table.c), are over-
+* written by application defaults, so that each application can have specific
+* defaults. The tables of option defaults for each application are defined
+* in gen.c, and each is referenced by the entry in the defaults field of the
+* stage struct for the application, (in model.c:FindStage()).
+**************************************************************************/
+
+/* override option defaults with specific defaults for this application */
+
+Option *constructOptions( which, applicationTable )
+char *which;
+Option *applicationTable ;
+{
+    struct _stage *sptr, *stage=FindStage( which ) ;
+    Option  *optr, *options;
+    char    **cptr, *vptr;
+    int     i, j, n=0;
+
+    /* count the stage options and find the bottom of the stage table */
+    for (sptr=stage ; sptr->ident != (char *)0 ; sptr++)
+	if ((optr=sptr->options) != (Option *) 0)
+	    for (i=0 ; optr[i].name != (char *)0 ; i++, n++)
+		;
+
+    /* add in the count of the display options for this application */
+    for (i=0 ; applicationTable[i].name != (char *)0 ; i++, n++)
+	;
+
+    /* allocate and null-terminate space for the complete options table */
+    options = NewArray(Option, n+1, "option_list");
+    options[n--].name = (char *)0;
+
+    /* copy the display options table into the options table */
+    for (i=0 ; applicationTable[i].name != (char *)0 ; i++, --n)
+	CopyArray( &applicationTable[i], &options[n], 1 );
+
+    /* copy stage options into options table from bottom up */
+    for (--sptr ; sptr>=stage ; --sptr)
+	if ((optr=sptr->options) != (Option *) 0)
+	    for (i=0 ; optr[i].name != (char *)0 ; i++, --n) {
+		CopyArray( &optr[i], &options[n], 1 );
+	    }
+
+    if( (cptr = stage->defaults) != (char **) 0 ) {
+
+	for (i=0 ; cptr[i] != (char *) 0 ; i++) {
+	    /* split string at '=', so cptr[i] is name and vptr is value */
+	    for (vptr=cptr[i] ; *vptr != '=' ; vptr++)
+		;
+		vptr++ ;
+	    /* find name in options table, and substitute default value */
+	    for ( j=n+1 ; options[j].name != (char *) 0 ; j++)
+		if (strncmp(options[j].name, cptr[i], vptr-1-cptr[i]) == 0) {
+		    options[j].defaultValue = vptr ;
+		    break;
+		}
+/*
+	    if( options[j].name == (char *) 0 ) stitch_error( "problem with %s", cptr[i] ) ;
+*/
+	}
+    }
+
+    return ( options ) ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/defaults.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,10 @@
+/*
+
+    defaults.h
+    ==========
+
+
+*/
+
+
+extern Option *constructOptions( /* char *which */ ) ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/faster.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,199 @@
+/*
+    faster.c
+    ========
+    
+    pretty cludgy hack to do fast raster image generation from
+    stabilised image frames.
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+
+
+#include "windows.h"
+#include "stitch.h"
+#include "source.h"
+#include "draw.h"
+#include "calc.h"
+
+#define NEAR_PTR *
+
+struct _generator_state { WindowObject window ; int width, height, framewidth ; long colinc, colmax, NEAR_PTR origins, NEAR_PTR scales, NEAR_PTR end_scales ; int times, hidden, colskip, NEAR_PTR offsets ; } ;
+
+void generate( this, frame )
+struct _generator_state *this ;
+DataType *frame ;
+{
+    register long NEAR_PTR origins, NEAR_PTR scales, NEAR_PTR end_scales = this->end_scales ;
+    register int fromtop, bit, colskip = this->colskip ;
+    register int NEAR_PTR offsets = this->offsets ;
+    register long column ;
+    register DataType *colptr ;
+    register int time, times = abs( this->times ) ;
+    WindowImage image_data = window__current_image( this->window ) ;
+    register char *ptr, *min_ptr, *base = image_data->data ;
+    register int bytes_per_line = image_data->bytes_per_line ;
+    register int height         = image_data->height ;
+
+    /* clear image */
+
+    ptr     = base ;
+    min_ptr = base + height * bytes_per_line / sizeof ( *base ) ;
+
+    while( ptr < min_ptr )
+	*ptr++ = 0 ;
+
+    bit  = image_data->start_bit ;
+
+    time = times ;
+
+    *offsets++ = 0 ;
+
+    for( ; offsets < this->offsets + height ; offsets++ )
+	*offsets = offsets[-1] + bytes_per_line / sizeof ( *base ) ;
+
+    offsets = this->offsets ;
+
+    for( column=0 ; DESCALE( column ) < this->framewidth ; column+=this->colinc ) {
+
+	colptr  = frame + DESCALE( column ) ;
+	origins = this->origins ;
+	scales  = this->scales  ;
+
+	if( this->hidden ) {
+
+	    min_ptr = base + offsets[ height-1 ] ;
+
+	    while( scales < end_scales ) {
+
+		if( ( fromtop = *origins++ - DESCALE( *colptr * *scales++ ) ) < 0 )
+		    fromtop = 0 ;
+
+		ptr = base + offsets[ fromtop ] ;
+
+		if( ptr < min_ptr ) {
+		   *ptr |= bit ;
+		   min_ptr = ptr ;
+		}
+
+		colptr += colskip ;
+	    }
+	}
+	else
+	    while( scales < end_scales ) {
+
+		if( ( fromtop = *origins++ - DESCALE( *colptr * *scales++ ) ) < 0 )
+		    fromtop = 0 ;
+
+	       *( base + offsets[ fromtop ] ) |= bit ;
+
+		colptr += colskip ;
+	    }
+
+	if(  --time <= 0 ) {
+
+	    if( bit == image_data->right_bit ) {
+		bit =  image_data->left_bit ;
+		base++ ;
+	    }
+	    else
+		if( image_data->right_bit < image_data->left_bit )
+		    bit >>= 1 ;
+		else
+		    bit <<= 1 ;
+
+	    time = times ;
+	}
+    }
+
+    return ;
+}
+
+
+struct _generator_state *genstate( window, min, max, framewidth, frameheight, frames, times )
+WindowObject window ;
+int min, max, framewidth, frameheight ;
+long frames ;
+int times ;
+{
+    DeclareNew( struct _generator_state *, this ) ;
+    double sintheta, scale, rowscale ;
+    int row ;
+
+    this->window  = window ;
+
+    this->times   = abs( times ) ;
+    this->hidden  = times < 0 ;
+
+    this->width   = Width(  window ) ;
+    this->height  = Height( window ) ;
+
+    this->origins = NewArray( long, frameheight, "faster.c for origins" ) ;
+    this->scales  = NewArray( long, frameheight, "faster.c for scales"  ) ;
+
+    this->offsets = NewArray( int, this->height, "faster.c for offsets" ) ;
+
+    this->end_scales = this->scales + frameheight ;
+
+    this->colskip = framewidth /* sizeof ( DataType ) */ ;
+
+    this->framewidth = framewidth ;
+    this->colinc = SCALAR( framewidth-1. ) / ( this->width-1 ) / this->times ;
+
+    sintheta = sin( drawTilt / 45. * atan( 1. ) ) ;
+    scale = ( 100. - drawHeadroom ) / 100. / ( drawDistance / ( drawDistance + sintheta ) ) ;
+
+    for( row=0 ; row<frameheight ; row++ ) {
+
+	rowscale = drawDistance / ( drawDistance + sintheta * ( row + 0.5 ) / frameheight ) ;
+
+	this->origins[row] = this->height - ( row + 0.5 ) / frameheight * this->height * rowscale * scale ;
+	this->scales[ row] = SCALAR( this->height / ( max * frameheight / rowscale ) ) ;
+    }
+
+    return ( this ) ;
+}
+
+#if 0
+
+#define FWIDTH 200
+#define CHANS  50
+
+double drawHeadroom=10, drawTilt=40, drawDistance=0.5 ;
+
+int main()
+{
+    DeclareNewArray( DataType, buffer, FWIDTH*CHANS, "for buffer" ) ;
+    WindowObject window = NewDisplayWindow( "rol", -1, -1, 300, 300, 1 ) ;
+    char *state = ( char * ) genstate( window, 0, 100, FWIDTH, CHANS, 1l, 1 ) ;
+    int x, chan ;
+
+    for( chan=0 ; chan<CHANS ; chan++ )
+	    for( x=0 ; x<FWIDTH ; x++ )
+		    buffer[chan*FWIDTH+x]= x%150 ;
+
+    Clear( window ) ;
+
+    x = Store( window ) ;
+
+    generate( state, buffer ) ;
+
+    Recall( window, 1 ) ;
+    Recall( window, 1 ) ;
+    Recall( window, 1 ) ;
+    Recall( window, 1 ) ;
+    Recall( window, 1 ) ;
+    Recall( window, 1 ) ;
+    Recall( window, 1 ) ;
+    Recall( window, 1 ) ;
+    Recall( window, 1 ) ;
+    Recall( window, 1 ) ;
+    Recall( window, 1 ) ;
+
+    Pause( window ) ;
+
+    exit( 0 ) ;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/gen.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,1548 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+*/
+
+/*
+	gen.c
+	=====
+
+    APU, ASP model demonstration program.
+
+
+    Copyright (c), 1989  The Medical Research Council, Applied Psychology Unit.
+
+
+    Authors : John Holdsworth (1989), Mike Allerhand (1990)
+
+
+    Edited  : M.Akeroyd 22-1-1993
+              Removed the conditional of `if (centering) Clear (w)' 
+	      (in plot_frame), so that Clear may be called for 
+	      PostScriptWindows that AREN'T centered, so allowing
+	      showpages to be generated.
+              See also edit to ps.c
+
+	    : M Akeroyd 3-8-1993
+              Added new options:
+		erbscale_efb (InputOption) mono_ctn (SilentOption)
+		colour_ctn (SilentOption) planemask_ctn (SilentOption)
+  	      Allowed "bitmap=stdout".
+
+	    : MAA 3rd August 1993
+              Extra options 
+	        framenumber (SilentOption), review (SilentOption)
+             
+            : MAA 22nd July 1994. 
+              Extra postscript options ALl silent
+                xstart_ps xend_ps ystart_ps yend_ps 
+                xtitle_ps ytitle_ps
+              Extra X options
+                fg_col bg_col
+
+            : MAA Summer 1984. Lots of postscript options. All silent
+  	       portraitstr, landscapestr;
+	       fontnamestr, fontsizestr;
+	       xmajorticksstr, xminorticksstr, ymajorticksstr, yminorticksstr;
+	       axistop, axisbottom, axisleft, axisright;
+            
+            : AJD Spring 1995.  
+              Added a new argument 'nwid' to the function SourceDraw, so that genspl
+              can have the necessary information. 
+
+            : AJD May, 1995.
+              Made options overlap, headroom, perspective, bytemax and type silent.
+*/
+
+
+#ifndef  lint
+static char *sccs_id = "@(#)gen.c	1.66 John Holdsworth, Mike Allerhand, Roy Patterson, Paul Manson (MRC-APU) 6/6/91" ;
+#endif
+
+
+/****************************************************************************
+* This module contains:
+*   Display option parameter strings.
+*   Model option parameter strings.
+*   File-format strings.
+*     X windows interface, (included from windows.h).
+*     Options handler routines, (included from options.h).
+*   Option defaults, (application specific).
+*   Strings for generic option types, (OnOption etc).
+*   Display options table, (displayopts[]).
+*     Model option tables, (included from table.c).
+*     Model entry-point functions, (included from model.c).
+*     Display drawing routines, (included from draw.h and fill.h).
+*   Options table construction, (constructOptions(), and mapOptions()).
+*   Main.
+****************************************************************************/
+
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <math.h>
+
+#if defined(THINK_C) || defined(NeXT)
+#include <stdlib.h>
+#endif
+
+/********************* Display option parameter strings *********************
+* The strings defined here are pointers referenced by the "value" field in
+* the display options table, displayopts. They are assigned to space which
+* initially contains defaults in the "defaultValue" field of the display
+* options table.
+****************************************************************************/
+
+static char *bmaxstr,   *topstr,    *botstr,    *overstr   ;
+static char *headstr,   *downcstr,  *heightstr, *helpstr   ;
+static char *invertstr, *lengthstr, *linstr,    *outstr    ;
+static char *reusestr,  *startstr,  *envstr,    *typestr   ;
+#ifdef X11
+static char *dispstr,   *erasestr,  *hiddenstr, *bitmapstr ;
+static char *kludgestr, *magstr,    *penstr,    *psfilestr ;
+static char *psstr,     *animstr,   *titlestr,  *viewstr   ;
+static char *widthstr,  *xstr,      *ystr                  ; 
+/* All these MAA. */
+char        *monostr,   *colourstr, *planemaskstr, *rotateaxesstr;
+char        *fgcolourstr, *bgcolourstr;                           
+char        *xstartstr, *ystartstr, *xendstr,   *yendstr;         
+char        *xnewtitlestr, *ynewtitlestr;        
+char        *portraitstr, *landscapestr;
+char        *fontnamestr, *fontsizestr, *titlesizestr;
+char        *xticksstr, *yticksstr, *outsidestr;
+char        *axistopstr, *axisbottomstr, *axisleftstr, *axisrightstr;
+char        *xmajorticksstr, *xminorticksstr, *ymajorticksstr, *yminorticksstr;
+char        *axislinewidthstr, *figurelinewidthstr;
+char        *boxstr;
+#endif  /* X11 */
+
+char *framenumberstr,  *reviewstr;            /* MAA: 3-8-1993 */
+
+static char *test1str,  *test2str,  *test3str,  *test4str  ;
+
+char headerstr[64] ;
+
+char *filestr ;
+
+/* application display parameters */
+
+#ifdef X11
+static char  *tiltstr = "0."       ;
+static char  *diststr = "0.5"      ;
+static char  *roomstr = "0%"       ;
+#endif  /* X11 */
+
+/*************** Included from glib (graphics library) directory ***********/
+
+#include "options.h"
+#include "defaults.h"
+
+#ifdef X11
+#include "windows.h"
+#endif  /* X11 */
+
+/******************* Strings for generic option values **********************
+* Generic option values, (ON_OPTION etc), are defined in options.h.
+* Convenience routines used to test or convert option values are:
+*  OptionStringsEqual( str1, str2 )     -(defined in options.c).
+*  isON( str )                          -(defined in options.h).
+*  isOFF( str )                         -(defined in options.c).
+*  isNULL( str )                        -(defined in options.c).
+*  OptionInt( str )                     -(defined in model.c).
+*  OptionDouble( str )                  -(defined in model.c).
+*  Samples( str )                       -(defined in model.c).
+*  Cycles( str, cfreq )                 -(defined in model.c).
+*  Scalar( str )                        -(defined in model.c).
+*  Freq( str )                          -(defined in model.c).
+*
+****************************************************************************/
+
+
+static char helpstring[200] = "no help initially" ;
+static char      OnOption[] =           ON_OPTION ;     /* "on"       */
+static char     OffOption[] =          OFF_OPTION ;     /* "off"      */
+static char    NullOption[] =         NULL_OPTION ;     /* "none"     */
+static char     CenterStr[] =            "center" ;
+static char     LengthStr[] =         "remainder" ;
+static char       LandStr[] =         "landscape" ;
+
+static int isEXCITE( str )
+char *str ;
+{
+    return ( strncmp( str, "excitation", strlen( str ) ) == 0 ) ;
+}
+
+static int isWATERFALL( str )
+char *str ;
+{
+    return ( strncmp( str, "waterfall", strlen( str ) ) == 0 ) ;
+}
+
+static int isGREYSCALE( str )
+char *str ;
+{
+    return ( strncmp( str, "greyscale", strlen( str ) ) == 0 ||
+	     strncmp( str, "grayscale", strlen( str ) ) == 0 ) ;
+}
+
+
+
+/************************* Options table ***********************************
+* The complete options table is built by constructOptions() according to the
+* application. It is composed of the display options, (displayopts[], below),
+* and the model option tables (from table.c) which are appropriate for the
+* application. The sequence of processing stages, (and hence model option
+* tables), for an application is determined by FindStage() in model.c.
+*
+* The complete options table is an array of Option structs.
+* The Option struct is defined in options.h as:
+*
+* typedef struct {
+*   char   *name           ;   The name of the option.
+*   char   *defaultValue   ;   Default value.
+*   char  **value          ;   Address of current value.
+*   char   *comment        ;   Something to print when the user types "-help".
+*   short   classification ;   Type of option it is.
+* } Option;
+*
+* The classification of options uses names defined in options.h:
+*   InputOption
+*   OutputOption
+*   InOutOption
+*   SilentOption
+*
+* Routines which access the option table:
+* Note: Some routines are called to supply arguments to other routines.
+*       Routines which access the option table in some way are denoted (*).
+*       Most of these routines are defined in options.c.
+*
+*                                 main()
+*                                   |
+*     +-----------------+-----------+----+-------+-----------------+
+*     |                 |                |       |                 |
+*     |                 |                | ModeledSource()         |
+*     |                 |                |       |                 |
+*     |                 |                | checkForFile()          |
+* helpopts()            |                |       |                 |
+*     |                 |                +---+---+                 |
+*     |                 |                    |                     |
+*     |              getopts()           readopts()           writeopts()
+*     |                 |                    |                     |
+*     |            getnopts(*)          readnopts()            writenopts(*)
+*     |   [arg countOptions(*)]   [arg countOptions(*)]  [arg countOptions(*)]
+*     |                 |                    |                     |
+*     |         +-------+------+             |            countBytesToWrite(*)
+*     |         |       |      |             |
+*     |         |       |      +------+------+
+*     |         |       |             |
+*     |         |       |      processOptionFile()
+*     |         |       |             |
+*     |         |       +------+------+
+*     |         |              |
+*     |         |        LookUpAndStore(*)
+*     |         |              |
+*     |         |          +---+---+----------+
+*     |         |          |       |          |
+*     |         +-----+----+    LookUp(*) Ambiguity(*)
+*     |         |     |
+*     +----+----+  updateOptionsFile(*)
+*          |
+*   defaultHelpHandler(*)
+*
+*
+* getopts()
+* Operates on the options table given to it as an argument.
+*  a) Each "value" field is initialized to its "defaultValue" field.
+*  b) The "value" fields are re-initialized by any corresponding values found
+*     in the options ("rc") file, (overriding the "defaultValue").
+*  c) The "value" fields are re-initialized again by any corresponding values
+*     found in command-line arguments.
+*  d) Special arguments are dealt with:
+*     "help"      calls the onLineHelpHandler() routine, (see below).
+*     "update"    calls the updateOptionsFile() routine.
+*  e) Return the remainder of the command-line (argc and argv) for use in
+*     main().
+*
+* helpopts()
+* Is called to print the help menu if no input file has been found by
+* getopts(), (in the "rc" file), and none remains on the command-line.
+* An alias for the onLineHelpHandler() function, which is in turn an
+* alias for the defaultHelpHandler() routine, (see options.c).
+*
+* readopts()
+* Read any options header which may be at the start of the input file.
+* Interpret the header like an options ("rc") file, and re-initialize any
+* corresponding "value" fields in the given options table, (as in getopts()).
+* Skip to the start of the input data, allowing for any offset (ie startstr).
+*
+* writeopts()
+* Write the given options table as an options header at the start of an o/p
+* file, if the "header" option is "on".
+*
+****************************************************************************/
+
+static  Option *options;
+
+/******************** Display options table ********************************
+* Options table for application display parameters.
+****************************************************************************/
+
+static  Option displayopts[] = {
+
+  /* Miscellaneous Silent Parameters (hidden from users) */
+
+
+ { "Version",      headerstr, &versionstr,      "Version number and date", OutputOption},
+
+ { "test1",              "0", &test1str,        "Dummy option for test and development", SilentOption},
+ { "test2",              "0", &test2str,        "Dummy option for test and development", SilentOption},
+ { "test3",              "0", &test3str,        "Dummy option for test and development", SilentOption},
+ { "test4",              "0", &test4str,        "Dummy option for test and development", SilentOption},
+
+ { "linear_sgm",   OffOption, &linstr,          "Linear frequency axis for spectrograms",SilentOption},
+ { "useprevious",  OffOption, &reusestr,        "Use previously stored output",          SilentOption},
+
+/* MAA: 21-8-1993 
+ * These next two options are here, because otherwise "gensgm -use ..." (at least) core dumps.
+ */
+ { "framenumber",  OffOption, &framenumberstr,  "Index of current frame (to stderr)\n",     SilentOption},
+ { "review",       OffOption, &reviewstr,       "Wait for keyboard <return> between frames",SilentOption},
+
+#ifdef X11
+ { "pstofile",     OffOption, &psfilestr,       "Send PostScript output to .ps file",    SilentOption},
+ { "invert",       OffOption, &invertstr,       "Invert axis of sai image",              SilentOption},
+ { "fast",         OffOption, &kludgestr,       "Speed up image generation",             SilentOption},
+#endif  /* X11 */
+
+  /* ( The order of the "help" option members is strange due to the way   */
+  /*   it was originally used.  See options.c: defaultHelpHandler() and   */
+  /*   updateOptionsFile() ).                                             */
+
+  /* Input Parameters */
+
+ { "envelope",     OffOption, &envstr,          "Type of model to use required",         SilentOption},
+ { "help",        "not used", &helpstr,         helpstring,                              SilentOption},
+
+#ifdef X11
+
+  /* Screen Output Parameters */
+
+ { "title",       "filename", &titlestr,  "Title of picture, or input filename",       InputOption},
+#ifdef THINK_C 
+ { "x0_win",            "10", &xstr,      "Left edge of window (pixels)",              InOutOption},
+ { "y0_win",            "50", &ystr,      "Lower edge of window (pixels)",             InOutOption},
+#else
+ { "x0_win",       CenterStr, &xstr,      "Left edge of window (pixels)",              InOutOption},
+ { "y0_win",       CenterStr, &ystr,      "Lower edge of window (pixels)",             InOutOption},
+#endif
+#ifdef PC
+ { "width_win",        "400", &widthstr,  "Window width (pixels)",                     InOutOption},
+ { "height_win",       "300", &heightstr, "Window height (pixels)\n",                  InOutOption},
+#else /* UNIX */
+ { "width_win",        "540", &widthstr,  "Window width (pixels)",                     InOutOption},
+ { "height_win",       "400", &heightstr, "Window height (pixels)\n",                  InOutOption},
+#endif
+ { "display",       OnOption, &dispstr,   "Select display of output image",            InOutOption},
+ { "view",           LandStr, &viewstr,   "Select display format",                     InOutOption},
+ { "top",             "1024", &topstr,    "Maximum of plotted range",                  InputOption},
+ { "bottom",         "-1024", &botstr,    "Minimum of plotted range",                  InputOption},
+ { "overlap",          "50%", &overstr,   "Overlap between channels",                  SilentOption}, /* AJD 16-5-95 */
+ { "headroom",          "0%", &roomstr,   "Headroom at top of picture",                SilentOption}, /* AJD 16-5-95 */
+ { "magnification",      "1", &magstr,    "Magnification of image in display",         InputOption},
+ { "pensize",            "1", &penstr,    "Size of plotted lines and dots",            InputOption},
+ { "hiddenline",    OnOption, &hiddenstr, "Hidden line removal\n",                       InputOption},
+ { "perspective",        "0", &tiltstr,   "Perspective view of display (degrees)\n",   SilentOption}, /* AJD 16-5-95 */
+#endif  /* X11 */
+
+ { "downchannel",  OffOption, &downcstr,  "Average adjacent frequency channels\n",     InOutOption},
+
+#ifdef X11
+
+  /* Auditory image cartoon parameters */
+
+ {   "erase_ctn",   OnOption, &erasestr,  "Erase display between cartoon frames",      InOutOption},
+ { "animate_ctn",  OffOption, &animstr,   "Animate cartoon",                           InOutOption},
+ {  "bitmap_ctn",  OffOption, &bitmapstr, "Produce cartoon output (.ctn)\n",           InputOption},
+ {    "mono_ctn",   OnOption, &monostr,   "Force monochrome (single plane) cartoons.", SilentOption},
+ {  "colour_ctn",  OffOption, &colourstr, "Force colour (multi-plane) cartoons.",      SilentOption},
+ {"planemask_ctn", "1", &planemaskstr,    "Planemask for creating cartoons.\n",        SilentOption},
+ {"fg_col",          "black", &fgcolourstr, "Foreground Colour.\n",                    SilentOption},
+ {"bg_col",          "white", &bgcolourstr, "Background Colour.\n",                    SilentOption},
+
+
+ /* Postscript options */
+
+ { "postscript",   OffOption, &psstr,     "Produce postscript output",                 InputOption},
+ { "rotateaxes",   OffOption, &rotateaxesstr,     "Rotate the axes labels in .ps output",  SilentOption},
+ { "xstart_ps",           "", &xstartstr, "Postscript x-axis: start point.",           SilentOption},
+ { "xend_ps",             "", &xendstr,   "Postscript x-axis: end point.",             SilentOption},
+ { "ystart_ps",           "", &ystartstr, "Postscript y-axis: start point.",           SilentOption},
+ { "yend_ps",             "", &yendstr,   "Postscript y-axis: end point.",             SilentOption},
+ { "xtitle_ps",           "", &xnewtitlestr, "Postscript x-axis: title.",              SilentOption},
+ { "ytitle_ps",           "", &ynewtitlestr, "Postscript x-axis: title.",              SilentOption},
+ { "portrait_ps",         "", &portraitstr, "Use 'portrait' page format",              SilentOption},
+ { "landscape_ps",        "", &landscapestr, "Use 'landscape' page format (overrides 'portriat)", SilentOption},
+ { "fontname_ps", "Helvetica", &fontnamestr, "Define font",              SilentOption},
+ { "fontsize_ps",       "12", &fontsizestr, "Define fontsize (points)",                     SilentOption},
+ { "fonttitlesize_ps",   "0", &titlesizestr, "Define fontsize for title (points)",                     SilentOption},
+ { "axislinewidth_ps",   "1", &axislinewidthstr, "Linewidth for axes & tickmarks (points)",                     SilentOption},
+ { "figurelinewidth_ps", "1", &figurelinewidthstr, "Linewidth for figures (points)",                     SilentOption},
+ { "xticks_ps",          "6", &xticksstr,   "Define size of x-axis (big) ticks (points)",   SilentOption},
+ { "yticks_ps",          "6", &yticksstr,   "Define size of y-axis (big) ticks' (points)",   SilentOption},
+ { "outsideticks_ps",OnOption, &outsidestr,   "Print tick-marks 'outside' figure",   SilentOption},
+ { "axistop_ps",    OnOption, &axistopstr,  "Print tick-marks on top side",   SilentOption},
+ { "axisbottom_ps", OnOption, &axisbottomstr, "Print tick-marks on bottom side",   SilentOption},
+ { "axisleft_ps",   OnOption, &axisleftstr, "Print tick-marks on left side",   SilentOption},
+ { "axisright_ps",  OnOption, &axisrightstr, "Print tick-marks on right side",   SilentOption},
+ { "xmajorticks_ps",  "1",   &xmajorticksstr, "Relative *spacing* of ticks",   SilentOption},
+ { "xminorticks_ps",  "1",   &xminorticksstr, "Relative *spacing* of ticks",   SilentOption},
+ { "ymajorticks_ps",  "1",   &ymajorticksstr, "Relative *spacing* of ticks",   SilentOption},
+ { "yminorticks_ps",  "1",   &yminorticksstr, "Relative *spacing* of ticks",   SilentOption},
+ { "box_ps",     OnOption,       &boxstr,                  "Plot a box",   SilentOption},
+#endif  /* X11 */
+
+  /* File Output Parameters */
+ { "output",       OffOption, &outstr,    "Produce output file",                       InputOption},
+ { "header",        OnOption, &headstr,   "Add a header to the output file\n",           InOutOption},
+ { "bytemax",          "255", &bmaxstr,   "Maximum value in byte output",              SilentOption}, /* AJD 16-5-95 */
+ { "type",           "short", &typestr,   "Output data type\n",                        SilentOption}, /* AJD 16-5-95 */
+
+ { "input_wave",  NullOption, &filestr,   "Default input file name",                   InputOption},
+ { "start_wave",       "0ms", &startstr,  "Start point in wave (ms)",                  InputOption},
+ { "length_wave",  LengthStr, &lengthstr, "Length of wave to process (ms)",            InputOption},
+
+ ( char * ) 0 } ;
+
+
+/*********************** Included from stitch directory ********************/
+
+/* interfaces to stitch system */
+
+#include "stitch.h"
+#include "source.h"
+#include "spiral.h"
+#include  "image.h"
+#include  "model.h"
+#include  "units.h"
+#include   "calc.h"
+#include    "ops.h"
+#include     "io.h"
+
+
+#ifdef X11
+#include   "draw.h"
+#include   "fill.h"
+#endif  /* X11 */
+
+/**************************************************************************/
+
+char *AlterSuffix() ;               /* alter suffix of file name. */
+#ifdef X11
+void save_frame(), plot_frame() ;   /* draw callbacks. */
+void fast_frame() ;
+#endif  /* X11 */
+
+extern char *genstate() ;
+static char *gen_state ;
+
+Source DownChannel() ;              /* reduce channels by averaging. */
+#ifdef X11
+Source PackShorts()  ;              /* pack output into one byte. */
+#endif  /* X11 */
+Source checkForFile() ;             /* create source from file if present. */
+
+#define POSTSCRIPT_FILE_SUFFIX ".ps"
+#define CARTOON_FILE_SUFFIX ".ctn"
+
+#ifdef X11
+static WindowObject display = 0 ;
+#endif  /* X11 */
+
+/***************************************************************************/
+
+/* Return length of the file in bytes */
+static long fileLength( fp )
+FILE *fp ;
+{
+    long posn = ftell( fp ) ;
+    long length = 0 ;
+
+    if( fseek( fp, 0l, 2 ) == 0 ) {
+
+	length = ftell( fp ) ;
+
+	(void) fseek( fp, posn, 0 ) ;
+    }
+
+    return ( length ) ;
+}
+
+/* per frame image handling */
+
+static FILE *inputFilePointer = ( FILE * ) 0 ;
+
+#ifdef X11
+
+static FILE *imageFilePointer = ( FILE * ) 0 ;
+static int   images = 0 ;
+static void (*frame_drawer)() ;
+
+/***** axis information *****/
+/*
+  "Axis" is defined in windows.h:143
+  The postscript program for drawing axis stuff is in axis.h
+*/
+
+static int Top()
+{
+    return ( atof( topstr ) / atof( magstr ) + 0.5 ) ;
+}
+
+static int Bot()
+{
+    if( atof( botstr ) < 0 )
+	return ( atof( botstr ) / atof( magstr ) - 0.5 ) ;
+    else
+	return ( atof( botstr ) / atof( magstr ) + 0.5 ) ;
+}
+
+static struct {
+  double min, max ;
+  char *label ;
+} xaxis, yaxis ;
+
+
+
+TimeAxis( min, max, label )
+double *min, *max ;
+char **label ;
+{
+    *min = Samples( startstr, Samplerate() ) / Samplerate()                                         ;
+    *max = Samples( startstr, Samplerate() ) / Samplerate() + Frames() * Framestep() / Samplerate() ;
+
+    if( *max > 1. )
+	*label = "Time [s]" ;
+    else {
+	*label = "Time [ms]" ;
+
+	*min *= 1000. ;
+	*max *= 1000. ;
+    }
+}
+
+MagnitudeAxis( min, max, label )
+double *min, *max ;
+char **label ;
+{
+    *min = Bot() ;
+    *max = Top() / ( 1. - atof( headstr ) / 100. ) ;
+
+    *label = "Magnitude" ;
+}
+
+
+static void DrawAxes( win )
+WindowObject win ;
+{
+    /* frame window with axes */
+
+    Axes( win, titlestr, xaxis.min, xaxis.max, xaxis.label,
+			 yaxis.min, yaxis.max, yaxis.label ) ;
+    return ;
+}
+
+#endif  /* X11 */
+
+/******************************* main **************************************
+* The following tables are used extensively:
+* stage table   Arrays of _stage structs, ("envelope", "fine", etc.), defined
+*               in routine FindStage() in model.c.
+* option table  Array of Option structs built at run-time by
+*               constructOptions() from displayopts, (in gen.c), and tables of
+*               model options included from table.c.
+*
+* Compiler switches for model versions are:
+*     FLOAT     For floating point version, (default uses integer arithmetic).
+*               Defined in calc.h.
+*
+* The model version number is the sccs <release-number>.<level-number> of
+* the file version.c. Refer to that file for incrementing the version number.
+* The version number is stored in versionstr in routine getversion().
+****************************************************************************/
+
+int    argc_save ;
+char **argv_save ;
+
+main( argc, argv )
+int argc ;
+char *argv[] ;
+#ifdef THINK_C
+{
+	static char *realargv[] = { "prog", "", 0 };
+	static char *progs = { "\pgenwav;-;\
+genfbm;genfbr;genfbc;genfbt;genfbd;gensai;genspl;gensas;-;\
+genbmm;gennap;gensai;-;gensgm;gencgm;gensas;-;genasa;genepn;gensep;-;Quit/Q" } ;
+	
+	extern char *MacMenu(), *MacFile() ;
+	
+	MacInit() ;
+
+	realargv[0] = MacMenu(progs) ;
+	realargv[1] = MacFile() ;
+
+	return ( real_main( sizeof( realargv ) / sizeof (*realargv) - 1, realargv ) ) ;
+}
+
+real_main( argc, argv )
+int argc ;
+char *argv[] ;
+#endif
+{
+    int    i ;
+    FILE *ofp = 0 ;
+    Source source ;
+    char *which, *psfilename ;
+    char title[256] ;
+    char *programName ;
+    int x, y, pixels, image, time ;
+    long headerSize, fileFramebytes ;
+    double *frequency_scale ;
+#ifdef X11
+    WindowObject psw = 0 ;
+    char *imageFileName ;
+#endif  /* X11 */
+
+/**************************************************************************
+* Determine which version of the model is required.
+* Set "which" to the last three chars of the program name, (allowing for
+* a ".exe" extension in the case of a PC version).
+**************************************************************************/
+
+
+    programName = argv[0] ;
+
+    which = programName + strlen( programName ) - strlen( "xxx" ) ;
+
+#ifdef PC
+    lowerArgs( argv, argc ) ;
+
+    which -= strlen( ".exe" ) ;
+#endif
+
+
+/***************************************************************************
+* Process arguments, (the model options):
+* Set option defaults (from option table in model.c).
+* Then override these by any options in the options file,
+* (the resource control file, eg .gensairc).
+* Finally, override these by any options given as command-line arguments.
+*
+* offsetOptions() finds the first option, (a ptr to one line of the "res"
+* array), required by the program. This gives a place mark in the options
+* table. (Note that the bottom of the options table, a null, corresponds with
+* the top of the help menu).
+* This first option appropriate to the program is found by looking it up in
+* the stage table (in model.c), and then cross-referencing the option name
+* with the names in the options table.
+*
+* Here is an example of an option, showing the members of the Options struct:
+*   name:         defaultValue: value:       comment:         classification:
+* {"length_wave", LengthStr,    &lengthstr, "Length of wave", InputOption},
+*
+* getopts() operates on the options between the given place mark and the
+* bottom of the table.
+* This is the only call to routine getopts(), which is defined in options.c.
+* First, each "value" is set to its corresponding "defaultvalue".
+* Then the options file (the "rc" file) is opened, and any options found there
+* are assigned to the corresponding "value", (overriding the "defaultvalue").
+* Then the command-line arguments are examined, and any options found there
+* are assigned to the corresponding "value", (overriding again).
+* Special arguments are dealt with:
+*   "help"      calls the onLineHelpHandler() routine, (see below).
+*   "update"    calls the updateOptionsFile() routine.
+*
+* Finally, leave the remainder of the command line (argc and argv).
+* Anything left on the command line is interpreted as follows:
+*   "filestr"   is the input data filename,
+*   "startstr"  is the start point in the data,
+*   "lengthstr" is the amount of data to process,
+*   "whichstr"  is the last 3 chars of the program name (the program version).
+*
+* Note that if no input file has been found by getopts(), (in the "rc" file),
+* and none remains on the command line, then helpopts() is called.
+* This is an alias for the onLineHelpHandler() function, which is in turn an
+* alias for the defaultHelpHandler() routine, (see options.c).
+*
+*
+***************************************************************************/
+
+    getversion( programName ) ;
+
+    /* The helpstring, defined in model.c, is stored as the comment field  */
+    /* of the help option (see table.c). It is accessed in options.c in    */
+    /* defaultHelpHandler(), using options[help].comment.                  */
+
+    (void) sprintf( helpstring, " [file_name]\n       Generates %s", modelHelp( which ) ) ;
+
+    options = constructOptions( which, displayopts ) ;
+
+
+    /* Hack to save argc and argv so they don't get mangled by getopts    */
+    /* This is so the command line args can override a reused file header */
+
+    argc_save = argc ;
+    argv_save = (char **)malloc( ( argc + 1 ) * sizeof( char *) ) ;
+    for ( i = 0 ; i < argc ; i++ ) {
+	argv_save[i] = (char *)malloc( ( strlen( argv[i] ) + 1 ) * sizeof( char ) ) ;
+	strcpy( argv_save[i], argv[i] ) ;
+    }
+
+    getopts( options, &argc, &argv ) ;
+
+    if( argc == 0 && isNULL( filestr ) ) {
+	(void) helpopts( options, programName ) ;
+	stitch_exit( -1 ) ;
+    }
+
+    if( argc > 0 && strcmp( *argv, "+" ) != 0 && argc-- > 0 )
+	filestr   = *argv++ ;
+
+    if( argc > 0 && strcmp( *argv, "+" ) != 0 && argc-- > 0 )
+	startstr  = *argv++ ;
+
+    if( argc > 0 && strcmp( *argv, "+" ) != 0 && argc-- > 0 )
+	lengthstr = *argv++ ;
+
+    if( isNULL( whichstr ) )
+	whichstr = which ;
+
+
+/***************************************************************************
+* horrrrrrrrible hack for now to try out -envelope option
+***************************************************************************/
+
+    if( isON( envstr ) )
+	if( whichstr[1] == 'b' )
+	    whichstr[1] =  'e' ;
+	else {
+	    /* map sai to sie and sas to sse */
+
+	    whichstr[1] = whichstr[2] ;
+	    whichstr[2] = 'e' ;
+	}
+
+
+/***************************************************************************
+* hack test arguments
+***************************************************************************/
+#if 00
+    test1 = atof( test1str ) ;
+    test2 = atof( test2str ) ;
+    test3 = atof( test3str ) ;
+    test4 = atof( test4str ) ;
+#endif
+
+/***************************************************************************
+* Open input data file, (use stdin if filename "-" is given).
+***************************************************************************/
+
+    if( strcmp( filestr, "-" ) == 0 )
+	inputFilePointer = stdin ;
+    else
+	inputFilePointer = fopen( filestr, readBinary ) ;
+
+/***************************************************************************
+* Position input data file pointer correctly:
+* Read any options header at the start of the input file. Set any options.
+* Skip to the start of the input data, allowing for any offset (ie startstr).
+* Set "framesstr" to the number of frames in the input data file, (here this
+* means the number of shorts remaining in the input file).
+* Create a source for the input data file.
+* Re-set "framesstr" to allow for a given "lengthstr", (ie not the whole file).
+***************************************************************************/
+
+    if( inputFilePointer != (FILE *) 0 ) {
+
+	readopts( options, inputFilePointer ) ;
+
+	headerSize = ftell( inputFilePointer ) ;
+
+	setFrames( fileLength( inputFilePointer ) / sizeof ( short ) - (long) Samples( startstr, Samplerate() ) ) ;
+
+	(void) fseek( inputFilePointer, (long)( headerSize + (long) Samples( startstr, Samplerate() ) * sizeof ( short ) ), 0 ) ;
+
+	source = FileSource( inputFilePointer ) ;
+    }
+
+    /* If a specific processing amount is specifed (other than "remainder") */
+    /* and this amount is less than the remainder of the input file, then   */
+    /* override the amount of data to process, (in framesstr).              */
+
+    if ( strncmp( lengthstr, LengthStr, strlen(lengthstr) ) != 0 &&
+			    Samples( lengthstr, Samplerate() ) < Frames() )
+	setFrames( (long) ( Samples( lengthstr, Samplerate() ) ) / Framestep() ) ;
+
+
+/***************************************************************************
+* Create source with data derived from processing file through model.
+* This may involve several stages of callback, and will initialize a chain of
+* objects which will ultimately execute the program, (see SinkSource() below).
+* If reusestr in "on", the "useprevious" option will use a previously
+* generated file, (see checkForFile() routine below).
+* If no input data file is found, report error: "could not open file".
+*
+* The routine ModeledSource() first uses Findstage() to find the appropriate
+* place in the stage table called for by the program, (see model.c).
+* Then it finds the end of the stage table, and works back up the table to
+* the stage called for by the program. Each stage in the table is a process
+* on the way to the program as a whole. The order of the stage table sets the
+* order of processing.
+* Immediately below are the only two calls to routine ModeledSource().
+***************************************************************************/
+
+    if( isON( reusestr ) )
+	source = ModeledSource( source, checkForFile ) ;
+    else
+	if( inputFilePointer != (FILE *) 0 )
+	    source = ModeledSource( source, (Source ( * )()) 0 ) ;
+
+    if( inputFilePointer == (FILE *) 0 )
+	stitch_error( "Could not open file \"%s\" for input\n", filestr ) ;
+
+/***************************************************************************
+* If the "downchannel" option is on, reduce channels by averaging.
+* (See DownChannel() routine below).
+* Then updateFramebytes sets  "framebytesstr" to the total number of bytes
+* in each frame, (ie the new width * height).
+***************************************************************************/
+
+
+    for( time=0 ; time<OptionInt( downcstr ) ; time++ ) {
+	source = DownChannel( source, Frameheight() ) ;
+	setFrameheight( Frameheight() / 2 ) ;
+    }
+    updateFramebytes() ;
+
+#if 0  /* for debugging */
+fprintf( stderr, "%d %d %d %d %ld\n",
+	Framewidth(),
+	Frameheight(),
+	Framebytes(),
+	Framestep(),
+	Frames() ) ;
+#endif
+
+/***************************************************************************
+* From here on is concerned with setting up for output, then starting the
+* processing, and finally cleaning up.
+***************************************************************************/
+
+#ifdef X11
+/* First sort out window placement. */
+
+    if( strcmp( xstr, CenterStr ) == 0 )
+	x = -1 ;
+    else
+	x = atoi( xstr ) ;
+
+    if( strcmp( ystr, CenterStr ) == 0 )
+	y = -1 ;
+    else
+	y = atoi( ystr ) ;
+
+    if( isGREYSCALE( viewstr ) )
+	pixels = 0 ;
+    else {
+	pixels = atoi( penstr ) ;
+
+	if( isON( hiddenstr ) && Frameheight() > 1 )
+
+	    pixels = -abs( pixels ) ;
+
+	/* Convert arguments for line-drawing. See draw.ch */
+	drawTilt     = atof( tiltstr ) ;
+	drawDistance = atof( diststr ) ;
+	drawHeadroom = atof( roomstr ) ;
+	drawOverlap  = atof( overstr ) / 100. ;
+#ifdef mips
+	if( pixels == 0 )
+	    pixels = 1 ;
+#endif
+    }
+#endif  /* X11 */
+
+    /* work out title of output */
+
+    (void) strcpy(  title, filestr ) ;
+    (void) strcat(  title, "." ) ;
+    (void) strncat( title, whichstr, strlen( "xxx" )+1 ) ;
+
+#ifdef X11
+
+    if( strcmp(titlestr,"filename") == 0)   /* was: if(isNULL(titlestr)) */
+	titlestr = title ;
+
+    /* calculate axis information */
+
+    if( isEXCITE( viewstr ) ) {
+	  ChannelAxis( &xaxis.min, &xaxis.max, &xaxis.label ) ;
+	MagnitudeAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ;
+    }
+    else if( isWATERFALL( viewstr ) ) {
+	  ChannelAxis( &xaxis.min, &xaxis.max, &xaxis.label ) ;
+	     TimeAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ;
+    }    /* landscape ones */
+    else if( Framewidth() > 1 ) {
+	    DelayAxis( &xaxis.min, &xaxis.max, &xaxis.label ) ;
+	  ChannelAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ;
+    }
+    else {
+	     TimeAxis( &xaxis.min, &xaxis.max, &xaxis.label ) ;
+
+	if( Frameheight() > 1 )
+	  ChannelAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ;
+	else
+	MagnitudeAxis( &yaxis.min, &yaxis.max, &yaxis.label ) ;
+
+    }
+
+
+    /* select outputs... */
+
+
+    /* select sai drawing method */
+
+    /* Hack so spiral parameters are independent of stage and option order */
+    /* (Spiral parameters appear late in options list, so are not known    */
+    /*  when an earlier stage is specified. So don't process unless sai).  */
+
+    if( strncmp(whichstr,"spl",strlen("spl")) == 0 ) {
+
+	frame_drawer = draw_spiral;
+
+	dotthresh_spl = Top() ;
+	dotsize_spl   = OptionInt(  penstr ) ;
+    }
+    else
+	frame_drawer = draw_frame;
+
+    /* screen output first         */
+    /* (set by option: display=on) */
+
+    if( isON( dispstr ) ) {
+
+	display = newDisplayWindow( titlestr, x, y, atoi( widthstr ), atoi( heightstr ), pixels ) ;
+
+	if( !isGREYSCALE( viewstr ) /* && OptionInt( penstr ) != 0 */ ) {
+
+		if( Top() == Bot() )
+		    stitch_error( "error: display top and bottom parameters the same value\n" );
+
+		if( isEXCITE( viewstr ) )
+		    source = SourceDraw( source, Bot(), Top(), display, Frameheight(), 1, Nwidth(), Frames(), save_frame, frame_drawer ) ;
+		else if( isWATERFALL( viewstr ) ) 
+		    source = SourceDraw( source, Bot(), Top(), display, Frameheight(),  Frames(), Nwidth(), 1, save_frame, frame_drawer ) ;
+		else if( !isON( kludgestr ) ) 
+		    source = SourceDraw( source, Bot(), Top(), display, Framewidth(), Frameheight(), Nwidth(), Frames(), save_frame, frame_drawer ) ; 
+		else {        /* speed-up for sai */
+		    source  = SourceDraw( source,    Bot(), Top(), display, Framewidth(), Frameheight(), Nwidth(), Frames(), save_frame, fast_frame  ) ;
+		    gen_state = genstate( display,   Bot(), Top(),          Framewidth(), Frameheight(), Nwidth(), Frames(), pixels ) ;
+		    frame_drawer=fast_frame ;
+		}
+	}
+	else {
+	    if( isON( erasestr ) )
+		Clear(   display ) ;
+
+	    DrawAxes( display ) ;
+
+	    if( isON( linstr ) )
+		frequency_scale = frequencies ;
+	    else
+		frequency_scale = (double *) 0 ;
+
+	    if( Framewidth() > 1 )
+		source = FillDown(   display, source, Top(), Bot(), Framewidth(), Frameheight() ) ;
+	    else
+		source = fillAcross( display, source, Top(), Bot(), Frameheight(),(int)Frames(), frequency_scale ) ;
+	}
+    }
+
+    /* postscript output next         */
+    /* (set by option: postscript=on) */
+
+    if( isON( psstr ) ) {
+
+	if( isON( psfilestr ) )
+	    psfilename = AlterSuffix( filestr, POSTSCRIPT_FILE_SUFFIX ) ;
+	else
+	    psfilename = (char *) 0 ;
+
+/* the extra argument to newPSWindow. MAA> 27-1-1993. */
+	psw = newPSWindow( psfilename, x, y, atoi(widthstr), atoi(heightstr), atoi( penstr ), isON( hiddenstr ) );
+
+	if( !isGREYSCALE( viewstr ) && OptionInt( penstr ) != 0 ) {
+
+		if( isEXCITE( viewstr ) )
+		    source = SourceDraw( source, Bot(), Top(), psw,     Frameheight(),            1, Nwidth(), Frames(), plot_frame, frame_drawer ) ;
+		else if( isWATERFALL( viewstr ) )
+		    source = SourceDraw( source, Bot(), Top(), psw,     Frameheight(),     Frames(),  Nwidth(),      1, plot_frame, frame_drawer ) ;
+		else
+		    source = SourceDraw( source, Bot(), Top(), psw,     Framewidth(), Frameheight(), Nwidth(), Frames(), plot_frame, frame_drawer ) ;
+	}
+	else { /* greyscale displays */
+
+	    if( isON( erasestr ) )
+		Clear(   psw ) ;
+
+	    DrawAxes( psw ) ;
+
+	    if( isON( linstr ) )
+		frequency_scale = frequencies ;
+	    else
+		frequency_scale = (double *) 0 ;
+
+	    if( Framewidth() > 1 )
+		source = FillDown(   psw, source, Top(), Bot(), Framewidth(), Frameheight() ) ;
+	    else
+		source = fillAcross( psw, source, Top(), Bot(), Frameheight(),(int)Frames(), frequency_scale ) ;
+	}
+    }
+
+
+    if( strcmp( typestr, "char" ) == 0 ) {
+	source = PackShorts( source ) ;
+	fileFramebytes = Framebytes() / sizeof ( short ) * sizeof ( char ) ;
+    }
+    else
+
+#endif  /* X11 */
+
+	fileFramebytes = Framebytes() ;
+
+    /* output to file */
+
+    if( !isOFF( outstr ) ) {
+
+	(void) unlink( title ) ;
+
+	if( OptionStringsEqual( outstr, OnOption ) )
+	    ofp = fopen( title,  writeBinary ) ;
+	else {
+	    if( strcmp( outstr, "stdout" ) == 0 )
+		ofp = stdout;
+	    else
+		ofp = fopen( outstr, writeBinary ) ;
+	}
+
+	if( ofp == (FILE *) 0 )
+	    stitch_error( "Unable to open file %s for output\n", title ) ;
+	else {
+	    if( isON( headstr ) )
+		writeopts( options, ofp ) ;
+
+	    source = FileTap( source, ofp ) ;
+	}
+    }
+
+#ifdef X11
+
+    /* output of screen "image" files in display format */
+    if( !isOFF( bitmapstr ) ) {
+      imageFileName = AlterSuffix(filestr, CARTOON_FILE_SUFFIX ) ;
+
+      if( (strcmp( bitmapstr, "stdout" ) == 0 )){
+           imageFilePointer = stdout;
+	   writeopts( options, imageFilePointer ) ;}
+      else 
+	if ( ( imageFilePointer = fopen(imageFileName, writeBinary ) ) == (FILE *) 0)
+	  stitch_error( "Unable to open file %s for image output\n", imageFileName ) ;
+	else
+	  writeopts( options, imageFilePointer ) ;}
+
+    if (( ofp == stdout ) && ( imageFilePointer == stdout ))
+        stitch_error( "Both 'output' and 'bitmap' set to stdout.\n", title);
+
+#endif  /* X11 */
+
+
+/***************************************************************************
+* Execute the program by pulling data from the source.
+* This is the only call to routine SinkSource(), which is defined in
+* stitch/source.c as sinkSource().
+* (SinkSource is an alias, defined in stitch/source.h, to cast the arguments).
+* Routine sinkSource() executes:  "(void) Pull( source, fileFramebytes ) ;"
+* for "Frames()" times in succession.
+* A chain of source objects, linked by callback-function pointers, was setup
+* earlier, (see call to ModeledSource() above).
+***************************************************************************/
+
+
+    SinkSource( source, fileFramebytes,   Frames() ) ;
+
+
+/***************************************************************************
+* Clean up and close
+****************************************************************************/
+
+    CloseSource( source ) ;
+
+    if( ofp != (FILE *) 0 )
+	(void) fclose( ofp ) ;
+
+#ifdef X11
+
+    if( psw != (WindowObject) 0 )
+	Close( psw ) ;
+
+    if( display != (WindowObject) 0 ) {
+
+	/* animate sai's if selected */
+
+	do
+	{
+	    for( image=1 ; image <= images ; image++ )
+		for( time = OptionInt( animstr ) ; time>0 ; time-- )
+		    Recall( display, image ) ;
+
+	    if( Pause( display ) == 'q' )
+		break;
+
+	} while( isON( animstr ) ) ;
+
+	Close( display ) ;
+    }
+
+#endif  /* X11 */
+
+    stitch_exit( 0 ) ;
+}
+
+/*************************** End main *************************************/
+
+/***************************************************************************
+* checkForFile()
+* Create source from file if present, to be used if reusestr in "on".
+* This is the "useprevious" option to use previously generated files.
+***************************************************************************/
+
+Source checkForFile( which )
+char *which ;
+{
+    static Source noSource = { (struct _source *) 0 } ;
+    long headerSize, fileFramebytes ;
+    char file_name[200] ;
+    FILE *tmp ;
+
+    (void) strcpy( file_name, filestr ) ;
+    (void) strcat( file_name, "."  ) ;
+    (void) strcat( file_name, which ) ;
+
+    if( ( tmp = fopen( file_name, readBinary ) ) != ( FILE * ) 0 ) {
+
+	inputFilePointer = tmp ;
+
+	(void) fprintf( stderr, "Using existing file \"%s\"\n", file_name ) ;
+
+	readopts( options, inputFilePointer ) ;
+
+	/* the saved command line overrides options from file header */
+
+	if( isON( reusestr ) )
+	    cmd_line_opts( options, &argc_save, &argv_save ) ;
+
+	headerSize = ftell( inputFilePointer ) ;
+
+	if( strcmp( typestr, "char" ) == 0 )
+	    fileFramebytes = Framebytes() / 2 ;
+	else
+	    fileFramebytes = Framebytes() ;
+
+	/*
+	If length=remainder then use the whole file.
+	Otherwise the length of the reused file is that given on the command
+	line, or the default length (if no length option is given).
+	*/
+
+	if ( strncmp( lengthstr, LengthStr, strlen(lengthstr) ) == 0 )
+	    setFrames( ( fileLength( inputFilePointer ) - headerSize ) / fileFramebytes - (long) Samples( startstr, Samplerate() ) / Framestep() ) ;
+	else
+	    setFrames( (long) ( Samples( lengthstr, Samplerate() ) ) / Framestep() ) ;
+
+
+	(void) fseek( inputFilePointer, headerSize + (long) Samples( startstr, Samplerate() ) / Framestep() * fileFramebytes, 0 ) ;
+
+#ifndef PC
+	if( strcmp( typestr, "char" ) == 0 )
+	    return( CharShortSource( FileSource( inputFilePointer ) ) ) ;
+	else
+#endif
+	    return(                  FileSource( inputFilePointer )   ) ;
+    }
+    else
+	return( noSource ) ;
+}
+
+/***************************************************************************
+* AlterSuffix().
+* Returns its argument fileName with a newSuffix appended in place of
+* any previous suffix it may have had. It should be noted that this
+* suffix must include any DOT it wishes to have appended to the name.
+***************************************************************************/
+
+/* File Name Suffix Conversion Parameters */
+
+#define BACKSLASH_CHAR  '\\'
+#define SLASH_CHARACTER '/'
+#define NULL_CHARACTER  '\000'
+#define DOT_CHARACTER '.'
+
+char *AlterSuffix(fileName, newSuffix)
+     char *fileName, *newSuffix;
+{
+  char *temp, *temp2, *lastPart;
+#if defined( PC )
+  int i;
+#endif
+
+  temp = stitch_malloc((unsigned) (strlen(fileName) + strlen(newSuffix) + 1), "AlterSuffix" );
+
+  temp = strcpy(temp, fileName);
+
+#if defined(PC)
+  /* Change all backslashes to forward slashes */
+  for (i = 0; temp[i] != NULL_CHARACTER; i++)
+    if (temp[i] == BACKSLASH_CHAR)
+      temp[i] = SLASH_CHARACTER;
+#endif
+  
+  if ((lastPart = strrchr(temp, SLASH_CHARACTER)) == NULL)
+    lastPart = temp;
+  else
+    lastPart++; /* Skip over the actual "/" */
+
+  /* lastPart points to the tail name of the path */
+
+  if ((temp2 = strchr(lastPart, DOT_CHARACTER)) == NULL)
+    temp = strcat(temp, newSuffix);
+  else
+    temp2 = strcpy(temp2, newSuffix);
+
+  return (temp);
+}
+
+#ifdef X11
+
+/***************************************************************************
+* Interceptions for various combinations of drawing.
+* An "interception function" is a function inserted into a chain a functions
+* linked by function pointers. The inserted function "intercepts" the
+* processing, to perform some transformation.
+****************************************************************************/
+
+/* intercept draw to store images for animation */
+
+void save_frame( state, frame, first )
+struct _draw_state *state ;
+short *frame ;
+int first ;
+{
+    if( first ) {
+	if( isON( erasestr ) )
+	    Clear( state->window ) ;
+
+	if( frame_drawer != (void (*)()) draw_spiral && state->framenumber == 1 )
+	    DrawAxes( state->window ) ;
+	}
+
+    frame_drawer( state, frame ) ;
+
+    if( isON( animstr ) && isOFF( kludgestr ) )
+	if( Store( state->window ) )
+	    ++images ;
+
+    if( isON( bitmapstr ) )
+	Write( state->window, imageFilePointer ) ;
+
+    return ;
+}
+
+/* hacky but effective faster frame drawing routine - for sai only! */
+
+void fast_frame( state, frame, first )
+struct _draw_state *state ;
+short *frame ;
+int first ;
+{
+    if( isON( animstr ) || images == 0 )
+	if( Store( state->window ) )
+	    ++images ;
+
+    /* generate image in current cleared image */
+
+    generate( gen_state, frame ) ;
+
+    /* then recal the window using the modified image */
+
+    Recall( state->window, images );
+
+    return ;
+}
+
+/* intercept plot to check if page should be output for printing */
+
+static int plot_wanted( state )
+struct _draw_state *state ;
+{
+#if !defined(PC)
+    if( display != ( WindowObject ) 0 && state->framewidth > 1 && state->frames > 1 ) {
+	(void) fprintf(stderr, "Hit \"y\" to include this image in the PostScript file: ");
+
+	switch ( Pause( display ) ) {
+
+	    case 'y' : case 'Y' :
+	    case 'p' : case 'P' :
+		return 1 ;
+
+	    default :
+		return 0 ;
+	}
+    }
+#endif
+    return 1 ;
+}
+
+void plot_frame( state, frame, first )
+struct _draw_state *state ;
+short *frame ;
+int first ;
+{
+    int centering = state->window->entries->x( state->window ) < 0 &&
+		    state->window->entries->y( state->window ) < 0 ;
+
+    if( isOFF( erasestr ) || state->framewidth == 1 || plot_wanted( state ) ) {
+
+	if( first && ( state->framenumber == 1 || isON( erasestr ) ) ) {
+/*  ***	    if( centering )   *** removed the conditional. M.Akeroyd. 22-1-1993.*/
+		Clear(   state->window ) ;
+
+	    if( frame_drawer != (void (*)()) draw_spiral )
+		DrawAxes( state->window ) ;
+	}
+
+	frame_drawer( state, frame ) ;
+    }
+
+    return ;
+}
+
+#endif  /* X11 */
+
+/***************************************************************************
+* downchannel: average across channels for output  (with special sai version)
+***************************************************************************/
+
+struct _down_channel_state {
+    struct _fillable_source parent ;
+    int channels ;
+    Source input ;
+} ;
+
+
+static Pointer down_channel_callback( state, bytes, buffer )
+struct _down_channel_state *state ;
+ByteCount *bytes ;
+short *buffer ;
+{
+    register int last = *bytes == 0 ;
+    register int chan, outchans = state->channels >> 1 ;
+    long frame, frames = ToPoints( short, *bytes ) / outchans ;
+    register short *iptr = PullItems( state->input, frames * state->channels, short ) ;
+    register short *bptr = buffer ;
+
+    for( frame=0 ; frame<frames ; frame++ ) {
+	for( chan=0 ; chan<outchans ; chan++ )
+	    *bptr++ = ( *iptr++ + *iptr++ ) / 2 ;
+
+	if( ( outchans << 1 ) != state->channels )
+	    iptr++ ;
+    }
+
+    if( !last )
+	return ( (Pointer) buffer ) ;
+    else
+	return ( DeleteFillableSource( state ) ) ;
+}
+
+static Pointer down_channel_callback_sai( state, bytes, buffer )
+struct _down_channel_state *state ;
+ByteCount *bytes ;
+short *buffer ;
+{
+    register int last = *bytes == 0 ;
+    register int chan, outchans = state->channels >> 1 ;
+    long frame, frames = ToPoints( short, *bytes ) / outchans ;
+    register short *iptr = PullItems( state->input, frames * state->channels, short ) ;
+    register short *bptr = buffer ;
+    register short *iptr2 ;
+
+    iptr2 = iptr + frames ;
+    for( chan=0 ; chan<outchans ; chan++ ) {
+	for( frame=0 ; frame<frames ; frame++ )
+	    *bptr++ = ( *iptr++ + *iptr2++ ) / 2 ;
+    }
+
+    if( !last )
+	return ( (Pointer) buffer ) ;
+    else
+	return ( DeleteFillableSource( state ) ) ;
+}
+
+
+Source DownChannel( source, channels )
+Source source ;
+{
+    DeclareNew( struct _down_channel_state *, state ) ;
+
+    state->channels = channels ;
+    state->input = source ;
+
+
+    /* Hack for special-case downchannel routine to handle format of sai and spl frames (mha: 22/6/93) */
+
+    if( strncmp(whichstr,"sai",strlen("sai")) == 0 ||
+	strncmp(whichstr,"spl",strlen("spl")) == 0    )
+
+	return ( SetFillableSource( state, down_channel_callback_sai, "down channeling sai frames" ) ) ;
+
+    return ( SetFillableSource( state, down_channel_callback, "down channeling" ) ) ;
+}
+
+
+#ifdef X11
+
+/***************************************************************************
+* Pack model output onto a single byte if required,
+* using greyscale Top() from display.
+***************************************************************************/
+
+typedef struct { struct _fillable_source parent ; Source input ; } *PackSource ;
+
+static Pointer pack_callback( state, bytes, buffer )
+PackSource state ;
+ByteCount *bytes ;
+Pointer buffer ;
+{
+    register int last = *bytes == 0 ;
+    register short  *iptr = PullShorts( state->input, *bytes ) ;
+    register Pointer optr = buffer ;
+    register Pointer eptr = buffer + *bytes ;
+    register int bytemax  = atoi( bmaxstr  ) ;
+    register int max      = Top() ;
+    register int min      = Bot() ;
+
+    while( optr < eptr )
+	if( *iptr > max ) {
+	    *optr++ = bytemax ;
+	     iptr++ ;
+	}
+	else if( *iptr < min ) {
+	    *optr++ = 0 ;
+	     iptr++ ;
+	}
+	else
+	    *optr++ = ( ( ( *iptr++ - min ) * bytemax + ( bytemax >> 1 ) ) / ( max - min ) ) & 0xff ;
+
+    if( !last )
+	return ( buffer ) ;
+    else
+	return ( DeleteFillableSource( state ) ) ;
+}
+
+
+Source PackShorts( input )
+Source input ;
+{
+    DeclareNew( PackSource, source ) ;
+
+    source->input = input ;
+
+    return ( SetFillableSource( source, pack_callback, "gen.c packing" ) ) ;
+}
+
+#endif  /* X11 */
+
+/***************************************************************************/
+
+#ifdef PC
+static lowerArgs( argv, argc )
+char **argv ;
+int argc ;
+{
+    register char *ptr ;
+    register int arg ;
+
+    for( arg=0 ; arg<=argc ; arg++ )
+	for( ptr=argv[arg] ; *ptr != '\000' ; ptr++ )
+	    if( isupper( *ptr ) )
+		*ptr = tolower( (int) *ptr ) ;
+    return ;
+}
+#endif
+
+
+/***************************************************************************
+* Set the value of versionstr to the model version number and current time.
+* The version number is the sccs <release-number>.<level-number> of the file
+* version.c. The current time is returned by ctime(time(0)).
+* This routine initializes the default version-string (headerstr), which is
+* later copied into the version-string (versionstr) during getopts().
+* In this way, the version-string is available for output at the head of
+* the help and the options (rc) files, and also output as part of the header,
+* (when output=on).
+* Note, the versionstr has to be quoted, otherwise the routine
+* processOptionFile in options.c will report an error (Detected Trailing...)
+* when it finds blanks within a line. This happens when trying to read an
+* options file, for example when reviewing. The addition of quotes enables
+* a line containing blanks to be read complete by the subroutine getName.
+***************************************************************************/
+
+#include "version.c"
+
+getversion( name )
+char *name ;
+{
+  char  releasestr[8] ;
+  char  levelstr[8]   ;
+  char  timestr[32]   ;
+  char *namestr       ;
+  long int  timeval   ;
+
+  sprintf(releasestr, "%d", atoi( version_Id ) ) ;
+  sprintf(levelstr, "%d", atoi( version_Id + strlen(releasestr) + 1 ) ) ;
+
+  if ( ( namestr = strrchr( name, '/' ) ) == (char *)0 )  namestr = name ;
+  else namestr++ ;
+
+#if defined( PC ) || defined( THINK_C )
+  sprintf(headerstr, "\"AIM MRC-APU Release R%s.%s [%s]\"", releasestr, levelstr, namestr ) ;
+#else
+  timeval = time(0);
+  sprintf(timestr,"%s", ctime(&timeval) ) ;
+  timestr[strlen(timestr) - 1] = '\0';  /* remove newline */
+  sprintf(headerstr, "\"AIM MRC-APU Release R%s.%s [%s] %s\"", releasestr, levelstr, namestr, timestr ) ;
+#endif
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/image.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,1271 @@
+/*
+    SCCS VERSION 1.29 WITH 1.28 STRIPPED OUT.
+
+
+
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+*/
+
+/***************************************************************************
+*    image.c            Version with trigger at right end of sai.
+*    =======
+* Input data derived from a cochleagram is used to construct a stabilised
+* auditory image (sai) of size `chans' * `framewidth' points.
+*
+* Organisation of data.
+* Data is 2-dimensional: in time (rows) and frequency (columns).
+*
+* Input data is ordered by columns. The input array consists of blocks (columns)
+* of `chans' points, each column being one time sample of `chans' channels.
+* The zero'th point in each column is the lowest frequency channel.
+*
+* Output (sai) data is ordered by rows. The output array consists of blocks
+* (rows) of `framewidth' points.
+* The zero'th point in each row is the "oldest" time, as the time origin is
+* on the right edge of the sai.
+*
+* Each sai is called a `frame', and its dimensions are `chans' rows by
+* `framewidth' columns. In the code, the `framewidth' is often represented
+* as imagewidth/chans, where imagewidth is the total amount of data in an
+* sai frame, (ie. imagewidth=chans*framewidth).
+
+* This module has been modified to have 5 levels of strobing.  
+                                        A Jay Datta  6/03/95 
+***************************************************************************/
+
+#include <math.h>
+#include <string.h>
+
+#include "options.h"
+#include "stitch.h"
+#include "source.h"
+#include "model.h"
+#include "units.h"
+#include "image.h"
+#include "calc.h"
+
+#define MAX_BUFFER (1l<<15)
+
+#ifdef FLOAT
+#define INPUT_SCALE 0.25
+#define DECAY_SCALE 0.875
+#else
+#define INPUT_SHIFT 2
+#define DECAY_ROUND 7
+#endif
+#define DECAY_SHIFT 3
+
+#define MAXCHAN 1000
+
+#ifndef  lint
+static char *sccs_id = "@(#)image.c	1.27     J. Holdsworth, M. Allerhand (MRC-APU)  6/6/91" ;
+#endif
+
+#ifdef DSP32
+static int segsize = 16 ;
+#else
+static int segsize = 50 ;
+#endif
+
+typedef enum { False, True } Bool ;
+typedef struct Node{int index; short val; struct Node *next;} node;
+
+static void doColumn();
+static Pointer sai_callback();
+static Pointer summary_callback();
+static void save_callback();
+static void addIn();
+static void decayImage();
+
+void output_simple_strobe_info();
+void doList_strobe_info();
+void output_thresh_info();
+void decay_strobe_threshold();
+void print_trigger_debugging_info();
+
+void initlist();
+node *getnode();
+node *insertl();
+void inss();
+
+FILE *trigger_file;
+FILE *infotxt_file;
+FILE *thresho_file;
+
+int locmax_searchtime[MAXCHAN]; 
+int locmax_searchstart[MAXCHAN];
+int val[MAXCHAN]; 
+int ltime[MAXCHAN];
+int initial_strobe_candidate_time[MAXCHAN];
+int ttime[MAXCHAN];
+
+static node *start, *endl, *pp,  *qq;
+static char *exposwitch;
+
+#ifdef FLOAT
+  float *S;
+#else
+  short *S;
+#endif
+
+
+/***************************************************************************
+*   struct _sai_state:
+*       The source->info->state structure which is initialised by the
+*       routine Sai, and is then the state argument for the callback
+*       function: sai_callback.
+***************************************************************************/
+struct _sai_state {
+    struct _pullable_source parent ;
+    Source     source;
+    void       (*trigger)();     /* trigger algorithm (originally doColumn) */
+    unsigned   chans;            /* number of filter channels               */
+    unsigned   framestep;        /* sai display update period               */
+    DataType   *image;           /* sai array (DataType = short)            */
+    unsigned   imagewidth;       /* length of sai array (framewidth*chans)  */
+    unsigned   imagenwidth;      /* portion of sai array for transient info */
+    unsigned   decay_time;       /* a factor of sai decay time constant     */
+    unsigned   decay_count;
+    ScalarType *framedecay;      /* array of factors for cochleagram frame  */
+    int        *cps;             /* array of 1/centre-freq (in samples)     */
+    int        *isPulse;         /* array of bools, to see if data > thres  */
+
+    int        Stcrit;          /* int restriction */       
+    int        SusThresh;        /* Level 2 user settable thresh */
+    ScalarType triggerdecay;     /* prop/point decay for strobe threshold */
+    int        *trigtime;        /* time of  last trigger pulse  */
+    int        *trigheight;      /* height of last trigger pulse */
+    int        *isStrobe;        /* array of booleans, set when pulse peak found */
+    float      *thresh;          /* array of thresholds, one per channel */
+    float        *tlim;            /* linear decay value */
+    int         time;            /* keep track of sai   */
+    int        *previnput;       /* lock till new pulse found */
+    int        *def_strobe_candidate_time;
+    int        *def_strobe_height;
+    char       *switch_info;
+    int         tlim1;
+    int         stlag; /* strobe nwid  first attempt to decouple nwids */
+};
+
+/***************************************************************************
+*   Sai:
+*       Sai is called from SaiEntry (in module model.c).
+*       Routines in this module it uses are:
+*                doColumn,       (which uses:  addIn)
+*                sai_callback,   (which uses:  decayImage)
+*
+* SaiEntry (in model.c) is the entry-point function to the stabilised image
+* processing module. Its purpose is to prepare the arguments for Sai by
+* converting parameter-option strings to integers, and then to call Sai.
+*
+* Sai is called with the following arguments (in model.c):
+*    Sai( source, Frameheight(), segment, width,
+*        (int) Samples( decaystr )/Framestep(), (int) Freq( samplestr ),
+*        frequencies, Samples(ttstr)/Framestep(), Samples(cgmstr)/Framestep(),
+*        (int) Freq("250Hz"), (int) Freq("20Hz") ) ;
+*
+* The arguments are as follows:
+* (The option name refers to the description given by "help". The values etc
+* can be found in table.c as described in model.docs).
+*
+*  Argument     Option name    Default  Comment
+*  --------     -----------    -------  -------
+*  chans        (see below)             Number of filter channels
+*  framestep    segment_sai    16ms     SAI display update period
+*  framewidth   duration_sai   32ms     SAI duration (ms)
+*  decay        decayrate_sai  32ms     SAI decay time constant (SU/ms)  15ms NOW Default
+*  samplerate   samplerate     20000.   Input wave sample rate (Hz)
+*  cfs          (see below)             An array of filter centre frequencies
+*  cgmdecay     napdecay_sai   16ms     NAP (ie cochleagram) decay time constant
+*
+* Both "chans" and "cfs" are setup from the routine "updateFrequencies" in
+* model.c, because both arguments are derived from three basic parameters:
+*
+*  minstr      mincf_afb      220Hz    Minimum center frequency (Hz)
+*  maxstr      maxcf_afb      4400Hz   Maximum center frequency (Hz)
+*  denstr      dencf_afb      4.       Filter density (filters/critical band)
+*
+* The "chans" argument is calculated in the routine "NumberCenterFrequencies",
+* and the result is copied into the "frameheightstr" by a call to the routine
+* "setFrameheight".
+* The "cfs" argument is calculated in the routine "GenerateCenterFrequencies".
+* (Both CenterFrequency routines are in gamma_tone.c).
+*
+***************************************************************************/
+
+Source Sai(source, chans, framestep, pwidth, nwidth, decay, samplerate, cfs, ttdecay, cgmdecay, tlim1, tlim2, suslevel, susthresh, switchinfo, expoSwitch,stlag)
+Source source ;
+int    chans, framestep, pwidth, nwidth, decay ;
+int    samplerate;
+double *cfs ;
+double ttdecay, cgmdecay ; 
+int    tlim1, tlim2;
+int    suslevel;
+char   *susthresh;
+char   *switchinfo; 
+char   *expoSwitch;
+int stlag;
+{
+    
+    DeclareNew( struct _sai_state *, state ) ;
+    int i, chan, startup, segment, framewidth ;
+    double pts_per_ms, lin_napdec, lin_napfac ;                 /* roy 11-8-92 roy */
+    char *ThreshoFile, *InfotxtFile, *TriggerFile;
+
+    exposwitch=(char *)calloc(5, sizeof(char));
+    exposwitch=expoSwitch;
+
+    ThreshoFile = (char *)calloc(256, sizeof(char));
+    InfotxtFile = (char *)calloc(256, sizeof(char));
+    TriggerFile = (char *)calloc(256, sizeof(char));
+
+    state->switch_info = (char *)calloc(256,sizeof(char));
+    state->switch_info = switchinfo;
+    
+    if (!strcmp(susthresh, "on"))
+      state->SusThresh=0;
+    else if (!strcmp(susthresh, "off"))
+      state->SusThresh=1;
+    else
+      state->SusThresh=atoi(susthresh);
+
+     if (!strcmp(state->switch_info, "off"))
+         ;
+    else if (!strcmp(state->switch_info, "on"))
+        infotxt_file=stdout;
+    else{
+        strcpy(InfotxtFile, switchinfo);
+        strcat(InfotxtFile, ".info");
+        infotxt_file=fopen(InfotxtFile, "w");
+
+        strcpy(TriggerFile, switchinfo);
+        strcat(TriggerFile, ".trigger");
+        trigger_file=fopen(TriggerFile, "w");
+
+        strcpy(ThreshoFile, switchinfo);
+        strcat(ThreshoFile, ".thresh");
+        thresho_file=fopen(ThreshoFile, "w");
+      }
+
+    initlist(); 
+    state->tlim1=0;
+
+    framewidth = pwidth+nwidth;
+
+    pts_per_ms = (double)samplerate/1000 ;
+
+    state->stlag=stlag; /* NEW line 95April */
+    /* Initialise members of the sai state structure */
+    state->source = NewRetainingSource( source, sizeof ( DataType ) * framewidth * chans ) ;
+    state->chans  = chans ;
+    state->trigger = doColumn ;
+    state->framestep = framestep  * chans ;
+    state->imagewidth = framewidth * chans ;    /* size of sai buffer */
+    state->imagenwidth = nwidth * chans ; /* size of buffer for transient info */
+    state->decay_time  = decay * -log( 1. - 1. / ( 1 << DECAY_SHIFT ) ) ;
+    state->decay_count = state->decay_time ;
+
+    state->Stcrit   = suslevel;
+    if (stlag==0 && state->Stcrit==5) /* was nwid  NEW */
+    state->Stcrit = suslevel-1;
+ 
+    /* state->SusThresh = susthresh; */
+
+    if (!strcmp(exposwitch, "on")) fprintf(stderr, "Exponential trigger decay SWITCH is ON\n");
+/*    if (!strcmp(exposwitch, "off")) printf("SWITCH is OFF\n"); */
+
+    if (!strcmp(exposwitch, "on"))
+      state->triggerdecay = (double) 1-((ttdecay / pts_per_ms ) /100.0) ;
+    else 
+      state->triggerdecay = (double) (ttdecay /pts_per_ms) / 100.0 ;
+
+    if (!strcmp(switchinfo, "off"))
+       ;
+    else 
+      fprintf(infotxt_file, "\ntriggerdecay = %15e\n", state->triggerdecay);  
+
+    state->isStrobe   = NewZeroedArray( int,           state->chans, "image.c for Strobe"  ) ;
+    state->isPulse    = NewZeroedArray( int,           state->chans, "image.c for trigger pulse"  ) ;
+    state->trigtime   = NewZeroedArray( int,           state->chans, "image.c for trigger time" ) ;
+    state->trigheight = NewZeroedArray( int,           state->chans, "image.c for trigger height" ) ;
+    state->thresh     = NewZeroedArray( float,      state->chans, "image.c for thresh" ) ;
+    state->tlim       = NewZeroedArray( float,           state->chans, "image.c for decay"  ) ;
+    state->time       = 0;  /* Time initialized to Zero */
+    state->previnput  = NewZeroedArray( int,           state->chans, "image.c for pulse lock" ) ;
+
+ state->def_strobe_candidate_time      = NewZeroedArray( int,    state->chans, "image.c for prevtrig time" );
+ state->def_strobe_height    = NewZeroedArray( int,    state->chans, "image.c for prev trig" );
+
+    for (chan=0; chan < MAXCHAN; chan++)
+        locmax_searchtime[chan]=0; 
+    for (chan=0; chan < MAXCHAN; chan++)
+        locmax_searchstart[chan]=0;
+    for (chan=0; chan < MAXCHAN; chan++)
+        val[chan]=0;
+    for (chan=0; chan < MAXCHAN; chan++)
+        initial_strobe_candidate_time[chan]=0;
+    for (chan=0; chan < MAXCHAN; chan++)
+        ltime[chan]=0;
+    for (chan=0; chan < MAXCHAN; chan++)
+        ttime[chan]=0;
+
+#ifdef FLOAT
+  S=(float *)calloc(state->chans, sizeof(float));
+#else
+  S=(short *)calloc(state->chans, sizeof(short));
+#endif
+
+    /* Declare new arrays for members of state structure */
+
+    state->framedecay = NewArray(       ScalarType,      framewidth, "image.c for decay"   ) ;
+    state->image      = NewZeroedArray( DataType, state->imagewidth, "image.c for image"   ) ;
+    state->cps        = NewZeroedArray( int,           state->chans, "image.c for channel centre periods" ) ;
+
+    /* Initialise cochleagram frame decay factors */
+    if (cgmdecay > 0)    
+      {
+      /* 11111 roy 11-8-92  These mods change to a linear nap decay.         1111111 roy */
+      /* It requires pts_per_ms, lin_napdec and lin_napfac declared just after DeclareNew above */
+
+         lin_napdec = ((cgmdecay/100)/pts_per_ms)/pts_per_ms ; /* roy 19-8 roy */
+
+	 /* cgmdecay is div by pts_per_ms to get back to napdecay in the original units */
+	 /* When napdecay is interpreted as the % to decay per ms, and since we are  */
+	 /* operating in points, we need napdec/pts_per_ms, as the dec for each pt within the ms */
+	 /* The decay vector is set to scale the NAP by 1.0 at strobe point. So, in the sai, */
+	 /* it falls to the left AND RISES to the right of 0 ms. **** roy **** */
+
+         lin_napfac = 1.0 + nwidth*lin_napdec ;
+
+	 for (i=0 ; i < framewidth ; i++)
+	    {
+              if ( lin_napfac > 0 ) 
+                 state->framedecay[i] = SCALAR( lin_napfac ); 
+              else
+        	 state->framedecay[i] = SCALAR( 0 ); 
+              lin_napfac -= lin_napdec ; 
+	    }
+       }
+    else                        /* disable decay factor on zero argument */
+	for (i=0 ; i < framewidth ; i++)
+	    state->framedecay[i] = SCALAR( 1.0 ) ;
+
+    /* Initialise centre-period for each channel */
+    for (i=0 ; i < state->chans ; i++)
+	state->cps[i] = samplerate / cfs[i];
+
+#if defined( PC ) || defined( THINK_C )
+    if( (long) ( MAX_BUFFER - (long) state->imagewidth * sizeof ( DataType ) ) < (long) ( state->chans * sizeof ( DataType ) ) )
+	stitch_error( "Sorry, image larger than maximum buffer size\n" ) ;
+#endif
+
+/* for (i=0; i<state->imagewidth;i++)
+ fprintf(stderr, "Image Buffer is %f, count = %d\n", *(state->image+i), (i+1)); */
+
+
+
+    return ( SetPullableSource( state, sai_callback, "image.c stabilised image" ) ) ;
+}
+
+/****************************************************************************
+*    sai_callback
+*        The callback function at source->info->callback in the source
+*        returned by Sai.
+* A "frame" is a window over the cochleagram, of size chans * points.
+* A "segment" is a stretch of the cochleagram which is segsize (ie 50) time
+*  samples long, ie segsize columns of the cochleagram.
+*
+* This callback routine is executed once for each sai frame which is plotted.
+* "*bytes" is the number of bytes in the sai, ie:
+*               *bytes = state->imagewidth * sizeof(DataType)
+****************************************************************************/
+static Pointer sai_callback( state, bytes )
+struct _sai_state *state ;
+ByteCount *bytes ;
+{
+    register long col, point ;
+    register long points = state->framestep;  /* total num points under frame   */
+#if defined( PC )
+    int segment = ( MAX_BUFFER - state->imagewidth * sizeof ( DataType ) ) / state->chans / sizeof ( DataType ) * state->chans ;
+#else
+    int segment = segsize * state->chans ;
+#endif
+    register DataType *input ;              /* cochleagram (input) data array */
+    static   int  first=1;
+    static   int  test=0;
+             int chan;
+             int i;
+/* #if defined( PC )
+    test=1;
+#else
+    if (state->SusThresh == 0)
+       segment= 30 * state->chans ;
+#endif  */
+
+/* test++; */
+
+
+    /* If size argument is zero, then by convention free space and return null */
+    if( *bytes == 0 ) {
+	Pull( state->source, 0 ) ;
+	Delete( state->image   ) ;
+	return ( DeletePullableSource( state ) ) ;
+    }
+
+    /* Initially pull enough data to buffer transient info ahead of the trigger */
+    /* Note, the pull operation is not valid when the size arg is zero.  */
+    /* The result would be a segmentation fault on the next pull, below. */
+
+if (state->Stcrit==0 || state->Stcrit==1 || state->Stcrit==2 || state->Stcrit==3)
+    if (first) {
+	if (state->imagenwidth > 0)
+	    input = PullItems(state->source, state->imagenwidth, DataType); 
+	first = 0;
+    } 
+
+
+    /* Search frame in segment blocks for trigger-points */
+    for( point=0 ; point < points ; point += segment ) {
+	if( segment > points - point )  /* Finish at end of frame */
+	    segment = points - point ;
+	/* Get one segment of the input data */
+	/* Pull 50 columns of data from the source, in buffer *input. */
+	/* Keep one sai of data, from last pull, in buffer behind *input */
+	input = PullItems(state->source, segment, DataType);
+        
+	for( col=0 ; col < segment ; col += state->chans ) {
+	    /* Retard the "current" data point by transient buffer width */
+	    /* (This retards the trigger by the transient time, about 5ms) */
+            if (state->Stcrit==0 || state->Stcrit==1 || state->Stcrit==2 || state->Stcrit==3)
+               state->trigger(input-state->imagenwidth, state) ;
+            else{
+	        state->trigger( input, state) ;     /* -state->imagenwidth, state ) ; */
+                /*fprintf(stderr, " %d ", points)  ; */ }
+	    input += state->chans ;     /* next column */
+	    /* decay image  periodically, once every `decay_time' columns */
+            /* Lines moved down */  
+	    if( --state->decay_count <= 0 ) {
+		decayImage( state ) ;
+		state->decay_count = state->decay_time ;
+	      }
+	 } /* for each col */
+      }    /* for each seg */
+
+    /* whatever the number of bytes requested, the image is always this size */
+     *bytes = state->imagewidth * sizeof ( *state->image ) ;
+
+/* if (state->Stcrit==1 && state->SusThresh==0){
+                if (test%5==0)
+                   decayImage( state );
+                test++;}
+            else if (state->Stcrit==1 && state->SusThresh>0){  changed 2 to 3 
+                 if (test%10==0)
+                    decayImage( state );
+                 test++;} 
+            else{ */
+
+    return ( (Pointer) state->image ) ; 
+ }
+
+/****************************************************************************
+*   decayImage
+* Periodically attenuate image to give computationally efficient image decay.
+* Attenuate all points in the sai by a constant factor.
+****************************************************************************/
+static void decayImage( state )
+struct _sai_state *state ;
+{
+    register DataType *image_ptr, *image_end ;
+#ifdef FLOAT
+    register FLOAT image_decay = DECAY_SCALE ;
+#endif
+
+    image_end = state->image + state->imagewidth ;  /* end of sai array */
+#ifdef FLOAT
+    for( image_ptr=state->image ; image_ptr < image_end ;   )
+	*image_ptr++ *= image_decay ;
+#else
+    for( image_ptr=state->image ; image_ptr < image_end ; image_ptr++ )
+	*image_ptr   -= *image_ptr + DECAY_ROUND >> DECAY_SHIFT ;
+#endif
+    return ;
+}
+
+/****************************************************************************
+*   doColumn
+*       Trigger algorithm for Sai.
+*       Installed as source->info->state->trigger.
+*
+****************************************************************************/
+static void doColumn( input, state )
+DataType *input ;
+struct _sai_state *state ;
+{
+  
+  register int chan ;
+  float strobelag;
+  int s_lag;
+
+  
+  short *STI;
+  static int   check=0;
+  int storev;
+  char buf[2];
+  short stipts=-2000;
+  short zeroval=0;
+
+  STI=(short *)calloc(state->chans, sizeof(short));
+
+  strobelag = (double) (state->time)-(state->stlag);
+  
+  s_lag=(state->time)-(state->stlag);
+    
+  /* For each channel up column, add a row of data to sai if the      */
+  /* current point is non-zero. Add the row from the current point    */
+  /* plus state->imagenwidth, to display the transient (nwidth) info. */
+  
+
+/* 000000000000000000000000 stcrit 0000000000000000000000000000000000 */
+/* Add on every point : Low Pass Filter */
+
+if (state->Stcrit==0)
+  {          
+    for( chan=0 ; chan < state->chans ; chan++ )
+      {
+	addIn(input+(state->imagenwidth), chan, state); 
+        output_simple_strobe_info(state, stipts);
+      }
+  } /* if (state->Stcrit==0)  */ 
+
+
+/* 111111111111111111111111 stcrit 1111111111111111111111111111111111 */
+/* Add on every point greater than "stthresh_ai" (default 0) */
+       
+if (state->Stcrit==1)
+  {                          
+    for( chan=0 ; chan < state->chans ; chan++ )
+      {   
+	if (input[chan] > state->SusThresh )
+	  {   
+	    addIn(input+(state->imagenwidth), chan, state);
+	    output_simple_strobe_info(state, stipts);
+	  }
+	else if (input[chan] <=state->SusThresh)
+	  output_simple_strobe_info(state, zeroval);
+      }
+  } /* if (state->Stcrit==1)  */
+ 
+
+/* 222222222222222222222222 stcrit 2222222222222222222222222222222222 */
+/* Add on every Nap pulse peak  */ 
+
+if (state->Stcrit==2)
+  {
+    for( chan=0 ; chan < state->chans ; chan++ )
+      {
+	if (state->isStrobe[chan])  /* Check to see if it is time to addIn */ 
+	  {
+	    addIn(input+((state->imagenwidth)-2*(state->chans)), chan, state); 
+	    state->isStrobe[chan]=0;    /* Reset strobe flag */
+            doList_strobe_info(state,  chan);
+	  }
+	
+/* Find a pulse peak routine */
+
+	if (!state->isPulse[chan])   /* Not in pulse, looking for pulse */
+	  {
+	    state->thresh[chan]=input[chan];
+	    if (input[chan] > 0 /*state->thresh[chan] */ ) /* Start of a Nap pulse */
+	      state->isPulse[chan] =1;  /* set in pulse flag */ 
+	  }
+	else                        /* In pulse, looking for peak */ 
+	  {
+	    if (input[chan] < state->thresh[chan]) /* peak found */
+	      {
+		state->isPulse[chan]=0;  
+		state->isStrobe[chan]=1; /* set strobe pending flag */
+	      }
+	    else
+	      state->thresh[chan]=input[chan];
+	  }
+	output_thresh_info(state, chan);
+      }
+  }        /* if (state->stcrit==2) */
+
+
+
+/* 333333333333333333333333 stcrit 3333333333333333333333333333333333 */
+/* Add on pulse peaks that exceed strobe threshold  (temporal shadow ) */
+/* Primitive Local Max algorithm */
+
+if (state->Stcrit==3)  
+  {
+    for( chan=0 ; chan < state->chans ; chan++ )
+      {
+	if (state->isStrobe[chan])  /* Check to see if it is time to addIn  */
+	  {
+	    addIn(input+((state->imagenwidth)-2*(state->chans)), chan, state); 
+	    state->isStrobe[chan]   = 0;  /* Reset strobe flag */ 
+            doList_strobe_info(state, chan);
+	  }
+
+/* Find a pulse peak routine */
+
+	if (!state->isPulse[chan])    /* Not in Pulse, looking for Pulse */
+	  {
+	    if (input[chan] > state->thresh[chan] && input[chan] > state->previnput[chan])     
+	      {                             /* Previnput check ensures threshold decay 
+                                               does not cut into pulse */     
+
+		state->isPulse[chan]  = 1;            /* set flag: in pulse */
+		state->thresh[chan]   = input[chan];  /* start search for peak */
+	      }
+            else {
+	      decay_strobe_threshold(state, chan);
+	      if (input[chan]==0)    /* in the zeroes between nap pulses */
+		state->previnput[chan] = 0;  /* Set it to Zero previnput */  
+	    }
+	  }
+
+	if (state->isPulse[chan])  /* Else in ongoing pulse looking for peak */
+	  {
+	    if (input[chan] <= state->thresh[chan] && input[chan] <= state->previnput[chan]) 
+                                                       /*  pulse peak found */
+	      {	      
+		state->isPulse[chan]  = 0;       /* clear flag: not in pulse */
+		state->isStrobe[chan] = 1;       /* set Strobe pending flag  */
+                if (!strcmp(exposwitch, "off")) 
+		  state->tlim[chan]=state->triggerdecay * state->thresh[chan];
+                state->trigtime[chan]=(state->time)-1;
+                /* state->previnput[chan]=input[cha */
+	      }
+	    else		    /* still in pulse, so continue search for peak */
+	        state->thresh[chan] = input[chan]; 
+
+	  }        /* if in Pulse */     
+	state->previnput[chan]=input[chan];
+	output_thresh_info(state, chan);
+      }                /* for all chans... */
+  }                 /* if (state->Stcrit==3) */
+
+
+
+/* 444444444444444444444444 stcrit 4444444444444444444444444444444444 */
+/* Add on pulse peaks that exceed strobe threshold and which are not succeeded by 
+   a larger pulse in nwid ms.  (Better Local Max mechanism) */
+
+if (state->Stcrit==4) 
+  {
+    for( chan=0 ; chan < state->chans ; chan++ )
+      {
+	if (state->isStrobe[chan])  /* Check to see if it is time to addIn  */
+	  {
+	    if ( strobelag-1 >= state->trigtime[chan])  
+                 /* initiates strobe after nwid ms */
+	      {
+		addIn(input-(state->chans), chan, state);
+                doList_strobe_info(state, chan);
+		state->isStrobe[chan]   = 0;    /* Reset strobe flag */
+		state->trigheight[chan] = 0;    /* Reset local max value */
+		
+	      }                   
+	  }
+
+/* Find a pulse peak routine */
+
+	if (!state->isPulse[chan])    /* Not in Pulse, looking for pulse */
+	  {
+	    if (input[chan] > state->thresh[chan] && input[chan] > state->previnput[chan])   
+	      {                            /* Previnput check ensures threshold
+                                              decay does not cut into pulse    */
+
+		state->isPulse[chan]  = 1;            /* set flag: in pulse */
+		state->thresh[chan]   = input[chan];  /* start search for peak */
+          /* state->previnput[chan]= 1;     in pulse till the next zero value */
+	      }
+	    else 
+	      {
+		decay_strobe_threshold(state, chan);
+                if (input[chan]==0) /* in the zeroes between nap pulses */ 
+		  state->previnput[chan] = 0;  /* Free previnput */
+ 	      }                             
+	  }
+
+	if (state->isPulse[chan])  /* Else in ongoing pulse, looking for peak */
+	  {
+	    if (input[chan] <= state->thresh[chan] && input[chan] <= state->previnput[chan])    
+                                                      /* pulse peak found */
+	      {
+		state->isPulse[chan]  = 0;       /* clear flag: not in pulse */
+		state->isStrobe[chan] = 1;       /* set Strobe pending flag  */
+		
+		if ( state->thresh[chan] > state->trigheight[chan] ) 
+                            /* Check for LOCAL MAX */
+		  {
+		    state->trigheight[chan] = state->thresh[chan];
+		    state->trigtime[chan] = (state->time)-1;  /* Set strobe time */
+                    if (!strcmp(exposwitch, "off"))
+		      state->tlim[chan]=state->triggerdecay * state->trigheight[chan];
+		  }
+	      }
+	    else	     /* still in pulse, so continue search for peak */
+	      state->thresh[chan] = input[chan]; 
+	  }   /* if in Pulse */     
+        state->previnput[chan]=input[chan];
+	output_thresh_info(state, chan);	
+  }             /* for all chans... */
+}            /* if (state->Stcrit==4) */
+
+
+
+/* 555555555555555555555555 stcrit 5555555555555555555555555555555555 */
+/* Add on pulse peaks that exceed storbe threshold and which are not succeeded by
+   a larger pulse in nwid ms, provided total lag is < 2*nwid ms  
+   Local Max mechanism with a timeout                            */
+
+if (state->Stcrit==5) 
+ { 
+  for (chan = 0;  chan < state->chans;  chan++) 
+    {
+     if(state->isStrobe[chan])   /* Check to see if it is time to addIn */
+       {    /* check for waiting till the first local max found */
+	 if (strobelag-1 >= state->def_strobe_candidate_time[chan])
+	   /* initiate strobe after nwid ms  */
+	   {  
+	     /* print_trigger_debugging_info(state, chan, s_lag, 1); */
+	     addIn(input-state->chans, chan, state);
+	     doList_strobe_info(state, chan);	       
+	     
+	     state->def_strobe_candidate_time[chan] = 0; /* Reset strobe time */
+	     state->def_strobe_height[chan] = 0; /* Reset local max value */
+	     state->trigheight[chan]=0; 
+	     state->isStrobe[chan]=0;       /* Reset strobe flag */
+	     
+	   }
+       }
+     
+/* Find a pulse peak routine */
+
+    if (!state->isPulse[chan])  /* Not in pulse, looking for pulse */
+      { 
+	if (input[chan] > state->thresh[chan] && input[chan] > state->previnput[chan]) 
+	  {                            /* Previnput check ensures threshold
+					  decay does not cut into pulse */
+	    
+	    state->isPulse[chan]   = 1;           /* set flag: in pulse */
+	    state->thresh[chan]    = input[chan]; /* start search for peak */
+       /* state->previnput[chan] = 1;     in pulse till the next zero value */
+	  }
+        else
+          {
+	    decay_strobe_threshold(state, chan);
+	    if (input[chan]==0)  /* in the zeroes between nap pulses */
+	      state->previnput[chan]=0; /* Free previnput */
+	  }
+
+      }
+
+    if (state->isPulse[chan]) /* Else in ongoing pulse, looking for peak */ 
+     {  
+       if (input[chan] <= state->thresh[chan] && input[chan] <= state->previnput[chan])  
+	 /* Pulse Peak Found */
+	 {
+	   state->isPulse[chan]=0;  /* clear flag: not in pulse */
+	   
+	   if (locmax_searchstart[chan]==0  )
+           /* && state->time>=((ttime[chan]-initial_strobe_candidate_time[chan])+ltime[chan]))  AJD 1-2-96 */
+	     {                              /* start local max time (for timeout) 
+					       and shift search window */
+	       locmax_searchtime[chan]=1;   /* local max time started */
+	       locmax_searchstart[chan]=1;  /* local max flag set */
+	       print_trigger_debugging_info(state, chan, s_lag, 2);
+	       initial_strobe_candidate_time[chan]=(state->time)-1;   /* local max start time noted */
+	       
+	     }
+	   
+	   /* if (locmax_searchstart[chan]==1) */   /* 8rd March, 1995  AJayDatta */
+	   if (state->thresh[chan] > state->trigheight[chan])
+	     /* Check for LOCAL MAX */
+	     {
+	       state->trigheight[chan]=state->thresh[chan];
+	       state->trigtime[chan]=(state->time)-1; /* Set strobe time */
+	       if (!strcmp(exposwitch, "off"))
+		 state->tlim[chan]=state->triggerdecay * state->trigheight[chan];
+	       if (locmax_searchstart[chan]==1)
+		 print_trigger_debugging_info(state, chan, s_lag, 3);	  
+	     }       /* if greater than thresh */    
+	    
+
+    /* Reached end of time-out period  (While in the peak finding stage !)  
+       End of the timeout period can occur at two stages of the algorithm,
+       at a Nap pulse peak or at any point of the pulse train.            */ 
+        
+ 	  if (locmax_searchtime[chan]==(state->stlag)) /* imagenwidth/state->chans)) */
+	    {
+	      print_trigger_debugging_info(state, chan, s_lag, 4);
+
+	      state->def_strobe_candidate_time[chan]=state->trigtime[chan];
+	      state->def_strobe_height[chan]=state->trigheight[chan];
+	      locmax_searchtime[chan]=0;
+	      locmax_searchstart[chan]=0; 
+	      state->trigheight[chan]=0; 
+	      state->trigtime[chan]=0;   
+	      state->isStrobe[chan]=1;  /* set Strobe pending flag */
+	      ltime[chan]=state->time;  /* End of search time */
+	      ttime[chan]=state->def_strobe_candidate_time[chan]; /* Local Max time */ 
+	    }
+	  /* reset search period to zero */
+	  /* as y ms search period ends, update the info for strobe and 
+	     clear current_ values for the next y ms */
+	}   /* Pulse Peak Loop  */ 
+      else
+	state->thresh[chan]=input[chan];
+    } /* if (state->isPulse..) */
+    
+    if (locmax_searchtime[chan] == (state->stlag)) /* imagenwidth/state->chans)) */ 
+    /* && state->def_strobe_candidate_time[chan]==0) */
+      {                              /* start local max time (for timeout) */  
+	print_trigger_debugging_info(state, chan, s_lag, 5);
+
+	state->def_strobe_candidate_time[chan]=state->trigtime[chan];
+	state->def_strobe_height[chan]=state->trigheight[chan];
+	locmax_searchtime[chan]=0;
+	locmax_searchstart[chan]=0;
+        state->trigheight[chan]=0; 
+        state->trigtime[chan]=0;   
+	state->isStrobe[chan]=1;  /* set Strobe pending flag */
+	ltime[chan]=state->time;
+	ttime[chan]=state->def_strobe_candidate_time[chan];
+      }
+    /* reset search period to zero */
+    /* as y ms search period ends, update the info for strobe and 
+       clear current_ values for the next y ms */
+    
+ 
+    if (locmax_searchstart[chan]==1)
+      (locmax_searchtime[chan])++;
+  state->previnput[chan]=input[chan];
+  output_thresh_info(state, chan);
+
+  } /* for all chans */
+} /* if (state->Stcrit== 5) */
+
+  
+  qq=insertl(state->time); /* insert time to list */ 
+  (state->time)++;  
+  return;
+  
+}  /* doColumn */ 
+
+
+/****************************************************************************
+*  addIn
+*    add row cochleagram into stabilised image
+****************************************************************************/
+static void addIn( input, chan, state )
+     DataType *input ;
+     int chan ;
+     struct _sai_state *state ;
+{
+  register DataType *channel_ptr, *image_ptr, *end;
+#ifdef FLOAT
+  register FLOAT input_scale = INPUT_SCALE ;
+#endif
+  register ScalarType *decayfactor = state->framedecay;
+  
+  /* Initialize channel_ptr to the input data to be added in.  */
+  /* `input' points to a particular column in the cochleagram, */
+  /* and `chan' indexes a particular channel in this column.   */
+  channel_ptr = input + chan ;
+  end = channel_ptr - state->imagewidth ;
+  
+  /* Initialize image_ptr to end of sai row corresponding to `chan'.*/
+  /* `state->image' points to the start of the sai,                 */
+  /* so increment pointer by chan*framewidth to get to row `chan'.  */
+  /* To get to end of row, increment by ((chan+1)*framewidth)-1.    */
+  /* But  framewidth = state->imagewidth / state->chans, and hence: */
+  /* Added fix; as new spiral.c accepts nwid  AJD 17-3-95 */
+  if (state->Stcrit==4 && state->stlag==0)
+  image_ptr = (state->image + state->imagewidth / state->chans * (chan+1));
+                         /* 13-3-95 removed -1; ajd */
+  else
+  image_ptr = (state->image + state->imagewidth / state->chans * (chan+1))-1; 
+  
+  /* Decrement channel_ptr by columns, from the initial column,    */
+  /* until one complete sai row has been added into, which is when */
+  /* channel_ptr has decreased by a whole imagewidth.              */
+  while( channel_ptr > end ) {
+#ifdef FLOAT
+    *image_ptr +=        ( ( *channel_ptr *  input_scale ) * (*decayfactor++) ) ;
+#else
+    *image_ptr += DESCALE( ( *channel_ptr >> INPUT_SHIFT ) * (*decayfactor++) ) ;
+#endif
+    /* if (state->chans <= 40) */
+    if (*image_ptr > 32767.0) 
+      *image_ptr = 32767.0;    /* 32767 */  
+    
+    image_ptr--; 
+    
+    channel_ptr -= state->chans ;   /* next (ie previous) input time point */
+  }
+  
+  return ;
+}
+
+
+/***************************************************************************
+ *        Summary is not called in this module.
+ *        (see SummaryEntry in model.c, which is the entry point for gensas).
+ *        Summary computes a row summary spectrogram and is called during the
+ *        program "gensas".
+ 
+ *        Routines in this module it uses are:
+ *                summary_callback
+ ****************************************************************************/
+
+struct  _summary_state {
+  struct _fillable_source parent ;
+  Source source;
+  int    framewidth;          /* number of time-points or cols in an sai */
+  int    frameheight;         /* number of channels or rows in an sai */
+  double scale;
+  int   *llim;  /* integration limits (lower & upper) for sai summary data */
+  int   *ulim;
+};
+
+
+Source Summary( source, frameheight, scale, cfs, samplerate, llimstr, ulimstr)
+Source  source ;
+int     frameheight ;
+double  scale ;
+double *cfs, samplerate ;       /* array of channel centre frequencies */
+char   *llimstr, *ulimstr;      /* lower and upper limit strings */
+{
+    int    i, framewidth, max_ulim=0, min_llim=99999999;
+
+    DeclareNew( struct _summary_state *, state ) ;
+
+    /* Allocate new arrays for integration limits */
+    state->llim = NewArray(int, frameheight, "image.c for lower limit array" );
+    state->ulim = NewArray(int, frameheight, "image.c for upper limit array" );
+
+    for (i=0 ; i<frameheight ; i++) {
+
+	/* Convert strings to sample points, allowing for cycles units */
+	state->llim[i] = Cycles( llimstr, cfs[i], Samplerate() );
+	state->ulim[i] = Cycles( ulimstr, cfs[i], Samplerate() );
+
+	/* Check that llim < ulim, and quit if not so */
+	if (state->llim[i] >= state->ulim[i])
+	    stitch_error("Warning: gensas integration limits badly ordered\n");
+
+	/* Find limits on required framewidth */
+	if (state->ulim[i] > max_ulim)
+	    max_ulim = state->ulim[i];
+	if (state->llim[i] < min_llim)
+	    min_llim = state->llim[i];
+    }
+
+    if (min_llim > 0) min_llim = 0;
+    framewidth = max_ulim - min_llim;
+
+    /* Adjust the integration limits for an sai with triggering on the      */
+    /* right. (The parameters llim <= ulim, but the resulting sai indices   */
+    /* state->llim[i] > state->ulim[i]).                                    */
+    /* This is done by subtracting from (framewidth-1), where framewidth is */
+    /* the maximum required number of points, (ie ulim in points).          */
+
+    for (i=0 ; i<frameheight ; i++) {
+	state->llim[i] = framewidth - state->llim[i] ;
+	state->ulim[i] = framewidth - state->ulim[i] ;
+    }
+
+    framewidth++;   /* extra point as array starts from zeroth location */
+
+    /* a blockings requests up into requests of the size specifed */
+    state->source      = NewBlockingSource( source, sizeof ( DataType ) * framewidth * frameheight ) ;
+    state->framewidth  = framewidth ;
+    state->frameheight = frameheight ;
+    state->scale       = scale ;
+
+    return ( SetFillableSource( state, summary_callback, "image.c summarising sai" ) ) ;
+}
+
+/*********************** Routines supporting Summary ***********************/
+
+static Pointer summary_callback( state, bytes, buffer )
+struct _summary_state *state ;
+ByteCount *bytes ;
+DataType *buffer ;
+{
+    register int last = *bytes == 0 ;
+    register int i, j, ulim, llim, point, points=ToPoints(DataType,*bytes) ;
+    register DataType *sairow;
+#ifdef FLOAT
+    register DataType sum ;
+#else
+    register long sum ;
+#endif
+
+    /* Pull an sai frame */
+
+    for( point=0 ; point < points ; )
+	/* For each channel (row) in the sai, sum the row between the given limits */
+	for(i=0 ; i<state->frameheight ; i++) {
+
+	    sairow = PullItems(state->source,state->framewidth,DataType);
+
+	    ulim = state->ulim[i];
+	    llim = state->llim[i];
+	    sum = 0;
+	    for (j=ulim ; j<=llim ; j++)
+		sum += sairow[j];
+
+	    /* store the row-sum, scaled and normalized for the range of the sum */
+	    buffer[point++] = sum*state->scale / (llim-ulim);
+	}
+
+    if( !last )
+	return ( (Pointer) buffer ) ;
+    else {
+	Delete( state->llim ) ;
+	Delete( state->ulim ) ;
+
+	return ( DeleteFillableSource( state ) ) ;
+    }
+}
+
+/********************************************************************************/
+/*                                                                              */
+/* initlist initialises the linked list pointer before the other list functions */
+/* call the list.                                                               */
+/*                                                                              */
+/********************************************************************************/
+void initlist()
+{ 
+  static int status=0;
+  if (status==0)
+    start = endl = pp = qq = (node *)malloc(sizeof(node));
+  status=1;
+}
+
+/********************************************************************************/
+/*                                                                              */
+/* Function getnode allocates storage for a link list node and returns a        */
+/* pointer to that node                                                         */
+/*                                                                              */
+/********************************************************************************/
+node *getnode()
+{
+  node *q;
+  q=(node *)malloc(sizeof(node));
+  if (q==NULL) exit(66);
+  return q;
+}
+
+/********************************************************************************/
+/*                                                                              */
+/* The function insertl inserts the value x at the end of the linked list and   */
+/* moves the end point by another node                                          */
+/*                                                                              */
+/********************************************************************************/
+node *insertl(x)
+int x;
+{
+  node *q=endl; 
+  endl=getnode();
+  q->next=endl;
+  q->index=x;
+  q->val=0;
+  /* fprintf(testfile, "insertl: index is %d, val is %d\n", q->index, q->val); */
+  return q;
+}
+
+/********************************************************************************/
+/*                                                                              */
+/* The function inss searches the list from the start, stops 3 nodes before the */
+/* value x, assigns the value -2000 to the three nodes till the (x+1)th node.   */
+/*                                                                              */
+/********************************************************************************/
+void inss(x)
+int x;
+{
+  node *q=start;
+  int   y=x-3;
+  int   z=x;
+  while (q!=endl)
+    {
+      if (q->index == y)
+	do
+	  {
+	    q->val=-2000;
+	    q=q->next;
+            /* fprintf(stderr, "Inss(x) index=%d\n",q->index); */
+	  } while (q->index < z);
+      q=q->next;
+    }
+}
+
+
+/********************************************************************************/
+/*                                                                              */
+/* output_simple_strobe_info routine creates a file pointed by trigger file     */
+/* which writes the points in the Nap pulse which initiates strobing            */
+/*                                                                              */
+/********************************************************************************/
+void output_simple_strobe_info(state, value)
+struct _sai_state *state;
+short value;
+{
+
+if (!(!strcmp(state->switch_info, "off") || !strcmp(state->switch_info, "on"))) 
+     fwrite(&(value), sizeof(short), 1 , trigger_file);
+}
+
+/********************************************************************************/
+/*                                                                              */
+/* doList_strobe_info creates a file (pointed by "trigger_file") which writes   */
+/* in binary shorts the points in the Nap pulse which initiates a strobe        */
+/* It uses a linked list data structure to keep track of the actual time which  */
+/* causes a strobe, rather than the time when the strobing event occurs.        */
+/* At stcrit 4 or 5, strobing occurs nwid ms after a nap pulse peak has been    */
+/* located.                                                                     */ 
+/*                                                                              */
+/********************************************************************************/
+void doList_strobe_info(state, chan)
+struct _sai_state *state;
+int chan;
+{
+  int storev;
+	    
+  if (state->Stcrit==2)
+    storev=(state->time)-2;
+  else if (state->Stcrit==5)
+    storev=state->def_strobe_candidate_time[chan];
+ /*   fprintf(stderr, "Storev value of doList is = %d\n", storev);} */
+  else
+    storev=state->trigtime[chan];
+
+  inss(storev);
+ 
+  while (pp->index<=storev)  /* (pp!=qq) */
+    {
+      if (!(!strcmp(state->switch_info, "off") || !strcmp(state->switch_info, "on"))) 
+	fwrite(&(pp->val), sizeof(short), 1, trigger_file);
+        /* fprintf(testfile, "doList: index is %d, val is %d\n", pp->index, pp->val); */
+      pp=pp->next;
+    }
+  /* pp=qq; */
+}
+
+/********************************************************************************/
+/*                                                                              */
+/* output_thresh_info writes threshold values (in binary shorts or floats) to   */
+/* the file opened by the file pointer "thresho_file"                           */
+/*                                                                              */
+/********************************************************************************/
+void output_thresh_info(state, chan)
+struct _sai_state *state;
+int chan;
+{
+  S[chan]=state->thresh[chan];
+
+if (!(!strcmp(state->switch_info, "off") || !strcmp(state->switch_info, "on")))
+#ifdef FLOAT
+	fwrite((S+chan), sizeof(float), 1, thresho_file); 
+#else
+	fwrite((S+chan), sizeof(short), 1, thresho_file);
+#endif 
+
+}
+
+/********************************************************************************/
+/*                                                                              */
+/* decay_strobe_threshold decays the strobe threshold at every clock            */
+/* tick either linearly or exponentially                                        */
+/*                                                                              */
+/********************************************************************************/
+void decay_strobe_threshold(state, chan)
+struct _sai_state *state;
+int chan;
+{
+
+  if (!strcmp(exposwitch, "on"))
+    state->thresh[chan] *= state->triggerdecay;
+  else
+    {
+      state->thresh[chan]  -= state->tlim[chan];
+      if (state->thresh[chan] < 0) 
+	state->thresh[chan]=0;
+    }
+}
+
+/********************************************************************************/
+/*                                                                              */
+/* This routine prints debugging information of the local max search            */
+/* with timeout (i.e. stcrit_ai=5)                                              */
+/*                                                                              */
+/********************************************************************************/
+void print_trigger_debugging_info(state, chan, strobe_lag, stage)
+struct _sai_state *state;
+int chan;
+int strobe_lag;
+int stage;
+{
+  if (stage==1)
+    {
+      if (strobe_lag > state->def_strobe_candidate_time[chan])
+	val[chan]=strobe_lag-state->def_strobe_candidate_time[chan];
+      if (strobe_lag == state->def_strobe_candidate_time[chan])
+	val[chan]=0; 
+      
+      if (!strcmp(state->switch_info,"off"));
+      else
+	fprintf(infotxt_file, "Chan %d: :: Actual time of trigger: s_lag=%d, trigtime=%d\n", chan, strobe_lag, state->def_strobe_candidate_time[chan]);
+    }
+
+/*   fprintf(infotxt_file, "Chan %d: Actual time of trigger: s_lag=%d, trigtime=%d, shift=%d\n", chan, strobe_lag, state->def_strobe_candidate_time[chan], val[chan]*state->chans); */
+       
+  
+  if (stage==2)
+    {
+      if (!strcmp(state->switch_info,"off"));
+      else
+	fprintf(infotxt_file, "Chan %d: Loc Max Start Time = %d, trigcurrent %d, Threshold=%f, shift=%d\n", chan, state->time, state->trigheight[chan], state->thresh[chan], (ttime[chan]-initial_strobe_candidate_time[chan]));
+    }
+
+  if (stage==3)
+    {
+      if (!strcmp(state->switch_info,"off"));
+      else
+	fprintf(infotxt_file, "Chan %d:    Loc Max is %d Time is %d\n", chan, state->trigheight[chan], state->trigtime[chan] );
+    }
+
+  if (stage==4)
+    {
+      if (!strcmp(state->switch_info,"off"));
+      else
+	fprintf(infotxt_file, "Chan %d: At the End of Search (At peak), trigtime = %d time = %d height = %d\n", chan, state->trigtime[chan], state->time, state->trigheight[chan]);
+    }
+  if (stage==5)
+    {
+      if (!strcmp(state->switch_info,"off"));
+      else
+	fprintf(infotxt_file, "Chan %d: At the End of Search, trigtime = %d time = %d height = %d\n", chan, state->trigtime[chan], state->time, state->trigheight[chan]);  
+    }
+  
+  
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/image.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,9 @@
+/*
+    image.h
+    =======
+
+    Entry points for stabilised image module
+
+*/
+
+extern Source Sai(), Summary(), Save(), Gpr() ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/integrate.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,190 @@
+/*
+    integrate.c
+    ===========
+
+*/
+
+#include <math.h>
+
+#include "stitch.h"
+#include "source.h"
+#include "calc.h"
+
+#include "integrate.h"
+
+
+struct _integral_state { ScalarType state, upward, downward, igain ; } ;
+
+static int new_integral_callback( state, buffer, end, input, skip )
+struct _integral_state *state ;
+DataType *buffer, *end, *input ;
+int skip ;
+{
+    register struct _integral_state *sptr = state ;
+    register DataType *iptr = input ;
+    register DataType *optr = buffer ;
+    register DataType *eptr = end ;
+
+    while( optr < eptr ) {
+
+	    /* the more accurate later version */
+
+	    *optr = DESCALE( sptr->state ) ;
+
+	    sptr->state += sptr->upward * DESCALE( *iptr * sptr->igain - sptr->state ) ;
+
+	    iptr += skip ;
+	    optr += skip ;
+    }
+
+    return ( sizeof ( DataType ) ) ;
+}
+
+static int old_integral_callback( state, buffer, end, input, skip )
+struct _integral_state *state ;
+DataType *buffer, *end, *input ;
+int skip ;
+{
+    register struct _integral_state *sptr = state ;
+    register DataType *iptr = input ;
+    register DataType *optr = buffer ;
+    register DataType *eptr = end ;
+
+    while( optr < eptr ) {
+
+	    /* the "interesting" one */
+
+	    *optr = sptr->state ;
+	    sptr->state += DESCALE( sptr->upward * ( DESCALE( *iptr * sptr->igain ) - sptr->state ) ) ;
+
+	    iptr += skip ;
+	    optr += skip ;
+    }
+
+    return ( sizeof ( DataType ) ) ;
+}
+
+static void integral_close( state )
+struct _integral_state *state ;
+{
+    Delete( state ) ;
+
+    return ;
+}
+
+Source LowpassDataTypeSource( source, stages, channels, upward, downward, igain )
+Source source ;
+int stages, channels ;
+double upward, downward, igain ;
+{
+    struct _integral_state **states ;
+    int stage, chan ;
+
+    for( stage=0 ; stage < abs( stages ) ; stage++ ) {
+
+	states = NewArray( struct _integral_state *, channels, "for states" ) ;
+
+	for( chan=0 ; chan<channels ; chan++ ) {
+
+	    states[chan] = New( struct _integral_state * ) ;
+
+	    states[chan]->state    = 0 ;
+	    states[chan]->upward   = SCALAR( 1. - exp( -1. /  upward  ) ) ;
+	    states[chan]->downward = SCALAR( 1. - exp( -1. / downward ) ) ;
+	    states[chan]->igain    = SCALAR(                  igain     ) ;
+
+	}
+
+	if( stages > 0 )
+	    source = NewMultiplexedSource( states, new_integral_callback, integral_close, channels, source, "integrate.c integration" ) ;
+	else
+	    source = NewMultiplexedSource( states, old_integral_callback, integral_close, channels, source, "integrate.c integration" ) ;
+    }
+
+    return ( source ) ;
+}
+
+
+
+
+
+struct _blocksample_state { struct _fillable_source parent ; Source source ; int spacing, channels ; } ;
+
+static Pointer blocksample_callback( state, bytes, buffer )
+struct _blocksample_state *state ;
+ByteCount *bytes ;
+DataType *buffer ;
+{
+    register int last = *bytes == 0 ;
+    register StoreType sum ;
+    register DataType *iptr ;
+    register DataType *input = (DataType *) Pull( state->source, *bytes * state->spacing ) ;
+    register DataType *end   = (DataType *) ( (Pointer) input  + *bytes * state->spacing ) ;
+    int channel ;
+
+    for( channel=0 ; channel<state->channels ; channel++ ) {
+
+	sum=0 ;
+
+	for( iptr=input+channel ; iptr < end ; iptr += state->channels )
+	    sum += *iptr ;
+
+	buffer[channel] = sum / state->spacing ;
+    }
+
+    if( !last )
+	return ( (Pointer) buffer ) ;
+    else
+	return ( DeleteFillableSource( state ) ) ;
+}
+
+Source BlockSampleSource( source, spacing, channels )
+Source source ;
+int spacing, channels ;
+{
+    DeclareNew( struct _blocksample_state *, state ) ;
+
+    state->source   = source ;
+    state->spacing  = spacing ;
+    state->channels = channels ;
+
+    source = SetFillableSource( state, blocksample_callback, "integrate.c block sampling" ) ;
+
+    source = NewSegmentingSource( source, channels * sizeof ( DataType ) ) ;
+
+    return ( source ) ;
+}
+
+
+struct _downsample_state { struct _pullable_source parent ; Source source ; int spacing, channels ; } ;
+
+static Pointer downsample_callback( state, bytes )
+struct _downsample_state *state ;
+ByteCount *bytes ;
+{
+    register int last = *bytes == 0 ;
+    Pointer output = Pull( state->source, *bytes * state->spacing ) + *bytes * state->spacing - state->channels * sizeof ( DataType ) ;
+
+    if( !last )
+	return ( output ) ;
+    else
+	return ( DeletePullableSource( state ) ) ;
+}
+
+Source DownSampleSource( source, spacing, channels )
+Source source ;
+int spacing, channels ;
+{
+    DeclareNew( struct _downsample_state *, state ) ;
+
+    state->source   = source ;
+    state->spacing  = spacing ;
+    state->channels = channels ;
+
+    source = SetPullableSource( state, downsample_callback, "integrate.c down sampling" ) ;
+
+    source = NewSegmentingSource( source, channels * sizeof ( DataType ) ) ;
+
+    return ( source ) ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/integrate.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,23 @@
+/*
+    integrate.h
+    =========
+
+    interface to some integrators and time samplers
+
+
+
+*/
+
+#define LowpassDataTypeSource( _source, _stages, _channels, _upward, _downward, _igain ) \
+	lowpassDataTypeSource( _source, _stages, _channels, _upward, _downward, _igain )
+
+#define BlockSampleSource( _source, _spacing, _channels ) \
+	blockSampleSource( _source, _spacing, _channels )
+
+#define  DownSampleSource( _source, _spacing, _channels ) \
+	 downSampleSource( _source, _spacing, _channels )
+
+
+extern Source lowpassDataTypeSource() ;
+extern Source     blockSampleSource() ;
+extern Source      downSampleSource() ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/interp.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,123 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    interp.c
+    ========
+
+    Some types of interpolation of short arrays for multiplexed filters
+
+    linterp() performs fast linear interpolations from n points to n*2-1
+    points repeatedly till the number of points required is reached.
+
+    interp() performs a slower but hopefully smoother (in the first differential)
+    interpolation from n points to n*2-1 points.
+
+    Author  : John Holdsworth
+    Written : 11th March, 1989.
+
+    Edited  :
+
+
+
+
+*/
+
+
+#ifndef  lint
+static char *sccs_id = "@(#)interp.c	1.4     J. Holdsworth (MRC-APU)  11/21/89" ;
+#endif
+
+
+/* linear interpolation */
+
+int linterp( input, output, points, newpoints )
+short *input, *output ;
+int points, newpoints ;
+{
+    register int store ;
+    register short *optr, *end, *iptr ;
+    register int nextpoints ;
+
+    nextpoints = points ;
+    end = input + 1 ;
+
+    do {
+
+	iptr = end - 1 + nextpoints - 1 ;
+
+	nextpoints = nextpoints * 2 - 1 ;
+
+	optr = output + nextpoints ;
+	end  = output + 1 ;
+
+	do {
+	    *--optr = store = *  iptr ;
+	    *--optr = store + *--iptr >> 1 ;
+	} while( optr > end ) ;
+
+    } while ( nextpoints < newpoints ) ;
+
+    *--optr = *iptr ;
+
+    return ;
+}
+
+/* simple 2nd orderish interpolation - preserves slopes */
+
+int interp( input, output, points, newpoints )
+short *input, *output ;
+int points, newpoints ;
+{
+    register short *optr, *end, *iptr ;
+    register int nextnum, bignum, oldbignum, oldput ;
+
+    iptr = input  ;
+    optr = output ;
+    end  = output + newpoints ;
+
+#ifdef lint
+    points ;
+#endif
+
+    nextnum   = *(iptr+1) ;
+    oldbignum = ( *iptr << 2 ) + *iptr   ;
+    oldput    = ( *iptr << 1 ) - nextnum ;
+
+    while( optr < end ) {
+	*optr++ = *iptr++ ;
+	if( optr < end ) {
+	    bignum = ( nextnum << 2 ) + nextnum ;
+	    if( optr < end - 2 )
+		nextnum = *(iptr+1) ;
+	    else
+		nextnum = ( *iptr << 1 ) - *(iptr-1) ;
+	    *optr++ = ( oldbignum + bignum - oldput - nextnum + 4 ) >> 3 ;
+	    oldbignum = bignum ;
+	    oldput = *(iptr-1) ;
+	}
+    }
+
+    return ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/makefile	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,78 @@
+###########################################################################
+#
+#  Makefile for AIM model library:  libmodel.a
+#
+#   (For convenience, this makefile directly calls the root makefile).
+#
+#   @(#)makefile        1.44 J. Holdsworth, (MRC-APU)  6/6/91
+#                            M. Allerhand,  (MRC-APU) 26/1/93
+#                            C. Giguere,              21/3/94
+#
+###########################################################################
+
+
+default : install
+
+GDIR = ../glib
+SDIR = ../stitch
+FDIR = ../filter
+WDIR = ../wdf
+
+MLIB =         libmodel.a
+GLIB = $(GDIR)/libglib.a
+SLIB = $(SDIR)/libstitch.a
+FLIB = $(FDIR)/libfilter.a
+WLIB = $(WDIR)/libwdf.a
+
+LIBS = $(MLIB) $(GLIB) $(SLIB) $(FLIB) $(WLIB)
+
+INCLUDES = -I$(SDIR) -I$(GDIR) -I$(FDIR) -I$(WDIR)
+
+.c.o :
+	$(CC) $(CFLAGS) $(INCLUDES) -c $<
+
+
+############################################################################
+# Make model library.
+
+OBJS =  units.o         defaults.o      bank.o          interp.o        \
+	integrate.o     corti.o         new.o           atan.o          \
+	image.o         spiral.o        faster.o        version.o       model.o
+
+lib $(MLIB) : $(OBJS)
+	ar rc $@ $? ; $(RANLIB) $@
+
+
+############################################################################
+# dependencies
+
+gen.o :         model.h calc.h spiral.h
+model.o:        model.h calc.h corti.h units.h bank.h
+bank.o :        bank.h
+new.o  :        calc.h
+integrate.o :   integrate.h calc.h
+corti.o :       corti.h calc.h corti.h
+image.o :       calc.h image.h
+faster.o:       calc.h
+spiral.o:       spiral.h
+io.o:           io.h
+units.o:        units.h
+defaults.o:     defaults.h model.h
+model.o:        model.h units.h defaults.h image.h spiral.h
+model.o:        $(WDIR)/bank_tl.h $(WDIR)/ear.h $(WDIR)/meddis.h         \
+                $(WDIR)/formulae_tl.h $(WDIR)/upsample.h $(WDIR)/calc_tl.h
+
+############################################################################
+# Make targets in root makefile.
+
+TARGETS   = main        install     all         sources \
+	    links       alllinks    demo        tar     \
+	    ftp         tape        mail        clean   \
+	    sccslinks   cleansccs   help        noplot
+
+$(TARGETS) : FORCE
+	@ cd .. ; make $@
+FORCE:
+
+
+############################################################################
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/model.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,2426 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+*/
+
+/*
+	model.c
+	=====
+
+    APU, ASP model demonstration program.
+
+
+    Copyright (c), 1989  The Medical Research Council, Applied Psychology Unit.
+
+
+    Author  : John Holdsworth
+    Written : 22th March, 1989.
+
+    Edited  : Mike Allerhand, 1990.
+
+    Edited  : Roy Patterson, 1992. Changed default values from time to time.
+
+    Edited  : MAA 10th June 1993
+	      Allowed pwidth=0
+
+    Edited  : Christian Giguere, March 1994. 
+	      - Added tools for manipulating sampling rate and scaling data
+	      - Added in an Entry Point for the outer/middle ear function
+	      - Added in an Entry Point for the transmission line filterbank
+	      - Implemented a completely new version of Meddis(). 
+                Files "haircell.h, haircell.c "                             
+	      - Changed option "scale_at" into "gain_at".
+	          That option is now passed to newCorti() as a double instead of an integer
+	          In Corti(), this meant multiplying *optr by state->scale
+              - Provided facilities to print filterbank information to stderr via
+                option info_afb. This supersedes option erbscale_afb.
+	      - Changed some default values
+              - To locate changes, search for "CG"
+
+    Edited  : Jay Datta, November 1994.
+              Added the stcrit options.
+
+            : Jay Datta, March 1995.
+              Added a function Nwidth() which returns the number
+              of sample points of the nwidth section of a SAI. 
+            : Silenced ulim_sas and llim_sas.  
+            : Changed trise_at default to 1000 from 10000. May, 1995.
+            : Changed trise_at default to 10000 from 1000. May, 1995.
+            : Separated nwidth and strobe lag by creating a new
+              option called stlag_ai.   May, 1995.
+
+*/
+
+/***************************************************************************
+* This module contains:
+*   Routines to access or modify string values.
+*   Unit conversion routines.
+*   Model entry-point functions.
+****************************************************************************/
+
+#include <string.h>
+#include  <stdio.h>
+#include   <math.h>
+
+#ifdef THINK_C
+#include <stdlib.h>
+#endif
+
+/* interfaces to stitch system */
+
+#include "options.h"
+
+#include "stitch.h"
+#include "source.h"
+#include  "funcs.h"
+#include  "units.h"
+#include   "calc.h"
+#if defined( DSP32 ) || defined( PC )
+#include   "oops.h"
+#else
+#include    "ops.h"
+#endif
+#include     "io.h"
+
+/* interface to model modules */
+
+#include "gamma_tone.h"
+#include  "integrate.h"
+#include   "formulae.h"              /* CG: removed haircell.h */
+#include    "recurse.h"
+#include     "scales.h"
+#include     "spiral.h"
+#include      "model.h"
+#include      "corti.h"
+#include      "image.h"
+#include       "bank.h"
+
+/* interface to WDF module */        /* CG */
+
+#include "formulae_tl.h"
+#include    "upsample.h"
+#include     "bank_tl.h"
+#include     "calc_tl.h"
+#include      "meddis.h"
+#include         "ear.h"
+
+/********************* Model option parameter strings ***********************
+* The strings are defined, allocated static array space, and initialized to
+* default values.
+****************************************************************************/
+
+#ifndef  lint
+static char *sccs_id = "@(#)model.c	1.49 John Holdsworth, Mike Allerhand, Roy Patterson, Paul Manson (MRC-APU) 12/23/92" ;
+#endif
+
+/* which model to use */
+
+char  whichdflt[] = "none"     ,        *whichstr = whichdflt  ;
+char sampledflt[] = "20000."   ,       *samplestr = sampledflt ;
+
+/* input properties */
+
+static char     dBdflt[] = "60."      ,           *dBstr = dBdflt     ;  /* CG */
+static char   bitsdflt[] = "12"       ,          *bitstr = bitsdflt   ;
+static char   swapdflt[] = "off"      ,         *swapstr = swapdflt   ;
+
+
+/************************ File-format strings ******************************
+* The strings are defined, allocated static array space, and initialized to
+* default values.
+****************************************************************************/
+
+#define RETURN_SIZE 50l
+
+static char      framesbuff[RETURN_SIZE] = "0",       *framesstr = framesbuff ;
+static char       bytesbuff[RETURN_SIZE] = "1",   *framebytesstr = bytesbuff  ;
+static char       widthbuff[RETURN_SIZE] = "1",   *framewidthstr = widthbuff  ;
+static char      heightbuff[RETURN_SIZE] = "1",  *frameheightstr = heightbuff ;
+static char        stepbuff[RETURN_SIZE] = "1",    *framestepstr = stepbuff   ;
+static char nwidthdflt[] = "-5ms"     ,       *nwidthstr = nwidthdflt ; /* roy 23-12-92 */
+static char stlagdflt[]   = "5ms"     ,       *stlagstr   = stlagdflt ; /* jay 16-05-95 */
+static char   susldflt[] = "5"      ,       *suslevelstr = susldflt   ; /* jay 30-08-95 */
+/************************ File-format strings *******************************
+*
+* The data which flows through the model is called a "file".
+* This is in an array which is structured or formatted according to the way
+* data is interpreted as it is pulled from each particular source.
+* The array is formatted into "frames", described by the file-format strings.
+* The format may be as successive points, (in which case each frame is a
+* single point with unit width and height), or the format may be as successive
+* 2-dimensional arrays, (in which case each frame is an array divided into
+* rows and columns).
+*
+* The strings are defined, allocated static array space, and initialized in
+* gen.c. A set of convenience routines (see below) are given to access or to
+* reset the value of a string. This enables the file format to be set up on
+* the fly, depending upon the format of the data passing through the source.
+*
+*  string:        access:     reset:          comment:
+* framesstr      Frames      setFrames       num frames in file
+* framebytesstr  Framebytes  setFramebytes   num bytes in frame
+* framewidthstr  Framewidth  setFramewidth   num points along frame width
+* frameheightst  Frameheight setFrameheight  num points along frame height
+* framestepstr   Framestep   setFramestep    num points between successive frames
+*
+* Access routines for file-format strings:
+*    Frames      returns value of "framesstr",      (initially 0)
+*    Framebytes  returns value of "framebytesstr",  (initially 1)
+*    Framewidth  returns value of "framewidthstr",  (initially 1)
+*    Frameheight returns value of "frameheightstr", (initially 1)
+*    Framestep   returns value of "framestepstr",   (initially 1)
+*
+****************************************************************************/
+
+long Frames()
+{
+    return ( atoi( framesstr      ) ) ;
+}
+
+int Framebytes()
+{
+    return ( atoi( framebytesstr  ) ) ;
+}
+
+int Framewidth()
+{
+    return ( atoi( framewidthstr  ) ) ;
+}
+
+int Frameheight()
+{
+    return ( atoi( frameheightstr ) ) ;
+}
+
+int Framestep()
+{
+    return ( atoi( framestepstr  ) ) ;
+}
+
+int  Nwidth()
+{     
+      int abc = (Samples(stlagstr, Samplerate()));
+      if ( (int)atoi(suslevelstr)>=4)
+      /* fprintf(stderr, "Nwidth is %d\n", -abc); */
+      return (-abc);
+      else
+      return 0;  
+}
+
+
+/******************* Value-to-string conversion routines. ******************/
+char *ltoa( val, buffer )
+long val ;
+char *buffer ;
+{
+    (void) sprintf( buffer, "%ld", val ) ;
+
+    return ( buffer ) ;
+}
+
+char *itoa( val, buffer )
+int val ;
+char *buffer ;
+{
+    (void) sprintf( buffer, "%d", val ) ;
+
+    return ( buffer ) ;
+}
+
+/******************* Reset routines for file-format strings ****************
+*  Convert argument (newval) to a string, and copy into the specific
+*  file-format string.
+*    setFrames      resets  "framesstr",      (initially 0)
+*    setFramebytes  resets  "framebytesstr",  (initially 1)
+*    setFramewidth  resets  "framewidthstr",  (initially 1)
+*    setFrameheight resets  "frameheightstr", (initially 1)
+*    setFramestep   resets  "framestepstr",   (initially 1)
+*
+*    updateFramebytes sets  "framebytesstr" to the total number of bytes in
+*                                     the frame, (ie current width * height).
+*
+*    Note: updateFramebytes is automatically done at the end of each call to
+*          setFramewidth or setFrameheight, to reset the "framebytesstr" to
+*          account for the new frame size.
+****************************************************************************/
+
+void setFrames( newval )
+long newval ;
+{
+    framesstr = ltoa( newval, framesbuff ) ;
+    return ;
+}
+
+void setFramebytes( newval )
+int newval ;
+{
+    framebytesstr  = itoa( newval, bytesbuff ) ;
+    return ;
+}
+
+void updateFramebytes()
+{
+    setFramebytes( Framewidth() * Frameheight() * sizeof ( short ) ) ;
+    return ;
+}
+
+void setFramewidth( newval )
+int newval ;
+{
+    framewidthstr  = itoa( newval, widthbuff ) ;
+    updateFramebytes() ;
+    return ;
+}
+
+void setFrameheight( newval )
+int newval ;
+{
+    frameheightstr = itoa( newval, heightbuff ) ;
+    updateFramebytes() ;
+    return ;
+}
+
+void setFramestep( newval )
+int newval ;
+{
+    framestepstr   = itoa( newval, stepbuff ) ;
+    return ;
+}
+
+
+static Option wavopts[] = {
+
+ { "framebytes",   bytesbuff, &framebytesstr,   "framebytes - internal",                 SilentOption},
+ { "framebytes",   bytesbuff, &framebytesstr,   "framebytes - internal",                 OutputOption},
+ { "frameheight", heightbuff, &frameheightstr,  "frameheight - internal",                SilentOption},
+ { "frameheight", heightbuff, &frameheightstr,  "frameheight - internal",                OutputOption},
+ { "framewidth",   widthbuff, &framewidthstr,   "framewidth - internal",                 SilentOption},
+ { "framewidth",   widthbuff, &framewidthstr,   "framewidth - internal",                 OutputOption},
+ { "frameshift",    stepbuff, &framestepstr,    "framestep - internal",                  SilentOption},
+ { "frameshift",    stepbuff, &framestepstr,    "framestep - internal",                  OutputOption},
+ { "frames",      framesbuff, &framesstr,       "frames - internal",                     SilentOption},
+ { "frames",      framesbuff, &framesstr,       "frames - internal",                     OutputOption},
+
+ { "samplerate",  sampledflt, &samplestr,       "Input wave sample rate (Hz)",            InOutOption},
+ { "swap_wave",     swapdflt, &swapstr,         "Swap bytes in input wave",               InOutOption},
+ { "bits_wave",     bitsdflt, &bitstr,          "Significant bits in input wave",         SilentOption},
+ { "dB_wave",        dBdflt,  &dBstr,           "Rel. input level (_tlf & _med only)\n",  InOutOption},  /* CG */
+ { "what",         whichdflt, &whichstr,        "Type of model to use required",         SilentOption},
+
+ (char *) 0 } ;
+
+
+/***************** Tools for manipulating sampling rate *********************    * CG *
+* This set of two routines allows to change and keep track of the sampling
+* rate of the data which flows through the model. It is the responsability
+* of each entry-point function to update the sampling rate as necessary.
+*
+*  routine:-       comment:-
+*  Samplerate      returns the current value of the sampling rate
+*  SetSamplerate   resets the sampling rate
+****************************************************************************/
+
+static double rateCache = 0.0 ;
+
+void setSamplerate( newval )
+double newval ;
+{
+    rateCache = newval ;
+    return ;
+}
+
+double Samplerate()
+{
+    if( rateCache == 0 )
+	rateCache = Freq( samplestr ) ;
+
+    return( rateCache ) ;
+}
+
+/******************* Tools for checking for special strings ****************
+*  OptionInt( str )
+*  OptionDouble( str )
+*  OptionStringsEqual( str1, str2 )     -(defined in options.c).
+****************************************************************************/
+
+double OptionDouble( str )
+char *str ;
+{
+    if( strcmp( str, "on" ) == 0 )
+	return( 1. ) ;
+    else if( strcmp( str, "Not_used" ) == 0 )
+	return( 0. ) ;
+    else
+	return( atof( str ) ) ;
+}
+
+int OptionInt( str )
+char *str ;
+{
+    if( strcmp( str, "on" ) == 0 )
+	return( 1 ) ;
+    else if( strcmp( str, "Not_used" ) == 0 )
+	return( 0 ) ;
+    else
+	return( atoi( str ) ) ;
+}
+
+int OptionLog ( str )
+char *str ;
+{
+   if ( strcmp( str, "off" ) == 0 )
+	return( 0 ) ;
+    else
+        return( 1 ) ;
+}
+
+
+
+
+/************************* Tools for scaling data **************************     * CG *
+* This set of two routines allows to keep track of the scaling factor needed 
+* to convert the data which flows through the model into absolute units in
+* the cgs system ( 0.0002 dyne/cm2 ==> 0 dB SPL). It is the responsability of
+* each entry-point function to update the correct scaling factor as necessary.
+* The user must initially specify the scaling of the input wave using the
+* "dB_wave" option. The default is "dB_wave=60.".
+*
+*  routine:-     comment:-
+*  Scaling       returns a scalar to convert data to cgs units
+*  SetScaling    resets the scaling factor
+****************************************************************************/
+
+static double scalingCache = 0.0 ;
+
+void setScaling( from_rms, from_dB, to_rms, to_dB )
+double from_rms, from_dB, to_rms, to_dB ;
+{
+    scalingCache = pow( 10., ( from_dB - to_dB ) / 20. ) * to_rms / from_rms ;
+}
+
+double Scaling()
+{
+    double rms = 200. ;      /* the default: 200 rms ==> 60 dB */
+    double dB  =  60. ;
+
+    if( scalingCache == 0 ) {
+    
+	if( strcmp( dBstr, "off" ) != 0 )
+	   dB = Scalar( dBstr ) ;
+	setScaling( rms, dB, 0.0002, 0. ) ;
+    }
+
+   return( scalingCache ) ;
+}
+
+/************************  entry-point functions ***************************
+* Each entry-point function creates and initializes a "source object", and
+* returns a pointer to this object. Each source set up by one of the routines
+* below is designed to be the entry point for a specialized auditory-modelling
+* process. (See also io.c for sources which read from disk).
+* Source set-up functions always return a Source. They may take one or more
+* sources as arguments, as a specification of the input to the process
+* the source performs. The set up routine intializes the source structure with
+* a pointer to a callback function, which performs the data processing when
+* the source is used.
+*
+* Pointers to the entry-point functions are defined in the stage table,
+* (see FindStage() below). The functions are called, using these pointers,
+* from routine ModeledSource() (see below). The purpose of this is to call the
+* functions, in the order set by the stage table, so as to initialize a chain
+* of objects which can ultimately be used to execute the program.
+*
+* The source set-up routines are analogous to fopen(), (see stitch/source.c).
+* The processing phase, (analogous to fread()), uses pull/fill/roll functions,
+* and this execution is started from gen.c:main() by a call to SinkSource().
+*
+*   routine:-                   special subroutines:-
+*   EarEntry()                  Ear()                                           * CG *
+*   GenericEntry()              GenericFilterBank()
+*   FilterEntry()               GenericEntry()
+*   TLF_FilterEntry()           TLF_GenBank()                                   * CG *
+*   FineEntry()                 EarEntry() FilterEntry() TLF_FilterEntry()      * CG *
+*   EnvelopeEntry()             GenericEntry()
+*   ComplexEntry()              GenericEntry()
+*   PolarEntry()
+*   RectifyEntry()
+*   LogEntry()
+*   UncompressEntry()
+*   SaturateEntry()             Saturate()
+*   LowpassEntry()              LowpassDataTypeSource()
+*   ThresholdEntry()            Meddis()  Mfsai()
+*   AdaptEntry()
+*   HardEntry()                 Saturate()
+*   IntegralEntry()             LowpassDataTypeSource()
+*   DownSampleEntry()           DownSampleSource() BlockSampleSource()
+*   SaiEntry()                  Sai()
+*   SummaryEntry()              Summary()
+*   NullEntry()
+****************************************************************************/
+
+/* As a means of introducing "cgm" as an alias for "fed", this NullEntry point does
+   absolutely nothing to the data, but it DOES enable us to enter the queue just above
+   the entry point for "fed". */
+
+static Source NullEntry( source )
+Source source ;
+{
+    return ( source ) ;
+}
+
+
+/***** upsampling parameters *****/                                     /* CG */
+
+static char    upfdflt[] = "auto"     ,          *upfstr = upfdflt    ; /* CG */
+static char cutoffdflt[] = "1.0"      ,       *cutoffstr = cutoffdflt ; /* CG */
+static char  downfdflt[] = "auto"     ,        *downfstr = downfdflt  ; /* CG */
+
+/***** ear parameters *****/                                            /* CG */
+ 
+static char middledflt[] = "on"       ,       *middlestr = middledflt ; /* CG */
+static char  lconcdflt[] = "0.90"     ,        *lconcstr =  lconcdflt ; /* CG */
+static char  rconcdflt[] = "1.00"     ,        *rconcstr =  rconcdflt ; /* CG */
+static char  kconcdflt[] = "0.01"     ,        *kconcstr =  kconcdflt ; /* CG */
+static char  nconcdflt[] = "2"        ,        *nconcstr =  nconcdflt ; /* CG */
+static char lcanaldflt[] = "2.85"     ,       *lcanalstr = lcanaldflt ; /* CG */
+static char rcanaldflt[] = "0.35"     ,       *rcanalstr = rcanaldflt ; /* CG */
+static char kcanaldflt[] = "0.04"     ,       *kcanalstr = kcanaldflt ; /* CG */
+static char ncanaldflt[] = "4"        ,       *ncanalstr = ncanaldflt ; /* CG */
+
+static Source EarEntry( source )                                  /* CG: new entry */
+Source source ;
+{
+    int     upfactor, downfactor ;
+    double  cutoff, gain = OptionDouble( middlestr ) ;
+    DeclareNew( struct _tube_info *, concha ) ;
+    DeclareNew( struct _tube_info *, canal ) ;
+
+    if( gain ) {
+
+      /*** set up/downsampling parameters ***/
+       if( strncmp( upfstr, "auto", 4 ) == 0 ) {
+	   if( strncmp( downfstr, "auto", 4 ) == 0 )
+	      upfactor = MIN( AUTO, ( int ) ( ( MAXSIGNALFREQ * AUTO * 2 ) / Samplerate() + 1.0 ) ) ;
+	   else 
+	      upfactor = ABS( OptionInt( downfstr ) ) ;
+	      downfactor = upfactor ;
+       }
+       else {
+	   upfactor = ABS( OptionInt( upfstr ) ) ;
+	   if( strncmp( downfstr, "auto", 4 ) == 0 )
+	      downfactor = upfactor ; 
+	   else
+	      downfactor = ABS( OptionInt( downfstr ) ) ;
+       }
+	   
+      /*** set cutoff frequency of FIR upsampling filter ***/
+       cutoff = 0.5 * Samplerate() * Scalar( cutoffstr ) ;
+       if( downfactor > upfactor ) {
+	   upfactor = MAX( 1, upfactor ) ;
+	   cutoff = cutoff * ( double ) upfactor / ( double ) downfactor ;
+       }    
+   
+      /*** upsample input wave ***/
+       if( upfactor >= 1 ) {
+	   source = UpSample( source, Samplerate(), cutoff, upfactor ) ;
+	   ( void ) setSamplerate( Samplerate() * upfactor ) ;
+	   ( void ) setFrames( Frames() * upfactor ) ;
+       }
+
+      /*** outer/middle ear filter ***/
+       concha->Nsegments = atoi( nconcstr ) ;
+       concha->length = atof( lconcstr ) ;
+       concha->diameter = atof( rconcstr ) * 2. ;
+       concha->att_factor = atof( kconcstr ) ;
+       canal->Nsegments = atoi( ncanalstr ) ;
+       canal->length = atof( lcanalstr ) ;
+       canal->diameter = atof( rcanalstr ) * 2. ;
+       canal->att_factor = atof( kcanalstr ) ;
+
+       source = Ear( source, Samplerate(), gain, concha, canal ) ;
+
+       Delete( concha ) ;
+       Delete( canal ) ;
+
+      /*** downsample output data ***/
+       if( downfactor >= 1 ) {
+	   source = DownSampleSource( source, downfactor, 1 ) ;
+	   ( void ) setSamplerate( Samplerate() / downfactor ) ;
+	   ( void ) setFrames( Frames() / downfactor ) ;
+       }
+
+    }
+    return ( source ) ;
+}
+
+
+/***** frequency scale parameters*****/
+
+static char   qualdflt[] = "9.265"    ,         *qualstr = qualdflt   ;
+static char  limitdflt[] = "24.7Hz"   ,        *limitstr = limitdflt  ;
+static char     mmdflt[] = "0.89"     ,           *mmstr = mmdflt     ; /* CG */
+
+static char interpdflt[] = "off"      ,       *interpstr = interpdflt ;
+
+/***** filterbank parameters ****/
+
+static char    maxdflt[] = "6000Hz"   ,          *maxstr = maxdflt    ; /* roy 23-12-92 */
+static char    mindflt[] = "100Hz"    ,          *minstr = mindflt    ; /* roy 23-12-92 */
+#ifdef PC
+static char    dendflt[] = "off"      ,          *denstr = dendflt    ; /* roy 23-12-92 */
+#else
+static char    dendflt[] = "off"      ,          *denstr = dendflt    ; /* roy 23-12-92 */
+#endif
+static char  chansdflt[] = "75"       ,        *chansstr = chansdflt  ; /* roy 23-12-92 */
+static char  audiodflt[] = "off"      ,        *audiostr = audiodflt  ; /* CG */
+static char   infodflt[] = "off"      ,         *infostr = infodflt   ; /* CG */
+
+static char filterdflt[] = "gtf"      ,       *filterstr = filterdflt ; /* CG */
+
+
+/****************************************************************************
+* updateFrequencies()
+* Routine called from ModeledSource(), below.
+* It sets the frameheight (number of filter-bank channels), and initializes
+* the array of channel centre-frequencies, (called "frequencies").
+* These are derived from three basic parameters:
+* option-name:  string-value: default:  comment:
+*  mincf_afb      minstr       220Hz    Minimum center frequency (Hz)
+*  maxcf_afb      maxstr       4400Hz   Maximum center frequency (Hz)
+*  dencf_afb      denstr       4.       Filter density (filters/critical band)
+*
+* The frameheight is calculated in the routine "NumberCenterFrequencies",
+* and the result is copied into the "frameheightstr" by a call to the routine
+* "setFrameheight".
+* The "frequencies" are calculated in the routine "GenerateCenterFrequencies".
+* (Both CenterFrequency routines are in gamma_tone.c).
+*
+* The frequencies are stored in a global array of center frequencies (below).
+****************************************************************************/
+
+double *frequencies ;    /* global array of centre frequencies */
+
+static void reverseFrequencies( freqs, channels )
+double *freqs ;
+int channels ;
+{
+    int i ;
+    double d ;
+
+    for( i=0 ; i<channels/2 ; i++ ) {
+	d = freqs[i] ;
+	freqs[i] = freqs[channels-i] ;
+	freqs[channels-i] = d ;
+    }
+}
+
+
+static void updateFrequencies()                                     /* CG: modified */
+{
+    int    chans = OptionInt( chansstr ) ;
+    double min, max, density = atof( denstr ) ;
+
+    if( frequencies != (double *) 0 )
+	Delete( frequencies ) ;
+
+    SetErbParameters( Freq( limitstr ), atof( qualstr ) ) ;
+
+    if( strncmp( filterstr, "tlf", 3 ) == 0 ) {
+
+	if( chans == 0 && density == 0. )
+	    chans = 1 ;
+
+	min  = adjustCF( Freq( minstr ), Samplerate() ) ;
+	max  = adjustCF( MAX( Freq( maxstr ), min ), Samplerate() ) ;
+    }
+
+    else {
+	min  = Freq( minstr ) ;
+	max  = Freq( maxstr ) ;
+    }
+
+    if( chans == 0 ) {
+	frequencies = GenerateCenterFrequencies( min, max, density )   ;
+	setFrameheight( NumberCenterFrequencies( min, max, density ) ) ;
+    }
+    else {
+	frequencies = NumberedCenterFrequencies( min, max, chans )   ;
+	setFrameheight( chans ) ;
+    }
+
+/*
+    reverseFrequencies( Frequencies, Frameheight() ) ;
+*/
+
+    return ;
+}
+
+
+ChannelAxis( min, max, label )
+double *min, *max ;
+char **label ;
+{
+    *min = (int) ( ErbScale( Freq( minstr ) ) * 10. ) / 10. ;
+    *max = (int) ( ErbScale( Freq( maxstr ) ) * 10. ) / 10. ;
+
+    *label = "Center Frequency [ERBs]" ;
+}
+
+/***** GTF auditory filter parameters *****/                             /* CG */
+
+static char  orderdflt[] = "4"        ,        *orderstr = orderdflt  ;
+static char  phasedflt[] = "0"        ,        *phasestr = phasedflt  ;
+static char   gaindflt[] = "4."       ,         *gainstr = gaindflt   ;
+static char  floatdflt[] = "off"      ,        *floatstr = floatdflt  ;
+
+static Source GenericEntry( source, proc )                               /* CG */
+Source source ;
+int (*proc)() ;
+{
+    int chans ;
+    Source ret ;
+
+    updateFrequencies() ;
+
+    chans  = Frameheight() ;
+    ret = GenericFilterBank( source, OptionInt( interpstr ), &chans, Samplerate(), 
+                      frequencies, Erb, ErbScale, Scalar( gainstr ), OptionDouble( audiostr ),
+                      atoi( orderstr ), atoi( phasestr ), atoi( bitstr ), Frames(), proc, 
+                      sizeof ( DataType ), OptionInt( infostr ) ) ;      /* CG */
+
+    setFrameheight( chans ) ;
+
+    return ( ret ) ;
+}
+
+static Source FilterEntry( source )
+Source source ;
+{
+    switch( OptionInt( floatstr ) ) {
+#ifdef FLOAT
+	case 0 :
+	case 1 :
+	    return ( GenericEntry( source, DoRealFilterFloatDataArray ) ) ;
+#else
+	case 0 :
+	    return ( GenericEntry( source,     DoFilterShortDataArray ) ) ;
+	case 1 :
+	    return ( GenericEntry( source, DoRealFilterShortDataArray ) ) ;
+#endif 
+	case 2 :
+	    return ( GenericEntry( source,       DoNewFilterDataArray ) ) ;
+    }
+
+    return ( source ) ;
+}
+
+/***** TLF auditory filter parameters *****/                             /* CG */
+
+static char  tgaindflt[] = "4."       ,        *tgainstr = tgaindflt  ;  /* CG */
+static char   dsatdflt[] = "5.75e-6"  ,         *dsatstr = dsatdflt   ;  /* CG */
+static char   feeddflt[] = "0.99"     ,         *feedstr = feeddflt   ;  /* CG */
+static char   qrefdflt[] = "2."       ,         *qrefstr = qrefdflt   ;  /* CG */ 
+static char outdendflt[] = "4."       ,       *outdenstr = outdendflt ;  /* CG */
+static char motiondflt[] = "vel"      ,       *motionstr = motiondflt ;  /* CG */
+
+static Source TLF_FilterEntry( source )                                  /* CG: new entry */
+Source source ;
+{
+    int chans ;
+    int upfactor, downfactor ;
+    double cutoff, dsat ;
+    DeclareNew( struct _tube_info *, concha ) ;
+    DeclareNew( struct _tube_info *, canal ) ;
+
+   /*** set up/downsampling parameters ***/
+    if( strncmp( upfstr, "auto", 4 ) == 0 ) {
+	if( strncmp( downfstr, "auto", 4 ) == 0 )
+	   upfactor = MIN( AUTO, ( int ) ( ( MAXSIGNALFREQ * AUTO * 2 ) / Samplerate() +1.0 ) ) ;
+	else 
+	   upfactor = ABS( OptionInt( downfstr ) ) ;
+	downfactor = upfactor ;
+    }
+    else {
+	upfactor = ABS( OptionInt( upfstr ) ) ;
+	if( strncmp( downfstr, "auto", 4 ) == 0 )
+	   downfactor = upfactor ; 
+	else
+	   downfactor = ABS( OptionInt( downfstr ) ) ;
+    }
+	   
+   /*** set cutoff frequency of FIR upsampling filter ***/
+    cutoff = 0.5 * Samplerate() * Scalar( cutoffstr ) ;
+    if( downfactor > upfactor ) {
+	upfactor = MAX( 1, upfactor ) ;
+	cutoff = cutoff * ( double ) upfactor / ( double ) downfactor ;
+    }    
+  
+   /*** upsample input wave ***/
+    if( upfactor >= 1 ) {
+	source = UpSample( source, Samplerate(), cutoff, upfactor ) ;
+	( void ) setSamplerate( Samplerate() * upfactor ) ;
+	( void ) setFrames( Frames() * upfactor ) ;
+    }
+
+   /*** set outer/middle ear parameters ***/
+    concha->Nsegments = atoi( nconcstr ) ;
+    concha->length = atof( lconcstr ) ;
+    concha->diameter = atof( rconcstr ) * 2. ;
+    concha->att_factor = atof( kconcstr ) ;
+    canal->Nsegments = atoi( ncanalstr ) ;
+    canal->length = atof( lcanalstr ) ;
+    canal->diameter = atof( rcanalstr ) * 2. ;
+    canal->att_factor = atof( kcanalstr ) ;
+
+   /*** set bank parameters ***/
+    updateFrequencies() ;
+    SetERBscaling( atof( mmstr ) ) ;
+    chans = Frameheight() ;
+
+   /*** OHC normalization: converts from cgs units (0 dB SPL=>0.0002 dynes/cm2) to input wave units ***/
+    dsat = atof( dsatstr ) / Scaling() ;
+
+   /*** process data and downsample output ***/
+    source = TLF_GenBank( source, OptionInt( interpstr ), OptionInt( infostr ), &chans, &downfactor, 
+                          Samplerate(), frequencies, Scalar( tgainstr ), atof( outdenstr ),
+			  atof( qrefstr ), atof( feedstr ), dsat, motionstr, concha, canal ) ;
+
+   /*** reset sampling rate and file-format strings ***/
+    ( void ) setFrameheight( chans ) ;
+    ( void ) setSamplerate ( Samplerate() / downfactor ) ;  
+    ( void ) setFrames( Frames() / downfactor ) ;
+
+    Delete( concha ) ;
+    Delete( canal ) ;
+
+    return ( source ) ;
+}
+
+static Source FineEntry(source )                                 /* CG: new Entry */
+Source source ;
+{
+    if( strncmp( filterstr, "off", 3 ) == 0 )
+	source = EarEntry( source ) ;
+
+    else {
+
+	if( strncmp( filterstr, "tlf", 3 ) == 0 )
+	    source = TLF_FilterEntry( source ) ;
+
+	else {
+       	    source = EarEntry( source ) ;
+	    source = FilterEntry( source ) ;
+	}
+    }
+
+    return( source ) ;
+}
+
+static Source EnvelopeEntry( source )
+Source source ;
+{
+#ifdef FLOAT
+    return ( GenericEntry( source, DoRealEnvelopeFloatDataArray ) ) ;
+#else
+    if( OptionInt( floatstr ) != 0 )
+	return ( GenericEntry( source, DoRealEnvelopeShortDataArray ) ) ;
+    else
+	return ( GenericEntry( source,     DoEnvelopeShortDataArray ) ) ;
+#endif
+}
+
+static Source ComplexEntry( source )
+Source source ;
+{
+    Source ret ;
+
+#ifdef FLOAT
+    ret = GenericEntry( source, DoComplexFilterFloatDataArray ) ;
+#else
+    ret = GenericEntry( source, DoComplexFilterShortDataArray ) ;
+#endif
+    setFrameheight( Frameheight() * 2 ) ;
+
+    return ( ret ) ;
+}
+
+/******* [fbm] [bmm] [fcp,fcr] stage: "auditory filter output" ************/
+
+static  Option fbmopts[] = {
+
+ {     "upfactor",    upfdflt,    &upfstr, "Upsampling factor (off, auto, int)",        SilentOption},  /* CG */
+ {       "cutoff", cutoffdflt, &cutoffstr, "LP cutoff as a fraction of Nyquist freq.",  SilentOption},  /* CG */
+ {   "downfactor",  downfdflt,  &downfstr, "Downsampling factor (off, auto, int)\n",    SilentOption},  /* CG */
+
+ {   "middle_ear", middledflt, &middlestr, "Enable outer/middle ear function\n",         InOutOption},  /* CG */
+ {  "nconcha_ear",  nconcdflt,  &nconcstr, "Number of segments in concha",              SilentOption},  /* CG */
+ {  "lconcha_ear",  lconcdflt,  &lconcstr, "Total length of concha (cm)",               SilentOption},  /* CG */
+ {  "rconcha_ear",  rconcdflt,  &rconcstr, "Radius of concha (cm)",                     SilentOption},  /* CG */
+ {  "kconcha_ear",  kconcdflt,  &kconcstr, "Attn. constant of concha (1/cm)",           SilentOption},  /* CG */
+ {   "ncanal_ear", ncanaldflt, &ncanalstr, "Number of segments in ear canal",           SilentOption},  /* CG */
+ {   "lcanal_ear", lcanaldflt, &lcanalstr, "Length of ear canal (cm)",                  SilentOption},  /* CG */
+ {   "rcanal_ear", rcanaldflt, &rcanalstr, "Radius of ear canal (cm)",                  SilentOption},  /* CG */
+ {   "kcanal_ear", kcanaldflt, &kcanalstr, "Attn. constant of ear canal (1/cm)\n",      SilentOption},  /* CG */
+
+ { "channels_afb",  chansdflt,  &chansstr, "Number of channels in filter",               InOutOption},
+ {    "mincf_afb",    mindflt,    &minstr, "Minimum center frequency (Hz)",              InOutOption},
+ {    "maxcf_afb",    maxdflt,    &maxstr, "Maximum center frequency (Hz)",              InOutOption},
+ {    "dencf_afb",    dendflt,    &denstr, "Filter density (filters/critical band)",     InOutOption},
+ {     "info_afb",  infodflt,    &infostr, "Prints filterbank information (to stderr).", InputOption},  /* CG */
+ {   "interp_afb", interpdflt, &interpstr, "Levels of interpolation to apply",          OutputOption},
+ {   "interp_afb", interpdflt, &interpstr, "Levels of interpolation to apply",          SilentOption},
+ {"audiogram_afb",  audiodflt,  &audiostr, "Audiogram equalisation parameter",          SilentOption},  /* CG */ 
+ {    "bwmin_afb",  limitdflt,  &limitstr, "Minimum filter bandwith",                    InOutOption},
+ {  "quality_afb",   qualdflt,   &qualstr, "Ultimate qualtity factor of filters",        InOutOption},
+ {    "mmerb_afb",     mmdflt,     &mmstr, "Length of 1 erb-rate unit along BM (mm)\n",  InOutOption},  /* CG */
+
+ {       "filter", filterdflt, &filterstr, "Select auditory filter (gtf, tlf, off)\n",   InOutOption},  /* CG */
+
+ {    "float_gtf",  floatdflt,  &floatstr, "Floating point filter calculations",        OutputOption},
+ {    "float_gtf",  floatdflt,  &floatstr, "Floating point filter calculations",        SilentOption},
+ {    "phase_gtf",  phasedflt,  &phasestr, "Phase compensation option",                  InOutOption},
+ {    "order_gtf",  orderdflt,  &orderstr, "Filter order",                               InOutOption},
+ {     "gain_gtf",   gaindflt,   &gainstr, "Filter output amplification\n",              InOutOption},  /* CG */
+
+ {   "motion_tlf", motiondflt, &motionstr, "BM output motion (disp, vel)",               InOutOption},  /* CG */
+ { "outdencf_tlf", outdendflt, &outdenstr, "Filter density outside display range",       InOutOption},  /* CG */
+ {     "qref_tlf",   qrefdflt,   &qrefstr, "Local Q-factor of BM segment",               InOutOption},  /* CG */
+ { "feedback_tlf",   feeddflt,   &feedstr, "Feedback gain of OHCs (0 to 0.999)",         InOutOption},  /* CG */
+ {     "dsat_tlf",   dsatdflt,   &dsatstr, "Half-saturation displacement (cm)",          InOutOption},  /* CG */
+ {     "gain_tlf",  tgaindflt,  &tgainstr, "Filter output amplification\n",              InOutOption},  /* CG */
+
+ ( char * ) 0 } ;
+
+static void polar_callback( state, bytes, output, end, input )
+Source state ;
+ByteCount *bytes ;
+scomplex *output, *end, *input ;
+{
+    register scomplex *iptr = input ;
+    register scomplex *optr = output ;
+    register scomplex *eptr = end ;
+
+    while( optr < eptr ) {
+	optr->real = imB( (long) iptr->real * iptr->real + (long) iptr->imag * iptr->imag ) >> 1 ;
+	optr->imag = iatan2( iptr->imag, iptr->real ) ;
+	iptr++ ;
+	optr++ ;
+    }
+
+    return ;
+}
+
+static Source PolarEntry( source )
+Source source ;
+{
+    return ( NewSimpleProcessingSource( polar_callback, source, "model.c polar conversion" ) ) ;
+}
+
+static void fullwave_callback( state, bytes, buffer, end, input )
+Source state ;
+ByteCount *bytes ;
+DataType *buffer, *end, *input ;
+{
+    register DataType *iptr = input ;
+    register DataType *optr = buffer ;
+    register DataType *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    if( *iptr > 0 )
+		*optr++ =  *iptr++ ;
+	    else
+		*optr++ = -*iptr++ ;
+
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+
+/* rectification */
+
+static char   rectdflt[] =     "off",   *rectstr =   rectdflt ;
+
+/************** [fbr] stage: "rectified filter output" ******************/
+
+static  Option fbropts[] = {
+
+ {      "rectify",   rectdflt,   &rectstr, "Rectify filter output",                      InOutOption},
+
+ ( char * ) 0 } ;
+
+
+static void halfwave_callback( state, bytes, buffer, end, input )
+Source state ;
+ByteCount *bytes ;
+DataType *buffer, *end, *input ;
+{
+    register DataType *iptr = input ;
+    register DataType *optr = buffer ;
+    register DataType *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    if( *iptr > 0 )
+		*optr++ =  *iptr++ ;
+	    else
+		*optr++ =0,*iptr++ ;
+
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+static Source RectifyEntry( source )
+Source source ;
+{
+    switch( OptionInt( rectstr ) ) {
+
+	case 1 :
+	    return ( SharingSource( NewSimpleProcessingSource( halfwave_callback, source, "model.c recification" ), source ) ) ;
+
+	case 2:
+	    return ( SharingSource( NewSimpleProcessingSource( fullwave_callback, source, "model.c recification" ), source ) ) ;
+
+	default :
+	    return ( source ) ;
+    }
+}
+
+
+/*********** [fbc] [fec] stage: "compressed filter output" **************/
+
+/* logaritmic compression function */
+
+static char    logdflt[] =      "log",    *logstr =    logdflt ;
+static char    powdflt[] =      "off",    *powstr =    powdflt ;
+
+static  Option fbcopts[] = {
+
+ {     "compress",    logdflt,    &logstr, "Compression (log, power value [0-1], off)",   InOutOption},
+ ( char * ) 0 } ;
+
+
+#ifdef FLOAT
+static void mB_callback( state, bytes, buffer, end, input )
+Pointer state ;
+ByteCount *bytes ;
+DataType *buffer, *end, *input ;
+{
+    register DataType *iptr = input  ;
+    register DataType *optr = buffer ;
+    register DataType *eptr = end ;
+    double pw;
+
+    if (!strcmp(logstr, "log") || !strcmp(logstr, "on"))
+      ;
+    else 
+      {
+	pw=(double)atof(logstr);
+        strcpy(powstr, "on");
+	if (pw > 1.0) {
+          fprintf(stderr, "The value of power compression cannot be more than 1.0\n");
+	  exit(-125);}
+      }
+    
+    if( optr < eptr )
+      do{
+	if( *iptr  >= 1. ){
+	  if (!(strcmp(powstr, "off"))){
+	    *optr = log10( *iptr ) * 2000. ;} 
+	  else{ 
+	    *optr = (float) pow((double)*iptr, (double) pw) * 100./(pw); } 
+	}
+	else
+	     *optr =   0. ;   /* -10.    Changed from -10,  AJD 29th August, 1995.  */
+	     iptr++; optr++;  }
+      while( optr < eptr ) ;
+
+    return ;
+
+}
+#endif
+
+static Source LogEntry( source )
+Source source ;
+{
+    if( OptionLog( logstr ) != 0 )
+#ifdef FLOAT
+	return ( SharingSource( NewSimpleProcessingSource( mB_callback, source, "model.c compression" ), source ) ) ;
+#else
+	return ( SharingSource( milliBellShortSource( source ), source ) ) ;
+#endif
+    else
+	return ( source ) ;
+}
+
+/*********** [fbu] [feu] stage: "uncompressed filter output" **************/
+
+/***** uncompress data by raising to a power *****/
+
+static char  powerdflt[] =     "off",  *powerstr =  powerdflt ;
+
+static  Option fbuopts[] = {
+
+ {        "power",  powerdflt,  &powerstr, "Power of Compression",                      SilentOption},
+
+ ( char * ) 0 } ;
+
+
+struct _uncompress_state { double power ; } ;
+
+static void uncompress_callback( state, bytes, buffer, end, input )
+struct _uncompress_state *state ;
+ByteCount *bytes ;
+DataType *buffer, *end, *input ;
+{
+    register DataType *iptr = input  ;
+    register DataType *optr = buffer ;
+    register DataType *eptr = end ;
+    register double power = state->power ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = pow( 10., *iptr++ * power ) ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+static Source UncompressEntry( source )
+Source source ;
+{
+    DeclareNew( struct _uncompress_state *, state ) ;
+
+    if( OptionDouble( powerstr ) != 0.0 ) {
+
+	state->power  = OptionDouble( powerstr ) / 2000. ;
+
+	return ( SharingSource (NewProcessingSource( state, uncompress_callback, stitch_free, source, "model.c compression" ), source ) ) ;
+    }
+    else
+	return ( source ) ;
+}
+
+/*********** [fbs] [fes] stage: "saturated filter output" **************/
+
+/***** provide for possible saturation at this point *****/
+
+static char    satdflt[] =     "off",    *satstr =    satdflt ;
+
+static  Option fbsopts[] = {
+
+ {     "saturate",    satdflt,    &satstr, "Introduce Saturation of non-linearity\n",   SilentOption},
+
+ ( char * ) 0 } ;
+
+
+struct _sat_state { int saturation ; } ;
+
+static void sat_callback( state, bytes, buffer, end, input )
+struct _sat_state *state ;
+ByteCount *bytes ;
+DataType *buffer, *end, *input ;
+{
+    register DataType *iptr = input ;
+    register DataType *optr = buffer ;
+    register DataType *eptr = end ;
+
+    if( optr < eptr )
+	do {
+
+	     if( *iptr > 0 )
+		 *optr++ = SCALE( *iptr ) / ( SCALE( 1 ) + SCALE( *iptr ) / state->saturation ) ;
+	     else
+		 *optr++ = SCALE( *iptr ) / ( SCALE( 1 ) - SCALE( *iptr ) / state->saturation ) ;
+	     iptr++ ;
+
+	} while( optr < eptr ) ;
+
+    return ;
+}
+
+static Source Saturate( source, str )
+Source source ;
+char *str ;
+{
+    DeclareNew( struct _sat_state *, state ) ;
+
+    if( OptionInt( str ) != 0 ) {
+
+	state->saturation = OptionInt( str ) ;
+
+	return ( SharingSource( NewProcessingSource( (Pointer) state, sat_callback, stitch_free, source, "model.c stauration"  ), source ) ) ;
+    }
+    else
+	return ( source ) ;
+}
+
+static Source SaturateEntry( source )
+Source source ;
+{
+    return( Saturate( source, satstr ) ) ;
+}
+
+#if 00
+/***** new processing entry *****/
+
+static char zongdflt[] =     "off", *zongstr = zongdflt ; /* parameter default for table.c */
+
+static Source ZongEntry( source )
+Source source ;
+{
+    int i, chans = Frameheight() ;
+    DeclareNewArray( WuState *, states, chans, "model.c for states" ) ;
+
+    /* for all of the channels create a new wu cels object */
+
+    for( i=0 ; i<chans ; i++ )
+	states[ i ] = NewWu( zongstr ) ; /* call constructor of new wu cell */
+
+    /* use general purpose source for processing multiplexed files with these cells */
+
+return (source ) ;
+    return ( NewMultiplexedSource( states, WuMultiplexedDataArray, DeleteWu, chans, source, "model.c wu" ) ) ;
+}
+#endif
+
+/*********** [fbl] [fel] stage: "low-pass filtered filter output ***********/
+
+/* low pass filtering */
+
+static char lstagedflt[] =     "off", *lstagestr = lstagedflt ;
+static char    lupdflt[] =   "0.5ms",    *lupstr =    lupdflt ;
+static char  ldowndflt[] =       "1",  *ldownstr =  ldowndflt ;
+static char  llossdflt[] =       "1",  *llossstr =  llossdflt ;
+static char lvlossdflt[] =       "0", *lvlossstr = lvlossdflt ;
+static char ligaindflt[] =       "1", *ligainstr = ligaindflt ;
+
+static  Option fblopts[] = {
+
+ {   "ligain_lpf", ligaindflt, &ligainstr, "Gain of integration stage\n",               OutputOption},
+ {   "ligain_lpf", ligaindflt, &ligainstr, "Gain of integration stage\n",               SilentOption},
+ {   "lvloss_lpf", lvlossdflt, &lvlossstr, "Rest level for loss",                       OutputOption},
+ {   "lvloss_lpf", lvlossdflt, &lvlossstr, "Rest level for loss",                       SilentOption},
+ {    "lloss_lpf",  llossdflt,  &llossstr, "Loss time constant",                        OutputOption},
+ {    "lloss_lpf",  llossdflt,  &llossstr, "Loss time constant",                        SilentOption},
+ {   "ltdown_lpf",  ldowndflt,  &ldownstr, "Downward time constant in ms",              OutputOption},
+ {   "ltdown_lpf",  ldowndflt,  &ldownstr, "Downward time constant in ms",              SilentOption},
+ {     "ltup_lpf",    lupdflt,    &lupstr, "Upward time constant in ms",                SilentOption},
+ {  "lstages_lpf", lstagedflt, &lstagestr, "Stages of integration\n",                   SilentOption},
+
+ ( char * ) 0 } ;
+
+static Source LowpassEntry( source )
+Source source ;
+{
+    return ( LowpassDataTypeSource( source, OptionInt( lstagestr ), Frameheight(), Samples( lupstr, Samplerate() ), Samples( ldownstr, Samplerate() ), Scalar( ligainstr ) ) ) ;
+}
+
+
+/*********** [nap,fbt] [fet] stage: "neural activity pattern" **************/
+
+/***** transduction switch *****/                              /* CG */
+
+static char  transdflt[] =    "at", *transstr = transdflt ;    /* CG */
+
+
+/***** meddis inner haircell model *****/                      /* CG */
+
+static char meddisdflt[] =    "1.", *meddisstr = meddisdflt ;
+static char  fibredflt[] ="medium",  *fibrestr = fibredflt ;   /* CG */
+static char thresdflt[] =     "0.",  *thresstr = thresdflt ;   /* CG */
+
+Source Meddis( input, chans, samplerate, scalar )              /* CG: modified */
+Source input ;
+int chans ;
+double samplerate, scalar ;
+{
+    char *state ;
+    double coupling = 100. / pow( 10., atof( thresstr ) / 20. ) ;
+
+   /*** convert from filterbank units to meddis units (30 dB => 1 rms ) ***/
+
+      /* first convert from filterbank output units to cgs units (0 dB SPL => 0.0002 dynes/cm2) ***/
+       ( void ) setScaling( 0.0002 / Scaling() * FILTERBANK_SCALE * 4.0, 0., 0.0002, 0. ) ;
+
+      /* second convert from cgs units to meddis units (30 dB => 1 rms) ***/
+       ( void ) setScaling( 0.0002 / Scaling(), 0., MEDDIS_RMS, MEDDIS_dB ) ;
+
+   /*** start array of Meddis hair cells ***/
+    coupling = coupling * Scaling() ;
+    state = NewHaircells( chans, samplerate, scalar, coupling, fibrestr ) ;
+    return ( NewProcessingSource( state, DoHaircells, CloseHaircells, input, "model.c meddis" ) ) ;
+}
+
+/***** adaptive thresholding *****/
+
+static char    stxdflt[] =      "1.",    *stxstr =    stxdflt ; /* CG 23-03-94 */
+static char   risedflt[] =  "10000.",   *risestr =   risedflt ;
+static char  rapiddflt[] =     "0.6",  *rapidstr =  rapiddflt ;
+static char   fastdflt[] =     "0.2",   *faststr =   fastdflt ;
+static char   propdflt[] =     "0.5",   *propstr =   propdflt ;
+static char    latdflt[] =     "20.",    *latstr =    latdflt ; /* roy 23-12-92 */
+static char vdraindflt[] =       "5", *vdrainstr = vdraindflt ;
+static char  timesdflt[] =       "2",  *timesstr =  timesdflt ;
+
+static char   compdflt[] =     "on",    *compstr =   compdflt ; /* mha 22/1/93 */
+
+
+static  Option fbtopts[] = {
+
+ { "transduction",  transdflt,  &transstr, "Select transduction function (at, meddis, off)\n",InOutOption},  /* CG */
+ 
+ {     "trise_at",   risedflt,   &risestr, "Threshold adaptation rate (upwards)",        InOutOption},
+ {"t1recovery_at",  rapiddflt,  &rapidstr, "Initial recovery rate relative to filter",   InOutOption},
+ {"t2recovery_at",   fastdflt,   &faststr, "Secondary recovery rate relative to filter", InOutOption},
+ {  "propt2t1_at",   propdflt,   &propstr, "Relative height of secondary adaptation",    InOutOption},
+ { "frecovery_at",    latdflt,    &latstr, "Recovery rate across frequency",             InOutOption},
+ {  "reclimit_at", vdraindflt, &vdrainstr, "Limitation on recovery level",               InOutOption},
+ {     "times_at",  timesdflt,  &timesstr, "Oversampling of calculation of threshold",  OutputOption},
+ {     "times_at",  timesdflt,  &timesstr, "Oversampling of calculation of threshold",  SilentOption},
+ {"compensate_at",   compdflt,   &compstr, "Cochlea output compensation",               SilentOption},
+ {      "gain_at",    stxdflt,    &stxstr, "Adaptive thresholding output gain\n",        InOutOption},  /* CG */ 
+
+ {    "fibre_med",  fibredflt,  &fibrestr, "Spont-rate fibre type (medium, high)",       InOutOption},  /* CG */
+ {   "thresh_med", thresdflt,   &thresstr, "Haircell threshold shift (dB)",              InOutOption},  /* CG */
+ {     "gain_med", meddisdflt, &meddisstr, "Meddis haircell model output gain\n",        InOutOption},  /* CG */
+
+ ( char * ) 0 } ;
+
+static Source ThresholdEntry( source )                           /* CG: modified */
+Source source ;
+{
+    double density ;
+
+    if( OptionInt( chansstr ) == 0 )
+	density = OptionDouble( denstr ) ;
+    else 
+	density = OptionInt( chansstr ) / ( ErbScale( Freq( maxstr ) ) - ErbScale( Freq( minstr ) ) ) ;
+
+    if( strncmp( transstr, "off", 3 ) == 0 ) 
+        source = source ;
+
+    else {
+
+        if( strncmp( transstr, "med", 3 ) == 0 )
+            source = Meddis(  source, Frameheight(), Samplerate(), OptionDouble( meddisstr ) ) ;
+
+        else {
+	   compensate = OptionDouble( compstr ) ;
+
+	   source = NewProcessingSource(
+		         newCorti(
+		             Frameheight(), Samplerate(), frequencies, Erb,
+			     atof(  risestr ), atof(  latstr ) * density,
+			     atof( rapidstr ), atof( faststr ), atof( propstr ),
+			     log10( Scalar( vdrainstr ) ) * 2000.,
+			     (int) ( density * atof( latstr ) / Samplerate() + 1. ) * atoi( timesstr ),
+			     OptionDouble( stxstr )
+			 ), (void ( * )()) Corti, closeCorti,
+			 source,
+			 "model.c thresholding"
+		   ) ;
+
+         }
+    }
+    return ( source ) ;
+}
+
+/* modulation frequency image */
+
+static char stepmfdflt[] =   "250Hz", *stepmfstr = stepmfdflt ;
+static char  maxmfdflt[] =   "250Hz",  *maxmfstr =  maxmfdflt ;
+static char  minmfdflt[] =    "50Hz",  *minmfstr =  minmfdflt ;
+static char  denmfdflt[] =     "off",  *denmfstr =  denmfdflt ;
+
+#ifndef DSP32
+
+Source Mfsai( source, segment )                               /* CG */
+Source source ;
+int segment ;
+{
+    extern char *filestr ;
+    Source mfsource = FileNameSource( filestr ) ;
+    int frameheight = Frameheight() ;
+    int i ;
+
+    frequencies = GenerateCenterFrequencies( Freq( minmfstr ), Freq( maxmfstr ), OptionDouble( denmfstr ) ) ;
+    setFrameheight( NumberCenterFrequencies( Freq( minmfstr ), Freq( maxmfstr ), OptionDouble( denmfstr ) ) ) ;
+
+    mfsource = GenericEntry( mfsource, DoFilterShortDataArray ) ;
+   /*  mfsource = GenericEntry( mfsource, DoNewFilterDataArray ) ; */
+    mfsource = NewProcessingSource(
+		newCorti(
+		    Frameheight(), Samplerate(), frequencies, Erb,
+		    atof( risestr ), atof( latstr ) * OptionDouble( denmfstr ),
+		    atof( rapidstr ), atof( faststr ), atof( propstr ),
+		    log10( Scalar( vdrainstr ) ) * 2000., /* convert to millibells */
+		    (int) ( OptionDouble( denmfstr ) * atof( latstr ) / Samplerate() + 1. ) * atoi( timesstr ),
+		    0
+		), (void ( * )()) Corti, closeCorti,
+		mfsource,
+		"model.c thresholding"
+	    ) ;
+
+    return ( mfsource ) ;
+}
+
+#endif
+/***** long term adaptation  - not implemented - used to sneak in modulation frequency thing *****/
+
+static char   adapdflt[] =       "0",   *adapstr =   adapdflt ;
+
+static Source AdaptEntry( source )
+Source source ;
+{
+#ifndef DSP32
+    if( OptionDouble( denmfstr ) > 0 )
+	source = Mfsai( source ) ;
+#endif
+    return( source ) ;
+}
+
+/*********** [fba] [fea] stage: "adapted transduced filter output" *********/
+
+static  Option fbaopts[] = {
+
+ {   "mmincf_mfb",  minmfdflt,  &minmfstr, "Minimum modulation frequency (Hz)",         SilentOption},
+ {   "mmaxcf_mfb",  maxmfdflt,  &maxmfstr, "Maximum modulation frequency (Hz)",         SilentOption},
+ {   "mdencf_mfb",  denmfdflt,  &denmfstr, "Modulation filter density ",                SilentOption},
+ {   "stepcf_mfb", stepmfdflt, &stepmfstr, "Step between images\n",                     SilentOption},
+
+ {  "tadaptation",   adapdflt,   &adapstr, "Time constant of long term adaptation\n",   SilentOption},
+
+ ( char * ) 0 } ;
+
+
+
+/***** hard limiting *****/
+
+static char   harddflt[] =     "off",   *hardstr =   harddflt ;
+
+static Source HardEntry( source )
+Source source ;
+{
+    return( Saturate( source, hardstr ) ) ;
+}
+
+/*********** [fbh] [feh] stage: "hard limited filter output" **************/
+
+static  Option fbhopts[] = {
+
+ {   "hard_limit",   harddflt,   &hardstr, "Hardlimit firing rate before integration\n",OutputOption},
+ {   "hard_limit",   harddflt,   &hardstr, "Hardlimit firing rate before integration\n",SilentOption},
+
+ ( char * ) 0 } ;
+
+
+/***** [sgm,cgm,fbd,fbi] [fed,fei] stage: "integrated filter output" *******/
+
+/***** temporal integration *****/
+
+static char  stagedflt[] =     "off",  *stagestr =  stagedflt ;
+static char     updflt[] =     "8ms",     *upstr =     updflt ;
+static char   downdflt[] =       "1",   *downstr =   downdflt ;
+static char   lossdflt[] =       "1",   *lossstr =   lossdflt ;
+static char  vlossdflt[] =       "0",  *vlossstr =  vlossdflt ;
+static char  igaindflt[] =       "1",  *igainstr =  igaindflt ;
+
+static  Option fbiopts[] = {
+
+ {   "stages_idt",  stagedflt,  &stagestr, "Stages of integration",                      InOutOption},
+ {    "igain_idt",  igaindflt,  &igainstr, "Gain of integration stage\n",               OutputOption},
+ {    "igain_idt",  igaindflt,  &igainstr, "Gain of integration stage\n",               SilentOption},
+
+ {    "vloss_idt",  vlossdflt,  &vlossstr, "Rest level for loss",                       OutputOption},
+ {    "vloss_idt",  vlossdflt,  &vlossstr, "Rest level for loss",                       SilentOption},
+ {     "loss_idt",   lossdflt,   &lossstr, "Loss time constant",                        OutputOption},
+ {     "loss_idt",   lossdflt,   &lossstr, "Loss time constant",                        SilentOption},
+ {    "tdown_idt",   downdflt,   &downstr, "Downward time constant in ms",              OutputOption},
+ {    "tdown_idt",   downdflt,   &downstr, "Downward time constant in ms",              SilentOption},
+ {      "tup_idt",     updflt,     &upstr, "Low-pass filter time constant",              InOutOption},
+
+ ( char * ) 0 } ;
+
+static Source IntegralEntry( source )
+Source source ;
+{
+    return ( LowpassDataTypeSource( source, OptionInt( stagestr ), Frameheight(), Samples( upstr, Samplerate() ), Samples( downstr, Samplerate() ), Scalar( igainstr ) ) ) ;
+}
+
+
+/* downsampling */
+
+static char  downsdflt[] =     "off",  *downsstr =  downsdflt ;
+
+static Option dwnopts[] = {
+
+ { "downsample",   downsdflt, &downsstr,  "Downsampling over time",                    InOutOption},
+ { "frstep_epn",   downsdflt, &downsstr,  "Downsampling over time\n",                  InOutOption},
+
+ (char *) 0 } ;
+
+static Source DownSampleEntry( source )
+Source source ;
+{
+    int spacing = Samples( downsstr, Samplerate() ) ;
+    int channels = Frameheight() * Framewidth() ;
+
+    if( spacing != 0 ) {
+
+#if defined( PC ) || defined( DSP32 )
+	source = NewSegmentingSource( source, Frameheight() * Framewidth() * sizeof ( DataType ) * 4 ) ;
+#endif
+
+	if( spacing > 0 )
+	    source  = DownSampleSource( source, spacing, channels ) ;
+	else {
+	    spacing = -spacing ;
+	    source = BlockSampleSource( source, spacing, channels ) ;
+	}
+
+	setFramestep( spacing ) ;
+
+	setFrames( Frames() / spacing ) ;
+    }
+
+    return( source ) ;
+}
+
+
+/* stabilised image defaults */
+
+static char   llimdflt[] = "1.5c"     ,         *llimstr = llimdflt   ;
+static char   ulimdflt[] = "24ms"     ,         *ulimstr = ulimdflt   ;
+
+static char    saidflt[] = "1"        ,          *saistr = saidflt    ;
+#ifdef PC
+static char pwidthdflt[] = "20ms"     ,       *pwidthstr = pwidthdflt ;
+#else
+static char pwidthdflt[] = "35ms"     ,       *pwidthstr = pwidthdflt ; /* roy 23-12-92 */
+#endif
+/* static char nwidthdflt[] = "-5ms"     ,       *nwidthstr = nwidthdflt ; roy 23-12-92 */
+
+static char  ltlimdflt[] = "150Hz"    ,        *ltlimstr = ltlimdflt  ;
+static char  utlimdflt[] = "20Hz"      ,        *utlimstr = utlimdflt ;
+static char  decaydflt[] = "30ms"     ,        *decaystr = decaydflt  ;
+static char    cgmdflt[] = "2.5"     ,          *cgmstr = cgmdflt    ; /* 30ms > 1.25 roy 23-12-92 */
+static char     ttdflt[] = "5"       ,           *ttstr = ttdflt     ; /* 8ms > 10 roy 23-12-92 */
+
+static char   sustdflt[] = "0"      ,     *susthreshstr  = sustdflt   ;
+
+static char     swdflt[] = "off"    ,            *swstr  = swdflt     ;
+
+#ifdef PC
+static char   stepdflt[] = "15.25ms"  ,         *stepstr = stepdflt    ;
+#else
+static char   stepdflt[] = "16ms"  ,         *stepstr = stepdflt    ;
+#endif
+
+/* spiral parameters */
+
+static char   zerodflt[] = "off"      ,         *zerostr = zerodflt    ;
+static char   formdflt[] = "arch"     ,         *formstr = formdflt    ;
+static char   origdflt[] = "3.072"    ,         *origstr = origdflt    ;
+
+static char       ArchStr[] =              "arch" ;
+static char        LogStr[] =               "log" ;
+
+static char   expodflt[] =  "off"     ,         *expostr = expodflt ;
+
+/*********** [spl,sai] [sie] stage: "stabilized auditory image" ************/
+
+static  Option saiopts[] = {
+
+ {   "frstep_aid",   stepdflt,   &stepstr,  "Step between frames of the auditory image (ms)",InOutOption},
+ {   "pwidth_aid", pwidthdflt, &pwidthstr,  "Positive width of auditory image  (ms)",    InOutOption},
+ {   "nwidth_aid", nwidthdflt, &nwidthstr,  "Negative width of auditory image (ms)",   InOutOption},
+
+ {     "form_spd",   formdflt,   &formstr,  "Form of spiral: Archemedian or log",        InputOption},
+ { "zeroline_spd",   zerodflt,   &zerostr,  "Draw zero axis of spiral",                  InOutOption},
+ {     "orig_spd",   origdflt,   &origstr,  "Spiral rotation and circuit removal\n",     InOutOption},
+
+ {  "napdecay_ai",    cgmdflt,    &cgmstr,  "Neural activity decay rate in %/ms",        InOutOption},
+ {   "stdecay_ai",     ttdflt,     &ttstr,  "Strobe-threshold decay rate in %/ms",       InOutOption},
+ {"stcrit_ai",   susldflt, &suslevelstr,"Strobe criterion (1 to 5) ",  InOutOption},
+ {"stlag_ai" ,  stlagdflt, &stlagstr,   "Auditory image strobe lag time (in ms)",      InOutOption},
+ {   "stthresh_ai",   sustdflt, &susthreshstr, "Strobe threshold set to all points above this", SilentOption},
+ {     "decay_ai",  decaydflt,  &decaystr,  "Auditory image decay time constant",      InOutOption},
+ {      "stinfo_ai",     swdflt,     &swstr,  "Strobe information (off, on, filename)\n",  InOutOption},   
+
+ {    "utrate_ai",  utlimdflt,  &utlimstr,  "Disconnected in R5.6",                      SilentOption},
+ {    "ltrate_ai",  ltlimdflt,  &ltlimstr,  "Disconnected in R5.6",                      SilentOption}, 
+ {     "ulim_sas",   ulimdflt,   &ulimstr,  "Upper integration limit for auditory image",   SilentOption},
+ {     "llim_sas",   llimdflt,   &llimstr,  "Lower integration limit for auditory image\n", SilentOption},
+ 
+ { "exponential_decay"  ,   expodflt,     &expostr , "Exponential trigger Decay", SilentOption},   
+
+ ( char * ) 0 } ;
+
+/* generate Stabilised image in image.c */
+
+static Source SaiEntry( source )                                   /* CG */
+Source source ;
+{
+    int framestep   = Samples( stepstr,   Samplerate() ) / Framestep() ;
+    int pwidth      = Samples( pwidthstr, Samplerate() ) / Framestep() ;
+    int nwidth      = Samples( nwidthstr, Samplerate() ) / Framestep() ;
+    int stlag       = Samples( stlagstr,  Samplerate() ) / Framestep() ;
+
+
+    /* Convert arguments for spiral drawing. See spiral.ch */
+
+#ifndef DSP32
+    if      (strncmp(formstr, ArchStr, strlen( formstr) ) == 0)    form_spl = 'A';
+    else if (strncmp(formstr,  LogStr, strlen( formstr) ) == 0)    form_spl = 'L';
+    else stitch_error("gensai: unknown form_spl\n");
+
+    axis_spl      = OptionInt(    zerostr ) ;
+    zero_spl      = OptionDouble( origstr ) ;
+#endif
+
+    /* Hack so that spirals never include transient info.  */ 
+     if (strncmp(whichstr,"spl", strlen("spl")) == 0) 
+       { nwidth=0; 
+         if ( (int)atoi(suslevelstr)>=4)
+            suslevelstr="3";
+/*         if ( (int)atoi(suslevelstr)>=4) 
+            pwidth+=stlag; 
+          else
+            stlag=0; */
+       }
+    /* Hack so that sas and sep have pwidth=max(ulim) and nwidth=min(llim) */
+
+    if ( strcmp(whichstr, "sas") == 0 || strcmp(whichstr, "sep") == 0 ) {
+	pwidth = Cycles( ulimstr, frequencies[0], Samplerate() ) ;
+	nwidth = Cycles( llimstr, frequencies[0], Samplerate() ) ;
+	if (nwidth > 0) nwidth=0;
+    }
+
+    /* Check ranges of pwidth and nwidth, and quit if invalid */
+    if (pwidth < 0)
+	stitch_error("Warning: gensai  pwidth_aid  should be positive\n");
+    if (nwidth > 0)
+	stitch_error("Warning: gensai  nwidth_aid  should be zero or negative\n");
+
+    /* nwidth is given as a -ve value, but is used internally as +ve */
+    nwidth = -(nwidth);
+
+    source = Sai( source,  Frameheight(),  framestep,  pwidth,  nwidth,
+		  (int)Samples(decaystr, Samplerate())/Framestep(),
+		  (int)Samplerate(),  frequencies,
+		  (double)atof(ttstr),
+		  Samples(cgmstr,Samplerate())/Framestep(),
+		  (int)Freq(utlimstr),  (int)Freq(ltlimstr), (int)atoi(suslevelstr),
+                  susthreshstr, swstr, expostr, stlag);
+
+    setFramewidth( pwidth+nwidth ) ;
+    setFramestep( framestep ) ;
+    setFrames( Frames()/framestep ) ;
+
+    return( source ) ;
+}
+
+DelayAxis( min, max, label )
+double *min, *max ;
+char **label ;
+{
+    *min = -Samples( pwidthstr, Samplerate() ) / Samplerate() * 1000. ;
+    *max = -Samples( nwidthstr, Samplerate() ) / Samplerate() * 1000. ;
+
+    *label = "Integration Interval [ms]" ;
+}
+
+
+
+#if 0 /* where did this come from? */
+/* table of default model options */
+
+static char   llimdflt[] =    "3.5",    *llimstr =   llimdflt ;
+static char   ulimdflt[] = "imagedurn", *ulimstr =   ulimdflt ;
+static char    saidflt[] =    "0.25",    *saistr =    saidflt ;
+/* static char   susldflt[] = "1",     *suslevelstr =    susldflt ;  AJD 13-3-95
+   static char   sustdflt[] = "0",    *susthreshstr =    sustdflt; */
+#endif
+
+
+
+/*********** [sas] [sse] stage: "stabilized auditory spectrogram" **********/
+
+/* summarise spectrogram by adding across rows */
+
+static  Option sasopts[] = {
+
+ ( char * ) 0 } ;
+
+static Source SummaryEntry( source )                             /* CG */
+Source source ;
+{
+    source = Summary( source, Frameheight(), Scalar( saistr ), frequencies, Samplerate(), llimstr, ulimstr ) ;
+
+    setFramewidth( 1 ) ;
+
+    return( source ) ;
+}
+
+#if defined(DSP32) || defined( THINK_C )
+static void swab( in, out, bytes )
+char *in, *out ;
+int bytes ;
+{
+    register int i ;
+
+    for( i=0 ; i<bytes ; i+=2 ) {
+	out[i+1] = in[i] ;
+	out[i] = in[i+1] ;
+    }
+
+    return ;
+}
+#endif
+
+static void swab_callback( state, bytes, buffer, end, input )
+Source state ;
+ByteCount *bytes ;
+DataType *buffer, *end, *input ;
+{
+    extern void swab() ;
+
+    swab( (char *) input, (char *) buffer, *bytes ) ;
+
+    return ;
+}
+
+static Source SwabEntry( source )
+Source source ;
+{
+    return ( NewSimpleProcessingSource( swab_callback, source, "model.c byte swapping" ) ) ;
+}
+
+struct _test_state { struct _fillable_source parent ; Source source ; unsigned chans ; } ;
+
+static Pointer test_callback( state, bytes, buffer )
+struct _test_state *state ;
+ByteCount *bytes ;
+DataType *buffer ;
+{
+    register DataType input ;
+    register DataType *optr = buffer ;
+    register Pointer eptr = (Pointer) buffer + *bytes ;
+    register int last = *bytes == 0 ;
+    register int chan ;
+
+    while( (Pointer) optr < eptr ) {
+
+	input = *PullItems( state->source, 1, DataType ) ;
+
+	for( chan=0 ; chan<state->chans ; chan++ )
+		*optr++ = input ;
+    }
+
+    if( !last )
+	return ( (Pointer) buffer ) ;
+    else
+	return ( DeleteFillableSource( state ) ) ;
+}
+
+static Source TestEntry( source )
+Source source ;
+{
+    DeclareNew( struct _test_state *, state ) ;
+
+    state->source = source ;
+    state->chans  = Frameheight() ;
+
+    return( SetFillableSource( state, test_callback, "test model.c" ) ) ;
+}
+
+/********************* Option defaults (application specific) ***************
+* Each application may have its own set of option defaults.
+* These override the generic defaults defined for each option, when the
+* options table is constructed, (see constructOptions()).
+* Note that options must have their full names. Abbreviations won't do here.
+****************************************************************************/
+
+/* Wave and excitation pattern modules */
+
+#ifndef DSP32
+static char zerobotstr[]   = "bottom=0" ;
+static char excitestr[]    = "view=excitation" ;
+static char nohiding[]     = "hiddenline=off" ;
+static char downsample[]   = "downsample=10ms" ;
+static char turn_on_idt[]  = "stages_idt=2" ;
+static char mincfdflt[]    = "mincf_afb=50" ;
+static char maxcfdflt[]    = "maxcf_afb=5000" ;
+static char chandflt[]     = "channels_afb=128" ;
+static char lengthdflt[]   = "length=32ms"  ;
+static char greyscalestr[] = "view=greyscale" ;
+#endif
+
+char *wavdflts[] = {
+#ifndef DSP32
+		     "view=wave",
+#endif
+		      (char *)0 } ;
+
+char *stpdflts[] = {                                             /* CG */
+#ifndef DSP32
+		     "view=wave",
+                     "filter=off",
+#endif
+		      (char *)0 } ;
+
+char *asadflts[] = {
+#ifndef DSP32
+		     excitestr,
+		     "top=2500",               zerobotstr,
+		     nohiding,
+		     chandflt,                                   /* CG */
+		     "transduction=off",                         /* CG */
+		     turn_on_idt,                                /* CG */
+		     downsample,                                 /* CG */
+#endif
+		      (char *)0 } ;
+
+char *epndflts[] = {
+#ifndef DSP32
+		     excitestr,
+		     "top=1000",                zerobotstr,      /* CG */
+		     nohiding,
+		     chandflt,                                   /* CG */
+		     turn_on_idt,
+		     downsample,
+#endif
+		      (char *)0 } ;
+
+char *sepdflts[] = {
+#ifndef DSP32
+		     excitestr,
+		     "top=200",                zerobotstr,
+		     nohiding,
+		     chandflt,                                   /* CG */
+		     "ulim_sas=16ms",          "llim_sas=-4ms",
+#endif
+		      (char *)0 } ;
+
+/* Auditory (ie landscape) modules */
+
+char *bmmdflts[] = {
+#ifndef DSP32
+		     lengthdflt,
+		     "top=100",                "bottom=-100",
+#endif
+		      (char *)0 } ;
+
+char *napdflts[] = {
+#ifndef DSP32
+		     lengthdflt,
+		     "top=2000",                zerobotstr,      /* CG */
+		     chandflt,                                   /* CG */
+		     "stages_idt=2",
+		     "tup_idt=0.133ms",
+		     "downsample=1p",
+#endif
+		      (char *)0 } ;
+
+
+char *saidflts[] = {
+#ifndef DSP32
+		     "top=500",                zerobotstr,       /* CG */
+		     "stages_idt=2",
+		     "tup_idt=0.133ms",
+		     "downsample=1p",
+		     "frstep_epn=1p",
+#endif
+		      (char *)0 } ;
+
+char *spldflts[] = {
+#ifndef DSP32
+		     "view=spiral",
+#ifdef PC
+		     "width_win=300",          "height_win=300",
+#else
+		     "width_win=500",          "height_win=500",
+#endif
+                     "box_ps=off",                 /* MAA 6/9/1995 */
+                     "figurelinewidth_ps=0.25",    /* MAA 6/9/1995 */
+		     "top=26",                 "bottom=25",
+		     "dencf=1",                 "pen=2", 
+		     "nwidth_aid=0ms",           "pwidth_aid=35ms",
+                     "stlag=5ms",                "stcrit=5",  /* AJD */
+#endif
+		      (char *)0 } ;
+
+/* Speech (ie greyscale) modules */
+
+char *sgmdflts[] = {
+#ifndef DSP32
+		     greyscalestr,
+		     "top=2500",               zerobotstr,
+		     chandflt,                                   /* CG */
+		     "transduction=off",                         /* CG */
+		     turn_on_idt,
+		     downsample,
+#endif
+		      (char *)0 } ;
+
+char *cgmdflts[] = {
+#ifndef DSP32
+		     greyscalestr,
+		     "top=1000",                zerobotstr,      /* CG */
+		     chandflt,                                   /* CG */
+		     turn_on_idt,
+		     downsample,
+#endif
+		      (char *)0 } ;
+
+char *sasdflts[] = {
+#ifndef DSP32
+		     greyscalestr,
+		     "top=300",                zerobotstr,       /* CG */
+		     chandflt,                                   /* CG */
+		     "stages_idt=off",
+		     "frstep_epn=off",
+		     "downsample=off",
+		     "ulim_sas=16ms",          "llim_sas=-4ms",
+#endif
+		      (char *)0 } ;
+
+
+
+/******************************* stage table ********************************
+*
+* The "stages" are application names.
+* A stage identifier name is the last three chars of the program name.
+*    (Eg "sai" is the stage identifier for the stabilized auditory image
+*     application, which is a program called "gensai". This is an alias for
+*     the "gen" program, provided by one of the set of symbolic links).
+* The stages are grouped into "models" (each an array of structs below):
+*     envelope: calculation of the envelope of the underlying function.
+*     fine:     calculation of the whole ("fine structure") of the function.
+*     complex
+*     nonmult
+*     noncalc
+*
+* FindStage( which )  - find a place in the stage table for the program goal.
+* Take a stage identifier, (contained in the "which" string), and return a ptr
+* to the corresponding stage structure, (one line of one of the arrays below).
+*
+* The returned goal stage is the final processing stage of the sequence of
+* stages which make up the program.
+* The sequential order of processing is dictated by the stage table.
+* The sequence of stages is from the first stage (texually at the bottom of
+* each "model" group in the stage table), through each stage back up the table
+* to the goal stage.
+*
+* The stage structure (defined below) is as follows:
+*     struct _stage {
+*         char    *ident    ;       Stage identifier name
+*         Source (*entry)() ;       Pointer to function for entry to stage
+*         Option  *options  ;       Model options for stage (see table.c)
+*         char   **defaults ;       Option defaults for stage (see gen.c)
+*         char    *help     ;       Description of stage
+*     };
+*
+* For example, the sai stage (found when gensai is asked for) is:
+*     "sai",  SaiEntry,  saiopts,  saidflts,  "stabilized auditory image",
+*
+* The stage struct fields are:
+*
+*  *ident
+* Stage identifier name used by FindStage() to match a stage struct to the
+* application. The stage is found by matching the ident string against those
+* stored in the model arrays of stages. The default stage is "wav".
+*
+*  (*entry)()
+* The name of the entry-point function for the stage. Most entry-point
+* functions are defned in model.c. The entry-point function name is only
+* accessed by a call to FindStage() from ModeledSource() in gen.c.
+*
+*  *options
+* The options field of a stage is used by the constructOptions() routine
+* to include the model options for that stage in the complete options table
+* which it constructs. This is composed of the display options, (which are
+* common to all applications, and are listed in array displayopts[] in gen.c),
+* the model options for the stage, (which are listed in table.c), AND all the
+* model options given for each of the stages back to the start stage, (at the
+* bottom of the stage table, within a model group of stages).
+*
+*  **defaults
+* The defaults field is used by the constructOptions() routine to override the
+* defaults defined for the options which have been included in the complete
+* options table. The reason for this is so that each application can have its
+* own set of option defaults, if necessary. (If defaults are not given
+* or the set is not complete, then the original defaults still apply).
+* The defaults fields contain option defaults which override the generic
+* defaults defined for each option.
+* After the complete options table has been constructed, (constructOptions()),
+* all options in the table will be:
+* a) initialized to their default values (in getnopts()).
+* b) re-initialized by any corresponding options in "rc" files.
+* c) displayed as a help menu (if asked for).
+*
+*  *help
+* This message is printed at the top of the help menu. The help field is only
+* accessed by modelHelp(which), called from gen.c, which takes a stage
+* identifier and returns the "help" string of the stage struct which has a
+* matching ident field, to assign it to "helpstring".
+*
+*
+* Its important to note that the options field refers to model options, and
+* these are cumulative over the sequential stages of processing.
+* The defaults field refers to the defaults to be used for the goal stage
+* only, (ie the application), and these are not cumulative.
+* The complete options table (constructed at run time) consists of the display
+* options, and the accumulated model options (one group per processing stage).
+*
+* The NullEntry routine is a dummy which does no processing, and is used to
+* introduce aliases into the stage sequence.
+*
+* Routines which call FindStage(), and access the stage table:
+*
+*                               main()
+*                                 |
+*          +----------------------+-----------------+
+*          |                      |                 |
+*          |                      |                 |
+*  constructOptions()       ModeledSource()     modelHelp()
+*          |                      |                 |
+*          |                      |                 |
+*          +----------------------+-----------------+
+*                                 |
+*                             FindStage()
+*
+****************************************************************************/
+
+
+#define NO_OPTS     (Option *) 0
+#define NO_DFLTS    (char **)  0
+
+struct _stage *FindStage( which )
+char *which ;
+{
+    static struct _stage envelope[] = {
+	"sse",    SummaryEntry, sasopts,    sasdflts,   "stabilized auditory spectrogram",
+	"sie",        SaiEntry, saiopts,    saidflts,   "stabilized auditory image",
+	"sem",       NullEntry, NO_OPTS,    NO_DFLTS,   "spectrogram",
+	"fed", DownSampleEntry, dwnopts,    NO_DFLTS,   "downsampled filter envelope",
+	"fei",   IntegralEntry, fbiopts,    NO_DFLTS,   "integrated filter envelope",
+	"feh",       HardEntry, fbhopts,    NO_DFLTS,   "hard limited filter envelope",
+	"fea",      AdaptEntry, fbaopts,    NO_DFLTS,   "adapted filter envelope",
+	"fet",  ThresholdEntry, fbtopts,    NO_DFLTS,   "thresholded filter envelope",
+	"fel",    LowpassEntry, fblopts,    NO_DFLTS,   "low-pass filtered filter envelope",
+	"fes",   SaturateEntry, fbsopts,    NO_DFLTS,   "saturated filter envelope",
+	"feu", UncompressEntry, fbuopts,    NO_DFLTS,   "uncompressed filter envelope",
+	"fec",   EnvelopeEntry, fbcopts,    NO_DFLTS,   "compressed filter envelope",
+	"fem",       NullEntry, fbmopts,    NO_DFLTS,   "dummy entry to get options through",
+	"wav",       NullEntry, wavopts,    wavdflts,   "picture of wave",
+	( char * ) 0 } ;
+
+    static struct _stage fine[] = {
+	"sep",       NullEntry, NO_OPTS,    sepdflts,   "stabilized excitation pattern",
+	"sas",    SummaryEntry, sasopts,    sasdflts,   "stabilized auditory spectrogram",
+	"spl",       NullEntry, NO_OPTS,    spldflts,   "spiral stabilized auditory image",
+	"sai",        SaiEntry, saiopts,    saidflts,   "stabilized auditory image",
+	"sgm",       NullEntry, NO_OPTS,    sgmdflts,   "spectrogram",
+	"cgm",       NullEntry, NO_OPTS,    cgmdflts,   "cochleogram",
+	"nap",       NullEntry, NO_OPTS,    napdflts,   "neural activity pattern",
+	"asa",       NullEntry, NO_OPTS,    asadflts,   "auditory spectral analysis",
+	"epn",       NullEntry, NO_OPTS,    epndflts,   "excitation pattern",
+	"fbd", DownSampleEntry, dwnopts,    NO_DFLTS,   "downsampled filter output",
+	"fbi",   IntegralEntry, fbiopts,    NO_DFLTS,   "integrated filter output",
+	"fbh",       HardEntry, fbhopts,    NO_DFLTS,   "hard limited filter output",
+	"fba",      AdaptEntry, fbaopts,    NO_DFLTS,   "adapted transduced filter output",
+	"fbt",  ThresholdEntry, fbtopts,    NO_DFLTS,   "thresholded filter output",
+	"fbl",    LowpassEntry, fblopts,    NO_DFLTS,   "low-pass filtered filter output",
+	"fbs",   SaturateEntry, fbsopts,    NO_DFLTS,   "saturated filter output",
+	"fbu", UncompressEntry, fbuopts,    NO_DFLTS,   "uncompressed filter output",
+	"fbc",        LogEntry, fbcopts,    NO_DFLTS,   "compressed filter output",
+	"fbr",    RectifyEntry, fbropts,    NO_DFLTS,   "rectified filter output",
+	"fbm",       NullEntry, NO_OPTS,    NO_DFLTS,   "auditory filter output",           /* CG */
+        "stp",       FineEntry, fbmopts,    stpdflts,   "stapes vibration output",          /* CG */
+	"wav",       NullEntry, wavopts,    wavdflts,   "picture of wave",
+	( char * ) 0 } ;
+
+    static struct _stage complex[] = {
+	"fcp",      PolarEntry, NO_OPTS,    NO_DFLTS,   "polar co-ordinate complex output",
+	"fcr",    ComplexEntry, fbmopts,    NO_DFLTS,   "rectangular co-ordinate complex output",
+	"wav",       NullEntry, wavopts,    wavdflts,   "picture of wave",
+	( char * ) 0 } ;
+
+    static struct _stage nonmult[] = {
+	"bmm",       NullEntry, NO_OPTS,    bmmdflts,   "basilar membrane motion",          /* CG */
+        "stp",       FineEntry, fbmopts,    stpdflts,   "stapes vibration output",          /* CG */
+	"wav",       NullEntry, wavopts,    wavdflts,   "draw wave",
+	( char * ) 0 } ;
+
+    static struct _stage noncalc[] = {
+	"tst",       TestEntry, NO_OPTS,    NO_DFLTS,   "Test system",
+	"wav",       NullEntry, wavopts,    wavdflts,   "draw wave",
+	( char * ) 0 } ;
+
+    static struct _stage *models[] = { envelope, fine, complex, nonmult, noncalc, ( struct _stage * ) 0 } ;
+
+    struct _stage *stage ;
+    int model ;
+
+    /* for each type of model */
+    for( model=0 ; models[ model ] != ( struct _stage * ) 0 ; model++ )
+	/* for each stage in the model */
+	for( stage=models[ model ] ; stage->ident != ( char * ) 0 ; stage++ )
+	    if( strncmp( which, stage->ident, strlen( stage->ident ) ) == 0 ) {
+
+		/* kludge to fix bug (see fixchans routine below) */
+		if ( strcmp( which, "nap" ) == 0 )
+		    fixchans( stage->defaults ) ;
+
+		return ( stage ) ;
+	    }
+
+    return ( FindStage( "wav" ) ) ;
+}
+
+/* Return the "help" string for the given stage identifier */
+/* This routine is called once from gen.c:main()           */
+char *modelHelp( which )
+char *which ;
+{
+    return( FindStage( which )->help ) ;
+}
+
+
+/*
+This routine is a hack to fix a bug we caused earlier!
+We changed the order of entry points in Findstage, so that nap was able
+to use the lp filter. But this caused nap to inherit the defaults of all
+the other entry points which use that filter. In particular, the number of
+channels for nap was changed as a result of this. This hack is designed to
+restore the number chans, in the case of gennap only, to their default
+value.
+*/
+
+fixchans( str )
+char **str ;
+{
+    while ( *str != (char *)0 ) {
+	if ( strncmp( *str, "channels_afb", 12 ) == 0 ) {
+	    strcpy( (*str)+13, chansdflt ) ;
+	/*    fprintf(stderr, "fixchans: %s\n", *str ) ;        */
+	    break ;
+	}
+	*str++ ;
+    }
+}
+
+
+/*********************** Strings for use in DSP version ********************/
+
+#if defined(DSPHOST) || defined(DSP32)
+#if 00
+char **shared[] = { &llimstr,       &ulimstr,        &saistr,       &pwidthstr,
+		    &nwidthstr,     &ltlimstr,       &utlimstr,     &ttstr,
+		    &cgmstr,        &decaystr,       &stepstr,      &downsstr,
+		    &stagestr,      &upstr,          &downstr,      &lossstr,
+		    &vlossstr,      &igainstr,       &hardstr,      &adapstr,
+		    &timesstr,      &vdrainstr,      &propstr,      &faststr,
+		    &latstr,        &rapidstr,       &risestr,      &stxstr,
+		    &lstagestr,     &lupstr,         &ldownstr,     &llossstr,
+		    &lvlossstr,     &ligainstr,      &meddisstr,    &satstr,
+		    &logstr,        &rectstr,        &qualstr,      &limitstr,
+		    &interpstr,     &minstr,         &maxstr,       &denstr,
+		    &chansstr,      &orderstr,       &phasestr,     &gainstr,
+		    &audiostr,      &floatstr,       &samplestr,    &bitstr,
+		    &envstr,        &whichstr,       &framesstr,    &framebytesstr,
+		    &framewidthstr, &frameheightstr, &framestepstr,
+		    ( char ** ) 0 } ;
+#endif
+char **returned[] = { &framesstr,      &framebytesstr,  &framewidthstr,
+		      &frameheightstr, &framestepstr,
+		      ( char ** ) 0 } ;
+
+#endif
+
+
+/******* support for DSP32 C ******************/
+
+#ifdef DSP32
+void receiveParameters( parameters, psize )
+char *parameters ;
+short psize ;
+{
+    struct _stage *stage = FindStage( "sas" ), *sptr ;
+    char *bptr ;
+    int c ;
+
+    for( sptr = stage ; sptr->ident != (char *) 0 ; sptr++ )
+	;
+
+    sptr-- ;
+
+    for( bptr = parameters ; bptr < parameters + psize ; sptr-- )
+	if( sptr->options != (Option *) 0 )
+	    for( c=0 ; sptr->options[c].name != (char *) 0 ; c++ ) {
+		*(sptr->options[c].value) = bptr ;
+		bptr += strlen( bptr ) + 1 ;
+	    }
+
+    return ;
+}
+#endif
+
+#ifdef DSPHOST
+#include "utils.h"
+#define  DSP_BIN_VAR     "DSPBIN"
+#define  DEFAULT_DSP_BIN "c:\\bin\\dspmain"
+extern char *getenv() ;
+
+void sendParameters( which )
+char *which ;
+{
+    register struct _stage *stage = FindStage( which ), *sptr ;
+    unsigned c, bytes = 0 ;
+    char *buffer, *bptr ;
+    long paddr, baddr ;
+
+    for( sptr = stage ; sptr->ident != (char *) 0 ; sptr++ )
+	if( sptr->options != (Option *) 0 )
+	    for( c=0 ; sptr->options[c].name != (char *) 0 ; c++ )
+		bytes += strlen( *(sptr->options[c].value) ) + 1 ;
+
+    sptr-- ;
+
+    buffer = Allocate( bytes, "argument array model.c" ) ;
+
+    for( bptr = buffer ; sptr >= stage ; sptr-- )
+	if( sptr->options != (Option *) 0 )
+	    for( c=0 ; sptr->options[c].name != (char *) 0 ; c++ ) {
+		(void) strcpy( bptr, *(sptr->options[c].value) ) ;
+		bptr += strlen( bptr ) + 1 ;
+	    }
+
+
+    paddr = find_label_name( "psize" ) ;
+
+    dsp_dl_int( paddr, (int) ( bptr - buffer ) ) ;
+
+    baddr = find_label_name( "params" ) ;
+
+    while( dsp_up_long( baddr ) == 0 )
+	;
+
+    dsp_dl_bytes( deref( baddr ), (long) ( bptr - buffer ), buffer ) ;
+
+    dsp_dl_int( paddr, 0 ) ;
+
+    return ;
+}
+
+
+struct _dsp_state { unsigned long needed_addr, output_addr, errno_addr ; } ;
+
+static void dsp_callback( state, bytes, buffer )
+struct _dsp_state *state ;
+ByteCount bytes ;
+Pointer buffer ;
+{	
+    char errbuff[200] ;
+	
+    /* tell dsp how much you want */
+
+    dsp_dl_int( state->needed_addr, bytes ) ;
+
+    /* wait for it to provide it */
+
+    while( dsp_up_int( state->needed_addr ) != 0 )
+	if( dsp_up_int( state->errno_addr ) != 0 ) {
+/*
+	    if( dispw != ( WindowObject ) 0 ) Close( dispw ) ;
+*/
+	    dsp_up_bytes( find_label_name( "errstr" ), (long) sizeof ( errbuff ), errbuff ) ;
+	    printf( "freemem %ld stackmax %lx\n",
+		dsp_up_long( find_label_name( "freemem"  ) ),
+		dsp_up_long( find_label_name( "stackmax" ) ) ) ;
+	    stitch_error( errbuff, dsp_up_int( find_label_name( "errno" ) ) ) ;
+     	}
+    
+    /* upload it into PC buffer */
+
+    dsp_up_bytes( deref( state->output_addr ), (long) bytes, buffer ) ;
+
+    return ;
+}
+
+Source DspSource( source )
+Source source ;
+{
+    DeclareNew( struct _dsp_state *, state ) ;
+    unsigned long addr ;
+    char errbuff[200] ;
+    char ***param ;
+    char *binary_path = getenv( DSP_BIN_VAR ) ;
+
+    if( binary_path == ( char * ) 0 )
+	binary_path =  DEFAULT_DSP_BIN ;
+
+    /* load dsp */
+
+    (void) fprintf( stderr, "Downloading %s to DSP32 at i/o addres 0x%x\n", binary_path, default_addr() ) ;
+
+    if( dsp_dl_exec( binary_path ) == 0 )
+	stitch_error( "\nDSP load failed\n" ) ;
+
+    /* start dsp */
+
+    dsp_run() ;
+
+    /* send parameters down to model */
+
+    sendParameters( whichstr ) ;
+
+    /* send down input if required */
+
+    if( whichstr[0] != 'i' ) {
+    	
+	addr = find_label_name( "input" ) ;
+
+	while( dsp_up_long( addr ) == 0 )
+	    ;
+
+	(void) fprintf( stderr, "Downloading input file of %ld points to dsp addres 0x%lx\n", Frames(), deref( addr ) ) ;
+
+	dsp_dl_array( deref( addr ), Frames(), PullInts( source, Frames() ) ) ;
+    }
+
+    /* wait for model setup */
+
+    state->needed_addr = find_label_name( "needed" ) ;
+    state->output_addr = find_label_name( "output" ) ;
+    state->errno_addr  = find_label_name( "errno"  ) ;
+
+    addr = find_label_name( "source" ) ;
+
+    while( dsp_up_long( addr ) == 0l && dsp_up_int( state->errno_addr ) == 0 )
+	(void) fprintf( stderr, "Waiting for dsp (status:%d)\r", dsp_up_long( addr ) ) ;
+      
+    if( dsp_up_int( state->errno_addr ) != 0 ) {
+	dsp_up_bytes( find_label_name( "errstr" ), (long) sizeof ( errbuff ), errbuff ) ;
+	(void) fprintf( stderr, "dsp error: %s\n", errbuff ) ;
+	stitch_error( "so there" ) ;
+    }
+
+    (void) fprintf( stderr, "DSP setup (source=0x%lx)\n", dsp_up_long( addr ) ) ;
+
+    addr = find_label_name( "returned" ) ;
+
+    for( param=returned ; *param != ( char ** ) 0 ; param++ ) {
+
+	dsp_up_bytes( deref( deref( addr ) ), RETURN_SIZE, **param ) ;
+	addr += 4 ;
+    }
+#if 0
+    fprintf( stderr, "Frames %ld - %d %d %d\n\nType Return\n", Frames(), Frameheight(), Framewidth(), Framebytes() ) ;
+    getchar() ;
+#endif
+    return ( stdAutoSource( ( Pointer ) state, dsp_callback ) ) ;
+}
+
+#endif
+
+/***************************************************************************
+* ModeledSource()
+* Called from main() in gen.c to initialize a chain of objects which will
+* ultimately execute the program, (see also SinkSource() in gen.c:main).
+*
+* The routine ModeledSource() first uses Findstage() to find the appropriate
+* place in the stage table, called for by the program, (and indicated by
+* "whichstr", the last three chars of the program's name).
+* Then it finds the end of the table, and works back up to the stage called
+* for by the program.
+* At each stage, call the corresponding entry-point function, (provided it's
+* not a null pointer), to create and initialize a source object.
+* (Each stage in the table is a process on the way to the program as a whole.
+* The order of the stage table sets the order of processing).
+*
+* The "check" argument is used when the "useprevious" option is on,
+* (see main() and checkForFile() in gen.c), otherwise it will be a null ptr.
+***************************************************************************/
+
+Source ModeledSource( source, check )
+Source source ;
+Source (*check)() ;
+{
+    /* Find the place in the stage table called for by the program */
+    register struct _stage *sptr, *stage = FindStage( whichstr ) ;
+    Source stmp ;
+
+#if !defined( DSP32 ) && !defined( THINK_C )
+    if( OptionInt( swapstr ) != 0 )
+	source = SwabEntry( source ) ;
+#endif
+
+#ifdef DSPHOST
+    if( getenv( "DSP32" ) != ( char * ) 0 )
+	return ( DspSource( source ) ) ;
+    else
+	(void) fprintf( stderr, "Not using DSP card\n" ) ;
+#endif
+
+    if( stage->entry == ( Source ( * )() ) 0 )
+	return ( source ) ;
+#if 00
+    /* Set frameheight (channels) and centre-frequencies array */
+    updateFrequencies() ;
+#endif
+
+#ifdef FLOAT
+    source = ShortFloatSource( source ) ;
+#endif
+
+    /* Find the end of the stage table */
+    for( sptr = stage ; sptr->ident != ( char * ) 0 ; sptr++ )
+	;
+
+    /* Work back up the stage table to the stage called for by the program */
+    /* At each stage, call the entry-point function (if it's not null)     */
+    while( sptr-- > stage ) {
+
+	if( sptr->entry != (Source ( * )()) 0 )
+	    source = sptr->entry( source ) ;
+
+	if( check != ( Source ( * )() ) 0 ) {
+	    stmp = check( sptr->ident ) ;
+	    if( _SPTR( stmp ) != (struct _source *) 0 ) {
+
+#ifdef FLOAT
+		source = ShortFloatSource( stmp ) ;
+#else
+		source = stmp ;
+#endif
+		/* Set frameheight (channels) and centre-frequencies array */
+		updateFrequencies() ;
+	    }
+	}
+    }
+
+#ifdef FLOAT
+    source = FloatShortSource( source ) ;
+#endif
+
+    setFrames( Frames() ) ;
+
+    return ( source ) ;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/model.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,45 @@
+/*
+    model.h
+    =======
+
+    inteface to Auditory model software
+
+*/
+
+struct _stage {
+  char *ident ;
+  Source (*entry)() ;
+  Option *options ;
+  char **defaults ;
+  char *help ;
+} ;
+
+extern struct _stage *FindStage( /* char *which */ ) ;
+
+extern Source ModeledSource( /* Source input */ ) ;
+
+extern char *modelStart() ;
+extern char *modelHelp() ;
+
+
+extern char *whichstr ;
+extern double *frequencies ;
+
+#if 00
+extern char *samplestr ;
+extern char *pwidthstr ;
+extern char *nwidthstr ;
+#endif
+
+extern long Frames() ;
+
+extern int Framebytes() ;
+extern int Framewidth() ;
+extern int Frameheight() ;
+extern int Framestep() ;
+extern int Nwidth() ;
+
+extern int    OptionInt() ;
+extern double OptionDouble() ;
+
+extern double Samplerate() ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/new.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,220 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+	 ===================================================
+	  new.c generic C code for recursive filter section.
+	 ===================================================
+
+
+		   J. Holdsworth - 23rd February 1988.
+
+
+    Copywright (c) Applied Psychology Unit, Medical Research Council. 1988.
+    =======================================================================
+
+
+    Release 2:  5th July 1988.
+    Rewrite  :  21st Jan 1989.
+
+*/
+
+#include "stitch.h"
+#include "recurse.h"
+#include "phase.h"
+#include "gamma_tone.h"
+#include "calc.h"
+
+#ifdef  DSP32
+#define ASM
+#endif
+
+#define STATE_TYPE float
+
+#ifndef INPUT_TYPE
+#define INPUT_TYPE DataType
+#endif
+
+#ifndef OUTPUT_TYPE
+#define OUTPUT_TYPE INPUT_TYPE
+#endif
+
+#ifndef MODULE_NAME
+#define MODULE_NAME DoNewFilterDataArray
+#define FILTER_NAME NewFilterDataArray
+#endif
+
+/* Code that performs the actual filtering */
+
+PointCount MODULE_NAME( filter_states, delays, input, output, points, channels )
+RecursiveFilterState **filter_states ;
+int *delays ;
+ INPUT_TYPE *input ;
+OUTPUT_TYPE *output ;
+int points, channels ;
+{
+    register STATE_TYPE  *start, *xpt, *ypt, *gpt ;
+#ifndef ASM
+    register double a0, a1, del1, del2 ;
+#endif
+    register RecursiveFilterState *filter_state ;
+    register OUTPUT_TYPE *output_ptr, *end ;
+    register INPUT_TYPE  *input_ptr ;
+    register STATE_TYPE a3, a2 ;
+    int channel ;
+
+    /* set up register pointers for speed of inner loop */
+
+    end = output + points * channels ;
+
+    /* for all channels */
+
+    for( channel=0 ; channel < channels ; channel++ ) {
+
+	filter_state = filter_states[ channel ] ;
+
+	/* if first time then perform implementation specific initialisation */
+
+	if( filter_state->states == ( Pointer ) 0 ) {
+
+	    filter_state->states = stitch_ralloc( ( unsigned ) ( filter_state->order + 1 ) * 2 * sizeof ( STATE_TYPE ), "generic.c for filter states\n" ) ;
+	    /* filter state stored in form of complex phasor for each cascade of filter */
+	    /* real and imaginary state values interleaved in state array */
+
+	    filter_state->states_end = ( Pointer ) ( ( STATE_TYPE * ) filter_state->states + ( filter_state->order + 1 ) * 2 ) ;
+
+	    stitch_bzero( filter_state->states, filter_state->states_end - filter_state->states ) ;
+
+	}
+
+	if( input    == ( INPUT_TYPE * ) 0 ) {
+	    input_ptr = ( INPUT_TYPE * ) output ;
+
+	    stitch_bzero( input_ptr, ( end - output ) / channels * sizeof ( *input_ptr ) ) ;
+	}
+	else
+	    input_ptr = input - delays[ channel ] ;
+
+	start = ( STATE_TYPE * ) filter_state->states ;
+
+	a2 = filter_state->k1 ;
+#ifndef ASM
+	a1 = a2 * 2 ;
+#endif
+	a3 = filter_state->k2 ;
+
+	ypt = start + filter_state->order + 1 ;
+
+	gpt = &filter_state->gain ;
+
+	for( output_ptr = output + channel ; output_ptr < end ; output_ptr += channels ) {
+
+#ifdef ASM
+asm("     r12e = r13                        ") ;
+
+asm("       a1 = a2 + a2                    ") ;
+
+asm("*r12 = a0 = *r6++                      ") ;
+
+asm("       a0 = a0 -          *r12++ * a2  ") ; /* xn-1 */
+asm("       a0 = a0 + ( *r11 = *r12 ) * a1  ") ; /* yn-1 */
+asm("*r12 = a0 = a0 -          *r11++ * a3  ") ; /* yn-2 */
+
+asm("       a0 = a0 -          *r12++ * a2  ") ; /* xn-1 */
+asm("       a0 = a0 + ( *r11 = *r12 ) * a1  ") ; /* yn-1 */
+asm("*r12 = a0 = a0 -          *r11++ * a3  ") ; /* yn-2 */
+
+asm("       a0 = a0 -          *r12++ * a2  ") ; /* xn-1 */
+asm("       a0 = a0 + ( *r11 = *r12 ) * a1  ") ; /* yn-1 */
+asm("*r12 = a0 = a0 -          *r11++ * a3  ") ; /* yn-2 */
+
+asm("       a0 = a0 -          *r12++ * a2  ") ; /* xn-1 */
+asm("       a0 = a0 + ( *r11 = *r12 ) * a1  ") ; /* yn-1 */
+asm("*r12 = a0 = a0 -          *r11++ * a3  ") ; /* yn-2 */
+
+asm("*r8  = a0 =               *r12++ * *r10") ;
+#else
+	    xpt = start ;
+
+	    del1 = a0 = *input_ptr++ ;
+
+	    a0 = a0 -          *xpt++ * a2     ; /* xn-1 */ xpt[-1] = del1 ;
+	    a0 = a0 + ( del2 = *xpt ) * a1     ; /* yn-1 */
+     del1 = a0 = a0 -          *ypt++ * a3     ; /* yn-2 */ ypt[-1] = del2 ;
+
+	    a0 = a0 -          *xpt++ * a2     ; /* xn-1 */ xpt[-1] = del1 ;
+	    a0 = a0 + ( del2 = *xpt ) * a1     ; /* yn-1 */
+     del1 = a0 = a0 -          *ypt++ * a3     ; /* yn-2 */ ypt[-1] = del2 ;
+
+	    a0 = a0 -          *xpt++ * a2     ; /* xn-1 */ xpt[-1] = del1 ;
+	    a0 = a0 + ( del2 = *xpt ) * a1     ; /* yn-1 */
+     del1 = a0 = a0 -          *ypt++ * a3     ; /* yn-2 */ ypt[-1] = del2 ;
+
+	    a0 = a0 -          *xpt++ * a2     ; /* xn-1 */ xpt[-1] = del1 ;
+	    a0 = a0 + ( del2 = *xpt ) * a1     ; /* yn-1 */
+     del1 = a0 = a0 -          *ypt++ * a3     ; /* yn-2 */ ypt[-1] = del2 ;
+
+   *output_ptr =               *gpt   * a0     ;            *xpt++  = del1 ;
+#endif
+	    ypt = xpt ;
+	}
+    }
+
+    return( sizeof ( OUTPUT_TYPE ) ) ;
+}
+
+/* for compatability */
+
+PointCount FILTER_NAME( compensator_state, input_array, output_array, npoints )
+FilterChannelInfo *compensator_state ;
+INPUT_TYPE *input_array ;
+OUTPUT_TYPE *output_array ;
+PointCount npoints ;
+{
+    ( ( PhaseCompensatorState * ) compensator_state )->filter_module = MODULE_NAME ;
+
+    return( PhaseCompensateFilter( ( PhaseCompensatorState * ) compensator_state, ( Pointer ) input_array, ( Pointer ) output_array, npoints ) ) ;
+}
+
+
+/* tidy up defines for redefinition */
+
+#undef  STATE_TYPE
+#undef  INPUT_TYPE
+#undef OUTPUT_TYPE
+#undef FILTER_NAME
+#undef MODULE_NAME
+#undef I_SHIFT
+#undef K_SHIFT
+#undef S_SHIFT
+
+#undef SIN
+#undef COS
+
+#ifdef FLOAT
+#undef FLOAT
+#endif
+
+#ifdef COMPLEX
+#undef COMPLEX
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/review.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,666 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee
+    is hereby granted for research purposes, provided that this copyright
+    notice appears in all copies and in all supporting documentation, and that
+    the software is not redistributed for any fee (except for a nominal shipping
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this
+    software for any purpose.  It is provided "as is" without express or implied
+    warranty.
+
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    review.c
+    ========
+
+    formerly known as revsai.c - reviews .ctn screen dump files from disk.
+
+
+    Copyright (c), 1989  The Medical Research Council, Applied Psychology Unit.
+
+
+    Authors : Paul Manson and John Holdsworth.
+    Written : 11th March, 1989
+
+    Edited  :
+
+    03 April 1989 (Paul Manson) -- A new star on the horizon! The all-singing, all-dancing
+				   new revue emerges from the ashes of last week's version.
+
+    19 April 1989 (Paul Manson) -- Added the <input> option. Changed the name to revsai.
+
+    27 April 1989 (Paul Manson) -- The port to the DecStation (and by implication, the VAX)
+				   has revealed several problems and bugs. All such known
+				   bugs have been fixed. The <memory> option has been
+				   introduced (for non-PCs only) to permit rapid reviewing
+				   on X-windows servers. NOTE THAT THE SCREEN SIZE FOR NON
+				   PC MACHINES HAS BEEN HARD_CODED! THIS SHOULD CHANGE!
+
+    05 May   1989 (Paul Manson) -- The above problem has been temporarily rectified by
+				   using the default width and height options to indicate
+				   the actual screen size. Also, the options format change
+				   has been accounted for.
+
+    11 May   1989 (Paul Manson) -- Altered options to conform to the new(est) r'egime.
+
+    15 May   1989 (Paul Manson) -- Incorporated the PC-style wildcarding into the Unix version.
+				   Made display use "NULL" instead of (char *) 0.
+
+    05 June  1989 (Paul Manson) -- Altered a couple of the option comments to reflect their
+				   behaviour more accurately. I also encountered the rather
+				   suspicious "bug" whereby revsai gets a segmentation fault
+				   whenever it is run on an old "sai" file ... those generated
+				   by sai now appear to be OK... If this really is a problem,
+				   it should be tracked down!
+
+    06 July  1989 (Paul Manson) -- As well as altering revsai to accomodate all of the new
+				   options names, I note that the abovementioned bug appears
+				   to have disappeared without trace; hopefully it was just
+				   due to previous (buggy) files, etc.
+
+    3 August 1993 (M. Akeroyd) --  Added declarations of "colourstr"  and "planemaskstr".
+                                   They aren't used, but are in X.c (and thus libglib.a),
+				   and are therfore required to fool the linker.
+
+    25 March 1994 (M. Akeroyd) --  Added colour. mono etc, so that 'review' would actually work.
+                                   (the previuos cahnge just made it compile.)
+*/
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+#if defined(THINK_C) || defined(NeXT) 
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+
+#include "windows.h"
+#include "options.h"
+
+
+char *monostr, *colourstr, *planemaskstr;   /* MAA 3-8-1993 */
+char *fgcolourstr, *bgcolourstr;  /* MAA 19-8-1993 */
+#ifndef  lint
+static char *sccs_id = "@(#)review.c	1.13 Paul Manson, John Holdsworth (MRC-APU) 5/31/91";
+#endif
+
+#define max(A,B) (((A) > (B)) ? (A) : (B))
+#define LENGTH_STR "remainder"
+#define MAX_LENGTH (9999)
+
+#define CENTER_STR "center"
+#define IMAGE_SUFFIX ".ctn"
+
+#ifdef PC
+#define READ_BINARY "rb"
+#else
+#define READ_BINARY "r"
+#endif
+
+/* configurables */
+
+static char *helpstr                               ;
+static char *speed1str, *speed2str                 ;
+static char *xstr, *ystr, *widthstr,  *heightstr   ;
+static char *start1str,   *stop1str,  *step1str    ;
+static char *start2str,   *stop2str,  *step2str    ;
+static char *minstr ,     *maxstr  ,  *framestr    ;
+static char *in1str,      *in2str,    *downstr     ;
+
+#if !defined( PC )
+extern void exit();
+static char *memorystr;
+#endif
+
+static Option res[] = {
+ { "help",       "none",       &helpstr,   "<wave1> [<wave2>]\n\n\
+	Redisplays stored images from memory or directly from disk.\n\
+	Review responds to various simple commands, viz.\n\n\
+	1\t Activate only wave1 (default when only one wave named).\n\
+	2\t Activate only wave2.\n\
+	b or B\t Activate Both waves (default when two waves named).\n\n\
+	a or A\t Animate cartoon wave(s). Hitting space bar is equivalent.\n\
+	s or S\t Single-step activated wave(s). Hit space bar to step.\n\
+	+\t Animate activated wave(s) faster.\n\
+	-\t Animate activated wave(s) slower.\n\n\
+	q or Q\t Quit Revue.\n", SilentOption },
+ { "input1",   NULL_OPTION,  &in1str,     "Default input file name 1",               InputOption},
+ { "start1" ,     "0" ,      &start1str , "Start point in wave 1 (in ms)",           InputOption},
+ { "length1", LENGTH_STR,    &stop1str  , "Length of wave 1 to display (in ms)",     InputOption},
+ { "step1"  ,     "1" ,      &step1str  , "Display every step-th image of wave 1",   InputOption},
+ { "speed1",     "1" ,       &speed1str,  "Image 1 display speed (1 is  fastest)", InputOption},
+
+ { "input2",   NULL_OPTION,  &in2str,     "Default input file name 2\n",             InputOption},
+ { "start2" ,     "0" ,      &start2str , "Start point in wave 2 (in ms)",           InputOption},
+ { "length2", LENGTH_STR,    &stop2str  , "Length of wave 2 to display (in ms)",     InputOption},
+ { "step2"  ,     "1" ,      &step2str  , "Display every step-th image of wave 2",   InputOption},
+ { "speed2",     "1" ,       &speed2str,  "Image 2 display speed (1 is  fastest)",   InputOption},
+
+ { "x0_win",  CENTER_STR,    &xstr,       "Left edge of window (in pixels)" ,        SilentOption},
+ { "y0_win",  CENTER_STR,    &ystr,       "Upper edge of window (in pixels)",        SilentOption},
+ { "width_screen", "960",    &widthstr,   "Physical screen width  in pixels",        SilentOption},
+ { "height_screen","750",    &heightstr,  "Physical screen height in pixels",        SilentOption},
+
+/* MAA: 25 March 1994
+ * These next added because they are used from within X.c (although defined in gen.c), and thus the graphics
+ * calls. They are of NO meaning, however; they define how the Model makes the bitmaps.
+ * Once made, you cannot edit bitmaps ... 
+ */
+ { "fg_col",         "black", &fgcolourstr, "Foreground Colour.\n",                   SilentOption},
+ { "bg_col",         "white", &bgcolourstr, "Background Colour.\n",                   SilentOption},
+ {    "mono_ctn",   ON_OPTION, &monostr, "Force monochrome (single plane) cartoons.", SilentOption},
+ {  "colour_ctn",  OFF_OPTION, &colourstr, "Force colour (multi-plane) cartoons.", SilentOption},
+ {"planemask_ctn", "1", &planemaskstr, "Planemask for creating cartoons.\n", SilentOption},
+/* MAA: End of that bit */
+
+#if !defined( PC )
+ { "memory",     ON_OPTION,  &memorystr,  "Read images into memory for reviewing\n", InputOption},
+#endif
+ ( char * ) 0 } ;
+
+static Option hiddenRes[] = {
+ { "downsample",     "20",   &downstr,    "Image file frame size (in ms)",           InputOption},
+ { "frstep_aid",     "20",   &framestr,   "Image file frame size (in ms)",           InputOption},
+ { "mincf_afb",     "220",   &minstr  ,   "Minimum Center Frequency in Hertz",       InputOption},
+ { "maxcf_afb",    "4400",   &maxstr  ,   "Maximum Center Frequency in Hertz",       InputOption},
+ { "width_win",     "900",   &widthstr,   "Window width  (pixels)",                  InputOption},
+ { "height_win",    "600",   &heightstr,  "Window height (pixels)",                  InputOption},
+ ( char * ) 0 } ;
+
+#define ONE (1)
+#define TWO (2)
+#define BOTH (0)
+
+#define FALSE (0)
+#define TRUE (1)
+#define OVERTHETOP (10000)
+#define AXES_WIDTH (15)
+
+static int msToImages(frame, ms)
+  double frame;
+  double ms   ;
+{
+  return (((int) (ms / frame)) + 1); /* Round Up */
+}
+
+/* File Name Suffix Conversion Parameters */
+
+#define BACKSLASH_CHAR  '\\'
+#define SLASH_CHARACTER '/'
+#define NULL_CHARACTER  '\000'
+#define DOT_CHARACTER '.'
+
+/******************************************************************************************/
+/*                                                                                        */
+/*    AlterSuffix(). Returns its argument fileName with a newSuffix appended in place of  */
+/*                   any previous suffix it may have had. It should be noted that this    */
+/*                   suffix must include any DOT it wishes to have appended to the name.  */
+/*                                                                                        */
+/******************************************************************************************/
+
+char *AlterSuffix(fileName, newSuffix)
+     char *fileName, *newSuffix;
+{
+  char *temp, *temp2, *lastPart;
+  int i;
+
+  temp = malloc((unsigned) (strlen(fileName) + strlen(newSuffix) + 1));
+
+  temp = strcpy(temp, fileName);
+
+#if defined( PC )
+  /* Change all backslashes to forward slashes */
+  for (i = 0; temp[i] != NULL_CHARACTER; i++)
+    if (temp[i] == BACKSLASH_CHAR)
+      temp[i] = SLASH_CHARACTER;
+#endif
+
+  if ((lastPart = strrchr(temp, SLASH_CHARACTER)) == NULL)
+    lastPart = temp;
+  else
+    lastPart++; /* Skip over the actual "/" */
+
+  /* lastPart points to the tail name of the path */
+
+  if ((temp2 = strchr(lastPart, DOT_CHARACTER)) == NULL)
+    temp = strcat(temp, newSuffix);
+  else
+    temp2 = strcpy(temp2, newSuffix);
+
+  return (temp);
+}
+
+/* -----------------------------------------------------------------------------------
+
+   A Routine to extend revsai for in-memory animation. This copies every image from
+   <start> to <stop> by <step> into the images buffer for the window <w>. It then
+   expects contiguous animation of these images. The integer returned is the number
+   of images that were saved; subsequent image Recall() calls should refer to images
+   in the range [1 .. this returned value].
+
+   ----------------------------------------------------------------------------------- */
+
+static int readIntoMemory(w, filePtr, start, stop, step)
+     WindowObject w;
+     FILE *filePtr ;
+     int      start;
+     int       stop;
+     int       step;
+{
+  int fileImage, memImage;
+
+  memImage = 0;
+
+  fileImage = start;
+
+  while (fileImage <= stop && Read(w, filePtr, fileImage)) {
+    Store(w);
+    fileImage += step;
+    memImage++;
+  }
+
+  return (memImage);
+}
+
+main( argc, argv )
+int argc ;
+char *argv[] ;
+{
+    WindowObject w1, w2;
+    int   screenWidth,  screenHeight ;
+    int   firstWidth ,  firstHeight  ;
+    int   secondWidth,  secondHeight ;
+    int   firstPixels,  secondPixels ;
+    FILE *firstWave  , *secondWave   ;
+
+    int OneWave, TwoWaves, spareWidth,
+	spareHeight                  ;
+
+    int waveMode , image1    , image2;
+    int            count1    , count2;
+    int stopFirst, stopSecond        ;
+    int start1   , stop1     , step1 ;
+    int start2   , stop2     , step2 ;
+    int speed1   , speed2            ;
+
+    char command, *firstWaveName,
+      *secondWaveName,
+      *programName;
+
+    double mincf1, mincf2, maxcf1, maxcf2, frame1, frame2;
+    int inMemory, x, y;
+
+    programName = argv[0];
+
+    (void) getopts( res, &argc, &argv );
+
+    /* Extract any information from the opts which is NECESSARY for the
+       operation of revue */
+
+    screenWidth = atoi( widthstr );
+    screenHeight= atoi( heightstr);
+
+#if defined( PC )
+    inMemory = FALSE;
+#else
+    inMemory = isON( memorystr );
+#endif
+
+    if (argc > 2 || (argc == 0 && isNULL(in1str))) {
+      (void) helpopts(res, programName);
+      exit(1);
+    }
+    else {
+      OneWave = ((argc == 0 && !isNULL(in1str)) ||
+		 (argc == 1 &&  isNULL(in2str)));
+      TwoWaves = !OneWave;
+    }
+
+    if (argc == 0)
+      firstWaveName = AlterSuffix(in1str, IMAGE_SUFFIX) ;
+    else
+      firstWaveName = AlterSuffix(argv[0], IMAGE_SUFFIX);
+
+    if ((firstWave = fopen(firstWaveName, READ_BINARY )) == NULL) {
+      (void) fprintf(stderr, "Could not open the image file %s.\n", firstWaveName);
+      exit(1);
+    }
+
+    (void) readopts(res, firstWave);
+
+    if (fseek(firstWave, 0l, 0)) {
+	(void) fprintf(stderr, "revsai: Could not re-seek the %s file.\n",
+		       firstWaveName);
+	exit(1);
+    }
+
+    (void) readopts(hiddenRes, firstWave);
+
+    if( framestr == (char *) 0 )
+		if( downstr == (char *) 0 )
+		 	frame1 = 1 ;
+		else
+			frame1 = atof(downstr);
+    else if ((frame1 = atof(framestr)) < 0.0)
+	frame1 = 0.0;
+
+    firstWidth  = atoi( widthstr );
+    firstHeight = atoi( heightstr);
+
+    start1 = msToImages(frame1, atof( start1str ));
+
+    if (strcmp(stop1str, LENGTH_STR) == 0)
+      stop1 = MAX_LENGTH;
+    else
+      stop1  = msToImages(frame1, atof( stop1str  )) + start1;
+
+    step1  = atoi( step1str  );
+    if (step1 < 1)
+      step1 = 1;
+
+    firstPixels = 1; /* atoi( pixelstr ); */
+
+    mincf1 = atof( minstr );
+    maxcf1 = atof( maxstr );
+
+    if (TwoWaves) {
+
+      if (argc == 1)
+	secondWaveName = AlterSuffix(in2str, IMAGE_SUFFIX);
+      else
+	secondWaveName = AlterSuffix(argv[1],IMAGE_SUFFIX);
+
+      if ((secondWave = fopen(secondWaveName, READ_BINARY )) == NULL) {
+	(void) fprintf(stderr, "Could not open the image file %s.\n",
+		       secondWaveName);
+	exit(1);
+      }
+
+      (void) readopts(res, secondWave);
+      if (fseek(secondWave, 0l, 0)) {
+	  (void) fprintf(stderr, "revsai: Could not re-seek the %s file.\n",
+			 secondWaveName);
+	  exit(1);
+      }
+      (void) readopts(hiddenRes, secondWave);
+
+      if( framestr == (char *) 0 )
+		if( downstr == (char *) 0 )
+		 	frame2 = 1. ;
+		else
+		  frame2 = atof(downstr);
+      else if ((frame2 = atof(framestr)) < 0.0)
+	  frame2 = atof(downstr);
+
+      secondWidth  = atoi( widthstr );
+      secondHeight = atoi( heightstr);
+
+      start2 = msToImages(frame2, atof( start2str ));
+
+      if (strcmp(stop2str, LENGTH_STR) == 0)
+	stop2 = MAX_LENGTH;
+      else
+	stop2  = msToImages(frame2, atof( stop2str  )) + start2;
+
+      step2  = atoi( step2str  );
+      if (step2 < 1)
+	step2 = 1;
+
+      secondPixels = 1; /* atoi( pixelstr ); */
+
+      mincf2 = atof( minstr );
+      maxcf2 = atof( maxstr );
+
+    }
+
+
+    /* Open display window(s) */
+
+    if (TwoWaves) {
+      /* Center them both for height, but try to fit them both on the screen
+	 at once, width-wise. Firstly, get the REAL screen size */
+#if defined( PC )
+      w1 = newDisplayWindow(firstWaveName, -1, -1, OVERTHETOP, OVERTHETOP, 1);
+      screenWidth  = Width(w1);
+      screenHeight = Height(w1);
+      Close(w1);
+#endif
+
+      if (screenHeight < firstHeight || screenHeight < secondHeight) {
+	(void) fprintf(stderr, "revsai: One (or both) of the waves specified was too\n        high for this screen.\n");
+	exit(1);
+      }
+      if (screenWidth < firstWidth + secondWidth) {
+	(void) fprintf(stderr, "revsai: These two waves are too wide to be viewed side-by-side.\n        Please revue them one at a time, or perhaps generate them smaller.\n");
+	exit(1);
+      }
+
+      spareWidth  = screenWidth  - (firstWidth  + secondWidth  + (2 * AXES_WIDTH));
+      spareHeight = screenHeight - (firstHeight + (2 * AXES_WIDTH));
+
+      w1 = newDisplayWindow(firstWaveName, spareWidth/6 + AXES_WIDTH, spareHeight/2,
+			    firstWidth, firstHeight, firstPixels);
+      Axes(w1, firstWaveName, 0.0, frame1, "Image Frame Size (in ms)",
+	       mincf1, maxcf1, "Center Frequency (in Hz)");
+
+      spareHeight = screenHeight - (secondHeight + (2 * AXES_WIDTH));
+
+      w2 = newDisplayWindow(secondWaveName, (5 * spareWidth / 6) +
+				     firstWidth + (2 * AXES_WIDTH),
+				     spareHeight/2, secondWidth, secondHeight,
+				     secondPixels);
+      Axes(w2, secondWaveName, 0.0, frame2, "Image Frame Size (in ms)",
+	       mincf2, maxcf2, "Center Frequency (in Hz)");
+    }
+    else {
+      /* Easy .. MetaPC Centers it for us */
+      if (OptionStringsEqual(xstr, CENTER_STR))
+	x = -1;
+      else
+	x = atoi(xstr);
+
+      if (OptionStringsEqual(ystr, CENTER_STR))
+	y = -1;
+      else
+	y = atoi(ystr);
+
+      w1 = newDisplayWindow(firstWaveName, x, y, firstWidth, firstHeight,
+			    firstPixels );
+      Axes(w1, firstWaveName, 0.0, frame1, "Image Frame Size (in ms)",
+	       mincf1, maxcf1, "Center Frequency (in Hz)");
+
+#if defined( SUN )
+      /* Kludge to overcome the window-sizing inconsistency when
+	 you open a SunView window with a frame */
+
+      if (Height(w1) >  firstHeight || Width(w1) >  firstWidth) {
+#else
+      if (Height(w1) != firstHeight || Width(w1) != firstWidth) {
+#endif
+	(void) fprintf(stderr, "revsai: The wave you wish to view is too large (ie. either too wide\nor too tall) for the current screen.\n");
+	exit(1);
+      }
+    }
+
+    /* Do the actual reviewing */
+
+    if (TwoWaves)
+      waveMode = BOTH;
+    else
+      waveMode = ONE ;
+
+    speed1 = atoi( speed1str );
+    if (speed1 < 1)
+      speed1 = 1;
+    speed2 = atoi( speed2str );
+    if (speed2 < 1)
+      speed2 = 1;
+
+    /* Initially, just open the files and display the first frame of each, */
+    /* UNLESS the inMemory switch is set, in which case you should read in */
+    /* all of the images and adjust start, stop to suit.                   */
+
+    if (inMemory) {
+	stop1 = readIntoMemory(w1, firstWave, start1, stop1, step1);
+	start1 = 1; /* Now runs from 0 to the adjusted stop */
+	step1  = 1; /* Now the images are contiguous        */
+	if (TwoWaves) {
+	  stop2 = readIntoMemory(w2, secondWave, start2, stop2, step2);
+	  start2 = 1; /* Now runs from 0 to the adjusted stop */
+	  step2  = 1; /* Now the images are contiguous        */
+	}
+    }
+    else {
+      if (!Read(w1, firstWave, start1)) {
+	(void) fprintf(stderr, "revsai: Could not read the first image from the first wave.\n");
+	exit(1);
+      }
+
+      if (TwoWaves && !Read(w2, secondWave, start2)) {
+	(void) fprintf(stderr, "revsai: Couldn't read the first image from the second wave.\n");
+	exit(1);
+      }
+    }
+
+    /* Sit and take commands */
+
+    while ((command = Pause(w1)) != 'q' && command != 'Q') {
+      switch (command) {
+      case '1':
+	    /* Toggle to Wave number One */
+	    waveMode = ONE;
+	break;
+      case '2':
+	    /* Try to toggle to Wave number Two */
+	    if (TwoWaves)
+	      waveMode = TWO;
+	    break;
+      case 'b': case 'B':
+	    /* Try to toggle to Both Waves */
+	    if (TwoWaves)
+	      waveMode = BOTH;
+	    break;
+      case '+':
+	    /* Speed up current Wave(s) */
+	if (waveMode == ONE || waveMode == BOTH)
+	  speed1 = ((speed1 > 1) ? (speed1 /= 2) : (1));
+	    if (waveMode == TWO || waveMode == BOTH)
+	  speed2 = ((speed2 > 1) ? (speed2 /= 2) : (1));
+	    break;
+      case '-':
+	    /* Slow down current Wave(s) */
+	if (waveMode == ONE || waveMode == BOTH)
+	  speed1 *= 2;
+	    if (waveMode == TWO || waveMode == BOTH)
+	  speed2 *= 2;
+	    break;
+      case 's': case 'S':
+	stopFirst  = (waveMode == TWO);
+	stopSecond = (waveMode == ONE);
+	image1 = start1;
+	image2 = start2;
+	while (!(stopFirst && stopSecond) && (Pause(w1) == ' ')) {
+	    if (!stopFirst) {
+		if (inMemory)
+			  Recall(w1, image1);
+		else
+			  stopFirst  = !Read(w1, firstWave , image1);
+		if (!stopFirst) {
+			  image1 += step1;
+			  stopFirst = (image1 > stop1);
+		}
+	    }
+	    if (!stopSecond) {
+		if (inMemory)
+			  Recall(w2, image2);
+			else
+			  stopSecond = !Read(w2, secondWave, image2);
+		if (!stopSecond) {
+			  image2 += step2;
+			  stopSecond = (image2 > stop2);
+		}
+	    }
+	}
+	break;
+      case 'a': case 'A': case ' ':
+	stopFirst  = (waveMode == TWO);
+	stopSecond = (waveMode == ONE);
+	image1 = start1;
+	image2 = start2;
+	count1 = count2 = 0    ;
+	while (!(stopFirst && stopSecond)) {
+		if (stopFirst || image1 > stop1) {
+		if (waveMode == BOTH && !stopSecond && image2 <= stop2 &&
+		    image1 > start1  && count1 == 0) {
+			/* Redisplay the previous image for constant speed */
+			if (inMemory)
+			  Recall(w1, image1-1);
+			else
+			  stopFirst = !Read(w1, firstWave, image1-1);
+		    }
+		    stopFirst = TRUE;
+		}
+		else {
+		    if (inMemory)
+		      Recall(w1, image1);
+		    else
+		      stopFirst = !Read(w1, firstWave, image1);
+		    if (!stopFirst)
+			    if (++count1 >= speed1) {
+			      image1 += step1;
+			      count1  = 0    ;
+			}
+	    }
+		if (stopSecond || image2 > stop2) {
+		if (waveMode == BOTH && !stopFirst && image1 <= stop1 &&
+		    image2 > start2  && count2 == 0) {
+			/* Redisplay the previous image for constant speed */
+			if (inMemory)
+			  Recall(w2, image2-1);
+			else
+			  stopSecond = !Read(w2, secondWave, image2-1);
+			}
+		    stopSecond = TRUE;
+		}
+		else {
+		    if (inMemory)
+		      Recall(w2, image2);
+		    else
+		      stopSecond = !Read(w2, secondWave, image2);
+		    if (!stopSecond)
+			    if (++count2 >= speed2) {
+			      image2 += step2;
+			      count2  = 0    ;
+			}
+	    }
+	}
+	break;
+      default:
+	    break;
+      }
+    }
+    if (fclose(firstWave)) {
+	(void) fprintf(stderr, "revsai: Could not close file % correctly.\n",
+		       firstWaveName);
+	exit(1);
+    }
+    if (TwoWaves && fclose(secondWave)) {
+	(void) fprintf(stderr, "revsai: Could not close file % correctly.\n",
+		       secondWaveName);
+	exit(1);
+    }
+  }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/spiral.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,460 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    spiral.c
+    ========
+
+    Tap SAI frames and draw each one as a spiral in the given window.
+*/
+
+/*  
+    Modifications made to the routines draw_spiral, map_ribbon, map_spiral
+    so that the nwidth section of the SAI image is taken into account while
+    doing the calculations, (in image.c, doColumn()) and while plotting,
+    only the positive section of the time axis is drawn.   
+    Added a new field "nwid" in the _draw_state object. 
+    17 March, 1995.   A Jay Datta 
+*/ 
+
+#include <math.h>
+#include <stdio.h>
+
+#include "windows.h"
+#include "stitch.h"
+#include "source.h"
+#include "draw.h"
+#include "ops.h"
+#include "spiral.h"
+
+#ifndef lint
+static char *sccs_id = "@(#)spiral.c	1.9 Mike Allerhand (MRC-APU) 6/1/91" ;
+#endif
+
+/****************************************************************************
+*       Misc definitions
+****************************************************************************/
+#define TWOPI       6.28318530717
+#define log2(x)     (log((double)x)/log(2.0))
+
+/****************************************************************************
+*       Model parameters.
+* Defaults:
+*     form_spl      =  'arch'
+*     dotsize_spl   =   2
+*     axis_spl      =   off
+*     zero_spl      =   4.072
+*     dotthresh_spl =   50
+****************************************************************************/
+int     frameheight, framewidth, nwid;    /* Dimensions of each sai */
+
+char    form_spl = 'A' ;             /* Form of spiral, 'A' or 'L' */
+int     dotsize_spl = 2 ;            /* Dotsize in pixels */
+int     axis_spl = 0 ;               /* Flag for spiral axis */
+double  zero_spl = 4.072 ;           /* For rotation and circuit removal */
+int     dotthresh_spl = 25 ;         /* Min peak height */
+
+/*=================== COORDINATE SYSTEM OF THE DATA =======================*/
+
+/****************************************************************************
+*       Size and location, (program arguments), of calibrated box, in
+*       coord system of the data.
+* range =     range or size of both axes, (ie. "magnification" of plot).
+* xorg,yorg = real plot coordinates at centre of screen.
+****************************************************************************/
+static float   range;
+static float   xorg;
+static float   yorg;
+
+/****************************************************************************
+*       Limits of calibrated box in coord system of the data.
+****************************************************************************/
+static float   Xd0, Yd0;       /* Bottom-left corner   */
+static float   Xd1, Yd1;       /* Top-right corner     */
+
+
+/*===================== PIXEL COORDINATE SYSTEM  ==========================*/
+
+/****************************************************************************
+*       Dimensions of window (box plus border) in pixel coord system.
+****************************************************************************/
+static int     width,height;
+static int     border;         /* border = min(width,height) / 6; */
+
+/****************************************************************************
+*       Limits of on-screen calibrated box in pixel coord system.
+****************************************************************************/
+static int     Xp0, Yp0;       /* Bottom-left corner (border, height-border)  */
+static int     Xp1, Yp1;       /* Top-right corner   (width-border, border)   */
+
+/****************************************************************************
+*       Dimensions of calibrated box in pixel coord system
+****************************************************************************/
+static int     Wb;             /* Box width  Wb = Xp1-Xp0  */
+static int     Hb;             /* Box height Hb = Yp0-Yp1  */
+
+/****************************************************************************
+*   The parameters for the calibrated box in the pixel coord system are
+*   initialized for a given window size (width, height, in pixels),
+*   as follows:
+*
+*       border = min(width,height) / 6;
+*       Xp0 =    border;
+*       Xp1 =    width - border;
+*       Yp0 =    border;
+*       Yp1 =    height - border;
+*       Wb  =    Xp1-Xp0;
+*       Hb  =    Yp1-Yp0;
+****************************************************************************/
+
+/*================= COORDINATE SYSTEM TRANSFORMATIONS =====================*/
+
+/****************************************************************************
+*       Transformations from coord system of the data to pixel coord system.
+*       For example, if the origin in the data coord system is (0,0), then
+*       the origin in the pixel coord system is (px(0),py(0)).
+****************************************************************************/
+#define px(x)           ((int)(Xp0+Wb/2+(x-xorg)*(Wb/range)))
+#define py(y)           ((int)(Yp0+Hb/2+(y-yorg)*(Hb/range)))
+
+/****************************************************************************
+*       Screen Position (in pixel coord system): test position is within box.
+****************************************************************************/
+#define Xinbox(x)       ((Xp0<=x && x<=Xp1) ? 1 : 0)
+#define Yinbox(y)       ((Yp0<=y && y<=Yp1) ? 1 : 0)
+#define inbox(x,y)      ((Xinbox(x) && Yinbox(y)) ? 1 : 0)
+
+
+
+
+/****************************************************************************
+* This routine is called once per SAI frame. The SAI data is in array "frame".
+* The SAI frame is formatted row-wise, starting with the lowest-frequency row.
+* The state structure is:
+*     struct _draw_state {
+*         Source source;
+*         WindowObject window;
+*         int min, max;
+*         int framewidth, frameheight;  dimensions of the SAI
+*         int nwid;
+*         long frames;
+*         long framenumber;
+*         void (*interceptor)();        function which stores window for replay
+*         void (*drawer)();             drawing function
+*     };
+*
+* This struct is defined in stitch/draw.h
+* It is initialized by routine "SourceDraw" in stitch/draw.c, which is called
+* from gen.c. Note that this takes place after the SaiEntry routine has been
+* called, so the sai dimensions set there will apply.
+*
+****************************************************************************/
+void draw_spiral( state, image )
+struct _draw_state *state ;
+short *image ;
+{
+    static int first=1;         /* flag for first-call of this routine */
+
+    /* Coordinate arrays for axis and spiral points */
+    static short *Xaxis;
+    static short *Yaxis;
+    static int    naxis = 0;    /* number of points plotted along spiral axis */
+				/* (naxis = (100 * nsamples) +1)              */
+    static short *Xspiral;
+    static short *Yspiral;
+    int           npoints = 0;  /* number of samples in pulse ribbon and spiral */
+
+    static short *Xdot;
+    static short *Ydot;
+
+    static short *frame ;
+
+    frameheight = state->frameheight;
+    framewidth= (state->framewidth)+(state->nwid);  /* -nwid */
+    /* fprintf(stderr, "THE NWID VALUE is %d\n", state->nwid); */ 
+    nwid=-state->nwid; 
+    /*  fprintf(stderr, "framewidth=%d, frameheight=%d\n", frameheight, framewidth); */
+    /* Initialize parameters of pixel coord system (see spiral.h) */
+    width =  Width(  state->window ) ;
+    height = Height( state->window ) ;
+
+    border = 0;
+
+    Xp0 =    border;
+    Xp1 =    width - border;
+    Yp0 =    border;
+    Yp1 =    height - border;
+    Wb  =    Xp1-Xp0;
+    Hb  =    Yp1-Yp0;
+
+    /* Initialize parameters of data coord system */
+    if (form_spl == 'A') range = 2 * (TWOPI * log2((double)(framewidth+nwid)) - TWOPI * zero_spl); 
+    if (form_spl == 'L') range = 2 * (framewidth+nwid);  
+    xorg =   0;
+    yorg =   0;
+
+    /* Allocate space (first-time call only). */
+    if (first) {
+	first = 0;
+	frame = NewArray(short, frameheight*(framewidth+nwid), "frame spiral.c" );
+	if (axis_spl) {
+	    /* Allocate space and compute (X,Y) coords for spiral axis.   */
+	    /* Resolution of points on axis is 100 times greater, so that */
+	    /* inner circuits look smooth. Add 1 as time starts from zero.*/
+	    naxis = (100*framewidth+nwid)+1; 
+	    Xaxis = NewArray(short, naxis, "Xaxis, spiral.c" );
+	    Yaxis = NewArray(short, naxis, "Yaxis, spiral.c" );
+	    naxis = gen_axis(Xaxis,Yaxis,naxis,form_spl,zero_spl);
+	}
+	if (dotsize_spl) {
+	    /* Allocate space for coords of spiral points.*/
+	    Xspiral = NewArray(short, frameheight * framewidth+nwid, "Xspiral spiral.c" );
+	    Yspiral = NewArray(short, frameheight * framewidth+nwid, "Yspiral spiral.c" );
+	    Xdot    = NewArray(short, frameheight * framewidth+nwid, "Xdot spiral.c" );
+	    Ydot    = NewArray(short, frameheight * framewidth+nwid, "Ydot spiral.c" );
+	}
+    }
+
+    CopyArray( image, frame, (framewidth+nwid)*frameheight ) ;
+
+    /* Map one SAI frame onto a pulse ribbon, and return the number of 1's */
+    npoints = map_ribbon(frame,dotthresh_spl);
+
+    /* Map 1's in a pulse ribbon onto points in spiral coords.  */
+    /* Return the number of points in the plot window.          */
+    npoints = map_spiral(frame,Xspiral,Yspiral,form_spl,zero_spl);
+
+    /* Plot spiral points and axis in window. */
+    if (dotsize_spl)
+	plotdots(state->window,Xspiral,Yspiral,Xdot,Ydot,npoints,dotsize_spl-1);
+    if (axis_spl)
+	Draw(state->window,Xaxis,Yaxis,naxis);
+
+    return ;
+}
+
+
+
+/****************************************************************************
+    Map an SAI frame onto a "pulse ribbon".
+
+Convert a "frame" into a binary array where a `1' corresponds to a peak in
+the SAI frame, and everwhere else is `0'. This binary array is called a
+pulse ribbon.
+
+Each SAI is a "frame". A frame is a matrix of "frameheight" rows by
+"framewidth" columns. Each row corresponds to a frequency channel, and
+frameheight corresponds to "chans" in image.c. The columns correspond to
+the number of time samples in the "image_duration", and framewidth
+corresponds to framewidth (or imagewidth/chans) in image.c.
+
+The format of data in the input file, (short *frame), is "unmultiplexed".
+This is an SAI frame in row-wise format, with the row corresponding
+to the lowest-frequency channel comming first.
+
+Every point in the sai frame is a coordinate pair:
+(f,t);  f=0,1,...,frameheight-1,  t=0,1,...,framewidth-1.
+(The lowest frequency channel has the lowest channel number f).
+(The time-origin is the rightmost point, framewidth-1).
+
+Peaks in the SAI frame are maxima along the time axis. Peaks are independent
+of adjacent frequency channels.
+A peak is defined as the highest point between zeroes, which also exceeds a
+threshold. (A zero-crossing between peaks is guaranteed, since the cochleagram
+signal has been half-wave rectified).
+
+The number of peaks found is returned.
+****************************************************************************/
+map_ribbon(frame,threshold)
+short   *frame;
+int      threshold;
+{
+    short   p, pmax;
+    int     i, j, k, jk, npoints=0;
+
+    /* for each SAI row (each frequency channel) in turn */
+    for (i=0, k=0 ; i<frameheight ; i++, k+=framewidth+nwid) /* SSS */
+	/* for each time sample, working from right to left */
+	for (j=framewidth ; j>=0 ; j--)  { /* SSS */
+	    /* while zero, advance to next peak */
+	    while (j>=(0-1) && frame[j+k]<=0) { /* SSS */
+		frame[j+k]=0;
+		j--;
+	    }
+	    /* while greater than zero, search for max peak */
+	    for (pmax=0 ; j>=(0-1) && (p=frame[j+k])>0 ; j--) { /* SSS */
+		frame[j+k]=0;
+		if (p>pmax) {
+		    pmax=p; jk=j+k;
+		}
+	    }
+	    /* record max peak if it exceeds the threshold */
+	    if (pmax > threshold) {
+		frame[jk]=1;
+		npoints++;
+	    }
+	}
+    return npoints;
+}
+
+
+/****************************************************************************
+*       Map 1's in pulse ribbon onto (x,y) spiral coords, and store in the
+*       given arrays if the points will appear in the plot window.
+*       Return the number of mapped points within the plot window.
+****************************************************************************/
+map_spiral(frame,Xarray,Yarray,form_spl,zero_spl)
+short *frame;
+short *Xarray, *Yarray;
+char   form_spl;
+float  zero_spl;
+{
+    float  t, f, x, y;
+    float  r0, r, theta;
+    int    i, j, k, X, Y;
+    int    points=0;
+
+    /* for each SAI row (each frequency channel) in turn */
+    for (i=0, k=0 ; i<frameheight ; i++, k+=framewidth+nwid) /* SSS */ 
+	/* for each time sample, working from right to left */
+	for (j=framewidth ; j>=0 ; j--)    /* SSS */
+	    if (frame[j+k] == 1) {          /* for each `1' in pulse ribbon */
+		f = i;
+		t = (framewidth-1) - j ;     /* time origin is on the right  */   
+
+		/* calculate polar coords of point, (r,theta): */
+		/* radius r at outer edge of spiral cycle, (ie at min f) */
+		/* radius r0, at same theta, at min f on previous cycle */
+		if (t > 1)  theta = TWOPI * (log2(t) - zero_spl);
+		else        theta = 0;        /* special case of 1st cycle */
+		if (form_spl == 'A') {        /* spiral == ARCHEMEDIAN */
+		    r = theta;
+		    if (r < 0)  r = 0;
+		    if (r > 0)  r0 = r - TWOPI;
+		    else        r0 = 0;         /* special case of 1st cycle */
+		}
+		if (form_spl == 'L') {          /* spiral == LOGARITHMIC */
+		    r = t;
+		    if (t > 1)  r0 = r/2;
+		    else        r0 = 0;         /* special case of 1st cycle */
+		}
+		/* scale radius r for current frequency f (>= min f) */
+		/* scale such that spiral axis occupies its own channel */
+		r = r - ((f+1)/(frameheight+1)) * (r-r0);
+		/* convert polar to cartesian coords */
+		x = r*cos(theta);
+		y = r*sin(theta);
+		/* Transform into pixel coord system and store point */
+		X = px(x);
+		Y = py(y);
+		if (inbox(X,Y)) {
+		    Xarray[points] =   X;
+		    Yarray[points++] = Y;
+		}
+	    }
+
+    return points;
+}
+
+
+/****************************************************************************
+*  Generate points (X,Y coords) for spiral axis and store in given arrays.
+*  Return the number of points stored.
+****************************************************************************/
+int gen_axis(Xarray,Yarray,naxis,form_spl,zero_spl)
+short *Xarray, *Yarray;
+int    naxis;
+char   form_spl;
+float  zero_spl;
+{
+    int    t;
+    float  r, theta;
+    int    X, Y;
+    float  x, y;
+    int    points=0;
+
+    /* Calculate axis points in data coord system */
+    for (t=100 ; t < naxis ; t++) {
+	theta = TWOPI * (log2((float)t/100) - zero_spl);
+	if (theta < 0) theta = 0;
+	if (form_spl == 'A')    /* spiral == Achemedian */
+	    r = theta;
+	else                    /* spiral == Logarithmic */
+	    r = (float)t/100;
+	x = r*cos(theta);
+	y = r*sin(theta);
+	/* Transform into pixel coord system and store */
+	X = px(x);
+	Y = py(y);
+	if (inbox(X,Y)) {
+	    Xarray[points] =   X;
+	    Yarray[points++] = Y;
+	}
+
+    }
+    return points;
+}
+
+
+
+/****************************************************************************
+*       Plot dots of size d.
+*
+* Plotting in a given window uses the glib routines Draw and Plot.
+* These routines, and associated structures, are declared in windows.h.
+* The WindowObject structure has an "entries" pointer to a WindowEntries
+* structure, and this holds pointers to a set of functions which operate on
+* the window. The window functions, and the routine newDisplayWindow which
+* allocates a new WindowObject, are defined in X.c.
+*
+* void Draw(win,X,Y,points)
+*       Takes two arrays of shorts, one with x-coords the other with y-coords.
+*       The number of x's = the number of y's = "points".
+*       The user must ensure that the data coords are scaled into the pixel
+*       coord system. This is as follows: (1,1) is bottom-left corner, and
+*       (width,height) is top-right corner.
+* void Plot(win,X,Y,points)
+*       Same as Draw, but plots points.
+****************************************************************************/
+plotdots(win,Xspiral,Yspiral,X,Y,npoints,d)
+WindowObject win;
+short *Xspiral, *Yspiral;
+short *X, *Y;
+int    npoints, d;
+{
+    int    x, y, i;
+
+    if (d==0)           /* dotsize = 1 */
+	Plot(win,Xspiral,Yspiral,npoints);
+    else {              /* dotsize > 1 */
+	for (x=(-d) ; x<=d ; x++)
+	    for (y=(-d) ; y<=d ; y++) {
+		for (i=0 ; i<npoints ; i++) {
+		    X[i] = Xspiral[i] + x;
+		    Y[i] = Yspiral[i] + y;
+		}
+		Plot(win,X,Y,npoints);
+	    }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/spiral.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,40 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    spiral.h
+    ========
+
+*/
+
+
+/****************************************************************************
+Externs of definitions in spiral.c.
+These are the drawing routine, and model parameters which it needs to know.
+****************************************************************************/
+extern char    form_spl;
+extern int     dotsize_spl;
+extern int     axis_spl;
+extern double  zero_spl;
+extern int     dotthresh_spl;
+extern void    draw_spiral();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/table.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,231 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+*/
+
+/*
+ table.c - Options tables for model parameters
+
+*/
+
+/***************************************************************************
+* The model options are grouped according to the processing stages which use
+* them. The stages which use each group are listed above each group. These
+* lists contain sub-lists of stages from each model type, (ie, envelope, fine,
+* complex, nonmult, noncalc. See model.c:FindStage() ).
+* The options table for a particular group must be installed in the options
+* field of the stage structure (see model.c:FindStage()) which is the lowest
+* stage (as listed textually in the stage table) of the stages which use that
+* group. In this way, the other stages which use that group will pick up the
+* options when the complete options table is constructed, by accumulating all
+* options groups from a given stage name to the bottom of the stage table.
+* For example, the "auditory filter output" group listed just below is used
+* by stage fbm (a "fine" model), stage bmm (a "nonmult" model), and stages
+* fcp and fcr (both "complex" models). The group options table (fbmopts)
+* should be installed in the stage table in the options fields for the stages
+* fbm, bmm, and fcr. The stage fcp can be assigned NO_OPTS because it will
+* pick up the options from stage fcr when the complete options table is
+* constructed, (see gen.c:constructOptions()).
+*
+* Routes through the model.
+* There are two parallel routes (ie sequential stages of processing):
+* a) an auditory route (conventionally displayed as landscapes).
+* b) a speech route (conventionally displayed as greyscales).
+* Either route is a three-stage model, composed of a sequence of modules.
+* The names of each of the three stages are an alias for the corresponding
+* module at a particular stage of processing. (Eg, genbmm is the first of the
+* three model stages in the auditory route. It is displayed as a landscape.
+* It is an alias for genfbm, and the sequence of modules leading to this is
+* wav,fbm).
+* An additional route displays excitation patterns, which are basically
+* spectra, (for example, genepn is like gennap, but viewed with the frequency
+* axis as the abscissa. Similarly, gensas is like genbmm).
+*
+* Process                       Module     Auditory    Speech    Excitation
+* ----------------------------  ------     --------    -------   ----------
+* Input wave                    genwav
+* Filterbank                    genfbm      genbmm
+* Rectifier                     genfbr
+* Compressor                    genfbc                  gensgm     genasa
+* LP filter                     genfbl
+* Adaptive threshold            genfbt      gennap
+* Integration and downsampling  genfbd                  gencgm     genepn
+* Triggered integration         gensai      gensai
+* Integration and downsampling  gensas                  gensas
+*
+* In addition, there is a spiral mapping of the auditory image, genspl,
+* which is a spiral version of gensai.
+*
+* Note that on the speech route, gensgm is identical to gencgm but with
+* enable_at=off.
+* Originally, gensgm and gencgm were simply aliases for the genfbd module,
+* which were to have distinct parameters using distinct options files.
+*
+****************************************************************************/
+
+
+/******* [fbm] [bmm] [fcp,fcr] stage: "auditory filter output" ************/
+
+static  Option fbmopts[] = {
+
+ { "channels_afb",  chansdflt,  &chansstr, "Number of channels in filter",               InOutOption},
+ {    "mincf_afb",    mindflt,    &minstr, "Minimum center frequency (Hz)",              InOutOption},
+ {    "maxcf_afb",    maxdflt,    &maxstr, "Maximum center frequency (Hz)",              InOutOption},
+ {    "dencf_afb",    dendflt,    &denstr, "Filter density (filters/critical band)",     InOutOption},
+ {   "interp_afb", interpdflt, &interpstr, "Levels of interpolation to apply",          OutputOption},
+ {   "interp_afb", interpdflt, &interpstr, "Levels of interpolation to apply",          SilentOption},
+ {    "bwmin_afb",  limitdflt,  &limitstr, "Minimum filter bandwith",                    InOutOption},
+ {  "quality_afb",   qualdflt,   &qualstr, "Ultimate qualtity factor of filters",        InOutOption},
+ {"audiogram_afb",  audiodflt,  &audiostr, "Audiogram equalisation parameter\n",         InOutOption},
+
+ {    "float_gtf",  floatdflt,  &floatstr, "Floating point filter calculations",        OutputOption},
+ {    "float_gtf",  floatdflt,  &floatstr, "Floating point filter calculations",        SilentOption},
+ {     "gain_gtf",   gaindflt,   &gainstr, "Filter output amplification",                InOutOption},
+ {    "phase_gtf",  phasedflt,  &phasestr, "Phase compensation option",                  InOutOption},
+ {    "order_gtf",  orderdflt,  &orderstr, "Filter order\n",                             InOutOption},
+
+ ( char * ) 0 } ;
+
+/************** [fbr] stage: "rectified filter output" ******************/
+
+static  Option fbropts[] = {
+
+ {      "rectify",   rectdflt,   &rectstr, "Rectify filter output",                      InOutOption},
+
+ ( char * ) 0 } ;
+
+/*********** [fbc] [fec] stage: "compressed filter output" **************/
+
+static  Option fbcopts[] = {
+
+ {     "compress",    logdflt,    &logstr, "Apply log compression",                    InOutOption},
+ {   "compensate",   compdflt,   &compstr, "Cochlea output compressor\n",              InputOption},
+
+ ( char * ) 0 } ;
+
+/*********** [fbu] [feu] stage: "uncompressed filter output" **************/
+
+static  Option fbuopts[] = {
+
+ {        "power",  powerdflt,  &powerstr, "Power of Compression",                      SilentOption},
+
+ ( char * ) 0 } ;
+
+/*********** [fbs] [fes] stage: "saturated filter output" **************/
+
+static  Option fbsopts[] = {
+
+ {     "saturate",    satdflt,    &satstr, "Introduce Saturation of non-linearity\n",   SilentOption},
+
+ ( char * ) 0 } ;
+
+/*********** [fbl] [fel] stage: "low-pass filtered filter output ***********/
+
+static  Option fblopts[] = {
+
+ {       "meddis", meddisdflt, &meddisstr, "Enables Meddis haircell model\n",           OutputOption},
+ {       "meddis", meddisdflt, &meddisstr, "Enables Meddis haircell model\n",           SilentOption},
+
+ {    "igain_lpf", ligaindflt, &ligainstr, "Gain of integration stage\n",               OutputOption},
+ {    "igain_lpf", ligaindflt, &ligainstr, "Gain of integration stage\n",               SilentOption},
+ {    "vloss_lpf", lvlossdflt, &lvlossstr, "Rest level for loss",                       OutputOption},
+ {    "vloss_lpf", lvlossdflt, &lvlossstr, "Rest level for loss",                       SilentOption},
+ {     "loss_lpf",  llossdflt,  &llossstr, "Loss time constant",                        OutputOption},
+ {     "loss_lpf",  llossdflt,  &llossstr, "Loss time constant",                        SilentOption},
+ {    "tdown_lpf",  ldowndflt,  &ldownstr, "Downward time constant in ms",              OutputOption},
+ {    "tdown_lpf",  ldowndflt,  &ldownstr, "Downward time constant in ms",              SilentOption},
+ {      "tup_lpf",    lupdflt,    &lupstr, "Upward time constant in ms",                SilentOption},
+ {   "stages_lpf", lstagedflt, &lstagestr, "Stages of integration\n",                   SilentOption},
+
+ ( char * ) 0 } ;
+
+/*********** [nap,fbt] [fet] stage: "neural activity pattern" **************/
+
+static  Option fbtopts[] = {
+
+ {    "enable_at",    stxdflt,    &stxstr, "Enable adaptive thresholding module",        InOutOption},
+ {     "trise_at",   risedflt,   &risestr, "Threshold adaptation rate (upwards)",        InOutOption},
+ {"t1recovery_at",  rapiddflt,  &rapidstr, "Initial recovery rate relative to filter",   InOutOption},
+ {"t2recovery_at",   fastdflt,   &faststr, "Secondary recovery rate relative to filter", InOutOption},
+ {  "propt2t1_at",   propdflt,   &propstr, "Relative height of secondary adaptation",    InOutOption},
+ { "frecovery_at",    latdflt,    &latstr, "Recovery rate across frequency",             InOutOption},
+ {  "reclimit_at", vdraindflt, &vdrainstr, "Limitation on recovery level\n",             InOutOption},
+
+ {     "times_at",  timesdflt,  &timesstr, "Oversampling of calculation of threshold",  OutputOption},
+ {     "times_at",  timesdflt,  &timesstr, "Oversampling of calculation of threshold",  SilentOption},
+
+ ( char * ) 0 } ;
+
+/*********** [fba] [fea] stage: "adapted transduced filter output" *********/
+
+static  Option fbaopts[] = {
+
+ {   "mmincf_mfb",  minmfdflt,  &minmfstr, "Minimum modulation frequency (Hz)",          InOutOption},
+ {   "mmaxcf_mfb",  maxmfdflt,  &maxmfstr, "Maximum modulation frequency (Hz)",          InOutOption},
+ {   "mdencf_mfb",  denmfdflt,  &denmfstr, "Modulation filter density ",                 InOutOption},
+ {   "stepcf_mfb", stepmfdflt, &stepmfstr, "Step between images\n",                      InOutOption},
+
+ {  "tadaptation",   adapdflt,   &adapstr, "Time constant of long term adaptation\n",   SilentOption},
+
+ ( char * ) 0 } ;
+
+/*********** [fbh] [feh] stage: "hard limited filter output" **************/
+
+static  Option fbhopts[] = {
+
+ {   "hard_limit",   harddflt,   &hardstr, "Hardlimit firing rate before integration\n",OutputOption},
+ {   "hard_limit",   harddflt,   &hardstr, "Hardlimit firing rate before integration\n",SilentOption},
+
+ ( char * ) 0 } ;
+
+/***** [sgm,cgm,fbd,fbi] [fed,fei] stage: "integrated filter output" *******/
+
+static  Option fbiopts[] = {
+
+ {    "igain_idt",  igaindflt,  &igainstr, "Gain of integration stage\n",               OutputOption},
+ {    "igain_idt",  igaindflt,  &igainstr, "Gain of integration stage\n",               SilentOption},
+
+ {    "vloss_idt",  vlossdflt,  &vlossstr, "Rest level for loss",                       OutputOption},
+ {    "vloss_idt",  vlossdflt,  &vlossstr, "Rest level for loss",                       SilentOption},
+ {     "loss_idt",   lossdflt,   &lossstr, "Loss time constant",                        OutputOption},
+ {     "loss_idt",   lossdflt,   &lossstr, "Loss time constant",                        SilentOption},
+ {    "tdown_idt",   downdflt,   &downstr, "Downward time constant in ms",              OutputOption},
+ {    "tdown_idt",   downdflt,   &downstr, "Downward time constant in ms",              SilentOption},
+ {      "tup_idt",     updflt,     &upstr, "Low-pass filter time constant in ms",        InOutOption},
+ {   "stages_idt",  stagedflt,  &stagestr, "Stages of integration\n",                    InOutOption},
+
+ ( char * ) 0 } ;
+
+/*********** [spl,sai] [sie] stage: "stabilized auditory image" ************/
+
+static  Option saiopts[] = {
+
+ {  "napdecay_ai",    cgmdflt,    &cgmstr,  "Neural activity decay time constant",                    InOutOption},
+ {   "ttdecay_ai",     ttdflt,     &ttstr,  "Trigger threshold decay time constant",     InOutOption},
+ {    "utrate_ai",  utlimdflt,  &utlimstr,  "Upper trigger rate limit (Hz)",             InOutOption},
+ {    "ltrate_ai",  ltlimdflt,  &ltlimstr,  "Lower trigger rate limit (Hz)",             InOutOption},
+ {     "decay_ai",  decaydflt,  &decaystr,  "Auditory image decay time constant\n",      InOutOption},
+
+ ( char * ) 0 } ;
+
+/*********** [sas] [sse] stage: "stabilized auditory spectrogram" **********/
+
+static  Option sasopts[] = {
+
+ {     "ulim_sas",   ulimdflt,   &ulimstr,  "Upper integration limit for auditory image",   InOutOption},
+ {     "llim_sas",   llimdflt,   &llimstr,  "Lower integration limit for auditory image\n", InOutOption},
+
+ ( char * ) 0 } ;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/units.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,185 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+*/
+
+/*
+    units.c
+    =======
+
+
+    Unit conversion routines for APU model.
+
+
+
+    Copyright (c), 1989  The Medical Research Council, Applied Psychology Unit.
+
+
+    Author  : John Holdsworth
+    Written : 22th March, 1989.
+
+    Edited  : Mike Allerhand, 1990.
+
+*/
+
+#ifndef  lint
+static char *sccs_id = "@(#)units.c	1.3 John Holdsworth, Mike Allerhand (MRC-APU) 6/6/91" ;
+#endif
+
+
+
+/*********************** Unit conversion routines ***************************
+*  Values are stored as strings.
+*  Units are specified by the final char:
+*    p          sample points.
+*    s          seconds.
+*    b or B     decibels.
+*    Hz         Hertz.
+*  Unit multipliers are specified by the optional penultimate char:
+*    k  kilo  (scale by one thousand).
+*    d  deci  (scale by one tenth).
+*    c  centi (scale by one hundreth).
+*    m  milli (scale by one thousandth).
+*    u        (scale by one millionth).
+*
+*  Examples:    "10p"     time period of 10 sample points
+*               "10ms"    time period of 10 milliseconds
+*               "10kHz"   frequency of 10 kiloHertz
+*
+*  Conversion routines:
+* units( ch )          Multiplier for unit, (k,d,c,m,u).
+* Freq( str )          String to value (eg: 10, 10Hz, 10kHz).
+* Samples( str )       String to value (num samples) (eg: 10p, 10s, 10ms).
+* Scalar( str )        String to value (scalar number), also converts dB's.
+*
+*  Examples:   Freq("10000")    returns 10000
+*              Freq("10kHz")    returns 10000
+*              Samples("3p")    returns 3
+*              Samples("3ms")   return 30  (when the sample rate is 10kHz).
+*              Samples("3")     like "3ms" (milliseconds is default unit).
+*              Scalar("10.")    returns 10
+*              Scalar( "20dB" ) returns 10
+*
+* See also stitch.h for conversion routines:
+*   ToPoints(type,bytes)  Count in bytes to number of points of given type.
+*   ToBytes(type,points ) Number of points of given type to count in bytes.
+*
+* Cycles( str, cfreq )  This is like Samples( str ), except that it also
+*                       allows `c' (cycles) units. A given number of cycles
+*                       of a particular channel are converted to samples.
+*                       This requires the centre frequency of the channel,
+*                       cfreq = frequencies[chan].
+****************************************************************************/
+
+#include <math.h>
+
+#if defined(THINK_C) || defined(NeXT)
+#include <stdlib.h>
+#endif
+
+#include "units.h"
+#include "formulae.h"
+
+extern char *samplestr ;
+
+static double units( ch )
+char ch ;
+{
+    switch( ch ) {
+	case 'k' :
+	    return ( 1000.    ) ;
+	case 'd' :
+	    return ( 0.1      ) ;
+	case 'c' :
+	    return ( 0.01     ) ;
+	case 'm' :
+	    return ( 0.001    ) ;
+	case 'u' :
+	    return ( 0.000001 ) ;
+
+	default :
+	    return ( 1.       ) ;
+    }
+}
+
+double Freq( str )
+char *str ;
+{
+    char *eptr = str + strlen( str ) ;
+    double f ;
+
+    --eptr ;
+
+    if( *eptr == 'e' )
+	return ( FofErbScale( atof( str ) ) * units( *--eptr ) ) ;
+
+    if( *eptr == 'z' )
+	--eptr ;
+
+    if( *eptr == 'H' || *eptr == 'h' )
+	return ( atof( str ) * units( *--eptr ) ) ;
+
+    return ( atof( str ) * units( *eptr ) ) ;
+}
+
+double Samples( str, samplerate )
+char *str ;
+double samplerate ;
+{
+    char *eptr = str + strlen( str ) ;
+
+    switch( *--eptr ) {
+	case 's' : /* seconds */
+	    return ( atof( str ) * samplerate * units( *--eptr ) ) ;
+	case 'p' : /* points  */
+	    return ( atof( str )              * units( *--eptr ) ) ;
+
+	default: /* default to milliseconds for specification of sample parameters */
+	    return ( atof( str ) * samplerate * units( 'm' ) ) ;
+    }
+}
+
+double Scalar( str )
+char *str ;
+{
+    char *eptr = str + strlen( str ) ;
+
+    if( *--eptr == 'B' || *eptr == 'b' )
+	return ( pow( 10., atof( str ) * units( *--eptr ) / 2. ) ) ;
+    else
+	return ( atof( str ) * units( *eptr ) ) ;
+}
+
+double Cycles( str, cfreq, samplerate )
+char   *str ;
+double  cfreq, samplerate ;  /* centre frequency of a particular channel */
+{
+    char *eptr = str + strlen( str ) ;
+
+    /* Look at last char in the string */
+    switch( *--eptr ) {
+	case 's' : /* seconds */
+	    return ( atof( str ) * samplerate * units( *--eptr ) ) ;
+	case 'p' : /* points  */
+	    return ( atof( str )              * units( *--eptr ) ) ;
+	case 'c' : /* cycles  */
+	    return ( atof( str ) * samplerate / cfreq ) ;
+
+	default:   /* default to milliseconds, 'ms' */
+	    return ( atof( str ) * samplerate * units( 'm' ) ) ;
+
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/units.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,20 @@
+/*
+    units.h
+    =======
+
+
+    interface to unit conversion routines for APU model ....
+
+
+*/
+
+
+#define Freq(    _str                      ) freq(    _str                      )
+#define Samples( _str,         _samplerate ) samples( _str,         _samplerate )
+#define Scalar(  _str                      ) scalar(  _str                      )
+#define Cycles(  _str, _cfreq, _samplerate ) cycles(  _str, _cfreq, _samplerate )
+
+extern double freq() ;
+extern double samples() ;
+extern double scalar() ;
+extern double cycles() ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/model/version.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,62 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+*/
+
+/*
+	version.c
+	=========
+
+    APU, ASP model version number.
+
+
+    Copyright (c), 1989  The Medical Research Council, Applied Psychology Unit.
+
+
+    Author  : Mike Allerhand
+    Written : 4th Feb, 1992.
+
+*/
+
+/****************************************************************************
+The version number is the sccs <release-number>.<level-number> of this file.
+This enables:
+	-easy incrementing of the version number for the novice user.
+	-centralised information on model versions, including date of new
+	 version and comments (stored in s.version.c) about the new version.
+
+The level number is incremented using:
+
+	sccs edit   version.c
+	sccs delget version.c
+
+The release number is set to N, (and the level number reset to 1) using:
+
+	sccs edit -rN version.c
+	sccs delget   version.c
+
+Dates and comments for previous versions can be reviewed using:
+	sccs prs version.c
+
+The level and release number can be edited locally (ie not installed) using:
+	sccs  get version.c
+	chmod +w  version.c
+	< edit version_Id and re-make >
+	chmod -w  version.c
+
+****************************************************************************/
+
+
+static char *version_Id = "8.2    4/11/97" ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/changeheader.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,285 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/* ------------------------------------------------------------------------*/
+
+/*  changeheader.c
+*  ----------------
+*
+* 'fakes' sai & nap headers.
+* 
+* M.Akeroyd. Summer 1993. Revised 1994.
+*/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "tip.h"
+
+
+void reset_header_bytes();
+void change_framebytes();
+
+extern char progname[MAX_STRING_LENGTH];
+extern char header[MAX_LINES_HEADER][MAX_LINE_LENGTH];
+
+extern int verboseflag;
+extern int header_lines;        /* number of lines in header */
+
+
+/* .nap parameters */
+
+extern int no_frames;
+extern int frameheight;             /* number of channels */
+extern int framewidth_samples;      /* = 1 
+extern int frameshift_samples;      /* = 1 */ 
+extern int width_win;               /* pixels */
+extern int height_win;              /* pixels */
+extern long samplerate;             /* samples per sec */
+extern int mincf;                   /* Hz */
+extern int maxcf;                   /* Hz */
+
+extern int greyscaleflag;           /* ON or OFF */
+
+
+
+/* ------------------------------------------------------------------------*/
+
+
+
+void changeheader(int no_frames, int new_pwidth, int new_nwidth, int framewidth_samples_output)
+{
+    /* Reset various values:
+     *
+     * number of frames -> no_frames
+     * pwidth -> new_pwidth
+     * nwidth -> new_nwidth
+     * framewidth -> (pwidth+nwidth * samplerate). in msecs
+     * header_bytes
+     *
+     */
+
+  int new_header_length = 0;
+  int counter;
+  char tempstring[MAX_STRING_LENGTH];
+  char tempstring2[MAX_STRING_LENGTH];
+
+
+/*-------------------------------- */
+
+  for(counter=1; counter<=header_lines; counter++){
+
+    /* frames */
+    if (strncmp(header[counter], "frames=", 7) == 0 ) {
+      sprintf(header[counter], "frames=%d\n", no_frames);}
+
+    /* pwidth */
+    if (strncmp(header[counter], "pwidth_aid=", 11) == 0 ) 
+      sprintf(header[counter], "pwidth_aid=%d\n", new_pwidth);
+
+    /* nwidth */
+    /* include a gratuitous minus */
+    if (strncmp(header[counter], "nwidth_aid=", 11) == 0 ) 
+      if (new_nwidth < 0) 
+	sprintf(header[counter], "nwidth_aid=%d\n", new_nwidth);
+      else
+	sprintf(header[counter], "nwidth_aid=-%d\n", new_nwidth);
+
+    /* framewidth */
+    if (strncmp(header[counter], "framewidth=", 11) == 0 ) 
+      sprintf(header[counter], "framewidth=%d\n", framewidth_samples_output);
+
+    /*view=landscape */
+    if (greyscaleflag == ON)
+      if (strncmp(header[counter], "view=landscape", 14) == 0 ) 
+	sprintf(header[counter], "view=greyscale\n");
+
+   }
+
+  /* reset framebytes */
+  change_framebytes();
+
+  /* reset header */
+  reset_header_bytes;
+
+}
+
+
+
+/* ------------------------------------------------------------------------*/
+
+
+void change_framebytes()
+{
+  /* This is seperate beacuse it depends on lots of things 
+   * framebytes -> frameheight * framewidth *2 (bytes), I hope.
+  */
+
+  int counter;
+  char *p_equal=" ";       /* pointer to where the '=' is in the headerline */
+  char tempstring[MAX_STRING_LENGTH];        
+  int local_frameheight = 0;
+  int local_framewidth = 0;
+  
+  /* find out the values */
+
+  for(counter=1; counter<=header_lines; counter++) {
+    if (strncmp(header[counter], "frameheight=", 12) == 0 ) {
+      p_equal = strchr(header[counter], '=');
+      local_frameheight = atoi(++p_equal); }
+    if (strncmp(header[counter], "framewidth=", 11) == 0 ) {
+      p_equal = strchr(header[counter], '=');
+      local_framewidth = atoi(++p_equal); }}
+
+  /* put in new value */
+
+  for(counter=1; counter<=header_lines; counter++){
+    if (strncmp(header[counter], "framebytes=", 11) == 0 ) 
+      sprintf(header[counter], "framebytes=%d\n", (local_framewidth * local_frameheight *2));
+  }      
+}
+
+
+
+/* ------------------------------------------------------------------------*/
+
+
+
+void reset_header_bytes()
+{
+  /* What this code does:
+   * 
+   * My latest attempt to get the "header_bytes" field to be set to the
+   * right number, well, one that AIM accepts.
+   *
+   * At the moment, it assumes 
+   * (1) all headers are an even number of bytes long
+   * (2) the field is 7 characters long 
+   * (3) header_bytes = total length of all strings in header
+                        + 2
+   *
+   */
+
+  int new_header_length = 0;
+  int counter;
+  char tempstring[MAX_STRING_LENGTH];
+  char tempstring2[MAX_STRING_LENGTH];
+
+  /* find out how many bytes there SHOULD be */
+  for(counter=0; counter<=header_lines; counter++) 
+    new_header_length = new_header_length + strlen(header[counter]);
+ 
+  /* If this is odd, change to even.*/
+  if ((new_header_length % 2) == 1) 
+    new_header_length ++;
+
+  /* add 2 to it */
+  new_header_length += 2;
+  
+  /* put lots of zeros on front */
+  sprintf(tempstring, "%d", new_header_length);
+
+  /* add enough zero's on front to make it 7 chars long. 
+   * Since this was the length of the input's field, I don't need to 
+   * worry about it changing the true length of the header */
+  
+  while (strlen(tempstring) != 7 ){
+    strcpy(tempstring2, "0");
+    strcat(tempstring2, tempstring);
+    strcpy(tempstring, tempstring2);}
+
+     
+  /* use this value to reset header_bytes */
+  sprintf(header[0], "header_bytes=%s\n", tempstring);
+
+}
+
+
+
+/* ------------------------------------------------------------------------*/
+
+
+
+void changeheader_B(int new_mincf, int new_maxcf, int new_channels)
+{
+    /* Reset various values:
+     *
+     * mincf == new_mincf
+     * maxcf == new_maxcf
+     * channels = framehieght == new_channels
+     *
+     * NB This assumes "channels=" and "frameheight=" are both set to the
+     * same value. I haven't yet seen a .sai in which they are 
+     * different, but I haven't looked too hard.
+     *
+     */
+
+  int new_header_length = 0;
+  int counter;
+  char tempstring[MAX_STRING_LENGTH];
+  char tempstring2[MAX_STRING_LENGTH];
+
+
+  for(counter=1; counter<=header_lines; counter++){
+
+    /* mincf */
+    if (strncmp(header[counter], "mincf_afb=", 10) == 0 ) {
+      sprintf(header[counter], "mincf_afb=%d\n", new_mincf);}
+
+    /* maxcf */
+    if (strncmp(header[counter], "maxcf_afb=", 10) == 0 ) {
+      sprintf(header[counter], "maxcf_afb=%d\n", new_maxcf);}
+
+    /* channels */
+    if (strncmp(header[counter], "channels_afb=", 12) == 0 ) {
+      sprintf(header[counter], "channels_afb=%d\n", new_channels);}
+
+    /* frameheight */
+    if (strncmp(header[counter], "frameheight=", 12) == 0 ) 
+      sprintf(header[counter], "frameheight=%d\n", new_channels);
+
+  }      
+
+  /* reset framebytes */
+  change_framebytes();
+
+  /* reset header */
+  reset_header_bytes;
+
+}
+
+
+/* The End */
+/* ------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/findintervals_nap.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,119 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/* findintervals_nap.c
+* 
+* Part of the temporal interval stuff.
+* M.Akeroyd Summer 1993.  Revised Winter 1994. */
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "tip.h"
+
+
+
+
+extern struct Peak peak[MAX_PEAKS];    /* all channels */
+extern short interval[MAX_CHANNELS][MAX_DATA];
+extern short clip[MAX_CHANNELS];
+
+extern struct Peak peak_nap_right[MAX_CHANNELS];
+extern struct Peak peak_nap_left[MAX_CHANNELS];
+
+extern short freqdata[MAX_CHANNELS];                
+extern short previousfreqdata[MAX_CHANNELS];
+extern short previouspreviousfreqdata[MAX_CHANNELS];
+
+
+
+
+void find_intervals_nap(int channel, int maximum_interval, int sample)
+{
+  /* What this code does ..
+   *
+   * It looks at the current .nap point. If it's < the previous point, 
+   * AND the previous point is >= the one before that, then the PREVIOUS
+   * point is marked as a peak: peak_nap_right[channel].sample = previous
+   *                            peak_nap_left[channel] = peak_nap_right ..
+   * Then it measures the interval between these two points.
+   * If they are less than the maximum interval, then yippee ...
+   *
+   * The peaks so defined are neither "simple" or "complex", but an
+   * amalgam. A real "complex" peak has its true top interpoltaed. None
+   * of that goes on here. The right-most edge of the plateau
+   * is used ...
+   *
+   * Finally, it moves the columns one notch leftwards.
+   */
+
+  int gap_samples;
+
+
+
+
+  if ((freqdata[channel] < previousfreqdata[channel]) &&
+      (previousfreqdata[channel] >= previouspreviousfreqdata[channel])) {
+    
+    /* this is a peak */
+    peak_nap_left[channel].sample = peak_nap_right[channel].sample;
+    peak_nap_right[channel].sample = sample-1; 
+        /* -1 beacuse its the prevoius point */
+
+    /* don't want to do any of this if this is the FIRST peak of any 
+     * channeL; ie, ...left[].sample == 0 
+     */
+    if (peak_nap_left[channel].sample != 0 ) {
+      gap_samples = peak_nap_right[channel].sample - peak_nap_left[channel].sample;
+      if (gap_samples >= maximum_interval)
+	gap_samples = maximum_interval -1;
+      interval[channel][gap_samples]++; 
+      
+      /* clip check */
+      if (interval[channel][gap_samples] > 32760) {
+	if (clip[channel] == OFF) {
+	  fprintf(stderr, " \nclipping (%i %i) ", channel, gap_samples);
+	  clip[channel] = ON;}
+	interval[channel][gap_samples] --;
+      }
+    }
+  } /* is this a peak? 'if' */
+
+  /* move everything across anyway */
+  previouspreviousfreqdata[channel] = previousfreqdata[channel];
+  previousfreqdata[channel] = freqdata[channel];
+
+}
+
+
+
+
+
+
+/* The End ................................................................*/
+/*.........................................................................*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/findintervals_sai.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,99 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/*------------------------------------------------------------------------*/
+
+/*   findintervals_sai.c 
+*  -----------------------
+*
+* M.Akeroyd. Summer 1993. Revised Winter 1994.
+*/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "tip.h"
+
+
+
+extern struct Peak peak[MAX_PEAKS];    /* all channels */
+extern short interval[MAX_CHANNELS][MAX_DATA];
+extern short clip[MAX_CHANNELS];
+
+extern int weightflag;
+
+
+
+/*------------------------------------------------------------------------*/
+
+
+void find_intervals(int total_peaks, int channel, int maximum_interval)
+{
+  /* WARNING! Reverse */
+
+  int gap_samples;
+  int n;
+
+     
+  for(n=2; n <= total_peaks; n++){
+
+    gap_samples = peak[n-1].sample - peak[n].sample;
+    if (gap_samples >= maximum_interval)
+      gap_samples = maximum_interval -1;
+    interval[channel][gap_samples]++; 
+
+    /*---------------------------------*/
+    /* weighting options */
+
+    if (weightflag == OFF) 
+      interval[channel][gap_samples]++; 
+    else if (weightflag == NORMAL_WEIGHTING)
+      interval[channel][gap_samples] += (short) (peak[n-1].mag + peak[n].mag) / 2 ; 
+    else if (weightflag == LOG_WEIGHTING)
+      interval[channel][gap_samples] += (short) log((peak[n-1].mag + peak[n].mag)/2)/log(10.0);
+
+    /*---------------------------------*/
+    /* clip check */
+    if ((interval[channel][gap_samples] > 32765) || 
+	(interval[channel][gap_samples] < 0)){
+      if (clip[channel] == OFF) {
+	fprintf(stderr, " \nclipping: channel %i, interval %i samples.\n ", channel, gap_samples);
+	clip[channel] = ON;}
+      interval[channel][gap_samples] = 32765;
+    }
+  }
+}
+
+
+
+/* The End */
+/*------------------------------------------------------------------------*/
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/findpeaks.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,256 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/*--------------------------------------------------------------------------*/
+
+/*   findpeaks.c 
+*   -------------
+*
+* Part of the temporal regularity programs
+*
+* M.Akeroyd. Summer 1993. Revised Winter 1994.
+*/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "tip.h"
+
+
+
+
+/*--------------------------------------------------------------------------*/
+
+
+int findpeaksreverse()
+{
+  /* What this code does: 
+   * Its primary job is to find out where the tops of local maxima ("peaks") 
+   * are. Its secondary job is to define the edges of those peaks.
+   * The locations and heights of the peaks are held in the peak[n] structure,
+   * where n is the number of the peak. The edges are held in the 
+   * nextevent[n] structure. 
+   *
+   * Its called 'findpeaksreverse' because it traverses the array from 'right'
+   * (ie, +ve Image Time) to 'left' (-ve Image Time): peaks get numbered
+   * accordingly. eg, if nwidth = 0, then the TriggerPeak is peak 1.
+   *
+   * Edge defintions:
+   *    for a peak n
+   *        nextevent[n] is the LEFT edge (because we are going right-to-left
+   *                                       on samples);
+   *        nextevent[n-1] the RIGHT edge.
+   * 
+   * Peak definitions:
+   *   simple peak:   f(sample - 1 ) <  f(sample)  > f(sample + 1)
+   *   complex peak is a plateau: hopefully the code finds the middle, or 
+   *                the leftedge of the middle (if the middle is an 
+   *                even number of samples)
+   *
+   * Nextevents definitions: 
+   *   minima:      f(sample - 1 ) > f(sample) < f(sample + 1)
+   *   rightzero:   the first f(sample) = 0 to the Right of a peak
+   *   leftzero:       ...       ...       ...     Left ...
+   *                (so, because we're going backwards, the RIGHTZERO of a 
+   *                 peak is actually held in nextevent[n-1], the LEFTZERO 
+   *                 in nextevent[n]).
+   *
+   *
+   * The first and last samples of a channel are dealt with differently, 
+   * if only because the inequalities will crash if the (sample-1) or 
+   * (sample+1) (respectively) don't exist. But I'm not sure if they work 
+   * properly. I'm pretty certain they don't: so, they are just ignored.
+   *
+   * Finally, the number of peaks found is RETURNed.
+   *
+   * 
+   * Version of 21 May 1993. Revised slighlty Winter 1994.
+   */
+
+
+/*---------------------------*/
+
+  extern short inputdata[MAX_DATA];                       
+  extern struct Peak peak[MAX_PEAKS];               
+  extern struct NextEvent nextevent[MAX_NEXTEVENTS];
+  extern char progname[MAX_STRING_LENGTH];
+  extern int framewidth_samples;           /* pwidth + nwidth * samplerate */
+
+  int sample;                              /* left to right */
+  int n = 0;                               /* peak counter: right to left */
+  int zeroflag = OFF;                      /* used within nextevents */   
+  int localsample, flat_top, truesample;   /* All 3 used in finding the 
+					      centre of a plateau */
+
+  /* WARNING: goes from right to left ... */
+
+/*---------------------------*/
+
+  /* do peak check for first sample: its framewidth - 1, because the channel 
+   * starts at 0 */
+  /* NB: removed 18th June 1993*/
+ 
+/*  if (inputdata[framewidth_samples - 1] > inputdata[framewidth_samples -2]){
+*    peak[++n].sample = framewidth_samples - 1;
+*    peak[n].mag = inputdata[framewidth_samples-1];}
+*/
+
+/*---------------------------*/
+
+  /* for the rest of the samples */
+  for (sample=framewidth_samples - 2; sample >= 1; sample--) {
+
+    /* simple peak ?  */
+    if ((inputdata[sample] > inputdata[sample - 1]) && 
+	(inputdata[sample] > inputdata[sample + 1])){
+      peak[++n].sample = sample;
+      peak[n].mag = inputdata[sample];
+      continue;}
+
+    /* complicated peak? ie, a plateau to it  */
+    /* but plateaus on the sides of big peaks don't count ... */
+    if ((inputdata[sample] >= inputdata[sample - 1]) && 
+	(inputdata[sample] > inputdata[sample + 1])){
+      localsample = sample;      /* counter to leftedge of the plateau */
+      flat_top = 1;              /* width, in samples, of the top */
+      truesample = sample;
+      while (inputdata[--localsample] == inputdata[sample]) 
+	flat_top ++;            /* find out the width of the plateau */
+
+      /* is this plateau a mere bump on the edge of a real peak? 
+       * If so, its not a peak.
+       * localsample is just off the leftedge of the plateau */
+      if (inputdata[localsample] > inputdata[localsample+1])
+	continue;
+
+      truesample = sample - (int) (flat_top / 2);  
+            /* I think this ensures it is a leftward as possible */
+      peak[++n].sample = truesample;
+      peak[n].mag = inputdata[truesample];
+      continue;}
+    
+    /*---------------------------*/
+
+    /* nextevents ...  */
+
+    /* This is an errorcheck ...
+     *  If we've reached a LEFTZERO, but the current nextevent is a 
+     *  RIGHTZERO, then something has gone very wrong ...  
+     *  we should have hit a peak on the way, so incrementing the counter */
+    if ((inputdata[sample] == 0) && nextevent[n].type == RIGHTEDGE) {
+      fprintf(stderr, " %s : something's gone wrong: didn't find a peak between two zeros.\n", progname);
+      exit(-1); }
+
+    if ((inputdata[sample] == 0) && (zeroflag == OFF)) {
+      nextevent[n].type = LEFTZERO;
+      nextevent[n].sample = sample;
+      nextevent[n].mag = inputdata[sample]; 
+      zeroflag = ON;
+      continue;}
+
+    if ((inputdata[sample] != 0) && (zeroflag == ON)) {
+      nextevent[n].type = RIGHTZERO;
+      nextevent[n].sample = sample+1;    /* +1 because you can only notice 
+					  * such an event when you are off it,
+					  * and because we are moving 
+					  * in reverse  */
+      nextevent[n].mag = inputdata[sample+1]; 
+      zeroflag = OFF;
+      continue;}
+    
+    /* This next bit removed at some stage */
+    /*	
+     *   if ((inputdata[sample] <= inputdata[sample +1]) && 
+     *       (inputdata[sample] < inputdata[sample -1]) && 
+     *       (nextevent[n].type == NULL)) { 
+     */
+
+    if ((inputdata[sample] <= inputdata[sample +1]) && 
+	(inputdata[sample] < inputdata[sample -1])) {
+      nextevent[n].type = MINIMUM;
+      nextevent[n].sample = sample;
+      nextevent[n].mag = inputdata[sample];
+      continue;}
+ 
+  } /* sample */
+
+/*-----------------------------*/
+      
+  /* repeat for last sample*/
+
+  /*  peak ?  */
+  /*NB: Removed 18th June 1993 */
+  
+  /*  if (inputdata[0] > inputdata[1] ){
+   *    peak[++n].sample = 0;
+   *    peak[n].mag = inputdata[0];}
+   */
+ 
+
+  /* nextevents ... */
+
+  if (inputdata[0] == 0 && zeroflag == OFF) {
+    nextevent[n].type = LEFTZERO;
+    nextevent[n].sample = 0;
+    nextevent[n].mag = inputdata[0]; 
+    zeroflag = ON;}
+  
+  
+  if (inputdata[0] != 0 && zeroflag == ON) {
+    nextevent[n].type = RIGHTZERO;
+    nextevent[n].sample = 0;  /* -1 because you only notice such an event 
+			       * when you've gone past*/
+    nextevent[n].mag = inputdata[0]; 
+    zeroflag = OFF;}
+  
+  if (inputdata[0] < inputdata[1]){
+    nextevent[n].type = MINIMUM;
+    nextevent[n].sample = 0;
+    nextevent[n].mag = inputdata[0]; }
+  
+  if (nextevent[n].type == UNSET) {
+    nextevent[n].type = END_OF_WIDTH;
+    nextevent[n].sample = 0;
+    nextevent[n].mag = inputdata[0]; }
+
+  return n;  /* total number of peaks found, starting at 1 */
+}
+
+
+
+
+/* The End */
+/*--------------------------------------------------------------------------*/
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/header.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,284 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/*-------------------------------------------------------------------------*/
+
+/* header.c 
+* ----------
+*
+* Part of the tr+fg+sai collection
+*
+* temporary version only, until I get architectures sussed:
+* see the comments to 'readheader'
+*
+*
+* M. Akeroyd. 26th May 1993. Revised Winter 1994.
+*
+*/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "tip.h"
+
+
+
+extern char progname[MAX_STRING_LENGTH];
+extern char header[MAX_LINES_HEADER][MAX_LINE_LENGTH];
+
+extern int verboseflag;
+extern int oppositearchflag;    /* ON if reading Sun on DEC, or DEC on Sun.*/
+extern int header_lines;        /* number of lines in header */
+
+
+/* .sai parameters */
+
+extern int no_frames;
+extern int frameheight;             /* number of channels */
+extern int framewidth_samples;      /* pwidth + nwidth * samplerate */
+extern int frameshift_samples;      /* frstep_aid * samplerate */
+extern int pwidth;                  /* in msecs */
+extern int nwidth;                  /* in msecs: NEGATIVE */
+extern int width_win;               /* pixels */
+extern int height_win;              /* pixels */
+extern long samplerate;              /* samples per sec */
+extern int mincf;                   /* Hz */
+extern int maxcf;                   /* Hz */
+
+
+/*-------------------------------------------------------------------------*/
+
+int readheader(FILE *inputfp) 
+{ 
+  /* Version of 20v1993 
+   * This is the latest attempt to get it to READ the required bytes.
+   *
+   * Because the headerlines are of the format "string"="number", 
+   * with no spaces imbetween, there is this hack ... 
+   * 
+   * MAA: Autumn 1993: but see comments below about Sparc10s and 
+   * DECstations.
+   */
+ 
+  char *p_equal=" ";       /* pointer to where the '=' is in the headerline */
+  char tempstring[MAX_STRING_LENGTH];        
+
+  int bytes_required = 0;  /* no. of bytes in header, as in "header_bytes=...
+			    * This is RETURNed */
+  int bytes_loaded = 0;    /* number actually loaded */
+  int counter;
+
+
+
+  /* get first line */
+  header_lines = 0;
+  fgets(header[0], MAX_LINE_LENGTH, inputfp);
+
+  if(strspn(header[0], "header_bytes") == 0) {
+    fprintf(stderr, "%s: is the input an AIM output file?\n", progname);
+    exit(-1);}
+
+  /* find out how many bytes there SHOULD be */
+  p_equal = strchr(header[0], '=');
+  bytes_required = atoi(++p_equal); 
+
+/*---------------------------------*/
+
+  /* loop on remaining lines, saving important information as required */
+
+  while (strncmp(fgets(header[++header_lines], MAX_LINE_LENGTH, inputfp),
+		 "Version=", 8)  != 0) {
+    if (strncmp(header[header_lines], "frameheight=", 12) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      frameheight = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "framewidth=", 11) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      framewidth_samples = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "frames=", 7) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      no_frames = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "frameshift=", 11) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      frameshift_samples = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "samplerate=", 11) == 0 ) {
+      /* For some unknown reason, the samplerate has a "." at the
+       * end of it. 
+       */
+      strncpy(tempstring, header[header_lines], 
+	      (strlen(header[header_lines])-0));
+      p_equal = strchr(tempstring, '=');
+      samplerate = atol(++p_equal); } 
+
+    if (strncmp(header[header_lines], "pwidth_aid=", 11) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      pwidth = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "nwidth_aid=", 11) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      nwidth = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "width_win=", 10) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      width_win = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "height_win=", 11) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      height_win = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "mincf_afb=", 10) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      mincf = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "maxcf_afb=", 10) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      maxcf = atoi(++p_equal); }
+
+  }
+
+/*------------------------------------*/
+
+  /* how many bytes have we loaded ? */
+  for (counter=0; counter<=header_lines; counter++) 
+    bytes_loaded += strlen(header[counter]);
+
+
+  /* include this warning */
+  if (bytes_loaded > bytes_required) {
+    fprintf(stderr, "%s: something's gone wrong ... too many header bytes were loaded.\n");
+    exit(-1);
+  }
+  
+  /* read some more bytes, till we are at the end of the header */
+  for (counter = 1; counter <= (bytes_required - bytes_loaded); counter++) 
+    fgetc(inputfp);
+
+
+/* printf("header.c: bytes_required %i\n", bytes_required); */
+/* printf("header.c: bytes_loaded %i\n", bytes_loaded); */
+
+
+/* MAA: Autumn 1993: Roy noticied that saisummary didn't always work
+*  properly, giving a "negative data" error. The following line is the
+*  standard working hack: load one extra byte of the header.
+*  It might be that the reason I didn't notice before
+*  is that a Sparc10 seems to require this extra byte, but that a DECstation
+*  3100 doesn't. At least when BOTH are reading a DECstation .sai file.
+*  But when they read their 'own' .sai files, it isn't needed.
+*  Therefore this is a byte-swapping bug.
+*/
+/* So, in summary:
+* KEEP this line if reading DEC .sai on a SPARC, or SPARC .sai on a DEC
+* REMOVE this line if reading DEc .sai on a DEC, or SPARC .sai on a SPARC
+*/
+/*     fgetc(inputfp);           /* THIS ONE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+/* MAA: Winter 1994: Changed this bit to the "-oparch" option */
+  if (oppositearchflag == ON) 
+    fgetc(inputfp);           /* THIS ONE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+  
+  return bytes_required; 
+}
+
+
+
+
+/*---------------------------------------------------------------------------*/
+
+
+
+void writeheader(FILE *outputfp)
+{
+  /* Version of 20v1993
+   * The header is written as a sequence of strings. If the total length
+   * is less than the number required ("header_bytes=..."), then send some
+   * NULL bytes, till its the correct length.
+   */
+
+  int counter;
+  int bytes_required = 0;
+  int bytes_outputed = 0;
+  char *p_equal;
+
+
+
+  /* find out how many bytes we are supposed to be writing */
+  p_equal = strchr(header[0], '=');
+  bytes_required = atoi(++p_equal); 
+
+  /* write header; in the process add up the bytes */
+  for(counter=0; counter<=header_lines; counter++) {
+    bytes_outputed += strlen(header[counter]);
+    fputs(header[counter], outputfp);}
+
+  fflush(outputfp);
+
+  /* if we haven't yet sent enough bytes, send some more */
+  for (counter=1; counter<=(bytes_required - bytes_outputed); counter++) 
+    fputc(NULL, outputfp);
+
+
+  /* include this warning */
+  if (bytes_required < bytes_outputed) {
+    fprintf(stderr, "%s: something's gone wrong ... the new header is %i too big.\n", progname, (bytes_outputed - bytes_required));
+    exit(-1);
+  }
+
+}
+
+
+
+
+/*---------------------------------------------------------------------------*/
+
+
+
+void checkheader()
+{
+
+  if (framewidth_samples >= MAX_DATA) {
+    fprintf(stderr, "%s: frames are too wide at %i: only alllowed %i samples\n", progname, framewidth_samples, MAX_DATA);
+    exit(-1); }
+
+  if (frameheight >= MAX_CHANNELS) {
+    fprintf(stderr, "%s: too many channels (%i): only alllowed %i \n", progname, frameheight, MAX_CHANNELS);
+    exit(-1); }
+
+}
+
+
+
+
+/* The End */
+/*---------------------------------------------------------------------------*/
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/inout.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,150 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/*--------------------------------------------------------------------------*/
+
+/*    inout.c 
+*    ----------
+*
+* Some of the data in/out functions.
+*
+* 
+* M. Akeroyd. 26th May 1993. Revised Winter 1994.
+*/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "tip.h"
+
+
+extern short outputfiguredata[MAX_DATA];
+extern short outputgrounddata[MAX_DATA];
+
+extern int verboseflag;
+extern char progname[MAX_STRING_LENGTH];
+
+
+/*---------------------------------------------------------------------------*/
+
+
+FILE *open_file(char filefn[],  FILE *dir_default, int streamtype)
+{
+  /* Opens a file stream associated with filefn[].
+   * If that's null, then the stream is a copy of the dir_default:
+   *    stdin / stdout / stderr.
+   * 'streamtype' is either READ (for "rb") or WRITE ("wb")
+   */
+
+  char tempfilefn[MAX_STRING_LENGTH];
+  FILE *filefp = NULL;
+  
+  if (strcmp(filefn, "") == 0) 
+    filefp = dir_default;
+  else
+    if (streamtype == READ) 
+      filefp = fopen(filefn, "rb");
+    else   /* WRITE */
+      filefp = fopen(filefn, "wb");
+
+  if (filefp == NULL) {
+    fprintf(stderr, " %s : unable to open file %s\n", progname, filefn);
+    exit(-1);}
+   
+
+  return filefp;
+	
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+
+
+
+
+void writedata_output(FILE *outputfp, int samples_to_write)
+{
+  /* writes an array  shorts to outputfp 
+   */
+
+  fwrite(outputfiguredata, 2, samples_to_write, outputfp);
+
+  if (ferror(outputfp)) {
+    fprintf(stderr, "  %s : something's gone wrong: error writing output \n", progname);
+    exit(-1);}
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+
+
+
+void writedata_output_fg(FILE *figurefp, FILE *groundfp, int samples_to_write)
+{
+  /* similar to writedata_output, but uses both figure and ground
+   * arrays 
+   */
+
+  fwrite(outputfiguredata, 2, samples_to_write, figurefp);
+  fwrite(outputgrounddata, 2, samples_to_write, groundfp);
+
+  if (ferror(figurefp)!=0) {
+    fprintf(stderr, "  %s : something's gone wrong: error writing figure \n", progname);
+    exit(-1);}
+
+  if (ferror(groundfp)!=0) {
+    fprintf(stderr, "  %s : something's gone wrong: error writing ground \n", progname);
+    exit(-1);}
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+
+
+
+void close_files(FILE *fp)
+{
+
+  if (verboseflag == ON)
+    fprintf(stderr, "\n");
+
+  fclose(fp);
+ 
+  if ( ferror(fp) != 0) {
+    fprintf(stderr, " %s : error closing file.\n", progname);
+    exit(-1);}
+}
+
+
+/* The End */
+/*---------------------------------------------------------------------------*/
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/makefile	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,143 @@
+#   Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+#   ==========================================================================
+#   Permission to use, copy, modify, and distribute this software without fee 
+#   is hereby granted for research purposes, provided that this copyright 
+#   notice appears in all copies and in all supporting documentation, and that 
+#   the software is not redistributed for any fee (except for a nominal 
+#   shipping charge). Anyone wanting to incorporate all or part of this 
+#   software in a commercial product must obtain a license from the Medical 
+#   Research Council.
+#
+#    The MRC makes no representations about the suitability of this 
+#    software for any purpose.  It is provided "as is" without express or
+#    implied warranty.
+# 
+#   THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+#   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+#   THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+#   OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+#   WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+#   ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+#   SOFTWARE.
+#---------------------------------------------------------------------------
+#
+# makefile for the temporal interval processing programs.
+#
+# M.Akeroyd. June 1993.  Revised Autumn 1993. Rewritten Winter 1994/Summer 1995
+#
+#----------------------------------------------------------------------------
+
+#CC = gcc
+#CFLAGS = -O -s
+#TARFILE = tip.tar
+
+#---------------------------------------------------------------------------
+
+all: saigraph saiinfo napgraph saisummary saicut sairotate 
+
+
+clean:
+	rm -f *.o saigraph saiinfo napgraph saisummary saicut \
+	sairotate $(TARFILE)
+
+tidy: 
+	rm -f *.o
+	
+tar: 
+	tar cvf $(TARFILE) saigraph.c saiinfo.c \
+	findpeaks.c header.c inout.c interval.c  \
+	trigger.c removepeaks.c findintervals_sai.c findintervals_nap.c \
+	napheader.c changeheader.c matrix.c napgraph.c saisummary.c saicut.c \
+	sairotate.c tip.h Copyright.text makefile
+
+
+#----------------------------------------------------------------------------
+
+saigraph: header.o inout.o changeheader.o matrix.o findpeaks.o removepeaks.o \
+	findintervals_sai.o saigraph.o
+	$(CC) $(CFLAGS) -o saigraph header.o inout.o changeheader.o matrix.o \
+	findpeaks.o removepeaks.o findintervals_sai.o saigraph.o \
+	-lm
+
+napgraph: napheader.o header.o changeheader.o matrix.o inout.o napgraph.o \
+	findintervals_nap.o
+	$(CC) $(CFLAGS) -o napgraph napheader.o header.o changeheader.o \
+	matrix.o inout.o findintervals_nap.o napgraph.o
+
+saiinfo: header.o inout.o saiinfo.o
+	$(CC) $(CFLAGS) -o saiinfo header.o inout.o saiinfo.o
+
+saisummary: header.o changeheader.o inout.o matrix.o saisummary.o
+	$(CC) $(CFLAGS) -o saisummary header.o matrix.o changeheader.o \
+	inout.o saisummary.o 
+
+saicut: header.o changeheader.o inout.o saicut.o
+	$(CC) $(CFLAGS) -o saicut header.o changeheader.o inout.o saicut.o -lm
+
+sairotate: header.o changeheader.o inout.o sairotate.o findpeaks.o trigger.o
+	$(CC) $(CFLAGS) -o sairotate header.o changeheader.o inout.o \
+	findpeaks.o trigger.o sairotate.o
+
+
+#--------------------------------------------------------------------------
+
+
+changeheader.o: changeheader.c tip.h
+	$(CC) $(CFLAGS) -c changeheader.c
+
+findintervals_nap.o: findintervals_nap.c tip.h
+	$(CC) $(CFLAGS) -c findintervals_nap.c
+
+findintervals_sai.o: findintervals_sai.c tip.h
+	$(CC) $(CFLAGS) -c findintervals_sai.c
+ 
+findpeaks.o: findpeaks.c  tip.h
+	$(CC) $(CFLAGS) -c findpeaks.c
+
+header.o: header.c  tip.h
+	$(CC) $(CFLAGS) -c header.c 
+
+inout.o: inout.c  tip.h
+	$(CC) $(CFLAGS) -c inout.c
+
+interval.o: interval.c  tip.h
+	$(CC) $(CFLAGS) -c interval.c
+
+matrix.o: matrix.c tip.h
+	$(CC) $(CFLAGS) -c matrix.c
+
+napgraph.o: napgraph.c tip.h
+	$(CC) $(CFLAGS) -c napgraph.c
+
+napheader.o: napheader.c tip.h
+	$(CC) $(CFLAGS) -c napheader.c
+
+removepeaks.o:	removepeaks.c tip.h
+	$(CC) $(CFLAGS) -c removepeaks.c
+
+saicut.o: saicut.c tip.h
+	$(CC) $(CFLAGS) -c saicut.c
+
+saigraph.o: saigraph.c tip.h
+	$(CC) $(CFLAGS) -c saigraph.c
+
+saiinfo.o: saiinfo.c tip.h
+	$(CC) $(CFLAGS) -c saiinfo.c
+
+sairotate.o: sairotate.c tip.h
+	$(CC) $(CFLAGS) -c sairotate.c
+
+saisummary.o: saisummary.c tip.h
+	$(CC) $(CFLAGS) -c saisummary.c
+
+trigger.o: trigger.c  tip.h
+	$(CC) $(CFLAGS) -c trigger.c
+
+saimaxpeak.o: saimaxpeak.c tip.h 
+	$(CC) $(CFLAGS) -c saimaxpeak.c
+
+
+# The End
+# ----------------------------------------------------
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/matrix.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,236 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/*-------------------------------------------------------------------------*/
+
+/*  matrix.c
+*  ----------
+*
+* Writes an interal histogram matrix in two pretty (ascii) formats.
+*
+* M. Akeroyd.  Summer 1993. Revised Winter 1994.
+*/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "tip.h"
+
+extern char progname[MAX_STRING_LENGTH];
+extern int verboseflag;
+extern short interval[MAX_CHANNELS][MAX_DATA];      
+extern short summation[MAX_CHANNELS];
+extern int summationflag;
+
+extern int frameheight;
+
+
+
+/*-------------------------------------------------------------------------*/
+
+
+
+void write_matrix_hori_freq(int framewidth, FILE *outputfigurefp)
+{
+  /* Format of matrix:
+   *
+# (Info on file, inclduing name, pwdith, nwidth, mincf etc goes here)
+# Rows = channels. Columns = intervals (samples)
+# 
+#                               Time Interval (samples)
+#                 0  1  2  3  4  5  6  7  8  9   ..... (framewidth-1)
+# .......................................................................
+ c  frameheight
+ h    ...
+ a    ...
+ n    ...
+ n     4
+ e     3
+ l     2
+ s     1
+ 
+# ......................................................................
+
+   * ALL comment lines have '#' in them.
+   *
+   * The entries are raw numbers: at the moment, no normalisation has taken 
+   * place. So the longer the .sai, the bigger the numbers.
+   *
+   * If the '-s' flag is set, then the row (=channel) sums are printed at 
+   * the end of each ROW.
+   *
+   * This version prints "." instead of zeros.
+   */
+
+
+  int channel, sample;   
+
+  /* rest of header ... */
+  fprintf(outputfigurefp,"# Rows = channels  Columns = intervals (samples)\n");
+  fprintf(outputfigurefp, "# \n");
+
+  /* Top line */
+  fprintf(outputfigurefp, "#    ");
+  for (sample=0; sample<framewidth; sample++)
+    fprintf(outputfigurefp, "%5i ", sample);
+  if (summationflag == ON)
+    fprintf(outputfigurefp, " :   Sum");
+  fprintf(outputfigurefp, "\n");
+
+  
+  /* top tabulation line */
+    fprintf(outputfigurefp, "#    ");
+  for (sample=0; sample<framewidth; sample++)
+    fprintf(outputfigurefp, "......");
+  if (summationflag == ON)
+    fprintf(outputfigurefp, "........");
+  fprintf(outputfigurefp, "\n");
+  
+  /* Main body: NOTE REVERSE ... */
+  for (channel=frameheight; channel >=1; channel --) {
+    fprintf(outputfigurefp, " %2i: ", channel);
+    for (sample = 0; sample < framewidth; sample++){
+      if (interval[channel][sample] == 0) 
+	fprintf(outputfigurefp, "    . ");
+      else 
+	fprintf(outputfigurefp, "%5i ", interval[channel][sample]);
+    }
+
+    if (summationflag == ON)
+      fprintf(outputfigurefp, " : %5i", summation[channel]);
+
+    fprintf(outputfigurefp, "\n");
+  }
+  
+  /* bottom tabulation line */
+  fprintf(outputfigurefp, "#    ");
+  for (sample=0; sample<framewidth; sample++)
+    fprintf(outputfigurefp, "......");
+  if (summationflag == ON)
+    fprintf(outputfigurefp, "........");
+  fprintf(outputfigurefp, "\n");
+
+}
+
+
+
+
+/*-------------------------------------------------------------------------*/
+
+
+
+
+void write_matrix_hori_time(int framewidth, FILE *outputfigurefp)
+{
+  int channel, sample;
+
+  /* Format of matrix:
+   *
+# (Info on file, inclduing name, pwdith, nwidth, mincf etc goes here)
+# Rows = intervals. Columns = channels
+#
+#                               Channels   
+#                     1  2  3  4  5  6  7  8  ... .... (frameheight)
+# ..................................................................
+ T 
+ i      0
+ m  (   1
+ e  s   2
+    a   3
+ I  m  
+ n  p  ...
+ t  l 
+ e  e  ... 
+ r  s
+ v  )  ...
+ a      
+ l   (framewidth-1)
+# .................................................................
+
+   * ALL comment lines have '#' in them.
+   *
+   * The entries are raw numbers: at the moment, no normalisation has taken 
+   * place. So the longer the .sai, the bigger the numbers.
+   *
+   * If the '-s' flag is set, then the row (=channel) sums are printed at 
+   * the end of each ROW.
+   *
+   * This version prints "." instead of zeros.
+   */
+
+
+  /* rest of Header ... */
+  fprintf(outputfigurefp, "# Rows = intervals (samples) Columns = channels\n");
+  fprintf(outputfigurefp, "# \n");
+   
+
+  /* Top line */
+  fprintf(outputfigurefp, "#     ");
+  for (channel=1; channel<=frameheight; channel++)
+    fprintf(outputfigurefp, "%5i ", channel);
+  fprintf(outputfigurefp, "\n");
+  
+  /* top tabulation line */
+  fprintf(outputfigurefp, "#    ");
+  for (channel=1; channel<=frameheight; channel++)
+    fprintf(outputfigurefp, "......");
+  fprintf(outputfigurefp, "\n");
+  
+  /* Main body: NOTE forward ... */
+  for (sample = 0; sample < framewidth; sample++) {
+    fprintf(outputfigurefp, " %4i: ", sample);
+    for (channel=1; channel<=frameheight; channel++)
+      if (interval[channel][sample] == 0) 
+	fprintf(outputfigurefp, "    . ");
+      else 
+	fprintf(outputfigurefp, "%5i ", interval[channel][sample]);
+    fprintf(outputfigurefp, "\n");
+  }
+  
+  /* bottom tabulation line */
+  fprintf(outputfigurefp, "#    ");
+  for (channel=1; channel<=frameheight; channel++)
+    fprintf(outputfigurefp, "......");
+  fprintf(outputfigurefp, "\n");
+
+  if (summationflag == ON) {
+    fprintf(outputfigurefp, "#\n");
+    fprintf(outputfigurefp, "# Sum: ");
+    for (channel=1; channel<=frameheight; channel++)
+      fprintf(outputfigurefp, "%5i ", summation[channel]);
+    fprintf(outputfigurefp, "\n");    
+  }
+}    
+
+
+
+
+/* The End */
+/*-------------------------------------------------------------------------*/
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/napgraph.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,433 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+/* napgraph.c 
+*
+* M. Akeroyd  11th June 1993. Revised Winter 1994.
+*/
+
+
+
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "tip.h"
+
+
+/* Function declarations */
+/*---------------------------------------------------------------------------*/
+
+void parsecommandline (int argc, char *argv[], char inputfn[], char outputfn[]);
+
+int readheader_nap(FILE *inputfp);
+void checkheader();
+void writeheader(FILE *outputfp);
+int fakeheader_sai();
+void changeheader(int no_frames, int new_pwidth, int new_nwidth, int framewidth_samples_output);
+
+void find_intervals_nap(int channel, int maximum_interval, int sample);
+
+void writedata_output (FILE *outputfp, int samples_to_write);
+FILE *open_file (char filefn[], FILE *dir_default, int streamtype);
+
+void write_matrix_hori_time(int framewidth, FILE *outputfigurefp);
+void write_matrix_hori_freq(int framewidth, FILE *outputfigurefp);
+
+
+
+
+/* Data arrays: global */
+/*---------------------------------------------------------------------------*/
+
+
+short freqdata[MAX_CHANNELS];                /* input .nap: a single column */
+short previousfreqdata[MAX_CHANNELS];
+short previouspreviousfreqdata[MAX_CHANNELS];
+short outputdata[MAX_DATA]; 
+short outputfiguredata[MAX_DATA]; 
+short outputgrounddata[MAX_DATA]; 
+
+short interval[MAX_CHANNELS][MAX_DATA];      /* histogram */ 
+short summation[MAX_CHANNELS];
+
+short clip[MAX_CHANNELS];                    /* set to ON of clipping occured*/
+
+
+/* other variables */
+/*---------------------------------------------------------------------------*/
+struct Peak peak[MAX_PEAKS];
+struct Peak peak_nap_right[MAX_CHANNELS];
+struct Peak peak_nap_left[MAX_CHANNELS];
+
+
+/* variables read from header */
+/*---------------------------------------------------------------------------*/
+
+char header[MAX_LINES_HEADER][MAX_LINE_LENGTH];
+int header_lines;
+
+int no_frames;
+int frameheight;             /* number of channels */
+int framewidth_samples;      /* pwidth + nwidth * samplerate */
+int frameshift_samples;      /* frstep_aid * samplerate */
+int pwidth;                  /* in msecs */
+int nwidth;                  /* in msecs: NEGATIVE */
+int width_win;               /* pixels */
+int height_win;              /* pixels */
+long samplerate;             /* samples per sec */
+int mincf;                   /* Hz */
+int maxcf;                   /* Hz */
+
+int no_columns;
+int nap_height;
+int greyscaleflag = OFF;
+
+
+/* misc */
+/*---------------------------------------------------------------------------*/
+
+char progname[MAX_STRING_LENGTH];
+char outputfigurefn[MAX_STRING_LENGTH];
+
+
+int verboseflag = OFF;               /* -v */
+int removeflag = OFF;                /* -r */
+double removevalue = 0.1;
+int widthflag = OFF;                 /* -w */     /* if OFF, use DEFAULT */
+int total_width;                     /* -w */     /* total width of new .sai */
+int asciiflag = OFF;
+int asciireverseflag = OFF;
+int summationflag = OFF;
+int oppositearchflag = OFF;          /* -oparch : see saigraph.c for info */
+
+
+
+/* ...................           Main           .............................*/
+/* ..........................................................................*/
+/* ..........................................................................*/
+
+
+
+void main (int argc, char *argv[])
+{
+  int sample;
+  int n;
+
+  int column, channel;
+  int framewidth_samples_input,
+      framewidth_samples_output;
+  int new_pwidth, 
+         new_nwidth;
+  int header_bytes = 0;
+ 
+  char inputfn[MAX_STRING_LENGTH], 
+       outputbasefn[MAX_STRING_LENGTH];
+
+  FILE *inputfp, *outputfigurefp;
+
+
+  strcpy(progname, argv[0]);
+  strcpy(inputfn, "");
+  strcpy(outputbasefn, "");
+  strcpy(outputfigurefn, "");
+
+  /* parse command line */
+  parsecommandline(argc, argv, inputfn, outputbasefn);
+
+  if (strcmp(outputbasefn, "") == 0) 
+    strcpy(outputfigurefn, "");
+  else {
+    strcpy(outputfigurefn, outputbasefn);
+/*    strcat(outputfigurefn, OUTPUT_EXT);*/
+  }
+
+
+  /* open files */
+  /* default directions are:
+   * input = stdin 
+   * figure = stdout
+   */
+
+  inputfp = open_file(inputfn, stdin, READ);
+  outputfigurefp = open_file(outputfigurefn, stdout, WRITE);
+
+  /* read Header */
+  header_bytes = readheader_nap(inputfp);
+
+  /* do some error-checking on the header, and set the fread pointer 
+   * to the right place */
+  checkheader();
+
+  /* fake the .sai header, but first copy the important variables:
+   *   no of columns (no_frames)
+   *   height (frameheight)
+   */
+  no_columns = no_frames;
+  nap_height = frameheight;
+  header_lines = fakeheader_sai();
+
+  /* reset the variables */
+  framewidth_samples_input = framewidth_samples;
+  if (widthflag == OFF) {
+    new_pwidth = + PWIDTH;
+    new_nwidth = - NWIDTH;}
+  else {
+    new_pwidth = + NEW_PWIDTH;
+    new_nwidth = - (new_pwidth + total_width);}
+
+  framewidth_samples_output = (int) ((int) (abs(new_pwidth) + abs(new_nwidth)) * samplerate ) / 1000;
+  
+  if (framewidth_samples_output >= MAX_DATA) {
+    fprintf(stderr, "%s: new frame is  too wide at %i: only alllowed %i samples\n", progname, framewidth_samples_output, MAX_DATA);
+    exit(-1); }
+
+  
+  /* change header */
+  changeheader(1, new_pwidth, new_nwidth, framewidth_samples_output);
+
+  /* write header */
+  if (asciiflag == OFF) 
+    writeheader(outputfigurefp);
+  else {
+    /* begining of ascii header. The rest depends on the matrix format ... */
+    fprintf(outputfigurefp, "# napgraph output.  %s\n", inputfn);
+    fprintf(outputfigurefp, "# \n");
+    fprintf(outputfigurefp, "# samplerate=%i  pwidth=%d  nwidth=%d  columns=%i ", samplerate, new_pwidth, new_nwidth, no_columns);
+    fprintf(outputfigurefp, " mincf=%i  maxcf=%i  channels=%i \n", mincf, maxcf, nap_height);
+    fprintf(outputfigurefp, "# \n");
+  }
+
+/* --------------------------------------------------------------------------*/
+
+
+  if  (verboseflag==ON) { 
+    fprintf(stderr, " channels "); 
+    fflush(stderr);}
+
+  
+  /* clear arrays */
+  
+  for (channel=0; channel<MAX_CHANNELS; channel++) {
+    previousfreqdata[channel] = previouspreviousfreqdata[channel] = 0;
+    peak_nap_left[channel].sample = 0;
+    peak_nap_right[channel].sample = 0;
+    for(sample=0; sample<MAX_DATA; sample++)
+      interval[channel][sample] = 0;
+    clip[channel] = OFF;
+  }
+
+
+  /* Main loop */
+
+
+/* .....  */
+
+  for (column=1; column<=no_columns; column++) {
+
+    if ((column % 100) == 1 ) { 
+      if (verboseflag==ON) {
+	fprintf(stderr, " %i ", column); 
+	fflush(stderr);}
+    }
+
+    /* load a column's worth of data  */
+    fread (freqdata, 2, (size_t) nap_height, inputfp);
+    
+    /* move everything UP one byte.
+     * Don't know why ... */
+    for (channel=nap_height; channel >=1; channel--)
+      freqdata[channel] = freqdata[channel-1];
+
+    /* This next is a simple input check: if any numbers < 0 , then say so */
+    for(channel=0; channel<nap_height; channel++)
+      if (freqdata[channel] < 0 )  {
+	fprintf(stderr, "%s: something's gone wrong: the data is negative.\n", progname);
+	exit(-1); }
+
+
+    /* the important bits ... */
+    for (channel=1; channel <=nap_height; channel++)
+      find_intervals_nap(channel, framewidth_samples_output, column);
+    
+
+  } /* column */
+
+
+/* --------------------------------------------------------------------------*/
+/* --------------------------------------------------------------------------*/
+
+
+  fflush(stdout);
+
+  /* If required, sum the values */
+  if (summationflag==ON) {
+    /* clear ... */
+    for (channel = 1; channel <= frameheight; channel ++)
+	summation[channel] = 0;
+    /* set ... */
+    for (channel = 1; channel <= frameheight; channel ++)
+      for (sample = 0; sample < framewidth_samples_output; sample++)
+	summation[channel] += interval[channel][sample];
+  }
+
+
+  /* write output */
+
+  if (asciiflag == OFF) {
+    for (channel = 1; channel <= frameheight; channel ++){
+      for (sample = 0; sample < framewidth_samples_output; sample++)
+	outputfiguredata[sample] = interval[channel][sample];
+      writedata_output(outputfigurefp, framewidth_samples_output);
+    }
+  }  
+  else {
+    frameheight = nap_height;
+    if (asciireverseflag == OFF) 
+      write_matrix_hori_freq(framewidth_samples_output, outputfigurefp);
+    else
+      write_matrix_hori_time(framewidth_samples_output, outputfigurefp);
+}    
+
+
+/* --------------------------------------------------------------------------*/
+/* --------------------------------------------------------------------------*/
+
+
+  /* Tidy up and exit */
+  fprintf(stderr, "\n");
+  fclose(inputfp); 
+  fclose(outputfigurefp); 
+ 
+  if ( ferror(inputfp) != 0) {
+    fprintf(stderr, " %s : error closing input file.\n", progname);
+    exit(-1);}
+
+  if ( ferror(outputfigurefp) != 0) {
+    fprintf(stderr, " %s : error closing figure file.\n", progname);
+    exit(-1);}
+
+  exit(0);
+
+} /* Main */
+
+
+
+
+
+
+
+
+/* ..........................................................................*/
+/* ..........................................................................*/
+/* ..........................................................................*/
+/* ..........................................................................*/
+
+
+
+
+
+
+
+
+
+
+void parsecommandline(int argc, char *argv[], char inputfn[], char outputbasefn[])
+{
+  int x=1, helpflag = OFF;
+  int group;
+
+  while (x < argc){
+    if      (!strcmp(argv[x], "-o")) {strcpy(outputbasefn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-output")) {strcpy(outputbasefn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-i")) {strcpy(inputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-input")) {strcpy(inputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-help")) {helpflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-h")) {helpflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-verbose")) {verboseflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-v")) {verboseflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-w")) {widthflag = ON; total_width=atof(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-width")) {widthflag = ON; total_width=atof(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-v")) {verboseflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-r")) { removeflag = ON; removevalue = atof(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-a")) { asciiflag = ON;x+=1;}
+    else if (!strcmp(argv[x], "-ar")) { asciiflag = ON; asciireverseflag=ON; x+=1;}
+    else if (!strcmp(argv[x], "-s")) { summationflag=ON; x+=1;}
+    else if (!strcmp(argv[x], "-g")) { greyscaleflag=ON; x+=1;}
+    else if (!strcmp(argv[x], "-grey")) { greyscaleflag=ON; x+=1;}
+    else if (!strcmp(argv[x], "-gray")) { greyscaleflag=ON; x+=1;}
+    else if (!strcmp(argv[x], "-oparch")) {oppositearchflag = ON; x+=1;}
+    else {fprintf(stderr, "%s: unknown option %s\n", progname, argv[x]);
+	  exit(-1);}
+  }
+  if (helpflag == ON)
+    {
+      fprintf(stderr, "\n");
+      fprintf(stderr, "                         %s\n", progname);
+      fprintf(stderr, " -----------------------------------------------------------\n");
+      fprintf(stderr, " Works out a histogram of peak intervals, from a .nap\n");
+      fprintf(stderr, " Default output is a .sai file: if -a or -ar specified,\n");
+      fprintf(stderr, " then output is a ASCII matrix.\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " The -oparch option is REQUIRED if reading a Sun .sai files \n");
+      fprintf(stderr, " on a DEC cpu or vice-versa.\n");
+      fprintf(stderr, " Add .nap to input filename, .sai to output filename.\n");
+      fprintf(stderr, " -----------------------------------------------------------\n");
+      fprintf(stderr, " -i <.nap file>      input file             default = stdin\n");
+      fprintf(stderr, " -o <.sai file>      output file            default = stdout\n");
+      fprintf(stderr, " -oparch          assume input was generated on an opposing architecture cpu\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " -a                  ASCII output: rows = channels\n");
+      fprintf(stderr, " -ar                 ASCII output: rows = time intervals\n");
+      fprintf(stderr, " -s                  include summations (ASCII only)\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " -w <int>            width of graph.sai (msecs).\n");
+      fprintf(stderr, " -r <fraction>       remove any peaks F(n) < F(n+1) & F(n-1) * fract \n");
+      fprintf(stderr, "                                            default = %.3f\n", removevalue);
+      fprintf(stderr, "\n");
+      fprintf(stderr, " -v                  verbose output (to stderr)\n");
+      fprintf(stderr, " -g                  Change .sai format to 'grayscale'.\n");
+      fprintf(stderr, "\n\n");
+      exit(-1);}
+
+}  
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/napheader.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,323 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+/* napheader.c 
+* ----------
+*
+* The .nap version of header.c
+*
+* M. Akeroyd. 10th June 1993.  Revised Winter 1994.
+*
+*/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "tip.h"
+
+void reset_header_bytes();
+
+
+extern char progname[MAX_STRING_LENGTH];
+extern char header[MAX_LINES_HEADER][MAX_LINE_LENGTH];
+
+extern int verboseflag;
+extern int header_lines;        /* number of lines in header */
+extern int oppositearchflag;    /* ON if reading Sun on DEC, or DEC on Sun.*/
+
+/* .nap parameters */
+
+extern int no_frames;
+extern int frameheight;             /* number of channels */
+extern int framewidth_samples;      /* = 1 */
+extern int frameshift_samples;      /* = 1 */ 
+extern int width_win;               /* pixels */
+extern int height_win;              /* pixels */
+extern long samplerate;              /* samples per sec */
+extern int mincf;                   /* Hz */
+extern int maxcf;                   /* Hz */
+
+
+
+
+int readheader_nap(FILE *inputfp) 
+{ 
+  /* Version of 10vi1993 
+   */
+ 
+  char *p_equal=" ";       /* pointer to where the '=' is in the headerline */
+  char tempstring[MAX_STRING_LENGTH];        
+
+  int bytes_required = 0;  /* no. of bytes in header, as in "header_bytes=...
+			    * This is RETURNed */
+  int bytes_loaded = 0;    /* number actually loaded */
+  int counter;
+
+
+
+  /* get first line */
+  header_lines = 0;
+  fgets(header[0], MAX_LINE_LENGTH, inputfp);
+
+  if(strspn(header[0], "header_bytes") == 0) {
+    fprintf(stderr, "%s: is the input a AIM file?\n", progname);
+    exit(-1);}
+
+  /* find out how many bytes there SHOULD be */
+  p_equal = strchr(header[0], '=');
+  bytes_required = atoi(++p_equal); 
+
+
+/*--------------------------------------------------------------------------*/
+
+  /* loop on remaining lines, saving important information as required */
+
+  while (strncmp(fgets(header[++header_lines], MAX_LINE_LENGTH, inputfp),
+		 "Version=", 8)  != 0) {
+    if (strncmp(header[header_lines], "frameheight=", 12) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      frameheight = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "framewidth=", 11) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      framewidth_samples = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "frames=", 7) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      no_frames = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "frameshift=", 11) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      frameshift_samples = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "samplerate=", 11) == 0 ) {
+      /* For some unknown reason, the samplerate has a "." at the
+       * end of it. 
+       * Well, sometimes.
+       */
+      strncpy(tempstring, header[header_lines], 
+	      (strlen(header[header_lines])-0));
+      p_equal = strchr(tempstring, '=');
+      samplerate = atol(++p_equal); } 
+
+    if (strncmp(header[header_lines], "width_win=", 10) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      width_win = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "height_win=", 11) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      height_win = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "mincf_afb=", 10) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      mincf = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "maxcf_afb=", 10) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      maxcf = atoi(++p_equal); }
+
+  }
+
+/*-------------------------------------------------------------------------*/
+
+/* Test for .nap: both frameshift_samples and framewidth_samples == 1 */
+  if ((framewidth_samples != 1) || (frameshift_samples != 1 )) {
+    fprintf(stderr, " %s : is the input a .nap file?\n", progname);
+    exit(-1);
+  }
+
+/*------------------------------------------------------------------------*/
+
+  /* how many bytes have we loaded ? */
+  for (counter=0; counter<=header_lines; counter++) 
+    bytes_loaded += strlen(header[counter]);
+  
+  /* read some more bytes, till we are at the end of the header */
+  for (counter = 1; counter <= (bytes_required - bytes_loaded); counter++) 
+    fgetc(inputfp);
+
+  /* read some more bytes, till we are at the end of the header */
+  for (counter = 1; counter <= (bytes_required - bytes_loaded); counter++) 
+    fgetc(inputfp);
+
+/* This next bit copied off header.c */
+
+/* MAA: Winter 1994: Changed this bit to the "-oparch" option */
+  if (oppositearchflag == ON) 
+    fgetc(inputfp);           /* THIS ONE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+
+  return bytes_required; 
+}
+
+
+
+
+
+
+
+int  fakeheader_sai()
+{
+  /* What this code does:
+   * 
+   * It builds a "fake" .sai header, so that a .sai can be output
+   * even though a .nap is input. 
+   *
+   * The following bits are copied off the .nap header:
+   *    samplerate
+   *    width_win
+   *    height_win
+   *    frameheight
+   *    frameshift (hopefully this is irrelevant)
+   *    mincf
+   *    maxcf
+   *
+   * The following get set anyway, but are reset to the correct values by
+   * changeheader():
+   *    framewidth
+   *    framebytes
+   *    header_bytes
+   *    frames
+   *    pwidth
+   *    nwidth
+   *
+   * EVERYTHING else is completely fake. The numbers seem to be 
+   * reasonable: for a histogram graph .sai, though, none of them matter.
+   * (Well, I hope not).
+   *
+   * The date is made up as well.
+   */
+
+  int nwidth = -5;    
+  int pwidth = 20;
+  int bytes = 1000;
+  int framebytes=150000;
+  
+  
+/*  strcpy(header[0],  "header_bytes=\n"); */
+  strcpy(header[1],  "llim_sas=1.5c\n");
+  strcpy(header[2],  "ulim_sas=24ms\n");
+  strcpy(header[3],  "decay_ai=15ms\n");
+  strcpy(header[4],  "ltrate_ai=150Hz\n");
+  strcpy(header[5],  "utrate_ai=20Hz\n");
+  strcpy(header[6],  "ttdecay_ai=10\n");
+  strcpy(header[7],  "napdecay_ai=1.25\n");
+  strcpy(header[8],  "orig_spd=3.072\n");
+  strcpy(header[9],  "zeroline_spd=off\n"); 
+/*  strcpy(header[10], "nwidth_aid=-5\n"); */    /* see below */
+/*  strcpy(header[11], "pwidth_aid=20\n"); */    /* see below */
+  strcpy(header[12], "frstep_aid=10\n");
+  strcpy(header[13], "frstep_epn=off\n");
+  strcpy(header[14], "downsample=off\n");
+  strcpy(header[15], "tup_idt=8ms\n");
+  strcpy(header[16], "tdown_idt=1\n");
+  strcpy(header[17], "loss_idt=1\n");
+  strcpy(header[18], "vloss_idt=0\n");
+  strcpy(header[19], "igain_idt=1\n");
+  strcpy(header[20], "stages_idt=off\n");
+  strcpy(header[21], "hard_limit=off\n");
+  strcpy(header[22], "meddis=off\n");
+  strcpy(header[23], "times_at=2\n");
+  strcpy(header[24], "reclimit_at=5\n");
+  strcpy(header[25], "frecovery_at=20.\n");
+  strcpy(header[26], "propt2t1_at=0.5\n");
+  strcpy(header[27], "t2recovery_at=0.2\n");
+  strcpy(header[28], "t1recovery_at=0.6\n");
+  strcpy(header[29], "trise_at=10000.\n");
+  strcpy(header[30], "scale_at=100\n");
+  strcpy(header[31], "ltdown_lpf=1\n");
+  strcpy(header[32], "lloss_lpf=1\n");
+  strcpy(header[33], "lvloss_lpf=0\n");
+  strcpy(header[34], "ligain_lpf=1\n");
+  strcpy(header[35], "compress=on\n");
+  strcpy(header[36], "rectify=off\n");
+  strcpy(header[37], "order_gtf=4\n");
+  strcpy(header[38], "phase_gtf=0\n");
+  strcpy(header[39], "gain_gtf=4.\n");
+  strcpy(header[40], "float_gtf=off\n");
+  strcpy(header[41], "audiogram_afb=on\n");
+  strcpy(header[42], "quality_afb=9.265\n");
+  strcpy(header[43], "bwmin_afb=24.7Hz\n");
+  strcpy(header[44], "interp_afb=off\n");
+  strcpy(header[45], "dencf_afb=off\n");
+/*  strcpy(header[46], "maxcf_afb=6000Hz\n"); */   /* see below */
+/*  strcpy(header[47], "mincf_afb=100Hz\n"); */    /* see below */
+/*  strcpy(header[48], "channels_afb=100\n"); */   /* see below */
+  strcpy(header[49], "bits_wave=12\n");
+  strcpy(header[50], "swap_wave=on\n");
+/*  strcpy(header[51], "samplerate=20000\n");  */  /* see below */
+/*  strcpy(header[52], "frames=10\n"); */          /* see below */
+/*  strcpy(header[53], "frameshift=200\n"); */     /* see below */
+/*  strcpy(header[54], "framewidth=500\n"); */     /* see below */
+/*  strcpy(header[55], "frameheight=100\n"); */    /* see below */
+/*  strcpy(header[56], "framebytes=100000\n"); */  /* see below */
+  strcpy(header[57], "type=short\n");
+  strcpy(header[58], "bytemax=255\n");
+  strcpy(header[59], "header=on\n");
+  strcpy(header[60], "animate_ctn=off\n");
+  strcpy(header[61], "erase_ctn=on\n");
+  strcpy(header[62], "downchannel=off\n");
+  strcpy(header[63], "view=landscape\n");
+  strcpy(header[64], "display=on\n");
+/*  strcpy(header[65], "height_win=400\n"); */    /* see below */
+/*  strcpy(header[66], "width_win=540\n"); */     /* see below */
+  strcpy(header[67], "y0_win=center\n");
+  strcpy(header[68], "x0_win=center\n");
+  strcpy(header[69], "Version=\"AICAP Version R6.3    Mon Jan 00 00:00:00 1900\"\n");
+
+
+
+  /* Fill in the values from .nap
+   * All the ones with "/* ..." next to are set anyway; they are
+   * overwritten with the REAL .sai values in changeheader
+   */
+  
+
+  sprintf(header[0],  "header_bytes=0001000\n");
+  sprintf(header[46], "maxcf_afb=%d\n", maxcf);
+  sprintf(header[47], "mincf_afb=%d\n", mincf);
+  sprintf(header[51], "samplerate=%d\n", samplerate);
+  sprintf(header[52], "frames=%d\n", no_frames);              /* */
+  sprintf(header[53], "frameshift=%d\n", frameshift_samples); 
+  sprintf(header[54], "framewidth=%d\n", framewidth_samples); /* */
+  sprintf(header[48], "channels_afb=%d\n", frameheight);
+  sprintf(header[55], "frameheight=%d\n", frameheight);
+  sprintf(header[56], "framebytes=%d\n", framebytes);         /* */
+  sprintf(header[65], "height_win=%d\n", 400);
+  sprintf(header[66], "width_win=%d\n", 540); 
+  sprintf(header[10], "nwidth_aid=%d\n", nwidth);            /* */
+  sprintf(header[11], "pwidth_aid=%d\n", pwidth);             /* */
+
+  header_lines=69;
+  reset_header_bytes();
+
+  /* RETURN the number of lines */
+  return 69;
+}
+  
+
+
+
+/* The End ...............................................................*/
+/*........................................................................*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/removepeaks.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,117 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/*-------------------------------------------------------------------------*/
+
+/*  removepeaks.c
+*  ---------------
+*
+* M.Akeroyd. Summer 1993. Revised Winter 1994.
+*/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "tip.h"
+
+
+
+
+extern struct Peak peak[MAX_PEAKS];    /* all channels */
+extern struct NextEvent nextevent[MAX_PEAKS];
+
+extern double removevalue;
+extern inputdata[MAX_DATA];
+
+
+
+
+/*-------------------------------------------------------------------------*/
+
+
+
+int removepeaks(int total_peaks)
+{
+  /* What this code does:
+   * 
+   * Its purpose is to remove, completely, any peak that is very small, 
+   * and perhaps shouldn't be regarded as being there. This is because they 
+   * tend to clutter up tents and glaciers.
+   *
+   * So, go through each peak. If F(n) < (F[n-1]*removevalue)  AND 
+   * F(n) < (F[n+1]*removevalue), then remove it. Exactly what samples are 
+   * removed depends on the next events.
+   *
+   * At the end, call findpeaksreverse again, to reset the nextevent counters.
+   * RETURN the new value of total_peaks.
+   *
+   */
+
+  int n;
+  int sample;
+
+/*--------------------------------------*/
+
+  for (n=2; n<total_peaks; n++)
+    
+    if ((peak[n].mag < (int) (peak[n-1].mag * removevalue)) &&
+	(peak[n].mag < (int) (peak[n+1].mag * removevalue))) {
+      /* remove peak */
+      for (sample = peak[n].sample; sample <= nextevent[n-1].sample; sample++)
+	inputdata[sample] = 0;
+      for (sample = peak[n].sample; sample >= nextevent[n].sample; sample--)
+	inputdata[sample] = 0;
+    }
+
+/*--------------------------------------*/
+
+  /* repeat for first and last peaks */
+
+  if (peak[1].mag  < (int) (peak[2].mag * removevalue)) {
+    for (sample = peak[1].sample; sample >= nextevent[1].sample; sample--)
+      inputdata[sample] = 0;
+  }
+
+  n=total_peaks;
+
+  if (peak[n].mag < (int) (peak[n-1].mag * removevalue)) {
+     for (sample = peak[n].sample; sample <= nextevent[n-1].sample; sample++)
+      inputdata[sample] = 0;
+  }
+    
+/*--------------------------------------*/
+  
+  findpeaksreverse();
+  return total_peaks;
+
+}
+      
+
+
+
+/* The End */
+/*-------------------------------------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/saicut.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,450 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+/*    saicut.c
+*   ------------
+*
+*  Cuts out frames or channels (or both) from a .sai
+*  output= .sai
+*   
+*  options:  -frame <start> <end>   (units=frame numbers; INCLUSIVE).
+*            -channel <low> <high>  (units=channel nos; INCLUSIVE).
+*          (both arguments are needed).
+*
+*  When using verbose, those frame numbers that are NOT kept are put in
+*  round brackets ().
+*
+*
+*  M Akeroyd.  June 1993. v1.00  Revised Spring 1994.
+*  Lots of extra options Winter 1995.
+*/
+
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "tip.h"
+
+
+
+
+/* Function declarations */
+/*-------------------------------------------------------------------------*/
+
+void parsecommandline (int argc, char *argv[], char inputfn[], char outputfn[]);
+int readheader(FILE *inputfp);
+void checkheader();
+void writeheader(FILE *outputfp);
+void changeheader(int no_frames, int new_pwidth, int new_nwidth, int framewidthsamples_output);
+void changeheader_B(int new_mincf, int new_maxcf, int new_channels);
+
+void writedata_output (FILE *outputfp, int samples_to_write);
+FILE *open_file (char filefn[], FILE *dir_default, int streamtype);
+
+
+/* Data Arrays */
+/* ------------------------------------------------------------------------*/
+short inputdata[MAX_DATA];
+short inputbychannel[MAX_CHANNELS][MAX_DATA];
+short outputfiguredata[MAX_DATA];
+short outputgrounddata[MAX_DATA];
+
+#define MAX_STROBES 2000
+int strobelocation[MAX_STROBES];       
+
+/* variables read from header */
+/*-------------------------------------------------------------------------*/
+char header[MAX_LINES_HEADER][MAX_LINE_LENGTH];
+int header_lines;
+
+/* .sai parameters */
+int no_frames;
+int frameheight;             /* number of channels */
+int framewidth_samples;      /* pwidth + nwidth * samplerate */
+int frameshift_samples;      /* frstep_aid * samplerate */
+int pwidth;                  /* in msecs */
+int nwidth;                  /* in msecs: NEGATIVE */
+int width_win;               /* pixels */
+int height_win;              /* pixels */
+long samplerate;             /* samples per sec */
+int mincf;                   /* Hz */
+int maxcf;                   /* Hz */
+
+/* parameters read from command line*/
+int framestart;
+int frameend;
+int minchannel;
+int maxchannel;
+
+int cut_timestart;
+int cut_timeend;
+int counter;
+float sum;
+float tempf;
+float timestart, timeend;
+
+/* misc */
+/*-----------------------------------------------------------------------*/
+
+char progname[MAX_STRING_LENGTH];
+char outputfigurefn[MAX_STRING_LENGTH];
+char strobefn[MAX_STRING_LENGTH];
+
+
+int verboseflag = OFF;               /* -v */
+int frameflag = OFF;                 /* -f */
+int channelflag = OFF;               /* -c */
+int greyscaleflag = OFF;             /* Not used: required for compilation */
+int oppositearchflag = OFF;          /* -oparch : see saigraph.c for info */
+int sumflag = OFF;
+int averageflag = OFF;
+int timeflag = OFF;
+int headerflag = ON;
+int strobeflag = OFF;
+int strobevalue = 1;                /* the value used to mark a strobe event in 
+				       the .trigger file */
+int cutthisframe = OFF;
+int infoflag = OFF;
+int forceframeflag = OFF;
+int forceframe = 0;
+int successforceflag = OFF;
+
+/* ...................         Main         ................................*/
+/* .........................................................................*/
+/* .........................................................................*/
+
+
+
+void main (int argc, char *argv[])
+{
+  int n, sample;
+  int frame, channel;
+  int trigger_peak = 0;
+  int header_bytes = 0;
+  int cut_framestart, cut_frameend, cut_no_frames;
+  int cut_minchannel, cut_maxchannel, cut_frameheight;
+  char inputfn[MAX_STRING_LENGTH],  outputbasefn[MAX_STRING_LENGTH];
+  FILE *inputfp, *outputfigurefp;
+  FILE *strobefp;
+  int x, counter, previousx;
+  int nstrobes;
+  short sampledata[2];
+
+/*-------------------------------------*/
+  strcpy(progname, argv[0]);
+  strcpy(inputfn, "");
+  strcpy(outputbasefn, "");
+  strcpy(outputfigurefn, "");
+
+  parsecommandline(argc, argv, inputfn, outputbasefn);
+
+  if (strcmp(outputbasefn, "") == 0) 
+    strcpy(outputfigurefn, "");
+  else {
+    strcpy(outputfigurefn, outputbasefn);
+/*    strcat(outputfigurefn, OUTPUT_EXT);*/
+  }
+
+/*--------------------------------------*/
+  /* open files, read and check header */
+  inputfp = open_file(inputfn, stdin, READ);
+  outputfigurefp = open_file(outputfigurefn, stdout, WRITE);
+  header_bytes = readheader(inputfp);
+  checkheader();
+
+/*-------------------------------------*/
+  /* strobe code */
+  if (strobeflag == ON){
+    strobefp = open_file(strobefn, stderr, READ);
+    /* note 
+     *   add (nwidth * samplerate) to the index
+     *   the frame number is the floor of that + 1 (because it seems to give the correct answer)
+     *   some versions of gensai return a triggerpoint 3 samples across; take the first.
+     */
+    for (x=0; x<MAX_STROBES; x++)
+      strobelocation[x] = 0;
+    x=0; counter=1;
+    previousx=0;
+    while( feof(strobefp) ==0) {
+      fread(sampledata, 2, 1, strobefp);
+      if (sampledata[0] >= strobevalue){
+	if (((x-previousx) <= 2) && (previousx != 0))
+	  /* don't need this trigger */
+	  continue;
+	strobelocation[counter] = x;
+	tempf = (float) strobelocation[counter] + (-1.0 * nwidth * samplerate / 1000.0);
+	tempf = tempf * 1.0 / frameshift_samples;
+	/* tempf = floor(tempf);*/
+	strobelocation[counter] = (int) tempf + 1.0;
+/*	if (verboseflag == ON) 
+	  fprintf(stderr, "strobe %i: %i samples %f (%i frames)\n", counter, x, tempf, (int)strobelocation[counter]);*/
+	previousx=x;
+	counter++;}
+      x++;
+      if (counter >= MAX_STROBES){
+	fprintf(stderr, " %s : too many strobes in .trigger file.\n", progname);
+	exit(-1);}
+    }
+    nstrobes=counter-1;
+    if (infoflag == ON){
+      fprintf(stderr, "using %i frames ", nstrobes);
+      for (counter=1; counter <=nstrobes; counter ++)  
+	fprintf(stderr, " %i", strobelocation[counter]);
+      fprintf(stderr, "\n");}
+    fclose(strobefp);
+  }
+
+/*--------------------------------------*/
+
+  /* reset the frame/channel counters */
+  if (frameflag == ON) {
+    cut_frameend = frameend;
+    cut_framestart = framestart; }
+  else {
+    cut_frameend = no_frames;
+    cut_framestart = 1; }
+
+  if (channelflag == ON) {
+    cut_maxchannel = maxchannel;
+    cut_minchannel = minchannel; }
+  else {
+    cut_maxchannel = frameheight;
+    cut_minchannel = 1; }
+
+  if (timeflag == ON) {
+    cut_timestart = samplerate * timestart/1000;
+    cut_timeend = samplerate * timeend/1000;}
+  else{
+    cut_timestart = 0;
+    cut_timeend = framewidth_samples;}
+
+/*  fprintf(stderr, "%d \n", cut_timestart);*/
+/*  fprintf(stderr, "%d \n", cut_timeend);*/
+
+  cut_no_frames = cut_frameend - cut_framestart + 1;     /* inclusive, so +1 */
+  cut_frameheight = cut_maxchannel - cut_minchannel + 1; /* inclusive, so +1 */
+  if (strobeflag == ON)
+    cut_no_frames = nstrobes;
+
+/*--------------------------------------*/
+/* WARNING: 'time' options are NOT built into the headers yet */
+
+  changeheader(cut_no_frames, pwidth, nwidth, framewidth_samples); 
+  changeheader_B(mincf, maxcf, cut_frameheight);
+  if (headerflag == ON)
+    writeheader(outputfigurefp);
+
+/*--------------------------------------*/
+
+  if  (verboseflag==ON) { 
+    fprintf(stderr, " frames "); 
+    fflush(stderr);}
+
+/*------------------------------------------------------------------------*/
+
+  for (frame=1; frame<=no_frames; frame++) {
+
+    if (strobeflag == OFF) {
+      if ((frame < cut_framestart) || (frame > cut_frameend )) 
+	cutthisframe = OFF;
+      else 
+	cutthisframe = ON;}
+    else {
+      cutthisframe = OFF;
+      for (counter=1; counter <= nstrobes; counter ++){
+	if (frame == strobelocation[counter])
+	  cutthisframe = ON;}}
+
+    if (forceframeflag == ON){
+      if (frame < forceframe){
+	cutthisframe = OFF;}
+      else {
+	if (successforceflag == OFF){
+	  if (cutthisframe == ON){
+	    successforceflag = ON;
+	    fprintf(stdout, "%d\n", frame);}}
+	else 
+	  cutthisframe = OFF;}}
+
+    if (verboseflag == ON) {
+      if (cutthisframe == ON){
+	fprintf(stderr, " %i ", frame); fflush(stderr);}
+      else {
+	fprintf(stderr, " (%i) ", frame); fflush(stderr);}}
+
+    /*--------------------------------------*/
+
+    for (channel=1; channel <=frameheight; channel ++) {
+
+      for(sample=0; sample<framewidth_samples; sample++) 
+	inputdata[sample] = 0;
+
+      fread (inputdata, 2, framewidth_samples, inputfp);
+
+      /* input check */
+      for(sample=0; sample<framewidth_samples; sample++)
+	if (inputdata[sample] < 0 )  {
+	  fprintf(stderr, "%s: something's gone wrong: the data is negative.\n", progname);
+	  exit(-1); }
+
+      for(sample=0; sample<framewidth_samples; sample++) 
+	inputbychannel[channel][sample] = inputdata[sample];
+     
+    } /* (loading of) channel */
+
+    /*--------------------------------------*/
+
+    /* Is this frame to be output? If not, next frame. */
+    if (strobeflag == OFF){
+      if ((frame < cut_framestart) || (frame > cut_frameend ))
+	continue;}
+    else {
+      if (cutthisframe == OFF)
+	continue;}
+       
+    /* output all required channels */
+    for (channel = cut_minchannel; channel <= cut_maxchannel; channel++) {
+      sum = 0.0;
+      counter=0;
+      for(sample=cut_timestart; sample<cut_timeend; sample++) {
+	outputfiguredata[counter] = inputbychannel[channel][sample];
+	if ((sumflag == ON) || (averageflag == ON))
+	  sum += inputbychannel[channel][sample];
+	counter++;}
+
+      if (sumflag == ON){
+	outputfiguredata[0] = (short) sum;
+	counter=1;}
+      if (averageflag == ON){
+	tempf = (float) sum/counter;
+	outputfiguredata[0] = (short) tempf;
+	counter=1;}
+/*      fprintf(stderr, "%f %d \n", sum, outputfiguredata[0]);*/
+
+      writedata_output(outputfigurefp, counter); }
+
+    /*--------------------------------------*/
+
+  } /* frame */
+
+/*----------------------------------------------------------------------*/
+
+  /* Tidy up and exit */
+  if (verboseflag == ON) 
+    fprintf(stderr, "\n");
+  fclose(inputfp);   fclose(outputfigurefp); 
+
+  if ( ferror(inputfp) != 0) {
+    fprintf(stderr, " %s : error closing input file.\n", progname);
+    exit(-1);}
+
+  if ( ferror(outputfigurefp) != 0) {
+    fprintf(stderr, " %s : error closing figure file.\n", progname);
+    exit(-1);}
+
+  exit(0);
+
+} /* Main */
+
+
+
+
+/*......................................................................*/
+/*......................................................................*/
+
+
+
+
+
+void parsecommandline(int argc, char *argv[], char inputfn[], char outputbasefn[])
+{
+  int x=1, helpflag = OFF;
+
+  while (x < argc){
+    if      (!strcmp(argv[x], "-o")) {strcpy(outputbasefn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-output")) {strcpy(outputbasefn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-i")) {strcpy(inputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-t")) {strobeflag=ON; frameflag=OFF;strcpy(strobefn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-input")) {strcpy(inputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-help")) {helpflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-h")) {helpflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-triggerinfo")) {infoflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-sum")) {sumflag = ON; averageflag=OFF; x+=1;}
+    else if (!strcmp(argv[x], "-average")) {sumflag = OFF; averageflag=ON; x+=1;}
+    else if (!strcmp(argv[x], "-header")) {headerflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-noheader")) {headerflag = OFF; x+=1;}
+    else if (!strcmp(argv[x], "-verbose")) {verboseflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-v")) {verboseflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-n")) {forceframeflag=ON; forceframe=atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-f")) {frameflag=ON; framestart=atoi(argv[x+1]); frameend=atoi(argv[x+2]); x+=3;}
+    else if (!strcmp(argv[x], "-frames")) {frameflag=ON; framestart=atoi(argv[x+1]); frameend=atoi(argv[x+2]); x+=3;}
+    else if (!strcmp(argv[x], "-c")) {channelflag=ON; minchannel=atoi(argv[x+1]); maxchannel=atoi(argv[x+2]); x+=3;}
+    else if (!strcmp(argv[x], "-channel")) {channelflag=ON; minchannel=atoi(argv[x+1]); maxchannel=atoi(argv[x+2]); x+=3;}
+    else if (!strcmp(argv[x], "-time")) {timeflag=ON; timestart=atof(argv[x+1]); timeend=atof(argv[x+2]); x+=3;}
+    else if (!strcmp(argv[x], "-oparch")) {oppositearchflag = ON; x+=1;}
+    else {fprintf(stderr, "%s: unknown option %s\n", progname, argv[x]);
+	  exit(-1);}
+  }
+    
+  if (helpflag == ON)
+    {
+      fprintf(stderr, "\n");
+      fprintf(stderr, "                         %s\n", progname);
+      fprintf(stderr, " -----------------------------------------------------------\n");
+      fprintf(stderr, " Cuts a .sai by frame or channel, and (if necessary) just some\n");
+      fprintf(stderr, " of the input image\n");
+      fprintf(stderr, " The -oparch option is REQUIRED if reading a Sun .sai files \n");
+      fprintf(stderr, " on a DEC cpu or vice-versa.\n");
+      fprintf(stderr, " Add .sai to both input and output filenames.\n");
+      fprintf(stderr, " WARNING: the header is not rebuilt properly for the\n");
+      fprintf(stderr, " '-time' options.\n");
+      fprintf(stderr, " -----------------------------------------------------------\n");
+      fprintf(stderr, " -i <.sai file>      input file             default = stdin\n");
+      fprintf(stderr, " -o <.sai file>      output file            default = stdout\n");
+      fprintf(stderr, " -t <.trigger file>  trigger location file\n");
+      fprintf(stderr, " -oparch          assume input was generated on an opposing architecture cpu\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " -n <frame>       take first frame after <frame>\n");
+      fprintf(stderr, " -frames <start>  <end>   (inclusive) (default=all)\n");
+      fprintf(stderr, " -time   <start>  <end>   (inclusive; ms from leftedge)\n");
+      fprintf(stderr, " -channel <low>  <high>   (inclusive) (default=all)\n");
+      fprintf(stderr, " -sum             sum and output 1 value per frame\n");
+      fprintf(stderr, " -average         sum, average & output 1 value per frame\n");
+      fprintf(stderr, " -noheader        don't output a .sai header\n");
+      fprintf(stderr, " -header          do output a .sai header (default)\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " -v               verbose output (to stderr)\n");
+      fprintf(stderr, " -triggerinfo     report the 'trigger' frames (to stderr)");
+      fprintf(stderr, "\n\n");
+      exit(-1);}
+
+}  
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/saigraph.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,465 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/*------------------------------------------------------------------------*/
+
+/*  saigraph.c
+*  --------------
+*  
+* Works out the (first-order) temporal intervals between peaks in a .sai file,
+* and saves them in a SINGLE-FRAME .sai
+* In essence, a histogram.
+*
+* Uses ALL peaks: if you just want the locallly maxima peaks, then use 
+* trbigpeak first.
+*
+* Output is another .sai file: but only a single frame. The header is
+* modified accordingly.
+* 
+*
+*
+* M. Akeroyd.   May 1993.   Version 2.0
+*
+*               Autumn 1993: added grayscaleflag
+*               Winter 1994: allowed weighting, and other general revisions.
+*/
+
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "tip.h"
+
+
+/* Function declarations */
+/*------------------------------------------------------------*/
+
+void parsecommandline (int argc, char *argv[], char inputfn[], char outputfn[]);
+
+int readheader(FILE *inputfp);
+void checkheader();
+void writeheader(FILE *outputfp);
+
+void changeheader(int no_frames, int new_pwidth, int new_nwidth, int framewidth_samples_output);
+
+int findpeaksreverse (); 
+void find_intervals(int total_peaks, int channel, int max_interval);
+
+void writedata_output (FILE *outputfp, int samples_to_write);
+void writedata_output_fg (FILE *figurefp, FILE *groundfp, int samples_to_write);
+FILE *open_file (char filefn[], FILE *dir_default, int streamtype);
+
+void copytooutput_fg_single (int total_peaks, int frame, int channel, int trigger_peak);
+
+void write_matrix_hori_time(int framewidth, FILE *outputfigurefp);
+void write_matrix_hori_freq(int framewidth, FILE *outputfigurefp);
+
+
+
+
+/* Data arrays: global */
+/*-----------------------------------------------------------------*/
+
+
+short inputdata[MAX_DATA];        /* input .sai: a single channel of a frame */
+short outputdata[MAX_DATA];       /* output .sai: a single channel */
+short outputfiguredata[MAX_DATA]; /* output figure.sai: a single channel */
+short outputgrounddata[MAX_DATA]; /* output ground.sai: a single channel */
+short clip[MAX_CHANNELS];
+
+short interval[MAX_CHANNELS][MAX_DATA];      /* histogram */ 
+short summation[MAX_CHANNELS];
+
+
+
+/* other variables */
+/*----------------------------------------------------------------*/
+
+struct Peak peak[MAX_PEAKS];                    /* used in findpeaksreverse():
+						 * single channel */
+struct NextEvent nextevent[MAX_NEXTEVENTS];     /* used in findpeaksreverse():
+						 * single channel */
+
+
+
+/* variables read from header */
+/*---------------------------------------------------------------*/
+
+char header[MAX_LINES_HEADER][MAX_LINE_LENGTH];
+int header_lines;
+
+int no_frames;
+int frameheight;             /* number of channels */
+int framewidth_samples;      /* pwidth + nwidth * samplerate */
+int frameshift_samples;      /* frstep_aid * samplerate */
+int pwidth;                  /* in msecs */
+int nwidth;                  /* in msecs: NEGATIVE */
+int width_win;               /* pixels */
+int height_win;              /* pixels */
+long samplerate;             /* samples per sec */
+int mincf;                   /* Hz */
+int maxcf;                   /* Hz */
+
+
+
+
+/* misc */
+/*-----------------------------------------------------------*/
+
+char progname[MAX_STRING_LENGTH];
+char outputfigurefn[MAX_STRING_LENGTH];
+
+
+int verboseflag = OFF;               /* -v */
+int removeflag = OFF;                /* -r */
+double removevalue = 0.1;            
+int widthflag = OFF;                 /* -width : if OFF, copy pwdith/nwidth 
+				      *      off Input .sai */
+int total_width;                     /* -width : total width of new .sai */
+int asciiflag = OFF;                 /* -a */
+int asciireverseflag = OFF;          /* -ar */
+int summationflag = OFF;             /* -s */
+int greyscaleflag = OFF;             /* -g */
+int weightflag = OFF;             /* -weight */
+int oppositearchflag = OFF;          /* -oparch: if ON, then the header-reading
+				      * code will load one (1) extra byte. This
+				      * is so that Sun .sai/.nap can be read
+				      * on a DEC, and equally the reverse.
+				      * It is NOT required if reading Sun on
+				      * Sun, or DEC on DEC. */
+
+
+
+/*...............           Main           ................................*/
+/*.........................................................................*/
+/*.........................................................................*/
+
+
+
+void main (int argc, char *argv[])
+{
+  int sample;
+  int n;
+
+  int frame, channel;
+  int trigger_peak = 0;
+  int no_peak = 0, total_peaks =0, total_peaks_2;
+  int framewidth_samples_input,
+      framewidth_samples_output;
+  int new_pwidth, 
+      new_nwidth;
+  int header_bytes = 0;
+ 
+  char inputfn[MAX_STRING_LENGTH], 
+       outputbasefn[MAX_STRING_LENGTH];
+
+  FILE *inputfp, *outputfigurefp;
+
+  int clipflag = OFF;
+
+/*-----------------------------------------*/
+
+  strcpy(progname, argv[0]);
+  strcpy(inputfn, "");
+  strcpy(outputbasefn, "");
+  strcpy(outputfigurefn, "");
+
+  /* parse command line */
+  parsecommandline(argc, argv, inputfn, outputbasefn);
+
+  if (strcmp(outputbasefn, "") == 0) 
+    strcpy(outputfigurefn, "");
+  else 
+    strcpy(outputfigurefn, outputbasefn);
+
+
+  /* open files */
+  /* default directions are:
+   * input = stdin 
+   * figure = stdout
+   */
+
+  inputfp = open_file(inputfn, stdin, READ);
+  outputfigurefp = open_file(outputfigurefn, stdout, WRITE);
+
+  /* read Header */
+  header_bytes = readheader(inputfp);
+  checkheader();
+
+
+  /* reset the variables */
+  framewidth_samples_input = framewidth_samples;
+  if (widthflag == OFF) {
+    new_pwidth = + pwidth;
+    new_nwidth = -nwidth;
+    framewidth_samples_output = framewidth_samples_input;}
+  else {
+    new_pwidth = + NEW_PWIDTH;
+    new_nwidth = (new_pwidth + total_width);
+    framewidth_samples_output = (int) ((int) (abs(new_pwidth) + abs (new_nwidth)) * samplerate ) / 1000;}
+
+  if (framewidth_samples_output >= MAX_DATA) {
+    fprintf(stderr, "%s: new frame is  too wide at %i: only allowed %i samples\n", progname, framewidth_samples_output, MAX_DATA);
+    exit(-1); }
+
+
+  /* change header */
+  changeheader(1, new_pwidth, new_nwidth, framewidth_samples_output);
+
+  /* write header */
+  if (asciiflag == OFF) 
+    writeheader(outputfigurefp);
+  else {
+    /* begining of ascii header. The rest depends on the matrix format ... */
+    fprintf(outputfigurefp, "# saigraph output.  %s\n", inputfn);
+    fprintf(outputfigurefp, "# \n");
+    fprintf(outputfigurefp, "# samplerate=%i  pwidth=%d  nwidth=%d  frames=%i ", samplerate, pwidth, nwidth, no_frames);
+    fprintf(outputfigurefp, " mincf=%i  maxcf=%i  channels=%i \n", mincf, maxcf,  frameheight);
+    fprintf(outputfigurefp, "# \n");
+  }
+
+/*------------------------------------------*/
+
+  /* Main loop */
+
+  if  (verboseflag == ON) { 
+    fprintf(stderr, " frames "); 
+    fflush(stderr);}
+
+  
+  /* clear arrays */
+  
+  for (channel=0; channel<MAX_CHANNELS; channel++) {
+    for(sample=0; sample<MAX_DATA; sample++)
+      interval[channel][sample] = 0;
+    clip[channel]=OFF;
+  }
+
+
+  /* reset this, so everything still works */
+  framewidth_samples = framewidth_samples_input;
+
+
+  for (frame=1; frame<=no_frames; frame++) {
+
+    if  (verboseflag == ON) { 
+      fprintf(stderr, " %i ", frame); 
+      fflush(stderr);}
+
+    /*--------------------------------------------*/
+
+    /* load the whole frame's worth of data first */
+
+    for (channel=1; channel <=frameheight; channel ++) {
+
+      /* clear arrays */
+      for(sample=0; sample<framewidth_samples; sample++) 
+	inputdata[sample] = outputdata[sample] = 0;
+      for(n=0; n < MAX_PEAKS; n++){
+	peak[n].tent = UNSET;
+	peak[n].sample=0;}
+
+      /* Nextevents are unnecessary */
+
+      /* load a single channel's worth of data */
+      fread (inputdata, 2, (size_t) framewidth_samples, inputfp);
+
+      /* This next is a simple input check: if any numbers < 0, then say so */
+      for(sample=0; sample<framewidth_samples; sample++)
+	if (inputdata[sample] < 0 )  {
+	  fprintf(stderr, "%s: something's gone wrong: the data is negative.\n", progname);
+	  exit(-1); }
+
+      /* find peaks. WARNING: in reverse */
+      total_peaks = findpeaksreverse();
+
+      /* bin any small peaks ... */
+      if ((removeflag == ON) && (total_peaks !=0 ) ) {
+        total_peaks_2 = removepeaks(total_peaks);
+        for(n=0; n < MAX_PEAKS; n++) {
+          peak[n].tent = UNSET;
+          peak[n].sample = 0;}
+        total_peaks = findpeaksreverse();}
+
+      /* get intervals */
+      find_intervals(total_peaks, channel, framewidth_samples_output);
+
+    } /* channel */
+
+  } /* frame */
+
+
+/*------------------------------------------*/
+/*------------------------------------------*/
+
+
+  fflush(stdout);
+
+
+  /* If required, sum the values */
+  if (summationflag==ON) {
+
+    for (channel = 1; channel <= frameheight; channel ++)
+	summation[channel] = 0;
+
+    for (channel = 1; channel <= frameheight; channel ++) {
+      clipflag = OFF;
+      for (sample = 0; sample < framewidth_samples_output; sample++)
+	summation[channel] += interval[channel][sample];
+
+      /* clip check */
+      if ((summation[channel] > 32765) || 
+	  (summation[channel] < 0)){
+	    if (clipflag == OFF) {
+	      fprintf(stderr, " \nclipping: channel %i, summations.\n ", channel);
+	      clipflag = ON;}
+	    summation[channel] = 32765;
+	  }
+    }
+  }
+
+/*-------------------------------------------*/
+
+  /* write output */
+
+  if (asciiflag == OFF) {
+    for (channel = 1; channel <= frameheight; channel ++){
+      for (sample = 0; sample < framewidth_samples_output; sample++)
+	outputfiguredata[sample] = interval[channel][sample];
+      writedata_output(outputfigurefp, framewidth_samples_output);
+    }
+  }  
+  else {
+    if (asciireverseflag == OFF) 
+      write_matrix_hori_freq(framewidth_samples_output, outputfigurefp);
+    else
+      write_matrix_hori_time(framewidth_samples_output, outputfigurefp);
+  }    
+  
+  /*-------------------------------------------*/
+
+  /* Tidy up and exit */
+    
+  if (verboseflag == ON) 
+    fprintf(stderr, "\n");
+  fclose(inputfp); 
+  fclose(outputfigurefp); 
+ 
+  if ( ferror(inputfp) != 0) {
+    fprintf(stderr, " %s : error closing input file.\n", progname);
+    exit(-1);}
+
+  if ( ferror(outputfigurefp) != 0) {
+    fprintf(stderr, " %s : error closing figure file.\n", progname);
+    exit(-1);}
+
+  exit(0);
+
+} /* Main */
+
+
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+
+
+
+
+void parsecommandline(int argc, char *argv[], char inputfn[], char outputbasefn[])
+{
+  int x=1, helpflag = OFF;
+
+  while (x < argc){
+    if      (!strcmp(argv[x], "-o")) {strcpy(outputbasefn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-output")) {strcpy(outputbasefn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-i")) {strcpy(inputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-input")) {strcpy(inputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-help")) {helpflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-h")) {helpflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-verbose")) {verboseflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-v")) {verboseflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-weight")) {weightflag = NORMAL_WEIGHTING; x+=1;}
+    else if (!strcmp(argv[x], "-weightlog")) {weightflag = LOG_WEIGHTING; x+=1;}
+    else if (!strcmp(argv[x], "-width")) {widthflag = ON; total_width=atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-r")) { removeflag = ON; removevalue = atof(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-a")) { asciiflag = ON;x+=1;}
+    else if (!strcmp(argv[x], "-ar")) { asciiflag = ON; asciireverseflag=ON; x+=1;}
+    else if (!strcmp(argv[x], "-s")) { summationflag=ON; x+=1;}
+    else if (!strcmp(argv[x], "-g")) { greyscaleflag=ON; x+=1;}
+    else if (!strcmp(argv[x], "-grey")) { greyscaleflag=ON; x+=1;}
+    else if (!strcmp(argv[x], "-gray")) { greyscaleflag=ON; x+=1;}
+    else if (!strcmp(argv[x], "-oparch")) { oppositearchflag=ON; x+=1;}
+    else {fprintf(stderr, "%s: unknown option %s\n", progname, argv[x]);
+	  exit(-1);}
+  }
+  
+  if (helpflag == ON)
+    {
+      fprintf(stderr, "\n");
+      fprintf(stderr, "                         %s\n", progname);
+      fprintf(stderr, " -----------------------------------------------------------------------------\n");
+      fprintf(stderr, " Works out a histogram of peak intervals, from a .sai\n");
+      fprintf(stderr, " Default output is a .sai file: if -a or -ar specified,\n");
+
+      fprintf(stderr, " then output is a ASCII matrix.\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " The -oparch option is REQUIRED if reading a Sun .sai files \n");
+      fprintf(stderr, " on a DEC cpu or vice-versa.\n");
+      fprintf(stderr, " Add .sai to both input and output filenames.\n");
+
+      fprintf(stderr, " -----------------------------------------------------------------------------\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " -i <.sai file>      input file             default = stdin\n");
+      fprintf(stderr, " -o <.sai file>      output file            default = stdout\n");
+      fprintf(stderr, " -oparch             assume input was generated on an opposing architecture\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " -a                  ASCII output: rows = channels\n");
+      fprintf(stderr, " -ar                 ASCII output: rows = time intervals\n");
+      fprintf(stderr, " -s                  include summations over time intervals (ASCII options only)\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " -width <int>        width of graph.sai (msecs).\n");
+      fprintf(stderr, " -r <fraction>       remove any peaks F(n) < F(n+1) & F(n-1) * fract \n");
+      fprintf(stderr, "                                            default = %.3f\n", removevalue);
+      fprintf(stderr, " -weight             weight histogram entries by mean height of peaks\n");
+      fprintf(stderr, " -weightlog          as per -weight, but use 10log(mean height)\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " -v                  verbose output (to stderr)\n");
+      fprintf(stderr, " -g                  change .sai 'view' format to 'grayscale'.\n");
+      fprintf(stderr, "\n\n");
+      exit(-1);}
+
+}  
+
+
+
+
+/* The End */
+/*---------------------------------------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/saiinfo.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,232 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+/*  saiinfo.c
+*  --------------
+*  
+* Outputs some useful info from the header of a .sai file
+* Copied from trmaxpeaks.
+* No output
+*
+*
+* M. Akeroyd.   May 1993.  2.00   Revised Winter 1994.
+*
+*
+*/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "tip.h"
+
+
+/* Function declarations */
+/*---------------------------------------------------------------------------*/
+
+void parsecommandline(int argc, char *argv[], char inputfn[], char outputfn[]);
+
+int readheader(FILE *inputfp);
+void checkheader();
+void writeheader(FILE *outputfp);
+
+void writedata_output (FILE *outputfp, int samples_to_write);
+void writedata_output_fg (FILE *figurefp, FILE *groundfp, int samples_to_write);
+FILE *open_file (char filefn[], FILE *dir_default, int streamtype);
+
+
+/* Data arrays: global */
+/*---------------------------------------------------------------------------*/
+
+short outputdata[MAX_DATA];                 /* output */
+short outputfiguredata[MAX_DATA];                 /* output figure.sai: a single channel */
+short outputgrounddata[MAX_DATA];                 /* output ground.sai: a single channel */
+
+
+
+/* variables read from header */
+/*---------------------------------------------------------------------------*/
+
+
+char progname[MAX_STRING_LENGTH];
+char header[MAX_LINES_HEADER][MAX_LINE_LENGTH];
+int header_lines;
+
+/* .sai parameters */
+
+int no_frames;
+int frameheight;             /* number of channels */
+int framewidth_samples;      /* pwidth + nwidth * samplerate */
+int frameshift_samples;      /* frstep_aid * samplerate */
+int pwidth;                  /* in msecs */
+int nwidth;                  /* in msecs: NEGATIVE */
+int width_win;               /* pixels */
+int height_win;              /* pixels */
+long samplerate;            /* samples per sec */
+int mincf;                   /* Hz */
+int maxcf;                   /* Hz */
+
+int oppositearchflag = OFF;          /* -oparch : see saigraph.c for info */
+int verboseflag = OFF;
+
+
+/*........           Main    ........................................*/
+/* ..................................................................*/
+/* ..................................................................*/
+
+
+
+
+void main (int argc, char *argv[])
+{
+
+  int sample;
+  int n;
+
+  int frame, channel;
+  int header_bytes = 0;
+
+  char inputfn[MAX_STRING_LENGTH],
+       outputbasefn[MAX_STRING_LENGTH];
+
+  FILE *inputfp;
+
+
+
+  strcpy(progname, argv[0]);
+  strcpy(outputbasefn, "");
+  strcpy(inputfn, "");
+
+  /* parse command line */
+  parsecommandline(argc, argv, inputfn, outputbasefn);
+
+
+  /* open input files 
+   * default: stdin
+   */
+  inputfp = open_file(inputfn, stdin, READ);
+
+  /* read Header */
+  header_bytes = readheader(inputfp);
+
+  /* do some error-checking on the header, and set the fread pointer to the 
+     right place */
+  checkheader();
+
+
+  /* print important bits */
+
+  fprintf(stdout, "\n");
+  fprintf(stdout, " header_lines  ...  : %5i     header_bytes   ... : %5i\n", header_lines, header_bytes);
+  fprintf(stdout, "\n");
+  fprintf(stdout, " frames   ...  ...  : %5i     channels  ...  ... : %5i\n", no_frames, frameheight);
+  fprintf(stdout, " framewidth_samples : %5i     frameshift_samples : %5i\n", framewidth_samples, frameshift_samples);
+  fprintf(stdout, " pwidth   ...  ...  : %5i     nwidth    ...  ... : %5i\n", pwidth, nwidth);
+  fprintf(stdout, " mincf    ...  ...  : %5i     maxcf     ...  ... : %5i\n", mincf, maxcf);
+  fprintf(stdout, "\n");
+  fprintf(stdout, " window width  ...  : %5i     window height  ... : %5i\n", width_win, height_win);
+  fprintf(stdout, " sampling rate  ..  : %i\n", samplerate);
+  fprintf(stdout, "\n");
+
+      
+
+  /* Tidy up and exit */
+  
+  fclose(inputfp); 
+  
+  if ( ferror(inputfp) != 0) {
+    fprintf(stderr, " %s : error closing input file.\n", progname);
+    exit(-1);}
+
+  exit(0);
+
+} /* Main */
+
+
+
+
+/*  ....................................................................*/
+/*  ....................................................................*/
+/*  ....................................................................*/
+/*  ....................................................................*/
+
+
+
+
+
+
+
+void parsecommandline(int argc, char *argv[], char inputfn[], char outputfn[])
+{
+  int x=1, helpflag = OFF;
+
+
+  while (x < argc){
+    if      (!strcmp(argv[x], "-i")) {strcpy(inputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-input")) {strcpy(inputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-help")) {helpflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-h")) {helpflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-oparch")) {oppositearchflag = ON; x+=1;}
+    /* this next is special ... */
+    else if (argc==2) { strcpy(inputfn, argv[2-1]);x=argc;}
+         else {fprintf(stderr, "%s: unknown option %s\n", progname, argv[x]);
+	       exit(-1);}
+  }
+  
+  if (helpflag == ON)
+    {
+      fprintf(stderr, "\n");
+      fprintf(stderr, "                         %s\n", progname);
+      fprintf(stderr, " -----------------------------------------------------------\n");
+      fprintf(stderr, " prints some useful information from the header of a .sai file \n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " The -oparch option is REQUIRED if reading a Sun .sai files \n");
+      fprintf(stderr, " on a DEC cpu or vice-versa.\n");
+      fprintf(stderr, " Add .sai to both input and output filenames.\n");
+
+      fprintf(stderr, " -----------------------------------------------------------\n");
+      fprintf(stderr, " -i <.sai file>      input file             default = stdin\n");
+      fprintf(stderr, " -oparch          assume input was generated on an opposing architecture cpu\n");
+      fprintf(stderr, "\n");
+      exit(-1);}
+}  
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/sairotate.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,326 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+/*    sairotate.c
+*   ------------
+*
+* 'Rotates' a .sai frame by 90degrees clockwise, so the horizontal
+* scale is frequency, vertical image-time.
+*   
+* If -R is specified, then put the trigger at the top, so ImageTime goes
+*                     down. This is equiv to a 270degree rotation pluse
+*                     a refelction about x=midpoint axis.
+*
+* If -T is specified, then start drawing from the "beginning" of the 
+*                     TriggerPeak (defined as the right nextevent).
+*
+*
+*  M Akeroyd.  June 1993. v1.00  Revised Spring 1994.
+*/
+
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "tip.h"
+
+
+
+
+/* Function declarations */
+/*-------------------------------------------------------------------------*/
+
+void parsecommandline (int argc, char *argv[], char inputfn[], char outputfn[]);
+int readheader(FILE *inputfp);
+void checkheader();
+void writeheader(FILE *outputfp);
+void changeheader(int no_frames, int new_pwidth, int new_nwidth, int framewidthsamples_output);
+void changeheader_B(int new_mincf, int new_maxcf, int new_channels);
+
+void writedata_output (FILE *outputfp, int samples_to_write);
+FILE *open_file (char filefn[], FILE *dir_default, int streamtype);
+
+int findpeaksreverse (); 
+int find_trigger(int frame, int channel, int total_peaks);
+
+
+/* Data Arrays */
+/* ------------------------------------------------------------------------*/
+short inputdata[MAX_DATA];
+short inputbychannel[MAX_CHANNELS][MAX_DATA];
+short outputfiguredata[MAX_DATA];
+short outputgrounddata[MAX_DATA];
+
+
+/* other variables */
+/*-------------------------------------------------------------------------*/
+
+struct Peak peak[MAX_PEAKS];
+struct NextEvent nextevent[MAX_NEXTEVENTS];
+
+
+/* variables read from header */
+/*-------------------------------------------------------------------------*/
+char header[MAX_LINES_HEADER][MAX_LINE_LENGTH];
+int header_lines;
+
+/* .sai parameters */
+int no_frames;
+int frameheight;             /* number of channels */
+int framewidth_samples;      /* pwidth + nwidth * samplerate */
+int frameshift_samples;      /* frstep_aid * samplerate */
+int pwidth;                  /* in msecs */
+int nwidth;                  /* in msecs: NEGATIVE */
+int width_win;               /* pixels */
+int height_win;              /* pixels */
+long samplerate;             /* samples per sec */
+int mincf;                   /* Hz */
+int maxcf;                   /* Hz */
+
+/* parameters read from command line*/
+int framestart;
+int frameend;
+int minchannel;
+int maxchannel;
+
+
+/* misc */
+/*-----------------------------------------------------------------------*/
+
+char progname[MAX_STRING_LENGTH];
+char outputfigurefn[MAX_STRING_LENGTH];
+
+int verboseflag = OFF;               /* -v */
+int trigger_bottomflag = ON;         /* -R ("lots of rotation" */
+int triggerflag = OFF;               /* -T */
+int greyscaleflag = OFF;             /* Not used: required for compilation */
+int oppositearchflag = OFF;          /* -oparch : see saigraph.c for info */
+
+/* ...................         Main         ................................*/
+/* .........................................................................*/
+/* .........................................................................*/
+
+
+
+void main (int argc, char *argv[])
+{
+  int n, sample;
+  int frame, channel;
+  int trigger_peak = 0;
+  int header_bytes = 0;
+  int cut_framestart, cut_frameend, cut_no_frames;
+  int cut_minchannel, cut_maxchannel, cut_frameheight;
+  char inputfn[MAX_STRING_LENGTH],  outputbasefn[MAX_STRING_LENGTH];
+  FILE *inputfp, *outputfigurefp;
+  int total_peaks;
+
+
+/*-------------------------------------*/
+  strcpy(progname, argv[0]);
+  strcpy(inputfn, "");
+  strcpy(outputbasefn, "");
+  strcpy(outputfigurefn, "");
+
+  parsecommandline(argc, argv, inputfn, outputbasefn);
+
+  if (strcmp(outputbasefn, "") == 0) 
+    strcpy(outputfigurefn, "");
+  else {
+    strcpy(outputfigurefn, outputbasefn);
+/*    strcat(outputfigurefn, OUTPUT_EXT);*/
+  }
+
+/*--------------------------------------*/
+  /* open files, read and check header */
+  inputfp = open_file(inputfn, stdin, READ);
+  outputfigurefp = open_file(outputfigurefn, stdout, WRITE);
+  header_bytes = readheader(inputfp);
+  checkheader();
+
+/*--------------------------------------*/
+
+  /* reset the frame/channel counters 
+   * framewidth -> frameheight 
+   * framehieght -> framewidth
+   * (it seems that onlr framewidth has an affect on 'gensai -use':
+   * pwidth/nwidth, nor mincf/maxcf don't do anything)
+   */
+
+  changeheader(no_frames, pwidth, nwidth, frameheight); 
+  changeheader_B(mincf, maxcf, framewidth_samples);
+
+  writeheader(outputfigurefp);
+
+/*--------------------------------------*/
+
+  if  (verboseflag==ON) { 
+    fprintf(stderr, " frames "); 
+    fflush(stderr);}
+
+/*------------------------------------------------------------------------*/
+
+  for (frame=1; frame<=no_frames; frame++) {
+    if  (verboseflag==ON) {
+	fprintf(stderr, " %i ", frame); fflush(stderr);}
+
+    /*--------------------------------------*/
+
+    for (channel=1; channel <=frameheight; channel ++) {
+      
+      for(n=0; n < MAX_PEAKS; n++) { 
+        peak[n].tent = UNSET;
+        nextevent[n].type = UNSET;}
+
+      for(sample=0; sample<framewidth_samples; sample++) 
+	inputdata[sample] = 0;
+
+      fread (inputdata, 2, framewidth_samples, inputfp);
+
+      /* input check */
+      for(sample=0; sample<framewidth_samples; sample++)
+	if (inputdata[sample] < 0 )  {
+	  fprintf(stderr, "%s: something's gone wrong: the data is negative.\n", progname);
+	  exit(-1); }
+
+      if (triggerflag == ON) {
+	/* find peaks */
+	total_peaks = findpeaksreverse();
+	/* find the trigger peak */
+	trigger_peak = 0;
+	trigger_peak = find_trigger(frame, channel, total_peaks);
+	/* from its rightwards nextevent onwards, set everything to zero.*/
+	for (sample = nextevent[trigger_peak-1].sample; sample<framewidth_samples; sample++)
+	  inputdata[sample] = 0;
+      }
+	
+      for(sample=0; sample<framewidth_samples; sample++) 
+	inputbychannel[channel][sample] = inputdata[sample];
+     
+    } /* (loading of) channel */
+
+    /*--------------------------------------*/
+
+    /* Write output */
+    if (trigger_bottomflag == ON ) {
+      /* write this frame, rotated through 90 degrees 
+       * Trigger goes at top */
+      for(sample= framewidth_samples-1; sample >= 0; sample--) {
+	for(channel = 1; channel <= frameheight; channel++) 
+	  outputfiguredata[(channel-1)] = inputbychannel[channel][sample];
+	writedata_output(outputfigurefp, frameheight); } }
+    else {
+      /* write this frame, rotated through 270 degrees (but with a mirror on 
+       * centre freq as well) 
+       * Trigger goes at bottom */
+      for(sample=0; sample<framewidth_samples; sample++) {
+	for(channel = 1; channel <= frameheight; channel++) 
+	  outputfiguredata[(channel-1)] = inputbychannel[channel][sample];
+	writedata_output(outputfigurefp, frameheight); }
+    }
+
+
+    /*--------------------------------------*/
+
+  } /* frame */
+
+/*----------------------------------------------------------------------*/
+
+  /* Tidy up and exit */
+  fprintf(stderr, "\n");
+  fclose(inputfp);   fclose(outputfigurefp); 
+
+  if ( ferror(inputfp) != 0) {
+    fprintf(stderr, " %s : error closing input file.\n", progname);
+    exit(-1);}
+
+  if ( ferror(outputfigurefp) != 0) {
+    fprintf(stderr, " %s : error closing figure file.\n", progname);
+    exit(-1);}
+
+  exit(0);
+
+} /* Main */
+
+
+
+
+/*......................................................................*/
+/*......................................................................*/
+
+
+
+
+
+void parsecommandline(int argc, char *argv[], char inputfn[], char outputbasefn[])
+{
+  int x=1, helpflag = OFF;
+
+  while (x < argc){
+    if      (!strcmp(argv[x], "-o")) {strcpy(outputbasefn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-output")) {strcpy(outputbasefn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-i")) {strcpy(inputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-input")) {strcpy(inputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-help")) {helpflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-h")) {helpflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-verbose")) {verboseflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-v")) {verboseflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-T")) {triggerflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-oparch")) {oppositearchflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-R")) {trigger_bottomflag = OFF; x+=1;}
+    else {fprintf(stderr, "%s: unknown option %s\n", progname, argv[x]);
+	  exit(-1);}
+  }
+  
+  if (helpflag == ON)
+    {
+      fprintf(stderr, "\n");
+      fprintf(stderr, "                         %s\n", progname);
+      fprintf(stderr, " -----------------------------------------------------------\n");
+      fprintf(stderr, " Rotates / reflects  a .sai. Default is start at nwidth=max,\n");
+      fprintf(stderr, " and put the trigger at the bottom (90 deg rotation)\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " The -oparch option is REQUIRED if reading a Sun .sai files \n");
+      fprintf(stderr, " on a DEC cpu or vice-versa.\n");
+      fprintf(stderr, " Add .sai to both input and output filenames.\n");
+      fprintf(stderr, " -----------------------------------------------------------\n");
+      fprintf(stderr, " -i <.sai file>      input file             default = stdin\n");
+      fprintf(stderr, " -o <.sai file>      output file            default = stdout\n");
+      fprintf(stderr, " -oparch          assume input was generated on an opposing architecture cpu\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " -T                  start at the TriggerPeak\n");
+      fprintf(stderr, " -R                  put Trigger at top (270 deg)\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " -v                  verbose output (to stderr)\n");
+      fprintf(stderr, "\n\n" );
+      exit(-1);}
+
+}  
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/saisummary.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,533 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+/*---------------------------------------------------------------------------*/
+/* 
+* saisummary
+*
+* builds a summary .sai 
+* Output is one channel.
+*
+* M. Akeroyd.   May 1993.  Version 2.0
+*               Revised Winter 1994.
+* revised Autumn 1993.
+* variuos fiddles added Summer 1994.
+* (and some new options)
+* and some more Spring 1995.
+* and more Summer 1995.
+*/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "tip.h"
+
+
+
+/* Function declarations */
+/*---------------------------------------------------------------------------*/
+
+
+void parsecommandline(int argc, char *argv[], char inputfn[], char outputfn[]);
+
+int readheader(FILE *inputfp);
+void checkheader();
+void writeheader(FILE *outputfp);
+
+void writedata_output (FILE *outputfp, int samples_to_write);
+FILE *open_file (char filefn[], FILE *dir_default, int streamtype);
+void copytooutput_single(int no_peaks, int frame, int channel, int trigger_peak);
+
+int findpeaksreverse();
+int findbigpeaks(int total_peaks);
+void integratebigpeaks(int total_bigpeaks);
+
+void changeheader(int no_frames, int new_pwidth, int new_nwidth, int framewidth_samples_output);
+void changeheader_B(int new_mincf, int new_maxcf, int new_channels);
+
+void write_matrix_hori_time(int framewidth, FILE *outputfigurefp);
+
+
+
+/* Data arrays: global */
+/*--------------------------------------------------------------------------*/
+
+
+short inputdata[MAX_DATA];
+short outputdata[MAX_DATA];
+short outputfiguredata[MAX_DATA];
+short outputgrounddata[MAX_DATA];
+float summary[MAX_DATA];
+float framesummary[MAX_DATA];
+
+short interval[MAX_CHANNELS][MAX_DATA];   /* required for matrix.c */
+short summation[MAX_CHANNELS];            /* required for matrix.c */ 
+
+int clip[MAX_DATA];
+
+/* other variables */
+/*-------------------------------------------------------------------------*/
+
+
+/* variables read from header */
+/*-------------------------------------------------------------------------*/
+
+char header[MAX_LINES_HEADER][MAX_LINE_LENGTH];
+int header_lines;
+
+
+
+/* .sai parameters */
+/*-------------------------------------------------------------------------*/
+
+int no_frames;
+int frameheight;             /* number of channels */
+int framewidth_samples;      /* pwidth + nwidth * samplerate */
+int frameshift_samples;      /* frstep_aid * samplerate */
+int pwidth;                  /* in msecs */
+int nwidth;                  /* in msecs: NEGATIVE */
+int width_win;               /* pixels */
+int height_win;              /* pixels */
+long samplerate;             /* samples per sec */
+int mincf;                   /* Hz */
+int maxcf;                   /* Hz */
+
+
+
+
+
+/* misc */
+/*---------------- ---------------------------------------------------------*/
+
+char progname[MAX_STRING_LENGTH];
+char outputfigurefn[MAX_STRING_LENGTH];
+
+
+int verboseflag = OFF;               /* -v */
+int summationflag = OFF;
+int frameflag = OFF;                 /* -f */
+int asciiflag = OFF;
+int greyscaleflag = OFF;
+int divideflag = OFF;
+
+int oppositearchflag = OFF;          /* -oparch : see saigraph.c for info */
+
+int nstopflag = ON;
+int nwarnflag = OFF;
+int n32760flag = OFF;
+int n0flag = OFF;
+int headeroutputflag = ON;
+int singleframeflag = OFF;
+int frameaverageflag = ON;
+int specificchannelflag = OFF;
+int cutchannels[MAX_CHANNELS];
+int nchannels=0;
+
+int framestart;   
+int frameend;
+int cut_framestart;
+int cut_frameend;
+
+
+/* ..............           Main           .............................*/
+/* .....................................................................*/
+/* .....................................................................*/
+
+
+
+
+void main (int argc, char *argv[])
+{
+  int sample;
+  int n;
+
+  int frame, channel;
+  int trigger_peak = 0;
+  int no_peak = 0, total_peaks =0;
+  int total_bigpeaks = 0;
+  int trueframeheight = 0;
+  int header_bytes = 0;
+
+  double temp;
+ 
+  char inputfn[MAX_STRING_LENGTH], 
+       outputbasefn[MAX_STRING_LENGTH];
+
+  FILE *inputfp, *outputfigurefp;
+
+  strcpy(progname, argv[0]);
+  strcpy(inputfn, "");
+  strcpy(outputbasefn, "");
+  strcpy(outputfigurefn, "");
+
+  for (n=0; n<MAX_CHANNELS; n++)
+    cutchannels[n] = OFF;
+
+  /* parse command line */
+  parsecommandline(argc, argv, inputfn, outputbasefn);
+
+/*    for (n=0; n<MAX_CHANNELS; n++)
+      if (cutchannels[n] == ON)
+	fprintf(stderr, "%d\n", n);
+*/
+  if (specificchannelflag == OFF)
+    for (n=0; n<MAX_CHANNELS; n++)
+      cutchannels[n] = ON;
+  
+  if (strcmp(outputbasefn, "") == 0) 
+    strcpy(outputfigurefn, "");
+  else {
+    strcpy(outputfigurefn, outputbasefn);
+  /*  strcat(outputfigurefn, OUTPUT_EXT);*/
+  }
+
+  /* open files */
+  /* default directions are:
+   * input = stdin 
+   * figure = stdout
+   */
+
+  inputfp = open_file(inputfn, stdin, READ);
+  outputfigurefp = open_file(outputfigurefn, stdout, WRITE);
+
+  /* read Header */
+  header_bytes = readheader(inputfp);
+
+  /* do some error-checking on the header, and set the fread 
+   * pointer to the right place */
+  checkheader();
+
+  if (frameflag == ON) {
+    cut_frameend = frameend;
+    cut_framestart = framestart; }
+  else {
+    cut_frameend = no_frames;
+    cut_framestart = 1; }
+
+  if (frameflag == ON)
+    changeheader((cut_frameend - cut_framestart + 1), pwidth, nwidth, framewidth_samples);
+
+  if (singleframeflag == ON)
+    changeheader(1, pwidth, nwidth, framewidth_samples);
+
+  /* reset the variables */
+  /* arguments: mincf  maxcf  channels */
+  changeheader_B(0, 0, 1);  
+  
+  /* write header */
+  if (singleframeflag == OFF) {
+    if ((asciiflag == OFF) && (headeroutputflag == ON))
+      writeheader(outputfigurefp);
+    else ;}
+  else {
+    if ((asciiflag == OFF) && (headeroutputflag == ON))
+      writeheader(outputfigurefp);
+    else if (asciiflag == ON){
+      /* begining of ascii header. The rest depends upon the output format. */
+      fprintf(outputfigurefp, "# saisummary output. %s\n", inputfn);
+      fprintf(outputfigurefp, "# \n");
+      fprintf(outputfigurefp, "# samplerate=%i  pwidth=%d  nwidth=%d  frameheight=%i\n", samplerate, pwidth, nwidth, frameheight);
+      fprintf(outputfigurefp, "# \n");
+    }}
+
+
+/*---------------------------------------------------------------------------*/
+
+  /* Main loop */
+
+
+  if  (verboseflag==ON) { 
+    fprintf(stderr, " frames "); 
+    fflush(stderr);}
+
+  for(sample=0; sample<framewidth_samples; sample++) 
+    framesummary[sample] = 0.0;
+
+  for (frame=1; frame<=no_frames; frame++) {
+    if  (verboseflag==ON) {
+      fprintf(stderr, " %i ", frame);
+      fflush(stderr);}
+
+    for(sample=0; sample<framewidth_samples; sample++) {
+      interval[1][sample] = outputfiguredata[sample] = 0;
+      summary[sample] = 0.0;
+      clip[sample] = OFF;}
+
+/*---------------------------------------------------------------------------*/
+
+    nchannels=0;
+    for (channel=1; channel <=frameheight; channel ++) {
+
+      /* clear arrays */
+      for(sample=0; sample<framewidth_samples; sample++)
+        inputdata[sample] = 0;
+
+      /* load data */
+      fread (inputdata, 2, (size_t) framewidth_samples, inputfp);
+
+      /* This next is a simple input check: */
+      /* revised for various warnings */
+      for(sample=0; sample<framewidth_samples; sample++) {
+/*	  fprintf(stderr, "data: %i  sample: %i channel: %i \n", inputdata[sample], sample, channel);*/
+        if (inputdata[sample] < 0 )  {
+	  if (nstopflag == ON) {
+	    if (verboseflag == ON) fprintf(stderr, "\n");
+	    fprintf(stderr, "%s: negative data: ", progname);
+	    fprintf(stderr, "%i  sample: %i channel: %i \n", inputdata[sample], sample, channel);
+	    fprintf(stderr, "bye.\n");
+	    exit(-1);}
+	  if (nwarnflag == ON){
+	    if (verboseflag == ON) fprintf(stderr, "\n");
+	    fprintf(stderr, "warning: negative data: %i  (sample: %i channel: %i)\n", inputdata[sample], sample, channel);}
+	  if (n0flag == ON)
+	    inputdata[sample] = 0;
+	  else if (n32760flag == ON)
+	    inputdata[sample] = 32760;}}
+
+      /* add data to the summary autoco: outputfigurefp */
+      if ((frame >= cut_framestart) && (frame <= cut_frameend)){
+	if (cutchannels[channel] == ON){
+	  nchannels ++;
+	  /*fprintf(stderr, "c%d ", channel);*/
+	  for(sample=0; sample<framewidth_samples; sample++)
+	    summary[sample] += (double) inputdata[sample];}
+	/*fprintf(stderr, "%d hello\n", channel);*/
+      }
+    } /* channel */
+
+/*    fprintf(stderr, "c%d ", nchannels);*/
+    /* divide everything by no. of channels */
+    if (divideflag == ON) {
+      for(sample=0; sample<framewidth_samples; sample++){
+	temp = (double) summary[sample] / nchannels;
+	if ( ( temp > 32760.0)||( temp < 0)) {
+	  if (clip[sample] == OFF) {
+	    fprintf(stderr, "\nclipping: time interval %i\n", sample);
+	    clip[sample] = ON; }
+	  temp = 32761.0; }
+	interval[1][sample] = outputfiguredata[sample] = (short) temp; }}
+    else {
+      for(sample=0; sample<framewidth_samples; sample++){
+	temp = (double) summary[sample];
+	if (( temp > 32760.0) || (temp < 0.0)){
+	  if (clip[sample] == OFF) {
+	    fprintf(stderr, "\nclipping: time interval %i\n", sample);
+	    clip[sample] = ON; }
+	  temp = 32761.0; }
+	interval[1][sample] = outputfiguredata[sample] = (short) temp; }}
+
+    /* This next is a simple output check: */
+    for(sample=0; sample<framewidth_samples; sample++)
+      if (outputfiguredata[sample] < 0 )  {
+	fprintf(stderr, " %s : something's gone wrong: the output data is negative. \n", progname);
+	exit(-1); }
+
+    /* if required, sum the values */
+    if (summationflag == ON) {
+       /* clear ... */
+       summation[1] = 0;
+       clip[0] = OFF;
+       /* set ... */
+       for (sample=0; sample < framewidth_samples; sample++) {
+         summation[1] += interval[1][sample];
+	 /* clip check */
+	 if (( summation[1] > 32760 )||(summation[1] < 0 )) {
+	   if (clip[0] == OFF) {
+	     fprintf(stderr, "\nclipping: summation\n");
+	     clip[0] = ON; }
+	   summation[1] = 32761;}}
+
+    }
+
+    /* add to frame average */
+    if ((frame >= cut_framestart) && (frame <= cut_frameend)){
+      for (sample=0; sample < framewidth_samples; sample++) 
+	framesummary[sample] += outputfiguredata[sample];
+    }
+
+    /* write output: outputfiguredata[] for the .sai
+     *               interval[] & summation[] for the ascii
+     * Note hack for frameheight
+     * BUT: not if only 1 frame is to be output 
+     */
+
+    if ((frame >= cut_framestart) && (frame <= cut_frameend)){    
+      if (singleframeflag == OFF) {
+	if (asciiflag == OFF)
+	  writedata_output(outputfigurefp, framewidth_samples);
+	else {
+	  trueframeheight=frameheight;
+	  frameheight=1;
+	  write_matrix_hori_time(framewidth_samples, outputfigurefp);
+	  frameheight=trueframeheight; }}
+      else ;
+    }
+
+/* -------------------------------------------------------------------------*/
+
+  }  /* frame */
+
+    if (singleframeflag == ON) {
+      if (verboseflag == ON) {
+	fprintf(stderr, " averaging ");
+	fflush(stderr);}
+      clip[0] = OFF;
+      for (sample=0; sample < framewidth_samples; sample++) {
+	if (frameaverageflag == ON)
+	  temp = framesummary[sample]/(cut_frameend - cut_framestart + 1);
+	else
+	  temp = framesummary[sample];
+	/* clip check */
+	if (temp > 32760) {
+	    if (clip[0] == OFF) {
+	      fprintf(stderr, "\nclipping: frameaverage at sample %i\n", sample);
+	      clip[0] = ON; }
+	    temp = 32760;}
+	outputfiguredata[sample]= (short)temp;
+	interval[1][sample] = outputfiguredata[sample];}
+      if (asciiflag == OFF)
+	writedata_output(outputfigurefp, framewidth_samples);
+      else {
+	trueframeheight=frameheight;
+	frameheight=1;
+	write_matrix_hori_time(framewidth_samples, outputfigurefp);
+	frameheight=trueframeheight; }}
+    else ;
+
+
+  /* Tidy up and exit */
+  fprintf(stderr, "\n");
+  fclose(inputfp); 
+  fclose(outputfigurefp); 
+ 
+  if ( ferror(inputfp) != 0) {
+    fprintf(stderr, " %s : error closing input file.\n", progname);
+    exit(-1);}
+
+  if ( ferror(outputfigurefp) != 0) {
+    fprintf(stderr, " %s : error closing figure file.\n", progname);
+    exit(-1);}
+
+  exit(0);
+
+} /* Main */
+
+
+
+
+
+
+/*  .....................................................................*/
+/*  .....................................................................*/
+/*  .....................................................................*/
+/*  .....................................................................*/
+
+
+
+
+
+
+void parsecommandline(int argc, char *argv[], char inputfn[], char outputfn[])
+{
+  int x=1, helpflag = OFF;
+  int group;
+
+  while (x < argc){
+    if      (!strcmp(argv[x], "-o")) {strcpy(outputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-output")) {strcpy(outputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-i")) {strcpy(inputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-input")) {strcpy(inputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-help")) {helpflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-h")) {helpflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-verbose")) {verboseflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-v")) {verboseflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-s")) {summationflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-g")) {greyscaleflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-gray")) {greyscaleflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-grey")) {greyscaleflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-ar")) {asciiflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-d")) {divideflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-channels")) {specificchannelflag = ON; 
+					     x+=1;
+					     while (x<argc){
+					       if ((int) strspn(argv[x], "-") == 0)
+						 cutchannels[atoi(argv[x])]=ON;
+					       else break;
+					       x++;}}
+    else if (!strcmp(argv[x], "-oneframe")) {singleframeflag = ON; frameaverageflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-sumframe")) {singleframeflag = ON; frameaverageflag = OFF; x+=1;}
+    else if (!strcmp(argv[x], "-oparch")) {oppositearchflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-nstop")) {nstopflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-header")) {headeroutputflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-noheader")) {headeroutputflag = OFF; x+=1;}
+    else if (!strcmp(argv[x], "-nwarn")) {nwarnflag = ON; nstopflag = OFF; x+=1;}
+    else if (!strcmp(argv[x], "-nignore")) {nwarnflag = OFF; nstopflag = OFF; x+=1;}
+    else if (!strcmp(argv[x], "-n0")) {n0flag = ON; n32760flag = OFF; nstopflag = OFF; x+=1;}
+    else if (!strcmp(argv[x], "-n32760")) {n0flag = OFF; n32760flag = ON; nstopflag = OFF; x+=1;}
+    else if (!strcmp(argv[x], "-frames")) {frameflag=ON; framestart=atoi(argv[x+1]); frameend=atoi(argv[x+2]); x+=3;}
+
+    else {fprintf(stderr, "%s: unknown option %s\n", progname, argv[x]);
+	  exit(-1);}
+  }
+  
+  if (helpflag == ON)
+    {
+      fprintf(stderr, "\n");
+      fprintf(stderr, "                         saisummary\n");
+      fprintf(stderr, " -----------------------------------------------------------\n");
+      fprintf(stderr, " Works out a summary image (cf a summary autocorrelogram).\n");
+      fprintf(stderr, " The -oparch option is REQUIRED if reading a Sun .sai files \n");
+      fprintf(stderr, " on a DEC cpu or vice-versa.\n");
+      fprintf(stderr, " Add .sai to both input and output filenames.\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " -i <.sai file>      input file             default = stdin\n");
+      fprintf(stderr, " -o <.sai file>      output file            default = stdout\n");
+      fprintf(stderr, " -oparch          assume input was generated on an opposing architecture cpu\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " -frames <start>  <end>   (inclusive) (default=all)\n");
+      fprintf(stderr, " -channels <> <> .....   specify channel numbers to be included (1++)\n");
+      fprintf(stderr, " -d               divide by no. of channels (Warning: precision may be lost).\n");
+      fprintf(stderr, " -ar              ASCII output: rows=time intervals (requires -oneframe)\n");
+      fprintf(stderr, " -s               include summations (ascii only)\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " -header          include AIM header in output file (default)\n");
+      fprintf(stderr, " -noheader        don't  ...  ...  ... \n");
+      fprintf(stderr, " -v               verbose output (to stderr)\n");
+      fprintf(stderr, " -g               change .sai format to 'grayscale'\n");
+      fprintf(stderr, " -oneframe        average frames together; one (1) output frame\n");
+      fprintf(stderr, " -sumframe        sum frames together; one (1) output frame\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, " -nstop           if negative inputs found, stop processing (default)\n");
+      fprintf(stderr, " -nwarn           if negative inputs found, continue (but warn user) \n");
+      fprintf(stderr, " -nignore         if negative inputs found, continue \n");
+      fprintf(stderr, " -n0              if negative inputs found, replace with 0 \n");
+      fprintf(stderr, " -n32760          if negative inputs found, replace with 32760 \n");
+      fprintf(stderr, "\n\n");
+      exit(-1);}
+}  
+
+/* The End. */
+/*------------------------------------------------------------------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/tip.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,135 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/*------------------------------------------------------------------------*/
+
+/* tr.h 
+* ------
+* 
+* Main include file.
+*
+* MAA Summer 1993.
+* Revised Winter 1994.
+*/
+
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+
+#define ERROR_INTERVAL           0       /* +/- value that the intervals are  
+                                            allowed to be in: in SAMPLES ... */
+#define ERROR_MAG               10       /* in percent ... +/- */
+
+
+#define MAX_DATA              6615       /* 0.15 image seconds, 44100 s sec-1*/
+#define MAX_CHANNELS           300       /* thus size of array is 
+					  * MAX_DATA * this = 1984500 samples*/
+#define MAX_PEAKS             1000       /* in a single channel */
+#define MAX_NEXTEVENTS        1000       /* ditto */
+#define ALIGN_CHANNELS           2       /* Default number of channels to 
+					  * align over */
+
+#define MAX_STRING_LENGTH 255            /* of a filename, etc */
+#define NULLSTRING ""
+
+#define MAX_LINES_HEADER       100       /* 69 is what .sai are */
+#define MAX_LINE_LENGTH         80       /* of a header : width of an xterm */
+
+#define UNSET             9              /* nextevents definitions */
+#define RIGHTZERO        10              /* ditto */
+#define LEFTZERO         11              /* ditto */
+#define MINIMUM          12              /* ditto */
+#define END_OF_WIDTH     13              /* ditto */
+
+#define RIGHTEDGE        21              /* tent definitions */
+#define LEFTEDGE         22              /* ditto */
+#define INSIDE           23              /* ditto */
+#define NOISE            24              /* ditto */
+#define FIGURE           25              /* ditto */
+#define TRIGGER          26              /* ditto */
+
+#define POINT            1               /* output format definitions */
+#define PEAK             2               /* ditto */
+#define INTEGRAL         3               /* ditto */
+#define TENT             4               /* ditto */
+#define HALF_DOME         5              /* ditto */
+
+
+#define FIGURE_EXT "figure.sai"          /* filename extensions */
+#define GROUND_EXT "ground.sai"          /* ditto */
+#define OUTPUT_EXT ".sai"                /* ditto */
+#define INPUT_EXT ".sai"                 /* ditto */
+#define OUTPUTGROUNDFN "ground.sai"      /* default file for ground */
+
+#define OFF 0
+#define ON 1
+
+#define READ             31              /* used in fopen as "rb" */
+#define WRITE            32              /* used in fopen as "wb" */
+
+#define SINGLECHANNEL  9999              /* used in copytoouput to indicate 
+					    that the arrays by channel 
+					    DON"T exist */
+#define THREE 3
+#define FIVE 5
+
+#define GLACIERVALUE 0.5
+
+#define NEW_PWIDTH 0
+#define NEW_NWIDTH 15
+#define PWIDTH 20                        /* used in napgraph: default */
+#define NWIDTH 5                         /* used in napgraph: default. 
+					  * The minus is added later.*/
+
+#define NORMAL_WEIGHTING 41
+#define LOG_WEIGHTING    42
+
+
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+
+
+struct Peak {
+  int sample;           /* where the triangulation point is */
+  int mag;              /* its height */
+  int tent;             /* whether its been included in figure or ground, 
+			 * or not : see 'tent defs' above*/
+  double weight;
+};
+
+struct NextEvent {
+  int sample;           /* the nextevent of a peak: because findpeaksreverse()
+			 * goes right -> left, this is LEFT*/
+  int type;             /* the type of that event: MINIMUM, RIGHTZERO, 
+			 * LEFTZERO, END_OF_WIDTH */
+  int mag;              /* its height */
+};
+
+
+/* The End ---------------------------------------------------------------*/
+/*------------------------------------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saitools/trigger.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,136 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/* trigger.c
+*
+* Part of the temporal regularity programs
+*
+* M.Akeroyd. Summer 1993. Revised Winter 1994.
+*/
+
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "tip.h"
+
+
+
+
+extern struct Peak peak[MAX_PEAKS];    /* all channels */
+
+extern int framewidth_samples;      /* pwidth + nwidth * samplerate */
+extern int pwidth;                  /* in msecs */
+extern int nwidth;                  /* in msecs: NEGATIVE */
+extern int samplerate;              /* samples per sec */
+
+
+extern char progname[MAX_STRING_LENGTH];
+
+
+
+
+
+
+int find_trigger(int frame, int channel, int total_peaks)
+{
+
+  /* What this code does: 
+   * 
+   * it looks for trigger peaks, at or near ImageTime = 0.
+   * First, it looks for a peak reasonably
+   * close to where the trigger-peak SHOULD be. If there isn't one there, then it reports 
+   * a failure, and crashes.
+   * (No it doesn't: in fact it takes the fisrt peak to the right of the pre-defined trigger point).
+   *
+   * The peaknumber of the trigger_peak is RETURNed.
+   *
+   * Version of 1st June 1993.
+   */
+
+
+  int n_1; 
+  int channel_1;
+  int trigger_sample;       /* where the trigger of channel_1 is */
+  double trigger_double;
+  int trigger_found = OFF;
+  int trigger_peak;          /* THIS IS RETURNED */
+
+
+  /* hack ... */
+  if (total_peaks == 0)
+    return 0;
+
+  /* First, find out where the trigger-point is :
+   * pwidth is in msecs, so divide that by 1000, multiply by sample, and you get pwidth in 
+   * samples.
+   * So, trigger = that - 1 (-1 because the indexing is 0 to (framewidth_samples -1)) 
+   * Hope this integer arithemetic works */
+
+  trigger_double = (double) ((double) pwidth * (double) samplerate) / 1000.0 - 1;
+  trigger_sample = (int) trigger_double;
+  n_1 = total_peaks + 1;
+
+  /* find first peak to RIGHT of trigger (reverse, remember) */
+  while ((peak[--n_1].sample < trigger_sample)) 
+    ;
+
+  /* the next peak will be the trigger, at least on today's definition */
+  trigger_found  = ON;
+  trigger_sample = peak[n_1].sample;
+  trigger_peak = n_1; 
+  
+  if (trigger_found == OFF ) {
+    fprintf(stderr, "%s: unable to find trigger point: frame  %i  channel %i\n", progname, frame, channel_1);
+    exit(-1);}
+
+  return trigger_peak;
+}
+
+
+
+/* The End .........................................................................*/
+/*..................................................................................*/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/buffer.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,57 @@
+/*
+    buffer.c
+    ========
+
+    generic data buffer
+
+*/
+
+
+#include "stitch.h"
+#include "buffer.h"
+
+Buffer NewBuffer( where )
+char where ;
+{
+    DeclareNew( Buffer, buffer ) ;
+
+    buffer->size = 0 ;
+    buffer->refs = 1 ;
+
+    return ( buffer ) ;
+}
+
+Buffer SharedBuffer( buffer )
+Buffer buffer ;
+{
+    buffer->refs++ ;
+
+    return ( buffer ) ;
+}
+
+Buffer ResizedBuffer( buffer, size )
+Buffer buffer ;
+unsigned size ;
+{
+    if( size > BufferSize( buffer ) || size == 0 ) {
+
+	if( BufferSize( buffer ) != 0 )
+	    Free( BufferPointer( buffer ) ) ;
+
+	SetBufferSize( buffer, size ) ;
+
+	if( size != 0 )
+	    SetBufferPointer( buffer, Malloc( size, "buffer.c for buffer" ) ) ;
+    }
+
+    return ( buffer ) ;
+}
+
+void FreeBuffer( buffer )
+Buffer buffer ;
+{
+    if( --buffer->refs == 0 )
+	Free( ResizedBuffer( buffer, 0 ) ) ;
+
+    return ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/buffer.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,26 @@
+/*
+
+    buffer.h
+    ========
+
+    simple generic buffer abstraction.
+
+*/
+
+#define DeleteBuffer(        _buffer        ) ( FreeBuffer( _buffer ), _buffer = 0 )
+
+#define       BufferSize(    _buffer        ) ( ( _buffer )->size         )
+#define       BufferPointer( _buffer        ) ( ( _buffer )->addr         )
+#define    SetBufferSize(    _buffer, _size ) ( ( _buffer )->size = _size )
+#define    SetBufferPointer( _buffer, _addr ) ( ( _buffer )->addr = _addr )
+#define  SizedBufferPointer( _buffer, _size ) ( BufferPointer( ( ( _size ) > BufferSize( _buffer ) ) ? ResizedBuffer( _buffer, _size ) : _buffer ) )
+
+typedef struct _buffer *Buffer ;
+
+
+struct _buffer { Pointer addr ; unsigned size, refs ; } ;
+
+extern Buffer NewBuffer(     /* char  where[] */ ) ;
+extern Buffer SharedBuffer(  /* Buffer buffer */ ) ;
+extern Buffer ResizedBuffer( /* Buffer buffer, unsigned size */ ) ;
+extern void   FreeBuffer(    /* Buffer buffer */ ) ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/draw.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,233 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    draw.c
+    ======
+
+    basic interface between file format and windows content
+
+*/
+
+/*  Added the field nwid in the '_draw_state' object.  AJD 17-3-95 */
+ 
+#include <math.h>
+
+#include "windows.h"
+#include "stitch.h"
+#include "source.h"
+#include "draw.h"
+#include "ops.h"
+
+#ifndef lint
+static char *draw_sccs_id = "@(#)draw.c	1.15 John Holdsworth (MRC-APU) 6/6/91" ;
+#endif
+
+/* maximum buffer size for segmentation of drawing */
+
+#if defined( PC ) || defined( THINK_C )
+#define MAX_BUFFER (1l<<14)
+#else
+#define MAX_BUFFER (1l<<16)
+#endif
+
+/* globale variable for display paramters */
+
+double drawHeadroom = 0.0 ;
+double drawTilt     = 0.0 ;
+double drawDepth    = 0.0 ;
+double drawDistance = 0.5 ;
+double drawOverlap = 0.0 ;
+
+/*
+
+    this mess is worth a comment
+
+    I'd like to apologise for the moras of scaling parameters for display
+    .. the price of backward compatability.
+
+    Originally you could tillt the diaply to give the sensation of depth,
+    then the display parameters where changed to min, max and overlap.
+    The result is the combination of the two. At least the new interface
+    is a bit cleaner from the outside.
+
+    There is also the complication of segmented drawing across and down
+    the screen. All in all this needs to be rewritten!
+
+    From the outside though it's interface is reasonably clean however.
+
+    if framewidth > 1 then it's a 2d image per frame. If not then its
+    a multiplexed file.
+
+*/
+
+
+void draw_frame( state, frame )
+struct _draw_state *state ;
+short *frame ;
+{
+    double sintheta = sin( drawTilt / 45. * atan( 1. ) ) ;
+    double scale = ( 100. - drawHeadroom ) / 100. / ( drawDistance / ( drawDistance + sintheta ) ) ;
+    double height = Height( state->window ) * ( 1. - drawHeadroom / 100. ) ;
+    double overscale, rowscale, origin ;
+    int row ;
+
+    for( row=state->frameheight-1 ; row >= 0 ; row-- ) {
+
+	rowscale = drawDistance / ( drawDistance + sintheta * ( row + 0.5 ) / state->frameheight ) ;
+	overscale = 1. / ( ( state->frameheight - 1. ) * ( 1. - drawOverlap ) + 1. ) ;
+	origin = row * height * overscale * ( 1. - drawOverlap ) +
+    ( 0. - state->min ) / ( state->max - state->min ) * Height( state->window ) * overscale ;
+
+	if( state->framewidth > 1 )
+	    Function(     state->window, frame+row*state->framewidth, state->framewidth,                     1, origin * rowscale * scale, ( state->max - state->min ) / overscale / rowscale ) ;
+	else
+	    if( state->colnumber == 0 )
+		Segment(  state->window, frame+row,                    state->colsegment,   state->frameheight, origin * rowscale * scale, ( state->max - state->min ) / overscale / rowscale, state->colnumber,   (int) state->frames ) ;
+	    else
+		Segment(  state->window, frame+row-state->frameheight, state->colsegment+1, state->frameheight, origin * rowscale * scale, ( state->max - state->min ) / overscale / rowscale, state->colnumber-1, (int) state->frames ) ;
+    }
+
+    return ;
+}
+
+
+static void draw_callback( state, bytes, buffer )
+struct _draw_state *state ;
+ByteCount *bytes ;
+short *buffer ;
+{
+    int first = state->colnumber == 0 ;
+
+    if( state->framewidth > 1 ) {
+	state->rowsegment = *bytes / sizeof ( short ) / state->framewidth  ;
+	if( state->rowsegment > state->frameheight - state->rownumber )
+	    state->rowsegment = state->frameheight - state->rownumber ;
+    }
+    else {
+	state->colsegment = *bytes / sizeof ( short ) / state->frameheight ;
+	if( state->colsegment > state->frames - state->colnumber )
+	    state->colsegment = state->frames - state->colnumber ;
+    }
+
+    if( first )
+	++state->framenumber ;
+
+    if( *bytes != 0 )
+	state->interceptor( state, buffer, first ) ;
+
+    if( state->framewidth > 1 )
+	state->rownumber = ( state->rownumber + state->rowsegment ) % state->frameheight ;
+    else
+	state->colnumber = ( state->colnumber + state->colsegment ) % state->frames ;
+
+}
+
+Source SourceDraw( source, min, max, window, framewidth, frameheight, nwid, frames, interceptor, drawer )
+Source source ;
+int min, max ;
+WindowObject window ;
+int framewidth, frameheight ;
+int nwid;
+long frames ;
+void (*interceptor)() ;
+void (*drawer)() ;
+{
+    DeclareNew( struct _draw_state *, state ) ;
+    int segsize ;
+
+    state->min = min ;
+    state->max = max ;
+
+    state->source = source ;
+    state->window = window ;
+
+    state->frameheight = frameheight ;
+    state->framewidth  = framewidth ;
+    state->nwid = nwid ;
+    state->frames      = frames ;
+
+    state->framenumber = 0 ;
+
+    state->colnumber  = 0 ;
+    state->rownumber  = 0 ;
+
+    state->colsegment = framewidth ;
+    state->rowsegment = frameheight ;
+
+    state->interceptor = interceptor ;
+    state->drawer      = drawer ;
+
+    source = NewTappingSource( state, draw_callback, stitch_free, source, "draw.c drawing" ) ;
+
+    if( state->framewidth == 1 ) {
+
+	segsize = MAX_BUFFER / frameheight / sizeof ( short ) - 1 ;
+
+	if( segsize > frames )
+	    segsize = frames ;
+	else
+	    source = NewRetainingSource( source, frameheight * sizeof ( short ) ) ;
+
+	source = NewBlockingSource(      source, frameheight * sizeof ( short ) * segsize ) ;
+    }
+
+    return ( source ) ;
+}
+
+static Source DrawEither( window, source, min, max, framepoints, nwid, frames, drawer, row_flag )
+WindowObject window ;
+Source source ;
+int min, max ;
+int framepoints, frames, nwid ;
+int row_flag ;
+void (*drawer)() ;
+{
+    void (*draw_routine)() = drawer ;
+
+    if( draw_routine == (void ( * )()) 0 )
+	draw_routine = draw_frame ;
+
+    return ( SourceDraw( source, min, max, window, 1, framepoints, nwid, (long) frames, draw_routine, draw_routine ) ) ;
+}
+
+Source drawAcross(       window, source, min, max, framepoints, nwid, frames, drawer )
+WindowObject window ;
+Source source ;
+int min, max ;
+int framepoints, frames ;
+void (*drawer)() ;
+{
+    return ( DrawEither( window, source, min, max, framepoints, nwid, frames, drawer, 0 ) ) ;
+}
+
+Source drawDown(         window, source, min, max, framepoints, nwid, frames, drawer )
+WindowObject window ;
+Source source ;
+int min, max ;
+int framepoints, frames ;
+void (*drawer)() ;
+{
+    return ( DrawEither( window, source, min, max, framepoints, nwid, frames, drawer, 1 ) ) ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/draw.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,56 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    draw.h
+    ======
+
+    interface to windows graphics calls for files of complex formats.
+
+*/
+
+#define _DRAW_H_
+
+struct _draw_state { Source source ; WindowObject window ;
+	     int min, max, framewidth, frameheight, nwid,
+		 rownumber, colnumber, rowsegment, colsegment ;
+      long frames, framenumber ; void (*interceptor)(), (*drawer)() ;
+} ;
+
+extern double drawHeadroom, drawTilt, drawDepth, drawDistance, drawOverlap ;
+
+extern void draw_frame() ;
+
+extern Source SourceDraw() ;
+
+
+#define       DrawAcross( _window, _source, _min, _max, _framepoints, _frames                   ) \
+	      drawAcross( _window, _source, _min, _max, _framepoints, _frames, (void ( * )()) 0 )
+
+extern Source drawAcross() ;
+
+
+#define       DrawDown(   _window, _source, _min, _max, _framepoints, _frames                   ) \
+	      drawDown(   _window, _source, _min, _max, _framepoints, _frames, (void ( * )()) 0 )
+
+extern Source drawDown(  ) ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/fill.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,289 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    fill.c
+    ======
+
+
+    window filling source
+
+
+    Copyright (c), 1989  The Medical Research Council, Applied Psychology Unit.
+
+
+    Author  : John Holdsworth
+    Written : 11th May, 1989.
+
+    Edited  :
+
+
+*/
+
+#include "windows.h"
+#include "stitch.h"
+#include "source.h"
+#include "fill.h"
+
+#ifndef lint
+static char *sccs_id = "@(#)fill.c	1.9     J. Holdsworth (MRC-APU)  11/8/90" ;
+#endif
+
+
+static int *Match( n1, n2 )
+int n1, n2 ;
+{
+    DeclareNewArray( int, array, n2+16, "for match" ) ;
+    float scale ;
+    int i ;
+
+    if( n2 > 1 )
+    {
+	scale = ( abs( n1 ) - 1. ) / ( n2 - 1. ) ;
+
+	if( n1 > 0 )
+	    for( i=0 ; i < n2 ; i++ )
+		array[ i ] = i * scale + .5 ;
+	else
+	    for( i=0 ; i < n2 ; i++ )
+		array[ i ] = abs( n1 ) - 1 - (int) ( i * scale + .5 ) ;
+
+	for( i=n2 ; i < n2 + 16 ; i++ )
+	    array[ i ] = 0 ;
+    }
+    else
+	array[ 0 ] = 0 ;
+
+    return( array ) ;
+}
+
+struct _fill_state { WindowObject window ; int row_flag, frame, framepoints, frames, major_count, *major, *minor ; short black, white ; } ;
+
+static void fill_callback( state, bytes, buffer )
+struct _fill_state *state ;
+ByteCount *bytes ;
+short *buffer ;
+{
+    short *bptr = buffer ;
+
+    while( (char *) bptr < (char *) buffer + *bytes ) {
+
+	if( state->frames != 0 && state->frame % state->frames == 0 ) {
+	    state->frame = 0 ;
+	    state->major_count=0 ;
+	}
+
+	while( state->major[ state->major_count ] == state->frame ) {
+	    state->major_count++ ;
+	    if( state->row_flag )
+		FillRow( state->window, state->major_count, bptr, state->black, state->white, state->minor,  Width( state->window ) ) ;
+	    else
+		FillCol( state->window, state->major_count, bptr, state->black, state->white, state->minor, Height( state->window ) ) ;
+	}
+
+	state->frame++ ;
+
+	bptr += state->framepoints ;
+    }
+
+    return ;
+}
+
+static void excite_callback( state, bytes, buffer )
+struct _fill_state *state ;
+ByteCount *bytes ;
+short *buffer ;
+{
+    double origin = 1. + ( Height( state->window ) - 1. ) * ( 0. - state->black ) / ( state->white - state->black ) ;
+
+    Clear( state->window ) ;
+
+    Function( state->window, buffer, ToPoints( short, *bytes ), 1, origin, (double) ( state->white - state->black ) ) ;
+
+    return ;
+}
+
+static void smear_callback( state, bytes, buffer )
+struct _fill_state *state ;
+ByteCount *bytes ;
+short *buffer ;
+{
+    double origin = 1. + ( Height( state->window ) - 1. ) * ( 0. - state->black ) / ( state->white - state->black ) ;
+
+    Function( state->window, buffer, ToPoints( short, *bytes ), 1, origin, (double) ( state->white - state->black ) ) ;
+
+    return ;
+}
+
+
+static void fill_close( state )
+struct _fill_state *state ;
+{
+    Delete( state->major ) ;
+    Delete( state->minor ) ;
+
+    Delete( state ) ;
+
+    return ;
+}
+
+/*
+Source SourceFill( source, black, white, window, framewidth, frameheight, frames, cfs )
+Source source ;
+int black, white ;
+WindowObject window ;
+int framewidth, frameheight ;
+long frames ;
+double *cfs ;
+{
+    DeclareNew( struct _fill_state *, state ) ;
+    double mincf, spancf, pixcf ;
+    int row, chan ;
+
+    state->window = window ;
+
+    state->black  = black ;
+    state->white  = white ;
+
+    state->major  = Match( (int) frames, Width( window ) ) ;
+    state->minor  = Match( frameheight, Height( window ) ) ;
+
+    if( cfs != (double *) 0 ) {
+	chan = 0 ;
+	mincf  = cfs[0] ;
+	spancf = cfs[frameheight-1]-mincf ;
+
+	for( row=0 ; row<Height( window ) ; row++ ) {
+
+	    pixcf = mincf + ( row + 0.5 ) / Height( window ) * spancf ;
+
+	    while( cfs[chan]<pixcf )
+		chan++ ;
+
+	    state->minor[row] = chan ;
+	}
+    }
+
+    state->major_count = 0 ;
+    state->frame       = 0 ;
+    state->frames      = 0 ;
+    state->framepoints = 0 ;
+
+    state->row_flag    = 0 ;
+
+    switch( abs( framewidth ) ) {
+	case 1 :
+	    return ( NewTappingSource( (Pointer) state,   fill_callback, fill_close, source, "fill.c filling" ) ) ;
+	case 2 :
+	    return ( NewTappingSource( (Pointer) state, excite_callback, fill_close, source, "fill.c filling" ) ) ;
+	case 3 :
+	    return ( NewTappingSource( (Pointer) state,  smear_callback, fill_close, source, "fill.c filling" ) ) ;
+    }
+}
+*/
+
+static Source FillEither( window, source, black, white, framepoints, frames, scale, row_flag )
+WindowObject window ;
+Source source ;
+int black, white ;
+int framepoints, frames ;
+double *scale ;
+int row_flag ;
+{
+    DeclareNew( struct _fill_state *, state ) ;
+    int minor_pixels, major_pixels ;
+    double min, span, value ;
+    int row, chan ;
+
+    if( row_flag ) {
+	minor_pixels   =  Width( window ) ;
+	major_pixels   = Height( window ) ;
+    }
+    else {
+	minor_pixels   = Height( window ) ;
+	major_pixels   =  Width( window ) ;
+    }
+
+    state->window = window ;
+
+    state->black    = black ;
+    state->white    = white ;
+
+    state->major  = Match(      frames, major_pixels ) ;
+    state->minor  = Match( framepoints, minor_pixels ) ;
+
+    if( !row_flag ) /* reverse match array for columns for now */
+	for( chan=0 ; chan<minor_pixels/2 ; chan++ ) {
+	    row = state->minor[minor_pixels-1-chan] ;
+	    state->minor[minor_pixels-1-chan] = state->minor[chan] ;
+	    state->minor[chan]= row ;
+	}
+
+    if( scale != (double *) 0 ) {
+
+	chan = 0 ;
+	min  = scale[0] ;
+	span = scale[framepoints-1]-min ;
+
+	for( row=0 ; row < minor_pixels ; row++ ) {
+
+	    value = min + ( row + 0.5 ) / minor_pixels * span ;
+
+	    while( scale[chan] < value )
+		chan++ ;
+
+	    state->minor[row] = chan ;
+	}
+    }
+
+    state->framepoints = framepoints ;
+    state->frames      = frames ;
+    state->frame       = 0 ;
+    state->major_count = 0 ;
+
+    state->row_flag    = row_flag ;
+
+    return ( NewTappingSource( (Pointer) state, fill_callback, fill_close, source, "fill.c filling" ) ) ;
+}
+
+Source fillAcross(       window, source, black, white, framepoints, frames, scale )
+WindowObject window ;
+Source source ;
+int black, white ;
+int framepoints, frames ;
+double *scale ;
+{
+    return ( FillEither( window, source, black, white, framepoints, frames, scale, 0 ) ) ;
+}
+
+Source fillDown(         window, source, black, white, framepoints, frames, scale )
+WindowObject window ;
+Source source ;
+int black, white ;
+int framepoints, frames ;
+double *scale ;
+{
+    return ( FillEither( window, source, black, white, framepoints, frames, scale, 1 ) ) ;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/fill.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,46 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    fill.h
+    ======
+
+    Greyscales fill windows with 2d array of data.
+
+
+*/
+
+
+extern Source SourceFill() ;
+
+
+#define       FillAcross( _window, _source, _black, _white, _framepoints, _frames               ) \
+	      fillAcross( _window, _source, _black, _white, _framepoints, _frames, (double *) 0 )
+
+extern Source fillAcross() ;
+
+
+#define       FillDown(   _window, _source, _black, _white, _framepoints, _frames               ) \
+	      fillDown(   _window, _source, _black, _white, _framepoints, _frames, (double *) 0 )
+
+extern Source fillDown(  ) ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/fillable.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,405 @@
+/*
+    fillable.c
+    ==========
+
+    Sources whose native mode of operation is the fill entry point.
+    They may be pulled in which case a buffer is allocated.
+
+*/
+
+#include "stitch.h"
+#include "source.h"
+
+#ifndef  lint
+static char *sccs_id = "@(#)fillable.c	1.2 John Holdsworth (MRC-APU) 11/8/90" ;
+#endif
+
+#if 0
+#define DEBUG 1
+#endif
+
+Source SharingSource( source1, source2 )
+struct _fillable_source *source1, *source2 ;
+{
+    DeleteBuffer( source1->buffer ) ;
+
+    source1->buffer = SharedBuffer( source2->buffer ) ;
+
+    return ( (Source) source1 ) ;
+}
+
+/* converter of pull command to fill commands */
+
+static Pointer pullFromFillable( source, bytes )
+struct _fillable_source *source ;
+ByteCount *bytes ;
+{
+#if DEBUG
+    printf( "buffering pulling from passive \"%s\", %d bytes\n", SourceName( source ), *bytes ) ;
+#endif
+#if 00
+    if( source->bsize < *bytes ) {
+
+	if( source->bsize != 0 )
+	    Delete( source->buffer ) ;
+
+	source->buffer = Allocate( *bytes, "fillable.c for source buffer" ) ;
+
+	source->bsize  = *bytes ;
+    }
+#endif
+    return ( source->parent.fill( source, bytes, SizedBufferPointer( SourceBuffer( source ), *bytes ) ) ) ;
+}
+
+/* constructor for all pullable sources */
+
+Source setFillableSource( source, filler, name )
+struct _fillable_source *source ;
+Pointer (*filler)() ;
+char *name ;
+{
+    source->buffer = NewBuffer( "pulling" ) ;
+
+    return ( SetSource( source, pullFromFillable, filler, nonRoller, name ) ) ;
+}
+
+Pointer deleteFillableSource( source )
+struct _fillable_source *source ;
+{
+    DeleteBuffer( source->buffer ) ;
+
+    return ( DeleteSource( source ) ) ;
+}
+
+
+/* derived fillable source */
+
+typedef struct {
+ struct _fillable_source parent ;
+ Pointer data, end, ptr ;
+ } *RepeatingSource ;
+
+static Pointer repeating_callback( source, bytes, buffer )
+RepeatingSource source ;
+ByteCount *bytes ;
+Pointer buffer ;
+{
+    register int last = *bytes == 0 ;
+    register Pointer bptr = buffer ;
+    register Pointer bend = buffer + *bytes ;
+    register ByteCount segment ;
+
+    if( !last ) {
+
+	while( bptr < bend ) {
+
+	    segment = source->end - source->ptr ;
+	    if( segment > bend - bptr )
+		segment = bend - bptr ;
+
+	    CopyArray( (char *) source->ptr, (char *) bptr, segment ) ;
+
+	    source->ptr += segment ;
+	    bptr        += segment ;
+
+	    if( source->ptr == source->end )
+		source->ptr = source->data ;
+	}
+
+	return ( buffer ) ;
+    }
+    else
+	return ( DeleteFillableSource( source ) ) ;
+}
+
+Source newRepeatingSource( data, segment )
+Pointer data ;
+ByteCount segment ;
+{
+    DeclareNew( RepeatingSource, source ) ;
+
+    source->data = data ;
+    source->end  = data + segment ;
+
+    source->ptr  = source->data ;
+
+    return ( SetFillableSource( source, repeating_callback, "fillable.c repeating" ) ) ;
+}
+
+typedef struct {
+ struct _fillable_source parent ;
+ Source input ; ByteCount segment ;
+ } *SegmentingSource ;
+
+static Pointer segmenting_callback( source, bytes, buffer )
+SegmentingSource source ;
+ByteCount *bytes ;
+Pointer buffer ;
+{
+    register int last = *bytes == 0 ;
+    Pointer bptr = buffer ;
+    ByteCount segment ;
+
+    do {
+
+	segment = source->segment ;
+
+	if( segment > buffer + *bytes - bptr )
+	    segment = buffer + *bytes - bptr ;
+
+	(void) FillSome( source->input, &segment, bptr ) ;
+
+	bptr += segment ;
+
+    } while ( bptr < buffer + *bytes ) ;
+
+    if( !last )
+	return ( buffer  ) ;
+    else
+	return ( DeleteFillableSource( source ) ) ;
+}
+
+Source newSegmentingSource( input, segment )
+Source input ;
+ByteCount segment ;
+{
+    DeclareNew( SegmentingSource, source ) ;
+
+    source->input = input ;
+
+    source->segment = segment ;
+
+    return ( SetFillableSource( source, segmenting_callback, "segmenting" ) ) ;
+}
+
+
+
+/* higher level methods to sources */
+
+
+typedef struct _callback_source {
+ struct _fillable_source parent ;
+ Pointer state ;
+ void (*callback)(), (*close)() ;
+ } *CallbackSource ;
+
+Source setCallbackSource( source, filler, state, callback, close, name )
+CallbackSource source ;
+Pointer (*filler)() ;
+Pointer state ;
+void (*callback)(), (*close)() ;
+char *name ;
+{
+    source->state    = state    ;
+    source->callback = callback ;
+    source->close    = close    ;
+
+    return ( SetFillableSource( source, filler, name ) ) ;
+}
+
+Source newCallbackSource( filler, state, callback, close, name )
+Pointer (*filler)() ;
+Pointer state ;
+void (*callback)(), (*close)() ;
+char *name ;
+{
+    return ( setCallbackSource( New( CallbackSource ), filler, state, callback, close, name ) ) ;
+}
+
+static Pointer externalFiller( source, bytes, buffer )
+CallbackSource source ;
+ByteCount *bytes ;
+Pointer buffer ;
+{
+    register int last = *bytes == 0 ;
+
+    source->callback( source->state, bytes, buffer, buffer+*bytes ) ;
+
+    if( !last )
+	return ( buffer ) ;
+    else {
+	if( source->close != (void ( * )()) 0 )
+	    source->close( source->state ) ;
+
+	return ( DeleteFillableSource( source ) ) ;
+    }
+}
+
+Source newExternalSource( state, callback, close, name )
+Pointer state ;
+void (*callback)(), (*close)() ;
+char *name ;
+{
+    return ( newCallbackSource( externalFiller, state, callback, close, name ) ) ;
+}
+
+typedef struct _through_source {
+ struct _callback_source parent ;
+ Source input ;
+ } *ThroughSource ;
+
+static Source setThroughSource( source, filler, state, callback, close, input, name )
+ThroughSource source ;
+Pointer (*filler)() ;
+Pointer state ;
+void (*callback)(), (*close)() ;
+Source input ;
+char *name ;
+{
+    source->input = input ;
+
+    return ( setCallbackSource( (CallbackSource) source, filler, state, callback, close, name ) ) ;
+}
+
+Source newThroughSource( filler, state, callback, close, input, name )
+Pointer (*filler)(), state ;
+void (*callback)(), (*close)() ;
+Source input ;
+char *name ;
+{
+    return ( setThroughSource( New( ThroughSource ), filler, state, callback, close, input, name ) ) ;
+}
+
+
+static Pointer processingFiller( source, bytes, buffer )
+ThroughSource source ;
+ByteCount *bytes ;
+Pointer buffer ;
+{
+    register int last = *bytes == 0 ;
+
+    source->parent.callback( source->parent.state, bytes, buffer, buffer+*bytes, PullSome( source->input, bytes ) ) ;
+
+    if( !last )
+	return ( buffer ) ;
+    else {
+	if( source->parent.close != (void ( * )()) 0 )
+	    source->parent.close( source->parent.state ) ;
+
+	return ( DeleteFillableSource( &source->parent ) ) ;
+    }
+}
+
+Source newProcessingSource( state, callback, close, input, name )
+Pointer state ;
+void (*callback)(), (*close)() ;
+Source input ;
+char *name ;
+{
+    return ( newThroughSource( processingFiller, state, callback, close, input, name ) ) ;
+}
+
+Source newSimpleProcessingSource( callback, input, name )
+void (*callback)() ;
+Source input ;
+char *name ;
+{
+    return ( NewProcessingSource( (Pointer) 0, callback, (void ( * )()) 0, input, name ) ) ;
+}
+
+typedef struct {
+    struct _fillable_source parent ;
+    Pointer *states ;
+    int (*callback)() ;
+    void (*close)() ;
+    int channels ;
+    Source input ;
+} *MultiplexedSource ;
+
+static Pointer multiplexed_callback( source, bytes, buffer )
+MultiplexedSource source ;
+ByteCount *bytes ;
+Pointer buffer ;
+{
+    register int last = *bytes == 0 ;
+    Pointer iptr = PullSome( source->input, bytes ) ;
+    Pointer optr = buffer ;
+    Pointer end = buffer + *bytes ;
+    ByteCount data_size ;
+    int channel ;
+
+    for( channel=0 ; channel<source->channels ; channel++ ) {
+	data_size = source->callback( source->states[channel], optr, end, iptr, source->channels ) ;
+	iptr += data_size ;
+	optr += data_size ;
+    }
+
+    if( !last )
+	return ( buffer ) ;
+    else {
+	if( source->close != (void ( * )()) 0 )
+	    for( channel=0 ; channel<source->channels ; channel++ )
+		source->close( source->states[channel] ) ;
+
+	Delete( source->states ) ;
+
+	return ( DeleteFillableSource( source ) ) ;
+    }
+}
+
+Source newMultiplexedSource( states, callback, close, channels, input, name )
+Pointer *states ;
+int (*callback)() ;
+void (*close)() ;
+int channels ;
+Source input ;
+char *name ;
+{
+    DeclareNew( MultiplexedSource, source ) ;
+
+    source->states   = states   ;
+    source->callback = callback ;
+    source->close    = close    ;
+    source->channels = channels ;
+
+    source->input    = input    ;
+
+    return ( SetFillableSource( source, multiplexed_callback, name ) ) ;
+}
+
+typedef struct _merging_source {
+ struct _callback_source parent ; Source *inputs ;
+ } *MergingSource ;
+
+static Pointer mergingFiller( source, bytes, buffer )
+MergingSource source ;
+ByteCount *bytes ;
+Pointer buffer ;
+{
+    register int last = *bytes == 0 ;
+    Pointer input1, input2 ;
+    int n ;
+
+    input1 = PullSome( source->inputs[0], bytes ) ;
+
+    for( n=1 ; _SPTR( source->inputs[n] ) != (struct _source *) 0 ; n++ ) {
+
+	input2 = PullSome( source->inputs[n], bytes ) ;
+
+	source->parent.callback( source->parent.state, bytes, buffer, buffer+*bytes, input1, input2 ) ;
+
+	input1 = buffer ;
+    }
+
+    if( !last )
+	return ( buffer ) ;
+    else {
+	Delete( source->inputs  ) ;
+
+	return ( DeleteFillableSource( &source->parent ) ) ;
+    }
+}
+
+Source newMergingSource( state, callback, close, inputs, name )
+Pointer state ;
+void (*callback)(), (*close)() ;
+Source *inputs ;
+char *name ;
+{
+    DeclareNew( MergingSource, source ) ;
+
+    source->inputs = inputs ;
+
+    return ( setCallbackSource( (CallbackSource) source, mergingFiller, state, callback, close, name ) ) ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/fillable.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,67 @@
+/*
+    fillable.h
+    ==========
+
+    fillable derived sources
+
+*/
+
+#define    SetFillableSource(    _source          , _filler, _name ) \
+	   setFillableSource( &( _source )->parent, _filler, _name )
+#define DeleteFillableSource(    _source                           ) \
+	deleteFillableSource( &( _source )->parent                 )
+
+/* derived Fillable sources */
+
+#define NewRepeatingSource(             _data  , _segment ) \
+	newRepeatingSource( (Pointer) ( _data ), _segment )
+
+
+#define NewSegmentingSource( _source,               _block      ) \
+	newSegmentingSource( _source, (ByteCount) ( _block    ) )
+
+
+#define NewCallbackSource( _filler,             _state  , _callback, _close,         _name ) \
+	newCallbackSource( _filler, (Pointer) ( _state ), _callback, _close,         _name )
+
+#define NewExternalSource(                      _state  , _callback, _close,         _name ) \
+	newExternalSource(          (Pointer) ( _state ), _callback, _close,         _name )
+
+#define NewThroughSource(  _filler,             _state  , _callback, _close, _input, _name ) \
+	newThroughSource(  _filler, (Pointer) ( _state ), _callback, _close, _input, _name )
+
+
+#define NewProcessingSource(                    _state  , _callback, _close, _input, _name ) \
+	newProcessingSource(        (Pointer) ( _state ), _callback, _close, _input, _name )
+
+#define NewSimpleProcessingSource(                        _callback,         _input, _name ) \
+	newSimpleProcessingSource(                        _callback,         _input, _name )
+
+
+#define NewMultiplexedSource(                  _states  , _callback, _close, _channels, _input, _name ) \
+	newMultiplexedSource(    (Pointer *) ( _states ), _callback, _close, _channels, _input, _name )
+
+
+#define NewMergingSource(                       _state  , _callback, _close, _inputs, _name ) \
+	newMergingSource(           (Pointer) ( _state ), _callback, _close, _inputs, _name )
+
+#define SharingSource( _source1, _source2 ) \
+	sharingSource( _source1, _source2 )
+
+/* derived higher level filling sources */
+
+extern Source         setFillableSource() ;
+extern Pointer     deleteFillableSource() ;
+
+extern Source       newSegmentingSource() ;
+
+extern Source         setCallbackSource() ;
+extern Source         newExternalSource() ;
+extern Source          newThroughSource() ;
+
+extern Source       newProcessingSource() ;
+extern Source newSimpleProcessingSource() ;
+extern Source      newMultiplexedSource() ;
+extern Source          newMergingSource() ;
+
+extern Source             sharingSource() ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/funcs.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,176 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    funcs.c
+    =======
+
+
+
+
+*/
+
+#include <math.h>
+
+#include "stitch.h"
+#include "source.h"
+#include "funcs.h"
+#include "ops.h"
+
+#if !defined(PC) && !defined(DSP32)
+DoubleSource LogarithmDoubleSource( source )
+DoubleSource                        source ;
+{
+    return ( CallingDoubleSource( source, log ) ) ;
+}
+
+DoubleSource ExponentialDoubleSource( source )
+DoubleSource                          source ;
+{
+    return ( CallingDoubleSource( source, exp) ) ;
+}
+
+DoubleSource SineDoubleSource( source )
+DoubleSource                   source ;
+{
+    return ( CallingDoubleSource( source, sin ) ) ;
+}
+
+DoubleSource CosineDoubleSource( source )
+DoubleSource                     source ;
+{
+    return ( CallingDoubleSource( source, cos ) ) ;
+}
+
+DoubleSource SquareRootDoubleSource( source )
+DoubleSource                         source ;
+{
+    return ( CallingDoubleSource( source, sqrt ) ) ;
+}
+
+DoubleSource DoubleAbsDoubleSource( source )
+DoubleSource                        source ;
+{
+    return ( CallingDoubleSource( source, fabs ) ) ;
+}
+
+DoubleSource OscilatorDoubleSource( input, samplerate, phase0 )
+DoubleSource                        input ;
+				    double samplerate, phase0 ;
+{
+    double TwoPi = atan( 1. ) * 8. ;
+
+    return (
+      CosineDoubleSource(
+	IntegrateDoubleSource(
+	  MultiplyDoubleSources(
+	      input,
+	      ConstantDoubleSource( TwoPi / samplerate )
+	  ),
+	  phase0 / 360. * TwoPi
+	)
+      )
+    ) ;
+}
+
+DoubleSource CosinewaveDoubleSource( frequency, amplitude, phase0 )
+			      double frequency, amplitude, phase0 ;
+{
+    return ( MultiplyDoubleSources( OscilatorDoubleSource( ConstantDoubleSource( frequency ), 1., phase0 ), ConstantDoubleSource( amplitude ) ) ) ;
+}
+
+DoubleSource SinewaveDoubleSource( frequency, amplitude, phase0 )
+			    double frequency, amplitude, phase0 ;
+{
+    return ( CosinewaveDoubleSource( frequency, amplitude, phase0 - 90. ) ) ;
+}
+
+DoubleSource RaisedCosinewaveDoubleSource( frequency, amplitude, phase0 )
+				    double frequency, amplitude, phase0 ;
+{
+    return ( AddDoubleSources( CosinewaveDoubleSource( frequency, amplitude / 2., phase0 ), ConstantDoubleSource( amplitude / 2. ) ) ) ;
+}
+
+DoubleSource RaisedSinewaveDoubleSource( frequency, amplitude, phase0 )
+				  double frequency, amplitude, phase0 ;
+{
+    return ( RaisedCosinewaveDoubleSource( frequency, amplitude, phase0 - 90. ) ) ;
+}
+#endif
+
+#define LOG_ZERO (-10)
+
+static short imB( number )
+	    short number ;
+{
+    register int i, out ;
+    register long in ;
+    static int precision = 12 ;
+    static int *table = { ( int * ) 0 } ;
+    static unsigned table_size ;
+    static int inc ;
+    double k ;
+
+    if( table == ( int * ) 0 ) {
+
+	table_size = 1 << precision ;
+
+	k   = 2000. / log( 10. ) ;
+	inc = k     * log(  2. ) + 0.5 ;
+
+	table = (int *) stitch_malloc( table_size * sizeof( *table ), "imb.c for log table" ) ;
+
+	for( i=0 ; i < table_size ; i++ )
+	    table[ i ] = log( (double) ( table_size + i ) / table_size ) * k + 0.5 ;
+    }
+
+    if( number > 0 ) {
+
+	in = number ;
+
+	out = precision * inc ;
+
+	if( number < table_size )
+	    do {
+		in <<= 1 ;
+		out -= inc ;
+	    }
+	    while( in < table_size ) ;
+	else
+	    while( in - table_size >= table_size ) {
+		in >>= 1 ;
+		out += inc ;
+	    }
+
+	return ( out + table[ in - table_size ] ) ;
+    }
+    else
+	return ( LOG_ZERO ) ;
+}
+
+ShortSource milliBellShortSource( source )
+ShortSource                       source ;
+{
+    return ( CallingShortSource( source, imB ) ) ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/funcs.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,69 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    funcs.h
+    =======
+
+
+*/
+
+
+extern DoubleSource     LogarithmDoubleSource( _ONE_SOURCE ) ;
+extern DoubleSource  ExponentiateDoubleSource( _ONE_SOURCE ) ;
+extern DoubleSource          SineDoubleSource( _ONE_SOURCE ) ;
+extern DoubleSource        CosineDoubleSource( _ONE_SOURCE ) ;
+extern DoubleSource    SquareRootDoubleSource( _ONE_SOURCE ) ;
+extern DoubleSource AbsoluteValueDoubleSource( _ONE_SOURCE ) ;
+
+extern ShortSource       milliBellShortSource( _ONE_SOURCE ) ;
+
+
+#define OscilatorDoubleSource( _frequency, _samplerate, _phase0 ) \
+	oscilatorDoubleSource( _frequency, _samplerate, _phase0 )
+
+extern DoubleSource     oscilatorDoubleSource( _ONE_SOURCE_PLUS ) ;
+
+
+#define CosinewaveDoubleSource( _frequency, _amplitude, _phase0 ) \
+	cosinewaveDoubleSource( _frequency, _amplitude, _phase0 )
+
+extern DoubleSource    cosinewaveDoubleSource( _MANY_ARGS ) ;
+
+
+#define   SinewaveDoubleSource( _frequency, _amplitude, _phase0 ) \
+	  sinewaveDoubleSource( _frequency, _amplitude, _phase0 )
+
+extern DoubleSource      sinewaveDoubleSource( _MANY_ARGS ) ;
+
+
+#define RaisedCosinewaveDoubleSource( _frequency, _amplitude, _phase0 ) \
+	raisedCosinewaveDoubleSource( _frequency, _amplitude, _phase0 )
+
+extern DoubleSource    raisedCosinewaveDoubleSource( _MANY_ARGS ) ;
+
+
+#define   RaisedSinewaveDoubleSource( _frequency, _amplitude, _phase0 ) \
+	  raisedSinewaveDoubleSource( _frequency, _amplitude, _phase0 )
+
+extern DoubleSource      raisedSinewaveDoubleSource( _MANY_ARGS ) ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/io.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,145 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    io.c
+    ====
+
+    file i/o sources/sinks.
+
+
+*/
+
+#include <stdio.h>
+
+#include "stitch.h"
+#include "source.h"
+#include "io.h"
+
+extern int fclose() ;
+
+/* for IBM pc's */
+#ifdef PC
+char  readBinary[] = "rb" ;
+char writeBinary[] = "wb" ;
+#else
+char  readBinary[] = "r" ;
+char writeBinary[] = "w" ;
+#endif
+
+/* sources */
+
+static void read_callback( state, bytes, buffer, end )
+FILE *state ;
+ByteCount *bytes ;
+Pointer buffer ;
+{
+    int actuall ;
+
+    if( *bytes > 0 ) {
+	actuall = fread( (char *) buffer, sizeof ( char ), *bytes, state ) ;
+
+	if( actuall == EOF )
+	    actuall  =  0  ;
+
+	stitch_bzero( (char *)buffer+actuall, *bytes-actuall ) ;
+
+	*bytes = actuall ;
+    }
+    else if( *bytes < 0 )
+	(void) fseek( state, (long) -*bytes, 1 ) ;
+
+    return ;
+}
+
+Source FileSource( fp )
+FILE *fp ;
+{
+    if( fp == ( FILE * ) 0 )
+	(void) fprintf( stderr, "Bad file pointer FileSource - unable to open file?\n" ) ;
+
+    return ( NewExternalSource( (Pointer) fp, read_callback, (void ( * )()) 0, "io.c file pointer" ) ) ;
+}
+
+Source StdinSource()
+{
+    return ( FileSource( stdin ) ) ;
+}
+
+Source FileNameSource( name )
+char *name ;
+{
+    FILE *fp = fopen( name, readBinary ) ;
+
+    if( fp == (FILE *) 0 )
+	if( strcmp( name, "-" ) == 0 )
+	    return ( StdinSource() ) ;
+	else {
+	    (void) fprintf( stderr, "Bad file pointer FileSource - unable to open file?\n" ) ;
+	    return ( EmptySource ) ;
+	}
+
+    return ( NewExternalSource( (Pointer) fopen( name, readBinary ), read_callback, (void ( * )()) fclose, "io.c named file" ) ) ;
+}
+
+
+/* tap source into file on way past */
+
+static void write_callback( state, bytes, buffer, end )
+FILE *state ;
+ByteCount *bytes ;
+Pointer buffer ;
+{
+    if( *bytes > 0 )
+	(void) fwrite( (char *) buffer, sizeof ( char ), *bytes, state ) ;
+    else if( *bytes < 0 )
+	(void) fseek( state, (long) -*bytes, 1 ) ;
+
+    return ;
+}
+
+Source FileTap( source, fp )
+Source source ;
+FILE *fp ;
+{
+    if( fp == ( FILE * ) 0 )
+	(void) fprintf( stderr, "Bad file pointer FileTap - unable to open file?\n" ) ;
+
+    return ( NewTappingSource( (Pointer) fp, write_callback, (void (*)()) 0, source, "io.c file pointer tapping" ) ) ;
+}
+
+Source FileNameTap( source, name )
+Source source ;
+char *name ;
+{
+    (void) unlink( name ) ;
+
+    return ( NewTappingSource( (Pointer) fopen( name, writeBinary ), write_callback, (void ( * )()) fclose, source, "io.c named file tapping" ) ) ;
+}
+
+Source StdoutTap( source )
+Source source ;
+{
+    return ( FileTap( source, stdout ) ) ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/io.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,39 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    io.h
+    ====
+
+
+*/
+
+Source FileNameSource( /*             char *name */ ) ;
+Source FileSource(     /*             FILE *fp   */ ) ;
+Source StdinSource(                                 ) ;
+
+Source FileNameTap( /* Source source, char *name */ ) ;
+Source FileTap(     /* Source source, FILE *fp   */ ) ;
+Source StdoutTap(   /* Source source             */ ) ;
+
+extern char readBinary[], writeBinary[] ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/makefile	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,69 @@
+###########################################################################
+#
+#  Makefile for AIM utilities library:  libstitch.a
+#
+#   (For convenience, this makefile directly calls the root makefile).
+#
+#   @(#)makefile        1.7  J. Holdsworth, (MRC-APU)  6/6/91
+#                            M. Allerhand,  (MRC-APU) 26/1/93
+#
+#
+###########################################################################
+
+
+default : install
+
+GDIR = ../glib
+
+SLIB = libstitch.a
+
+INCLUDES  =  -I$(GDIR)
+
+.c.o :
+	$(CC) $(CFLAGS) $(INCLUDES) -c $<
+
+
+############################################################################
+# Make stitch utilities library.
+
+OBJS =  wrap.o          funcs.o         draw.o          fill.o          \
+	pullable.o      fillable.o      stypes.o        io.o            \
+	buffer.o        source.o        srcio.o         stitch.o        \
+	ops.o
+
+lib $(SLIB) : $(OBJS)
+	ar rc $@ $? ; $(RANLIB) $@
+
+
+############################################################################
+# dependencies
+
+stitch.o:   stitch.h wrap.h
+source.o:   stitch.h source.h pullable.h fillable.h buffer.h
+fillable.o: stitch.h source.h            fillable.h buffer.h
+pullable.o: stitch.h source.h pullable.h
+srcio.o:    stitch.h source.h pullable.h fillable.h srcio.h
+stypes.o:   stitch.h source.h ops.h stypes.h
+funcs.o:    stitch.h source.h ops.h funcs.h
+draw.o:     stitch.h source.h ops.h draw.h
+fill.o:     stitch.h source.h fill.h
+io.o:       stitch.h source.h io.h
+ops.o:      stitch.h source.h stypes.h ops.h
+buffer.o:   stitch.h buffer.h
+wrap.o:     stitch.h wrap.h
+
+
+############################################################################
+# Make targets in root makefile.
+
+TARGETS   = main        install     all         sources \
+	    links       alllinks    demo        tar     \
+	    ftp         tape        mail        clean   \
+	    sccslinks   cleansccs   help        noplot
+
+$(TARGETS) : FORCE
+	@ cd .. ; make $@
+FORCE:
+
+
+############################################################################
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/ops.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,2264 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+	ops.c
+	=====
+
+	quickie operators for stitch
+
+*/
+
+
+
+typedef char    *Pointer ;
+
+typedef char    *Address ;
+
+
+/* a portable inteface to the system */
+
+extern void           stitch_error()  ;
+
+extern Pointer        stitch_malloc() ;
+extern Pointer stitch_copied_malloc() ;
+extern Pointer stitch_zeroed_malloc() ;
+extern Pointer        stitch_ralloc() ;
+extern Pointer        stitch_calloc() ;
+
+extern void           stitch_free()   ;
+extern void           stitch_exit()   ;
+
+/* beware these definitions, they are for speed and fail if stitch.h not included */
+
+extern void  (*stitch_bcopy)() ;
+extern void  (*stitch_bzero)() ;
+
+extern char stitchStructStr[] ;
+
+
+
+
+typedef struct _buffer *Buffer ;
+
+
+struct _buffer { Pointer addr ; unsigned size, refs ; } ;
+
+extern Buffer NewBuffer(     /* char  where[] */ ) ;
+extern Buffer SharedBuffer(  /* Buffer buffer */ ) ;
+extern Buffer ResizedBuffer( /* Buffer buffer, unsigned size */ ) ;
+extern void   FreeBuffer(    /* Buffer buffer */ ) ;
+
+
+
+
+/* basic types */
+
+typedef struct _source *Source, *SourceArray[1] ;
+
+
+
+typedef Source      CharSource,      ShortSource,      IntSource,      FloatSource,      DoubleSource,      ComplexSource      ;
+typedef SourceArray CharSourceArray, ShortSourceArray, IntSourceArray, FloatSourceArray, DoubleSourceArray, ComplexSourceArray ;
+
+typedef int ByteCount ;
+
+/* dependant on type of source */
+
+struct           _source { Pointer (*pull)(), (*fill)(), (*roll)(), returned ; char *name, *type ; int opened ; Source (*open)() ; } ;
+struct _source_operators { Source (*set)() ; Pointer (*delete)() ; Source (*setType)() ; char *(*getType)() ; char *(*getName)() ; } ;
+
+struct _pullable_source { struct _source parent ; } ;
+struct _fillable_source { struct _source parent ; Buffer buffer ; } ;
+
+
+
+
+
+
+extern Source     setSource() ;
+extern Source    typeSource() ;
+extern char     *sourceType() ;
+extern char     *sourceName() ;
+extern Pointer deleteSource() ;
+
+extern Pointer oldPull(), oldFill(), oldRoll() ;
+
+
+extern void   sinkSource() ;
+extern void   CloseSource() ;
+extern void   sinkAndCloseSource() ;
+
+/* derived source types for different purposes */
+
+extern Source  newTappingSource() ;
+extern Source newRollableSource() ;
+
+extern Pointer nonRoller() ;
+
+
+
+/* fundamental active source types */
+
+extern Source     setPullableSource() ;
+extern Pointer deletePullableSource() ;
+
+/* simple assertive derived sources */
+
+extern Source        newSlaveSource() ;
+extern Source       newStaticSource() ;
+extern Source    newRetainingSource() ;
+extern Source     newDelayingSource() ;
+extern Source     newBlockingSource() ;
+
+
+
+/* derived higher level filling sources */
+
+extern Source         setFillableSource() ;
+extern Pointer     deleteFillableSource() ;
+
+extern Source       newSegmentingSource() ;
+
+extern Source         setCallbackSource() ;
+extern Source         newExternalSource() ;
+extern Source          newThroughSource() ;
+
+extern Source       newProcessingSource() ;
+extern Source newSimpleProcessingSource() ;
+extern Source      newMultiplexedSource() ;
+extern Source          newMergingSource() ;
+
+extern Source             sharingSource() ;
+
+extern Source *BindSources() ;
+
+/* for compatability... for now */
+
+extern Source stdStaticSource() ;
+extern Source stdSlaveSource() ;
+extern Source stdAutoSource() ;
+extern Source stdSelfSource() ;
+
+
+
+extern Source EmptySource ;
+/*
+    stypes.h
+    ======
+
+    defines types for sources operations
+
+
+*/
+
+typedef struct { char *ident ; int size ; Source (*maker)() ; } TypeInfo ;
+
+extern int typeEntryNumber() ;
+extern Source TypeConvertSource() ;
+extern Source SourceSource() ;
+
+extern char   CharIdent[] ;
+extern char  ShortIdent[] ;
+extern char    IntIdent[] ;
+extern char   LongIdent[] ;
+extern char  FloatIdent[] ;
+extern char DoubleIdent[] ;
+
+
+
+/* basic data operations */
+
+extern    CharSource    ConstantCharSource(  ),    IntegrateCharSource(  ),    CallingCharSource(  ) ;
+extern   ShortSource   ConstantShortSource(  ),   IntegrateShortSource(  ),   CallingShortSource(  ) ;
+extern     IntSource     ConstantIntSource(  ),     IntegrateIntSource(  ),     CallingIntSource(  ) ;
+extern   FloatSource   ConstantFloatSource(  ),   IntegrateFloatSource(  ),   CallingFloatSource(  ) ;
+extern  DoubleSource  ConstantDoubleSource(  ),  IntegrateDoubleSource(  ),  CallingDoubleSource(  ) ;
+extern ComplexSource ConstantComplexSource(  ), IntegrateComplexSource(  ), CallingComplexSource(  ) ;
+
+/* binary operators */
+
+extern    CharSource    AddCharSources(  ),    SubtractCharSources(  ),    MultiplyCharSources(  ),    DivideCharSources(  ) ;
+extern   ShortSource   AddShortSources(  ),   SubtractShortSources(  ),   MultiplyShortSources(  ),   DivideShortSources(  ) ;
+extern     IntSource     AddIntSources(  ),     SubtractIntSources(  ),     MultiplyIntSources(  ),     DivideIntSources(  ) ;
+extern   FloatSource   AddFloatSources(  ),   SubtractFloatSources(  ),   MultiplyFloatSources(  ),  DivideDoubleSources(  ) ;
+extern  DoubleSource  AddDoubleSources(  ),  SubtractDoubleSources(  ),  MultiplyDoubleSources(  ),   DivideFloatSources(  ) ;
+extern ComplexSource AddComplexSources(  ), SubtractComplexSources(  ), MultiplyComplexSources(  ), DivideComplexSources(  ) ;
+
+extern        Source AddSources(         ),        SubtractSources(  ),        MultiplySources(  ),        DivideSources(  ) ;
+
+/* convertors */
+
+extern    CharSource    CharCharSource(  ),    ShortCharSource(  ),    IntCharSource(  ),    FloatCharSource(  ),    DoubleCharSource(  ) ;
+extern   ShortSource   CharShortSource(  ),   ShortShortSource(  ),   IntShortSource(  ),   FloatShortSource(  ),   DoubleShortSource(  ) ;
+extern     IntSource     CharIntSource(  ),     ShortIntSource(  ),     IntIntSource(  ),     FloatIntSource(  ),     DoubleIntSource(  ) ;
+extern   FloatSource   CharFloatSource(  ),   ShortFloatSource(  ),   IntFloatSource(  ),   FloatFloatSource(  ),   DoubleFloatSource(  ) ;
+extern  DoubleSource  CharDoubleSource(  ),  ShortDoubleSource(  ),  IntDoubleSource(  ),  FloatDoubleSource(  ),  DoubleDoubleSource(  ) ;
+extern ComplexSource CharComplexSource(  ), ShortComplexSource(  ), IntComplexSource(  ), FloatComplexSource(  ), DoubleComplexSource(  ) ;
+
+extern Source SourceCharSource(  ), SourceShortSource(  ), SourceIntSource(  ), SourceFloatSource(  ), SourceDoubleSource(  ), SourceComplexSource(  ) ;
+
+
+static void charConstantCallback( state, bytes, buffer, end )
+char *state ;
+ByteCount *bytes ;
+char *buffer, *end ;
+{
+    register char  i, *optr = buffer, *eptr = end ;
+
+    i = *state ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = i ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+CharSource ConstantCharSource( constant )
+char constant ;
+{
+     char *   state  = (             char *                       ) stitch_malloc( (unsigned) (        ( sizeof * (              char *                      ) 0 ) ),                            stitchStructStr  ) ;
+
+    *state = constant ;
+
+    return ( 	newExternalSource(          (Pointer) (  (Pointer) state ),  charConstantCallback,  stitch_free,          "ops.type constant"  ) ) ;
+}
+
+
+static void charIntegralCallback( integral, bytes, buffer, end, input )
+char *integral ;
+ByteCount *bytes ;
+char *buffer, *end, *input ;
+{
+    register char *iptr = input ;
+    register char *optr = buffer ;
+    register char *eptr = end ;
+
+    if( optr < eptr )
+	do {
+	    *optr++ = *integral ;
+	    *integral += *iptr++ ;
+	} while( optr < eptr ) ;
+
+    return ;
+}
+
+CharSource IntegrateCharSource( source, initial )
+CharSource source ;
+char initial ;
+{
+     char *   integral  = (             char *                       ) stitch_malloc( (unsigned) (        ( sizeof * (              char *                      ) 0 ) ),                            stitchStructStr  ) ;
+
+    *integral = initial ;
+
+    return ( 	newProcessingSource(        (Pointer) (  (Pointer) integral ),  charIntegralCallback,  stitch_free,  source,  "ops.type integrating"  ) ) ;
+}
+
+static void charCallingCallback( function, bytes, buffer, end, input )
+char (*function)() ;
+ByteCount *bytes ;
+char *buffer, *end, *input ;
+{
+    register char   *iptr = input ;
+    register char   *optr = buffer ;
+    register char   *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = function( *iptr++ ) ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+CharSource CallingCharSource( source, function )
+CharSource source ;
+char (*function)() ;
+{
+    return ( 	newProcessingSource(        (Pointer) (  (Pointer) function ),  charCallingCallback,  (void ( * )()) 0,  source,  "ops.type function"   ) ) ;
+}
+
+/* do operators */
+
+
+static void AddCharOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+char *output, *end, *input1, *input2 ;
+{
+    register char *optr = output ;
+    register char *ipt1 = input1 ;
+    register char *ipt2 = input2 ;
+    register char *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ + *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source AddCharSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  AddCharOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source AddCharSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  AddCharOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+static void SubtractCharOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+char *output, *end, *input1, *input2 ;
+{
+    register char *optr = output ;
+    register char *ipt1 = input1 ;
+    register char *ipt2 = input2 ;
+    register char *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ - *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source SubtractCharSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  SubtractCharOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source SubtractCharSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  SubtractCharOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+static void MultiplyCharOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+char *output, *end, *input1, *input2 ;
+{
+    register char *optr = output ;
+    register char *ipt1 = input1 ;
+    register char *ipt2 = input2 ;
+    register char *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ * *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source MultiplyCharSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  MultiplyCharOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source MultiplyCharSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  MultiplyCharOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+static void DivideCharOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+char *output, *end, *input1, *input2 ;
+{
+    register char *optr = output ;
+    register char *ipt1 = input1 ;
+    register char *ipt2 = input2 ;
+    register char *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ / *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source DivideCharSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  DivideCharOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source DivideCharSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  DivideCharOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+
+
+/* create convertors */
+
+static void CharCharCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+char *buffer ;
+{
+    register char  *i = ( ( char  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  char  *) 0l + (   ( (  bytes  ) >> ( sizeof( char) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register char   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+CharSource CharCharSource( source )
+CharSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, CharCharCallback ) ) ;
+}
+
+
+static void ShortCharCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+char *buffer ;
+{
+    register short  *i = ( ( short  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  short  *) 0l + (   ( (  bytes  ) >> ( sizeof( char) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register char   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+CharSource ShortCharSource( source )
+CharSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, ShortCharCallback ) ) ;
+}
+
+
+
+
+static void IntCharCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+char *buffer ;
+{
+    register int  *i = ( ( int  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  int  *) 0l + (   ( (  bytes  ) >> ( sizeof( char) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register char   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+CharSource IntCharSource( source )
+CharSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, IntCharCallback ) ) ;
+}
+
+
+static void FloatCharCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+char *buffer ;
+{
+    register float  *i = ( ( float  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  float  *) 0l + (   ( (  bytes  ) >> ( sizeof( char) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register char   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+CharSource FloatCharSource( source )
+CharSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, FloatCharCallback ) ) ;
+}
+
+
+
+static void DoubleCharCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+char *buffer ;
+{
+    register double  *i = ( ( double  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  double  *) 0l + (   ( (  bytes  ) >> ( sizeof( char) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register char   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+CharSource DoubleCharSource( source )
+CharSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, DoubleCharCallback ) ) ;
+}
+
+
+
+
+Source SourceCharSource( source )
+Source source ;
+{
+    static Source (*converts[])() = {
+		 SourceSource,
+       CharCharSource,
+      ShortCharSource,
+	IntCharSource,
+      FloatCharSource,
+     DoubleCharSource
+    } ;
+
+    return ( converts[ typeEntryNumber( sourceType( (struct _source *)  source                                    ) ) ]( source ) ) ;
+}
+
+
+static void shortConstantCallback( state, bytes, buffer, end )
+short *state ;
+ByteCount *bytes ;
+short *buffer, *end ;
+{
+    register short  i, *optr = buffer, *eptr = end ;
+
+    i = *state ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = i ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+ShortSource ConstantShortSource( constant )
+short constant ;
+{
+     short *   state  = (             short *                       ) stitch_malloc( (unsigned) (        ( sizeof * (              short *                      ) 0 ) ),                            stitchStructStr  ) ;
+
+    *state = constant ;
+
+    return ( 	newExternalSource(          (Pointer) (  (Pointer) state ),  shortConstantCallback,  stitch_free,          "ops.type constant"  ) ) ;
+}
+
+
+static void shortIntegralCallback( integral, bytes, buffer, end, input )
+short *integral ;
+ByteCount *bytes ;
+short *buffer, *end, *input ;
+{
+    register short *iptr = input ;
+    register short *optr = buffer ;
+    register short *eptr = end ;
+
+    if( optr < eptr )
+	do {
+	    *optr++ = *integral ;
+	    *integral += *iptr++ ;
+	} while( optr < eptr ) ;
+
+    return ;
+}
+
+ShortSource IntegrateShortSource( source, initial )
+ShortSource source ;
+short initial ;
+{
+     short *   integral  = (             short *                       ) stitch_malloc( (unsigned) (        ( sizeof * (              short *                      ) 0 ) ),                            stitchStructStr  ) ;
+
+    *integral = initial ;
+
+    return ( 	newProcessingSource(        (Pointer) (  (Pointer) integral ),  shortIntegralCallback,  stitch_free,  source,  "ops.type integrating"  ) ) ;
+}
+
+static void shortCallingCallback( function, bytes, buffer, end, input )
+short (*function)() ;
+ByteCount *bytes ;
+short *buffer, *end, *input ;
+{
+    register short   *iptr = input ;
+    register short   *optr = buffer ;
+    register short   *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = function( *iptr++ ) ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+ShortSource CallingShortSource( source, function )
+ShortSource source ;
+short (*function)() ;
+{
+    return ( 	newProcessingSource(        (Pointer) (  (Pointer) function ),  shortCallingCallback,  (void ( * )()) 0,  source,  "ops.type function"   ) ) ;
+}
+
+/* do operators */
+
+static void AddShortOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+short *output, *end, *input1, *input2 ;
+{
+    register short *optr = output ;
+    register short *ipt1 = input1 ;
+    register short *ipt2 = input2 ;
+    register short *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ + *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source AddShortSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  AddShortOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source AddShortSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  AddShortOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+static void SubtractShortOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+short *output, *end, *input1, *input2 ;
+{
+    register short *optr = output ;
+    register short *ipt1 = input1 ;
+    register short *ipt2 = input2 ;
+    register short *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ - *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source SubtractShortSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  SubtractShortOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source SubtractShortSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  SubtractShortOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+static void MultiplyShortOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+short *output, *end, *input1, *input2 ;
+{
+    register short *optr = output ;
+    register short *ipt1 = input1 ;
+    register short *ipt2 = input2 ;
+    register short *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ * *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source MultiplyShortSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  MultiplyShortOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source MultiplyShortSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  MultiplyShortOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+static void DivideShortOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+short *output, *end, *input1, *input2 ;
+{
+    register short *optr = output ;
+    register short *ipt1 = input1 ;
+    register short *ipt2 = input2 ;
+    register short *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ / *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source DivideShortSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  DivideShortOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source DivideShortSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  DivideShortOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+
+
+/* create convertors */
+
+
+static void CharShortCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+short *buffer ;
+{
+    register char  *i = ( ( char  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  char  *) 0l + (   ( (  bytes  ) >> ( sizeof( short) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register short   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+ShortSource CharShortSource( source )
+ShortSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, CharShortCallback ) ) ;
+}
+
+
+
+static void ShortShortCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+short *buffer ;
+{
+    register short  *i = ( ( short  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  short  *) 0l + (   ( (  bytes  ) >> ( sizeof( short) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register short   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+ShortSource ShortShortSource( source )
+ShortSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, ShortShortCallback ) ) ;
+}
+
+
+static void IntShortCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+short *buffer ;
+{
+    register int  *i = ( ( int  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  int  *) 0l + (   ( (  bytes  ) >> ( sizeof( short) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register short   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+ShortSource IntShortSource( source )
+ShortSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, IntShortCallback ) ) ;
+}
+
+
+
+static void FloatShortCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+short *buffer ;
+{
+    register float  *i = ( ( float  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  float  *) 0l + (   ( (  bytes  ) >> ( sizeof( short) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register short   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+ShortSource FloatShortSource( source )
+ShortSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, FloatShortCallback ) ) ;
+}
+
+
+static void DoubleShortCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+short *buffer ;
+{
+    register double  *i = ( ( double  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  double  *) 0l + (   ( (  bytes  ) >> ( sizeof( short) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register short   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+ShortSource DoubleShortSource( source )
+ShortSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, DoubleShortCallback ) ) ;
+}
+
+
+
+
+Source SourceShortSource( source )
+Source source ;
+{
+    static Source (*converts[])() = {
+		 SourceSource,
+       CharShortSource,
+      ShortShortSource,
+	IntShortSource,
+      FloatShortSource,
+     DoubleShortSource
+    } ;
+
+    return ( converts[ typeEntryNumber( sourceType( (struct _source *)  source                                    ) ) ]( source ) ) ;
+}
+
+
+
+static void intConstantCallback( state, bytes, buffer, end )
+int *state ;
+ByteCount *bytes ;
+int *buffer, *end ;
+{
+    register int  i, *optr = buffer, *eptr = end ;
+
+    i = *state ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = i ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+IntSource ConstantIntSource( constant )
+int constant ;
+{
+     int *   state  = (             int *                       ) stitch_malloc( (unsigned) (        ( sizeof * (              int *                      ) 0 ) ),                            stitchStructStr  ) ;
+
+    *state = constant ;
+
+    return ( 	newExternalSource(          (Pointer) (  (Pointer) state ),  intConstantCallback,  stitch_free,          "ops.type constant"  ) ) ;
+}
+
+
+static void intIntegralCallback( integral, bytes, buffer, end, input )
+int *integral ;
+ByteCount *bytes ;
+int *buffer, *end, *input ;
+{
+    register int *iptr = input ;
+    register int *optr = buffer ;
+    register int *eptr = end ;
+
+    if( optr < eptr )
+	do {
+	    *optr++ = *integral ;
+	    *integral += *iptr++ ;
+	} while( optr < eptr ) ;
+
+    return ;
+}
+
+IntSource IntegrateIntSource( source, initial )
+IntSource source ;
+int initial ;
+{
+     int *   integral  = (             int *                       ) stitch_malloc( (unsigned) (        ( sizeof * (              int *                      ) 0 ) ),                            stitchStructStr  ) ;
+
+    *integral = initial ;
+
+    return ( 	newProcessingSource(        (Pointer) (  (Pointer) integral ),  intIntegralCallback,  stitch_free,  source,  "ops.type integrating"  ) ) ;
+}
+
+static void intCallingCallback( function, bytes, buffer, end, input )
+int (*function)() ;
+ByteCount *bytes ;
+int *buffer, *end, *input ;
+{
+    register int   *iptr = input ;
+    register int   *optr = buffer ;
+    register int   *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = function( *iptr++ ) ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+IntSource CallingIntSource( source, function )
+IntSource source ;
+int (*function)() ;
+{
+    return ( 	newProcessingSource(        (Pointer) (  (Pointer) function ),  intCallingCallback,  (void ( * )()) 0,  source,  "ops.type function"   ) ) ;
+}
+
+/* do operators */
+
+
+static void AddIntOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+int *output, *end, *input1, *input2 ;
+{
+    register int *optr = output ;
+    register int *ipt1 = input1 ;
+    register int *ipt2 = input2 ;
+    register int *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ + *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source AddIntSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  AddIntOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source AddIntSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  AddIntOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+
+static void SubtractIntOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+int *output, *end, *input1, *input2 ;
+{
+    register int *optr = output ;
+    register int *ipt1 = input1 ;
+    register int *ipt2 = input2 ;
+    register int *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ - *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source SubtractIntSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  SubtractIntOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source SubtractIntSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  SubtractIntOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+
+
+static void MultiplyIntOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+int *output, *end, *input1, *input2 ;
+{
+    register int *optr = output ;
+    register int *ipt1 = input1 ;
+    register int *ipt2 = input2 ;
+    register int *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ * *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source MultiplyIntSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  MultiplyIntOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source MultiplyIntSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  MultiplyIntOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+
+static void DivideIntOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+int *output, *end, *input1, *input2 ;
+{
+    register int *optr = output ;
+    register int *ipt1 = input1 ;
+    register int *ipt2 = input2 ;
+    register int *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ / *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source DivideIntSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  DivideIntOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source DivideIntSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  DivideIntOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+
+
+/* create convertors */
+
+static void CharIntCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+int *buffer ;
+{
+    register char  *i = ( ( char  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  char  *) 0l + (   ( (  bytes  ) >> ( sizeof( int) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register int   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+IntSource CharIntSource( source )
+IntSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, CharIntCallback ) ) ;
+}
+
+
+
+static void ShortIntCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+int *buffer ;
+{
+    register short  *i = ( ( short  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  short  *) 0l + (   ( (  bytes  ) >> ( sizeof( int) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register int   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+IntSource ShortIntSource( source )
+IntSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, ShortIntCallback ) ) ;
+}
+
+
+
+static void IntIntCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+int *buffer ;
+{
+    register int  *i = ( ( int  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  int  *) 0l + (   ( (  bytes  ) >> ( sizeof( int) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register int   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+IntSource IntIntSource( source )
+IntSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, IntIntCallback ) ) ;
+}
+
+
+
+static void FloatIntCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+int *buffer ;
+{
+    register float  *i = ( ( float  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  float  *) 0l + (   ( (  bytes  ) >> ( sizeof( int) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register int   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+IntSource FloatIntSource( source )
+IntSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, FloatIntCallback ) ) ;
+}
+
+
+
+static void DoubleIntCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+int *buffer ;
+{
+    register double  *i = ( ( double  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  double  *) 0l + (   ( (  bytes  ) >> ( sizeof( int) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register int   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+IntSource DoubleIntSource( source )
+IntSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, DoubleIntCallback ) ) ;
+}
+
+
+
+
+Source SourceIntSource( source )
+Source source ;
+{
+    static Source (*converts[])() = {
+		 SourceSource,
+       CharIntSource,
+      ShortIntSource,
+	IntIntSource,
+      FloatIntSource,
+     DoubleIntSource
+    } ;
+
+    return ( converts[ typeEntryNumber( sourceType( (struct _source *)  source                                    ) ) ]( source ) ) ;
+}
+
+
+static void floatConstantCallback( state, bytes, buffer, end )
+float *state ;
+ByteCount *bytes ;
+float *buffer, *end ;
+{
+    register float  i, *optr = buffer, *eptr = end ;
+
+    i = *state ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = i ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+FloatSource ConstantFloatSource( constant )
+float constant ;
+{
+     float *   state  = (             float *                       ) stitch_malloc( (unsigned) (        ( sizeof * (              float *                      ) 0 ) ),                            stitchStructStr  ) ;
+
+    *state = constant ;
+
+    return ( 	newExternalSource(          (Pointer) (  (Pointer) state ),  floatConstantCallback,  stitch_free,          "ops.type constant"  ) ) ;
+}
+
+
+static void floatIntegralCallback( integral, bytes, buffer, end, input )
+float *integral ;
+ByteCount *bytes ;
+float *buffer, *end, *input ;
+{
+    register float *iptr = input ;
+    register float *optr = buffer ;
+    register float *eptr = end ;
+
+    if( optr < eptr )
+	do {
+	    *optr++ = *integral ;
+	    *integral += *iptr++ ;
+	} while( optr < eptr ) ;
+
+    return ;
+}
+
+FloatSource IntegrateFloatSource( source, initial )
+FloatSource source ;
+float initial ;
+{
+     float *   integral  = (             float *                       ) stitch_malloc( (unsigned) (        ( sizeof * (              float *                      ) 0 ) ),                            stitchStructStr  ) ;
+
+    *integral = initial ;
+
+    return ( 	newProcessingSource(        (Pointer) (  (Pointer) integral ),  floatIntegralCallback,  stitch_free,  source,  "ops.type integrating"  ) ) ;
+}
+
+static void floatCallingCallback( function, bytes, buffer, end, input )
+float (*function)() ;
+ByteCount *bytes ;
+float *buffer, *end, *input ;
+{
+    register float   *iptr = input ;
+    register float   *optr = buffer ;
+    register float   *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = function( *iptr++ ) ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+FloatSource CallingFloatSource( source, function )
+FloatSource source ;
+float (*function)() ;
+{
+    return ( 	newProcessingSource(        (Pointer) (  (Pointer) function ),  floatCallingCallback,  (void ( * )()) 0,  source,  "ops.type function"   ) ) ;
+}
+
+/* do operators */
+
+static void AddFloatOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+float *output, *end, *input1, *input2 ;
+{
+    register float *optr = output ;
+    register float *ipt1 = input1 ;
+    register float *ipt2 = input2 ;
+    register float *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ + *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source AddFloatSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  AddFloatOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source AddFloatSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  AddFloatOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+
+static void SubtractFloatOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+float *output, *end, *input1, *input2 ;
+{
+    register float *optr = output ;
+    register float *ipt1 = input1 ;
+    register float *ipt2 = input2 ;
+    register float *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ - *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source SubtractFloatSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  SubtractFloatOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source SubtractFloatSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  SubtractFloatOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+static void MultiplyFloatOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+float *output, *end, *input1, *input2 ;
+{
+    register float *optr = output ;
+    register float *ipt1 = input1 ;
+    register float *ipt2 = input2 ;
+    register float *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ * *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source MultiplyFloatSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  MultiplyFloatOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source MultiplyFloatSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  MultiplyFloatOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+
+static void DivideFloatOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+float *output, *end, *input1, *input2 ;
+{
+    register float *optr = output ;
+    register float *ipt1 = input1 ;
+    register float *ipt2 = input2 ;
+    register float *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ / *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source DivideFloatSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  DivideFloatOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source DivideFloatSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  DivideFloatOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+
+
+/* create convertors */
+
+
+static void CharFloatCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+float *buffer ;
+{
+    register char  *i = ( ( char  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  char  *) 0l + (   ( (  bytes  ) >> ( sizeof( float) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register float   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+FloatSource CharFloatSource( source )
+FloatSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, CharFloatCallback ) ) ;
+}
+
+
+static void ShortFloatCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+float *buffer ;
+{
+    register short  *i = ( ( short  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  short  *) 0l + (   ( (  bytes  ) >> ( sizeof( float) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register float   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+FloatSource ShortFloatSource( source )
+FloatSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, ShortFloatCallback ) ) ;
+}
+
+
+
+static void IntFloatCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+float *buffer ;
+{
+    register int  *i = ( ( int  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  int  *) 0l + (   ( (  bytes  ) >> ( sizeof( float) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register float   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+FloatSource IntFloatSource( source )
+FloatSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, IntFloatCallback ) ) ;
+}
+
+
+
+static void FloatFloatCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+float *buffer ;
+{
+    register float  *i = ( ( float  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  float  *) 0l + (   ( (  bytes  ) >> ( sizeof( float) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register float   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+FloatSource FloatFloatSource( source )
+FloatSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, FloatFloatCallback ) ) ;
+}
+
+
+
+static void DoubleFloatCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+float *buffer ;
+{
+    register double  *i = ( ( double  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  double  *) 0l + (   ( (  bytes  ) >> ( sizeof( float) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register float   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+FloatSource DoubleFloatSource( source )
+FloatSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, DoubleFloatCallback ) ) ;
+}
+
+
+
+
+Source SourceFloatSource( source )
+Source source ;
+{
+    static Source (*converts[])() = {
+		 SourceSource,
+       CharFloatSource,
+      ShortFloatSource,
+	IntFloatSource,
+      FloatFloatSource,
+     DoubleFloatSource
+    } ;
+
+    return ( converts[ typeEntryNumber( sourceType( (struct _source *)  source                                    ) ) ]( source ) ) ;
+}
+
+
+
+
+static void doubleConstantCallback( state, bytes, buffer, end )
+double *state ;
+ByteCount *bytes ;
+double *buffer, *end ;
+{
+    register double  i, *optr = buffer, *eptr = end ;
+
+    i = *state ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = i ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+DoubleSource ConstantDoubleSource( constant )
+double constant ;
+{
+     double *   state  = (             double *                       ) stitch_malloc( (unsigned) (        ( sizeof * (              double *                      ) 0 ) ),                            stitchStructStr  ) ;
+
+    *state = constant ;
+
+    return ( 	newExternalSource(          (Pointer) (  (Pointer) state ),  doubleConstantCallback,  stitch_free,          "ops.type constant"  ) ) ;
+}
+
+
+static void doubleIntegralCallback( integral, bytes, buffer, end, input )
+double *integral ;
+ByteCount *bytes ;
+double *buffer, *end, *input ;
+{
+    register double *iptr = input ;
+    register double *optr = buffer ;
+    register double *eptr = end ;
+
+    if( optr < eptr )
+	do {
+	    *optr++ = *integral ;
+	    *integral += *iptr++ ;
+	} while( optr < eptr ) ;
+
+    return ;
+}
+
+DoubleSource IntegrateDoubleSource( source, initial )
+DoubleSource source ;
+double initial ;
+{
+     double *   integral  = (             double *                       ) stitch_malloc( (unsigned) (        ( sizeof * (              double *                      ) 0 ) ),                            stitchStructStr  ) ;
+
+    *integral = initial ;
+
+    return ( 	newProcessingSource(        (Pointer) (  (Pointer) integral ),  doubleIntegralCallback,  stitch_free,  source,  "ops.type integrating"  ) ) ;
+}
+
+static void doubleCallingCallback( function, bytes, buffer, end, input )
+double (*function)() ;
+ByteCount *bytes ;
+double *buffer, *end, *input ;
+{
+    register double   *iptr = input ;
+    register double   *optr = buffer ;
+    register double   *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = function( *iptr++ ) ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+DoubleSource CallingDoubleSource( source, function )
+DoubleSource source ;
+double (*function)() ;
+{
+    return ( 	newProcessingSource(        (Pointer) (  (Pointer) function ),  doubleCallingCallback,  (void ( * )()) 0,  source,  "ops.type function"   ) ) ;
+}
+
+/* do operators */
+
+
+static void AddDoubleOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+double *output, *end, *input1, *input2 ;
+{
+    register double *optr = output ;
+    register double *ipt1 = input1 ;
+    register double *ipt2 = input2 ;
+    register double *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ + *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source AddDoubleSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  AddDoubleOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source AddDoubleSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  AddDoubleOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+
+
+static void SubtractDoubleOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+double *output, *end, *input1, *input2 ;
+{
+    register double *optr = output ;
+    register double *ipt1 = input1 ;
+    register double *ipt2 = input2 ;
+    register double *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ - *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source SubtractDoubleSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  SubtractDoubleOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source SubtractDoubleSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  SubtractDoubleOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+
+
+static void MultiplyDoubleOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+double *output, *end, *input1, *input2 ;
+{
+    register double *optr = output ;
+    register double *ipt1 = input1 ;
+    register double *ipt2 = input2 ;
+    register double *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ * *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source MultiplyDoubleSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  MultiplyDoubleOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source MultiplyDoubleSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  MultiplyDoubleOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+static void DivideDoubleOp( state, bytes, output, end, input1, input2 )
+Pointer *state ;
+ByteCount *bytes ;
+double *output, *end, *input1, *input2 ;
+{
+    register double *optr = output ;
+    register double *ipt1 = input1 ;
+    register double *ipt2 = input2 ;
+    register double *eptr = end ;
+
+    if( optr < eptr )
+	do
+	    *optr++ = *ipt1++ / *ipt2++ ;
+	while( optr < eptr ) ;
+
+    return ;
+}
+
+Source DivideDoubleSources( input1, input2 )
+Source input1, input2 ;
+{
+     Source * inputs = (        Source *) stitch_malloc( (unsigned) (        sizeof (        Source) * (unsigned) (   3 ) ),                                      "for 2 inputs"    ) ;
+
+    inputs[0] =  input1    ;
+    inputs[1] =  input2    ;
+
+     inputs[2]  = (struct _source *) 0 ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  DivideDoubleOp,  (void ( * )()) 0,  inputs,  "binary operator"  ) ) ;
+}
+
+/* VARARGS2 */
+Source DivideDoubleSourceArray( inputs )
+Source *inputs ;
+{
+    int count = 0 ;
+
+    while(  inputs[count]  != (struct _source *) 0 )
+	count++ ;
+
+    return( 	newMergingSource(           (Pointer) (  (Pointer) 0 ),  DivideDoubleOp,  (void ( * )()) 0,  inputs,  "operator"  ) ) ;
+}
+
+
+
+
+/* create convertors */
+
+
+static void CharDoubleCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+double *buffer ;
+{
+    register char  *i = ( ( char  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  char  *) 0l + (   ( (  bytes  ) >> ( sizeof( double) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register double   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+DoubleSource CharDoubleSource( source )
+DoubleSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, CharDoubleCallback ) ) ;
+}
+
+
+
+
+static void ShortDoubleCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+double *buffer ;
+{
+    register short  *i = ( ( short  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  short  *) 0l + (   ( (  bytes  ) >> ( sizeof( double) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register double   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+DoubleSource ShortDoubleSource( source )
+DoubleSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, ShortDoubleCallback ) ) ;
+}
+
+
+
+static void IntDoubleCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+double *buffer ;
+{
+    register int  *i = ( ( int  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  int  *) 0l + (   ( (  bytes  ) >> ( sizeof( double) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register double   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+DoubleSource IntDoubleSource( source )
+DoubleSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, IntDoubleCallback ) ) ;
+}
+
+
+
+
+static void FloatDoubleCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+double *buffer ;
+{
+    register float  *i = ( ( float  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  float  *) 0l + (   ( (  bytes  ) >> ( sizeof( double) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register double   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+DoubleSource FloatDoubleSource( source )
+DoubleSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, FloatDoubleCallback ) ) ;
+}
+
+
+static void DoubleDoubleCallback( state, bytes, buffer )
+Source state ;
+ByteCount bytes ;
+double *buffer ;
+{
+    register double  *i = ( ( double  *) (    state ->returned =                oldPull(    state , (ByteCount  ) (  ( ( char *) ( (  double  *) 0l + (   ( (  bytes  ) >> ( sizeof( double) >> 1 ) )  ) ) - ( char *) 0l )  )                          ) ) ) ;
+    register double   *o = buffer ;
+    register Pointer e = (Pointer) buffer + bytes ;
+
+    if( (Pointer) o < e )
+	do
+	    *o++ = *i++ ;
+	while( (Pointer) o < e ) ;
+
+    return ;
+}
+
+DoubleSource DoubleDoubleSource( source )
+DoubleSource source ;
+{
+    return( stdAutoSource( ( Pointer ) source, DoubleDoubleCallback ) ) ;
+}
+
+
+
+
+Source SourceDoubleSource( source )
+Source source ;
+{
+    static Source (*converts[])() = {
+		 SourceSource,
+       CharDoubleSource,
+      ShortDoubleSource,
+	IntDoubleSource,
+      FloatDoubleSource,
+     DoubleDoubleSource
+    } ;
+
+    return ( converts[ typeEntryNumber( sourceType( (struct _source *)  source                                    ) ) ]( source ) ) ;
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/ops.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,62 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    ops.h
+    =====
+
+*/
+
+
+/* basic data operations */
+
+extern    CharSource    ConstantCharSource( _MANY_ARGS ),    IntegrateCharSource( _ONE_SOURCE_PLUS ),    CallingCharSource( _ONE_SOURCE_PLUS ) ;
+extern   ShortSource   ConstantShortSource( _MANY_ARGS ),   IntegrateShortSource( _ONE_SOURCE_PLUS ),   CallingShortSource( _ONE_SOURCE_PLUS ) ;
+extern     IntSource     ConstantIntSource( _MANY_ARGS ),     IntegrateIntSource( _ONE_SOURCE_PLUS ),     CallingIntSource( _ONE_SOURCE_PLUS ) ;
+extern   FloatSource   ConstantFloatSource( _MANY_ARGS ),   IntegrateFloatSource( _ONE_SOURCE_PLUS ),   CallingFloatSource( _ONE_SOURCE_PLUS ) ;
+extern  DoubleSource  ConstantDoubleSource( _MANY_ARGS ),  IntegrateDoubleSource( _ONE_SOURCE_PLUS ),  CallingDoubleSource( _ONE_SOURCE_PLUS ) ;
+extern ComplexSource ConstantComplexSource( _MANY_ARGS ), IntegrateComplexSource( _ONE_SOURCE_PLUS ), CallingComplexSource( _ONE_SOURCE_PLUS ) ;
+
+/* binary operators */
+
+extern    CharSource    AddCharSources( _TWO_SOURCES ),    SubtractCharSources( _TWO_SOURCES ),    MultiplyCharSources( _TWO_SOURCES ),    DivideCharSources( _TWO_SOURCES ) ;
+extern   ShortSource   AddShortSources( _TWO_SOURCES ),   SubtractShortSources( _TWO_SOURCES ),   MultiplyShortSources( _TWO_SOURCES ),   DivideShortSources( _TWO_SOURCES ) ;
+extern     IntSource     AddIntSources( _TWO_SOURCES ),     SubtractIntSources( _TWO_SOURCES ),     MultiplyIntSources( _TWO_SOURCES ),     DivideIntSources( _TWO_SOURCES ) ;
+extern   FloatSource   AddFloatSources( _TWO_SOURCES ),   SubtractFloatSources( _TWO_SOURCES ),   MultiplyFloatSources( _TWO_SOURCES ),  DivideDoubleSources( _TWO_SOURCES ) ;
+extern  DoubleSource  AddDoubleSources( _TWO_SOURCES ),  SubtractDoubleSources( _TWO_SOURCES ),  MultiplyDoubleSources( _TWO_SOURCES ),   DivideFloatSources( _TWO_SOURCES ) ;
+extern ComplexSource AddComplexSources( _TWO_SOURCES ), SubtractComplexSources( _TWO_SOURCES ), MultiplyComplexSources( _TWO_SOURCES ), DivideComplexSources( _TWO_SOURCES ) ;
+
+extern        Source AddSources(        _TWO_SOURCES ),        SubtractSources( _TWO_SOURCES ),        MultiplySources( _TWO_SOURCES ),        DivideSources( _TWO_SOURCES ) ;
+
+/* convertors */
+
+extern    CharSource    CharCharSource( _ONE_SOURCE ),    ShortCharSource( _ONE_SOURCE ),    IntCharSource( _ONE_SOURCE ),    FloatCharSource( _ONE_SOURCE ),    DoubleCharSource( _ONE_SOURCE ) ;
+extern   ShortSource   CharShortSource( _ONE_SOURCE ),   ShortShortSource( _ONE_SOURCE ),   IntShortSource( _ONE_SOURCE ),   FloatShortSource( _ONE_SOURCE ),   DoubleShortSource( _ONE_SOURCE ) ;
+extern     IntSource     CharIntSource( _ONE_SOURCE ),     ShortIntSource( _ONE_SOURCE ),     IntIntSource( _ONE_SOURCE ),     FloatIntSource( _ONE_SOURCE ),     DoubleIntSource( _ONE_SOURCE ) ;
+extern   FloatSource   CharFloatSource( _ONE_SOURCE ),   ShortFloatSource( _ONE_SOURCE ),   IntFloatSource( _ONE_SOURCE ),   FloatFloatSource( _ONE_SOURCE ),   DoubleFloatSource( _ONE_SOURCE ) ;
+extern  DoubleSource  CharDoubleSource( _ONE_SOURCE ),  ShortDoubleSource( _ONE_SOURCE ),  IntDoubleSource( _ONE_SOURCE ),  FloatDoubleSource( _ONE_SOURCE ),  DoubleDoubleSource( _ONE_SOURCE ) ;
+extern ComplexSource CharComplexSource( _ONE_SOURCE ), ShortComplexSource( _ONE_SOURCE ), IntComplexSource( _ONE_SOURCE ), FloatComplexSource( _ONE_SOURCE ), DoubleComplexSource( _ONE_SOURCE ) ;
+
+extern Source SourceCharSource( _ONE_SOURCE ), SourceShortSource( _ONE_SOURCE ), SourceIntSource( _ONE_SOURCE ), SourceFloatSource( _ONE_SOURCE ), SourceDoubleSource( _ONE_SOURCE ), SourceComplexSource( _ONE_SOURCE ) ;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/pullable.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,230 @@
+/*
+    pullable.c
+    ==========
+
+    sources who's native operation is receive pull commands.
+
+*/
+
+#include "stitch.h"
+#include "source.h"
+
+#ifndef  lint
+static char *sccs_id = "@(#)pullable.c	1.3 John Holdsworth (MRC-APU) 6/6/91" ;
+#endif
+
+#if 0
+#define DEBUG 1
+#endif
+
+/*
+    fill a users buffer from a process that returns it's own buffer
+
+*/
+
+static Pointer fillFromPullable( source, bytes, buffer )
+struct _pullable_source *source ;
+ByteCount *bytes ;
+Pointer buffer ;
+{
+    Pointer input = source->parent.pull( source, bytes ) ;
+
+    CopyArray( (char *) input, (char *) buffer, *bytes ) ;
+
+    return ( buffer ) ;
+}
+
+Source setPullableSource( source, puller, name )
+struct _pullable_source *source ;
+Pointer (*puller)() ;
+char *name ;
+{
+    return ( SetSource( source, puller, fillFromPullable, nonRoller, name ) ) ;
+}
+
+Pointer deletePullableSource( source )
+struct _pullable_source *source ;
+{
+    return ( DeleteSource( source ) ) ;
+}
+
+/*
+    simple slave source as example of derived source
+
+*/
+
+typedef struct { struct _pullable_source parent ; Source master ; } *SlaveSource ;
+
+static Pointer slavePull( source, bytes )
+SlaveSource source ;
+ByteCount *bytes ;
+{
+    register int last = *bytes == 0 ;
+
+    if( !last )
+	return ( _SPTR( source->master )->returned ) ;
+    else
+	return ( DeletePullableSource( source ) ) ;
+}
+
+Source newSlaveSource( master )
+Source master ;
+{
+    DeclareNew( SlaveSource, source ) ;
+
+    source->master = master ;
+
+    return ( SetPullableSource( source, slavePull, "pullable.c slave" ) ) ;
+}
+
+/*
+    the simplest Source is one direct from memory
+
+*/
+
+typedef struct {
+ struct _pullable_source parent ;
+ Pointer next ;
+ } *StaticSource ;
+
+static Pointer staticPull( source, bytes )
+StaticSource source ;
+ByteCount *bytes ;
+{
+    register int last = *bytes == 0 ;
+    register Pointer this = source->next ;
+
+    if( !last ) {
+
+	source->next += abs( *bytes ) ;
+
+	return ( this ) ;
+    }
+    else
+	return ( DeletePullableSource( source ) ) ;
+}
+
+Source newStaticSource( pointer )
+Pointer pointer ;
+{
+    DeclareNew( StaticSource, source ) ;
+
+    source->next = pointer ;
+
+    return ( SetPullableSource( source, staticPull, "pullable.c static" ) ) ;
+}
+
+typedef struct {
+ struct _pullable_source parent ;
+ Source input ; Pointer buffer ; ByteCount retained ;
+} *RetainingSource ;
+
+static Pointer retaining_callback( source, bytes )
+RetainingSource source ;
+ByteCount *bytes ;
+{
+    register int last = *bytes == 0 ;
+    Pointer buffer = RollSome( source->input, bytes, source->retained ) ;
+
+    if( !last )
+	return ( buffer ) ;
+    else
+	return ( DeletePullableSource( source ) ) ;
+}
+
+Source newRetainingSource( input, retained )
+Source input ;
+ByteCount retained ;
+{
+    DeclareNew( RetainingSource, source ) ;
+
+    source->retained = retained ;
+
+    source->input = NewRollableSource( input ) ;
+
+    return ( SetPullableSource( source, retaining_callback, "pullable.c retaining" ) ) ;
+}
+
+typedef struct {
+ struct _pullable_source parent ;
+ Source input ; ByteCount delay ;
+ } *DelayingSource  ;
+
+static Pointer delay_callback( source, bytes )
+DelayingSource source ;
+ByteCount *bytes ;
+{
+    register int last = *bytes == 0 ;
+    Pointer delayed = PullSome( source->input, bytes ) - source->delay ;
+
+    if( !last )
+	return ( delayed ) ;
+    else
+	return ( DeletePullableSource( source ) ) ;
+}
+
+Source newDelayingSource( input, delay )
+Source input ;
+ByteCount delay ;
+{
+    DeclareNew( DelayingSource, source ) ;
+
+    source->input = NewRetainingSource( input, delay ) ;
+
+    source->delay = delay ;
+
+    return ( SetPullableSource( source, delay_callback, "pullable.c delaying" ) ) ;
+}
+
+typedef struct {
+ struct _pullable_source parent ;
+ Source input ; Pointer buffer, position, end ; ByteCount segment ;
+} *BlockingSource ;
+
+static Pointer block_callback( source, bytes )
+BlockingSource source ;
+ByteCount *bytes ;
+{
+    register int last = *bytes == 0 ;
+    ByteCount segment = source->segment ;
+
+    if( source->position == source->end || last ) {
+
+	if( segment < *bytes || last )
+	    segment = *bytes ;
+
+	source->buffer = PullSome( source->input, &segment ) ;
+#if DEBUG
+printf( "pulled block at %x from %s\n", source->buffer, SourceName( source->input ) ) ;
+#endif
+	source->end  = source->buffer + segment ;
+
+	source->position = source->buffer ;
+    }
+
+    if( *bytes > source->end - source->position )
+	*bytes = source->end - source->position ;
+
+    source->position += *bytes ;
+
+    if( !last )
+	return ( source->position - *bytes ) ;
+    else
+	return ( DeletePullableSource( source ) ) ;
+}
+
+Source newBlockingSource( input, segment )
+Source input ;
+ByteCount segment ;
+{
+    DeclareNew( BlockingSource, source ) ;
+
+    source->input = input ;
+
+    source->position = source->end = (Pointer) 0 ;
+
+    source->segment = segment ;
+
+    return ( SetPullableSource( source, block_callback, "pullable.c blocking" ) ) ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/pullable.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,44 @@
+/*
+    pullable.h
+    ==========
+
+    pullable derived sources
+
+*/
+
+#define    SetPullableSource(    _source          , _puller, _name ) \
+	   setPullableSource( &( _source )->parent, _puller, _name )
+#define DeletePullableSource(    _source                           ) \
+	deletePullableSource( &( _source )->parent                 )
+
+/* derived Pullable sources */
+
+#define      NewSlaveSource( _master ) \
+	     newSlaveSource( _master )
+
+#define     NewStaticSource(             _pointer    ) \
+	    newStaticSource( (Pointer) ( _pointer  ) )
+
+#define  NewRetainingSource( _source,               _retained   ) \
+	 newRetainingSource( _source, (ByteCount) ( _retained ) )
+
+#define   NewDelayingSource( _source,               _delay      ) \
+	  newDelayingSource( _source, (ByteCount) ( _delay    ) )
+
+#define   NewBlockingSource( _source,               _block      ) \
+	  newBlockingSource( _source, (ByteCount) ( _block    ) )
+
+
+/* fundamental active source types */
+
+extern Source     setPullableSource() ;
+extern Pointer deletePullableSource() ;
+
+/* simple assertive derived sources */
+
+extern Source        newSlaveSource() ;
+extern Source       newStaticSource() ;
+extern Source    newRetainingSource() ;
+extern Source     newDelayingSource() ;
+extern Source     newBlockingSource() ;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/source.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,681 @@
+/*
+	source.c
+	========
+
+	New super minimal source system.
+
+	John Holdsworth, 2nd January 1989.
+
+	edited: MAA 3-8-1993
+                new options "review_aid" and "frameno_aid"
+
+*/
+
+#if 0
+
+    What is a Source?
+    =================
+
+    Sources are a suggested style for coding  computational  processes  on
+    continuous data streams.  Making the extra effort to code according to
+    this style allows such processes to be easilly  cascaded  while  still
+    able to operate on data streams of indefinite length.  This is done by
+    performing the processing of the data stream in segments  and  passing
+    intermediate  results systematically between processing stages using a
+    simple convention.
+
+    A source is like a file, in that it specifies the source of stream  of
+    data.  The  data  can  be  read in segments of user-defined size, like
+    reading from a file.  For example, the routines  sread()  and  sseek()
+    operate  on  Sources  the same way that fread() and fseek() operate on
+    file streams. (sseek() operations on sources can only move forward  in
+    a data stream).
+
+    Sources are different from files in  that  they  do  not  necessarilly
+    just read data from disk. A Source may generally be a transformation
+    of data, or some simple processing operation on data. In addition, the
+    data may originate in any way the user may specify. The data may come
+    from a previous (cascaded) "Source".
+
+    The structured type "Source" contains enough information to generate
+    a stream of data. One way of processing a stream of data is to perform
+    a simple data-processing operation on another stream of data.
+    The input stream can be specified using a source.
+    Composite  data-processing  functions  can be built up by cascading a
+    number of elementary functions.
+
+    If  data  is  processed  in  large  enough  segments,  the overhead of
+    performing the processing task in stages is not significant.
+
+
+    How to use sources
+    ==================
+
+    There are two distinct phases in working with sources, analogous to
+    opening a file (eg fopen()), and reading the file (eg fread()).
+
+    The first phase uses "setup" functions, analogous to fopen().
+    (See io.c for sources which read from disk. See model.c for sources
+    which perform specialised auditory-modelling processes).
+    Setup functions always return a Source. They may take one or more
+    sources as arguments, as a specification of the input to the process
+    the source performs. The user may define his own setup routine for
+    any new process. This routine intialises the source structure with
+    a pointer to a callback function, which performs the data processing
+    when the source is used.
+
+    The second phase uses pull/fill/roll functions, analogous to fread().
+    Unlike the fread function, Sources do not require  you  to  supply  a
+    buffer  for  the  data to be "read" into.
+    There are three types of operation that can be  performed  on  sources
+    depending on whether the users wishes to supply the data buffer.
+    (These three operations are referred to as "methods", in the style of
+    object-oriented programming. Sources are thought of as "objects").
+
+    The Pull() method returns  a  pointer  to  a  buffer which has been
+    allocated  by  the  source itself.
+    In the following example, the buffer will contain the next 100 bytes
+    of processed data.
+
+	/* declarations */
+	char     *buffer ;
+	Source    source = OpenSource( somehow ) ;
+	ByteCount bytes  = 100 ;
+
+	/* call to "pull" 100 bytes of data out of Source "source" */
+	buffer = Pull( source, bytes ) ;
+
+
+    If the user has a buffer available for data and would prefer the  data
+    be directly tranfered into it, the Fill() method can be used instead of
+    the Pull() method.  The Fill method returns the address of the  buffer
+    the user provides in case it is of use for the programmer.
+
+	/* declarations */
+	char      buffer[100] ;
+	Source    source = OpenSource( somehow ) ;
+	ByteCount bytes  = 100 ;
+
+	/* call to "fill" the user's buffer with 100 bytes of data */
+	(void) Fill( source, bytes, buffer ) ;
+
+
+    In addition there is one further method of calling data from a  source
+    that  works like Pull(), but keeps a given number of bytes from the
+    previous call in the buffer.
+    The pointer returned by roll points to the start of the new data, as
+    in pull, but the space immediately before the pointer is still valid
+    and contains a specified number of bytes of data kept from the previous
+    call.
+    Bytes at the end of the buffer can be kept for the following roll call.
+
+	/* declarations */
+	char     *buffer ;
+	Source    source = OpenSource( somehow ) ;
+	ByteCount bytes  = 100 ;
+
+	/* call to "pull" 100 bytes of data out of Source "source"    */
+	buffer = Roll( source, bytes, 50 ) ;
+
+	/* "pull" another 100 bytes out of the source.                */
+	/* The last 50 bytes of the previous call will be kept in the */
+	/* buffer, and will immediately precede the new 100 bytes.    */
+	buffer = Roll( source, &bytes, 50 ) ;
+
+
+    In order for Roll to work properly though it MUST be  the  only  call
+    made  on  a  given  source.  This  is  as  it retains more information
+    between calls than the Pull() and Fill() methods.
+
+
+    More recent versions are defined as: PullSome, FillSome, RollSome.
+    In these methods, a pointer to the number of bytes (eg. &bytes) is
+    used, so that the source can indicate that less data was available
+    than was requested.
+
+    Remember also that requesting a negative number of bytes is interpreted
+    as requesting a skip without processing of the negative of that number
+    of bytes. This works as most processing sources will simply ignore
+    a request to process a negative number of bytes but will pass on the
+    request to their input sources which may which to actually act on the
+    skip operation.
+
+    More importantly A request for zero bytes it taken to mean that the
+    source is not required anymore and should close itself and free any
+    resources it is using. If the request is passed on to any input sources
+    a close operation cascades the close request to it's' input sources. This
+    means in order to close a cascade of process only the final source need be closed.
+    N.B. The close operation is only performed if the number of bytes requested is
+    zero not if the number of bytes returned is zero.
+
+
+
+...ctd jwh
+
+    Writing new sources
+    ===================
+
+    At the lowest level a source is a pointer to a struct which contains
+    pointers to three functions or methods to deal with the three types
+    of request that can be issued to a source. Pull(), Fill(),and Roll()
+    are #defines macros that convert the not quite C language calls into
+    full C calls passing the source pointer as the first argument then
+    the arguments the user specifies.
+
+    For example:
+
+	buffer = PullSome( source, bytes ) ;
+
+    Becomes:
+
+	buffer = source->methods->pull( source, bytes ) ;
+
+    The #define macros is used simply as a convienience.
+
+    The basic Source typedefs are as follows :
+
+    typedef struct _methods {
+	Pointer (*pull)(), (*fill)(), (*roll)() ;
+      } Methods ;
+    typedef struct _source  {
+	Methods methods ; Pointer buffer ; ByteCount bsize, valid ;
+      } Source ;
+
+    All sources must point to a structure containing at least this information
+    for Pull(), Fill() and Roll() operations to work on all sources.
+
+    To create a source the user initialises a static variable of type struct _methods with
+    the three routines written to support the three basic source operations.
+    A pointer to this structure is then used to initialise the methods field of
+    the struct _source section of the source's' state. A pointer to this structure
+    becomes the new source.
+
+    The function setSource() is provided to perform this minimal setup  of
+    a  new  source  and  to  initialise  the  other  fields  in the source
+    structure. The pointer to the new Source structure is allocated outside
+    setSource and passed to it in order to alow the possibility of it containing
+    more than the basic source information.
+
+#endif
+
+#include <stdio.h>           /* added: MAA 3-8-1993*/
+#include "stitch.h"
+#include "source.h"
+#include "options.h"         /* added: MAA 3-8-1993*/
+
+#ifndef DEBUG
+#define DEBUG 0
+#endif
+
+
+/*
+    initialise new Source structure
+
+*/
+
+Source setSource( source, puller, filler, roller, name )
+struct _source *source ;
+Pointer (*puller)(), (*filler)(), (*roller)() ;
+char *name ;
+{
+    Source returned ;
+    Source (*opener)() = 0 ;
+
+    source->pull    =  puller ;
+    source->fill    =  filler ;
+    source->roll    =  roller ;
+    source->open    =  opener ;
+
+    source->type    =  "void" ;
+    source->name    =   name  ;
+
+    source->opened   =           0 ;
+    source->returned = (Pointer) 0 ;
+#if DEBUG
+    printf( "Creating %s\n", SourceName( source ) ) ;
+#endif
+    _SPTR( returned ) = source ;
+
+    return ( returned ) ;
+}
+
+Source typeSource( source, type )
+Source source ;
+char *type ;
+{
+    _SPTR( source )->type = type ;
+
+    return ( source ) ;
+}
+
+char *sourceType( source )
+Source source ;
+{
+    return ( _SPTR( source )->type ) ;
+}
+
+char *sourceName( source )
+Source source ;
+{
+    return ( _SPTR( source )->name ) ;
+}
+
+Pointer deleteSource( source )
+Source source ;
+{
+#if DEBUG
+    printf( "Deleteing %s\n", SourceName( source ) ) ;
+#endif
+    Delete( source ) ;
+
+    return ( (Pointer) 0 ) ;
+}
+
+
+#if 00
+struct _source_operators NameOfClass = {
+ setSource, deleteSource,
+ typeSource, sourceType,
+ sourceName
+ } ;
+#endif
+
+
+/* MAA: 3-8-1993 */
+    
+void sinkSource( source, framebytes, frames )   
+Source source ;
+int framebytes ;
+long frames ;
+{
+    long frame ;
+    
+
+    extern *reviewstr;
+    extern *framenumberstr;
+
+    for( frame=0 ; frame<frames ; frame++ ) {
+
+      if ( isON (framenumberstr) || isON (reviewstr) ){
+	fprintf(stderr, " %i ", frame+1);
+	fflush(stderr);}
+
+      (void) Pull( source, framebytes ) ;
+
+      if ( isON (reviewstr)) {
+	fflush(stdin);getchar();}
+      }
+    return ; 
+}
+
+
+
+void CloseSource( source )
+Source source ;
+{
+    (void) Pull( source, 0 ) ;
+
+    return ;
+}
+
+void sinkAndCloseSource( source, framebytes, frames )
+Source source ;
+int framebytes ;
+long frames ;
+{
+    SinkSource( source, framebytes, frames ) ;
+
+    CloseSource( source ) ;
+
+    return ;
+}
+
+/* tapping derived source */
+
+typedef struct {
+    struct _source parent ;
+    Pointer state ;
+    void (*callback)(), (*close)() ;
+    Source input ;
+} *TappingSource ;
+
+static Pointer tapping_callback( source, bytes, buffer, last )
+TappingSource source ;
+ByteCount *bytes ;
+Pointer buffer ;
+int last ;
+{
+    source->callback( source->state, bytes, buffer, buffer+*bytes ) ;
+
+    if( !last )
+	return ( buffer ) ;
+    else {
+	if( source->close != (void ( * )()) 0 )
+	    source->close( source->state ) ;
+
+	return ( DeleteSource( source ) ) ;
+    }
+}
+
+static Pointer tappingPuller( source, bytes )
+TappingSource source ;
+ByteCount *bytes ;
+{
+    register int last = *bytes == 0 ;
+    Pointer buffer = PullSome( source->input, bytes ) ;
+
+#if DEBUG
+    printf( "\"%s\" pull tapping %d from \"%s\"\n", SourceName( source ), *bytes, SourceName( source->input ) ) ;
+#endif
+
+    return ( tapping_callback( source, bytes, buffer, last ) ) ;
+}
+
+static Pointer tappingFiller( source, bytes, buffer )
+TappingSource source ;
+ByteCount *bytes ;
+Pointer buffer ;
+{
+    register int last = *bytes == 0 ;
+
+    FillSome( source->input, bytes, buffer ) ;
+
+#if DEBUG
+    printf( "\"%s\" fill tapping %d from \"%s\"\n", SourceName( source ), *bytes, SourceName( source->input ) ) ;
+#endif
+
+    return ( tapping_callback( source, bytes, buffer, last ) ) ;
+}
+
+static Pointer tappingRoller( source, bytes, keep )
+TappingSource source ;
+ByteCount *bytes, keep ;
+{
+    register int last = *bytes == 0 ;
+    Pointer buffer = RollSome( source->input, bytes, keep ) ;
+
+#if DEBUG
+    printf( "\"%s\" roll tapping %d from \"%s\"\n", SourceName( source ), *bytes, SourceName( source->input ) ) ;
+#endif
+
+    return ( tapping_callback( source, bytes, buffer, last ) ) ;
+}
+
+Source newTappingSource( state, callback, close, input, name )
+Pointer state ;
+void (*callback)(), (*close)() ;
+Source input ;
+char *name ;
+{
+    DeclareNew( TappingSource, source ) ;
+
+    source->state    = state    ;
+    source->callback = callback ;
+    source->close    = close    ;
+    source->input    = input    ;
+
+    return ( SetSource( source, tappingPuller, tappingFiller, tappingRoller, name ) ) ;
+}
+
+/* rollable derived source */
+
+typedef struct {
+    struct _source parent ;
+    Pointer buffer ;
+    ByteCount bsize, valid ;
+    Source input ;
+} *RollableSource ;
+
+Pointer DeleteRollableSource( source )
+RollableSource source ;
+{
+    if( source->bsize != 0 )
+	Delete( source->buffer ) ;
+
+    return ( DeleteSource( source ) ) ;
+}
+
+static Pointer rollablePuller( source, bytes )
+RollableSource source ;
+ByteCount *bytes ;
+{
+#if DEBUG
+    printf( "rollable \"%s\" pulling %d from \"%s\"\n", SourceName( source ), *bytes, SourceName( source->input ) ) ;
+#endif
+
+    return ( RollSome( source->input, bytes, 0 ) ) ;
+}
+
+static Pointer rollableFiller( source, bytes, buffer )
+RollableSource source ;
+ByteCount *bytes ;
+Pointer buffer ;
+{
+    register int last = *bytes == 0 ;
+
+    FillSome( source->input, bytes, buffer ) ;
+
+    source->valid = *bytes ;
+
+#if DEBUG
+    printf( "rollable \"%s\" filling %d from \"%s\"\n", SourceName( source ), *bytes, SourceName( source->input ) ) ;
+#endif
+
+    if( !last )
+	return ( buffer ) ;
+    else
+	return ( DeleteRollableSource( source ) ) ;
+}
+
+static Pointer rollableRoller( source, bytes, keep )
+RollableSource source ;
+ByteCount *bytes, keep ;
+{
+    register int last = *bytes == 0 ;
+    Pointer oldBuffer = source->buffer ;
+    ByteCount toStore = *bytes + keep ;
+
+    if( source->bsize < toStore ) {
+
+	source->buffer = Allocate( toStore, "source.c for retaining buffer" ) ;
+
+	source->bsize = toStore ;
+    }
+
+    if( oldBuffer == (Pointer) 0 )
+	ZeroArray( (char *) source->buffer, keep ) ;
+    else {
+	CopyArray( (char *) oldBuffer+source->valid-keep, (char *) source->buffer, keep ) ;
+
+	if( oldBuffer != source->buffer )
+	    Delete( oldBuffer ) ;
+    }
+
+    FillSome( source->input, bytes, source->buffer + keep ) ;
+
+    source->valid = keep + *bytes ;
+
+    if( !last )
+	return ( source->buffer + keep ) ;
+    else
+	return ( DeleteRollableSource( source ) ) ;
+}
+
+Source newRollableSource( input )
+Source input ;
+{
+    DeclareNew( RollableSource, source ) ;
+
+    source->buffer = (Pointer) 0 ;
+
+    source->bsize =   0   ;
+    source->valid =   0   ;
+
+    source->input = input ;
+
+    return ( SetSource( source, rollablePuller, rollableFiller, rollableRoller, "rollable" ) ) ;
+}
+
+/* all other sources don't support rolling */
+
+Pointer nonRoller( source, bytes, keep )
+Source source ;
+ByteCount *bytes, keep ;
+{
+    stitch_error( "Sorry rolling not availiable on source \"%s\"\n", SourceName( source ) ) ;
+
+    return ( Pull( source, bytes ) ) ;
+}
+
+
+
+/* for compatability */
+
+typedef struct _auto_source {
+    struct _fillable_source parent ; Pointer state ; void (*callback)() ;
+  } *AutoSource ;
+
+static Pointer autoFiller( source, bytes, buffer )
+AutoSource source ;
+ByteCount *bytes ;
+Pointer buffer ;
+{
+    register int last = *bytes == 0 ;
+
+    source->callback( source->state, *bytes, buffer ) ;
+
+    if( !last )
+	return ( buffer ) ;
+    else
+	return ( DeleteFillableSource( source ) ) ;
+}
+
+Source stdAutoSource( state, callback )
+Pointer state ;
+void (*callback)() ;
+{
+    DeclareNew( AutoSource, source ) ;
+
+    source->state    = state    ;
+    source->callback = callback ;
+
+    return ( SetFillableSource( source, autoFiller, "stdAuto" ) ) ;
+}
+
+typedef struct _self_source {
+ struct _pullable_source parent ; Pointer state, (*callback)() ;
+ } *SelfSource ;
+
+static Pointer selfGenerator( source, bytes )
+SelfSource source ;
+ByteCount *bytes ;
+{
+    register int last = *bytes == 0 ;
+    Pointer ptr = source->callback( source->state, *bytes ) ;
+
+    if( !last )
+	return ( ptr ) ;
+    else
+	return ( DeleteSource( source ) ) ;
+}
+
+Source stdSelfSource( state, callback )
+Pointer state ;
+Pointer (*callback)() ;
+{
+    DeclareNew( SelfSource, source ) ;
+
+    source->state    = state    ;
+    source->callback = callback ;
+
+    return ( SetPullableSource( source, selfGenerator, "stdSelf" ) ) ;
+}
+
+Source stdStaticSource( ptr )
+Pointer ptr ;
+{
+    return ( NewStaticSource( ptr ) ) ;
+}
+
+Source stdSlaveSource( source )
+Source source ;
+{
+    return ( NewSlaveSource( source ) ) ;
+}
+
+Pointer oldPull( source, bytes )
+struct _source *source ;
+ByteCount bytes ;
+{
+    ByteCount tmp = bytes ;
+
+    return ( source->pull( source, &tmp ) ) ;
+}
+
+Pointer oldFill( source, bytes, buffer )
+struct _source *source ;
+ByteCount bytes ;
+Pointer buffer ;
+{
+    ByteCount tmp = bytes ;
+    Pointer bptr = buffer ;
+
+    do {
+	tmp = buffer + bytes - bptr ;
+
+	source->fill( source, &tmp, bptr ) ;
+	bptr += tmp ;
+
+    } while( bptr < buffer + bytes && tmp != 0 ) ;
+
+    return ( buffer ) ;
+}
+
+Pointer oldRoll( source, bytes, keep )
+struct _source *source ;
+ByteCount bytes, keep ;
+{
+    ByteCount tmp = bytes ;
+
+    return ( source->roll( source, &tmp, keep ) ) ;
+}
+
+#if 00
+static struct _source convertors = { oldPull, oldFill, oldRoll } ;
+struct _source *call_conversions = &convertors ;
+#endif
+
+/* for binding multiple sources */
+
+#if !defined(PC) && !defined(DSP32)
+#include <varargs.h>
+
+Source *BindSources( va_alist )
+va_dcl
+{
+    Source *inputs ;
+    va_list argp ;
+    int count, c ;
+
+    va_start( argp ) ;
+
+    for( count=0 ; _SPTR( va_arg( argp, Source ) ) != (struct _source *) 0 ; count++ )
+	;
+
+    inputs = NewArray( Source, count+1, "for binding inputs in source.c" ) ;
+
+    va_end(   argp ) ;
+    va_start( argp ) ;
+
+    for( c=0 ; c<=count ; c++ )
+	inputs[c] = va_arg( argp, Source ) ;
+
+    va_end(   argp ) ;
+
+    return ( inputs ) ;
+}
+#endif
+
+struct _source notRealySource ;
+
+Source EmptySource ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/source.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,191 @@
+/*
+	source.h
+	========
+
+
+
+*/
+
+#ifndef _SOURCE_H_
+#define _SOURCE_H_
+
+#include "buffer.h"
+
+/* standard entry points */
+
+#define PullSome( _source, _bytes          ) ( _SPTR( _source )->returned = _SPTR( _source )->pull( _SPTR( _source ), (ByteCount *) ( _bytes )                          ) )
+#define FillSome( _source, _bytes, _buffer ) ( _SPTR( _source )->returned = _SPTR( _source )->fill( _SPTR( _source ), (ByteCount *) ( _bytes ), (Pointer  ) ( _buffer ) ) )
+#define RollSome( _source, _bytes, _kept   ) ( _SPTR( _source )->returned = _SPTR( _source )->roll( _SPTR( _source ), (ByteCount *) ( _bytes ), (ByteCount) ( _kept   ) ) )
+
+/* for compatability */
+
+#define Pull( _source, _bytes              ) ( _SPTR( _source )->returned =                oldPull( _SPTR( _source ), (ByteCount  ) ( _bytes )                          ) )
+#define Fill( _source, _bytes, _buffer     ) ( _SPTR( _source )->returned =                oldFill( _SPTR( _source ), (ByteCount  ) ( _bytes ), (Pointer  ) ( _buffer ) ) )
+#define Roll( _source, _bytes, _kept       ) ( _SPTR( _source )->returned =                oldRoll( _SPTR( _source ), (ByteCount  ) ( _bytes ), (ByteCount) ( _kept   ) ) )
+
+/* for more compatability */
+
+#define Shift( _source, _bytes, _kept      ) Roll( _source, _bytes, _kept )
+
+/* count conversions */
+
+#define ToPoints( _type, _bytes )  ( ( _bytes ) >> ( sizeof(_type) >> 1 ) )
+#define ToBytes(  _type, _points ) ( ( char *) ( (_type *) 0l + ( _points ) ) - ( char *) 0l )
+
+/* for convenience */
+
+#define PullItems(   _source, _number,          _type ) ( (_type *) Pull( _source, ToBytes( _type, _number ) ) )
+
+#define PullChars(   _source, _number                 ) PullItems( _source, _number, char   )
+#define PullShorts(  _source, _number                 ) PullItems( _source, _number, short  )
+#define PullInts(    _source, _number                 ) PullItems( _source, _number, int    )
+#define PullDoubles( _source, _number                 ) PullItems( _source, _number, double )
+
+
+#define FillItems(   _source, _number, _buffer, _type ) ( (_type *) Fill( _source, ToBytes( _type, _number ), (Pointer) ( _buffer ) ) )
+
+#define FillChars(   _source, _number, _buffer        ) FillItems( _source, _number, _buffer, char   )
+#define FillShorts(  _source, _number, _buffer        ) FillItems( _source, _number, _buffer, short  )
+#define FillInts(    _source, _number, _buffer        ) FillItems( _source, _number, _buffer, int    )
+#define FillDoubles( _source, _number, _buffer        ) FillItems( _source, _number, _buffer, double )
+
+
+#define RollItems(   _source, _number, _keep,   _type ) ( (_type *) Roll( _source, ToBytes( _type, _number ), ( _keep ) * sizeof ( _type ) ) )
+
+#define RollChars(   _source, _number, _keep          ) RollItems( _source, _number, _keep, char   )
+#define RollShorts(  _source, _number, _keep          ) RollItems( _source, _number, _keep, short  )
+#define RollInts(    _source, _number, _keep          ) RollItems( _source, _number, _keep, int    )
+#define RollDoubles( _source, _number, _keep          ) RollItems( _source, _number, _keep, double )
+
+/* operators on sources */
+
+#define    SetSource( _src, _puller, _filler, _roller, _name )    setSource( (struct _source *) _src, _puller, _filler, _roller, _name )
+#define   TypeSource( _src, _type                            )   typeSource( (struct _source *) _src, _type                            )
+#define   SourceType( _src                                   )   sourceType( (struct _source *) _src                                   )
+#define   SourceName( _src                                   )   sourceName( (struct _source *) _src                                   )
+#define DeleteSource( _src                                   ) deleteSource( (struct _source *) _src                                   )
+
+#if 00
+#define NameOfClass BasicSourceClass
+
+#define    SetSource( _source, _puller, _filler, _roller, _name ) NameOfClass.set(     (struct _source *) _source, _puller, _filler, _roller, _name )
+#define   TypeSource( _source, _type                            ) NameOfClass.setType( (struct _source *) _source, _type                            )
+#define   SourceType( _source                                   ) NameOfClass.getType( (struct _source *) _source                                   )
+#define   SourceName( _source                                   ) NameOfClass.getName( (struct _source *) _source                                   )
+#define DeleteSource( _source                                   ) NameOfClass.delete(  (struct _source *) _source                                   )
+#endif
+
+
+
+#define SinkSource( _source,               _framebytes  ,        _frames ) \
+	sinkSource( _source, (ByteCount) ( _framebytes ), (long) _frames )
+
+#define SinkAndCloseSource( _source,               _framebytes  ,        _frames ) \
+	sinkAndCloseSource( _source, (ByteCount) ( _framebytes ), (long) _frames )
+
+/* moving towards buffer abstraction, slowly */
+
+#define    SourceBuffer( _source          ) ( ( _source )->buffer           )
+#define SetSourceBuffer( _source, _buffer ) ( ( _source )->buffer = _buffer )
+
+/* only pure source */
+
+#define NewTappingSource(             _source  , _state, _callback, _close, _name ) \
+	newTappingSource( (Pointer) ( _source ), _state, _callback, _close, _name )
+
+#define NewRollableSource( _source ) \
+	newRollableSource( _source )
+
+#if 0
+/* for compatability */
+
+#define NewShiftableSource( _source ) \
+	NewRollableSource(  _source )
+#endif
+
+/* for binding with C++ perhaps someday */
+
+#if defined(__cplusplus) || defined(c_plusplus)
+#define CPLPL 1
+#else
+#define CPLPL 0
+#endif
+
+#if     CPLPL
+
+#define _SPTR( _s ) ((_s).ptr)
+#define _MANY_ARGS        ...
+#define _ONE_SOURCE       Source source
+#define _TWO_SOURCES      Source source1, Source source2
+#define _ONE_SOURCE_PLUS  Source source...
+
+typedef class _source &Source ; /* ?? or something */
+
+#else
+
+#define _SPTR( _s ) _s
+#define _MANY_ARGS        /* ...                            */
+#define _ONE_SOURCE       /* Source source                  */
+#define _TWO_SOURCES      /* Source source1, Source source2 */
+#define _ONE_SOURCE_PLUS  /* Source source...               */
+
+/* basic types */
+
+typedef struct _source *Source, *SourceArray[1] ;
+
+#endif
+
+typedef Source      CharSource,      ShortSource,      IntSource,      FloatSource,      DoubleSource,      ComplexSource      ;
+typedef SourceArray CharSourceArray, ShortSourceArray, IntSourceArray, FloatSourceArray, DoubleSourceArray, ComplexSourceArray ;
+
+typedef int ByteCount ;
+
+/* dependant on type of source */
+
+struct           _source { Pointer (*pull)(), (*fill)(), (*roll)(), returned ; char *name, *type ; int opened ; Source (*open)() ; } ;
+struct _source_operators { Source (*set)() ; Pointer (*delete)() ; Source (*setType)() ; char *(*getType)() ; char *(*getName)() ; } ;
+
+struct _pullable_source { struct _source parent ; } ;
+struct _fillable_source { struct _source parent ; Buffer buffer ; } ;
+
+#if 00
+extern struct _source_operators NameOfClass ;
+extern struct _source *call_conversions ;
+#endif
+
+extern Source     setSource() ;
+extern Source    typeSource() ;
+extern char     *sourceType() ;
+extern char     *sourceName() ;
+extern Pointer deleteSource() ;
+
+extern Pointer oldPull(), oldFill(), oldRoll() ;
+
+
+extern void   sinkSource() ;
+extern void   CloseSource() ;
+extern void   sinkAndCloseSource() ;
+
+/* derived source types for different purposes */
+
+extern Source  newTappingSource() ;
+extern Source newRollableSource() ;
+
+extern Pointer nonRoller() ;
+
+#include "pullable.h"
+
+#include "fillable.h"
+
+extern Source *BindSources() ;
+
+/* for compatability... for now */
+
+extern Source stdStaticSource() ;
+extern Source stdSlaveSource() ;
+extern Source stdAutoSource() ;
+extern Source stdSelfSource() ;
+
+#endif
+
+extern Source EmptySource ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/srcio.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,52 @@
+/*
+    srcio.c
+    =======
+
+    stdio compatability routines for sources
+
+*/
+
+#include "stitch.h"
+#include "source.h"
+#include "srcio.h"
+
+
+
+/* Can be used for compatability with stdio FILE operations */
+
+int sread( pointer, size, number, source )
+char *pointer ;
+unsigned size, number ;
+Source source ;
+{
+    ByteCount bytes = size * number ;
+
+    (void) FillSome( source, &bytes, pointer ) ;
+
+    return ( bytes / size ) ;
+}
+
+/* sseek() only works for positive, relative seeks i.e. data skiping seeks */
+
+int sseek( source, offset, pointername )
+Source source ;
+long offset ;
+int pointername ;
+{
+    ByteCount bytes = -offset ;
+
+    if( offset > 0 && pointername == 1 )
+	(void) PullSome( source, &bytes ) ;
+
+    return ( 0 ) ;
+}
+
+int sclose( source )
+Source source ;
+{
+    ByteCount bytes = 0 ;
+
+    (void) PullSome( source, &bytes ) ;
+
+    return ( 0 ) ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/srcio.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,11 @@
+/*
+    srcio.h
+    =======
+
+    stdio-like inteface to sources
+
+*/
+
+int sread(  /* char *pointer, int size, int number, Source source */ ) ;
+int sseek(  /* Source source, int offset, int from                */ ) ;
+int sclose( /* Source source                                      */ ) ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/stitch.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,419 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+				==========
+				 stitch.c
+				==========
+
+
+    Copyright (c), 1989  John Holdsworth, Medical Research Council, Applied Psychology Unit.
+
+
+    Author  : John Holdsworth
+    Written : 22th March, 1989.
+
+    Edited  :
+
+
+    provides an unvarying interface for allocation and copying operations.
+
+*/
+
+#include <stdio.h>
+
+#include <string.h>
+#if defined( NeXT )
+#include <stdlib.h>
+#else
+#include <malloc.h>
+#endif
+
+#ifndef  _STITCH_H_
+#include "stitch.h"
+#endif
+
+#if defined( sun )
+extern bcopy(), bzero(), exit() ;
+#else
+#ifndef NeXT
+extern void bcopy(), bzero(), free(), exit() ;
+#endif
+#endif
+
+#ifndef  lint
+static char *stitch_sccs_id = "@(#)stitch.c	1.19   J. Holdsworth (MRC-APU)  6/6/91" ;
+#endif
+
+#ifndef WRAPPING
+#define WRAPPING 0
+#endif
+
+#if     WRAPPING
+
+#include "wrap.h"
+
+Pointer wrap_malloc( size, where )
+unsigned size ;
+char where[] ;
+{
+    return ( wrap( malloc( WRAPPED_SIZE( size ) ), size, where ) ) ;
+}
+
+Pointer wrap_realloc( old, size, where )
+char *old ;
+unsigned size ;
+char where[] ;
+{
+    return ( wrap( realloc( unwrap( old ), WRAPPED_SIZE( size ) ), where ) ) ;
+}
+
+void wrap_free( ptr )
+Pointer ptr ;
+{
+    free( (char *) unwrap( ptr ) ) ;
+
+    return ;
+}
+#else
+Pointer wrap_malloc( size, where )
+unsigned size ;
+char where[] ;
+{
+#ifdef lint
+    where ;
+#endif
+    return ( malloc( size ) ) ;
+}
+
+Pointer wrap_realloc( old, size, where )
+char *old ;
+unsigned size ;
+char where[] ;
+{
+#ifdef lint
+    where ;
+#endif
+#ifdef DSP32
+    stitch_error( "realloc called" ) ;
+#else
+    return ( realloc( old, size ) ) ;
+#endif
+}
+
+void wrap_free( ptr )
+Pointer ptr ;
+{
+    free( ptr ) ;
+
+    return ;
+}
+#endif
+
+#ifdef DSP32
+extern char _EAdata[], _EUdata[] ;
+char *freemem = _EUdata ;
+char errstr[200] ;
+
+int abs( n )
+int n ;
+{
+    if( n >= 0 )
+	return  n ;
+    else
+	return -n ;
+}
+
+#endif
+
+void stitch_error( string, thing )
+char *string ;
+char *thing ;
+{
+    int i ;
+#ifdef DSP32
+    extern int errno ;
+
+    (void) strcpy( errstr, string ) ;
+    errno = thing - (char *) 0 ;
+#else
+    (void) fprintf( stderr, string, thing ) ;
+#endif
+
+#ifdef PC
+    /* put in delay to be able to read message if any */
+
+    for(i=0 ; i<3000 ; i++ )
+	(void) sqrt( 2. ) ;
+#endif
+
+    stitch_exit( 1 ) ;
+}
+
+static void failed( bytes, where )
+unsigned bytes ;
+char *where ;
+{
+    static char msg[200] = "Memory allocation error, allocating %u bytes in " ;
+
+    stitch_error( strcat( msg, where ), ( Pointer ) 0 + bytes ) ;
+}
+
+char stitchStructStr[] = "allocating a structure somewhere" ;
+
+/* memory usage indicators */
+
+static long sused ;
+static long bused ;
+
+Pointer stitch_malloc( bytes, where )
+unsigned bytes ;
+char *where ;
+{
+    Pointer ptr ;
+
+    if( where == stitchStructStr )
+	sused += bytes ;
+    else
+	bused += bytes ;
+
+#ifdef NOT_DSP32_ANYMORE
+    int size = bytes + 3 >> 2 << 2 ;
+
+    ptr = freemem ;
+
+    if( ( freemem += size ) > _EAdata )
+#else
+    if( ( ptr = wrap_malloc( bytes, where ) ) == ( Pointer ) 0 )
+#endif
+	failed( bytes, where ) ;
+
+    return ( ptr ) ;
+}
+
+Pointer stitch_ralloc( bytes, where )
+unsigned bytes ;
+char *where ;
+{
+#ifdef DSP32
+    extern char _EAram2[], _EUram2[] ;
+    static char *mempt   = _EUram2 ;
+    int size ;
+
+    size = bytes + 3 >> 2 << 2 ;
+
+    if( mempt + size <= _EAram2 )
+	return ( ( mempt += size ) - size ) ;
+#endif
+#ifdef NICHE
+
+#ifdef NICHEE
+#include <trillium/ram.h>
+#else
+#define ONCHIP 2
+#endif
+
+    Pointer ptr ;
+
+    if( ( ptr =  valloc( items * size, ONCHIP, size ) ) == ( char * ) 0 )
+	return ( ptr ) ;
+#endif
+
+    return ( stitch_malloc( bytes, where ) ) ;
+}
+
+Pointer stitch_calloc( number, size, where )
+unsigned number, size ;
+char *where ;
+{
+    Pointer ptr ;
+#if defined( NICHE ) || defined( DSP32 )
+    if( ( ptr = stitch_malloc( number * size ) ) == ( char * ) 0 )
+	failed( number * size, where ) ;
+
+    stitch_bzero( ptr, ( int ) number * size ) ;
+
+#else
+    if( ( ptr = ( char * ) calloc( number, size ) ) == ( char * ) 0 )
+	failed( number * size, where ) ;
+#endif
+    return ( ptr ) ;
+}
+
+Pointer stitch_zeroed_malloc( size, where )
+unsigned size ;
+char *where ;
+{
+    Pointer ptr = stitch_malloc( size, where ) ;
+
+    stitch_bzero( ptr, size ) ;
+
+    return ( ptr ) ;
+}
+
+Pointer stitch_copied_malloc( size, model, where )
+unsigned size ;
+Pointer model ;
+char *where ;
+{
+    Pointer ptr = stitch_malloc( size, where ) ;
+
+    stitch_bcopy( model, ptr, size ) ;
+
+    return ( ptr ) ;
+}
+
+void stitch_free( pointer )
+Pointer pointer ;
+{
+    if( pointer == (Pointer) 0 )
+	stitch_error( "attempt to free null pointer" ) ;
+
+#ifndef DSP32
+    wrap_free( pointer ) ;
+#endif
+    return ;
+}
+
+void stitch_exit( status )
+int status ;
+{
+#if 00
+    (void) fprintf( stderr, "memory usage: %d for structures, %d for buffers\n", sused, bused ) ;
+#endif
+
+#ifdef NICHE
+    kexit( status ) ;
+#else
+    exit( status ) ;
+#endif
+}
+
+/* beware these defintions - they make stitch.h mandatory */
+
+#if defined( vax ) || defined( mips ) || defined( sun )
+
+void (*stitch_bcopy)() = ( void ( * ) () ) bcopy ;
+
+#else
+
+#ifdef PC
+
+/* memmove must be able to cope with overlapping buffers */
+
+static void call_memmove( from, to, bytes )
+char *from, *to ;
+unsigned bytes ;
+{
+    ( void ) memmove( to, from, bytes ) ;
+    return ;
+}
+
+void (*stitch_bcopy)() = call_memmove ;
+
+#else
+
+static void reserve_bcopy( from, to, number )
+Pointer from, to ;
+int number ;
+{
+    register char *i, *j, *end ;
+
+    if( from > to ) {
+	for( i = from, j = to, end = from + number ; ( end - i ) % 4 > 0 ; )
+	    *j++ = *i++ ;
+
+	if( i < end )
+	    do
+	    {
+		*j++ = *i++ ;
+		*j++ = *i++ ;
+		*j++ = *i++ ;
+		*j++ = *i++ ;
+	    }
+	    while( i < end ) ;
+    }
+    else if( from < to ) {
+	for( i = from + number, j = to + number, end = from ; ( i - end ) % 4 > 0 ; )
+	    *--j = *--i ;
+
+	if( i > end )
+	    do
+	    {
+		*--j = *--i ;
+		*--j = *--i ;
+		*--j = *--i ;
+		*--j = *--i ;
+	    }
+	    while( i > end ) ;
+    }
+
+    return ;
+}
+
+void (*stitch_bcopy)() = reserve_bcopy ;
+
+#endif
+
+#endif
+
+
+
+#if defined( vax ) || defined( mips ) || defined( sun )
+
+void (*stitch_bzero)() = ( void ( * ) () ) bzero ;
+
+#else
+
+#if defined( PC ) || defined( DSP32 )
+
+static void call_memset( to, bytes )
+char *to ;
+int bytes ;
+{
+    (void) memset( to, '\000', bytes ) ;
+}
+
+void (*stitch_bzero)() = call_memset ;
+
+#else
+
+static void reserve_bzero( to, bytes )
+char *to ;
+int bytes ;
+{
+    register char *ptr = to ;
+    register char *end = to + bytes ;
+
+    while( ptr < end )
+	*ptr++ = 0 ;
+
+    return ;
+}
+
+void (*stitch_bzero)() = reserve_bzero ;
+
+#endif
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/stitch.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,149 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+    stitch.h
+    ========
+
+    interface for stitch system.
+
+    This contains many regrettable #defines which are the act of a parnoid
+    bad typist who wishes to lerave nothing to chance. They are not as hostile
+    as they might first seem being mostly to do with methodical means of
+    allocation making more use of typeing to avoid any chance of a badly
+    allocated data buffer. This file is supported by two other abstractions:
+    buffer.[ch] which ensures a buffer is the size required without realoocation.
+    wrap.[ch] which encapsulates allocations to detect buffer overflows.
+
+    In general there are two levels of indirection between the macros defined
+    below and the final calls for memory allocation from the C library function.
+    The first level is a C pre-processor macro to get all the catsings right
+    for lint and do things with types that procedures just can't do.
+    The second level is just passes the allocation call on so it can
+    be intercepted as an aid to portability.
+
+*/
+
+
+#ifndef _STITCH_H_
+#define _STITCH_H_
+
+/* redefinitions of general memory allocation to check number and cast argumnets */
+
+#define Malloc(         _size,         _where )  stitch_malloc( (unsigned) ( _size ),                        _where )
+#define Ralloc(         _size,         _where )  stitch_ralloc( (unsigned) ( _size ),                        _where )
+#define Calloc(         _size, _items, _where )  stitch_malloc( (unsigned) ( _size ), (unsigned) ( _items ), _where )
+#define Realloc( _old,  _size        , _where )  stitch_realloc( (Pointer) ( _old  ), (unsigned) ( _size  )         )
+
+/* deallocation - delete destroys pointer to keep it out of trouble */
+
+#define Free(        _old ) stitch_free( (Pointer) ( _old ) )
+#define Delete( _variable ) ( Free( _variable ), _variable = 0 )
+
+/* more names for the allocation */
+
+#define Allocate(       _size,         _where )        stitch_malloc( (unsigned) ( _size ),                   _where )
+#define AllocateZeroed( _size,         _where ) stitch_zeroed_malloc( (unsigned) ( _size ),                   _where )
+#define AllocateCopied( _size, _model, _where ) stitch_copied_malloc( (unsigned) ( _size ), (Pointer) _model, _where )
+
+#define Reallocate( _old, _size ) stitchRealloc( (Pointer) ( _old ), (unsigned) ( _size ) )
+
+/* macros for allocation making more use of type of variable receiving pointer */
+
+#define TypeSize( _pointer ) ( sizeof * (_pointer) 0 )
+
+/* return pointer to New structure, random, zeroed or copied */
+
+#define New(                   _type                            ) (_type  ) Allocate(       TypeSize( _type ),         stitchStructStr )
+#define NewZeroed(             _type                            ) (_type  ) AllocateZeroed( TypeSize( _type ),         stitchStructStr )
+#define NewCopied(             _type,            _model         ) (_type  ) AllocateCopied( TypeSize( _type ), _model, stitchStructStr )
+
+/* return pointer to array of structures */
+
+#define NewArray(              _type,        _n,         _where ) (_type *) Allocate(       sizeof (_type) * (unsigned) ( _n ),         _where )
+#define NewZeroedArray(        _type,        _n,         _where ) (_type *) AllocateZeroed( sizeof (_type) * (unsigned) ( _n ),         _where )
+#define NewCopiedArray(        _type,        _n, _model, _where ) (_type *) AllocateCopied( sizeof (_type) * (unsigned) ( _n ), _model, _where )
+
+/* as above but declare variable to receive pointer as well like new in C++ */
+
+#define DeclareNew(            _type, _name                     )  _type  _name = New(            _type                     )
+#define DeclareNewZeroed(      _type, _name                     )  _type  _name = NewZeroed(      _type                     )
+#define DeclareNewCopied(      _type, _name,     _model         )  _type  _name = NewCopied(      _type,     _model         )
+
+#define DeclareNewArray(       _type, _name, _n,         _where )  _type *_name = NewArray(       _type, _n,         _where )
+#define DeclareNewZeroedArray( _type, _name, _n,         _where )  _type *_name = NewZeroedArray( _type, _n,         _where )
+#define DeclareNewCopiedArray( _type, _name, _n, _model, _where )  _type *_name = NewCopiedArray( _type, _n, _model, _where )
+
+/* structure utilities */
+
+#define CopyArray( _from, _to, _number ) ( stitch_bcopy( _from, _to, sizeof ( * ( _to ) ) * ( _number ) ), _to )
+#define ZeroArray(        _to, _number ) ( stitch_bzero(        _to, sizeof ( * ( _to ) ) * ( _number ) ), _to )
+
+#define Copy(      _from, _to          ) ( stitch_bcopy( _from, _to, sizeof ( * ( _to ) )               ), _to )
+#define Zero(             _to          ) ( stitch_bzero(        _to, sizeof ( * ( _to ) )               ), _to )
+
+#if 0
+
+/* defines for new names for now ( removed for clarity ) */
+
+#define       stitchMalloc( _size,         _where )        stitch_malloc( (unsigned) _size,         _where )
+#define stitchZeroedMalloc( _size,         _where ) stitch_zeroed_malloc( (unsigned) _size,         _where )
+#define stitchCopiedMalloc( _size, _model, _where ) stitch_copied_malloc( (unsigned) _size, _model, _where )
+
+#define stitchRealloc( _pt, _size,         _where ) stitch_ralloc( (Pointer) _pt, (unsigned) _size, _where )
+
+#define stitchFree( _old ) stitch_free( _old )
+#endif
+
+
+/* realy important typedefs.... */
+
+#if PEDANTIC
+typedef struct _void *Pointer ; /* pointer to object of unknown size effectively void * */
+#else
+typedef char    *Pointer ;
+#endif
+typedef char    *Address ;
+
+
+/* a portable inteface to the system */
+
+extern void           stitch_error()  ;
+
+extern Pointer        stitch_malloc() ;
+extern Pointer stitch_copied_malloc() ;
+extern Pointer stitch_zeroed_malloc() ;
+extern Pointer        stitch_ralloc() ;
+extern Pointer        stitch_calloc() ;
+
+extern void           stitch_free()   ;
+extern void           stitch_exit()   ;
+
+/* beware these definitions, they are for speed and fail if stitch.h not included */
+
+extern void  (*stitch_bcopy)() ;
+extern void  (*stitch_bzero)() ;
+
+extern char stitchStructStr[] ;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/stypes.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,63 @@
+/*
+    stypes.c
+    ======
+
+    defines types for sources operations
+
+
+*/
+
+#include <string.h>
+
+#include "stitch.h"
+#include "source.h"
+#include "stypes.h"
+#include "ops.h"
+
+char   VoidIdent[] =   "void" ;
+char   CharIdent[] =   "char" ;
+char  ShortIdent[] =  "short" ;
+char    IntIdent[] =    "int" ;
+char  FloatIdent[] =  "float" ;
+char DoubleIdent[] = "double" ;
+
+Source SourceSource( source )
+Source source ;
+{
+    return ( source ) ;
+}
+
+static TypeInfo typeTable[] = {
+      VoidIdent,                 0, SourceSource,
+      CharIdent, sizeof (   char ), SourceCharSource,
+     ShortIdent, sizeof (  short ), SourceShortSource,
+       IntIdent, sizeof (    int ), SourceIntSource,
+     FloatIdent, sizeof (  float ), SourceFloatSource,
+    DoubleIdent, sizeof ( double ), SourceDoubleSource,
+    (char *) 0 } ;
+
+int typeEntryNumber( type )
+char *type ;
+{
+    register int n ;
+
+    for( n=0 ; typeTable[n].ident != (char *) 0 ; n )
+	if( type == typeTable[n].ident )
+	    return ( n ) ;
+
+    for( n=0 ; typeTable[n].ident != (char *) 0 ; n )
+	if( strcmp( type, typeTable[n].ident ) )
+	    return ( n ) ;
+
+    return ( n ) ;
+}
+
+Source TypeConvertSource( source, type )
+Source source ;
+char *type ;
+{
+    if( strcmp( SourceType( source ), type ) != 0 )
+	return ( typeTable[ typeEntryNumber( type ) ].maker( source ) ) ;
+    else
+	return ( source ) ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/stypes.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,22 @@
+/*
+    stypes.h
+    ======
+
+    defines types for sources operations
+
+
+*/
+
+typedef struct { char *ident ; int size ; Source (*maker)() ; } TypeInfo ;
+
+extern int typeEntryNumber() ;
+extern Source TypeConvertSource() ;
+extern Source SourceSource() ;
+
+extern char   CharIdent[] ;
+extern char  ShortIdent[] ;
+extern char    IntIdent[] ;
+extern char   LongIdent[] ;
+extern char  FloatIdent[] ;
+extern char DoubleIdent[] ;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/wrap.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,122 @@
+/*
+    wrap.c
+    ======
+
+    encapsulate memory allocation for debugging en masse.
+
+*/
+
+#include "stitch.h"
+#include "wrap.h"
+
+#define LOGGING
+
+/* linked list of framed allocations */
+
+static struct _head *lastAllocated = (struct _head *) 0 ;
+
+
+static void wraperr( id, hsz, tsz )
+char *id ;
+unsigned hsz, tsz ;
+{
+    printf( "memerr %s %d %d\n", id, hsz, tsz ) ;
+}
+
+
+Pointer wrap( mem, size, where )
+char *mem ;
+unsigned size ;
+char where[] ;
+{
+    register struct _head *head = (struct _head *) mem ;
+    register Pointer wrapped    = (Address) head + ROUNDUP( sizeof ( *head ) ) ;
+    register struct _tail *tail = (struct _tail *) ( (Address) wrapped + ROUNDUP( size ) ) ;
+
+#ifdef LOGGING
+    (void) printf( "wrapping %x, %d bytes in %s\n", mem, size, where ) ;
+#endif
+
+    head->where = where ;
+    head->size  = size  ;
+
+    tail->size  = size  ;
+
+    head->previous =  lastAllocated ;
+
+    if( lastAllocated != 0 )
+	lastAllocated->pointing = &head->previous ;
+
+    lastAllocated = head ;
+    lastAllocated->pointing = &lastAllocated ;
+
+    return ( wrapped ) ;
+}
+
+
+Pointer unwrap( wrapped )
+Pointer wrapped ;
+{
+    register struct _head *head = (struct _head *) ( (Address) wrapped - ROUNDUP( sizeof ( *head ) ) ) ;
+    register struct _tail *tail = (struct _tail *) ( (Address) wrapped + ROUNDUP( head->size ) ) ;
+
+#ifdef LOGGING
+    (void) printf( "unwrapping %x, %d bytes in %s\n", head, head->size, head->where ) ;
+#endif
+
+    if( head->size != tail->size )
+	wraperr( head->where, head->size, tail->size ) ;
+
+    *head->pointing = head->previous ;
+
+    if( head->previous != (struct _head *) 0 )
+	head->previous->pointing = head->pointing ;
+
+    return ( (char *) head ) ;
+}
+
+check_wrapping( printer )
+{
+    register struct _head *head = lastAllocated ;
+    register Pointer wrapped ;
+    register struct _tail *tail ;
+
+    while( head != (struct _head *) 0 ) {
+
+	wrapped = (Pointer) ( head + 1 ) ;
+
+	tail = ( struct _tail * ) ( (Address) wrapped + ROUNDUP( head->size ) ) ;
+
+	if( tail->size != head->size )
+	    wraperr( head->where, head->size, tail->size ) ;
+
+	head = head->previous ;
+    }
+
+    return ;
+}
+
+print_wrapping()
+{
+    register struct _head *head = lastAllocated ;
+    register Pointer wrapped ;
+    register struct _tail *tail ;
+
+    while( head != (struct _head *) 0 ) {
+
+	wrapped = (Pointer) ( head + 1 ) ;
+
+	tail = (struct _tail *) ( (Address) wrapped + ROUNDUP( head->size ) ) ;
+
+printf( "%d bytes \"%s\"\n", head->size, head->where ) ;
+	if( tail->size != head->size )
+	    wraperr( head->where, head->size, tail->size ) ;
+
+	head = head->previous ;
+    }
+
+printf( "\n" ) ;
+
+    return ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stitch/wrap.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,65 @@
+/*
+    wrap.h
+    ======
+
+    wrap alocations with debugging information for program verifiaction.
+
+*/
+
+/*
+    The following routines "wrap" memory with a frame as it is  allocated.
+    The  information  in the frame is sufficient to check if the bounds of
+    the alloacation have been exceeded.  Part of the frame is  used  as  a
+    pointer for a linked list  which  is  also  assembled  containing  all
+    allocated  memory  chunks.  This  enables  a  call  at any time to the
+    routine "checkWrapping()" to examine all  the  frames  of  all  memory
+    allocations for corruption while an application runs.
+
+
+	Memory map of a framed allocation after "wrapping"
+
+		   +--------------+
+	   head--> | struct _head |
+		   +--------------+
+	wrapped--> |  user data   |
+		   |      .       |
+		   |      .       |
+		   |      .       |
+		   |              |
+		   +--------------+
+	   tail--> | struct _tail |
+		   +--------------+
+
+
+    On allocation the  pointer  returned  from  tyhe  system  becomes  the
+    pointer  to  in instance of the stucture "_head".  A tail structure is
+    then constructed containing a repeat of the size feild of  the  header
+    for  consistency  checking  and a pointer to the previous allocation's
+    frame.  The user receives a pointer to  the  memory  bytes  availiable
+    after  the  head  structure  and  is therefore unaware of the wrapping
+    process.  On deallocation or reallocation the framed memory is  simply
+    unwrapped  by the reverse process checking for corruption before being
+    passed to the system memory allocation routines.
+
+*/
+
+/* bits rounded up in alligning the tail structure */
+
+#define BITS_ROUND 4
+
+/* rounds up byte size specification to ensure tail structure's elements are aligned */
+
+#define ROUNDUP( _size ) ( ( _size ) + ( 1 << BITS_ROUND ) - 1 >> BITS_ROUND << BITS_ROUND )
+
+/* Calculates the size required for the wrapped allocation including frame. */
+
+#define WRAPPED_SIZE( _size ) ( ROUNDUP( sizeof ( struct _head ) ) + ROUNDUP( _size ) + sizeof( struct _tail ) )
+
+
+struct _head { char *where ; struct _head **pointing, *previous ; unsigned size ; } ;
+struct _tail { unsigned size ; } ;
+
+extern Pointer wrap( /* char   *mem, unsigned size, char where[] */ ) ;
+extern char *unwrap( /* Pointer mem, unsigned size               */ ) ;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/acf.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,229 @@
+/*
+  Autocorrelation function using FFT routines adapted from routines given in
+  Numerical Recipes.
+  The routine acf() uses an fft to compute the array of lagged products
+  which is the autocovariance function. An optional normalization (dividing
+  each coefficient by the zeroth coefficient) produces the autocorrelation
+  function, (and this is then scaled up to the range [0-1000]).
+
+  The output framewidth is the given maximum acf lag, which must not be
+  greater than the input framewidth.
+
+  Padding with zeroes is recommended to counter end-effects (See NR, p416).
+  It is also necessary since:
+1) framesize + padding must be a power of two (sample points at given rate).
+2) max possible acf lag = ( framesize + padding ) / 2
+
+  Each input frame is padded with zeroes so that it is at least twice the
+  required max acf lag, and is also a power of 2.
+  This is because the fft method is "radix-2", and because the output acf is
+  symmetrical so that just half the points are unique.
+  Therefore each input frame is padded with zeroes to the next power of 2
+  larger than either the input framewidth, or twice the required max acf lag,
+  (whichever is  the larger).
+
+  If necessary, extra padding can be enforced using the padding option to
+  add extra zeroes, padding to a larger power of 2.
+  The amount of extra padding is "exponential", expanding the basic size to:
+	( framesize + padding ) * 2**n
+  where the padding option is n.
+  (n=0 by default, so that no extra padding is added. When n=1 then padding is
+  added to double the size, and when n=2 the size is quadrupled, etc.).
+
+  Frames are selected from the input stream using the "frames" option,
+  which has syntax: [[-]frame=a[-b]]. Input frames  are numbered 1,2,...
+  For example:
+    frame=a      Select just the a'th frame.
+    frame=a-b    Select frames from the a'th to b'th inclusive.
+  The strings "min" and "max" can be used as specifiers, meaning eg:
+    frame=min    Select the first frame.
+    frame=max    Select the last frame.
+    frame=a-max  Select frames from the a'th to the last inclusive.
+    frame=min-b  Select frames from the first to the b'th inclusive.
+  The default selects all frames, (ie frame=min-max).
+
+  Other options (set using <option>=on):
+    size         Print the input and output frame sizes in sample points.
+    echo         Echo buffered input without processing.
+    negative     Write negative half of acf (ie. with zeroth lag on right).
+
+
+  Examples:
+
+1. To print the input and output frame sizes in sample points, eg for a
+   subsequent plotting program, use the size option:
+
+acf ... size=on
+
+2. An acf of a waveform sampled at 10kHz, computed to a max lag of 12.8ms
+   within a frame of 12.8ms, plotting the 2nd frame in a sequence of frames
+   with frameshift 12.8ms.
+
+acf samp=10kHz width=12.8ms frstep=12.8ms frame=2 lag=12.8ms file | x11plot
+
+3. An animated plot of successive acf's of a waveform sampled at 10kHz,
+   each computed within a frame of 12.8ms, and shifted by 2 sample points.
+
+acf samp=10kHz width=12.8ms frstep=2p lag=12.8ms file | x11play -n128
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+#include "sigproc.h"
+
+char applic[]     = "autocorrelation function of contiguous frames.\n      i/p and o/p data in binary shorts." ;
+
+static char *helpstr, *debugstr, *sampstr, *startstr, *shiftstr, *widthstr, *sizestr ;
+static char *padstr, *wstr, *lagstr, *scalestr, *normstr, *framestr, *echostr, *negstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                  , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                      , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "                           , VAL     },
+    {   "start"     ,   "0"         ,  &startstr    ,   "Start point in i/p file."              , VAL     },
+    {   "frames"    ,   "1-max"     ,  &framestr    ,   "Select frames inclusively"             , VAL     },
+    {   "frstep"    ,   "16ms"      ,  &shiftstr    ,   "Step between input frames."            , VAL     },
+    {   "width"     ,   "32ms"      ,  &widthstr    ,   "Width of input frames."                , VAL     },
+    {   "lag"       ,   "32ms"      ,  &lagstr      ,   "Maximum acf lag (output frame width)." , VAL     },
+    {   "padding"   ,   "0"         ,  &padstr      ,   "Exponential frame padding"             , SVAL    },
+    {   "window"    ,   "on"        ,  &wstr        ,   "Hamming window"                        , SETFLAG },
+    {   "normalize" ,   "off"       ,  &normstr     ,   "normalized acf"                        , SETFLAG },
+    {   "scale"     ,   "0.025"     ,  &scalestr    ,   "scale output"                          , SVAL    },
+    {   "size"      ,   "off"       ,  &sizestr     ,   "print input/output frame size in samples"      , SETFLAG },
+    {   "echo"      ,   "off"       ,  &echostr     ,   "echo buffered input without processing", SVAL    },
+    {   "negative"  ,   "off"       ,  &negstr      ,   "write negative half of acf (zeroth lag on right)", SVAL    },
+   ( char * ) 0 } ;
+
+
+int     samplerate  ;
+int     width       ;
+int     step        ;
+int     zeroes      ;
+int     maxlag      ;
+int     dowindow    ;
+double  scale       ;
+int     normalize   ;
+int     echo        ;
+int     negative    ;
+
+float  *vec, *window ;
+short  *obuf ;
+
+main (argc, argv)
+int     argc;
+char  **argv;
+{
+    FILE     *fp  ;
+    short    *buf ;
+    int       a, b ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    samplerate = to_Hz( sampstr ) ;
+    dowindow   = ison(  wstr    ) ;
+    normalize  = ison(  normstr ) ;
+    echo       = ison(  echostr ) ;
+    negative   = ison(  negstr  ) ;
+
+    width      = to_p( widthstr, samplerate )  ;
+    step       = to_p( shiftstr, samplerate )  ;
+    maxlag     = to_p( lagstr  , samplerate )  ;
+
+    if ( ( maxlag << 1 ) < width )
+	zeroes = ( getpower( width ) << atoi( padstr ) ) - width ;
+    else if ( maxlag <= width )
+	zeroes = ( getpower( maxlag << 1 ) << atoi( padstr ) ) - width ;
+    else {
+	fprintf(stderr,"acf: required max lag [%dms] greater than framewidth [%dms]\n", maxlag*1000/samplerate, width*1000/samplerate);
+	exit( 1 ) ;
+    }
+
+    scale = ( 1./(double)(width+zeroes) ) * atof( scalestr ) ;
+
+    /* frame size printout */
+
+    if ( ison( sizestr ) ) {
+	fprintf(stderr,"acf sizes in sample points:\n" ) ;
+	fprintf(stderr,"    input  frame size = %d  (framewidth=%d + padding=%d)\n", width+zeroes, width, zeroes ) ;
+	fprintf(stderr,"    output frame size = %d \n", maxlag ) ;
+	exit( 0 ) ;
+    }
+
+    /* parse bounds on number of frames */
+
+    if ( selector( framestr, &a, &b ) == 0 ) {
+	fprintf(stderr,"acf: bad frame selector [%s]\n", framestr ) ;
+	exit( 1 ) ;
+    }
+
+    /* Allocate working space */
+
+    obuf  = (short *)malloc( maxlag * sizeof(short) ) ;
+    vec   = (float *)malloc( width+zeroes * sizeof(float) ) ;
+    if ( dowindow )
+	window = hamming( width ) ;
+
+    /* Compute acf for each frame of width shorts in the input stream */
+
+    if ( seekbytes( fp, (int)( to_p( startstr, samplerate ) * sizeof(short) ) ) == 0 ) {
+	fprintf(stderr,"improper seek\n") ;
+	exit( 1 ) ;
+    }
+
+    while ( ( buf = getframe( fp, a, width, step ) ) != (short *)0  && ( a<=b || b==0 ) ) {
+	if ( echo ) fwrite( buf, sizeof(short), width, stdout ) ;
+	else process( buf ) ;
+	a++ ;
+    }
+    if ( a<=b && b>0 )
+	fprintf(stderr,"warning: not enough frames for request\n");
+
+    fclose( fp ) ;
+}
+
+
+process( buf )
+short *buf ;
+{
+    short *bptr   = buf ;
+    short *endptr = buf + width ;
+    short *optr   = obuf ;
+    short *endlag = obuf + maxlag ;
+    float *wptr   = window ;
+    float *vptr   = vec    ;
+    float *endvec = vec + width + zeroes ;
+
+    if ( dowindow )
+	while ( bptr < endptr )
+	    *vptr++ =  *bptr++  *  *wptr++ ;
+    else
+	while ( bptr < endptr )
+	    *vptr++ =  *bptr++ ;
+
+    while ( vptr < endvec )         /* padding */
+	*vptr++ =  0 ;
+
+    acf( vec, width+zeroes ) ;
+
+    if ( normalize )
+	scale = 1000. / *vec ;
+
+    vptr = vec ;
+    while ( optr < endlag )
+	*optr++ = (short)( scale * *vptr++ ) ;
+
+    if ( !negative )
+	fwrite( obuf, sizeof(short), maxlag, stdout ) ;
+    else {
+	for ( optr = endlag-1 ; optr >= obuf ; optr-- ) /* write in reverse */
+	    fwrite( optr, sizeof(short), 1, stdout ) ;
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/acgram.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,616 @@
+/*
+ acgram.c       Autocorrelogram program by Michael Allerhand.
+----------
+
+  Short-time autocorrelation function applied to each row of input frames.
+  Output frames consist of row-wise autocorrelation coefficients.
+  The routine acf() uses an fft to compute the array of lagged products
+  which is the autocovariance function. An optional normalization (dividing
+  each coefficient by the zeroth coefficient) produces the autocorrelation
+  function, (and this is then scaled up to the range [0-5000]).
+
+Input/output:
+  Read a header and frame in NAP format.
+  Write a header, (constructed from the original input header), and a
+  succession of frames in SAI format.
+
+  The input file is interpreted as one large frame in NAP format to be
+  divided into input frames, each to be processed and output in SAI format.
+
+  The options "start" and "length" specify the input file.
+  The special option value length=max specifies all the input file from
+  the given start to its end.
+
+  The options "width" and "frstep"  specify the input frames.
+  The width option is the framewidth of each input frame) and the frstep
+  option is the frameshift between input frames in the input file.
+  The special option value width=max specifies the input framewidth as equal
+  to the given input file length, (and if this is also "max", then the
+  input framewidth is the remainder of the input file).
+
+  Most options in the input header are copied to the output header.
+  This enables options which are needed for the eventual display
+  to pass straight through. Some options are set so that they can override
+  the input header. For example, the display option is set on to enable
+  display even when input has display=off. The animate option can be set on
+  even when the input has animate=off.
+  Parts of the header are changed for the new sai format:
+  (frames, frameshift, framewidth, frameheight, framebytes).
+
+Padding:
+  The output framewidth is the given maximum acf lag, which is also the
+  number of acf coefficients computed from each row of each input frame.
+  The rows of each input frame are padded with zeroes so that the input
+  framewidth is at least twice the required output framewidth (max acf lag),
+  and also a power of 2. This is because the fft method is "radix-2", and
+  because the output acf is symmetrical so that just half the points are
+  unique. It is advisable to pad input frames for the additional reason that
+  padding counters end-effects (which can be significant with the fft method
+  for computing acf).
+
+  Therefore each row of each input frame is padded with zeroes to the next
+  power of 2 larger than either the original input framewidth or twice the
+  max acf lag (whichever is  the larger).
+  If necessary, extra padding can be enforced using the padding option to
+  add extra zeroes, padding to a larger power of 2.
+  The amount of extra padding is "exponential" since if the basic padded
+  framesize is N, and the padding option is n, then extra padding is to:
+  N * 2**n.
+  (n=0 by default, so that N is not changed. When n=1 then N is doubled, and
+  when n=2 then N is quadrupled, etc.).
+
+
+Examples:
+
+1. Autocorrelogram of a NAP, animated and normalized, with max lag 16ms:
+
+gennap len=128ms output=stdout display=off file | acgram lag=16ms norm=on anim=on > file.sai
+gensai useprev=on headr=5 top=1000 file             -(for landscape plot)
+genspl useprev=on headr=5 top=1000 pensize=2 file   -(for spiral plot)
+
+2. Autocorrelogram of an SAI:
+  (Note that gensai removes file.sai, so you must use some other name, eg foo.sai).
+
+gensai len=64 pwidth=64 nwidth=0 output=stdout display=off file |  \
+saitonap frame=3 | acgram lag=32ms frame=1 > foo.sai
+gensai useprev=on top=1000 headr=5 mag=2 foo
+
+3. Autocorrelogram of a NAP, followed by a cross-channel summary:
+
+gennap len=128ms output=stdout display=off file | acgram lag=16ms scale=0.001 > file.sai
+edframe frame=1 file.sai | integframe var=freq > file.sum
+
+*/
+
+
+#include <stdio.h>
+#include <math.h>
+#include "header.h"
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+#include "sigproc.h"
+
+char applic[]     = "Autocorrelogram auditory image." ;
+
+static char *helpstr  , *debugstr, *dispstr , *anistr   , *startstr  ;
+static char *lengthstr, *widthstr, *shiftstr, *headerstr, *framestr  ;
+static char *normstr  , *wstr    , *scalestr, *lagstr   , *padstr    ;
+static char *negstr   , *vstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                       , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                           , DEBUG   },
+    {   "display"   ,   "on"        ,  &dispstr     ,   "Display output image."                      , SETFLAG },
+    {   "animate"   ,   "off"       ,  &anistr      ,   "Animate cartoon."                           , SETFLAG },
+    {   "frames"    ,   "1-max"     ,  &framestr    ,   "Select frames inclusively"                  , VAL     },
+    {   "Header"    ,   "on"        ,  &headerstr   ,   "Header (for gensai useprevious=on)."        , VAL     },
+    {   "start"     ,   "0"         ,  &startstr    ,   "Start point in i/p file."                   , VAL     },
+    {   "length"    ,   "max"       ,  &lengthstr   ,   "Length of i/p file to process."             , VAL     },
+    {   "frstep"    ,   "16ms"      ,  &shiftstr    ,   "Step between input frames."                 , VAL     },
+    {   "width"     ,   "32ms"      ,  &widthstr    ,   "Width of input frames."                     , VAL     },
+    {   "lag"       ,   "32ms"      ,  &lagstr      ,   "Maximum acf lag (output frame width)."      , VAL     },
+    {   "padding"   ,   "0"         ,  &padstr      ,   "Exponential frame padding"                  , SVAL    },
+    {   "window"    ,   "on"        ,  &wstr        ,   "Hamming window"                             , SETFLAG },
+    {   "normalize" ,   "off"       ,  &normstr     ,   "Normalization"                              , SETFLAG },
+    {   "scale"     ,   "1."        ,  &scalestr    ,   "Scale factor for output"                    , VAL     },
+    {   "negative"  ,   "off"       ,  &negstr      ,   "write negative half of acf (zeroth lag on right)", SVAL    },
+    {   "verbose"   ,   "off"       ,  &vstr        ,   "print at each frame"                        , SVAL    },
+   ( char * ) 0 } ;
+
+
+int     samplerate ;
+
+int     frameheight, framewidth ;
+int     frames, framebytes ;
+int     frameshift ;
+
+int     Newframeheight, Newframewidth ;
+int     Newframes, Newframebytes ;
+int     Newframeshift ;
+
+int     start, length ; /* Size of input file (num cols) */
+int     frameslength ;  /* Length (num cols) of input file to process */
+
+int     zeroes ;
+int     window ;        /* Flag for Hamming window */
+float   scale  ;        /* Scale factor for output */
+int     normalize ;     /* Flag to normalize acf   */
+int     negative  ;
+int     Verbose   ;
+
+short  *file ;          /* Input file (NAP format) */
+float  *W    ;          /* Hamming window for fft  */
+float  *buf  ;          /* fft working space       */
+
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE   *fp ;
+    char   *header, *SaiHeader();
+    char   *versionstr, c ;
+    int     startbytes, framebyteshift ;
+    short  *frame, *endframe ;
+    int     i, a, b ;
+    float   acgram(), f, newscale = 1. ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    window    = ison( wstr    ) ;
+    normalize = ison( normstr ) ;
+    negative  = ison( negstr  ) ;
+    Verbose   = ison( vstr    ) ;
+
+
+    /**** parse bounds on number of frames ****/
+
+    if ( selector( framestr, &a, &b ) == 0 ) {
+	fprintf(stderr,"acgram: bad frame selector [%s]\n", framestr ) ;
+	exit( 1 ) ;
+    }
+
+
+    /**** Input frame dimensions (from header and options) ****/
+
+    if ((header = ReadHeader(fp)) == (char *) 0 ) {
+	fprintf(stderr,"acgram: header not found\n");
+	exit(1);
+    }
+
+    if ( (versionstr = HeaderString( header, "Version" )) == (char *)0 ) {
+	fprintf(stderr,"acgram: model version-number not found in header\n");
+	exit(1);
+    }
+
+    samplerate  = HeaderSamplerate( header );
+
+    /* In NAP format, the size of the 2-D image is given by:  */
+    /*   frameheight = number of rows (filterbank channels)   */
+    /*   frames      = number of columns (sample points)      */
+
+    frameheight = HeaderInt( header, "frameheight" );
+    frames      = HeaderInt( header, "frames"      );
+
+    if ( ( frameshift  = to_p( shiftstr, samplerate ) ) <= 0 ) {
+	fprintf(stderr,"acgram: non-positive frstep [%d]\n", frameshift);
+	exit(1);
+    }
+
+    /* calculate start of first frame (in cols) */
+
+    if ( ( start = to_p( startstr, samplerate ) + ( a-1 ) * frameshift ) >= frames ) {
+	fprintf(stderr,"acgram: input file too small (%dms) for given framing parameters\n", frames * 1000 / samplerate );
+	exit(1);
+    }
+
+    /* get length of input file (in cols) and framewidth of input frames */
+
+    if ( ismax( lengthstr ) ) length = frames - start ;
+    else                      length = to_p( lengthstr, samplerate ) - start ;
+
+    if ( ismax( widthstr ) )  framewidth = length ;
+    else                      framewidth = to_p( widthstr, samplerate ) ;
+
+    if ( length < framewidth ) {
+	fprintf(stderr,"acgram: input file too small (%dms) for given framing parameters\n", frames * 1000 / samplerate );
+	exit(1);
+    }
+
+    /* calculate length (num cols) to process, and the number of frames */
+
+    if ( b==0 ) {
+	frameslength = length ;
+	Newframes = 1 + ( length - framewidth ) / frameshift ;
+    }
+    else {
+	frameslength = framewidth + ( b-a ) * frameshift ;
+	Newframes = b - ( a-1 ) ;
+    }
+
+    if ( start + frameslength > frames ) {
+	fprintf(stderr,"acgram: input file too small (%dms) for requested start and length \n", frames * 1000 / samplerate );
+	exit(1);
+    }
+
+    framebytes = frameheight * frameslength * sizeof(short) ;
+    startbytes = frameheight * start  * sizeof(short) ;
+
+
+    /**** Output frame dimensions ****/
+
+    Newframeheight =  frameheight ;
+    Newframewidth  =  to_p( lagstr, samplerate );   /* Max acf lag   */
+    Newframeshift  =  frameshift ;
+    Newframebytes  =  Newframeheight * Newframewidth * sizeof(short) ;
+
+
+    /**** Padding and output scale factor ****/
+
+    if ( ( Newframewidth << 1 ) < framewidth )
+	zeroes = ( getpower( framewidth ) << atoi( padstr ) ) - framewidth ;
+    else if ( Newframewidth <= framewidth )
+	zeroes = ( getpower( Newframewidth << 1 ) << atoi( padstr ) ) - framewidth ;
+    else {
+	fprintf(stderr,"acgram: required max lag [%dms] greater than framewidth [%dms]\n", Newframewidth*1000/samplerate, framewidth*1000/samplerate);
+	exit( 1 ) ;
+    }
+
+    if ( normalize == 0 )   /* no normalize, so divide by length to get average of products */
+	scale = 1./(double)(framewidth + zeroes) * atof( scalestr ) ;
+    else
+	scale = atof( scalestr ) ;
+
+
+    /**** Debug ****/
+
+    if ( ison( debugstr ) ) {
+	fprintf(stderr, "Input:   frames=%d frameheight=%d frameshift=%d\n", frames, frameheight, frameshift ) ;
+	fprintf(stderr, "Sizes:   start=%d length=%d framewidth=%d frameslength=%d\n", start, length, framewidth, frameslength ) ;
+	fprintf(stderr, "Output:  zeroes=%d Newframewidth=%d Newframes=%d \n", zeroes, Newframewidth, Newframes ) ;
+	exit( 1 ) ;
+    }
+
+
+    /**** Allocate space (input file, window coeffs, and fft working space) ****/
+
+    if ( ( file = (short *)malloc( framebytes ) ) == NULL ) {
+	fprintf(stderr,"acgram: malloc out of space\n");
+	exit(1);
+    }
+
+    if ( window )
+	W = hamming( framewidth ) ;
+
+    buf = (float *)malloc( ( framewidth + zeroes ) * sizeof(float) );
+
+
+    /**** Write new sai header ****/
+
+    if ( ison( headerstr ) )
+	WriteHeader( SaiHeader(header), stdout );
+
+
+    /**** Seek to start of input file in blocks of framebytes ****/
+
+    for (i=framebytes ; i < startbytes ; i += framebytes)
+	if ( fread( file, framebytes, 1, fp ) == NULL ) {
+	    fprintf(stderr,"acgram: missing data after header\n");
+	    exit(1);
+	}
+    if ( (startbytes -= (i - framebytes)) > 0 )
+	if ( fread( file, startbytes, 1, fp ) == NULL ) {
+	    fprintf(stderr,"acgram: missing data after header\n");
+	    exit(1);
+	}
+
+
+    /**** Read framebytes of i/p file ****/
+
+    if ( fread( file, framebytes, 1, fp ) == NULL ) {
+	fprintf(stderr,"acgram: missing data after header\n");
+	exit(1);
+    }
+
+
+    /**** Process frames ****/
+
+    framebyteshift = frameshift * frameheight ;
+    endframe = file + Newframes * framebyteshift ;
+
+    for ( frame = file, i=1 ; frame < endframe ; frame += framebyteshift, i++ ) {
+	if ( Verbose )
+	    fprintf(stderr,"acgram: %d / %d  [%dms]\n", i, Newframes, start*1000/samplerate );
+	if ( ( f = acgram( frame ) ) < newscale )
+	    newscale = f ;
+	start += frameshift ;
+    }
+
+    fclose(fp);
+
+    if ( newscale < 1. ) {
+	fprintf( stderr, "Warning: 16-bit overflow during acgram.  " ) ;
+	if ( normalize == 0 )
+	    fprintf( stderr, "Try scale<%f\n", newscale * (float)(framewidth + zeroes) ) ;
+	else
+	    fprintf( stderr, "Try scale<%f\n", newscale ) ;
+    }
+
+    if ( Verbose )
+	fprintf(stderr,"acgram: done\n" ) ;
+}
+
+
+/************************** Autocorrelation function ***********************/
+
+/* Call acf for each row in the SAI frame */
+
+float acgram( frame )
+short *frame ;
+{
+    register int  i, j, row, col ;
+    float    writebuf(), f, newscale = 1. ;
+
+    for ( row=0 ; row < frameheight ; row++ ) {
+
+	if ( window )
+	    for ( col=0 , i=row ; col < framewidth ; col++, i+=frameheight )
+		buf[col] = frame[i] * W[col] ;
+	else
+	    for ( col=0 , i=row ; col < framewidth ; col++, i+=frameheight )
+		buf[col] = frame[i] ;
+
+	for ( j=0 ; j<zeroes ; j++ )    /* padding */
+	    buf[col++] = 0 ;
+
+	acf( buf, framewidth+zeroes ) ;
+
+	if ( normalize == 0 )
+	    f = writebuf( buf, Newframewidth, scale ) ;
+	else
+	    f = writebuf( buf, Newframewidth, scale/buf[0] ) ;
+
+	if ( f < newscale )
+	    newscale = f ;
+    }
+
+    return ( newscale ) ;
+}
+
+
+/********************** Write o/p ****************************************/
+
+float writebuf( buf, n, scale )       /* write buffer as scaled shorts */
+float *buf ;
+int    n ;
+float  scale ;
+{
+    register int  i ;
+    short         p ;
+    float newscale  ;
+
+    if ( !negative ) {  /* usual acf (ie. positive half, with zeroth lag on left) */
+	for (i=0 ; i < n ; i++)  {
+
+	    newscale = check_overflow( buf[i], scale, 1 ) ;
+
+	    p = (short)( buf[i] * scale ) ;
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+	}
+    }
+
+    else {      /* write negative half of acf (zeroth lag on right) */
+	for ( i = n-1 ; i >= 0 ; --i )  {
+
+	    newscale = check_overflow( buf[i], scale, 1 ) ;
+
+	    p = (short)( buf[i] * scale ) ;
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+	}
+    }
+    return ( newscale ) ;
+}
+
+
+
+/************************ Output header ************************************/
+/*
+   First create a new header with
+     nwidth_aid
+     pwidth_aid
+     frstep_aid
+   Then copy the original nap header into the sai header, changing in order:
+     frames
+     frameshift
+     framewidth
+     frameheight
+     framebytes
+     animate
+     display
+   Then change applic name [gennap] to [gensai] in the Version string.
+   Finally, update the new header_bytes, and return the new header.
+*/
+
+char *SaiHeader( napheader )
+char *napheader ;
+{
+    char *saiheader;
+    char *p0, *p1, *p2, *s, str[64];
+
+    saiheader = (char *)malloc( strlen(napheader) + 128 ) ;
+
+    p0 = saiheader ;
+    p1 = napheader ;
+
+
+    /** copy initial header bytes **/
+
+    p2 = HeaderString( napheader , "header_bytes" ) ;
+    while( p1 < p2 )
+	*p0++ = *p1++ ;
+    while (*p1 != '\n')
+	*p0++ = *p1++ ;
+    *p0++ = *p1++ ;
+
+
+    /** insert nwidth_aid at top of new header **/
+
+    sprintf(str,"nwidth_aid=0\n");
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+
+
+    /** insert pwidth_aid into new header **/
+
+    sprintf(str,"pwidth_aid=%dms\n", (int)(1000*((float)Newframewidth/samplerate)) );
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+
+
+    /** insert frstep_aid into new header **/
+
+    sprintf(str,"frstep_aid=%dms\n", (int)(1000*((float)frameshift/samplerate)) );
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+
+
+    /** copy up to frames **/
+
+    p2 = HeaderString( napheader , "frames" ) ;
+    while( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframes);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to frameshift **/
+
+    p2 = HeaderString( napheader , "frameshift" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframeshift);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to framewidth **/
+
+    p2 = HeaderString( napheader , "framewidth" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframewidth);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to frameheight **/
+
+    p2 = HeaderString( napheader , "frameheight" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframeheight);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to framebytes **/
+
+    p2 = HeaderString( napheader , "framebytes" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframebytes);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to animate_ctn **/
+
+    p2 = HeaderString( napheader , "animate_ctn" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%s\n", anistr );
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to display **/
+
+    p2 = HeaderString( napheader , "display" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%s\n", dispstr );
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy rest of header **/
+
+    p2 = HeaderString( napheader , "Version" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    while (*p1 != ']')          /* change applic name [gennap] to [gensai] */
+	*p0++ = *p1++ ;
+    *(p0-3) = 's' ;
+    *(p0-2) = 'a' ;
+    *(p0-1) = 'i' ;
+    while (*p1 != '\n')
+	*p0++ = *p1++ ;
+    *p0++ = *p1++ ;
+
+
+    /** update header_bytes **/
+
+    sprintf(str, "%0*d", 7, p0-saiheader);
+    p0 = HeaderString( saiheader , "header_bytes" ) ;
+    s = str;
+    while(*p0 != '\n')
+	*p0++ = *s++ ;
+
+
+    return saiheader;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/atob.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,64 @@
+/*
+ atob (binary-to-ascii) conversion.
+
+ Read ascii numbers from the input stream until eof.
+ Write each number on the stdout in the given type.
+
+ Bugs:
+  1. When converting binary floats to ascii, and then back to binary, there
+     will be some difference between the binary files because the ascii
+     floats are printed with limited precision.
+*/
+
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+
+
+char applic[]     = "ascii to binary conversion." ;
+
+static char *helpstr, *debugstr, *shortstr, *intstr, *floatstr, *typestr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"              ,  DEBUG },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging"         ,  DEBUG },
+    {   "type"      ,   "short"     ,  &typestr     ,   "output data type"  ,  VAL   },
+    {   "short"     ,   "off"       ,  &shortstr    ,   "data type"         ,  STOG  },
+    {   "int"       ,   "off"       ,  &intstr      ,   "data type"         ,  STOG  },
+    {   "float"     ,   "off"       ,  &floatstr    ,   "data type"         ,  STOG  },
+   ( char * ) 0 } ;
+
+
+int     itype       ;   /* input datatype index  */
+int     otype       ;   /* output datatype index */
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE *fp ;
+    float y  ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    itype = typeindex( "ascii" ) ;
+
+    if ( ( otype = typeindex( typestr ) ) < 0 ) {
+	fprintf( stderr, "atob: bad type [%s]\n", typestr ) ;
+	exit( 1 ) ;
+    }
+
+    if (      ison( shortstr ) )  otype = 1 ;   /* compatibility */
+    else if ( ison( intstr   ) )  otype = 2 ;
+    else if ( ison( floatstr ) )  otype = 3 ;
+
+    while ( readitem( &y, itype, 1, fp ) )
+	writeitem( &y, otype, 1, stdout ) ;
+
+    fclose(fp);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/audim.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,973 @@
+/*
+  audim.c           auditory images
+ ---------
+
+   This program provides methods of constructing time-varying auditory
+   images from the output of the cochlear model which are alternatives to
+   the gensai (stabilized auditory image) program. Correlograms (ie. row-
+   wise autocorrelation) and row-wise Fourier transform are provided.  The
+   program reads an AIM header and the output from the genbmm (basilar mem-
+   brane motion) or gennap (neural activity pattern) programs. This is
+   divided into contiguous time frames and written on the stdout with an
+   appropriate header as if output from the gensai program. This enables
+   genbmm or gennap output to be divided into time frames and replayed as a
+   cartoon by gensai using the "useprevious" option.  Additional processing
+   to each frame is optionally available to compute alternative forms of
+   auditory image according to the "image" option.
+
+
+   The options "start" and "length" specify the size of the input.  The
+   options "width" and "frstep"  specify the frames which are output.  The
+   input is divided into frames according to the width option and the
+   frstep option.
+
+   Special option values are:
+
+     length=max      Read all the input from the given start to its end.
+     width=max       Output framewidth is set equal to the given input
+	       length, and if this is also "max", then the
+	       framewidth is the remainder of the input.
+     frames=1-max    Select the 1st to the last frame inclusively.
+     frame=4         Select the 4th frame only.
+
+     image=off       Divide the input into frames for replay as a cartoon.
+     image=acgram    Compute correlogram of each frame.
+     image=ftgram    Compute power spectrum of each channel of each frame.
+     image=phgram    Compute phase spectrum of each channel of each frame.
+
+   Most options in the input header are copied to the output header.  This
+   enables options which are needed for the eventual display to pass
+   straight through. Some options are set so that they can override the
+   input header. For example, the display option is set on to enable
+   display even when input has display=off. The animate option can be set
+   on even when the input has animate=off.  Parts of the header are changed
+   for the new sai format: (frames, frameshift, framewidth, frameheight,
+   framebytes).
+
+  Padding:
+  The input nap is divided into frames according to the width option (called
+  framewidth internally) and the frstep option (called frameshift internally).
+  The framewidth is used as the basis for output image frame width:
+  the output width is actually the next power-of-2 above twice the framewidth.
+  This is because:
+  a. fft and acf output is always half the given frame size, due to symmetry,
+     so the input must be padded to twice its width.
+  b. To use fft, the input must also be a power of two.
+  So, each input row is padded out to the next power of two above twice its
+  width.
+
+  Certain display parameters have different default values for different
+  applications. The gensai display parameters should be set to the
+  appropriate values, in order to plot the cartoon on the same scale. For
+  example: when the source application is gennap, set gensai top=1000,
+  when the source application is genbmm, set gensai bottom=-100.
+
+
+Examples:
+
+1. An animated normalized autocorrelogram from a nap:
+
+gennap len=64ms output=stdout display=off file | audim norm=on anim=on > file.sai
+gensai useprev=on top=1000 cegc             -(for landscape plot)
+genspl useprev=on top=1000 pensize=2 cegc   -(for spiral plot)
+
+
+2. To convert a nap to multiple animated frames:
+
+gennap len=16ms display=off output=stdout file | audim image=off width=8ms frstep=0.2ms anim=on > file.sai
+gensai useprev=on top=1000 cegc             -(for landscape plot)
+genspl useprev=on top=1000 pensize=2 cegc   -(for spiral plot)
+
+    (Note: spirals look better in a square box, so you might use options:
+	   dencf=1 width=500 height=500 )
+
+3. To view the basilar membrane from a cross section, animating the waves on it.
+
+genbmm mincf=220 maxcf=660 len=8ms output=stdout display=off file | audim image=off width=1p frstep=1p display=on anim=on | edframe Tran=on > foo.sai
+gensai bott=-100 useprev=on mag=.2 foo
+
+or:
+
+genbmm mincf=220 maxcf=660 len=32ms output=stdout display=off file | \
+audim image=off width=1p frstep=1p display=on anim=on | \
+edframe Tran=on Header=off > foo
+
+x11play -n75 -a500 foo
+
+*/
+
+
+#include <stdio.h>
+#include <math.h>
+#include "header.h"
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+#include "sigproc.h"
+#include "freqs.c"
+
+char applic[]     = "Auditory images of neural activity patterns (NAP). " ;
+
+static char *helpstr, *debugstr, *dispstr, *anistr, *startstr, *imstr ;
+static char *lengthstr, *widthstr, *shiftstr, *headerstr, *cfstr, *framestr ;
+static char *normstr, *wstr, *sacfstr, *smagstr, *sphstr ;
+static char *blstr, *erbstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                       , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                           , DEBUG   },
+    {   "display"   ,   "on"        ,  &dispstr     ,   "Display output image."                      , SETFLAG },
+    {   "animate"   ,   "off"       ,  &anistr      ,   "Animate cartoon."                           , SETFLAG },
+    {   "frames"    ,   "1-max"     ,  &framestr    ,   "Select frames inclusively"                  , VAL     },
+    {   "image"     ,   "acgram"    ,  &imstr       ,   "Form of auditory image."                    , VAL     },
+    {   "header"    ,   "on"        ,  &headerstr   ,   "Header (for gensai useprevious=on)."        , VAL     },
+    {   "start"     ,   "0"         ,  &startstr    ,   "Start point in i/p NAP"                     , VAL     },
+    {   "length"    ,   "max"       ,  &lengthstr   ,   "Length of i/p NAP to process."              , VAL     },
+    {   "frstep"    ,   "16ms"      ,  &shiftstr    ,   "Step between frames of the auditory image." , VAL     },
+    {   "width"     ,   "32ms"      ,  &widthstr    ,   "Width of auditory image."                   , VAL     },
+    {   "normalize" ,   "off"       ,  &normstr     ,   "Normalization"                              , SETFLAG },
+    {   "window"    ,   "off"       ,  &wstr        ,   "Hamming window"                             , SETFLAG },
+    {   "bandlimit" ,   "off"       ,  &blstr       ,   "Zero outside bandwidth."                    , SETFLAG },
+    {   "erbs"      ,   "2"         ,  &erbstr      ,   "Width (in ERBS) of band either side of cf." , SVAL    },
+    {   "align_cf"  ,   "off"       ,  &cfstr       ,   "Align on centre frequency."                 , SETFLAG },
+    {   "scale_acf" ,   "0.025"     ,  &sacfstr     ,   "Scale factor for acf output"                , SVAL    },
+    {   "scale_fft" ,   "0.08"      ,  &smagstr     ,   "Scale factor for fft magnitude output"      , SVAL    },
+    {   "scale_phs" ,   "100"       ,  &sphstr      ,   "Scale factor for fft phase output"          , SVAL    },
+   ( char * ) 0 } ;
+
+
+int     frameheight ;   /* Nap parameters read from header */
+int     frames, samplerate ;
+int     framewidth  ;   /* width option */
+
+int     start, length ;
+
+int     Newframeheight, Newframewidth ; /* Sai parameters to write  */
+int     Newframes ;
+int     Newframeshift ;
+int     Newframebytes ;
+
+
+char   *limitstr ;      /* Sai parameters used to get centre-frequencies */
+char   *qualstr  ;
+char   *minstr   ;
+char   *maxstr   ;
+char   *denstr   ;
+char   *chansstr ;
+double *frequencies ;
+int     nerbs ;         /* bandwidth defined as number of erbs either side of cf */
+int     bandlimit ;     /* flag for zeroing outside bandwidth around centre-freqs */
+int     align ;         /* flag for aligning centre-freqs */
+
+#define NONE    0       /* forms of auditory image */
+#define ACGRAM  1
+#define FTGRAM  2
+#define PHGRAM  3
+int     image ;
+
+float  *buf ;           /* fft working space */
+int     zeroes ;        /* padding */
+float  *W ;             /* Hamming window for fft */
+short   window ;        /* flag for window */
+
+short   debug ;         /* flag for debug printf's */
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE   *fp ;
+    int     i, framebytes, startbytes, frameshift, framebyteshift;
+    char   *header, *SaiHeader();
+    short  *nap, *frame, *endframe;
+    int     a, b ;
+    char   *val1, *val2 ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    window = ison( wstr ) ;
+    nerbs  = atoi( erbstr ) ;
+    debug  = ison( debugstr ) ;
+
+    /**** Form of image ****/
+
+    if ( iststr( imstr, "acgram" ) )  {
+	image = ACGRAM ;
+    }
+    else if ( iststr( imstr, "ftgram" ) )  {
+	image = FTGRAM ;
+    }
+    else if ( iststr( imstr, "phgram" ) )  {
+	image = PHGRAM ;
+    }
+    else if ( isoff( imstr ) ) {
+	image = NONE ;
+    }
+    else {
+	fprintf(stderr, "audim: unknown form of auditory image [%s]\n", imstr ) ;
+	exit( 1 ) ;
+    }
+
+    align     = ison( cfstr ) ;
+    bandlimit = ison( blstr ) ;
+
+
+    /**** parse bounds on number of frames ****/
+
+    if ( getvals( framestr, &val1, &val2, "-" ) == BADVAL ) {
+	fprintf(stderr,"audim: bad frame selector [%s]\n", framestr ) ;
+	exit( 1 ) ;
+    }
+    a = atoi( val1 ) ;
+    if ( isempty( val2 ) )    b = a ;
+    else if ( ismax( val2 ) ) b = 0 ;
+    else                      b = atoi( val2 ) ;
+
+    if (b<a && b>0) fprintf(stderr,"audim warning: bad frame specifiers\n");
+
+
+    /**** Read header and options to find dimensions of auditory image ****/
+
+    if ( (header = ReadHeader(fp)) == (char *) 0 ) {
+	fprintf(stderr,"audim: header not found\n");
+	exit(1);
+    }
+
+    frameheight = HeaderInt( header, "frameheight" );
+    frames      = HeaderInt( header, "frames"      );
+    samplerate  = HeaderSamplerate( header );
+    start       = to_p( startstr,  samplerate );
+    frameshift  = to_p( shiftstr, samplerate ) ;
+
+    if ( ismax( lengthstr ) )   /* Special case for remainder of input */
+	length = frames - start ;
+    else
+	length = to_p( lengthstr, samplerate );
+
+    if ( start + length > frames ) {
+	fprintf(stderr,"audim: nap too small (%d ms) for requested start and length \n", to_ms( frames, samplerate ) );
+	exit(1);
+    }
+
+    framebytes = frameheight * length * sizeof(short) ;
+    startbytes = frameheight * start  * sizeof(short) ;
+
+    if ( ismax( widthstr ) )    /* Special case for single frame of max width */
+	framewidth = length ;
+    else
+	framewidth = to_p( widthstr, samplerate ) ;
+
+    frames = ( length - framewidth ) / frameshift ;
+    zeroes = getpower( framewidth << 1 ) - framewidth ;
+
+
+    /**** Get centre-frequencies information using info given in header ****/
+
+    limitstr =    HeaderStringOnly( header, "bwmin_afb"    );
+    qualstr =     HeaderStringOnly( header, "quality_afb"  );
+    minstr =      HeaderStringOnly( header, "mincf_afb"    );
+    maxstr =      HeaderStringOnly( header, "maxcf_afb"    );
+    denstr =      HeaderStringOnly( header, "dencf_afb"    );
+    chansstr =    HeaderStringOnly( header, "channels_afb" );
+
+    SetErbParameters( to_Hz( limitstr ), atof( qualstr ) ) ;
+    if( OptionInt( chansstr ) == 0 )
+	frequencies = GenerateCenterFrequencies( to_Hz( minstr ), to_Hz( maxstr ), atof( denstr ) )   ;
+    else
+	frequencies = NumberedCenterFrequencies( to_Hz( minstr ), to_Hz( maxstr ), OptionInt( chansstr ) ) ;
+
+
+    /**** Output frame dimensions (to write into new header) ****/
+
+    Newframeheight = frameheight ;
+
+    if ( !align ) {
+	if ( image == NONE )
+	    Newframewidth = framewidth ;
+	else
+	    Newframewidth = ( framewidth + zeroes ) >> 1 ;  /* spectral bins */
+    }
+    else  {      /* number of bins corresponding to the filter bandwidth */
+	switch ( image ) {
+	    case NONE   :   Newframewidth = framewidth ;
+			    break ;
+	    case ACGRAM :   Newframewidth = maxlagwidth( to_Hz( minstr ), nerbs ) ;
+			    break ;
+	    case FTGRAM :   Newframewidth = maxbandwidth( to_Hz( maxstr ), nerbs, (framewidth+zeroes)>>1 ) ;
+			    break ;
+	}
+    }
+    Newframeshift =  frameshift ;
+    Newframebytes =  Newframeheight * Newframewidth * sizeof(short) ;
+
+    if ( frameshift > 0 ) {
+	if ( b == 0 )
+	    Newframes = frames - (a-1) ;
+	else
+	    Newframes = b - (a-1) ;
+    }
+    else {
+	fprintf(stderr,"audim: non-positive frstep [%d]\n", frameshift);
+	exit(1);
+    }
+
+
+    /**** Check limits etc.. ****/
+
+    if ( b > frames ) {
+	fprintf(stderr,"audim: can't select frame %d out of %d frames\n", b, frames ) ;
+	exit(1);
+    }
+
+    if ( length < framewidth ) {
+	fprintf(stderr,"audim: nap too small (%d ms) for requested width\n", to_ms( length, samplerate ) );
+	exit(1);
+    }
+
+    if (frames<=0) {
+	if (frames==0)  fprintf(stderr,"audim: zero frames input\n");
+	if (frames<0)   fprintf(stderr,"audim: garbled number of frames, (start set too big?)\n");
+	exit(1);
+    }
+
+    if (a>frames || b>frames)
+	fprintf(stderr,"audim warning: bad frame selectors\n");
+
+
+
+    if ( debug ) {
+	fprintf(stderr, "Header:  frames=%d frameheight=%d\n", frames, frameheight ) ;
+	fprintf(stderr, "Options: a=%d b=%d start=%d length=%d frameshift=%d framewidth=%d\n", a, b, start, length, frameshift, framewidth ) ;
+	fprintf(stderr, "Output:  zeroes=%d Newframewidth=%d Newframes=%d \n", zeroes, Newframewidth, Newframes ) ;
+    }
+
+
+    /**** Write new sai header ****/
+
+    if ( ison( headerstr ) )
+	WriteHeader( SaiHeader(header), stdout );
+
+
+    /**** Allocate space for framebytes of nap data ****/
+
+    if ( (nap = (short *)malloc( framebytes )) == NULL ) {
+	fprintf(stderr,"audim: malloc out of space\n");
+	exit(1);
+    }
+
+
+    /**** Allocate and assign window coeffs ****/
+
+    if ( window )
+	W = hamming( framewidth ) ;
+
+
+    /**** Allocate fft working space ****/
+
+    buf = (float *)malloc( ( framewidth + zeroes ) * sizeof(float) );
+
+
+    /**** Seek to start in blocks of framebytes ****/
+
+    for (i=framebytes ; i < startbytes ; i += framebytes)
+	if ( fread( nap, framebytes, 1, fp ) == NULL ) {
+	    fprintf(stderr,"audim: missing data after header\n");
+	    exit(1);
+	}
+    if ( (startbytes -= (i - framebytes)) > 0 )
+	if ( fread( nap, startbytes, 1, fp ) == NULL ) {
+	    fprintf(stderr,"audim: missing data after header\n");
+	    exit(1);
+	}
+
+    /**** Read framebytes of i/p nap data ****/
+
+    if ( fread( nap, framebytes, 1, fp ) == NULL ) {
+	fprintf(stderr,"audim: missing data after header\n");
+	exit(1);
+    }
+
+    framebyteshift = frameshift * frameheight ;
+    nap = nap + (a-1) * framebyteshift ;
+    endframe = nap + Newframes * framebyteshift ;
+
+    switch ( image ) {
+	case NONE   : fprintf(stderr,"Output framewidth = %dp \n", Newframewidth ) ;  break ;
+	case ACGRAM : fprintf(stderr,"Output framewidth = %dp Lag range = 0-%dms\n", Newframewidth, (Newframewidth*1000)/samplerate ) ; break ;
+	case FTGRAM : fprintf(stderr,"Output framewidth = %dp Frequency range = 0-%dkHz\n", Newframewidth, samplerate/2000 ) ; break ;
+	case PHGRAM : break ;
+    }
+
+    for ( frame = nap ; frame < endframe ; frame += framebyteshift ) {
+
+	fprintf(stderr,"audim: %d / %d\n", a++, frames );
+	switch ( image ) {
+
+	    case NONE   : writeframe( frame ) ; break ;
+	    case ACGRAM : acgram( frame ) ;     break ;
+	    case FTGRAM : ftgram( frame ) ;     break ;
+	    case PHGRAM : phgram( frame ) ;     break ;
+
+	}
+    }
+    fprintf(stderr,"audim: done\n" );
+}
+
+
+
+
+
+int OptionInt( str )
+char *str ;
+{
+    if( strcmp( str, "on" ) == 0 )
+	return( 1 ) ;
+    else if( strcmp( str, "Not_used" ) == 0 )
+	return( 0 ) ;
+    else
+	return( atoi( str ) ) ;
+}
+
+
+/*********************** Read header and build new header *****************/
+
+/*
+   Copy the original nap header to a new sai header, changing in order:
+     frames
+     frameshift
+     framewidth
+     frameheight
+     framebytes
+     animate
+     display
+   Finally, update the new header_bytes, and return the new header.
+*/
+
+char *SaiHeader( napheader )
+char *napheader ;
+{
+    char *saiheader;
+    char *p0, *p1, *p2, *s, str[64];
+
+    saiheader = (char *)malloc( strlen(napheader) + 256 ) ;
+
+    p0 = saiheader ;
+    p1 = napheader ;
+
+    /* copy to first item after the header_bytes */
+
+    p2 = HeaderString( napheader , "header_bytes" ) ;
+    while( p1 < p2 )
+	*p0++ = *p1++ ;
+    while (*p1 != '\n')
+	*p0++ = *p1++ ;
+    *p0++ = *p1++;
+
+    /* insert frstep_aid at top of new header */
+
+    sprintf( str,"frstep_aid=%s\n", shiftstr ) ;
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+
+    /** copy up to frames **/
+
+    p2 = HeaderString( napheader , "frames" ) ;
+    while( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframes);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to frameshift **/
+
+    p2 = HeaderString( napheader , "frameshift" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframeshift);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to framewidth **/
+
+    p2 = HeaderString( napheader , "framewidth" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframewidth);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to frameheight **/
+
+    p2 = HeaderString( napheader , "frameheight" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframeheight);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to framebytes **/
+
+    p2 = HeaderString( napheader , "framebytes" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframebytes);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to animate_ctn **/
+
+    p2 = HeaderString( napheader , "animate_ctn" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%s\n", anistr );
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to display **/
+
+    p2 = HeaderString( napheader , "display" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%s\n", dispstr );
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy rest of header **/
+
+    p2 = HeaderString( napheader , "Version" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    if ( ( p2 = ApplicString( napheader ) ) == (char *)0 )  {
+	fprintf(stderr,"audim: application name not found in header\n");
+	exit( 1 ) ;
+    }
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    *p0++ = 's' ; *p0++ = 'a' ; *p0++ = 'i' ;   /* copy sai into applic name */
+    p1 += 3 ;
+
+    while (*p1 != '\n')
+	*p0++ = *p1++ ;
+    *p0++ = *p1++ ;
+
+
+    /** update header_bytes **/
+
+    sprintf(str, "%0*d", 7, p0-saiheader);
+    p0 = HeaderString( saiheader , "header_bytes" ) ;
+    s = str;
+    while(*p0 != '\n')
+	*p0++ = *s++ ;
+
+
+    return saiheader;
+}
+
+
+/************************** Autocorrelation function ***********************/
+
+/* Call acf for each row in auditory image */
+
+acgram( frame )
+short *frame ;
+{
+    static   float  scale ;
+    static   int    normalize ;
+    static   int    first = 1 ;
+    register int    i, j, row, col ;
+    short    p ;
+
+    if (first) {
+	normalize = ison( normstr ) ;
+	scale = 1./(double)( framewidth + zeroes ) * atof( sacfstr ) ;
+	first=0;
+    }
+
+    for ( row=0 ; row < frameheight ; row++ ) {
+	for ( col=0 , i=row ; col < framewidth ; col++, i+=frameheight )
+	    buf[col] = frame[i] ;
+	for ( j=0 ; j<zeroes ; j++ )    /* padding */
+	    buf[col++] = 0 ;
+
+	acf( buf, framewidth+zeroes ) ;
+
+	if ( align || bandlimit )
+	    writelags( buf, row, (framewidth+zeroes)>>1, Newframewidth, scale ) ;
+	else {
+	    if ( normalize == 0 )
+		writebuf( buf, Newframewidth, scale ) ;
+	    else
+		writebuf( buf, Newframewidth, 5000./buf[0] ) ;
+	}
+    }
+}
+
+
+/********************************** FFT ************************************/
+
+/* Call fft and magnitude spectrum for each row in auditory image */
+
+ftgram( frame )
+short *frame ;
+{
+    static   float  scale ;
+    static   int    first = 1 ;
+    register int    i, j, row, col ;
+
+    if (first) {
+	scale = atof( smagstr ) ;
+	first=0;
+    }
+
+    for ( row=0 ; row < frameheight ; row++ ) {
+	if ( window )
+	    for ( col=0 , i=row ; col < framewidth ; col++, i+=frameheight )
+		buf[col] = frame[i] * W[col] ;
+	else
+	    for ( col=0 , i=row ; col < framewidth ; col++, i+=frameheight )
+		buf[col] = frame[i] ;
+
+	for ( j=0 ; j<zeroes ; j++ )    /* padding */
+	    buf[col++] = 0 ;
+
+	fft( buf, framewidth+zeroes, 1 ) ;
+	mag( buf, framewidth+zeroes ) ;
+
+	if ( align || bandlimit )
+	    writebins( buf, row, (framewidth+zeroes)>>1, Newframewidth, scale ) ;
+	else
+	    writebuf( buf, Newframewidth, scale ) ;
+    }
+}
+
+
+/********************************** Phase **********************************/
+
+/* Call fft and phase spectrum for each row in auditory image */
+
+phgram( frame )
+short *frame ;
+{
+    static   float  scale ;
+    static   int    first = 1 ;
+    register int    i, j, row, col ;
+
+    if (first) {
+	scale = atof( sphstr ) ;
+	first=0;
+    }
+
+    for ( row=0 ; row < frameheight ; row++ ) {
+	for ( col=0 , i=row ; col < framewidth ; col++, i+=frameheight )
+	    buf[col] = frame[i] ;
+	for ( j=0 ; j<zeroes ; j++ )    /* padding */
+	    buf[col++] = 0 ;
+
+	fft( buf, framewidth+zeroes, 1 ) ;
+	phase( buf, framewidth+zeroes ) ;
+
+	writebuf( buf, Newframewidth, scale ) ;
+    }
+}
+
+
+/**** Write o/p routines ****/
+
+writebuf( buf, n, scale )       /* write buffer as scaled shorts */
+float *buf ;
+int    n ;
+float  scale ;
+{
+    register int  i ;
+    short         p ;
+
+    for (i=0 ; i < n ; i++)  {
+	p = (short)( buf[i] * scale ) ;
+	fwrite( &p, sizeof(short), 1, stdout ) ;
+    }
+}
+
+
+
+
+writeframe( frame )     /* Write a nap frame in sai format */
+short  *frame ;
+{
+    int    i, row, col;
+
+    for (row=0 ; row < frameheight ; row++)
+	for (col=0 , i=row ; col < framewidth ; col++, i+=frameheight)
+	    fwrite( &frame[i], sizeof(short), 1, stdout );
+}
+
+
+/*
+  Write a band of spectral bins around the centre-freq of the given channel.
+
+  The o/p spectrum is 0 to samplerate/2 Hz, resolved into spectral bins:
+	bins = (framewidth + zeroes) / 2
+
+  For the i'th channel, the centre-frequency cf = frequencies[i].
+  Filters are symmetrical bandpass, so considering a bandwidth of 4 ERB
+  the side-frequencies at the band limits are:
+
+    side1 = cf - 2*ERB     [Hz]
+    side2 = cf + 2*ERB     [Hz]
+
+  Note: side1 < side2
+
+  Convert frequency to bin number as follows:
+  Let centre-frequency cf have bin number j, so that ratios:
+	cf/(samplerate/2) = j/bins
+  and so:
+	j  = ( cf*bins ) / ( samplerate/2 )
+
+  (Similarly for each of the side-frequencies at the 2-ERB band limits).
+
+*/
+
+writebins( buf, chan, bins, maxwidth, scale )
+float *buf ;
+int    chan ;
+int    bins ;       /* number of spectral bins */
+int    maxwidth ;
+float  scale ;
+{
+    double ERB, cf, side1, side2, max ;
+    register int  i, j, s1, s2 ;
+    short         p ;
+
+    ERB   = frequencies[chan]/9.26449 + 24.7 ;
+    cf    = frequencies[chan]          ;
+    side1 = frequencies[chan] - nerbs*ERB  ;
+    side2 = frequencies[chan] + nerbs*ERB  ;
+
+    j  = (int)( ( cf    * bins ) / ( samplerate >> 1 ) + 0.5 ) ;   /* rounding */
+    s1 = (int)( ( side1 * bins ) / ( samplerate >> 1 ) + 0.5 ) ;
+    s2 = (int)( ( side2 * bins ) / ( samplerate >> 1 ) + 0.5 ) ;
+
+    if ( debug )
+	fprintf(stderr,"chan=%d bins=%d maxwidth=%d j=%d side1=%d side2=%d\n",chan,bins,maxwidth,j,s1,s2);
+
+    /*  Plot the given bandwidth, zeroing elsewhere:     */
+
+    if ( bandlimit && !align ) {
+
+	for ( i=0, p=0 ; i < s1 ; i++ )
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+
+	for (  ; i < s2 && i < bins ; i++ )  {
+	    p = (short)( buf[i] * scale ) ;
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+	}
+
+	for ( p=0 ; i < bins ; i++ )
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+    }
+
+    /* Plot the given bandwidth, shifting it to the centre */
+
+    if ( align ) {
+
+/* align on max bin in band
+	max = 0 ;
+	for ( i=s1 ; i<s2 ; i++ )
+	    if ( buf[i] >= max ) {
+		max = buf[i] ;
+		j = i ;
+	    }
+	for ( i=0, p=0 ; i < s1+(maxwidth/2-j) ; i++ )
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+	for ( j = s1 ; j < s2 && i < maxwidth ; i++, j++ )  {
+	    p = (short)( buf[j] * scale ) ;
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+	}
+	for ( p=0 ; i < maxwidth ; i++ )
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+*/
+
+	j = (maxwidth+s1-s2)/2 ;
+	for ( i=0, p=0 ; i < j ; i++ )
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+
+	for ( j = s1 ; j < s2 ; i++, j++ )  {
+	    p = (short)( buf[j] * scale ) ;
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+	}
+	for ( p=0 ; i < maxwidth ; i++ )
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+
+    }
+}
+
+
+
+/*
+  Write a band of acf lags around the centre-period of the given channel.
+
+  For the i'th channel, the centre-frequency
+	Centre-frequency   cf  = frequencies[i]     [Hz]
+	Bandwidth          ERB = cf/9.26449 + 24.7  [Hz]
+	Centre-period       cp = samplerate / cf    [samples]
+
+  Filters are symmetrical bandpass, so considering a bandwidth of 4 ERB
+
+    side1 = samplerate / ( cf - 2*ERB )    [samples]
+    side2 = samplerate / ( cf + 2*ERB )    [samples]
+
+  Note: side2 < side1 since periods
+
+  Also, successive bins ARE successive lags (in samples).
+*/
+
+
+
+writelags( buf, chan, lags, maxwidth, scale )
+float *buf ;
+int    chan ;
+int    lags ;       /* number of acf lags */
+int    maxwidth ;
+float  scale ;
+{
+    double ERB, cp, side1, side2 ;
+    register int  i, j, s1, s2 ;
+    short         p ;
+
+    ERB   = frequencies[chan]/9.26449 + 24.7 ;
+    cp    = (double)samplerate /   frequencies[chan]           ;
+    side1 = (double)samplerate / ( frequencies[chan] - nerbs*ERB ) ;
+    side2 = (double)samplerate / ( frequencies[chan] + nerbs*ERB ) ;
+
+    j  = (int)( cp    + 0.5 ) ;         /* rounding */
+    s1 = (int)( side1 + 0.5 ) ;
+    s2 = (int)( side2 + 0.5 ) ;
+
+    if ( debug )
+	fprintf(stderr,"chan=%d lags=%d side1=%d side2=%d\n",chan,lags,s1,s2);
+
+    /*  Plot the given bandwidth, zeroing elsewhere:     */
+
+    if ( bandlimit && !align ) {
+
+	for ( i=0, p=0 ; i < s2 ; i++ )
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+
+	for (  ; i < s1 && i < lags ; i++ )  {
+	    p = (short)( buf[i] * scale ) ;
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+	}
+
+	for ( p=0 ; i < lags ; i++ )
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+    }
+
+    /* Plot the given bandwidth, shifting it to the centre */
+
+    if ( align ) {
+
+	j = (maxwidth+s2-s1)/2 ;
+	for ( i=0, p=0 ; i < j ; i++ )
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+
+	for ( j = s2 ; j < s1 ; i++, j++ )  {
+	    p = (short)( buf[j] * scale ) ;
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+	}
+	for ( p=0 ; i < maxwidth ; i++ )
+	    fwrite( &p, sizeof(short), 1, stdout ) ;
+    }
+}
+
+
+/*
+  Return the number of lags corresponding to a bandwidth of nerbs ERBS either
+  side of a given mincf. This will be the max required framewidth.
+*/
+
+maxlagwidth( mincf, nerbs )
+double mincf ;
+int    nerbs ;
+{
+    double ERB, side1, side2 ;
+
+    ERB   = mincf/9.26449 + 24.7 ;
+    side1 = (double)samplerate / ( mincf - nerbs*ERB ) ;
+    side2 = (double)samplerate / ( mincf + nerbs*ERB ) ;
+
+    return (int)( side1 - side2 ) ;
+}
+
+
+/*
+  Return the number of bins corresponding to a bandwidth of nerbs ERBS either
+  side of a given maxcf. This will be the max required framewidth.
+*/
+
+maxbandwidth( maxcf, nerbs, bins )
+double maxcf ;
+int    nerbs ;
+int    bins  ;
+{
+    double ERB, side1, side2 ;
+    int    s1, s2 ;
+
+    ERB   = maxcf/9.26449 + 24.7 ;
+    side1 = maxcf - nerbs*ERB  ;
+    side2 = maxcf + nerbs*ERB  ;
+
+    /* convert frequencies to bin numbers */
+
+    s1 = (int)( ( side1 * bins ) / ( samplerate >> 1 ) + 0.5 ) ;
+    s2 = (int)( ( side2 * bins ) / ( samplerate >> 1 ) + 0.5 ) ;
+
+    return (int)( s2 - s1 ) ;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/btoa.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,67 @@
+/*
+ btoa (binary-to-ascii) conversion.
+
+ Read numbers of given type from the input stream until eof.
+ Print each number in ascii on the stdout to the given precision.
+
+ Bugs:
+  1. When converting binary floats to ascii, and then back to binary, there
+     will be some difference between the binary files because the ascii
+     floats are printed with limited precision.
+*/
+
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+
+
+char applic[]     = "binary to ascii conversion." ;
+
+static char *helpstr, *debugstr, *shortstr, *intstr, *floatstr, *precstr, *typestr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"          ,  DEBUG },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging"     ,  DEBUG },
+    {   "type"      ,   "short"     ,  &typestr     ,   "input data type"  ,  VAL   },
+    {   "precision" ,   "3"         ,  &precstr     ,   "decimal places",  VAL   },
+    {   "short"     ,   "off"       ,  &shortstr    ,   "data type"     ,  STOG  },
+    {   "int"       ,   "off"       ,  &intstr      ,   "data type"     ,  STOG  },
+    {   "float"     ,   "off"       ,  &floatstr    ,   "data type"     ,  STOG  },
+   ( char * ) 0 } ;
+
+
+int     itype       ;   /* input datatype index  */
+int     otype       ;   /* output datatype index */
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE *fp ;
+    float y  ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    PRECISION = atoi( precstr ) ;
+
+    otype = typeindex( "ascii" ) ;
+
+    if ( ( itype = typeindex( typestr ) ) < 0 ) {
+	fprintf( stderr, "atob: bad type [%s]\n", typestr ) ;
+	exit( 1 ) ;
+    }
+
+    if (      ison( shortstr ) )  itype = 1 ;   /* compatibility */
+    else if ( ison( intstr   ) )  itype = 2 ;
+    else if ( ison( floatstr ) )  itype = 3 ;
+
+    while ( readitem( &y, itype, 1, fp ) )
+	writeitem( &y, otype, 1, stdout ) ;
+
+    fclose(fp);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/bufframe.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,414 @@
+/*
+    bufframe.c    shifting AIM output frame buffer.
+    ----------
+
+
+
+Examples:
+
+1. To convert gennap output to multiple animated frames:
+
+gennap len=16ms display=off output=stdout file | \
+bufframe width=8ms frstep=0.2ms anim=on > file.sai
+gensai useprev=on top=1000 cegc             -(for landscape plot)
+genspl useprev=on top=1000 pensize=2 cegc   -(for spiral plot)
+
+    (Note: spirals look better in a square box, so you might use options:
+	   dencf=1 width=500 height=500 )
+
+2. To view the basilar membrane from a cross section, animating the waves on it.
+
+genbmm mincf=220 maxcf=660 len=8ms output=stdout display=off file | \
+bufframe width=1p frstep=1p Tran=on display=on anim=on > foo.sai
+gensai bott=-100 useprev=on mag=.2 foo
+
+or:
+
+genbmm mincf=220 maxcf=660 len=32ms output=stdout display=off file | \
+bufframe width=1p frstep=1p Tran=on Header=off > foo
+
+x11play -n75 -a500 foo
+
+*/
+
+
+
+#include <stdio.h>
+#include <math.h>
+#include "header.h"
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+
+char applic[]     = "shifting AIM output frame buffer. " ;
+
+
+static char *helpstr,   *debugstr, *dispstr,    *anistr,    *transtr  ;
+static char *widthstr,  *shiftstr, *headerstr,  *framestr             ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                  , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                      , DEBUG   },
+    {   "width"     ,   "32ms"      ,  &widthstr    ,   "Width of image frame."                 , VAL     },
+    {   "frstep"    ,   "16ms"      ,  &shiftstr    ,   "Step between image frames."            , VAL     },
+    {   "frames"    ,   "min-max"   ,  &framestr    ,   "Select frames inclusively"             , VAL     },
+    {   "Transpose" ,   "off"       ,  &transtr     ,   "Transpose image frames"                , SETFLAG },
+    {   "Header"    ,   "on"        ,  &headerstr   ,   "Header (for gensai useprevious=on)."   , VAL     },
+    {   "display"   ,   "on"        ,  &dispstr     ,   "Display output image."                 , SETFLAG },
+    {   "animate"   ,   "off"       ,  &anistr      ,   "Animate cartoon."                      , SETFLAG },
+   ( char * ) 0 } ;
+
+
+int        frameheight,    framewidth,    frames,    framebytes ;
+int     Newframeheight, Newframewidth, Newframes, Newframebytes ;
+
+int        rows,    cols,    numframes ;
+int     Newrows, Newcols, Newnumframes ;
+
+int     samplerate  ;
+int     frstep      ;
+int     application ;
+int     startbytes  ;
+int     frshift     ;
+int     Transpose   ;
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE   *fp ;
+    char   *header, *Header() ;
+    short  *frame, *endframe ;
+    char   *val1, *val2 ;
+    int     i,j,k, a,b ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    if ( ( header = ReadHeader( fp ) ) == (char *) 0 ) {
+	fprintf( stderr, "edframe: header not found\n" ) ;
+	exit( 1 ) ;
+    }
+    frameheight = HeaderInt( header, "frameheight" );
+    framewidth  = HeaderInt( header, "framewidth"  );
+    frames      = HeaderInt( header, "frames"      );
+    samplerate  = HeaderSamplerate( header );
+
+    if ( ( application = Applic( header) ) < 0 ) {
+	fprintf(stderr,"bufframe: application name not found in header\n" ) ;
+	exit( 1 ) ;
+    }
+    if ( Format( application ) != NAP ) {
+	fprintf(stderr,"bufframe: buffer for %s format not implemented\n", gen_applics[application] ) ;
+	exit( 1 ) ;
+    }
+    frame_to_matrix( NAP, &rows, &cols, &numframes, frameheight, framewidth, frames ) ;
+
+    Transpose    = ison( transtr ) ;
+    frstep       = to_p( shiftstr, samplerate ) ;
+    Newrows      = frameheight ;
+    Newcols      = to_p( widthstr, samplerate ) ;
+    Newnumframes = ( cols - Newcols ) / frstep + 1 ;    /* since: Newcols + ( Newnumframes - 1 ) * frstep <= cols */
+
+
+    /* Get limits on specified number of frames */
+
+    if ( getvals( framestr, &val1, &val2, "-" ) == BADVAL ) {
+	fprintf(stderr,"bufframe: bad frame selector [%s]\n", framestr ) ;
+	exit( 1 ) ;
+    }
+    if      ( ismin( val1 ) ) a = 0 ;
+    else if ( ismax( val1 ) ) a = Newnumframes - 1 ;
+    else if ( Units( val1 ) ) a = (int)to_p( val1, samplerate ) / frstep ;
+    else                      a = atoi( val1 ) ;
+
+    if ( isempty( val2 ) )    b = a ;
+    else if ( ismin( val2 ) ) b = 0 ;
+    else if ( ismax( val2 ) ) b = Newnumframes - 1 ;
+    else if ( Units( val2 ) ) b = (int)to_p( val2, samplerate ) / frstep ;
+    else                      b = atoi( val2 ) ;
+
+    if (a<0 || b>=Newnumframes || a>b) {
+	if ( b>=Newnumframes ) fprintf(stderr,"bufframe: bad frame selector [%d frames needed but %d available]\n", b+1, Newnumframes );
+	else                fprintf(stderr,"bufframe: bad frame selector \n" );
+	exit(1);
+    }
+
+    Newnumframes = b - a + 1 ;
+
+    framebytes   = Newrows * ( Newcols + ( Newnumframes - 1 ) * frstep ) * sizeof(short) ;
+
+    if ( Transpose )
+	matrix_to_frame( SAI, Newcols, Newrows, Newnumframes, &Newframeheight, &Newframewidth, &Newframes ) ;
+    else
+	matrix_to_frame( SAI, Newrows, Newcols, Newnumframes, &Newframeheight, &Newframewidth, &Newframes ) ;
+
+    Newframebytes  = Newframeheight * Newframewidth * sizeof(short) ;
+
+    if ( ison( headerstr ) )
+	WriteHeader( Header( header ), stdout ) ;
+
+
+    /* Allocate space for framebytes of data */
+
+    if ( ( frame = (short *)malloc( framebytes ) ) == NULL ) {
+	fprintf( stderr, "bufframe: malloc out of space\n" ) ;
+	exit( 1 ) ;
+    }
+
+    frshift = frstep * rows ;
+
+    /* Seek past `a' frames in blocks of framebytes */
+
+    startbytes = a * frshift * sizeof(short) ;
+    for (i=framebytes ; i < startbytes ; i += framebytes)
+	if ( fread( frame, framebytes, 1, fp ) == NULL ) {
+	    fprintf(stderr,"bufframe: missing data after header\n");
+	    exit(1);
+	}
+    if ( (startbytes -= (i - framebytes)) > 0 )
+	if ( fread( frame, startbytes, 1, fp ) == NULL ) {
+	    fprintf(stderr,"bufframe: missing data after header\n");
+	    exit(1);
+	}
+
+    /* Read framebytes of data */
+
+    if ( fread( frame, framebytes, 1, fp ) == NULL ) {
+	fprintf(stderr,"bufframe: insufficient data after header\n");
+	exit(1);
+    }
+    fclose( fp ) ;
+
+    endframe = frame + Newframes * frshift ;
+
+    fprintf(stderr,"bufframe: %d frames   [height=%d  width=%d]\n", Newnumframes, Newframeheight, Newframewidth );
+
+    if ( ison( debugstr ) ) {
+	fprintf( stderr,"   frameheight=%3d    framewidth=%3d       frames=%3d    framebytes=%d\n",     frameheight,    framewidth,    frames,    framebytes ) ;
+	fprintf( stderr,"Newframeheight=%3d Newframewidth=%3d    Newframes=%3d Newframebytes=%d\n",  Newframeheight, Newframewidth, Newframes, Newframebytes ) ;
+	fprintf( stderr,"          rows=%3d          cols=%3d    numframes=%d\n",     rows,    cols,    numframes ) ;
+	fprintf( stderr,"       Newrows=%3d       Newcols=%3d Newnumframes=%d\n",  Newrows, Newcols, Newnumframes ) ;
+	fprintf( stderr,"frstep=%d  startbytes=%d frshift=%d\n",  frstep, startbytes, frshift ) ;
+	exit( 1 ) ;
+    }
+
+    if ( Transpose ) {
+
+	for (  ; frame < endframe ; frame += frshift )
+	    for ( j=0 ; j < Newcols ; j++ )
+		fwrite( frame + j*frameheight, sizeof(short), Newrows, stdout ) ;
+    }
+
+    else {
+	for (  ; frame < endframe ; frame += frshift )
+	    for (j=0 ; j < Newrows ; j++)
+		for (k=0 , i=j ; k < Newcols ; k++, i+=frameheight)
+		    fwrite( &frame[i], sizeof(short), 1, stdout );
+    }
+    fprintf(stderr,"bufframe: done\n" );
+}
+
+
+
+/* Return 1 if the str has appended units. Otherwise return 0.             */
+/* (A freqency specifier with no units is interpreted as a channel number) */
+
+Units(str)
+char *str ;
+{
+    char *eptr = str + strlen( str ) ;
+
+    if( isdigit( *--eptr ) ) return 0 ; /* last char is digit, so no units */
+    else return 1 ;
+}
+
+
+/*
+   Copy the original (NAP format) header to a new sai header, changing in order:
+     frstep
+     frames
+     framewidth
+     frameheight
+     framebytes
+     animate
+     display
+   Copy application name "sai" into the version string.
+   Finally, update the new header_bytes, and return the new header.
+*/
+
+char *Header( oldheader )
+char *oldheader ;
+{
+    char *saiheader;
+    char *p0, *p1, *p2, *s, str[64];
+
+    saiheader = (char *)malloc( strlen(oldheader) + 256 ) ;
+
+    p0 = saiheader ;
+    p1 = oldheader ;
+
+    /* copy to first item after the header_bytes */
+
+    p2 = HeaderString( oldheader , "header_bytes" ) ;
+    while( p1 < p2 )
+	*p0++ = *p1++ ;
+    while (*p1 != '\n')
+	*p0++ = *p1++ ;
+    *p0++ = *p1++;
+
+    /* insert frstep_aid at top of new header */
+
+    sprintf( str,"frstep_aid=%s\n", shiftstr ) ;
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+
+
+    /** copy up to channels_afb (if transpose changes apparent number of channels) **/
+
+    if ( Transpose ) {
+	p2 = HeaderString( oldheader , "channels_afb" ) ;
+	while( p1 < p2 )
+	    *p0++ = *p1++ ;
+
+	sprintf(str,"%d\n", Newframeheight);
+	for (s = str ; *s != '\n' ; )
+	    *p0++ = *s++;
+	*p0++ = *s;
+	while (*p1 != '\n')
+	    *p1++;
+	*p1++;
+    }
+
+
+    /** copy up to frames **/
+
+    p2 = HeaderString( oldheader , "frames" ) ;
+    while( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframes);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to framewidth **/
+
+    p2 = HeaderString( oldheader , "framewidth" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframewidth);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to frameheight **/
+
+    p2 = HeaderString( oldheader , "frameheight" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframeheight);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to framebytes **/
+
+    p2 = HeaderString( oldheader , "framebytes" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframebytes);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to animate_ctn **/
+
+    p2 = HeaderString( oldheader , "animate_ctn" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%s\n", anistr );
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to display **/
+
+    p2 = HeaderString( oldheader , "display" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%s\n", dispstr );
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy rest of header **/
+
+    p2 = HeaderString( oldheader , "Version" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+       /** ( copy application name "sai" into header ) **/
+
+    if ( ( p2 = ApplicString( oldheader ) ) == (char *)0 )  {
+	fprintf(stderr,"bufframe: application name not found in header\n");
+	exit( 1 ) ;
+    }
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    *p0++ = 's' ; *p0++ = 'a' ; *p0++ = 'i' ;
+    p1 += 3 ;
+
+    while (*p1 != '\n')
+	*p0++ = *p1++ ;
+    *p0++ = *p1++ ;
+
+
+    /** update header_bytes **/
+
+    sprintf(str, "%0*d", 7, p0-saiheader);
+    p0 = HeaderString( saiheader , "header_bytes" ) ;
+    s = str;
+    while(*p0 != '\n')
+	*p0++ = *s++ ;
+
+
+    return saiheader;
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/bufwave.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,222 @@
+/*
+  bufwave.c      a shifting waveform buffer.
+  ---------
+
+  A buffer (or window) is shifted along the input, and the
+  contents of the buffer are written to the stdout on each shift.
+
+  Input is buffered in frames of size `width' samples, and the buffer is
+  shifted along the input in steps of `frstep' samples.
+  Both `width' and `frstep' may be given with time units (s or ms), in which
+  case the they are converted to a number of samples using the given
+  `samplerate' option.
+
+  The `type' option sets the size of a binary sample in bytes.
+  Standard type names are recognised (char, short, int, float, double).
+  For example, type=1 is synonymous with type=char, both specifying a
+  binary sample of 1 byte.
+
+  The special case of type=ASCII sets a sample to be a line of ASCII text
+  (delimited by a CR), of size up to a maximum number of characters set by
+  the `length' option.
+
+  The `frame' option selects a sequence of contiguous frames for output by:
+	frame=a[-b]
+  where `a' and `b' are frame numbers: 1,2,3,...
+  The upper limit `b' is optional, and when it is missing then the frame
+  sequence is a single frame, otherwise `a' and `b' are inclusive limits.
+  The strings "min" and "max" are recognised as extreme limits.
+
+  The `start' option is an offset to the start of the first frame in samples.
+  If given with time units, the start is converted to samples using the
+  given `samplerate' option.
+
+  The `reverse' option causes each buffer to be written out in reverse order
+  of its samples.
+
+  For example, if a file foo contains a sequence of frames, each 75 samples
+  long, then to reverse the contents of each frame do:
+
+	bufwave rev=on width=75 frstep=75 foo
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[]     = "shifting waveform buffer." ;
+
+static char *helpstr, *debugstr, *fstr, *bstr, *nstr, *ostr, *sstr, *sampstr, *rstr, *lenstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                              , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                  , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "                       , VAL     },
+    {   "frame"     ,   "1-max"     ,  &fstr        ,   "select frames inclusively"         , VAL     },
+    {   "width"     ,   "10ms"      ,  &nstr        ,   "frame width"                       , VAL     },
+    {   "frstep"    ,   "0"         ,  &ostr        ,   "frame step (ie. shift)"            , VAL     },
+    {   "start"     ,   "0"         ,  &sstr        ,   "offset to start first frame"       , VAL     },
+    {   "type"      ,   "short"     ,  &bstr        ,   "data type or size in bytes"        , VAL     },
+    {   "reverse"   ,   "off"       ,  &rstr        ,   "write each frame in reverse"       , SETFLAG },
+    {   "length"    ,   "256"       ,  &lenstr      ,   "max line length in chars"          , SVAL    },
+   ( char * ) 0 } ;
+
+
+int   samplerate ;
+int   width      ;
+int   frstep     ;
+int   overlap    ;
+int   start      ;
+int   reverse    ;
+
+main (argc, argv)
+int    argc;
+char **argv;
+{
+    FILE  *fp ;
+    char  *buf, **linebuf ;
+    int    m, bytes ;
+    int    a, b, f, i, j, k0, k1 ;
+    int    helpdatatype() ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts1( helpstr, argv[0], applic, option, helpdatatype ) ;
+
+    samplerate = to_Hz( sampstr ) ;
+    width      = to_p( nstr, samplerate ) ;
+    frstep     = to_p( ostr, samplerate ) ;
+    start      = to_p( sstr, samplerate ) ;
+    reverse    = ison( rstr ) ;
+    overlap    = width - frstep ;
+
+    if ( ( bytes = databytes( bstr ) ) < 0 ) {
+	fprintf( stderr, "bufwave: bad type [%s]\n", bstr ) ;
+	exit( 1 ) ;
+    }
+
+    if ( selector( fstr, &a, &b ) == 0 ) {
+	fprintf(stderr,"bufwave: bad frame selector [%s]\n", fstr ) ;
+	exit( 1 ) ;
+    }
+
+    if ( ison( debugstr ) ) {
+	printf("width=%d frstep=%d start=%d bytes=%d samplerate=%d reverse=%d a=%d b=%d \n",
+		width, frstep, start, bytes, samplerate, reverse, a, b );
+	exit(0);
+    }
+
+
+    if (bytes > 0) {    /* binary objects of size `bytes' */
+
+	/* Allocate space for frame buffer */
+	if ( ( buf = (char *)malloc( width*bytes ) ) == (char *)0 ) {
+	    fprintf( stderr, "bufwave: cannot allocate %d * %d bytes\n", width, bytes ) ;
+	    exit( 1 ) ;
+	}
+
+	/* Seek to start, past start*bytes and a-1 frame shifts of frstep*bytes */
+
+	if ( start>0 && seekstart( start, bytes, fp ) < start ) {
+	    fprintf(stderr,"bufwave: seek overshot end-of-file\n");
+	    exit(1);
+	}
+	for (f=1 ; f<a  && fread(buf,bytes,frstep,fp) ; f++)
+	    ;
+
+	/* Buffer b-a+1 frames (or the remainder if b==0) */
+	m = fread(buf, bytes, width, fp);   /* m enables oversizing single frames for direct reversing */
+	if ( reverse )
+	    for (k0=m-1 ; k0>=0 && fwrite(&buf[(k0)*bytes], bytes, 1, stdout) ; --k0)
+		;
+	else
+	    fwrite(buf, bytes, m, stdout);
+
+	k0 = k1 = 0;
+	for (i=width, f++ ; k0 == k1 && (f<=b || b==0) ; i+=width, f++) {
+	    for (k0=i, k1=i+frstep ; k0<k1 && fread(&buf[(k0%width)*bytes], bytes, 1, fp) ; k0++)
+		;
+	    i -= overlap ;
+	    if (k0 == k1) {
+		if ( reverse )  /* write out in reverse */
+		    for (k0=i+width-1, k1=i-1 ; k0>k1 && fwrite(&buf[(k0%width)*bytes], bytes, 1, stdout) ; --k0)
+			;
+		else        /* write out correct order */
+		    for (k0=i, k1=i+width ; k0<k1 && fwrite(&buf[(k0%width)*bytes], bytes, 1, stdout) ; k0++)
+			;
+	    }
+	}
+    }
+
+    else {      /* ASCII objects of size lines up to lenstr chars */
+
+	/* Allocate space for `width' lines */
+	bytes = atoi( lenstr ) ;
+	if ( ( linebuf = (char **)malloc( width * sizeof( char * ) ) ) == (char **)0 ) {
+	    fprintf( stderr, "bufwave: cannot allocate %d * sizeof( char * )\n", width ) ;
+	    exit( 1 ) ;
+	}
+	for ( i = 0 ; i < width ; i++)
+	    if ( ( linebuf[i] = (char *)malloc( bytes ) ) == (char *)0 ) {
+		fprintf( stderr, "bufwave: cannot allocate %d bytes %d times\n", bytes, i+1 ) ;
+		exit( 1 ) ;
+	    }
+
+	/* Seek to start, past start*bytes and frstep*a-1 lines */
+	for (i=0 ; i<start && fgets( *linebuf, bytes, fp ) ; i++)
+	    ;
+	if (i<start) {
+	    fprintf(stderr,"bufwave: seek overshot end-of-file\n");
+	    exit(1);
+	}
+	m = frstep * ( a-1 ) ;
+	for (i=0 ; i<m  && fgets( *linebuf, bytes, fp ) ; i++)
+	    ;
+	if ( m > 0 )  f = m/frstep + 1 ;
+	else          f = 1 ;
+
+	/* Buffer b-a+1 lines (or the remainder if b==0) */
+	/* (m enables oversizing single frames for direct reversing) */
+	for ( m = 0 ; m < width && fgets( linebuf[m], bytes, fp ) ; m++ )
+	    ;
+	if ( reverse )
+	    for (k0=m-1 ; k0>=0 ; --k0)
+		fputs( linebuf[k0], stdout ) ;
+	else
+	    for (k0=0 ; k0<m ; k0++)
+		fputs( linebuf[k0], stdout ) ;
+
+	k0 = k1 = 0;
+	for (i=width, f++ ; k0 == k1 && (f<=b || b==0) ; i+=width, f++) {
+	    for (k0=i, k1=i+frstep ; k0<k1 && fgets( linebuf[k0%width], bytes, fp ) ; k0++)
+		;
+	    i -= overlap ;
+	    if (k0 == k1) {
+		if ( reverse )  /* write out in reverse */
+		    for (k0=i+width-1, k1=i-1 ; k0>k1 ; --k0)
+			fputs( linebuf[k0%width], stdout ) ;
+		else        /* write out correct order */
+		    for (k0=i, k1=i+width ; k0<k1 ; k0++)
+			fputs( linebuf[k0%width], stdout) ;
+	    }
+	}
+    }
+
+}
+
+
+helpdatatype()
+{
+    fprintf(stderr,"\ndata types:       \n");
+    fprintf(stderr,"            char    \n");
+    fprintf(stderr,"            short   \n");
+    fprintf(stderr,"            int     \n");
+    fprintf(stderr,"            float   \n");
+    fprintf(stderr,"            double  \n");
+    fprintf(stderr,"            <number>  (sizeof binary object in bytes)  \n" ) ;
+    fprintf(stderr,"            ASCII     (lines of up to %d characters)   \n", atoi( lenstr ) ) ;
+    exit( 1 ) ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/chi.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,79 @@
+/*
+    chi.c       repetitative chi-squared curve.
+
+Examples:
+
+chi amp=500 asym=1 per=4ms | x11plot
+chi amp=500 asym=1 per=16ms | x11plot -n512
+chi amp=500 asym=4 per=16ms | x11plot -n512
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[]  = "generate a repeated chi-squared waveform. " ;
+char usage[]   = "chi [options]" ;
+
+static char *helpstr, *debugstr, *sampstr, *perstr, *astr, *asymstr, *dstr, *datastr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                     , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"         , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "              , VAL     },
+    {   "period"    ,   "8ms"       ,  &perstr      ,   "period [s,ms,p] of repetition"  , VAL     },
+    {   "amplitude" ,   "1024"      ,  &astr        ,   "amplitude of waveform"    , VAL     },
+    {   "asymmetry" ,   "1.0"       ,  &asymstr     ,   "parameter controlling assymmetry (>=1)"      , VAL     },
+    {   "duration"  ,   "500ms"     ,  &dstr        ,   "duration of waveform"     , VAL     },
+    {   "datatype"  ,   "short"     ,  &datastr     ,   "o/p datatype (short/float)", VAL     },
+   ( char * ) 0 } ;
+
+
+#define e   ( 2.718 )
+
+int     samplerate ;
+int     amplitude  ;
+int     duration   ;
+int     period     ;
+float   a          ;
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    int    i, n, t ;
+    short  s ;
+    float  f ;
+    float  b ;
+    float  r = 4 ;
+
+    getopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts3( helpstr, argv[0], applic, usage, option ) ;
+
+    samplerate = to_Hz( sampstr, 0 ) ;
+    amplitude  = atoi( astr ) ;
+    period     = (int)to_p( perstr, samplerate ) ;
+    a          = atof( asymstr ) ;
+    duration   = to_p( dstr, samplerate )   ;
+
+    b = ( 2. * a ) / period ;   /* sets mode at half-way to period */
+
+    if ( iststr( datastr, "short" ) )
+	for ( i=0 ; i<duration ;  )
+	    for ( t=0 ; t<period*r && i<duration ; t+=r, i++ ) {
+		s = amplitude * pow( (double)( ( e * b * t ) / a ), (double)a ) * exp( -(double)( b * t ) ) ;
+		fwrite( &s, sizeof(short), 1, stdout ) ;
+	    }
+    else if ( iststr( datastr, "float" ) )
+	for ( i=0 ; i<duration ;  )
+	    for ( t=0 ; t<period && i<duration ; t++, i++ ) {
+		f = amplitude * pow( (double)( ( e * b * t ) / a ), (double)a ) * exp( -(double)( b * t ) ) ;
+		fwrite( &f, sizeof(float), 1, stdout ) ;
+	    }
+    else
+	fprintf(stderr,"unknown datatype [%s]\n", datastr) ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/conv.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,128 @@
+/*
+  conv.c  Convolution.  [NR: 407-413].
+  ------
+
+  Usage:  conv [options]  signal_file  response_file
+
+  The response of a linear filter to an arbitiary input signal is the
+  convolution of the signal with the filter's impulse response.
+  The `response_file' contains the impulse response which characterises the
+  filter, and the result of the convolution operation is the response of
+  that filter to the signal contained in the `signal_file'.
+
+  The program uses the FFT to transform both input files, and then obtains
+  the convolution by multiplying in the frequency domain, and inverse
+  transforming the result.
+
+Eg:
+
+ptrain > foo1                               -signal
+gauss -b5 | op type=float mult=500 > foo3   -response
+conv factor=.0005 foo1 foo3 | x11plot
+
+Deconv doesn't seem to work !
+*/
+
+
+#include <stdio.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/dir.h>
+#include <sys/stat.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+#include "sigproc.h"
+
+char applic[]     = "Convolution. \n i/p and o/p signal in binary shorts, impulse response file in floats." ;
+char usage[]      = "conv [options] signal_file  response_file" ;
+
+static char *helpstr, *debugstr, *sampstr, *lenstr, *domstr,  *scalestr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"         ,  &helpstr     ,   "help"                                  , DEBUG   },
+    {   "debug"     ,   "off"         ,  &debugstr    ,   "debugging switch"                      , DEBUG   },
+    {   "samplerate",   "20kHz"       ,  &sampstr     ,   "samplerate "                           , VAL     },
+    {   "length"    ,   "max"         ,  &lenstr      ,   "Size of input."                        , VAL     },
+    {   "domain"    ,   "time"        ,  &domstr      ,   "Convolve in time or frequency domain"  , VAL     },
+    {   "scale"     ,   "1.0"         ,  &scalestr    ,   "scale factor for output"               , VAL     },
+   ( char * ) 0 } ;
+
+
+int     samplerate  ;
+float   scale       ;
+
+short  *signal      ;
+float  *response    ;
+float  *out         ;
+
+main (argc, argv)
+int     argc;
+char  **argv;
+{
+    FILE     *fp1, *fp2  ;
+    struct    stat  stbuf ;
+    int       i, n, m ;
+    float     f ;
+
+    if ( getopts( option, argc, argv ) != 2 || !isoff( helpstr ) )
+	helpopts3( helpstr, argv[0], applic, usage, option ) ;
+
+    samplerate = to_Hz( sampstr ) ;
+    scale      = atof( scalestr ) ;
+
+    if ( ( fp1 = fopen( argv[argc-2], "r" ) ) == (FILE *)0 ) {
+	fprintf( stderr,"%s: can't open %s\n", argv[0], argv[argc-2] ) ;
+	exit( 1 ) ;
+    }
+    stat( argv[argc-2], &stbuf ) ;
+    if ( ismax( lenstr ) )
+	n = stbuf.st_size / sizeof( short ) ;       /* size of signal file */
+    else if ( ( n = to_p( lenstr,  samplerate ) ) > stbuf.st_size / sizeof( short ) ) {
+	fprintf( stderr,"conv: insufficient signal\n");
+	exit( 1 ) ;
+    }
+
+
+    if ( ( fp2 = fopen( argv[argc-1], "r" ) ) == (FILE *)0 ) {
+	fprintf( stderr,"%s: can't open %s\n", argv[0], argv[argc-1] ) ;
+	exit( 1 ) ;
+    }
+    stat( argv[argc-1], &stbuf ) ;
+    m = stbuf.st_size / sizeof( float ) ;       /* size of response file */
+
+    if ( m > n ) {      /* size of response file must <= signal file */
+	fprintf( stderr,"conv: size of response file must be <= size of signal file\n" ) ;
+	exit( 1 ) ;
+    }
+
+    signal   = (short *)malloc( n * sizeof(short) ) ;
+    response = (float *)malloc( m * sizeof(float) ) ;
+    out      = (float *)malloc( n * sizeof(float) ) ;
+
+    fread( signal,   sizeof(short), n, fp1 ) ;
+    fread( response, sizeof(float), m, fp2 ) ;
+    fclose( fp1 ) ; fclose( fp2 ) ;
+
+
+    if ( iststr( domstr, "time" ) )
+	convolve_time( signal, n, response, m, out ) ;
+
+    else if ( iststr( domstr, "frequency" ) )
+	convolve_freq( signal, n, response, m, out ) ;
+
+    else {
+	fprintf( stderr,"conv: unknown domain [%s]\n", domstr ) ;
+	exit( 1 ) ;
+    }
+
+
+    if ( ( f = ftos( out, signal, n, scale ) ) < 1. )
+	fprintf( stderr,"Warning: 16-bit overflow during convolution. Try scale factor < %f\n", f ) ;
+
+    fwrite( signal, sizeof(short), n, stdout ) ;
+
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/convert.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,113 @@
+/*
+ convert.c
+-----------
+Convert <number><units> to new units given by the "to" option.
+<units> are:
+	p       sample points
+	s       time in seconds
+	ms      time in millisecs
+	Hz      frequency in Hz
+	kHz     frequency in kHz
+
+Time in seconds or miliseconds is converted to and from sample points using
+the given samplerate. Time (in seconds, miliseconds or samples) is converted
+to and from frequency by reciprocal.
+
+Example:
+
+Convert 100 samples to time in ms, and the 10ms to a number of samples, both
+at the default sample-rate of 20kHz. Then at a sample-rate of 10kHz print
+the number of samples in 32ms.
+
+    convert to=ms 100p to=p 10ms samplerate=10kHz to=p 32ms
+
+Convert 0.1 seconds to sample points.
+
+    convert -topoints 0.1sec
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[] = "Convert units: frequency, time, and sample numbers." ;
+char usage[]  = "convert [options] arguments " ;
+
+static char *helpstr, *debugstr, *sampstr, *tostr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                          , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"              , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "                   , VAL     },
+    {   "to"        ,   "points"    ,  &tostr       ,   "convert to <units>"            , VAL     },
+   ( char * ) 0 } ;
+
+
+int  samplerate ;
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    int  i, helpunits() ;
+
+    i = argc ;
+    while ( i > 0 ) {
+
+	if ( i == argc )        /* first time, to account for prog name */
+	    i = getopts( option, i, &argv[argc-i] ) ;
+	else                    /* subsequent times */
+	    i = getopts( option, i+1, &argv[argc-i-1] ) ;
+	if ( !isoff( helpstr ) )
+	    helpopts2( helpstr, argv[0], applic, usage, option, helpunits ) ;
+
+	samplerate = to_Hz( sampstr, 0 ) ;
+
+	for(  ; i > 0 && !isopt( argv[argc-i] ) ; --i )
+	    convert( argv[argc-i] ) ;
+    }
+}
+
+
+convert( s )
+char *s ;
+{
+    switch ( listindex( units, tostr ) ) {
+	case (-2) : fprintf(stderr,"ambiguous units [%s]\n", tostr ) ;
+		    exit( 1 ) ;
+	case (-1) : fprintf(stderr,"unknown units [%s]\n", tostr ) ;
+		    exit( 1 ) ;
+	case   0  : /* to points */
+		    printf( "%dp\n"   , (int)to_p( s, samplerate  ) ) ;
+		    break ;
+	case   1  : /* to seconds */
+		    printf( "%.3fs\n"   , to_s( s, samplerate  ) ) ;
+		    break ;
+	case   2  : /* to ms */
+		    printf( "%.3fms\n"  , to_ms( s, samplerate ) ) ;
+		    break ;
+	case   3  : /* to Hz */
+		    printf( "%.3fHz\n"  , to_Hz( s, samplerate   ) ) ;
+		    break ;
+	case   4  : /* to kHz */
+		    printf( "%.3fkHz\n" , to_kHz( s, samplerate  ) ) ;
+		    break ;
+	case   5  : /* to ERB */
+		    printf( "%.3ferb\n" , to_erb( s ) ) ;
+		    break ;
+    }
+}
+
+
+helpunits()
+{
+    fprintf(stderr,"\nunits: \n");
+    fprintf(stderr,"            points      sample points     \n");
+    fprintf(stderr,"            seconds     time in seconds   \n");
+    fprintf(stderr,"            ms          time in millisecs \n");
+    fprintf(stderr,"            Hz          frequency in Hz   \n");
+    fprintf(stderr,"            kHz         frequency in kHz  \n");
+    exit( 1 ) ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cosine.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,102 @@
+/*
+    cosine.c    generate a cosine window
+    --------
+
+    1. Hann (or raised cosine) window
+
+	w[n] = 0.5 [ 1 - cos( TWOPI . n/(N-1) ) ]
+
+    2. Hamming window
+
+	w[n] = 0.54 - 0.46 cos( TWOPI . n/(N-1) )
+
+    Both windows are defined for 0 <= n <= N-1 and are zero otherwise.
+
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+#include "sigproc.h"
+
+
+char applic[]     = "generate a cosine window." ;
+
+static char *helpstr,  *debugstr, *sampstr,  *hammstr ;
+static char *scalestr, *typestr,  *sizestr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                      , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                          , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "                               , VAL     },
+    {   "size"      ,   "10ms"      ,  &sizestr     ,   "Size of window"                            , VAL     },
+    {   "Hamming"   ,   "off"       ,  &hammstr     ,   "Hamming window (default raised cosine)"    , SETFLAG },
+    {   "scale"     ,   "1000"      ,  &scalestr    ,   "Scale factor for output"                   , VAL     },
+    {   "type"      ,   "short"     ,  &typestr     ,   "Output datatype (short/float)"             , VAL     },
+   ( char * ) 0 } ;
+
+
+int     samplerate  ;
+
+float  *window ;
+int     n      ;
+
+short  *buf    ;
+
+
+main (argc, argv)
+int     argc;
+char  **argv;
+{
+    float f ;
+
+    getopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    samplerate = to_Hz( sampstr ) ;
+    n          = to_p( sizestr, samplerate ) ;
+
+    if ( ison( hammstr ) )
+	window = hamming( n ) ;
+
+    else if ( isoff( hammstr ) )
+	window = raised_cosine( n ) ;
+
+    else {
+	fprintf(stderr,"cosine: unknown window [%s]\n", hammstr) ;
+	exit( 1 ) ;
+    }
+
+    if ( iststr( typestr, "float" ) ) {
+	scalar( window, n, atof( scalestr ) ) ;
+	fwrite( window, sizeof(float), n, stdout ) ;
+    }
+
+    else if ( iststr( typestr, "short" ) ) {
+	buf = (short *)malloc( n * sizeof(short) ) ;
+	if ( ( f = ftos( window, buf, n, atof( scalestr ) ) ) < 1. )
+	    fprintf( stderr,"Warning: 16-bit overflow. Try scale factor < %f\n", f ) ;
+	fwrite( buf, sizeof(short), n, stdout ) ;
+    }
+
+    else
+	fprintf(stderr,"cosine: unknown datatype [%s]\n", typestr) ;
+}
+
+
+scalar( y, n, scale )
+float  *y ;
+int     n ;
+float   scale ;
+{
+    int  i ;
+
+    if ( scale != 1. ) {
+	for ( i=0 ; i < n ; i++ )
+	    y[i] *= scale ;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/edframe.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,754 @@
+/*
+ edframe.c    Edit (ie. partition) AIM output files.
+----------
+
+ The input file must have a model header.
+
+ Usage: edframe  [[-]frame=a[-b]]  [[-]time=a[-b]]  [[-]freq=a[-b]]  [file]
+
+ Special arguments:
+
+ -help        Print help on stderr.
+ -info        Print frame size information on the stdout.
+  info=fbank  Print channel centre-frequency information for the selected
+	      range of frequencies on the stdout. (This information is based
+	      on the filterbank parameters given in the input header).
+
+ Each input frame is a matrix with (0,0) in the bottom left.
+ The partition, output for each frame, is a sub-matrix indexed by rows a-to-b
+ and columns a-to-b inclusive.
+ The partition is specified using args: freq=a-b (rows) and time=a-b (cols).
+ A single row or col is specified using a single number: freq=a or time=a.
+ Rows (channels) are numbered 0,1,...,frameheight-1  -(lowest freq first).
+ Cols (samples)  are numbered 0,1,...,framewidth-1.
+ The strings "min" and "max" can be used as selectors, meaning eg:
+	freq=a-max   rows a to frameheight-1
+	freq=min-b   rows 0 to b
+	time=a-max   cols a to framewidth-1
+	time=min-b   cols 0 to b
+ The default selector specifies the whole matrix:
+	freq=min-max time=min-max
+
+ Expressing time as cols (along the horizontal axis) and frequency as rows
+ (up the vertical axis) applies to most gen programs with the exception of
+ genwav (where the vertical axis contains just one wave), and the excitation
+ patterns genasa, genepn, and gensep (where frequency is measured as cols
+ along the horizontal axis). The horizontal dimension is controlled by the
+ "freq" parameter for excitation patterns.
+
+ The units of the freq selector are Hz or kHz, specifying a range of channels
+ in terms of frequency, or if no units are appended, then the selector is
+ interpreted as a channel number in the range 0 to frameheight-1.
+ When the freq selector is given with frequency units, then the "closest"
+ corresponding channel number is used. (This depends upon the parameters
+ mincf_afb, maxcf_afb, and dencf_afb as given in the header).
+
+ The units of the time selector are s or ms, specifying a range of samples
+ in terms of time, (seconds and milliseconds respectively), or if no units
+ are appended, then the selector is interpreted as a sample number in the
+ range 0 to framewidth-1.
+
+
+ When the input consists of a cartoon of multiple frames (eg gensai output)
+ then individual frames or subsequences of frames may be selected from the
+ input using [[-]frame=a[-b]].
+ Input frames  are numbered 0,1,2,...,frames-1
+   frame=a      Select just the a'th frame.
+   frame=a-b    Select frames from the a'th to b'th inclusive.
+ The strings "min" and "max" can be used as selectors, meaning eg:
+   frame=min    Select the first frame.
+   frame=max    Select the last frame.
+   frame=a-max  Select frames from the a'th to the last inclusive.
+   frame=min-b  Select frames from the first to the b'th inclusive.
+ The default selector is for all frames, (ie frame=min-max).
+
+ The units of the frame selector are s or ms, each specifying a frame which
+ is "closest" to the given time, being the frame number which is the greatest
+ integer multiple of the framestep (frstep_aid) which does not exceed the
+ given time, measured from the start of the input file.
+ If no units are appended, then the selector is interpreted as a frame number.
+
+ The output frames are preceded by a model header, so that the partition for
+ each frame can be plotted using the option "useprevious=on".
+
+ The "Header" option controls the output of the modified header. When it is
+ set Header=off then a header is not output.
+
+ The "Transpose" option is a matrix transpose (swap rows and columns) of the
+ output partition of each input frame.
+ When a frame partition has a height greater than it's width (ie. cols < rows)
+ then setting Transpose=on may provide a preferable display orientation.
+ For example, this enables a very narrow (eg. single column) time-slice to be
+ plotted horizontally, so that a time-slice of filterbank output may be
+ plotted as a spectrum on a horizontal frequency axis.
+
+
+Examples:
+---------
+
+Edited output may be displayed using the "useprevious" option, for example:
+
+  genXXX  ...  output=stdout  file1  |  edframe  ...  >  file2.XXX
+  genXXX  useprevious=on file2
+
+Note that that file2.XXX must have a different base-name to the genXXX input
+(file1) because genXXX will remove any file1.XXX as a side-effect.
+
+
+Information on the output is printed on the stdout. For example:
+Print size information for gensai output for all frames.
+
+  gensai output=stdout ... | edframe -info
+
+Print channel centre-frequency information for genbmm output for the 1kHz
+channel, and then for channel numbers 37 to 50.
+(To print the exact centre-frequency occupied by a given channel).
+
+  genbmm output=stdout ... | edframe info=fbank freq=1kHz
+  genbmm output=stdout ... | edframe info=fbank freq=37-50
+
+
+Selecting particular frames from AIM output.
+-------------------------------------------
+
+1. Plot gennap output and its transpose.
+
+  gennap output=stdout ... | edframe         >  file1.sai
+  gennap output=stdout ... | edframe Tran=on >  file2.sai
+  gensai useprevious=on file1
+  gensai useprevious=on file2
+
+2. Select and plot frame 2 (ie. the 3rd frame) of gensai output.
+
+  gensai output=stdout ... | edframe frame=2  >  file.sai
+  gensai useprevious=on file
+
+3. Select the frames of gensai output which start between 16ms and 47ms from
+   the start of it's input. (When the option frstep_aid=16ms then this would
+   select the 2nd and 3rd frames).
+
+  gensai output=stdout ... | edframe frame=16ms-47ms >  file.sai
+
+4. Select the 5th to the last frame inclusively of gensai output.
+
+  gensai output=stdout ... | edframe frame=4-max  >  file.sai
+
+5. Select the first frame of genepn output and plot the spectrum.
+
+  genepn output=stdout ... | edframe frame=min > file1.epn
+  genepn useprevious=on file1
+
+
+Editing frames to select particular frequency ranges or channels (ie rows).
+--------------------------------------------------------------------------
+
+6. Select and plot the channel with centre-frequency closest to 1kHz from
+   gennap output.
+
+  gennap output=stdout ... | edframe freq=1kHz  >  file.nap
+  gennap useprevious=on file
+
+7. Select and plot channel 40 then the channel with the lowest and then
+   the highest centre-frequency over all frames of gensai output.
+
+  gensai output=stdout ... | edframe freq=40  >  file.sai
+  gensai useprevious=on file
+
+  gensai output=stdout ... | edframe freq=min  >  file.sai
+  gensai useprevious=on file
+
+  gensai output=stdout ... | edframe freq=max  >  file.sai
+  gensai useprevious=on file
+
+8. Select and plot all channels of genbmm output from channel 10 to
+   the channel with centre-frequency closest to 1kHz inclusively.
+
+  genbmm output=stdout ... | edframe freq=10-1000Hz  >  file.bmm
+  genbmm useprevious=on file
+
+9. Select and plot a portion of the spectrum from the first frame of genepn
+   output between 1kHz and 2kHz.
+   Note: frequency controls the horizontal (ie cols) dimension for genepn.
+
+  genepn output=stdout ... | edframe frame=min freq=1kHz-2kHz > file.epn
+  genepn useprevious=on file
+
+
+Editing frames to select particular time slices (ie cols).
+---------------------------------------------------------
+
+10. Plot column (ie sample) 100 of the 3rd frame of gensai output as a row.
+
+  gensai output=stdout ... | edframe frame=2 time=100 Tran=on >  file.sai
+  gensai useprevious=on file
+
+11. Plot column of sample at 20ms from start of gennap output as a row
+
+  gennap output=stdout ... | edframe time=20ms Tran=on >  file.nap
+  gennap useprevious=on file
+
+12. Edit a wave to select the stretch between 4ms and 16ms, strip the
+    header and plot the resulting wave.
+
+  genwav output=stdout ... | edframe time=4ms-16ms Header=off > file
+  genwav file
+
+
+Editing frames to select partitions.
+-----------------------------------
+
+13. Plot a partition of channels 40 to 44 over the last 5ms (ie near the
+    trigger point on the right of the image) of all frames of gensai output.
+    Then plot a partition of frequency range 1kHz to 1.5kHz over the first
+    20ms (on the left of the image) of all frames of gensai output.
+
+  gensai pwidth=35ms nwidth=0 output=stdout ... | edframe time=30ms-max > file.sai
+  gensai useprevious=on file
+  gensai output=stdout ... | edframe freq=1kHz-1.5kHz time=min-20ms > file.sai
+  gensai useprevious=on file
+
+14. Plot the highest-frequency channel over the last 20ms of gennap output.
+
+  gennap output=stdout ... | edframe freq=max time=20ms-max > file.sai
+  gennap useprevious=on file
+
+
+*/
+
+
+#include <stdio.h>
+#include <math.h>
+#include "header.h"
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+#include "freqs.c"
+
+char application[]     = "Edit AIM output frames. " ;
+
+static char *helpstr, *debugstr, *fstr, *tstr, *cfstr, *infostr, *transtr, *headstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                                  , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                                      , DEBUG   },
+    {   "frame"     ,   "min-max"   ,  &fstr        ,   "select frames inclusively"                             , VAL     },
+    {   "time"      ,   "min-max"   ,  &tstr        ,   "time (or sample number) partition"                     , VAL     },
+    {   "freq"      ,   "min-max"   ,  &cfstr       ,   "frequency (or channel number) partition"               , VAL     },
+    {   "Transpose" ,   "off"       ,  &transtr     ,   "transpose each output partition"                       , SETFLAG },
+    {   "Header"    ,   "on"        ,  &headstr     ,   "output header"                                         , SETFLAG },
+    {   "info"      ,   "off"       ,  &infostr     ,   "print size and channel centre-frequency information"   , SETFLAG },
+   ( char * ) 0 } ;
+
+
+char *limitstr ;
+char *qualstr  ;
+char *minstr   ;
+char *maxstr   ;
+char *denstr   ;
+char *chansstr ;
+
+double *frequencies ;
+
+
+int     frameheight, framewidth ;       /* Parameters read from header */
+int     frames, framebytes ;
+int     frstep ;
+int     samplerate ;
+
+int     applic ;
+int     format ;
+int     rows, cols, numframes ;
+int     Newrows, Newcols, Newnumframes ;
+
+int     Newframeheight, Newframewidth ;
+int     Newframes, Newframebytes ;
+
+int     Transpose ;
+
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE   *fopen(), *fp = (FILE *) 0 ;
+    char   *header, *Header();
+    char   *val1, *val2, *headerstring() ;
+    short  *frame ;
+    int     i,j,k, a,b, xa,xb, ya,yb;
+    char    c, Info=0 ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], application, option ) ;
+
+    Transpose = ison( transtr ) ;
+
+    if ( (header = ReadHeader(fp)) == (char *) 0 ) {
+	fprintf(stderr,"edframe: header not found\n");
+	exit(1);
+    }
+    frameheight = HeaderInt( header, "frameheight" );
+    framewidth  = HeaderInt( header, "framewidth"  );
+    frames      = HeaderInt( header, "frames"      );
+    samplerate  = HeaderSamplerate( header );
+
+    if ( ( applic = Applic( header) ) < 0 ) {
+	fprintf(stderr,"edframe: application name not found in header\n" ) ;
+	exit( 1 ) ;
+    }
+    format = Format( applic ) ;
+    frame_to_matrix( format, &rows, &cols, &numframes, frameheight, framewidth, frames ) ;
+    framebytes  = rows * cols * sizeof(short) ;
+
+    if ( format > WAV ) {   /* if not genwav */
+	limitstr    = headerstring( header, "bwmin_afb"    );
+	qualstr     = headerstring( header, "quality_afb"  );
+	minstr      = headerstring( header, "mincf_afb"    );
+	maxstr      = headerstring( header, "maxcf_afb"    );
+	denstr      = headerstring( header, "dencf_afb"    );
+	chansstr    = headerstring( header, "channels_afb" );
+
+	SetErbParameters( to_Hz( limitstr, samplerate ), atof( qualstr ) ) ;
+	if( OptionInt( chansstr ) == 0 )
+	    frequencies = GenerateCenterFrequencies( to_Hz( minstr, samplerate ), to_Hz( maxstr, samplerate ), atof( denstr ) )   ;
+	else
+	    frequencies = NumberedCenterFrequencies( to_Hz( minstr, samplerate ), to_Hz( maxstr, samplerate ), OptionInt( chansstr ) ) ;
+    }
+    else    frequencies = (double *)0 ;
+
+
+    if ( format == SAI )  /* if gensai or genspl */
+	frstep = to_p( headerstring( header, "frstep_aid" ), samplerate ) ;
+    else
+	frstep = 1 ;
+
+
+    /* Get limits on specified number of frames */
+
+    if ( getvals( fstr, &val1, &val2, "-" ) == BADVAL ) {
+	fprintf(stderr,"edframe: bad frame selector [%s]\n", fstr ) ;
+	exit( 1 ) ;
+    }
+    if      ( ismin( val1 ) ) a = 0 ;
+    else if ( ismax( val1 ) ) a = numframes - 1 ;
+    else if ( Units( val1 ) ) a = (int)to_p( val1, samplerate ) / frstep ;
+    else                      a = atoi( val1 ) ;
+
+    if ( isempty( val2 ) )    b = a ;
+    else if ( ismin( val2 ) ) b = 0 ;
+    else if ( ismax( val2 ) ) b = numframes - 1 ;
+    else if ( Units( val2 ) ) b = (int)to_p( val2, samplerate ) / frstep ;
+    else                      b = atoi( val2 ) ;
+
+    if ( ison( debugstr ) ) {
+	printf("samplerate=%d val1=[%s] val2=[%s] a=%d b=%d numframes=%d\n", samplerate, val1,val2,a,b,numframes);
+    }
+
+    if ( a<0 || a>b || b>numframes ) {
+	if ( b>numframes )  fprintf(stderr,"edframe: bad frame selector [just %d frames available]\n", numframes );
+	else                fprintf(stderr,"edframe: bad frame selector \n" );
+	exit(1);
+    }
+
+
+    if ( format == EPN )  /* kludge for excitation patterns with horizontal freq axis */
+	swap( &rows, &cols ) ;
+
+
+    /* Get limits on specified time (ie samples or cols) */
+
+    if ( getvals( tstr, &val1, &val2, "-" ) == BADVAL ) {
+	fprintf(stderr,"edframe: bad time selector [%s]\n", tstr ) ;
+	exit( 1 ) ;
+    }
+    if ( ismin( val1 ) )        xa = 0 ;
+    else if ( ismax( val1 ) )   xa = cols-1 ;
+    else if ( Units( val1 ) )   xa = to_p( val1, samplerate ) ;
+    else                        xa = atoi( val1 ) ;
+
+    if (      isempty( val2 ) ) xb = xa ;
+    else if ( ismin( val2 ) )   xb = 0 ;
+    else if ( ismax( val2 ) )   xb = cols-1 ;
+    else if ( Units( val2 ) )   xb = to_p( val2, samplerate ) ;
+    else                        xb = atoi( val2 ) ;
+
+    /* Get limits on specified freqency (ie channels or rows) */
+
+    if ( getvals( cfstr, &val1, &val2, "-" ) == BADVAL ) {
+	fprintf(stderr,"edframe: bad frequency selector [%s]\n", cfstr ) ;
+	exit( 1 ) ;
+    }
+    if ( ismin( val1 ) )         ya = 0 ;
+    else if ( ismax( val1 ) )    ya = rows-1 ;
+    else if ( Units( val1 ) )    ya = closest( to_Hz( val1, samplerate ), frequencies, rows ) ;
+    else                         ya = atoi( val1 ) ;
+
+    if (      isempty( val2 ) )  yb = ya ;
+    else if ( ismin( val2 ) )    yb = 0 ;
+    else if ( ismax( val2 ) )    yb = rows-1 ;
+    else if ( Units( val2 ) )    yb = closest( to_Hz( val2, samplerate ), frequencies, rows ) ;
+    else                         yb = atoi( val2 ) ;
+
+
+    if ( format == EPN ) { /* excitation patterns have horizontal freq axis */
+	swap( &xa, &ya ) ;
+	swap( &xb, &yb ) ;
+	swap( &rows, &cols ) ;
+    }
+
+    if ( ya<0 || yb>=rows || ya>yb || xa<0 || xb>=cols || xa>xb ) {
+	fprintf(stderr,"edframe: bad specifiers  [xa=%d xb=%d  ya=%d yb=%d]\n", xa,xb,ya,yb ) ;
+	fprintf(stderr,"         input frames have %d rows and %d columns \n", rows, cols ) ;
+	exit(1);
+    }
+
+    Newrows      = yb - ya + 1 ;
+    Newcols      = xb - xa + 1 ;
+    Newnumframes =  b -  a + 1 ;
+
+    if ( Transpose )  swap( &Newrows, &Newcols ) ;
+
+    matrix_to_frame( format, Newrows, Newcols, Newnumframes, &Newframeheight, &Newframewidth, &Newframes ) ;
+    Newframebytes  = Newframewidth * Newframeheight * sizeof(short) ;
+
+    if ( !isoff( infostr ) ) {
+	if ( ison( infostr ) ) printinfo() ;
+	if ( isstr( infostr, "fbank" ) ) printfbank( xa, xb, ya, yb ) ;
+	exit( 0 ) ;
+    }
+    if ( ison( debugstr ) ) {
+	printf( "rows=%d cols=%d numframes=%d\n", rows,cols,numframes);
+	printf( "a=%d b=%d  ya=%d yb=%d  xa=%d xb=%d\n", a,b,ya,yb,xa,xb ) ;
+	printf( "Newrows=%d Newcols=%d Newnumframes=%d\n", Newrows,Newcols,Newnumframes);
+	printf( "Newframeheight=%d  Newframewidth=%d  Newframes=%d\n", Newframeheight, Newframewidth, Newframes ) ;
+	printf( "framebytes=%d Newframebytes=%d\n", framebytes, Newframebytes ) ;
+	exit( 1 ) ;
+    }
+
+    if ( ison( headstr ) )
+	WriteHeader( Header(header, ya,yb), stdout );
+
+
+    /* Allocate space for framebytes of data */
+
+    if ( (frame = (short *)malloc( framebytes )) == NULL ) {
+	fprintf(stderr,"edframe: malloc out of space\n");
+	exit(1);
+    }
+
+    /* seeks past `a' frames */
+
+    for ( i = 0 ; i < a  &&  fread( frame,framebytes,1,fp ) ; i++ )
+	;
+
+    /* edit frames `a' to `b' */
+
+    if ( Transpose ) {
+
+	for (  ; i <= b && fread( frame,framebytes,1,fp ) ; i++ ) {
+
+	    if ( format == SAI || format == EPN )
+		for ( j=xa ; j<=xb ; j++ )
+		    for ( k=ya ; k<=yb ; k++ )
+			fwrite( frame + k*framewidth + j, sizeof(short), 1, stdout ) ;
+	    else
+		for ( j=ya ; j<=yb ; j++ )
+		    for ( k=xa ; k<=xb ; k++ )
+			fwrite( frame + k*frameheight + j, sizeof(short), 1, stdout ) ;
+	}
+    }
+    else {      /* direct (un-transposed) output */
+
+	for (  ; i <= b && fread( frame,framebytes,1,fp ) ; i++ ) {
+
+	    if ( format == SAI || format == EPN )
+		for ( j=ya ; j<=yb ; j++ )
+		    fwrite( frame + j*framewidth + xa, sizeof(short), Newcols, stdout ) ;
+	    else
+		for ( j=xa ; j<=xb ; j++ )
+		    fwrite( frame + j*frameheight + ya, sizeof(short), Newrows, stdout ) ;
+	}
+    }
+
+    fclose(fp);
+
+}
+
+
+/*
+Return an allocated string to the value part of an option in the header
+with the given name. Exit if option not found in header.
+*/
+
+char *headerstring( header, name )
+char *header, *name ;
+{
+    char  *valuestr ;
+
+    if ( (valuestr = HeaderStringOnly( header, name )) == (char *) 0) {
+	fprintf(stderr,"edframe: option %s not found in header\n", name);
+	exit( 1 ) ;
+    }
+    return ( valuestr ) ;
+}
+
+
+int OptionInt( str )
+char *str ;
+{
+    if( strcmp( str, "on" ) == 0 )
+	return( 1 ) ;
+    else if( strcmp( str, "Not_used" ) == 0 )
+	return( 0 ) ;
+    else
+	return( atoi( str ) ) ;
+}
+
+
+/*
+   Copy the original nap header to a new sai header, changing in order:
+     maxcf_afb
+     mincf_afb
+     channels_afb
+     frames
+     framewidth
+     frameheight
+     framebytes
+     view
+   Finally, update the new header_bytes, and return the new header.
+*/
+
+char *Header( oldheader, ya,yb )
+char *oldheader ;
+int   ya,yb ;
+{
+    char *saiheader;
+    char *p0, *p1, *p2, *s, str[64];
+
+    saiheader = (char *)malloc( strlen(oldheader) + 64 ) ;
+
+    p0 = saiheader ;
+    p1 = oldheader ;
+
+
+    if ( format > WAV ) {  /* if not genwav */
+
+	/** copy up to maxcf_afb **/
+
+	p2 = HeaderString( oldheader , "maxcf_afb" ) ;
+	while( p1 < p2 )
+	    *p0++ = *p1++ ;
+
+	sprintf(str,"%.2fHz\n", frequencies[yb]);
+	for (s = str ; *s != '\n' ; )
+	    *p0++ = *s++;
+	*p0++ = *s;
+	while (*p1 != '\n')
+	    *p1++;
+	*p1++;
+
+
+	/** copy up to mincf_afb **/
+
+	p2 = HeaderString( oldheader , "mincf_afb" ) ;
+	while( p1 < p2 )
+	    *p0++ = *p1++ ;
+
+	sprintf(str,"%.2fHz\n", frequencies[ya]);
+	for (s = str ; *s != '\n' ; )
+	    *p0++ = *s++;
+	*p0++ = *s;
+	while (*p1 != '\n')
+	    *p1++;
+	*p1++;
+
+
+	/** copy up to channels_afb **/
+
+	p2 = HeaderString( oldheader , "channels_afb" ) ;
+	while( p1 < p2 )
+	    *p0++ = *p1++ ;
+
+	sprintf(str,"%d\n", Newframeheight);
+	for (s = str ; *s != '\n' ; )
+	    *p0++ = *s++;
+	*p0++ = *s;
+	while (*p1 != '\n')
+	    *p1++;
+	*p1++;
+
+    }
+
+    /** copy up to frames **/
+
+    p2 = HeaderString( oldheader , "frames" ) ;
+    while( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframes);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to framewidth **/
+
+    p2 = HeaderString( oldheader , "framewidth" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframewidth);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to frameheight **/
+
+    p2 = HeaderString( oldheader , "frameheight" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframeheight);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to framebytes **/
+
+    p2 = HeaderString( oldheader , "framebytes" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframebytes);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy rest of header **/
+
+    p2 = HeaderString( oldheader , "Version" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    while (*p1 != '\n')
+	*p0++ = *p1++ ;
+    *p0++ = *p1++ ;
+
+
+    /** update header_bytes **/
+
+    sprintf(str, "%0*d", 7, p0-saiheader);
+    p0 = HeaderString( saiheader , "header_bytes" ) ;
+    s = str;
+    while(*p0 != '\n')
+	*p0++ = *s++ ;
+
+
+    return saiheader;
+}
+
+
+
+
+/* Return the index of the frequency closest to the given "freq" */
+
+int closest( freq, frequencies, channels )
+double freq, *frequencies ;
+int    channels ;
+{
+    int i;
+
+    if ( frequencies == (double *)0 ) return 0 ;
+
+    for (i=0 ; i<channels && frequencies[i]<freq ; i++)
+	;
+    if (i==channels) return ( i-1 ) ;
+    if (i==0) return i ;
+    if ( frequencies[i]-freq < freq-frequencies[i-1] ) return i ;
+    else return ( i-1 ) ;
+}
+
+
+/* Return 1 if the str has appended units. Otherwise return 0.             */
+/* (A freqency specifier with no units is interpreted as a channel number) */
+Units(str)
+char *str ;
+{
+    char *eptr = str + strlen( str ) ;
+
+    if( isdigit( *--eptr ) ) return 0 ; /* last char is digit, so no units */
+    else return 1 ;
+}
+
+
+printinfo()
+{
+    printf( "gen%s output file\n", gen_applics[ applic ] ) ;
+    switch ( format ) {
+	case WAV : printf( "    wave format (array of time points)\n" ) ;
+		   break ;
+	case NAP : printf( "    activity-pattern format (by columns, lowest centre-frequency first in each)\n" ) ;
+		   break ;
+	case SGM : printf( "    spectrogram format (by columns, lowest centre-frequency first in each)\n" ) ;
+		   break ;
+	case EPN : printf( "    excitation-pattern format (array of frequency points per frame)\n" ) ;
+		   break ;
+	case SAI : printf( "    auditory-image format (by rows, lowest centre-frequency first per frame)\n" ) ;
+		   break ;
+    }
+
+    if ( format != WAV && format != EPN )  /* frameheight meaningless for wav and epn */
+	printf( "   frameheight = %4d channels (%.2fHz to %.2fHz) \n", rows, to_Hz( minstr, samplerate ), to_Hz( maxstr, samplerate ) ) ;
+
+    if ( format == EPN )   /* horiz axis is freq for epn, otherwise is time */
+	printf( "   framewidth  = %4d channels (%.2fHz to %.2fHz) \n", cols, to_Hz( minstr, samplerate ), to_Hz( maxstr, samplerate ) ) ;
+    else
+	printf( "   framewidth  = %4d samples  (%d ms at %dHz samplerate) \n", cols, (int)to_ms( itoa( cols ), samplerate ), samplerate ) ;
+
+    printf( "   frames      = %4d \n", numframes ) ;
+    printf( "   framesize   = %4d bytes \n", rows*cols*2 ) ;
+}
+
+
+printfbank( xa, xb, ya, yb )    /* print filterbank info */
+int xa, xb, ya, yb ;
+{
+    int i ;
+
+    if ( format > WAV ) { /* no filterbank for genwav */
+	if ( format == EPN )    /* freq axis is horiz for epn */
+	    for (i=xa ; i<=xb ; i++)
+		printf( "channel %2d. %7.2fHz,  %4.2fms,  %5.2f samples \n", i, frequencies[i], 1000./frequencies[i], (double)samplerate/frequencies[i] );
+	else
+	    for (i=ya ; i<=yb ; i++)
+		printf( "channel %2d. %7.2fHz,  %4.2fms,  %5.2f samples \n", i, frequencies[i], 1000./frequencies[i], (double)samplerate/frequencies[i] );
+    }
+}
+
+
+/* Swap the values in integer addresses p1 and p2 */
+
+swap( p1, p2 )
+int *p1 , *p2 ;
+{
+    int tmp ;
+
+    tmp = *p1  ;
+    *p1 = *p2  ;
+    *p2 =  tmp ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/edwave.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,163 @@
+/*
+  edwave.c   Edit a given range of a wave in binary short (16-bit) numbers.
+  --------   Write results on the stdout.
+
+ The `range' option sets the start and duration of the process.
+ Its arguments are of the form: range=a-b (where start=a and duration=b-a+1)
+			    or: range=a   (where start=a and duration=1    )
+ The arguments can be in time units (ms, s) or samples (no units), and both
+ "min" (start of file) and "max" (end of file) are recognised.
+ Samples in a file are numbered 0,1,2,...,max.
+
+ The `operation' option sets the edit operation:
+    extract     = output the part of the input which is inclusively within
+		  the given range.
+    delete      = output the part of the input which is NOT inclusively
+		  within the given range.
+
+ These operation types can be given in unambiguous abreviated form.
+
+*/
+
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "strmatch.h"
+#include "units.h"
+
+char applic[] = "Edit a given range of a wave." ;
+
+static char *helpstr, *debugstr, *sampstr,  *rangestr, *opstr, *typestr, *sizestr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                  , DEBUG },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                      , DEBUG },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "                           , VAL   },
+    {   "range"     ,   "min-max"   ,  &rangestr    ,   "inclusive time range wrt start"        , VAL   },
+    {   "operation" ,   "extract"   ,  &opstr       ,   "edit operation: {extract, delete}"     , VAL   },
+    {   "type"      ,   "short"     ,  &typestr     ,   "datatype"                              , VAL     },
+    {   "size"      ,   "off"       ,  &sizestr     ,   "print wave size {s, ms}"               , VAL   },
+   ( char * ) 0 } ;
+
+
+int     samplerate ;
+int     type       ;    /* datatype index */
+
+
+main(argc, argv)
+int    argc;
+char **argv;
+{
+    FILE   *fp ;
+    int     i, n ;
+    int     a, b ;
+    float   y    ;
+
+    fp = openopts( option, argc, argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    samplerate  = to_Hz( sampstr, 0 ) ;
+
+    if ( ( type = typeindex( typestr ) ) < 0 ) {
+	fprintf( stderr, "edwave: bad type [%s]\n", typestr ) ;
+	exit( 1 ) ;
+    }
+
+    if ( range( rangestr, &a, &b, samplerate ) == 0 ) {
+	fprintf(stderr,"edwave: bad range \n" ) ;
+	exit( 1 ) ;
+    }
+    n = b-a+1 ;
+
+    if ( ison( debugstr ) ) {
+	fprintf( stderr, "range=%s  a=%d b=%d n=%d\n", rangestr,a,b,n ) ;
+	exit( 0 ) ;
+    }
+
+    if ( !isoff( sizestr ) ) {
+	for ( i = 0 ; readitem( &y, type, 1, fp )  ; i++ )
+	    ;
+	if ( isstr( sizestr, "s" ) )        printf( "%.3f\n",  (float)i/samplerate ) ;
+	else if ( isstr( sizestr, "ms" ) )  printf( "%.1f\n", ((float)i/samplerate)*1000. ) ;
+	else if ( ison( sizestr ) )         printf( "%d\n", i ) ; /* samples */
+	else {
+	    fprintf( stderr,"edwave: unknown units for size [%s]\n", sizestr ) ;
+	    exit( 1 ) ;
+	}
+    }
+
+    else if ( a == (-1) )       /* special case of range=max */
+	edmax( fp ) ;
+
+    else if ( iststr( opstr, "extract" ) ) {
+
+	if ( ( i = seektype( a, type, fp ) ) < a ) {
+	    fprintf( stderr,"edwave: eof after %d items \n", i ) ;
+	    exit( 1 ) ;
+	}
+	for ( i = 0 ; ( b < 0  ||  i < n ) && readitem( &y, type, 1, fp ) ; i++ )
+	    writeitem( &y, type, 1, stdout ) ;
+	if ( i < n && b >= 0 ) {
+	    fprintf( stderr,"edwave: eof after %d items \n", a+i ) ;
+	    exit( 1 ) ;
+	}
+    }
+
+    else if ( iststr( opstr, "delete" ) ) {
+	for ( i = 0 ; i < a && readitem( &y, type, 1, fp ) ; i++ )
+	    writeitem( &y, type, 1, stdout ) ;
+	if ( i < a ) {
+	    fprintf( stderr,"edwave: eof after %d items \n", i ) ;
+	    exit( 1 ) ;
+	}
+	if ( ( i = seektype( n, type, fp ) ) < n ) {
+	    fprintf( stderr,"edwave: eof after %d items \n", a+i ) ;
+	    exit( 1 ) ;
+	}
+	while ( readitem( &y, type, 1, fp ) )
+	    writeitem( &y, type, 1, stdout ) ;
+    }
+
+    else {
+	fprintf( stderr, "edwave: unknown operation [%s]\n", opstr ) ;
+	exit( 1 ) ;
+    }
+
+    fclose( fp ) ;
+}
+
+
+/*
+Special case of range=max or range=max-max
+*/
+
+edmax( fp )
+FILE *fp ;
+{
+    float x, y ;
+
+    if ( iststr( opstr, "extract" ) ) {
+	while ( readitem( &y, type, 1, fp ) )
+	    x = y ;
+	writeitem( &x, type, 1, stdout ) ;
+    }
+
+    else if ( iststr( opstr, "delete" ) ) {
+
+	if ( readitem( &x, type, 1, fp ) && readitem( &y, type, 1, fp ) ) {
+	    do {
+		writeitem( &x, type, 1, stdout ) ;
+		x = y ;
+	    } while ( readitem( &y, type, 1, fp ) ) ;
+	}
+    }
+
+    else {
+	fprintf( stderr, "edwave: unknown operation [%s]\n", opstr ) ;
+	exit( 1 ) ;
+    }
+
+    fclose( fp ) ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/fbank.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,199 @@
+/*
+    fbank.c     Print parameters and misc info of a filterbank.
+    -------
+
+  The filterbank parameters are read from defaults or overriding options.
+  If the "input" option is set, then the parameters are read from a model
+  header, which can be given as a model output filename, or piped in.
+
+  Channels may be specified using option: freq=a-b
+  where "a" and "b" may be numbers with optional units of Hz or kHz appended,
+  or may be the strings "min" or "max".
+
+  With no units, the specifier is interpreted as channel (ie row) numbers.
+  These must be in the range 0 to channels-1, (where the lowest centre-freq
+  channel has the lowest channel number, 0, and `channels' is the max number
+  of channels, depending upon the parameters of the filterbank).
+
+  "min" is interpreted as the lowest  frequency channel (number 0).
+  "max" is interpreted as the highest frequency channel (number channels-1).
+
+  With frequency units, the specifier is interpreted as centre-frequencies.
+  These are converted to channel numbers using the "closest" channel number
+  in the filterbank to each specified centre-frequency.
+
+  Single channels or ranges can be specified.
+  The default specifier is freq=min-max
+  Eg:
+	specifier    channel number
+	----------   ---------------
+	freq=5       5
+	freq=1kHz    channel number with centre-freq closest to 1kHz
+	freq=max     max channel number (channels-1)
+	freq=10-max  10 to channels-1
+	freq=min-15  0 to 15
+
+*/
+
+
+#include <stdio.h>
+#include <math.h>
+#include "header.h"
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+#include "freqs.c"
+
+char applic[]     = "Print parameters of a filterbank. " ;
+
+static char *helpstr, *debugstr, *instr, *cfstr, *sampstr, *chanstr, *minstr, *maxstr, *denstr, *bwstr, *qualstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                          , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                              , DEBUG   },
+    {   "input"     ,   "off"       ,  &instr       ,   "Input (off/on)"                                , FLAG    },
+    {   "freq"      ,   "min-max"   ,  &cfstr       ,   "Frequency (or channel number)"                 , VAL     },
+    {   "samplerate",   "20000."    ,  &sampstr     ,   "Input wave sample rate (Hz)"                   , VAL     },
+    {   "channels"  ,   "75"        ,  &chanstr     ,   "Number of channels in filter"                  , VAL     },
+    {   "mincf"     ,   "100Hz"     ,  &minstr      ,   "Minimum center frequency (Hz)"                 , VAL     },
+    {   "maxcf"     ,   "6000Hz"    ,  &maxstr      ,   "Maximum center frequency (Hz)"                 , VAL     },
+    {   "dencf"     ,   "off"       ,  &denstr      ,   "Filter density (filters/critical band)"        , VAL     },
+    {   "bwmin"     ,   "24.7Hz"    ,  &bwstr       ,   "Minimum filter bandwith"                       , VAL     },
+    {   "quality"   ,   "9.265"     ,  &qualstr     ,   "Ultimate qualtity factor of filters"           , VAL     },
+   ( char * ) 0 } ;
+
+
+int     samplerate  ;
+int     channels    ;
+double *frequencies ;
+
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE  *fp ;
+    char  *header ;
+    char  *val1, *val2, *headerstring() ;
+    int    i, cf1, cf2 ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    if ( !isoff( instr ) ) {
+
+	if ( (header = ReadHeader(fp)) == (char *) 0 ) {
+	    fprintf(stderr,"fbank: header not found\n");
+	    exit(1);
+	}
+	sampstr  =  headerstring( header, "samplerate"   ) ;
+	chanstr  =  headerstring( header, "channels_afb" ) ;
+	minstr   =  headerstring( header, "mincf_afb"    ) ;
+	maxstr   =  headerstring( header, "maxcf_afb"    ) ;
+	denstr   =  headerstring( header, "dencf_afb"    ) ;
+	bwstr    =  headerstring( header, "bwmin_afb"    ) ;
+	qualstr  =  headerstring( header, "quality_afb"  ) ;
+    }
+
+    samplerate = to_Hz( sampstr, 0 ) ;
+    channels   = OptionInt( chanstr ) ;
+
+    SetErbParameters( to_Hz( bwstr, samplerate ), atof( qualstr ) ) ;
+    if( channels == 0 ) {
+	frequencies = GenerateCenterFrequencies( to_Hz( minstr, samplerate ), to_Hz( maxstr, samplerate ), atof( denstr ) ) ;
+	channels = NumberCenterFrequencies( to_Hz( minstr, samplerate ), to_Hz( maxstr, samplerate ), atof( denstr ) ) ;
+    }
+    else
+	frequencies = NumberedCenterFrequencies( to_Hz( minstr, samplerate ), to_Hz( maxstr, samplerate ), OptionInt( chanstr ) ) ;
+
+
+    /* Get limits on specified frequency (ie channels or rows) */
+
+    if ( getvals( cfstr, &val1, &val2, "-" ) == BADVAL ) {
+	fprintf(stderr,"fbank: bad frequency selector [%s]\n", cfstr ) ;
+	exit( 1 ) ;
+    }
+    if ( ismin( val1 ) )         cf1 = 0 ;
+    else if ( ismax( val1 ) )    cf1 = channels-1 ;
+    else if ( Units( val1 ) )    cf1 = closest( to_Hz( val1, samplerate ), frequencies, channels ) ;
+    else                         cf1 = atoi( val1 ) ;
+
+    if (      isempty( val2 ) )  cf2 = cf1 ;
+    else if ( ismin( val2 ) )    cf2 = 0 ;
+    else if ( ismax( val2 ) )    cf2 = channels-1 ;
+    else if ( Units( val2 ) )    cf2 = closest( to_Hz( val2, samplerate ), frequencies, channels ) ;
+    else                         cf2 = atoi( val2 ) ;
+
+    if ( cf1<0 || cf1>cf2 || cf2>channels ) {
+	fprintf( stderr,"fbank: incorrect frequency specifier [%s] for %d channel filterbank\n", cfstr, channels ) ;
+	exit( 1 ) ;
+    }
+
+    printf("channel     cf         period            ERB   \n");
+    printf("number     (Hz)     (ms)  (samples)      (Hz)  \n");
+    printf("-------   ------    ---------------     ------ \n");
+
+    for (i=cf1 ; i<=cf2 ; i++)
+	printf( "%3d      %7.2f   %6.2f    %6.2f    %6.2f \n", i, frequencies[i], 1000./frequencies[i], (double)samplerate/frequencies[i], frequencies[i]/9.26449 + 24.7 );
+
+}
+
+
+/* Return the index of the frequency closest to the given "freq" */
+
+int closest( freq, frequencies, channels )
+double freq, *frequencies ;
+int    channels ;
+{
+    int i;
+
+    for (i=0 ; i<channels && frequencies[i]<freq ; i++)
+	;
+    if (i==channels) return ( i-1 ) ;
+    if (i==0) return i ;
+    if ( frequencies[i]-freq < freq-frequencies[i-1] ) return i ;
+    else return ( i-1 ) ;
+}
+
+/* Return 1 if the str has appended units. Otherwise return 0.             */
+/* (A freqency specifier with no units is interpreted as a channel number) */
+
+Units(str)
+char *str ;
+{
+    char *eptr = str + strlen( str ) ;
+
+    if( isdigit( *--eptr ) ) return 0 ; /* last char is digit, so no units */
+    else return 1 ;
+}
+
+
+int OptionInt( str )
+char *str ;
+{
+    if( strcmp( str, "on" ) == 0 )
+	return( 1 ) ;
+    else if( strcmp( str, "Not_used" ) == 0 )
+	return( 0 ) ;
+    else
+	return( atoi( str ) ) ;
+}
+
+
+/*
+Return an allocated string to the value part of an option in the header
+with the given name. Exit if option not found in header.
+*/
+
+char *headerstring( header, name )
+char *header, *name ;
+{
+    char  *valuestr ;
+
+    if ( (valuestr = HeaderStringOnly( header, name )) == (char *) 0) {
+	fprintf(stderr,"edframe: option %s not found in header\n", name);
+	exit(1);
+    }
+    return ( valuestr ) ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/fft.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,298 @@
+/*
+  FFT program adapted from routines given in Numerical Recipes.
+
+  The output framewidth = ( input framewidth + padding ) / 2  spectral points.
+
+  Padding with zeroes is recommended to counter end-effects (See NR, p416).
+  It is also necessary since framewidth + padding must be a power of 2
+  (sample points at given rate).
+  This is because the fft method is "radix-2", and because the output is
+  symmetrical so that just half the points are unique.
+  Therefore each input frame is padded with zeroes to the next power of 2
+  larger than the input framewidth.
+
+  If necessary, extra padding can be enforced using the padding option to
+  add extra zeroes, padding to a larger power of 2.
+  The amount of extra padding is "exponential", expanding the basic size to:
+	( framewidth + padding ) * 2**n
+  where the padding option is n.
+  (n=0 by default, so that no extra padding is added. When n=1 then padding is
+  added to double the size, and when n=2 the size is quadrupled, etc.).
+
+  Frames are selected from the input stream using the "frames" option,
+  which has syntax: [[-]frame=a[-b]]. Input frames  are numbered 1,2,...
+  For example:
+    frame=a      Select just the a'th frame.
+    frame=a-b    Select frames from the a'th to b'th inclusive.
+  The strings "min" and "max" can be used as specifiers, meaning eg:
+    frame=min    Select the first frame.
+    frame=max    Select the last frame.
+    frame=a-max  Select frames from the a'th to the last inclusive.
+    frame=min-b  Select frames from the first to the b'th inclusive.
+  The default selects all frames, (ie frame=min-max).
+
+  Several forms of fft processing are provided, according to the "spectrum"
+  option:  log/magnitude/phase/complex/inverse/verbose.
+
+  Log and magnitude are both magnitude spectra (log is log10 of magnitude).
+  Phase is the phase spectrum.
+  Complex is the full complex spectrum, in <real,imag> pairs.
+  Inverse transform reads framewidth numbers which are interpreted as
+  <real,imag> pairs, (ie framewidth/2 complex numbers),
+  and outputs the inverse transform scaled by 1/framewidth.
+  Verbose prints the spectrum in ASCII on the stdout.
+
+
+  Examples:
+
+1. To print the input and output frame sizes in sample points, eg for a
+   subsequent plotting program, use the size option:
+
+fft ... size=on
+
+2. An fft of a waveform sampled at 10kHz, computed within a frame of 12.8ms,
+   plotting the 2nd frame in a sequence of frames with half-frame overlap.
+
+fft samp=10kHz width=12.8ms frstep=6.4ms frame=2 file | x11plot
+
+3. An animated plot of successive fft spectra of a waveform sampled at 10kHz,
+   each computed within a frame of 12.8ms, and shifted by 2 sample points.
+
+fft samp=10kHz width=12.8ms frstep=2p file | x11play -n64
+
+4. Using the complex output from fft, and inverse transform without windowing
+   to recover original input.
+
+fft samp=10kHz frame=2 spec=complex window=off file > foo
+fft samp=10kHz frame=1 spec=inverse window=off foo | x11plot
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+#include "sigproc.h"
+
+char applic[]     = "fast Fourier transform of contiguous frames.\n      i/p and o/p data in binary shorts." ;
+
+static char *helpstr, *debugstr, *sampstr, *widthstr, *padstr, *wstr, *sstr, *sizestr ;
+static char *startstr, *shiftstr, *framestr, *smagstr, *slogstr, *sphasestr, *echostr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                          , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                              , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "                                   , VAL     },
+    {   "start"     ,   "0"         ,  &startstr    ,   "Start point in i/p file."                      , VAL     },
+    {   "frames"    ,   "1-max"     ,  &framestr    ,   "Select frames inclusively"                     , VAL     },
+    {   "frstep"    ,   "16ms"      ,  &shiftstr    ,   "Step between input frames."                    , VAL     },
+    {   "width"     ,   "32ms"      ,  &widthstr    ,   "Width of input frames."                        , VAL     },
+    {   "padding"   ,   "0"         ,  &padstr      ,   "Exponential frame padding"                     , SVAL    },
+    {   "window"    ,   "on"        ,  &wstr        ,   "Hamming window"                                , SETFLAG },
+    {   "spectrum"  ,   "magnitude" ,  &sstr        ,   "log/magnitude/phase/complex/inverse/verbose"   , SETFLAG },
+    {   "scalemag"  ,   "0.08"      ,  &smagstr     ,   "scale magnitude  spectrum"                     , SVAL    },
+    {   "scalelog"  ,   "10"        ,  &slogstr     ,   "scale log  spectrum"                           , SVAL    },
+    {   "scalephase",   "100"       ,  &sphasestr   ,   "scale phase spectrum"                          , SVAL    },
+    {   "size"      ,   "off"       ,  &sizestr     ,   "print input/output frame size in samples"      , SETFLAG },
+    {   "echo"      ,   "off"       ,  &echostr     ,   "echo buffered input without processing"        , SVAL    },
+   ( char * ) 0 } ;
+
+
+int     samplerate  ;
+int     width       ;
+int     step        ;
+int     zeroes      ;
+int     dowindow    ;
+double  scale       ;
+int     echo        ;
+
+float  *vec, *window ;
+short  *obuf ;
+
+int     allbins  ;
+int     halfbins ;
+
+#define MAG     1       /* magnitude spectrum */
+#define PHASE   2       /* phase spectrum     */
+#define INV     3       /* inverse transform  */
+#define VERB    4       /* verbose (ASCII)    */
+#define LOG     5       /* log magnitude      */
+#define COMP    6       /* complex spectrum   */
+
+int     output ;
+
+main (argc, argv)
+int     argc;
+char  **argv;
+{
+    FILE     *fp  ;
+    short    *buf ;
+    int       a, b ;
+    int       isign ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    samplerate = to_Hz( sampstr ) ;
+    dowindow   = ison( wstr ) ;
+    echo       = ison( echostr ) ;
+    width      = to_p( widthstr, samplerate )  ;
+    step       = to_p( shiftstr, samplerate )  ;
+    zeroes     = ( getpower( width ) << atoi( padstr ) ) - width ;
+
+    allbins    = width + zeroes ;
+    halfbins   = allbins / 2    ;
+
+    if ( iststr( sstr, "magnitude" ) )  {
+	output = MAG ;
+	scale = atof( smagstr ) ;
+	isign = 1 ;
+    }
+    else if ( iststr( sstr, "log" ) )  {
+	output = LOG ;
+	scale = atof( slogstr ) ;
+	isign = 1 ;
+    }
+    else if ( iststr( sstr, "phase" ) ) {
+	output = PHASE ;
+	scale = atof( sphasestr ) ;
+	isign = 1 ;
+    }
+    else if ( iststr( sstr, "complex" ) ) {
+	output = COMP ;
+	isign = 1 ;
+    }
+    else if ( iststr( sstr, "inverse" ) ) {
+	output = INV ;
+	scale = 1./(double)width ;
+	isign = (-1) ;
+    }
+    else if ( iststr( sstr, "verbose" ) ) {
+	output = VERB ;
+	isign = 1 ;
+    }
+    else {
+	fprintf(stderr,"unknown spectrum \n");
+	exit( 1 ) ;
+    }
+
+    /* frame size printout */
+
+    if ( ison( sizestr ) ) {
+	fprintf(stderr,"fft sizes in sample points:\n" ) ;
+	fprintf(stderr,"    input  frame size = %d  (framewidth=%d + padding=%d)\n", width+zeroes, width, zeroes ) ;
+	fprintf(stderr,"    output frame size = %d \n", (width + zeroes)/2 ) ;
+	exit( 0 ) ;
+    }
+
+    /* parse bounds on number of frames */
+
+    if ( selector( framestr, &a, &b ) == 0 ) {
+	fprintf(stderr,"fft: bad frame selector [%s]\n", framestr ) ;
+	exit( 1 ) ;
+    }
+
+    /* Allocate working space */
+
+    obuf  = (short *)malloc( halfbins * sizeof(short) ) ;
+    vec   = (float *)malloc( allbins * sizeof(float) ) ;
+    if ( dowindow )
+	window = hamming( width ) ;
+
+
+    /* Compute fft for each frame of width shorts in the input stream */
+
+    if ( seekbytes( fp, (int)( to_p( startstr, samplerate ) * sizeof(short) ) ) == 0 ) {
+	fprintf(stderr,"improper seek\n") ;
+	exit( 1 ) ;
+    }
+
+    while ( ( buf = getframe( fp, a, width, step ) ) != (short *)0  && ( a<=b || b==0 ) ) {
+	if ( echo ) fwrite( buf, sizeof(short), width, stdout ) ;
+	else process( buf, isign ) ;
+	a++ ;
+    }
+    if ( a<=b && b>0 )
+	fprintf(stderr,"warning: not enough frames for request\n");
+
+    fclose( fp ) ;
+}
+
+
+process( buf, isign )
+short *buf ;
+int    isign ;
+{
+    short *bptr     = buf ;
+    short *endptr   = buf + width ;
+    short *optr     = obuf ;
+    short *endbin   = obuf + halfbins ;
+    float *wptr     = window ;
+    float *vptr     = vec    ;
+    float *endvec   = vec + allbins ;
+
+    if ( dowindow )
+	while ( bptr < endptr )
+	    *vptr++ =  *bptr++  *  *wptr++ ;
+    else
+	while ( bptr < endptr )
+	    *vptr++ =  *bptr++ ;
+
+    while ( vptr < endvec )         /* padding */
+	*vptr++ =  0 ;
+
+    fft( vec, width+zeroes, isign ) ;
+
+    vptr = vec ;
+    switch ( output ) {
+
+	case COMP  :  while ( vptr < endvec )
+			  *optr++ = (short)( *vptr++ ) ;
+		      fwrite( obuf, sizeof(short), allbins, stdout ) ;
+		      break;
+	case PHASE :  phase( vec, allbins ) ;
+		      while ( optr < endbin )
+			  *optr++ = (short)( scale * *vptr++ ) ;
+		      fwrite( obuf, sizeof(short), halfbins, stdout ) ;
+		      break;
+	case MAG   :  mag( vec, allbins ) ;
+		      while ( optr < endbin )
+			  *optr++ = (short)( scale * *vptr++ ) ;
+		      fwrite( obuf, sizeof(short), halfbins, stdout ) ;
+		      break;
+	case LOG   :  mag( vec, allbins ) ;
+		      while ( optr < endbin )
+			  *optr++ = (short)( scale * 10 * log10(*vptr++) ) ;
+		      fwrite( obuf, sizeof(short), halfbins, stdout ) ;
+		      break;
+	case INV   :  while ( vptr < endvec )
+			  *optr++ = (short)( scale * *vptr++ ) ;
+		      fwrite( obuf, sizeof(short), allbins, stdout ) ;
+		      break;
+	case VERB  :  print_complex_spectrum( (complex *)vec, halfbins, samplerate ) ;
+		      break;
+
+    }
+}
+
+
+/*
+ Pretty-print complex k-spectrum on the stdout.
+*/
+
+print_complex_spectrum(C,k,samplerate)
+complex *C;
+int      k, samplerate;
+{
+    float res;      /* frequency resolution. */
+    int   i;
+
+    res = (float)(samplerate>>1) / (float)k;
+    for (i=0; i<k ; i++) {
+	printf ("%3d.  %6.1fHz.  Re=%9.2f  Im=%9.2f  mod=%8.2f  arg=%4.2f\n",
+		i, i*res, Re(&C[i]), Im(&C[i]), mod(&C[i]), arg(&C[i]) );
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/filt1.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,118 @@
+/*
+  filt1.c       1st order LP filter using an exponential smoother
+		(recursive "leaky integrator" filter)
+
+  The n'th recursive update is:
+
+    a)    y[n] = a.y[n-1] + x[n]                recursive sum
+    b)    y[n] = a.y[n-1] + (1-a).x[n]          recursive mean
+
+  where decay constant a = exp(-Ts/T)
+  and   Ts is sample interval in seconds
+	T  is decay time-constant in seconds
+
+  The 1st order LP filter is an exponential window which decays into the past.
+  With decay constant a=1 there is infinite memory because it does not decay.
+  The result is either a steadily accumulating sum or mean.
+  (A zero mean is assumed).
+  With 0 < a < 1 there is a finite decaying memory.
+  The smaller `a', the smaller the memory (it decays faster).
+  With a = 0 the filter output is identical with its input.
+
+  The window width parameter is the time-constant parameter.
+  The half life of the exponential window is given by -T.ln(0.5) = 0.693T
+  ie. for a given time constant, T secs, the window decays to half of its
+  current value in a period of 0.693T secs.
+  (Thus T can be set to accomodate an expected period).
+
+  When the time-constant parameter is given with time units (s or ms) then
+  it is converted to a decay constant using  a = exp(-Ts/T).
+  Otherwise it is taken to be the decay constant directly.
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[]     = "1st order low-pass filter using exponential smoother." ;
+
+static char *helpstr, *debugstr, *sampstr, *tcstr,  *destr  ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                  , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"      , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "Samplerate "           , VAL     },
+    {   "tc"        ,   "3ms"       ,  &tcstr       ,   "Decay time constant"   , VAL     },
+    {   "de"        ,   "mean"      ,  &destr       ,   "Difference equation"   , VAL     },
+   ( char * ) 0 } ;
+
+
+int     samplerate  ;
+double  a           ;   /* decay constant */
+
+
+main (argc, argv)
+int     argc;
+char  **argv;
+{
+    FILE  *fp  ;
+    short  x, y ;
+    int    morehelp() ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts1( helpstr, argv[0], applic, option, morehelp ) ;
+
+    samplerate = to_Hz( sampstr ) ;
+
+    if ( Units( tcstr ) )
+	a = exp( -(double)( 1. / ( samplerate * to_s( tcstr, samplerate ) ) ) ) ;
+    else
+	a = (double)atof( tcstr ) ;
+
+    y = 0 ;     /* initialization */
+
+    if ( iststr( destr, "mean" ) )
+	while ( fread( &x, sizeof(short), 1, fp ) ) {
+	    y = a * y  +  ( 1 - a ) * x ;
+	    fwrite( &y, sizeof(short), 1, stdout ) ;
+	}
+
+    else if ( iststr( destr, "sum" ) )
+	while ( fread( &x, sizeof(short), 1, fp ) ) {
+	    y = a * y  +  x ;
+	    fwrite( &y, sizeof(short), 1, stdout ) ;
+	}
+
+    else {
+	fprintf( stderr,"unknown de [%s]\n", destr ) ;
+	exit( 1 ) ;
+    }
+
+    fclose( fp );
+}
+
+
+/* Return 1 if the str has appended units. Otherwise return 0.             */
+
+Units(str)
+char *str ;
+{
+    char *eptr = str + strlen( str ) ;
+
+    if( isdigit( *--eptr ) ) return 0 ; /* last char is digit, so no units */
+    else return 1 ;
+}
+
+
+
+morehelp()
+{
+    fprintf(stderr,"\nde: \n");
+    fprintf(stderr,"    sum     y[n] = a.y[n-1] + x[n]   \n");
+    fprintf(stderr,"    mean    y[n] = a.y[n-1] + (1-a).x[n]    (unity steady-state gain)\n");
+    exit( 1 ) ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/freqs.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,213 @@
+/**************************************************************************
+
+	Filter-bank routines.
+       ======================
+
+Filter-bank parameters in model headers are as follows:
+(These may be converted, using the given routines, into values which are then
+passed as args into the routines below. All the values are double except for
+the number of channels which is an int. Remember to cast Freq as double).
+
+String name    Conversion   Value      Comment
+-------------  -----------  ---------  -------------------------------------
+channels_afb   Optionint()  channels   Number of channels in filter
+mincf_afb      Freq()       mincf      Minimum center frequency (Hz)
+maxcf_afb      Freq()       maxcf      Maximum center frequency (Hz)
+dencf_afb      atof()       dencf      Filter density (filters/critical band)
+bwmin_afb      Freq()       bwmin      Minimum filter bandwith
+quality_afb    Freq()       quality    Ultimate qualtity factor of filters
+
+
+
+Initialize global filter parameters.
+
+    SetErbParameters( bwmin, quality )
+    double bwmin, quality ;
+
+Return array of centre frequencies for given density.
+
+    double *GenerateCenterFrequencies( mincf, maxcf, dencf )
+    double mincf, maxcf, dencf ;
+
+(This uses routine GenerateScale() to compute the scale, and uses
+routine ErbScale() to convert the parameters (mincf etc) into Erbs).
+
+Return array of centre frequencies for given number of channels.
+
+    double *NumberedCenterFrequencies( mincf, maxcf, channels )
+    double mincf, maxcf ;
+    int    channels ;
+
+(This uses routine NumberedScale() to compute the scale, and uses
+routine ErbScale() to convert the parameters (mincf etc) into Erbs).
+
+Return number of channels for given density.
+
+    int NumberCenterFrequencies( mincf, maxcf, dencf )
+    double mincf, maxcf, dencf ;
+
+Basic utilities:
+
+ErbScale()      Convert freq in Hz to Erbs.
+
+
+Example of application
+----------------------
+
+#include "freqs.c"
+
+int    channels = 0     ;
+double mincf    = 220.  ;
+double maxcf    = 4400. ;
+double dencf    = 4.    ;
+double bwmin    = 24.7  ;
+double quality  = 9.265 ;
+
+    SetErbParameters( bwmin, quality ) ;
+
+    if (channels==0) {
+	frequencies = GenerateCenterFrequencies( mincf, maxcf, dencf ) ;
+	channels = NumberCenterFrequencies( mincf, maxcf, dencf ) ;
+    }
+    else
+	frequencies = NumberedCenterFrequencies( mincf, maxcf, channels ) ;
+
+
+**************************************************************************/
+
+extern void SetErbParameters() ;
+
+extern double Erb(), ErbScale(), FofErbScale() ;
+
+extern double *GenerateCenterFrequencies() ;
+extern int     NumberCenterFrequencies() ;
+extern double *NumberedCenterFrequencies() ;
+extern double *GenerateScale() ;
+extern int     NumberOnScale() ;
+extern double *NumberedScale() ;
+
+/* Defaults */
+
+static double limit = 24.7  ;
+static double Q     = 9.265 ;
+
+/**********************  filter/gamma_tone.c *******************************/
+
+double bankBaseFrequency   = 1000. ;
+
+double *GenerateCenterFrequencies( min_cf, max_cf, erb_density )
+double min_cf, max_cf, erb_density ;
+{
+    return ( GenerateScale( ErbScale( min_cf ), ErbScale( max_cf ), erb_density, ErbScale( bankBaseFrequency ), FofErbScale ) ) ;
+}
+
+int NumberCenterFrequencies( min_cf, max_cf, erb_density )
+double min_cf, max_cf, erb_density ;
+{
+    return ( NumberOnScale( ErbScale( min_cf ), ErbScale( max_cf ), erb_density, ErbScale( bankBaseFrequency ) ) ) ;
+}
+
+double *NumberedCenterFrequencies( min_cf, max_cf, channels )
+double min_cf, max_cf ;
+int channels ;
+{
+    return ( NumberedScale( ErbScale( min_cf ), ErbScale( max_cf ), channels, FofErbScale ) ) ;
+}
+
+
+/********************** filter/scales.c ************************************/
+
+double *GenerateScale( min, max, density, base, inverse )
+double min, max, density, base, (*inverse)() ;
+{
+    unsigned n_scale = NumberOnScale( min, max, density, base ) ;
+    double *scale ;
+    double scale_start ;
+    int i ;
+
+    scale = (double *)malloc( (n_scale+1) * sizeof(double) ) ;
+
+    if( min != max ) {
+
+	scale_start = base - floor( ( base - min ) * density ) / density ;
+
+	/* fill array scale points 1./density apart */
+
+	for( i=0 ; i < n_scale  ; i++ )
+	    scale[ i ] = scale_start + i / density   ;
+
+	scale[ i++ ] = 0. ;
+    }
+    else {
+	scale[0] = min ;
+	scale[1] = 0.  ;
+    }
+
+	/* convert scale space back to units required */
+
+    if( inverse != (double ( * )()) 0 )
+	for( i=0 ; i < n_scale  ; i++ )
+	    scale[ i ] = inverse( scale[ i ] ) ;
+
+    return ( scale ) ;
+}
+
+int NumberOnScale( min, max, density, base )
+double min, max, density, base ;
+{
+    if( min != max )
+	return ( ( int ) ( ( floor( ( base - min ) * density ) + 1. + ( floor( ( max - base ) * density ) ) ) ) ) ;
+    else
+	return ( 1 ) ;
+}
+
+
+double *NumberedScale( min, max, channels, inverse )
+double min, max ;
+int channels ;
+double (*inverse)() ;
+{
+    double *scale ;
+    int chan ;
+
+    scale = (double *)malloc( (channels+1) * sizeof(double) ) ;
+
+    scale[ 0 ] = min ;
+    for( chan=1 ; chan < channels  ; chan++ )
+	scale[ chan ] = min + chan * (max-min) / ( channels - 1 ) ;
+
+    if( inverse != (double ( * )()) 0 )
+	for( chan=0 ; chan < channels  ; chan++ )
+	    scale[ chan ] = inverse( scale[ chan ] ) ;
+
+    scale[ channels ] = 0. ;
+
+    return ( scale ) ;
+}
+
+/********************** filter/formulae.c ************************************/
+
+
+void SetErbParameters( new_limit, new_Q )
+double new_limit, new_Q ;
+{
+    limit = new_limit ;
+    Q     = new_Q     ;
+
+    return ;
+}
+
+double ErbScale( frequency )
+	  double frequency ;
+{
+    return ( log( 1. + frequency / Q / limit ) * Q ) ;
+}
+
+double FofErbScale( E )
+	     double E ;
+{
+    return ( ( exp( E / Q ) - 1 ) * Q * limit ) ;
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ftgram.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,503 @@
+/*
+ ftgram.c       Row-wise fft program by Michael Allerhand.
+----------
+
+  Short-time Fourier transform applied to each row of input frames.
+  Output frames consist of row-wise magnitude spectra, computed using fft.
+
+Input/output:
+  Read a header and frame in NAP format.
+  Write a header, (constructed from the original input header), and a
+  succession of frames in SAI format.
+
+  The input file is interpreted as one large frame in NAP format to be
+  divided into input frames, each to be processed and output in SAI format.
+
+  The options "start" and "length" specify the input file.
+  The special option value length=max specifies all the input file from
+  the given start to its end.
+
+  The options "width" and "frstep"  specify the input frames.
+  The width option is the framewidth of each input frame) and the frstep
+  option is the frameshift between input frames in the input file.
+  The special option value width=max specifies the input framewidth as equal
+  to the given input file length, (and if this is also "max", then the
+  input framewidth is the remainder of the input file).
+
+  Most options in the input header are copied to the output header.
+  This enables options which are needed for the eventual display
+  to pass straight through. Some options are set so that they can override
+  the input header. For example, the display option is set on to enable
+  display even when input has display=off. The animate option can be set on
+  even when the input has animate=off.
+  Parts of the header are changed for the new sai format:
+  (frames, frameshift, framewidth, frameheight, framebytes).
+
+Padding:
+  The output framewidth is the next power-of-2 above twice the input
+  framewidth.
+  The rows of each input frame are padded with zeroes so that the input
+  framewidth is at least twice its original size, and also a power of 2.
+  This is because the fft method is "radix-2", and because each output
+  spectrum is symmetrical so that just half the points are unique.
+  It is advisable to pad input frames for the additional reason that
+  padding counters frame end-effects.
+
+  Therefore each row of each input frame is padded with zeroes to the next
+  power of 2 larger than the original input framewidth.
+  If necessary, extra padding can be enforced using the padding option to
+  add extra zeroes, padding to a larger power of 2.
+  The amount of extra padding is "exponential" since if the basic padded
+  framesize is N, and the padding option is n, then extra padding is to:
+  N * 2**n.
+  (n=0 by default, so that N is not changed. When n=1 then N is doubled, and
+  when n=2 then N is quadrupled, etc.).
+
+  The output framewidth (and hence the frequency resolution) depends upon the
+  input framewidth and the padding.
+
+Examples:
+
+1. ftgram of a NAP, animated, with framewidth 16ms
+
+gennap len=128ms output=stdout display=off file | ftgram width=16ms anim=on > file.sai
+gensai useprev=on headr=5 top=1000 file             -(for landscape plot)
+genspl useprev=on headr=5 top=1000 pensize=2 file   -(for spiral plot)
+
+2. ftgram of an SAI:
+  (Note that gensai removes file.sai, so you must use some other name, eg foo.sai).
+
+gensai len=64 pwidth=64 nwidth=0 output=stdout display=off file |  \
+saitonap frame=3 | ftgram width=32ms frame=1 > foo.sai
+gensai useprev=on top=1000 headr=5 mag=2 foo
+
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "header.h"
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+#include "sigproc.h"
+
+char applic[]     = "Autocorrelogram auditory image." ;
+
+static char *helpstr  , *debugstr, *dispstr , *anistr   , *startstr  ;
+static char *lengthstr, *widthstr, *shiftstr, *headerstr, *framestr  ;
+static char *wstr     , *scalestr, *padstr                           ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                       , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                           , DEBUG   },
+    {   "display"   ,   "on"        ,  &dispstr     ,   "Display output image."                      , SETFLAG },
+    {   "animate"   ,   "off"       ,  &anistr      ,   "Animate cartoon."                           , SETFLAG },
+    {   "frames"    ,   "1-max"     ,  &framestr    ,   "Select frames inclusively"                  , VAL     },
+    {   "header"    ,   "on"        ,  &headerstr   ,   "Header (for gensai useprevious=on)."        , VAL     },
+    {   "start"     ,   "0"         ,  &startstr    ,   "Start point in i/p file."                   , VAL     },
+    {   "length"    ,   "max"       ,  &lengthstr   ,   "Length of i/p file to process."             , VAL     },
+    {   "frstep"    ,   "16ms"      ,  &shiftstr    ,   "Step between input frames."                 , VAL     },
+    {   "width"     ,   "32ms"      ,  &widthstr    ,   "Width of input frames."                     , VAL     },
+    {   "padding"   ,   "0"         ,  &padstr      ,   "Exponential frame padding"                  , SVAL    },
+    {   "window"    ,   "on"        ,  &wstr        ,   "Hamming window"                             , SETFLAG },
+    {   "scale"     ,   "0.08"      ,  &scalestr    ,   "Scale factor for output"                    , SVAL    },
+   ( char * ) 0 } ;
+
+
+int     samplerate ;
+
+int     frameheight, framewidth ;
+int     frames, framebytes ;
+int     frameshift ;
+
+int     Newframeheight, Newframewidth ;
+int     Newframes, Newframebytes ;
+int     Newframeshift ;
+
+int     start, length ; /* Size of input file (num cols) */
+int     frameslength ;  /* Length (num cols) of input file to process */
+
+int     zeroes ;
+int     window ;        /* Flag for Hamming window */
+float   scale  ;        /* Scale factor for output */
+
+short  *file ;          /* Input file (NAP format) */
+float  *W    ;          /* Hamming window for fft  */
+float  *buf  ;          /* fft working space       */
+
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE   *fp ;
+    char   *header, *SaiHeader();
+    char   *versionstr, c ;
+    int     startbytes, framebyteshift ;
+    short  *frame, *endframe ;
+    int     i, a, b ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    window  = ison( wstr ) ;
+
+
+    /**** parse bounds on number of frames ****/
+
+    if ( selector( framestr, &a, &b ) == 0 ) {
+	fprintf(stderr,"ftgram: bad frame selector [%s]\n", framestr ) ;
+	exit( 1 ) ;
+    }
+
+
+    /**** Input frame dimensions (from header and options) ****/
+
+    if ((header = ReadHeader(fp)) == (char *) 0 ) {
+	fprintf(stderr,"ftgram: header not found\n");
+	exit(1);
+    }
+
+    if ( (versionstr = HeaderString( header, "Version" )) == (char *)0 ) {
+	fprintf(stderr,"ftgram: model version-number not found in header\n");
+	exit(1);
+    }
+
+    samplerate  = HeaderSamplerate( header );
+
+    /* In NAP format, the size of the 2-D image is given by:  */
+    /*   frameheight = number of rows (filterbank channels)   */
+    /*   frames      = number of columns (sample points)      */
+
+    frameheight = HeaderInt( header, "frameheight" );
+    frames      = HeaderInt( header, "frames"      );
+
+    if ( ( frameshift  = to_p( shiftstr, samplerate ) ) <= 0 ) {
+	fprintf(stderr,"ftgram: non-positive frstep [%d]\n", frameshift);
+	exit(1);
+    }
+
+    /* calculate start of first frame (in cols) */
+
+    if ( ( start = to_p( startstr, samplerate ) + ( a-1 ) * frameshift ) >= frames ) {
+	fprintf(stderr,"ftgram: input file too small (%dms) for given framing parameters\n", frames * 1000 / samplerate );
+	exit(1);
+    }
+
+    /* get length of input file (in cols) and framewidth of input frames */
+
+    if ( ismax( lengthstr ) ) length = frames - start ;
+    else                      length = to_p( lengthstr, samplerate ) - start ;
+
+    if ( ismax( widthstr ) )  framewidth = length ;
+    else                      framewidth = to_p( widthstr, samplerate ) ;
+
+    if ( length < framewidth ) {
+	fprintf(stderr,"ftgram: input file too small (%dms) for given framing parameters\n", frames * 1000 / samplerate );
+	exit(1);
+    }
+
+    /* calculate length (num cols) to process, and the number of frames */
+
+    if ( b==0 ) {
+	frameslength = length ;
+	Newframes = 1 + ( length - framewidth ) / frameshift ;
+    }
+    else {
+	frameslength = framewidth + ( b-a ) * frameshift ;
+	Newframes = b - ( a-1 ) ;
+    }
+
+    if ( start + frameslength > frames ) {
+	fprintf(stderr,"ftgram: input file too small (%dms) for requested start and length \n", frames * 1000 / samplerate );
+	exit(1);
+    }
+
+    framebytes = frameheight * frameslength * sizeof(short) ;
+    startbytes = frameheight * start  * sizeof(short) ;
+
+
+    /**** Output frame dimensions ****/
+
+    Newframeheight =  frameheight ;
+    Newframewidth  =  ( framewidth + zeroes ) >> 1 ;  /* spectral bins */
+    Newframeshift  =  frameshift ;
+    Newframebytes  =  Newframeheight * Newframewidth * sizeof(short) ;
+
+
+    /**** Padding and output scale factor ****/
+
+    zeroes = ( getpower( framewidth << 1 ) << atoi( padstr ) ) - framewidth ;
+    scale  = atof( scalestr ) ;
+
+
+    /**** Debug ****/
+
+    if ( ison( debugstr ) ) {
+	fprintf(stderr, "Input:   frames=%d frameheight=%d frameshift=%d\n", frames, frameheight, frameshift ) ;
+	fprintf(stderr, "Sizes:   start=%d length=%d framewidth=%d frameslength=%d\n", start, length, framewidth, frameslength ) ;
+	fprintf(stderr, "Output:  zeroes=%d Newframewidth=%d Newframes=%d \n", zeroes, Newframewidth, Newframes ) ;
+	exit( 1 ) ;
+    }
+
+
+    /**** Allocate space (input file, window coeffs, and fft working space) ****/
+
+    if ( ( file = (short *)malloc( framebytes ) ) == NULL ) {
+	fprintf(stderr,"ftgram: malloc out of space\n");
+	exit(1);
+    }
+
+    if ( window )
+	W = hamming( framewidth ) ;
+
+    buf = (float *)malloc( ( framewidth + zeroes ) * sizeof(float) );
+
+
+    /**** Write new sai header ****/
+
+    if ( ison( headerstr ) )
+	WriteHeader( SaiHeader(header), stdout );
+
+
+    /**** Seek to start of input file in blocks of framebytes ****/
+
+    for (i=framebytes ; i < startbytes ; i += framebytes)
+	if ( fread( file, framebytes, 1, fp ) == NULL ) {
+	    fprintf(stderr,"ftgram: missing data after header\n");
+	    exit(1);
+	}
+    if ( (startbytes -= (i - framebytes)) > 0 )
+	if ( fread( file, startbytes, 1, fp ) == NULL ) {
+	    fprintf(stderr,"ftgram: missing data after header\n");
+	    exit(1);
+	}
+
+
+    /**** Read framebytes of i/p file ****/
+
+    if ( fread( file, framebytes, 1, fp ) == NULL ) {
+	fprintf(stderr,"ftgram: missing data after header\n");
+	exit(1);
+    }
+
+
+    /**** Process frames ****/
+
+    framebyteshift = frameshift * frameheight ;
+    endframe = file + Newframes * framebyteshift ;
+
+    for ( frame = file, i=1 ; frame < endframe ; frame += framebyteshift, i++ ) {
+	fprintf(stderr,"ftgram: %d / %d  [%dms]\n", i, Newframes, start*1000/samplerate );
+	ftgram( frame ) ;
+	start += frameshift ;
+    }
+
+    fclose(fp);
+    fprintf(stderr,"ftgram: done\n" ) ;
+}
+
+
+
+/********************************** FFT ************************************/
+
+/* Call fft and magnitude spectrum for each row in auditory image */
+
+ftgram( frame )
+short *frame ;
+{
+    register int  i, j, row, col ;
+
+    for ( row=0 ; row < frameheight ; row++ ) {
+
+	if ( window )
+	    for ( col=0 , i=row ; col < framewidth ; col++, i+=frameheight )
+		buf[col] = frame[i] * W[col] ;
+	else
+	    for ( col=0 , i=row ; col < framewidth ; col++, i+=frameheight )
+		buf[col] = frame[i] ;
+
+	for ( j=0 ; j<zeroes ; j++ )    /* padding */
+	    buf[col++] = 0 ;
+
+	fft( buf, framewidth+zeroes, 1 ) ;
+	mag( buf, framewidth+zeroes ) ;
+
+	writebuf( buf, Newframewidth, scale ) ;
+    }
+}
+
+
+/********************** Write o/p ****************************************/
+
+writebuf( buf, n, scale )       /* write buffer as scaled shorts */
+float *buf ;
+int    n ;
+float  scale ;
+{
+    register int  i ;
+    short         p ;
+
+    for (i=0 ; i < n ; i++)  {
+	p = (short)( buf[i] * scale ) ;
+	fwrite( &p, sizeof(short), 1, stdout ) ;
+    }
+}
+
+
+/************************ Output header ************************************/
+/*
+   Copy the original nap header to a new sai header, changing in order:
+     frames
+     frameshift
+     framewidth
+     frameheight
+     framebytes
+     animate
+     display
+   Finally, update the new header_bytes, and return the new header.
+*/
+
+char *SaiHeader( napheader )
+char *napheader ;
+{
+    char *saiheader;
+    char *p0, *p1, *p2, *s, str[64];
+
+    saiheader = (char *)malloc( strlen(napheader) + 64 ) ;
+
+    p0 = saiheader ;
+    p1 = napheader ;
+
+
+    /** copy up to frames **/
+
+    p2 = HeaderString( napheader , "frames" ) ;
+    while( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframes);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to frameshift **/
+
+    p2 = HeaderString( napheader , "frameshift" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframeshift);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to framewidth **/
+
+    p2 = HeaderString( napheader , "framewidth" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframewidth);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to frameheight **/
+
+    p2 = HeaderString( napheader , "frameheight" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframeheight);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to framebytes **/
+
+    p2 = HeaderString( napheader , "framebytes" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframebytes);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to animate_ctn **/
+
+    p2 = HeaderString( napheader , "animate_ctn" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%s\n", anistr );
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to display **/
+
+    p2 = HeaderString( napheader , "display" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%s\n", dispstr );
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy rest of header **/
+
+    p2 = HeaderString( napheader , "Version" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    while (*p1 != '\n')
+	*p0++ = *p1++ ;
+    *p0++ = *p1++ ;
+
+
+    /** update header_bytes **/
+
+    sprintf(str, "%0*d", 7, p0-saiheader);
+    p0 = HeaderString( saiheader , "header_bytes" ) ;
+    s = str;
+    while(*p0 != '\n')
+	*p0++ = *s++ ;
+
+
+    return saiheader;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ftoa.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,91 @@
+/*
+    ftoa.c      frames (SAI or NAP) to ASCII
+    ------
+
+    Each data point is output as a triple: (x,y,z)
+    where (x,y) specify the coordinate in terms of a pointwise coordinate
+    system with the origin (0,0) in the bottom-left of the display.
+
+    The output is in space-separated ASCII numbers with one triple per line.
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "header.h"
+#include "options.h"
+#include "strmatch.h"
+
+
+char applic[]     = "Frames to ASCII triples (x,y,z). " ;
+
+static char *helpstr, *debugstr, *formatstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                          , DEBUG },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"              , DEBUG },
+    {   "format"    ,   "nap"       ,  &formatstr   ,   "frame format (nap or sai)"     , VAL   },
+   ( char * ) 0 } ;
+
+
+int     frameheight, framewidth ;       /* Parameters read from header */
+int     frames, framebytes ;
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE   *fp ;
+    char   *header, *SaiHeader();
+    short  *frame ;
+    int     x, y  ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    if ( (header = ReadHeader(fp)) == (char *) 0 ) {
+	fprintf(stderr,"integrate: header not found\n");
+	exit(1);
+    }
+
+    frameheight = HeaderInt( header, "frameheight" );
+    framewidth =  HeaderInt( header, "framewidth"  );
+    frames =      HeaderInt( header, "frames"      );
+    framebytes =  HeaderInt( header, "framebytes"  );
+
+
+    if ( isstr( formatstr, "nap" ) ) {
+	framebytes =  frames*frameheight*sizeof(short) ;
+	framewidth =  frames ;
+	if ( (frame = (short *)malloc( framebytes )) == (short *)0 ) {
+	    fprintf(stderr,"ftoa: malloc out of space\n");
+	    exit(1);
+	}
+	while ( fread( frame,framebytes,1,fp ) ) {
+	    for ( x=0 ; x<framewidth ; x++ )
+		for ( y=0 ; y<frameheight ; y++ )
+		    printf("%-5d %-5d %-5d\n", x, y, *frame++ ) ;
+	}
+    }
+
+    else if ( isstr( formatstr, "sai" ) ) {
+	if ( (frame = (short *)malloc( framebytes )) == (short *)0 ) {
+	    fprintf(stderr,"ftoa: malloc out of space\n");
+	    exit(1);
+	}
+	while ( fread( frame,framebytes,1,fp ) ) {
+	    for ( y=0 ; y<frameheight ; y++ )
+		for ( x=0 ; x<framewidth ; x++ )
+		    printf("%-5d %-5d %-5d\n", x, y, *frame++ ) ;
+	}
+    }
+
+    else {
+	fprintf( stderr,"ftoa: unknown format [%s]\n", formatstr ) ;
+	exit( 1 ) ;
+    }
+
+    fclose( fp ) ;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ftos.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,76 @@
+/*
+  ftos.c        binary float-to-short conversion.
+ --------
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+
+char applic[]     = "float to short data-type conversion." ;
+
+static char *helpstr, *errstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"          ,  DEBUG     },
+    {   "error"     ,   "off"       ,  &errstr      ,   "print overflow and quantization errors"  ,  VAL  },
+   ( char * ) 0 } ;
+
+
+#define MAX           32767.
+#define MIN        ( -32767. )
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE  *fp ;
+    float  X  ;
+    short  Y  ;
+    int    i  ;
+    float  min = MAX, fmin ;
+    float  max = MIN, fmax ;
+    float  quant, maxquant, sumquant=0 ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    if ( isoff( errstr ) ) {
+
+	while ( fread( &X, sizeof(float), 1, fp ) ) {
+	    Y = (short)X ;
+	    fwrite( &Y, sizeof(short), 1, stdout);
+	}
+    }
+
+    else {
+
+	for ( i = 0 ; fread( &X, sizeof(float), 1, fp ) ; i++ ) {
+	    if ( X > max ) max = X ;
+	    if ( X < min ) min = X ;
+	    quant = ( X - (int)X ) / (int)( 1 + X ) ;
+	    sumquant += quant ;
+	    if ( quant > maxquant ) maxquant = quant ;
+	    Y = (short)X ;
+	    fwrite( &Y, sizeof(short), 1, stdout);
+	}
+
+	if ( max > MAX || min < MIN ) {
+
+	    if ( max > MAX )  fmax = MAX / max ;
+	    if ( min < MIN )  fmin = MIN / min ;
+
+	    if ( fmax < fmin ) fprintf( stderr, "16-bit overflow  (scale down by a factor < %f\n", fmax ) ;
+	    else               fprintf( stderr, "16-bit underflow  (scale down by a factor < %f\n", fmin ) ;
+	}
+	fprintf( stderr, "max  quantization error = %f\n", maxquant   ) ;
+	fprintf( stderr, "mean quantization error = %f\n", sumquant/i ) ;
+    }
+
+    fclose(fp);
+    exit(0);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/gate.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,201 @@
+/*
+  gate.c      gate numbers from input stream
+  ------
+    Read and write numbers of a given type.
+    All numbers within the given gate ranges are replaced by the
+    given gate <value>, (a real ie. float number).
+    Gate ranges are: xrange (a time range, with optional time units)
+    and:             yrange (an amplitude range, in real ie. float numbers).
+    If the gate is not a <value>, but is an <operation>, then the numbers
+    within the gate ranges are operated on as appropriate.
+    Abbreviated forms of the operation names are allowed.
+
+	<operation>     comment
+	-----------     -----------------------------
+	exclude         exclude numbers from output
+	negate          negate numbers
+	count           print a count of the numbers found in the gate range
+			on the stderr.
+
+Examples:
+
+1. Replace all numbers <=0 by value 0  (ie. half-wave rectification).
+
+gate yrange=min-0 val=0  file
+
+2. Replace all numbers <=0 by their inverse (ie. full-wave rectification).
+
+gate yrange=min-0 val=neg  file
+
+3. Gate the onset of a signal: replace the first 20ms with zeroes.
+
+gate xrange=0-20ms yrange=min-max val=0 file
+
+4. Exclude all numbers <=0
+
+gate yrange=min-0  val=exclude file
+
+5. Exclude all numbers >0
+
+gate yrange=1-max val=exclude file
+
+6. Delete lines 4 to 8 inclusive from ascii input (lines numbered 0,1,2,...)
+
+gate type=ASCII xrange=4-8 yrange=min-max val=exclude  file
+
+7. Replace all numbers in the yrange -1 to +1 inclusive by 0
+
+gate yrange=-1-1 val=0  file
+
+8. Replace all instances of number 10 by -10
+
+gate yrange=10 val=-10  file
+
+9. Print a count of all numbers = 0
+
+gate yrange=0 val=count file
+
+10. Print a count of all numbers < 0
+
+gate yrange=min--1  val=count file
+
+*/
+
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[] = "gate specific numbers in input stream using given value." ;
+
+static char *helpstr, *debugstr, *sampstr, *xrstr, *yrstr, *gstr, *typestr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                      , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"          , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "               , VAL     },
+    {   "xrange"    ,   "min-max"   ,  &xrstr       ,   "time range"                , VAL     },
+    {   "yrange"    ,   "min-0"     ,  &yrstr       ,   "amplitude range"           , VAL     },
+    {   "value"     ,   "0"         ,  &gstr        ,   "replacement value or <operation>", VAL     },
+    {   "type"      ,   "short"     ,  &typestr     ,   "datatype"                  , VAL     },
+   ( char * ) 0 } ;
+
+
+int    samplerate  ;
+int    type        ;    /* datatype index */
+
+main(argc, argv)
+int    argc;
+char **argv;
+{
+    FILE   *fp ;
+    int     i, n=0, ax, bx, real_range(), helpoperations() ;
+    float   ay, by, x, val ;
+
+    fp = openopts( option, argc, argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts1( helpstr, argv[0], applic, option, helpoperations ) ;
+
+    samplerate = to_Hz( sampstr, 0 ) ;
+
+    if ( ( type = typeindex( typestr ) ) < 0 ) {
+	fprintf( stderr, "gate: bad type [%s]\n", typestr ) ;
+	exit( 1 ) ;
+    }
+
+    if ( range( xrstr, &ax, &bx, samplerate ) == 0 ) {
+	fprintf(stderr,"gate: bad xrange [%s]\n", xrstr ) ;
+	exit( 1 ) ;
+    }
+
+    if ( real_range( yrstr, &ay, &by ) == 0 ) {
+	fprintf(stderr,"gate: bad yrange [%s]\n", yrstr ) ;
+	exit( 1 ) ;
+    }
+
+    if ( iststr( gstr, "count" ) ) {            /* gate=count */
+
+	for ( i = 0 ; readitem( &x, type, 1, fp ) ; i++ )
+	    if ( i >= ax && ( i <= bx || bx == (-1) ) )
+		if ( x >= ay && x <= by )
+		    n++ ;
+	fprintf(stderr,"%d numbers in gate\n", n);
+    }
+
+
+    else if ( iststr( gstr, "exclude" ) ) {     /* gate=exclude */
+
+	for ( i = 0 ; readitem( &x, type, 1, fp ) ; i++ ) {
+	    if ( i < ax || ( i > bx && bx != (-1) ) )
+		writeitem( &x, type, 1, stdout ) ;
+	    else if ( x < ay || x > by )
+		writeitem( &x, type, 1, stdout ) ;
+	}
+    }
+
+    else if ( iststr( gstr, "negate" ) ) {      /* gate=negate  */
+
+	for ( i = 0 ; readitem( &x, type, 1, fp ) ; i++ ) {
+	    if ( i < ax || ( i > bx && bx != (-1) ) )
+		writeitem( &x, type, 1, stdout ) ;
+	    else if ( x < ay || x > by )
+		writeitem( &x, type, 1, stdout ) ;
+	    else {
+		x = ( -x ) ;
+		writeitem( &x, type, 1, stdout ) ;
+	    }
+	}
+    }
+
+    else {                                      /* gate=<value> */
+	val = atof( gstr ) ;
+	for ( i = 0 ; readitem( &x, type, 1, fp ) ; i++ ) {
+	    if ( i < ax || ( i > bx && bx != (-1) ) )
+		writeitem( &x, type, 1, stdout ) ;
+	    else if ( x < ay || x > by )
+		writeitem( &x, type, 1, stdout ) ;
+	    else
+		writeitem( &val, type, 1, stdout ) ;
+	}
+    }
+
+    fclose(fp);
+}
+
+
+/*
+Parse a range specifier into real numbers representing amplitude.
+*/
+
+int real_range( s, a, b )
+char  *s ;
+float *a, *b ;
+{
+    char *val1, *val2 ;
+
+    if ( getvals( s, &val1, &val2, "-" ) == (-3) )
+	return ( 0 ) ;
+    if      ( ismin( val1 ) ) *a = (-1e10) ;    /* minimum         */
+    else if ( ismax( val1 ) ) *a =   1e10  ;    /* maximum         */
+    else *a = atof( val1 ) ;
+
+    if ( isempty( val2 ) )    *b = *a ;          /* single object        */
+    else if ( ismin( val2 ) ) *b = (-1e10) ;
+    else if ( ismax( val2 ) ) *b =   1e10  ;
+    else *b = atof( val2 ) ;
+
+    if ( *a > *b ) return 0 ;
+    return 1 ;
+}
+
+
+helpoperations()
+{
+    fprintf(stderr,"\n<operation>:          \n");
+    fprintf(stderr,"            exclude     exclude numbers in gate range from output \n");
+    fprintf(stderr,"            negate      negate numbers in gate range              \n");
+    fprintf(stderr,"            count       print count of numbers in gate range      \n");
+    exit( 1 ) ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/gauss.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,95 @@
+/*
+  gauss.c   generate a Gaussian window for a given variance over a given
+  -------   range of standard deviations.
+
+  Output to stdout in binary shorts or floats.
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+#include "sigproc.h"
+
+char applic[]     = "generate a Gaussian window." ;
+
+static char *helpstr, *debugstr, *sampstr,  *varstr ;
+static char *ranstr,  *normstr,  *scalestr, *typestr,  *sizestr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                      , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                          , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "                               , VAL     },
+    {   "variance"  ,   "20"        ,  &varstr      ,   "Variance of Gaussian window"               , VAL     },
+    {   "range"     ,   "4"         ,  &ranstr      ,   "Range in standard deviations about mean"   , VAL     },
+    {   "normalize" ,   "off"       ,  &normstr     ,   "Unit area under curve (unit max if off)"   , SETFLAG },
+    {   "scale"     ,   "1000"      ,  &scalestr    ,   "Scale factor for output"                   , VAL     },
+    {   "type"      ,   "short"     ,  &typestr     ,   "Output datatype (short/float)"             , VAL     },
+    {   "size"      ,   "off"       ,  &sizestr     ,   "Print size of window in samples"           , VAL     },
+   ( char * ) 0 } ;
+
+
+int     samplerate  ;
+
+float  *window ;
+int     points ;
+
+short  *buf    ;
+
+
+main (argc, argv)
+int     argc;
+char  **argv;
+{
+    float f ;
+
+    getopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    samplerate = to_Hz( sampstr ) ;
+
+    window = gauss_window( to_p( sqrt_units( varstr ), samplerate ), atof( ranstr ), &points ) ;
+
+    if ( ison( normstr ) ) normalize_area( window, points ) ;
+    else if ( !isoff( normstr ) ) {
+	fprintf(stderr,"gauss: unknown normalization [%s]\n", normstr) ;
+	exit( 1 ) ;
+    }
+
+    if ( ison( sizestr ) )
+	printf( "%d\n", points ) ;
+
+    else if ( iststr( typestr, "float" ) ) {
+	scalar( window, points, atof( scalestr ) ) ;
+	fwrite( window, sizeof(float), points, stdout ) ;
+    }
+
+    else if ( iststr( typestr, "short" ) ) {
+	buf = (short *)malloc( points * sizeof(short) ) ;
+	if ( ( f = ftos( window, buf, points, atof( scalestr ) ) ) < 1. )
+	    fprintf( stderr,"Warning: 16-bit overflow. Try scale factor < %f\n", f ) ;
+	fwrite( buf, sizeof(short), points, stdout ) ;
+    }
+
+    else
+	fprintf(stderr,"gauss: unknown datatype [%s]\n", typestr) ;
+}
+
+
+scalar( y, n, scale )
+float  *y ;
+int     n ;
+float   scale ;
+{
+    int  i ;
+
+    if ( scale != 1. ) {
+	for ( i=0 ; i < n ; i++ )
+	    y[i] *= scale ;
+    }
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/hdr.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,286 @@
+/*
+    hdr.c   Operations on AIM header.
+    -----
+
+  Usage:  hdr [options] [file]
+
+  Read an AIM output file. If no filename is given then input is expected
+  on the stdin. The input from AIM is expected to consist of an AIM header
+  followed by some data.
+
+  Options take the form:  <name>=<value>
+  and abbreviated option names are recognised provided they are unambiguous
+  wrt other names in the input header.
+
+  The operations are header stripping, querying, or modifying:-
+
+  1. If no options are given, then strip the header and write the data which
+  follows the header on the stdout.
+  Eg:
+	gensai output=stdout ... | hdr | ...
+
+  2. An empty value field (ie. <name>=) is interpreted as a query, and the
+  corresponding option value found in the header is printed on the stderr.
+  Eg., to query the value of option pwidth_aid:
+
+	hdr pwid=  file
+
+  The special option names are:
+
+	"all"       causes all option values to be printed.
+	"format"    causes the format of the AIM output file to be printed.
+
+  3. Each option of the form <name>=<value> is substituted for the corresponding
+  option found in the input header. A new header is constructed using the
+  input header and all given substitutions, and the new header is written
+  on the stdout, followed by the data which follows the input header.
+  Eg., to change the value of pwidth_aid to 32ms:
+
+	hdr pwid=32ms  file >  file2
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "header.h"
+#include "strmatch.h"
+
+char  **nameptr, *tmpptr ;
+int    *namespn,  tmpspn ;
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE   *fp=stdin, *fopen() ;
+    char   *header, *Header(), str[64], *s, c ;
+    int     i, j, min ;
+    int     modify=0 ;
+    short   data ;
+
+    namespn  = ( int *)malloc( (argc-1) * sizeof(int) ) ;
+    nameptr  = (char **)malloc( (argc-1) * sizeof(char *) ) ;
+
+    if ( iststr( "-h", argv[argc-1] ) || iststr( "help=", argv[argc-1] ) )
+	printhelp();
+
+    /* search for "=" to get span of each option name, and check option */
+
+    if ( argc == 1 || strchr( argv[argc-1], '=' ) != (char *)0 )
+	fp = stdin ;
+    else if ( ( fp = fopen( argv[--argc], "r" ) ) == (FILE *)0 ) {
+	fprintf(stderr, "can't open %s\n", argv[argc] ) ;
+	exit( 1 ) ;
+    }
+
+    for ( i=1 ; i<argc ; i++ ) {
+
+	if ( iststr( "-h", argv[argc-1] ) || iststr( "help=", argv[argc-1] ) )
+	    printhelp();
+
+	if ( ( namespn[i] = strspnbrk( argv[i], "=" ) ) == ( -1 ) ) {
+	    fprintf(stderr,"hdr: [%s] incorrect option syntax (<name>=<value>)\n", argv[i] );
+	    exit( 1 ) ;
+	}
+	else if ( namespn[i] == strlen( argv[i] ) - 1 ) {   /* query */
+	    argv[i][namespn[i]] = '\0' ;
+	    namespn[i] = 0 ;            /* query denoted by zero span */
+	}
+    }
+
+    if ( ( header = ReadHeader( fp ) ) == (char *) 0 ) {
+	fprintf(stderr,"hdr: header not found\n");
+	exit(1);
+    }
+
+    /* if no options, then just strip header */
+
+    if ( argc == 1 ) {
+	while ( fread(&c, sizeof(char),1,fp) )
+	    fwrite(&c,sizeof(char),1,stdout);
+	fclose( fp ) ;
+	exit( 0 ) ;
+    }
+
+
+    /* find the position of each option name in the header */
+
+    for ( i=1 ; i<argc ; i++ ) {
+
+
+	if ( namespn[i] > 0 ) {
+	    strncpy( str, argv[i], namespn[i] ) ;
+	    str[namespn[i]] = '\0' ;
+	    if ( ( nameptr[i] = HeaderStrings( header , str ) ) == (char *)0 ) {
+		fprintf(stderr,"hdr: option [%s] ambiguous or not found in header\n", str);
+		exit(1);
+	    }
+	    modify++ ;
+	}
+
+	else {
+	    if ( isstr( argv[i], "all" ) )
+		WriteHeader( header, stderr ) ;
+	    else if ( isstr( argv[i], "format" ) )
+		WriteFormat( header, stderr ) ;
+	    else {
+		if ( ( s = HeaderValueString( header, argv[i] ) ) == (char *)0 )
+		    fprintf( stderr,"option %s ambiguous or not found\n", argv[i] ) ;
+		else
+		    fprintf( stderr, "%s=%s\n", HeaderNameString( header, argv[i] ), s ) ;
+	    }
+	}
+    }
+
+    if ( modify ) {
+
+	/* sort the name lists into the order the names appear in the header */
+
+	for ( i=1 ; i<argc ; i++ ) {
+	    if ( namespn[i] > 0 ) {
+		min = i ;
+		for ( j=i+1 ; j<argc ; j++ ) {
+		    if ( nameptr[j] < nameptr[min] )
+			min = j ;
+		}
+		if ( min != i ) {
+		    tmpptr = nameptr[i] ; nameptr[i] = nameptr[min] ; nameptr[min] = tmpptr ;
+		    tmpptr = argv[i]    ; argv[i]    = argv[min]    ; argv[min]    = tmpptr ;
+		    tmpspn = namespn[i] ; namespn[i] = namespn[min] ; namespn[min] = tmpspn ;
+		}
+	    }
+	}
+
+	header = Header( header, argc, argv ) ;
+	WriteHeader( header, stdout );
+
+	/* echo the rest of the file */
+
+	while ( fread( &data, sizeof(short), 1, fp ) != NULL )
+	    fwrite( &data, sizeof(short), 1, stdout) ;
+
+    }
+    fclose( fp ) ;
+}
+
+
+
+/*
+   Copy the original header to a new header, changing the ordered options.
+   Then update the new header_bytes, and return the new header.
+*/
+
+char *Header( oldheader, argc, argv )
+char *oldheader ;
+int   argc ;
+char *argv[] ;
+{
+    char *newheader;
+    char *p0, *p1, *p2, *s, str[64];
+    int   i ;
+
+    newheader = (char *)malloc( strlen(oldheader) + 64 ) ;
+
+    p0 = newheader ;
+    p1 = oldheader ;
+
+    /** copy up to each new option **/
+
+    for ( i=1 ; i<argc ; i++ ) {
+
+	if ( namespn[i] > 0 ) {
+
+	    p2 = nameptr[i] ;
+	    while( p1 < p2 )
+		*p0++ = *p1++ ;
+
+	    sprintf(str,"%s\n", argv[i] + namespn[i] + 1 );
+	    for (s = str ; *s != '\n' ; )
+		*p0++ = *s++;
+	    *p0++ = *s;
+	    while (*p1 != '\n')
+		*p1++;
+	    *p1++;
+	}
+    }
+
+    /** copy rest of header **/
+
+    p2 = HeaderString( oldheader , "Version" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    while (*p1 != '\n')
+	*p0++ = *p1++ ;
+    *p0++ = *p1++ ;
+
+
+    /** update header_bytes **/
+
+    sprintf(str, "%0*d", 7, p0-newheader);
+    p0 = HeaderString( newheader , "header_bytes" ) ;
+    s = str;
+    while(*p0 != '\n')
+	*p0++ = *s++ ;
+
+
+    return newheader;
+}
+
+
+WriteFormat( header, fp )
+char  *header ;
+FILE  *fp     ;
+{
+    int   applic, format, rows, cols, frames ;
+
+    if ( ( applic = Applic( header) ) < 0 ) {
+	fprintf(stderr,"hdr: application name not found in header\n" ) ;
+	exit( 1 ) ;
+    }
+    format = Format( applic ) ;
+
+    frame_to_matrix( format, &rows, &cols, &frames,
+				HeaderInt( header, "frameheight" ),
+				HeaderInt( header, "framewidth"  ),
+				HeaderInt( header, "frames"      )  ) ;
+
+    fprintf( fp, "gen%s output file\n", gen_applics[ applic ] ) ;
+
+    switch ( format ) {
+	case 0 : fprintf( fp, "wave format (array of time points)\n" ) ;
+		 break ;
+	case 1 : fprintf( fp, "activity-pattern format (by columns, lowest centre-frequency first in each)\n" ) ;
+		 break ;
+	case 2 : fprintf( fp, "spectrogram format (by columns, lowest centre-frequency first in each)\n" ) ;
+		 break ;
+	case 3 : fprintf( fp, "excitation-pattern format (array of frequency points per frame)\n" ) ;
+		 break ;
+	case 4 : fprintf( fp, "auditory-image format (by rows, lowest centre-frequency first per frame)\n" ) ;
+		 break ;
+    }
+
+    fprintf( fp, "       rows (channels) = %d  per frame\n", rows   ) ;
+    fprintf( fp, "       cols (samples)  = %d  per frame\n", cols   ) ;
+    fprintf( fp, "       frames          = %d\n", frames ) ;
+    fprintf( fp, "       framesize       = %d bytes\n", rows*cols*2 ) ;
+
+}
+
+
+printhelp()
+{
+    fprintf(stderr,"hdr: Operations on AIM header.\n");
+    fprintf(stderr,"Usage: hdr [options] [file]\n");
+    fprintf(stderr,"options         comment      \n");
+    fprintf(stderr,"----------      ----------   \n");
+    fprintf(stderr,"                strip header (when no options given) \n");
+    fprintf(stderr,"<name>=         query header (for each empty options field) \n");
+    fprintf(stderr,"<name>=<value>  modify header by substituting given values\n");
+    fprintf(stderr,"\n");
+    fprintf(stderr,"option names for special queries: \n");
+    fprintf(stderr,"all=            query all options in header \n");
+    fprintf(stderr,"format=         query format of AIM output file \n");
+    exit( 0 ) ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/header.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,644 @@
+/***************************************************************************
+    Utilities for model output headers.
+
+    A header is an ASCII desciption which summarises the state of
+    a process by giving a list of parameter values etc etc..
+    Each parameter is described on a separate line, and the header consists
+    of several lines of the general form:
+
+	<ASCII description> = <value>\n
+
+    For example, the first five lines of the header generated by a command
+    line "gensai -header fname" is as follows:
+
+	header_bytes=0000532
+	scale_sai=0.25
+	imagedurn_sai=16
+	decayrate_sai=10
+	cgmdecay=24
+	 ...
+	date=Thu Jan 11 00:19:41 WET 1990\n
+	\000
+
+    This string is written onto the front of  the  file  with  padding  if
+    desired  before  any data is written.  The header can be of any length
+    and contain any combination of non null characters.  Header items  are
+    identified  by  the  string on the left of the equals symbol and their
+    value is represented by the string on the remainder of that line.
+
+    The first line is always the HEADER_STRING (ie. header_bytes=....\n)
+    which gives the length of the header.
+
+Synopsis of utilities:
+----------------------
+
+char *ReadHeader( fp )
+FILE *fp ;
+
+WriteHeader(header,fp)
+char  *header;
+FILE  *fp;
+
+char *HeaderString( header, name )
+char *header, *name ;
+
+char *HeaderStringOnly( header, name )
+char *header, *name ;
+
+double HeaderDouble( header, name )
+char *header, *name ;
+
+double HeaderInt( header, name )
+char *header, *name ;
+
+void FreeHeader( header )
+char *header ;
+
+ReadHeader() reads a header (if it exists ) from the  file  into
+    memory  and  returns  a  pointer to the header in memory allocated for
+    storing the header. It returns a null pointer if no header is found.
+    It leaves the fp pointing to the data which follows the header.
+WriteHeader() writes the given header on the given file stream.
+HeaderString() simply searches through the header for values the  user
+    requests  and  returns  a  pointer  to  the  beginning  of  the  value.
+    It returns a null pointer if the required string is not found.
+HeaderStringOnly() returns a pointer  to  an  allocated  string  that
+    contains  only  the  value  rather  than  a  pointer  to a string that
+    includes the all the rest of the header (which is what  HeaderString()
+    returns). It returns a null pointer if the required string is not found.
+HeaderDouble() converts values to Doubles.
+HeaderInt() converts values to Ints.
+FreeHeader() frees the space allocated for a header by ReadHeader.
+
+Example:
+-------
+    A simple example of the use of the header utility routines to read the
+    sai dimensions from a header would be:
+    (This assumes a ".sai" file generated by a command like "gensai -header")
+
+    #include <stdio.h>
+    #include <math.h>
+    #include "header.c"
+    char *header = ReadHeader(fp);        fp is file-pointer to ".sai" file
+    int   frameheight = HeaderInt(header,"frameheight");   num chans
+    int   framewidth  = HeaderInt(header,"framewidth");    sai duration
+
+    char *name = "frameheight";
+    printf( "%s=%s\n", name, HeaderStringOnly( header, name ) ) ;
+
+****************************************************************************/
+
+#include <stdio.h>
+/* #include <strings.h> */
+#include <string.h>
+#include <malloc.h>
+#include "header.h"
+#include "units.h"
+
+
+/***************************************************************************
+    ReadHeader() reads a header (if it exists ) from the  file  into
+    memory  and  returns  a  pointer to the header in memory allocated for
+    storing the header. It returns a null pointer if no header is found.
+****************************************************************************/
+char *ReadHeader( fp )
+FILE *fp ;
+{
+    static char header_string[] = HEADER_STRING ;
+    static char header_start[]  = HEADER_START  ;
+    unsigned header_length ;
+    char *header ;
+
+    if( fread( header_string, sizeof ( *header_string ), STRSIZE( header_string ), fp ) == STRSIZE( header_string )
+	  && strncmp( header_string, header_start, STRSIZE( header_start ) ) == 0 ) {
+
+	/* header located - remove carriage return */
+
+	header_length = atoi( header_string + STRSIZE( header_start ) ) ;
+
+	header = malloc( header_length ) ;
+
+	if( header != (char *) 0 ) {
+	    (void) strcpy( header, header_string ) ;
+	    (void) fread( header + STRSIZE( header_string ), sizeof ( *header_string ), (int) header_length - STRSIZE( header_string ), fp ) ;
+	}
+
+	return ( header ) ;
+    }
+    else {
+	/* header not present */
+
+	(void) fseek( fp, 0l, 0 ) ;
+
+	return ( (char *) 0 ) ;
+    }
+}
+
+/***************************************************************************
+    WriteHeader() writes the given header on the given file stream.
+****************************************************************************/
+WriteHeader(header,fp)
+char  *header;
+FILE  *fp;
+{
+    int    header_length, HeaderInt();
+
+    header_length = HeaderInt(header,"header_bytes");
+    fwrite(header,sizeof(char),header_length,fp);
+}
+
+
+/***************************************************************************
+    HeaderString() simply searches through the header for values the  user
+    requests  and  returns  a  pointer  to  the  begining  of  the  value.
+****************************************************************************/
+char *HeaderString( header, name )
+char *header, *name ;
+{
+    register char *next_line = header ;
+    register int name_len = strlen( name ) ;
+
+    do
+	if( strncmp( next_line, name, name_len ) == 0 ) {
+
+	    next_line+=name_len ;
+
+	    if( *next_line++ == '=' )
+		return ( next_line ) ;
+	}
+
+    while( ( next_line = strchr( next_line, '\n' ) + 1 ) != (char *) 0 + 1 ) ;
+
+    return ( (char *) 0 ) ;
+}
+
+
+/***************************************************************************
+    HeaderStringOnly() returns a pointer  to  an  allocated  string  that
+    contains  only  the  value  rather  than  a  pointer  to a string that
+    includes the all the rest of the header which is what  HeaderString()
+    returns.
+****************************************************************************/
+char *HeaderStringOnly( header, name )
+char *header, *name ;
+{
+    char *value = HeaderString( header, name ) ;
+    unsigned value_length ;
+
+    if( value != (char *) 0 ) {
+	value_length = strchr( value, '\n' ) - value ;
+	return ( strncpy( malloc( value_length+1 ), value, (int) value_length ) ) ;
+    }
+    else
+	return ( (char *) 0 ) ;
+}
+
+
+/***************************************************************************
+    HeaderStrings() searches through the header for values the  user
+    requests  and  returns  a  pointer  to  the  begining  of  the  value.
+    This is a version of HeaderString() which allows abbreviated names,
+    return null ptr if not found or ambiguous.
+****************************************************************************/
+char *HeaderStrings( header, name )
+char *header, *name ;
+{
+    register char *next_line = header ;
+    register int name_len = strlen( name ) ;
+    char *valptr ;
+    int   count = 0 ;
+
+    do
+	if( strncmp( next_line, name, name_len ) == 0 ) {
+
+	    next_line+=name_len ;
+
+	    if ( ( valptr = strchr( next_line, '=' ) ) != (char *)0 ) {
+
+		/* return directly if name matches exactly otherwise wait to check ambiguity */
+		if ( valptr == next_line ) return ( valptr + 1 ) ;
+
+		valptr++ ;
+		count++ ;
+	    }
+	}
+
+    while( ( next_line = strchr( next_line, '\n' ) + 1 ) != (char *) 0 + 1 ) ;
+
+    if( count == 1 )
+	return ( valptr ) ;
+    else
+	return ( (char *) 0 ) ; /* not found or ambiguous */
+}
+
+
+/***************************************************************************
+    HeaderNameString() returns a pointer  to  an  allocated  string  that
+    contains  the full name corresponding to the given name, which can be
+    given in abbreviated form provided this is unambiguous.
+    Return a null ptr if the name is not found or is ambiguous.
+    (This is an amalgam of HeaderString() and HeaderStringOnly() which also
+    checks for ambiguity)
+****************************************************************************/
+
+char *HeaderNameString( header, name )
+char *header, *name ;
+{
+    register char *next_line = header ;
+    register int name_len = strlen( name ) ;
+    unsigned name_length ;
+    char *nameptr ;
+    int   count = 0 ;
+
+    do
+	if( strncmp( next_line, name, name_len ) == 0 ) {
+	    if ( strchr( next_line, '=' ) != (char *)0 ) {
+		nameptr = next_line ;
+
+		/* return directly if name matches exactly otherwise wait to check ambiguity */
+		if ( name_len == ( name_length = strchr( next_line, '=' ) - next_line ) )
+		    return ( strncpy( malloc( name_length+1 ), nameptr, (int) name_length ) ) ;
+		count++ ;
+	    }
+	}
+
+    while( ( next_line = strchr( next_line, '\n' ) + 1 ) != (char *) 0 + 1 ) ;
+
+    if( count == 1 ) {
+	name_length = strchr( nameptr, '=' ) - nameptr ;
+	return ( strncpy( malloc( name_length+1 ), nameptr, (int) name_length ) ) ;
+    }
+    else
+	return ( (char *) 0 ) ; /* not found or ambiguous */
+}
+
+
+/***************************************************************************
+    HeaderValueString() returns a pointer  to  an  allocated  string  that
+    contains  the value corresponding to the given name, which can be given
+    in abbreviated form provided this is unambiguous.
+    Return a null ptr if the name is not found or is ambiguous.
+    (This is an amalgam of HeaderString() and HeaderStringOnly() which also
+    checks for ambiguity)
+****************************************************************************/
+
+char *HeaderValueString( header, name )
+char *header, *name ;
+{
+    register char *next_line = header ;
+    register int name_len = strlen( name ) ;
+    unsigned value_length ;
+    char *valptr ;
+    int   count = 0 ;
+
+    do
+	if( strncmp( next_line, name, name_len ) == 0 ) {
+
+	    next_line+=name_len ;
+
+	    if ( ( valptr = strchr( next_line, '=' ) ) != (char *)0 ) {
+
+		/* return directly if name matches exactly otherwise wait to check ambiguity */
+		if ( valptr == next_line ) {
+		    valptr++ ;
+		    value_length = strchr( valptr, '\n' ) - valptr ;
+		    return ( strncpy( malloc( value_length+1 ), valptr, (int) value_length ) ) ;
+		}
+
+		valptr++ ;
+		count++ ;
+	    }
+	}
+
+    while( ( next_line = strchr( next_line, '\n' ) + 1 ) != (char *) 0 + 1 ) ;
+
+    if( count == 1 ) {
+	value_length = strchr( valptr, '\n' ) - valptr ;
+	return ( strncpy( malloc( value_length+1 ), valptr, (int) value_length ) ) ;
+    }
+    else
+	return ( (char *) 0 ) ; /* not found or ambiguous */
+}
+
+
+/***************************************************************************
+    HeaderDouble() converts values to Doubles.
+****************************************************************************/
+double HeaderDouble( header, name )
+char *header, *name ;
+{
+    char  *valuestr ;
+
+    if ( (valuestr = HeaderString( header, name )) == (char *) 0) {
+	fprintf(stderr,"option %s not found in header\n", name);
+	exit(1);
+    }
+    return ( atof( HeaderString( header, name ) ) ) ;
+}
+
+
+/***************************************************************************
+    HeaderInt() converts values to Ints.
+****************************************************************************/
+int HeaderInt( header, name )
+char *header, *name ;
+{
+    char  *valuestr ;
+
+    if ( (valuestr = HeaderString( header, name )) == (char *) 0) {
+	fprintf(stderr,"option %s not found in header\n", name);
+	exit(1);
+    }
+    return ( atoi( valuestr ) ) ;
+}
+
+
+/***************************************************************************
+    HeaderSamplerate() returns the samplerate
+****************************************************************************/
+HeaderSamplerate( header )
+char *header ;
+{
+    char  *valuestr ;
+
+    if ( (valuestr = HeaderStringOnly( header, "samplerate" )) == (char *) 0) {
+	fprintf(stderr,"samplerate not found in header\n");
+	exit(1);
+    }
+    return ( (int)to_Hz( valuestr, 1 ) ) ;
+}
+
+
+/***************************************************************************
+    FreeHeader frees the space allocated for a header by ReadHeader
+****************************************************************************/
+void FreeHeader( header )
+char *header ;
+{
+    free( header ) ;
+    return ;
+}
+
+
+/***************************************************************************
+  ApplicString() return a ptr to the rest of the header which starts with
+  the 3-char application name of the program.
+***************************************************************************/
+
+char *ApplicString( header )
+char *header ;
+{
+    char *versionstr, *progname ;
+
+    if ( ( versionstr = HeaderString( header, "Version" ) ) == (char *)0 )
+	return (char *)( 0 ) ; /* version string not found in header           */
+
+    if ( ( progname = strchr( versionstr, '[' ) ) == (char *)0 )
+	return (char *)( 0 ) ; /* program name not found in version string     */
+    if ( strchr( versionstr, ']' ) - ( progname += 4 ) != 3 )
+	return (char *)( 0 ) ; /* application name not found in version string */
+
+    return ( progname ) ;
+}
+
+
+/***************************************************************************
+  Applic() returns the index number to the gen_applics list (see header.h)
+  of the application name of the program (the last three letters of its name).
+  This is assumed to be delimited by [ ] in the version string in the header.
+  Return a -ve number on error.
+***************************************************************************/
+
+Applic( header )
+char *header ;
+{
+    char *versionstr, *progname ;
+    int   i ;
+
+    if ( ( versionstr = HeaderStringOnly( header, "Version" ) ) == (char *)0 )
+	return ( -2 ) ; /* version string not found in header           */
+
+    if ( ( progname = strchr( versionstr, '[' ) ) == (char *)0 )
+	return ( -3 ) ; /* program name not found in version string     */
+    if ( strchr( versionstr, ']' ) - ( progname += 4 ) != 3 )
+	return ( -4 ) ; /* application name not found in version string */
+    for ( i = 0 ; gen_applics[i] != (char *)0 ; i++ )
+	if ( strncmp( gen_applics[i], progname, 3 ) == 0 )
+	    return i ;
+
+    return ( -1 ) ;     /* application name not found in version string */
+}
+
+
+/**************************************************************************
+
+The table below gives the meaning of the frame parameters for each gen
+program. The frame parameters are frameheight, framewidth, and frames.
+Depending upon the program and the "view", they can mean:
+
+	chans      =  number of filterbank channels.
+	length     =  duration in samples.
+	num frames =  number of cartoon frames.
+	pwidth     =  "positive width" of auditory image.
+	nwidth     =  "negative width" of auditory image.
+
+In all cases framebytes = frameheight * framewidth * sizeof(short)
+
+The table also shows how the frame parameters relate to the format of the
+display, where each of "num frames" frames of a cartoon is described as a
+matrix of "rows" * "cols". The number of rows describes the vertical direction
+and the number of cols describes the horizontal direction.
+
+
+gen         Frame parameters in header                    Format of display matrix
+---     -------------------------------------        ----------------------------------
+	view         height  width     frames        rows        cols        num frames
+	----         ------  -----     ------        ----        ----        ----------
+
+wav     wave         1       1         length        frameheight frames      1
+
+bmm     landscape    chans   1         length        frameheight frames      1
+nap     landscape    chans   1         length        frameheight frames      1
+
+sgm     greyscale    chans   1         length        frameheight frames      1
+cgm     greyscale    chans   1         length        frameheight frames      1
+sas     greyscale    chans   1         length        frameheight frames      1
+
+asa     excitation   chans   1         num frames    framewidth  frameheight frames
+epn     excitation   chans   1         num frames    framewidth  frameheight frames
+sep     excitation   chans   1         num frames    framewidth  frameheight frames
+
+sai     landscape    chans   p+nwidth  num frames    frameheight framewidth  frames
+
+spl     spiral       chans   pwidth    num frames    frameheight framewidth  frames
+
+
+The table below shows the format of the AIM output array for each gen program
+in terms of the frame parameters.
+
+
+gen  Output array format                          Comment
+---  ----------------------------------   -----------------------------
+wav  frames sets of frameheight (=1)      array of time samples.
+
+					  -----------------------------
+bmm  frames sets of frameheight           2-D array by columns,
+nap  frames sets of frameheight             with lowest centre-frequency
+					    first in each column.
+sgm  frames sets of frameheight
+cgm  frames sets of frameheight
+sas  frames sets of frameheight
+
+					  -----------------------------
+asa  frameheight sets of framewidth (=1)  array of frequency samples.
+epn  frameheight sets of framewidth (=1)
+sep  frameheight sets of framewidth (=1)
+
+					  -----------------------------
+sai  frameheight sets of framewidth       2-D array by rows,
+					    with lowest centre-frequency
+spl  frameheight sets of framewidth         row first in each frame.
+
+
+The gen programs group into five format types each with a particular
+interpretation of it's frame parameters, it's output array format, and it's
+"view". These are defined (in header.h) as:
+
+Format  gen programs
+------  --------------
+WAV     wav
+NAP     bmm, nap
+SGM     sgm, cgm, sas
+EPN     asa, epn, sep
+SAI     sai, spl
+
+
+
+
+
+***************************************************************************/
+
+
+
+
+
+/**************************************************************************
+  Format() returns the index number to the gen_formats list (see header.h)
+  of the given application number (eg returned by Applic()).
+   0 = wave format (array of time points)
+   1 = nap format  (by columns, lowest centre-frequency first in each column)
+   2 = sgm format  (by columns, lowest centre-frequency first in each column)
+   3 = epn format  (array of frequency points per frame)
+   4 = sai format  (by rows, lowest centre-frequency row first per frame)
+***************************************************************************/
+
+Format( applic )
+int  applic ;
+{
+    switch ( applic ) {
+
+	case 0 :                        return ( 0 ) ;
+
+	case 1 :  case 2 :  case 3 :
+	case 4 :  case 5 :  case 6 :
+	case 7 :                        return ( 1 ) ;
+
+	case 8 :  case 9 :  case 10:    return ( 2 ) ;
+
+	case 11:  case 12:  case 13:    return ( 3 ) ;
+
+	case 14:  case 15:              return ( 4 ) ;
+
+	default : fprintf( stderr,"unknown application index number\n" ) ;
+		  exit( 1 ) ;
+    }
+}
+
+
+/**************************************************************************
+  frame_to_matrix()
+  Given the format number (see: Format(), Applic() and the gen_formats list
+  in header.h), and the frameheight, framewidth, and frames,
+  return the format of the frames in terms of the number of rows
+  (ie. channels) and columns (ie. samples) per frame, and the number of
+  such frames, via the given addresses.
+  The number of bytes per frame is then = rows * cols * 2.
+***************************************************************************/
+
+frame_to_matrix( format, rows, cols, numframes, frameheight, framewidth, frames )
+int format, *rows, *cols, *numframes, frameheight, framewidth, frames ;
+{
+    switch ( format ) {
+	case 0 :        *rows      = 1           ;      /* wav format */
+			*cols      = frames      ;
+			*numframes = 1           ;
+			break ;
+
+	case 1 :        *rows      = frameheight ;      /* nap format */
+			*cols      = frames      ;
+			*numframes = 1           ;
+			break ;
+
+	case 2 :        *rows      = frameheight ;      /* sgm format */
+			*cols      = frames      ;
+			*numframes = 1           ;
+			break ;
+
+	case 3 :        *rows      = 1           ;      /* epn format */
+			*cols      = frameheight ;
+			*numframes = frames      ;
+			break ;
+
+	case 4 :        *rows      = frameheight ;      /* sai format */
+			*cols      = framewidth  ;
+			*numframes = frames      ;
+			break ;
+
+	default :       fprintf( stderr,"unknown format number\n" ) ;
+			exit( 1 ) ;
+    }
+}
+
+
+/**************************************************************************
+  matrix_to_frame()
+  Inverse of frame_to_matrix().
+  Given the format number and the format in terms of the number of rows and
+  columns per frame and the number of such frames, return the frameheight,
+  framewidth and frames via the given addresses.
+***************************************************************************/
+
+matrix_to_frame( format, rows, cols, numframes, frameheight, framewidth, frames )
+int format, rows, cols, numframes, *frameheight, *framewidth, *frames ;
+{
+    switch ( format ) {
+	case 0 :        *frameheight = 1         ;      /* wav format */
+			*framewidth  = 1         ;
+			*frames      = cols      ;
+			break ;
+
+	case 1 :        *frameheight = rows      ;      /* nap format */
+			*framewidth  = 1         ;
+			*frames      = cols      ;
+			break ;
+
+	case 2 :        *frameheight = rows      ;      /* sgm format */
+			*framewidth  = 1         ;
+			*frames      = cols      ;
+			break ;
+
+	case 3 :        *frameheight = cols      ;      /* epn format */
+			*framewidth  = 1         ;
+			*frames      = numframes ;
+			break ;
+
+	case 4 :        *frameheight = rows      ;      /* sai format */
+			*framewidth  = cols      ;
+			*frames      = numframes ;
+			break ;
+
+	default :       fprintf( stderr,"unknown format number\n" ) ;
+			exit( 1 ) ;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/header.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,64 @@
+
+#define HEADER_STRING "header_bytes=000000\n"
+#define HEADER_START  "header_bytes="
+#define STRSIZE( _string ) ( sizeof ( _string ) - 1 )
+
+#define ApplicStr( header )     ( gen_applics[ Applic( header ) ] )
+
+
+/* gen applications list */
+
+static char *gen_applics[] = {
+	"wav"   ,   /*  0 */            /* WAV format */
+
+	"fbm"   ,   /*  1 */            /* NAP format */
+	"bmm"   ,   /*  2 */
+	"fbr"   ,   /*  3 */
+	"fbc"   ,   /*  4 */
+	"fbt"   ,   /*  5 */
+	"fbd"   ,   /*  6 */
+	"nap"   ,   /*  7 */
+
+	"sgm"   ,   /*  8 */            /* SGM format */
+	"cgm"   ,   /*  9 */
+	"sas"   ,   /* 10 */
+
+	"asa"   ,   /* 11 */            /* EPN format */
+	"epn"   ,   /* 12 */
+	"sep"   ,   /* 13 */
+
+	"sai"   ,   /* 14 */            /* SAI format */
+	"spl"   ,   /* 15 */
+   ( char * ) 0 } ;
+
+
+/* gen formats list */
+
+#define WAV     0
+#define NAP     1
+#define SGM     2
+#define EPN     3
+#define SAI     4
+
+static char *gen_formats[] = {
+	"wav"   ,   /*  0 */
+	"nap"   ,   /*  1 */
+	"sgm"   ,   /*  2 */
+	"epn"   ,   /*  3 */
+	"sai"   ,   /*  4 */
+   ( char * ) 0 } ;
+
+
+extern char  *ReadHeader()        ;
+extern char  *HeaderString()      ;
+extern char  *HeaderStringOnly()  ;
+extern char  *HeaderStrings()     ;
+extern char  *HeaderValueString() ;
+extern char  *HeaderNameString()  ;
+extern char  *ApplicString()      ;
+extern double HeaderDouble()      ;
+extern int    HeaderInt()         ;
+extern int    HeaderSamplerate()  ;
+extern int    Applic()            ;
+extern int    Format()            ;
+extern void   FreeHeader()        ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/integframe.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,175 @@
+/*
+    integrate.c    Integrate (ie average) SAI frames over time or frequency.
+    -----------
+
+    Sequence of frames must have an SAI header.
+    The whole of every frame read in is integrated (in either time or freq).
+    Use edframe to set integration limits and select frames.
+    The output is a sequence of arrays without a header, one per input frame,
+    each of length `framewidth'.
+    If `average=on' the output is one array of length `framewidth' which is
+    the average of the sequence of arrays.
+
+    Example:
+
+1. Integrate the 2nd SAI frame over time from 10ms to 20ms.
+  gensai output=stdout ... | select frame=2 time=10ms-20ms  |  integrate var=time  >  ...
+
+2. Integrate the 2nd SAI frame over frequency from channels 5 to 8 inclusive.
+  gensai output=stdout ... | select frame=2 freq=5-8  |  integrate var=time  >  ...
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "header.h"
+#include "options.h"
+#include "strmatch.h"
+
+
+char applic[]     = "Integrate SAI frames over time or frequency. " ;
+
+static char *helpstr, *debugstr, *varstr, *avstr, *typestr, *infostr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                          , DEBUG },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                              , DEBUG },
+    {   "variable"  ,   "time"      ,  &varstr      ,   "variable of integration (time or frequency)"   , VAL   },
+    {   "average"   ,   "off"       ,  &avstr       ,   "average all integrated frames"                 , VAL   },
+    {   "type"      ,   "short"     ,  &typestr     ,   "output data type"                              , VAL   },
+    {   "info"      ,   "off"       ,  &infostr     ,   "print frame size info"                         , VAL   },
+   ( char * ) 0 } ;
+
+
+int     frameheight, framewidth ;       /* Parameters read from header */
+int     framebytes ;
+int     average    ;
+int     type       ;
+
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE   *fp ;
+    char   *header, *SaiHeader();
+    short  *frame ;
+    float  *buf, *avbuf ;
+    int     i, j, k, n ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    average = ison( avstr ) ;
+    if ( ( type = typeindex( typestr ) ) < 0 ) {
+	fprintf( stderr, "integframe: bad type [%s]\n", typestr ) ;
+	exit( 1 ) ;
+    }
+
+    if ( (header = ReadHeader(fp)) == (char *) 0 ) {
+	fprintf(stderr,"integrate: header not found\n");
+	exit(1);
+    }
+
+    frameheight = HeaderInt( header, "frameheight" );
+    framewidth =  HeaderInt( header, "framewidth"  );
+    framebytes =  HeaderInt( header, "framebytes"  );
+
+    if ( ison( infostr ) )
+	fprintf( stderr,"frameheight=%d  framewidth=%d\n", frameheight, framewidth ) ;
+
+    /* Allocate space for framebytes of data */
+
+    if ( (frame = (short *)malloc( framebytes )) == (short *)0 ) {
+	fprintf(stderr,"integrate: malloc out of space\n");
+	exit(1);
+    }
+
+    if ( iststr( varstr, "time" ) ) {
+	if ( (buf = (float *)malloc( frameheight * sizeof( float ) )) == (float *)0 ) {
+	    fprintf(stderr,"integrate: malloc out of space\n");
+	    exit(1);
+	}
+	if ( average ) {
+	    if ( (avbuf = (float *)malloc( frameheight * sizeof( float ) )) == (float *)0 ) {
+		fprintf(stderr,"integrate: malloc out of space\n");
+		exit(1);
+	    }
+	    for ( i=0 ; i<frameheight ; i++ )
+		avbuf[i] = 0 ;
+	}
+	for ( n = 0 ; fread( frame,framebytes,1,fp ) ; n++ ) {
+	    for ( i=0, j=0 ; i<frameheight ; i++, j+=framewidth )
+		buf[i] = frame[j] ;
+	    for ( k=1 ; k<framewidth ; k++)
+		for ( i=0, j=k ; i<frameheight ; i++, j+=framewidth )
+		    buf[i] += frame[j] ;
+	    if ( average )
+		for ( i=0 ; i<frameheight ; i++ )
+		    avbuf[i] += ( buf[i] / framewidth ) ;
+	    else {
+		for ( i=0 ; i<frameheight ; i++ ) {
+		    buf[i] = buf[i] / framewidth ;
+		    writeitem( &buf[i], type, 1, stdout ) ;
+		}
+	    }
+	}
+	if ( average && n > 0 )  {
+	    for ( i=0 ; i<frameheight ; i++ ) {
+		avbuf[i] = avbuf[i] / n ;
+		writeitem( &avbuf[i], type, 1, stdout ) ;
+	    }
+	}
+    }
+
+    else if ( iststr( varstr, "frequency" ) ) {
+	if ( (buf = (float *)malloc( framewidth * sizeof( float ) )) == (float *)0 ) {
+	    fprintf(stderr,"integrate: malloc out of space\n");
+	    exit(1);
+	}
+	if ( average ) {
+	    if ( (avbuf = (float *)malloc( framewidth * sizeof( float ) )) == (float *)0 ) {
+		fprintf(stderr,"integrate: malloc out of space\n");
+		exit(1);
+	    }
+	    for ( i=0 ; i<framewidth ; i++ )
+		avbuf[i] = 0 ;
+	}
+	for ( n = 0 ; fread( frame,framebytes,1,fp ) ; n++ ) {
+	    for ( i=0 ; i<framewidth ; i++ )
+		buf[i] = frame[i] ;
+	    for ( k=1 ; k<frameheight ; k++)
+		for ( i=0, j=k*framewidth ; i<framewidth ; i++, j++ )
+		    buf[i] += frame[j] ;
+	    if ( average ) {
+		for ( i=0 ; i<framewidth ; i++ )
+		    avbuf[i] += ( buf[i] / frameheight ) ;
+	    }
+	    else {
+		for ( i=0 ; i<framewidth ; i++ ) {
+		    buf[i] = buf[i] / frameheight ;
+		    writeitem( &buf[i], type, 1, stdout ) ;
+		}
+	    }
+	}
+	if ( average && n > 0 )  {
+	    for ( i=0 ; i<framewidth ; i++ ) {
+		avbuf[i] = avbuf[i] / n ;
+		writeitem( &avbuf[i], type, 1, stdout ) ;
+	    }
+	}
+    }
+
+    else {
+	fprintf( stderr,"unknown variable of integration [%s]\n", varstr ) ;
+	exit( 1 ) ;
+    }
+
+    if ( ison( infostr ) )
+	fprintf( stderr,"frames=%d\n", n ) ;
+
+    fclose( fp ) ;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/loudness.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,147 @@
+/***************************************************************************
+ loudness.c     Loudness measure from spiral sector-weights contour.
+ ----------
+			Michael Allerhand, 1992.
+
+	Read m binary shorts (default m=SECTORS) for each specified frame.
+	Compute the loudness as the mean value of the sector-weights.
+
+****************************************************************************/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[] = "Loudness measure from spiral sector-weights contour.\n           (Input and output in binary shorts)." ;
+
+static char *helpstr, *debugstr, *fstr, *sstr, *mstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                        , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"            , DEBUG   },
+    {   "frames"    ,   "1-max"     ,  &fstr        ,   "select frames inclusively"   , VAL     },
+    {   "scale"     ,   "1.848"     ,  &sstr        ,   "scale factor"                , SVAL    },
+    {   "nsectors"  ,   "64"        ,  &mstr        ,   "number of sectors"           , SVAL    },
+   ( char * ) 0 } ;
+
+
+main (argc, argv)
+int    argc;
+char **argv;
+{
+    FILE   *fp;
+    int     m;                  /* Number of sectors around spiral.     */
+    short  *sector;             /* Sector-weights contour.              */
+    float   scalar;             /* Scale factor for loudness.           */
+    int     i, a, b;
+    char   *val1, *val2 ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    m = atoi( mstr ) ;
+    scalar = atof( sstr ) ;
+
+    /* parse bounds on number of frames */
+
+    if ( getvals( fstr, &val1, &val2, "-" ) == BADVAL ) {
+	fprintf(stderr,"loudness: bad frame selector [%s]\n", fstr ) ;
+	exit( 1 ) ;
+    }
+    a = atoi( val1 ) ;
+    if ( isempty( val2 ) )    b = a ;
+    else if ( ismax( val2 ) ) b = 0 ;
+    else                      b = atoi( val2 ) ;
+
+    if (b<a && b>0) fprintf(stderr,"loudness: warning, bad frame specifiers\n");
+
+    if ( ison( debugstr ) ) {
+	printf("a=%d b=%d m=%d scalar=%.3f\n",
+		a, b, m, scalar );
+	exit(0);
+    }
+
+
+    /* Allocate space for sector-weights contour */
+
+    if (( sector = (short *)malloc(m*sizeof(short))) == NULL)
+	    fprintf(stderr,"loudness: malloc out of space\n");
+
+    /* Seek past a-1 frames, then read the next b-a+1 frames, or all    */
+    /* remaining frames if b==0.                                        */
+
+    if (a>0) {
+
+	for (i=1 ; i<a  && fread(sector,sizeof(short),m,fp) ; i++)
+	    ;
+	if (b > 0)
+	    for (  ; i<=b && fread(sector,sizeof(short),m,fp) ; i++)
+		loudness(sector,m,scalar);
+	else
+	    while ( fread(sector,sizeof(short),m,fp) )
+		loudness(sector,m,scalar);
+    }
+
+    fclose(fp);
+}
+
+
+loudness(sector,m,scalar)
+short  *sector;         /* Sector-weights contour.                  */
+int     m;              /* Number of sectors around spiral.         */
+float   scalar;         /* Scale factor for loudness measure.       */
+{
+    short   scale;      /* Mean weights.                            */
+
+    scale = (short)( normalize_scale(sector,m) * scalar );
+    fwrite(&scale,sizeof(short),1,stdout);
+
+}
+
+
+/****************************************************************************
+    Normalize Scale.
+****************************************************************************/
+
+/*
+Normalize for unit variance and zero mean, and then scale for MEAN and STDDEV.
+In general the stddev is scaled down to STDDEV, but if the stddev is already
+less than the target STDDEV, than it is left alone.
+*/
+
+#define MEAN    100
+#define STDDEV  32       /* Resulting variance will be this squared */
+
+normalize_scale(V,m)
+short *V;
+int    m;
+{
+    int   i;
+    float mean, var;
+    float sum, sumsq, stddev, norm;
+
+    sum=0; sumsq=0;
+    for (i=0 ; i<m ; i++) {
+	sum   += V[i];
+	sumsq += V[i] * V[i];
+    }
+    mean = sum/m;
+    var  = sumsq/m - mean*mean;
+
+    if ((stddev = sqrt(var)) >= STDDEV)
+	for (i=0 ; i<m ; i++) {
+	    norm = ( (float)V[i] - mean ) / stddev;
+	    V[i] = norm * STDDEV + MEAN;
+	}
+    else
+	for (i=0 ;  i<m ; i++) {
+	    norm = (float)V[i]-mean;
+	    V[i] = norm + MEAN;
+	}
+
+    return (int)mean;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/makefile	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,123 @@
+#############################################################################
+#
+#
+#       Makefile for AIM tools  - Michael Allerhand 1993
+#
+#  Machine defaults:-
+#
+#  on DEC:
+#               CC        =  cc
+#               CFLAGS    =  -O  -I/usr/include
+#               LDFLAGS   =  -L/usr/lib -lX11 -lm
+#  on SUN:
+#               CC        =  cc
+#               CFLAGS    =  -O  -I/usr/openwin/include
+#               LDFLAGS   =  -L/usr/lib -lX11 -lm
+#  on SUN (gcc):
+#               CC        =  gcc        (eg: /usr/local/bin/gcc)
+#               CFLAGS    =  -O2  -I/usr/openwin/include
+#               LDFLAGS   =  -L/usr/lib -lX11 -lm
+#
+#  on SUN (using APU local sun Xlib server):
+#               CC        =  cc
+#               CFLAGS    =  -O  -I/usr/local2/include
+#               LDFLAGS   =  -L/usr/local2/lib -lX11 -lm
+#
+#
+
+
+.c.o :
+	$(CC) $(CFLAGS)  -c $<
+
+
+OBJS = hdr           atob          btoa            bufwave           \
+       bufframe                                                      \
+       chi           convert       edframe         edwave            \
+       fbank         ftoa          ftos            gate              \
+       integframe    loudness      merge           naptosai          \
+       noise         op            pitch_strength  ptrain            \
+       ramp          saitonap      scale           sp_weights        \
+       stats         step          stof            swab              \
+       tone          filt1
+
+SOBJS = acf          acgram        audim           conv              \
+	fft          ftgram        racf            smooth            \
+	gauss        cosine
+
+XOBJS = x11fonts     x11gram       x11play         x11plot
+
+
+$(OBJS) : strmatch.o options.o units.o header.o $$@.o
+
+$(XOBJS) : x11coord.o $$@.o
+
+$(SOBJS) : strmatch.o options.o units.o header.o sigproc.o  $$@.o
+
+
+############################################################################
+# dependencies
+
+x11gram.o        : x11coord.h
+x11fonts.o       : x11coord.h
+x11play.o        : x11coord.h
+x11plot.o        : x11coord.h
+x11coord.o       : x11coord.h
+
+strmatch.o       : strmatch.h
+options.o        : options.h strmatch.h
+units.o          : units.h strmatch.h
+header.o         : header.h units.h
+sigproc.o        : sigproc.h
+
+ftos.o           : options.h
+stof.o           : options.h
+
+op.o             : options.h strmatch.h
+
+hdr.o            : strmatch.h header.h
+
+integframe.o     : options.h strmatch.h header.h
+ftoa.o           : options.h strmatch.h header.h
+
+atob.o           : options.h units.h strmatch.h
+btoa.o           : options.h units.h strmatch.h
+edwave.o         : options.h units.h strmatch.h
+bufwave.o        : options.h units.h strmatch.h
+convert.o        : options.h units.h strmatch.h
+loudness.o       : options.h units.h strmatch.h
+pitch_strength.o : options.h units.h strmatch.h
+ptrain.o         : options.h units.h strmatch.h
+tone.o           : options.h units.h strmatch.h
+merge.o          : options.h units.h strmatch.h
+noise.o          : options.h units.h strmatch.h
+ramp.o           : options.h units.h strmatch.h
+swab.o           : options.h units.h strmatch.h
+stats.o          : options.h units.h strmatch.h
+scale.o          : options.h units.h strmatch.h
+chi.o            : options.h units.h strmatch.h
+filt1.o          : options.h units.h strmatch.h
+step.o           : options.h units.h strmatch.h
+gate.o           : options.h units.h strmatch.h
+
+naptosai.o       : options.h units.h strmatch.h header.h
+saitonap.o       : options.h units.h strmatch.h header.h
+bufframe.o       : options.h units.h strmatch.h header.h
+sp_weights.o     : options.h units.h strmatch.h header.h
+
+fbank.o          : options.h units.h strmatch.h header.h freqs.c
+edframe.o        : options.h units.h strmatch.h header.h freqs.c
+
+fft.o            : options.h units.h strmatch.h sigproc.h
+acf.o            : options.h units.h strmatch.h sigproc.h
+racf.o           : options.h units.h strmatch.h sigproc.h
+conv.o           : options.h units.h strmatch.h sigproc.h
+smooth.o         : options.h units.h strmatch.h sigproc.h
+gauss.o          : options.h units.h strmatch.h sigproc.h
+cosine.o         : options.h units.h strmatch.h sigproc.h
+
+acgram.o         : options.h units.h strmatch.h header.h sigproc.h
+ftgram.o         : options.h units.h strmatch.h header.h sigproc.h
+audim.o          : options.h units.h strmatch.h header.h sigproc.h
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/merge.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,362 @@
+/*
+    merge.c     Merge N streams onto stdout using given operator.
+    -------
+
+ Usage:  merge  [options]  file1  file2  ...  fileN
+
+ For each vector of items (p1,p2,...,pN) read from file1, file2,...,fileN
+ respectively write the result of a merging operation on the stdout.
+
+ An input item is a number depending upon the type option.
+ The output item has the same type as that selected for input.
+
+ Internal processing is in floating point. A scale factor is included to
+ avoid overflow when casting output data.
+ If 16-bit over or under-flow occurs a warning is printed on the stderr.
+
+ The `range' option sets the start and duration of the process.
+ Its arguments are of the form: range=a-b (where start=a and duration=b-a+1)
+			    or: range=a   (where start=a and duration=1    )
+ The arguments can be in time units (ms, s) or samples (no units), and both
+ "min" (start of file) and "max" (end of file) are recognised.
+ Samples in a file are numbered 0,1,2,...,max.
+
+ All files are interpreted as functions sampled with origin at the point in
+ the file given by the first argument of the `range' option.
+ The functions are assumed to be zero for all samples beyond those specified
+ in the files.
+
+ The `phase' option shifts the origin to introduce a phase difference between
+ files. The `phase' option takes as argument a comma-separated list of
+ arguments which must be the same length as the number of file arguments.
+ Each argument can be in time units (ms, s) or samples (no units).
+ A +ve phase advances the origin into the file.
+ A -ve phase retards the origin. If a negative phase in combination with
+ the start of the file as set by the `range' option results in a new origin
+ outside the specified file, then the difference is padded with zeroes.
+
+ The weights option takes as argument a comma-separated list of real numbers
+ which must be the same length as the number of file arguments.
+ These number are applied as weights to each item prior to the merging
+ operation.
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "strmatch.h"
+#include "units.h"
+
+char applic[] = "Merge N streams onto stdout using given operator." ;
+char usage[]  = "merge [options] file1 file2 ... fileN" ;
+
+static char *helpstr,   *debugstr,  *sampstr,   *opstr      ;
+static char *phstr,     *rangestr,  *scalestr,  *typestr    ;
+static char *wtstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                  , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                      , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "                           , VAL     },
+    {   "operator"  ,   "mean"      ,  &opstr       ,   "operator for merging"                  , VAL     },
+    {   "phase"     ,   "off"       ,  &phstr       ,   "phase shift (phi1,...,phiN)"           , VAL     },
+    {   "weights"   ,   "off"       ,  &wtstr       ,   "weight coefficients (w1,...,wN)"       , VAL     },
+    {   "range"     ,   "0-max"     ,  &rangestr    ,   "inclusive time range for all files"    , VAL     },
+    {   "scale"     ,   "1.0"       ,  &scalestr    ,   "scale factor for output"               , VAL     },
+    {   "type"      ,   "short"     ,  &typestr     ,   "datatype"                              , VAL     },
+   ( char * ) 0 } ;
+
+char *operator[] = {
+    "cat"      ,
+    "add"      ,
+    "subtract" ,
+    "multiply" ,
+    "divide"   ,
+    "abs"      ,
+    "max"      ,
+    "min"      ,
+    "mean"     ,
+    "norm"     ,
+   ( char * ) 0 } ;
+
+
+#define Cat          0  /* Functions (index of operator list) */
+#define Add          1
+#define Subtract     2
+#define Multiply     3
+#define Divide       4
+#define Abs          5
+#define Max          6
+#define Min          7
+#define Mean         8
+#define Norm         9
+
+#define sq(p)           ((p)*(p))
+
+int     samplerate ;
+int     bytes      ;
+int     type       ;    /* datatype index */
+int     op         ;    /* operator index */
+float   scale      ;
+
+
+main(argc, argv)
+int    argc;
+char **argv;
+{
+    FILE  **fp ;
+    float  *vec, *weight ;
+    int    *origin ;
+    char  **list ;
+    int     i, j, n, morehelp() ;
+    int     a, b ;
+    float   writevec(), f, newscale = 1. ;
+
+    if ( ( i = getopts( option, argc, argv ) ) == 0 || !isoff( helpstr ) )
+	helpopts2( helpstr, argv[0], applic, usage, option, morehelp ) ;
+
+    samplerate  = to_Hz( sampstr, 0 ) ;
+    scale       = atof( scalestr ) ;
+    op          = opindex( opstr ) ;
+
+    if ( ( type = typeindex( typestr ) ) < 0 ) {
+	fprintf( stderr, "merge: bad type [%s]\n", typestr ) ;
+	exit( 1 ) ;
+    }
+    bytes = typebytes( type ) ;
+
+    if ( range( rangestr, &a, &b, samplerate ) == 0 ) {
+	fprintf(stderr,"merge: bad range [%s]\n", rangestr ) ;
+	exit( 1 ) ;
+    }
+
+
+    fp     = (FILE **)malloc( i * sizeof( FILE *) ) ;
+    vec    = (float *)malloc( i * sizeof( float ) ) ;
+    origin = (int   *)malloc( i * sizeof( int   ) ) ;
+
+
+    if ( isoff( wtstr ) ) weight = (float *)0 ;
+    else {
+	list   = (char **)malloc( i * sizeof( char *) ) ;
+	weight = (float *)malloc( i * sizeof( float ) ) ;
+	if ( ( n = tokens( wtstr, list, i, ',' ) ) != i ) {
+	    fprintf( stderr,"merge: incorrect number of weights\n" ) ;
+	    exit( 1 ) ;
+	}
+	for ( j = 0 ; j < n ; j++ )
+	    weight[j] = atof( list[j] ) ;
+    }
+
+    if ( isoff( phstr ) )
+	for ( j = 0 ; j < i ; j++ )
+	    origin[j] = a ;
+    else {
+	list   = (char **)malloc( i * sizeof( char *) ) ;
+	if ( ( n = tokens( phstr, list, i, ',' ) ) != i ) {
+	    fprintf( stderr,"merge: incorrect number of phases\n" ) ;
+	    exit( 1 ) ;
+	}
+	for ( j = 0 ; j < n ; j++ )
+	    origin[j] = a + to_p( list[j], samplerate ) ;
+    }
+
+
+
+    for ( n = 0 ; i > 0 ; i--, n++ )  {
+	if ( ( fp[n] = fropen( argv[argc-i] ) ) == (FILE *)0 ) {
+	    fprintf( stderr,"merge: can't open %s\n", argv[argc-i] ) ;
+	    exit( 1 ) ;
+	}
+    }
+
+
+    for ( i = 0 ; i < n ; i++ )
+	if ( origin[i] > 0 )
+	    if ( seekstart( origin[i], bytes, fp[i] ) < origin[i] ) {
+		fprintf( stderr, "insufficient data in file%d\n", i+1 ) ;
+		exit( 1 ) ;
+	    }
+
+
+    for ( i = a ; ( i <= b || b == (-1) ) && readvec( vec, n, fp, type, origin ) ; i++ ) {
+
+	if ( weight != (float *)0 )
+	    do_weights( vec, weight, n ) ;
+
+	j = do_operation( vec, n, op ) ;
+	if ( ( f = writevec( vec, j, type, scale ) ) < newscale )
+	    newscale = f ;
+    }
+
+    if ( newscale < 1. )
+	fprintf( stderr, "Warning: 16-bit overflow during merge. Try scale<%.4f\n", newscale ) ;
+
+}
+
+
+/*
+Return the operator index (to the operator list) of the given operator string.
+*/
+
+int opindex( opstr )
+char *opstr ;
+{
+    int  i ;
+
+    if ( ( i = listindex( operator, opstr ) ) < 0 ) {
+	if ( i == (-1) )
+	    fprintf(stderr,"merge: unknown operator [%s]\n", opstr ) ;
+	if ( i == (-2) )
+	    fprintf(stderr,"merge: ambiguous operator [%s]\n", opstr ) ;
+	exit( 1 ) ;
+    }
+    return i ;
+}
+
+
+
+/*
+Assign the given n-vector of floats using one item of given type (an index
+to the datatype list in options.h) read from each of the n streams given in
+the fp array. Return 0 if eof on any stream, otherwise return 1.
+If the stream origin < 0 read a value of 0, increment the origin, and return
+1 (successful read).
+*/
+
+readvec( vec, n, fp, type, origin )
+float  *vec  ;
+int     n    ;
+FILE  **fp   ;
+int     type ;
+int    *origin ;
+{
+    int  i ;
+
+    for ( i = 0 ; i < n ; i++ ) {
+
+	if ( origin[i] < 0 ) {
+	    vec[i] = 0  ;
+	    origin[i]++ ;
+	}
+
+	else if ( readitem( &vec[i], type, 1, fp[i] ) == 0 )
+	    return 0 ;
+
+    }
+    return 1 ;
+}
+
+
+/*
+Write n elements from the given vector on the stdout in the given type
+(an index to the datatype list in options.h)
+Multiply each element by the given scale factor (prior to type conversion).
+If any element will over or underflow when scaled and cast into type
+then return a more appropriate scale factor.
+Return scale factor of 1 if no over or underflow.
+*/
+
+float writevec( vec, n, type, scale )
+float *vec  ;
+int    n    ;
+int    type ;
+float  scale;
+{
+    float newscale ;
+    int   i ;
+
+
+    for ( i = 0 ; i < n ; i++ ) {
+
+	newscale = check_overflow( vec[i], scale, type ) ;
+
+	vec[i] *= scale ;
+	writeitem( &vec[i], type, 1, stdout ) ;
+    }
+
+    return ( newscale ) ;
+}
+
+
+
+/*
+Perform the given operation (op is an index to the operations list) on the
+given n-vector, storing the results in the vector.
+Return the size of the result (the number of elements of vec it occupies).
+*/
+
+do_operation( vec, n, op )
+float *vec  ;
+int    n    ;
+int    op   ;
+{
+    int  i ;
+
+    switch ( op ) {
+
+	case Cat      : return n ;
+	case Add      : for ( i = 1 ; i < n ; i++ )
+			    vec[0] += vec[i] ;
+			return 1 ;
+	case Subtract : for ( i = 1 ; i < n ; i++ )
+			    vec[0] -= vec[i] ;
+			return 1 ;
+	case Abs      : for ( i = 1 ; i < n ; i++ )
+			    vec[0] = fabs(vec[0]-vec[i]) ;
+			return 1 ;
+	case Multiply : for ( i = 1 ; i < n ; i++ )
+			    vec[0] *= vec[i] ;
+			return 1 ;
+	case Divide   : for ( i = 1 ; i < n ; i++ )
+			    vec[0] /= vec[i] ;
+			return 1 ;
+	case Max      : for ( i = 1 ; i < n ; i++ )
+			    if ( vec[i] > vec[0] ) vec[0] = vec[i] ;
+			return 1 ;
+	case Min      : for ( i = 1 ; i < n ; i++ )
+			    if ( vec[i] < vec[0] ) vec[0] = vec[i] ;
+			return 1 ;
+	case Mean     : for ( i = 1 ; i < n ; i++ )
+			    vec[0] += vec[i] ;
+			vec[0] /= n ;
+			return 1 ;
+	case Norm:      vec[0] = sq(vec[0]) ;
+			for ( i = 1 ; i < n ; i++ )
+			    vec[0] += sq(vec[i]) ;
+			vec[0] = sqrt(vec[0]) ;
+			return 1 ;
+    }
+}
+
+
+do_weights( vec, weight, n )
+float *vec    ;
+float *weight ;
+int    n      ;
+{
+    int  i ;
+
+    for ( i = 0 ; i < n ; i++ )
+	vec[i] *= weight[i] ;
+}
+
+
+morehelp()
+{
+    fprintf(stderr,"\noperators:                       \n");
+    fprintf(stderr,"            cat         concatenate  p1,p2,p3,... \n");
+    fprintf(stderr,"            add         p1+p2+p3+...      \n");
+    fprintf(stderr,"            subtract    p1-p2-p3-...      \n");
+    fprintf(stderr,"            abs         ||p1-p2|-p3|-...    \n");
+    fprintf(stderr,"            multiply    p1*p2*p3*...      \n");
+    fprintf(stderr,"            divide      p1/p2/p3/...      \n");
+    fprintf(stderr,"            max         max(p1,p2,p3,...) \n");
+    fprintf(stderr,"            min         min(p1,p2,p3,...) \n");
+    fprintf(stderr,"            mean        mean(p1,p2,p3,...) \n");
+    fprintf(stderr,"            norm        sqrt( p1*p1+p2*p2+p3*p3+... )  \n");
+    exit( 1 ) ;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/naptosai.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,362 @@
+/*
+  naptosai.c            NAP to SAI format conversion.
+ ------------
+
+    Read a NAP header and frame.
+    Write a SAI header, (created from the NAP header).
+    Write a succession of SAI frames.
+
+    The options "start" and "length" specify the NAP which is input.
+    The options "width" and "frstep"  specify the SAI frames which are output.
+
+    Special option values are:
+
+      length=max      Input all the NAP from the given start to its end.
+      width=max       Output framewidth is set equal to the given NAP length,
+		      and if this is also "max", then the framewidth is the
+		      remainder of the NAP.
+      frstep=0        Output one frame of given width from the given start of
+		      the NAP.
+
+    For example, use naptosai with width=max and frstep=0 to produce one SAI
+    frame the same size as the input NAP.
+
+Examples:
+
+
+1. To convert a nap or a bmm output to a single frame of sai output:
+
+gennap length=64 output=stdout file | naptosai width=32 frstep=0 > file.sai
+gensai top=1000 useprevious=on file
+
+genbmm output=stdout file | naptosai  > file.sai
+gensai bottom=-100 useprevious=on file
+
+  This uses special case of zero frstep to generate one frame of output with
+  the given width. The default width is the given length, and the default
+  length is the remainder of the input file. If the width=length, then the
+  frstep is zero by default, and therefore the default process, (ie with no
+  arguments), converts the whole of the input to a single SAI frame.
+
+  Note, certain display parameters have different default values for different
+  applications. The SAI display parameters should be set to the appropriate
+  values, in order to plot the SAI on the same scale. For example:
+    When the source application is NAP, set gensai top=1000
+    When the source application is BMM, set gensai bottom=-100
+
+
+2. To convert a nap output to multiple frames of sai output:
+
+gennap length=40 output=stdout file | naptosai width=32 frstep=0.2 > file.sai
+gensai top=1000 useprevious=on file
+
+   The sai output can be plotted as a spiral, but it is best to set the
+   display parameters as follows:
+
+gennap length=40 output=stdout dencf=1 width=500 height=500 file | \
+				naptosai width=32 frstep=0.2 > file.sai
+genspl useprevious=on pensize=2 file
+
+
+3. To convert a nap output to a sai format bitmap, to display an animated
+   stream:
+
+gennap length=40 output=stdout file | naptosai width=32 frstep=0.2 > file.sai
+gensai top=1000 useprevious=on bitmap=on file
+review file
+
+  The same can be done for the spiral display:
+
+gennap length=40 output=stdout dencf=1 width=500 height=500 file | \
+				naptosai width=32 frstep=0.2 > file.sai
+genspl useprevious=on pensize=2 bitmap=on file
+review file
+
+  The plots show the nap moving though 8ms (40-32), in steps of 0.2ms,
+  first in rectangular display, then in spiral-mapped display.
+
+*/
+
+
+#include <stdio.h>
+#include <math.h>
+#include "header.h"
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[]     = "NAP to SAI format conversion. " ;
+
+static char *helpstr, *debugstr, *startstr, *lengthstr, *widthstr, *shiftstr, *headerstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                          , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"              , DEBUG   },
+    {   "start"     ,   "0"         ,  &startstr    ,   "Start point in i/p NAP"        , VAL     },
+    {   "length"    ,   "max"       ,  &lengthstr   ,   "Length of i/p NAP to process." , VAL     },
+    {   "header"    ,   "on"        ,  &headerstr   ,   "sai header"                    , VAL     },
+    {   "width"     ,   "max"       ,  &widthstr    ,   "Width of o/p SAI frame."       , VAL     },
+    {   "frstep"    ,   "1ms"       ,  &shiftstr    ,   "Step between o/p frames of SAI.\n(frstep=0 gets 1 frame of given width)." , VAL },
+   ( char * ) 0 } ;
+
+
+int     frameheight, framewidth ;       /* Nap parameters read from header */
+int     frames, samplerate ;
+
+int     start, length ;
+
+int     Newframeheight, Newframewidth ; /* Sai parameters to write  */
+int     Newframes ;
+int     Newframeshift ;
+int     Newframebytes ;
+
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE   *fp ;
+    int     i, framebytes, startbytes, frameshift;
+    char   *header, *SaiHeader();
+    short  *nap, *frame, *endframe;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    if ( ison( debugstr ) ) {
+	printf("start=%s length=%s width=%s shift=%s\n",
+		startstr, lengthstr, widthstr, shiftstr );
+	exit(0);
+    }
+
+    if ( (header = ReadHeader(fp)) == (char *) 0 ) {
+	fprintf(stderr,"naptosai: header not found\n");
+	exit(1);
+    }
+
+    frameheight = HeaderInt( header, "frameheight" );
+    framewidth =  HeaderInt( header, "framewidth"  );
+    frames =      HeaderInt( header, "frames"      );
+    samplerate =  HeaderSamplerate( header, "samplerate"  );
+
+    start =  to_p( startstr,  samplerate );
+    if ( ismax( lengthstr ) )   /* Special case for remainder of input */
+	length = frames - start ;
+    else
+	length = to_p( lengthstr, samplerate );
+
+    if ( start + length > frames ) {
+	fprintf(stderr,"naptosai: nap too small (%d ms) for requested start and length \n", to_ms( frames, samplerate ) );
+	exit(1);
+    }
+
+    framebytes = frameheight * length * sizeof(short) ;
+    startbytes = frameheight * start  * sizeof(short) ;
+
+    Newframeheight = frameheight ;
+    if ( ismax( widthstr ) )    /* Special case for single frame of max width */
+	Newframewidth = length ;
+    else
+	Newframewidth = to_p( widthstr, samplerate ) ;
+    Newframeshift = to_p( shiftstr, samplerate ) ;
+    Newframebytes =  Newframeheight * Newframewidth * sizeof(short) ;
+    if ( Newframeshift > 0 )
+	Newframes = 1 + ( length - Newframewidth ) / Newframeshift ;
+    else {              /* Special case of zero shift */
+	Newframes = 1 ;
+	Newframeshift = 1 ;
+    }
+
+    if ( length < Newframewidth ) {
+	fprintf(stderr,"naptosai: nap too small (%d ms) for requested width\n", to_ms( length, samplerate ) );
+	exit(1);
+    }
+
+    fprintf(stderr,"Output %d sai frames, each %d bytes\n", Newframes, Newframebytes );
+
+    if ( ison( headerstr ) )
+	WriteHeader( SaiHeader(header), stdout );
+
+    /* Allocate space for framebytes of nap data */
+
+    if ( (nap = (short *)malloc( framebytes )) == NULL ) {
+	fprintf(stderr,"naptosai: malloc out of space\n");
+	exit(1);
+    }
+
+    /* Seek to start in blocks of framebytes */
+
+    for (i=framebytes ; i < startbytes ; i += framebytes)
+	if ( fread( nap, framebytes, 1, fp ) == NULL ) {
+	    fprintf(stderr,"naptosai: missing data after header\n");
+	    exit(1);
+	}
+    if ( (startbytes -= (i - framebytes)) > 0 )
+	if ( fread( nap, startbytes, 1, fp ) == NULL ) {
+	    fprintf(stderr,"naptosai: missing data after header\n");
+	    exit(1);
+	}
+
+    /* Read framebytes of i/p nap data */
+
+    if ( fread( nap, framebytes, 1, fp ) == NULL ) {
+	fprintf(stderr,"naptosai: missing data after header\n");
+	exit(1);
+    }
+
+    frameshift = Newframeshift * Newframeheight ;
+    endframe = nap + Newframes * frameshift ;
+
+    for ( frame = nap ; frame < endframe ; frame += frameshift )
+	writeframe( frame, stdout ) ;
+
+    fprintf(stderr,"naptosai done\n" ) ;
+
+}
+
+
+
+/* Write a frame in sai format */
+
+writeframe( frame, fp )
+short  *frame ;
+FILE   *fp ;
+{
+    int    i, row, col;
+
+    for (row=0 ; row < Newframeheight ; row++)
+	for (col=0 , i=row ; col < Newframewidth ; col++, i+=Newframeheight)
+	    fwrite( &frame[i], sizeof(short), 1, fp );
+}
+
+
+/*********************** Read header and build new header *****************/
+
+/*
+   Copy the original nap header to a new sai header, changing in order:
+     frames
+     frameshift
+     framewidth
+     frameheight
+     framebytes
+   Then change applic name [gennap] to [gensai] in the Version string.
+   Finally, update the new header_bytes, and return the new header.
+*/
+
+char *SaiHeader( napheader )
+char *napheader ;
+{
+    char *saiheader;
+    char *p0, *p1, *p2, *s, str[64];
+
+    saiheader = (char *)malloc( strlen(napheader) + 64 ) ;
+
+    p0 = saiheader ;
+    p1 = napheader ;
+
+
+    /** copy up to frames **/
+
+    p2 = HeaderString( napheader , "frames" ) ;
+    while( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframes);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to frameshift **/
+
+    p2 = HeaderString( napheader , "frameshift" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframeshift);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to framewidth **/
+
+    p2 = HeaderString( napheader , "framewidth" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframewidth);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to frameheight **/
+
+    p2 = HeaderString( napheader , "frameheight" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframeheight);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to framebytes **/
+
+    p2 = HeaderString( napheader , "framebytes" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", Newframebytes);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy rest of header **/
+
+    p2 = HeaderString( napheader , "Version" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    while (*p1 != ']')          /* change applic name [gennap] to [gensai] */
+	*p0++ = *p1++ ;
+    *(p0-3) = 's' ;
+    *(p0-2) = 'a' ;
+    *(p0-1) = 'i' ;
+    while (*p1 != '\n')
+	*p0++ = *p1++ ;
+    *p0++ = *p1++ ;
+
+
+    /** update header_bytes **/
+
+    sprintf(str, "%0*d", 7, p0-saiheader);
+    p0 = HeaderString( saiheader , "header_bytes" ) ;
+    s = str;
+    while(*p0 != '\n')
+	*p0++ = *s++ ;
+
+
+    return saiheader;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/noise.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,171 @@
+/*
+   noise.c   generate samples of a normally distributed deviate (white noise)
+   -------   in binary shorts or floats.
+
+
+   The routine gasdev returns normally distributed numbers with zero mean
+   and unit variance, using the Box-Muller method described in Numerical
+   recipes [p203]. It is based upon a random number generator ran1 which
+   generates uniformly distributed numbers in the range [0,1].
+
+   The period of the random sequences is claimed to be infinite,
+   [Numerical recipes, p196].
+   Random sequences which repeat can be heard as periodic if the sequence
+   repeats every 4secs or less. Therefore the period of a random sequence
+   should be greater than 5secs, or 100000 samples (at 20kHz samplerate).
+
+   The seed of each random sequence is the variable "seed", which should be
+   set to any negative value to initialize or re-initialize the sequence,
+   [Numerical recipes, p196]. The same seed gives the same random sequence.
+   Otherwise, (and by default when seed=off or seed=0), the system call
+   getpid() supplies a new seed each run.
+
+   Each sample is scaled using the given mean and variance parameters so that
+   samples are drawn from a normal distribution of given mean and variance.
+*/
+
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[]  = "generate white noise. " ;
+char usage[]   = "noise [options]" ;
+
+static char *helpstr, *debugstr, *sampstr, *durstr, *meanstr, *varstr, *seedstr, *datastr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                      , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"          , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "               , VAL     },
+    {   "duration"  ,   "500ms"     ,  &durstr      ,   "duration of waveform"      , VAL     },
+    {   "mean"      ,   "0"         ,  &meanstr     ,   "mean value of waveform"    , VAL     },
+    {   "variance"  ,   "500"       ,  &varstr      ,   "variance of values"        , VAL     },
+    {   "seed"      ,   "off"       ,  &seedstr     ,   "seed for random sequence"  , VAL     },
+    {   "type"      ,   "short"     ,  &datastr     ,   "o/p datatype (short/float)", VAL     },
+   ( char * ) 0 } ;
+
+
+int     samplerate ;
+int     duration   ;
+float   mean       ;
+float   variance   ;
+int     seed       ;
+
+
+main (argc,argv)
+int    argc;
+char **argv;
+{
+    float gasdev();
+    float n2 ;
+    short n1 ;
+
+    getopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts3( helpstr, argv[0], applic, usage, option ) ;
+
+    samplerate = to_Hz( sampstr, 0 ) ;
+    duration   = to_p( durstr, samplerate ) ;
+    mean       = atof( meanstr ) ;
+    variance   = atof( varstr ) ;
+
+    if ( isoff( seedstr ) )
+	seed = ( -getpid() ) ;
+    else
+	seed = atoi( seedstr ) ;
+
+
+    if ( iststr( datastr, "short" ) )
+	while ( duration-- ) {
+	    n1 = (short)( gasdev( &seed ) * variance + mean ) ;
+	    fwrite( &n1, sizeof(short), 1, stdout ) ;
+	}
+
+    else if ( iststr( datastr, "float" ) )
+	while ( duration-- ) {
+	    n2 = gasdev( &seed ) * variance + mean ;
+	    fwrite( &n2, sizeof(float), 1, stdout ) ;
+	}
+
+    else
+	fprintf(stderr,"noise: unknown datatype [%s]\n", datastr) ;
+}
+
+
+float gasdev( idum )
+int *idum;
+{
+    static int   iset=0;
+    static float gset;
+    float  fac,r,v1,v2;
+    float  ran1();
+
+    if ( iset == 0 ) {
+	do {
+	    v1 = 2.0 * ran1( idum ) - 1.0 ;
+	    v2 = 2.0 * ran1( idum ) - 1.0 ;
+	    r  = v1*v1+v2*v2;
+	} while (r >= 1.0);
+	fac  = sqrt(-2.0*log(r)/r);
+	gset = v1*fac;
+	iset = 1;
+	return v2*fac;
+    }
+    else {
+	iset = 0;
+	return gset;
+    }
+}
+
+
+#define M1 259200
+#define IA1 7141
+#define IC1 54773
+#define RM1 (1.0/M1)
+#define M2 134456
+#define IA2 8121
+#define IC2 28411
+#define RM2 (1.0/M2)
+#define M3 243000
+#define IA3 4561
+#define IC3 51349
+
+float ran1( idum )
+int *idum;
+{
+    static long ix1,ix2,ix3;
+    static float r[98];
+    float temp;
+    static int iff=0;
+    int j;
+
+    if ( *idum < 0 || iff == 0 ) {
+	iff=1;
+	ix1=(IC1-(*idum)) % M1;
+	ix1=(IA1*ix1+IC1) % M1;
+	ix2=ix1 % M2;
+	ix1=(IA1*ix1+IC1) % M1;
+	ix3=ix1 % M3;
+	for (j=1;j<=97;j++) {
+	    ix1=(IA1*ix1+IC1) % M1;
+	    ix2=(IA2*ix2+IC2) % M2;
+	    r[j]=(ix1+ix2*RM2)*RM1;
+	}
+	*idum=1;
+    }
+    ix1=(IA1*ix1+IC1) % M1;
+    ix2=(IA2*ix2+IC2) % M2;
+    ix3=(IA3*ix3+IC3) % M3;
+    j=1 + ((97*ix3)/M3);
+    if (j > 97 || j < 1) {
+	fprintf(stderr, "noise: This cannot happen\n");
+	exit(1);
+    }
+    temp=r[j];
+    r[j]=(ix1+ix2*RM2)*RM1;
+    return temp;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/op.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,492 @@
+/*
+    op.c        Ordered sequence of operations on input stream.
+   ------
+
+    Operations on each input item are done in the order they appear on the
+    command line. Operations can be repeated as many times as needed on the
+    command line.
+
+    Input items may be binary numbers (short or float) or ascii lines
+    (terminated by CR) according to the type option.
+
+    The list of operations is as follows. Some operations take valued
+    arguments (which are real numbers), others are flags, as indicated:
+
+    operation           result for each input item x
+    -----------------   --------------------------------------------
+    add=<value>         x+<value>
+    negate=on           -x
+    multiply=<value>    x*<value>
+    divide=<value>      x/<value>
+    remainder=<value>   real remainder of x/<value>
+    inverse=on          1/x
+    round=on            x rounded to nearest integer
+    absolute=on         |x|
+    power=<value>       x^<value>
+    exponent=<value>    <value>^x
+    e-exponent=on       e^x
+    log=<value>         log(x) to base <value>
+    e-log=on            log(x) to base e.
+    sin=on              sin(x)
+    cos=on              cos(x)
+    tan=on              tan(x)
+    threshold=<value>   if ( x  <value> ) 0 else if ( x = <value> ) 1
+    diff1=on            first difference
+    diff2=on            second difference
+    diff3=on            third difference
+    cusum=on            cumulative sum
+    cumean=on           cumulative (recursive) mean an
+    cumin=on            cumulative min
+    cumax=on            cumulative max
+
+    The `type' option sets the data type for all input and output items.
+    Recognised data types are: short, float, ascii.
+
+
+    Ascii data is read in line-by-line, and comment lines are allowed.
+    The following operation apply only to ascii input items, enabling
+    comment lines to be stripped or echoed directly to the output.
+
+    strip=<value>       ignore lines beginning with <value> string
+    echo=<value>        echo lines beginning with <value> string
+    number=on           number output lines
+			If number=on then stripped lines are
+			not numbered; they simply dissappear.
+
+    If there are no operations, (other than comment stripping/echoing or line
+    numbering), then ascii lines are echoed.
+
+
+Examples:
+
+1. To specify the following ordered sequence of operations on each binary
+float in the input stream: invert (take reciprocal), scale up by 100,
+square (raise to power 2), invert (take reciprocal), square root (raise to
+power 0.5).
+
+op type=float inverse=on multiply=100 power=2 inverse=on power=.5  file
+
+
+2. To use as an interactive "desk calculator", eg to print out the result
+of log2(17/16):
+
+echo 17 | op type=ascii -div16 -log2
+
+3. To interactively operate on a list, eg add 1 to each of the list 1,2,3,
+(note how to put newlines into echo'd lists):
+
+echo "1\
+2\
+3" | op type=ascii -add1
+
+4. To read ascii data, echoing any comment lines beginning with the string
+"**", and for each number x in infile, o/p the number 149-x, do:
+
+op type=ascii echo="**" neg=on -add149  infile > outfile
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "strmatch.h"
+
+char applic[] = "Ordered sequence of operations on each item in input stream.\n     (Input and output in binary shorts)." ;
+
+static char *helpstr, *debugstr,
+		*addstr ,
+		*negstr ,
+		*mulstr ,
+		*divstr ,
+		*remstr ,
+		*invstr ,
+		*rndstr ,
+		*absstr ,
+		*powstr ,
+		*expstr ,
+		*eexpstr,
+		*logstr ,
+		*elogstr,
+		*sinstr ,
+		*cosstr ,
+		*tanstr ,
+		*threshstr,
+		*diff1str  ,
+		*diff2str  ,
+		*diff3str  ,
+		*cusumstr   ,
+		*cumeanstr  ,
+		*cuminstr   ,
+		*cumaxstr   ,
+		*typestr ,
+		*stripstr ,
+		*echostr  ,
+		*numstr    ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                                  , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                                      , DEBUG   },
+    {   "add"       ,   "off"       ,  &addstr      ,   "Add                    x = x+value  "                  , VAL     },
+    {   "negate"    ,   "off"       ,  &negstr      ,   "Negate                 x = -x     "                    , SETFLAG },
+    {   "multiply"  ,   "off"       ,  &mulstr      ,   "Multiply               x = x*value  "                  , VAL     },
+    {   "divide"    ,   "off"       ,  &divstr      ,   "Divide                 x = x/value  "                  , VAL     },
+    {   "remainder" ,   "off"       ,  &remstr      ,   "Remainder              x = real remainder of x/value"  , VAL     },
+    {   "inverse"   ,   "off"       ,  &invstr      ,   "Inverse                x = 1/x    "                    , SETFLAG },
+    {   "round"     ,   "off"       ,  &rndstr      ,   "Round                  x = x, to nearest integer"      , SETFLAG },
+    {   "absolute"  ,   "off"       ,  &absstr      ,   "Absolute               x = |x|    "                    , SETFLAG },
+    {   "power"     ,   "off"       ,  &powstr      ,   "Power                  x = x^value  "                  , VAL     },
+    {   "exponent"  ,   "off"       ,  &expstr      ,   "Exponent               x = value^x  "                  , VAL     },
+    {   "e-exponent",   "off"       ,  &eexpstr     ,   "e-exponent             x = e^x    "                    , SETFLAG },
+    {   "log"       ,   "off"       ,  &logstr      ,   "Log                    x = log(x), base `value'."      , VAL     },
+    {   "e-log"     ,   "off"       ,  &elogstr     ,   "elog                   x = log(x), base e.    "        , SETFLAG },
+    {   "sin"       ,   "off"       ,  &sinstr      ,   "sin                    x = sin(x) "                    , SETFLAG },
+    {   "cos"       ,   "off"       ,  &cosstr      ,   "cos                    x = cos(x) "                    , SETFLAG },
+    {   "tan"       ,   "off"       ,  &tanstr      ,   "tan                    x = tan(x) "                    , SETFLAG },
+    {   "threshold" ,   "off"       ,  &threshstr   ,   "Threshold              x = 0 (x<value) or 1 (x>=value)", VAL     },
+    {   "diff1"     ,   "off"       ,  &diff1str    ,   "First difference "                                     , SETFLAG },
+    {   "diff2"     ,   "off"       ,  &diff1str    ,   "Second difference "                                    , SETFLAG },
+    {   "diff3"     ,   "off"       ,  &diff1str    ,   "Third difference "                                     , SETFLAG },
+    {   "cusum"     ,   "off"       ,  &cusumstr    ,   "Cumulative sum         x = current sum"                , SETFLAG },
+    {   "cumean"    ,   "off"       ,  &cumeanstr   ,   "Cumulative mean        x = current (recursive) mean"   , SETFLAG },
+    {   "cumin"     ,   "off"       ,  &cuminstr    ,   "Cumulative min         x = current min  "              , SETFLAG },
+    {   "cumax"     ,   "off"       ,  &cumaxstr    ,   "Cumulative max         x = current max  "              , SETFLAG },
+    {   "type"      ,   "short"     ,  &typestr     ,   "Data type (short, float, ascii)"                       , VAL     },
+    {   "strip"     ,   "off"       ,  &stripstr    ,   "Ignore lines beginning with value string"              , VAL     },
+    {   "echo"      ,   "off"       ,  &echostr     ,   "Echo lines beginning with value string"                , VAL     },
+    {   "number"    ,   "off"       ,  &numstr      ,   "Number output lines"                                   , SETFLAG },
+   ( char * ) 0 } ;
+
+
+#define SIZE        64  /* Max number of program command-line arguments */
+
+#define Add          2  /* Functions */
+#define Negate       3
+#define Multiply     4
+#define Divide       5
+#define Remainder    6
+#define Inverse      7
+#define Round        8
+#define Absolute     9
+#define Power       10
+#define Exp         11
+#define Eexp        12
+#define Log         13
+#define Elog        14
+#define Sin         15
+#define Cos         16
+#define Tan         17
+#define Threshold   18
+#define Diff1       19
+#define Diff2       20
+#define Diff3       21
+#define Sum         22
+#define Mean        23
+#define Min         24
+#define Max         25
+#define Ascii       26
+#define Strip       27
+#define Echo        28
+#define Number      29
+
+
+/* data types */
+
+#define SHORT        0
+#define FLOAT        1
+#define ASCII        2
+
+int     Type ;
+
+int     STRIP=0;
+char    Stripstr[]="*";         /* Default strip comment string */
+
+int     ECHO=0;
+char    Echostr[]="**";         /* Default echo comment string */
+
+int     NUMBER=0;               /* Flag for numbering ascii lines */
+int     n=0;
+
+/*
+ Rounding for both +ve and -ve numbers. Real numbers are truncated to ints in
+ the direction of zero (EG both 0.9 and -0.9 are truncated to 0). Using round,
+ 0.9 becomes 1 and -0.9 becomes -1. (Note also 0.5 becomes 1, -0.5 becomes -1.
+*/
+#define round(x)    ((x >= 0) ? ((int)(x+0.5)) : ((int)(x-0.5)))
+
+/* Remainder of real division for +ve and -ve numbers */
+#define rem(x,y)    ((x >= 0) ? (fabs((x) - (y)*(int)((x)/(y)))) : (fabs((x) - (y)*(int)((x)/(y)-0.5))))
+
+/* Threshold and convert to binary (0,1) value */
+#define threshold(x,T)  ((x >= T) ? 1 : 0)
+
+float diff1();
+float diff2();
+float diff3();
+float mean();
+float min();
+float max();
+float sum();
+
+struct opstr {      /* array of operations: functions and (optional) arg */
+    char  func;
+    float arg;
+} op[SIZE];
+
+int k=0;            /* number of operations stored in array */
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE *fp, *fopen();
+    float xf, ops();
+    short xs ;
+    char  s[256], stripcomment[32], echocomment[32];
+    char *prog, *val ;
+    int   i, index, span ;
+
+    strcpy(stripcomment, Stripstr);
+    strcpy(echocomment,  Echostr );
+
+    for (i=0 ; option[i].name != (char *)0 ; i++)
+	*(option[i].val) = option[i].dflt ;
+
+    prog = argv[0] ;
+    while ( --argc > 0 && ++argv ) {
+	if ( ( i = whichopt( option, *argv, &index, &span ) ) == UNKNOWN )
+	    break ;
+	if ( ( val = checksyntax( *argv, span, option[index].type ) ) == (char *)0 )
+	    break ;
+	if ( i == AMBIGUOUS ) {
+	    fprintf(stderr,"%s: ambiguous option [%s]\n", prog, *argv ) ;
+	    exit ( 1 ) ;
+	}
+	switch ( index ) {
+	    case  0 : operate( option, index,  val ) ;                      break;
+	    case  1 : operate( option, index,  val ) ;                      break;
+	    case  2 : op[k].func = Add;         op[k].arg = atof(val); k++; break;
+	    case  3 : op[k].func = Negate;                             k++; break;
+	    case  4 : op[k].func = Multiply;    op[k].arg = atof(val); k++; break;
+	    case  5 : op[k].func = Divide;      op[k].arg = atof(val); k++; break;
+	    case  6 : op[k].func = Remainder;   op[k].arg = atof(val); k++; break;
+	    case  7 : op[k].func = Inverse;                            k++; break;
+	    case  8 : op[k].func = Round;                              k++; break;
+	    case  9 : op[k].func = Absolute;                           k++; break;
+	    case 10 : op[k].func = Power;       op[k].arg = atof(val); k++; break;
+	    case 11 : op[k].func = Exp;         op[k].arg = atof(val); k++; break;
+	    case 12 : op[k].func = Eexp;                               k++; break;
+	    case 13 : op[k].func = Log;         op[k].arg = atof(val); k++; break;
+	    case 14 : op[k].func = Elog;                               k++; break;
+	    case 15 : op[k].func = Sin;                                k++; break;
+	    case 16 : op[k].func = Cos;                                k++; break;
+	    case 17 : op[k].func = Tan;                                k++; break;
+	    case 18 : op[k].func = Threshold;   op[k].arg = atof(val); k++; break;
+	    case 19 : op[k].func = Diff1;                              k++; break;
+	    case 20 : op[k].func = Diff2;                              k++; break;
+	    case 21 : op[k].func = Diff3;                              k++; break;
+	    case 22 : op[k].func = Sum;                                k++; break;
+	    case 23 : op[k].func = Mean;                               k++; break;
+	    case 24 : op[k].func = Min;                                k++; break;
+	    case 25 : op[k].func = Max;                                k++; break;
+	    case 26 : Type = checktype( val ) ;                             break;
+	    case 27 : STRIP++; strcpy(stripcomment, val);                   break;
+	    case 28 : ECHO++;  strcpy(echocomment,  val);                   break;
+	    case 29 : NUMBER++;                                             break;
+	}
+
+    }
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, prog, applic, option ) ;
+
+    if (argc <= 0) fp = stdin;
+    else if ((fp = fopen(*argv, "r")) == NULL) {
+	    fprintf(stderr,"can't open %s\n", *argv);
+	    exit(1);
+	}
+
+    switch ( Type ) {
+
+	case SHORT :
+	    while ( fread( &xs, sizeof(short), 1, fp ) ) {
+		xs = (short)ops( (float)xs ) ;
+		fwrite( &xs, sizeof(short), 1, stdout ) ;
+	    }
+	    break ;
+
+	case FLOAT :
+	    while ( fread( &xf, sizeof(float), 1, fp ) ) {
+		xf = ops( xf ) ;
+		fwrite( &xf, sizeof(float), 1, stdout ) ;
+	    }
+	    break ;
+
+	case ASCII :
+	    while (fgets(s, 256, fp)) {
+		if (STRIP && match(s,stripcomment)==0)
+		    ;                       /* strip comment (ie do nothing) */
+		else {
+		    if (NUMBER) printf("%d: ", ++n);
+		    if (ECHO && match(s,echocomment)==0)
+			fputs(s,stdout);        /* echo comment */
+		    else {
+			if ( k>0 ) {
+			    xf = ops( atof(s) ) ;
+			    printf("%.3f\n", xf ) ;
+			}
+			else fputs(s,stdout);   /* echo line (case of no ops) */
+		    }
+		}
+	    }
+	    break ;
+    }
+
+    fclose(fp);
+}
+
+
+checktype( s )
+char *s ;
+{
+    if ( iststr( s, "short" ) )  return SHORT ;
+    if ( iststr( s, "float" ) )  return FLOAT ;
+    if ( iststr( s, "ascii" ) )  return ASCII ;
+    fprintf( stderr,"unknown datatype [%s]\n", s ) ;
+    exit( 1 ) ;
+}
+
+
+float ops(x)
+float x;
+{
+    int i;
+
+    for (i=0 ; i<k ; i++)
+	switch (op[i].func) {
+	    case Add:           x = x+op[i].arg;            break;
+	    case Negate:        x = (-x);                   break;
+	    case Multiply:      x = x*op[i].arg;            break;
+	    case Divide:        x = x/op[i].arg;            break;
+	    case Remainder:     x = rem(x,op[i].arg);       break;
+	    case Inverse:       x = 1.0/x;                  break;
+	    case Round:         x = round(x);               break;
+	    case Absolute:      x = fabs(x);                break;
+	    case Power:         x = pow(x,op[i].arg);       break;
+	    case Exp:           x = pow(op[i].arg,x);       break;
+	    case Eexp:          x = exp(x);                 break;
+	    case Log:           x = log(x)/log(op[i].arg);  break;
+	    case Elog:          x = log(x);                 break;
+	    case Sin:           x = sin(x);                 break;
+	    case Cos:           x = cos(x);                 break;
+	    case Tan:           x = tan(x);                 break;
+	    case Threshold:     x = threshold(x,op[i].arg); break;
+	    case Diff1:         x = diff1(x);               break;
+	    case Diff2:         x = diff2(x);               break;
+	    case Diff3:         x = diff3(x);               break;
+	    case Sum:           x = sum(x);                 break;
+	    case Mean:          x = mean(x);                break;
+	    case Min:           x = min(x);                 break;
+	    case Max:           x = max(x);                 break;
+	}
+    return x;
+}
+
+
+match(s1,s2)
+char *s1, *s2;
+{
+    int  n1, n2;
+
+    if ((n1=strlen(s1)) < (n2=strlen(s2)))
+	return strncmp(s1,s2,n1);
+    else
+	return strncmp(s1,s2,n2);
+}
+
+
+/****************************************************************************
+ The past values used to compute differences are, (in the order they would
+ appear in an array, where x is the current value):
+	1st diffs           ... x11 x
+	2nd diffs       ... x22 x21 x
+	3rd diffs   ... x33 x32 x31 x
+*****************************************************************************/
+float diff1(x)
+float x;
+{
+    static float x11=0;
+    float  d;
+
+    d=fabs(x11-x);
+    x11=x;
+    return d;
+}
+
+float diff2(x)
+float x;
+{
+    static float x21=0, x22=0;
+    float  d;
+
+    d=fabs( fabs(x22-x21)-fabs(x21-x) );
+    x22=x21;
+    x21=x;
+    return d;
+}
+
+float diff3(x)
+float x;
+{
+    static float x31=0, x32=0, x33=0;
+    float  d;
+
+    d=fabs( fabs( fabs(x33-x32)-fabs(x32-x31) ) - fabs( fabs(x32-x31)-fabs(x31-x) ) );
+    x33=x32;
+    x32=x31;
+    x31=x;
+    return d;
+}
+
+/****************************************************************************
+ Recurisve estimation of the mean
+ (Ref: Young, eqn 2.14 (p14), eqn VI(2) (p63), eqn 5.17 (p65))
+****************************************************************************/
+float mean(x)
+float x;
+{
+    static float a = 0;         /* initial mean value */
+    static float p = 10000;     /* initial gain factor [Young p65] */
+
+    p = p/(1+p);                /* update p (the gain factor)   */
+    a = a - p*(a-x);            /* update a (the mean estimate) */
+    return a;
+}
+
+/****************************************************************************
+ Min, Max, and Sum
+****************************************************************************/
+float min(x)
+float x;
+{
+    static float MIN=1.0e30;
+
+    if (x < MIN) MIN = x;
+    return MIN;
+}
+
+float max(x)
+float x;
+{
+    static float MAX=0;
+
+    if (x > MAX) MAX = x;
+    return MAX;
+}
+
+float sum(x)
+float x;
+{
+    static float SUM=0;
+
+    SUM += x;
+    return SUM;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/options.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,1038 @@
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "strmatch.h"
+#include "units.h"
+
+
+/*
+Defaults for i/o parameters.
+These are declared externally in options.h so they may be overridden by
+option assignment.
+*/
+
+int LINE_LENGTH = 256 ; /* max length of line for ascii data.               */
+int FIELDWIDTH  = 0   ; /* field width for printf.                          */
+			/* (FIELDWIDTH=0 sets no extra fieldwidth.          */
+			/* Positive integer fieldwidth sets right-justified */
+			/* columns, negative integer fieldwidth sets left-  */
+			/* justified columns).                              */
+int PRECISION   = 3   ; /* precision (num decimal places) for printf,       */
+			/* (PRECISION=0 sets integer output).               */
+
+
+
+/*
+Return a file pointer to a file `name' opened to read.
+If `name' is `-' then return stdin.
+If file `name' is not found return null pointer.
+*/
+
+FILE *fropen( name )
+char *name ;
+{
+    FILE  *fopen() ;
+
+    if ( isstr( name, "-" ) ) return stdin ;
+    else  return ( fopen( name, "r" ) ) ;
+}
+
+
+/*
+Generic options handler and file opener.
+Return a file pointer to an opened file, either stdin (if no args remained on
+command line after scanning) or the first name left on the command line.
+*/
+
+FILE *openopts( option, argc, argv )
+Options *option ;
+int      argc   ;
+char    *argv[] ;
+{
+    FILE *fp ;
+    int   i ;
+
+    if ( ( i = getopts( option, argc, argv ) ) == 0 )
+	return stdin ;
+    if ( ( fp = fropen( argv[argc-i] ) ) == (FILE *)0 ) {
+	fprintf(stderr, "%s: can't open %s\n", argv[0], argv[argc-i] ) ;
+	exit( 1 ) ;
+    }
+    return ( fp ) ;
+}
+
+
+/*
+Options handler and two file opener.
+If one file is on command line after scanning options, then the first file
+fp1 is assumed to be the stdin. Otherwise two files are expected.
+Return 0 if incorrect number of files, otherwise return 1.
+(Note: fp1 and fp2 are pts to file ptrs, so pass them as &fp1, &fp2 if
+originally declared as file ptrs).
+*/
+
+open2opts( option, argc, argv, fp1, fp2 )
+Options *option ;
+int      argc   ;
+char    *argv[] ;
+FILE    **fp1   ;
+FILE    **fp2   ;
+{
+    switch ( getopts( option, argc, argv ) ) {
+
+	case 1 :
+		*fp1 = stdin;
+		if ( ( *fp2 = fropen( argv[argc-1] ) ) == (FILE *)0 ) {
+		    fprintf( stderr,"%s: can't open %s\n", argv[0], argv[argc-1] ) ;
+		    exit( 1 ) ;
+		}
+		break ;
+	case 2 :
+		if ( ( *fp1 = fropen( argv[argc-2] ) ) == (FILE *)0 ) {
+		    fprintf( stderr,"%s: can't open %s\n", argv[0], argv[argc-2] ) ;
+		    exit( 1 ) ;
+		}
+		if ( ( *fp2 = fropen( argv[argc-1] ) ) == (FILE *)0 ) {
+		    fprintf( stderr,"%s: can't open %s\n", argv[0], argv[argc-1] ) ;
+		    exit( 1 ) ;
+		}
+		break ;
+	default :
+		return ( 0 ) ;
+    }
+    return ( 1 ) ;
+}
+
+
+
+/*
+  Build an options table.
+  First assign all the option values with the defaults given in the table.
+  Then scan the command line for arguments to overwrite corresponding vals.
+
+  Argument syntax is one of the following three types (or combinations).
+  Each syntax must contain either a leading '-' char or an embedded '=' char,
+  to distinguish arguments from possible filenames.
+
+
+  1)    -<name>                 FLAG_SYNTAX
+  2)    -<name>[=]<value>       ARG_SYNTAX
+  3)   [-]<name>=<value>        EQ_SYNTAX
+
+  FLAG_SYNTAX takes no value. (The returned value is the empty string).
+
+  ARG_SYNTAX takes a value after an optional '=' char.
+  If the '=' char is not found, then the <value> is whatever follows the
+  longest matching <name> string. Otherwise the <value> is whatever follows
+  the '=' char. (The value is not allowed to be empty).
+
+  EQ_SYNTAX takes a value which is whatever follows the '=' char.
+  (The value is not allowed to be empty).
+
+  It is assumed that all args remaining on the command line after an arg with
+  invalid syntax must be filenames. These remain unscanned.
+  Return argc, the number of args remaining unscanned on the command line,
+  (argc=0 if no args left).
+  To scan the remainder of the command line, and (eg) print the filenames:-
+
+    if ( ( i = getopts( option, argc, argv, ) ) == 0 )
+	printf("stdin\n" );
+    else
+	for ( ; i>0 ; i--)
+	    printf("[%s]\n", argv[argc-i] );
+
+*/
+
+
+int getopts( option, argc, argv )
+Options *option ;
+int      argc   ;
+char    *argv[] ;
+{
+    char *prog, *val ;
+    int   i, n, index[64], span[64] ;
+
+    /* Assign option vals using the defaults */
+
+    for (i=0 ; option[i].name != (char *)0 ; i++)
+	*(option[i].val) = option[i].dflt ;
+
+    /* Overwrite option vals with corresponding vals found on command line */
+
+    prog = *argv ;
+    while ( --argc > 0 && ++argv ) {
+
+	/* find list of options all with longest matching name span      */
+	/* returning if none, with argc args remaining                   */
+	if ( ( n = whichopt( option, *argv, index, span ) ) == 0 )
+	    return ( argc ) ;
+
+	/* check arg syntax, returning if invalid with argc args remaining */
+	for ( i=0 ; i<n && ( val = checksyntax( *argv, span[i], option[index[i]].type ) ) == (char *)0  ; i++ )
+	    ;
+	if ( val == (char *)0 )
+	    return ( argc ) ;
+
+	/* if whichopt was ambiguous, yet an arg is valid, then its an     */
+	/* ambiguous option, (and not a possible filename).                */
+	if ( n > 1 ) {
+	    fprintf(stderr,"%s: ambiguous option [%s]\n", prog, *argv ) ;
+	    exit ( 1 ) ;
+	}
+
+	/* do operation */
+	operate( option, *index, val ) ;
+	side_effect( option, *index ) ;
+
+    }
+    return argc ;
+}
+
+
+/*
+Find the default value of the first option whose name unambiguously matches
+`s' (possibly abbreviated).
+Return a ptr to the default value of the matching option.
+Otherwise return the null ptr if a matching name is not found or is ambiguous.
+*/
+
+char *optdflt( option, s )
+Options *option ;
+char    *s      ;
+{
+    int  i ;
+
+    if ( ( i = optindex( option, s ) ) < 0 )
+	return ( (char *)0 ) ;
+    return ( option[i].dflt ) ;
+}
+
+/*
+Find the option whose name unambiguously matches `s' (possibly abbreviated).
+Return the option list index of the matching option.
+Otherwise return -1 if a matching name is not found, or -2 if the name is
+ambiguous.
+*/
+
+int optindex( option, s )
+Options *option ;
+char    *s      ;
+{
+    int   i, n, index[64], span[64] ;
+
+    if ( ( n = whichopt( option, s, index, span ) ) == 0 )
+	return (-1) ;   /* option not found */
+    if ( n > 1 )
+	return (-2) ;   /* option name ambiguous */
+    return ( *index ) ;
+}
+
+
+/*
+Find the option whose name has the longest matching span with the head of `s'
+(the argument string, possibly abbreviated or with trailing value parts).
+Pass the option list index of the matching option back via arg `index'.
+Pass the length of the matching span back via arg `span'.
+Return the number of options found which have an equal longest matching span.
+(Any `-' at the head of `s' is skipped before matching).
+If there is an exact match (ie the longest matching span equals the length of
+the option name) then return an unambiguous match.
+*/
+
+int whichopt( option, s, index, span )
+Options *option ;
+char    *s      ;
+int     *index, *span ;
+{
+    int  i, j, n = 0, jmax = 0 ;
+
+    if ( *s == '-' ) s++ ;  /* Skip leading hyphen  */
+
+    for ( i = 0 ; option[i].name != (char *)0 ; i++ ) {
+
+	if ( ( j = streqspn( s, option[i].name ) ) > jmax ) {
+	    jmax = j ;                  /* a new longest matching span */
+	    n = 0 ;
+	    index[n]  = i ;
+	    span[n++] = j ;
+	}
+	else if ( j > 0 && j == jmax ) {    /* ambiguous name with same matching span */
+		index[n]  = i ;
+		span[n++] = j ;
+	}
+    }
+
+    for ( i = 0 ; i < n ; i++ )         /* check for an exact match */
+	if ( span[i] == strlen( option[index[i]].name ) ) {
+	    index[0] = index[i] ;
+	    span[0]  = span[i] ;
+	    return 1 ;
+	}
+
+    return n ;
+}
+
+
+/*
+Check arg syntax and return a pointer to the value part, (or a pointer to the
+terminating null if the value part is empty).
+Return a NULL pointer if the syntax is invalid. It is assumed then that the
+current arg (and all remaining) is a filename.
+Print a warning if the syntax is an error rather than a possible filename,
+(the filename will not be found in this case).
+
+The check is arranged so that different option syntax types can be OR'd.
+*/
+
+char *checksyntax( s, span, type )
+char *s ;
+int   span, type ;
+{
+    int   i   ;
+    char *v, *val = (char *)0 ;
+
+    if ( bitset( type, FLAG_SYNTAX ) ) {        /*  -<name>             */
+	if ( *s == '-' && *(v = s+1 + span) == '\0' )
+	    val = v ;
+    }
+
+    if ( bitset( type, ARG_SYNTAX ) ) {         /*  -<name>[=]<value>   */
+	if ( *s == '-' ) {
+	    if ( *(v = s+1 + span) == '=' ) v++ ;
+	    if ( *v != '\0' ) val = v ;
+	}
+    }
+
+    if ( bitset( type, EQ_SYNTAX ) ) {          /* [-]<name>=<value>    */
+	if ( *s == '-' ) s++ ;
+	if ( *(v = s + span) == '=' && *++v != '\0' )
+	    val = v ;
+    }
+
+    return ( val ) ;
+}
+
+
+/*
+Return 1 if string s a possible option, (ie. a string which is not a <number>,
+and contains either an embedded '=' or a leading '-').
+Otherwise return 0.
+*/
+
+int isopt( s )
+char  *s ;
+{
+    if ( isnumber( s ) ) return 0 ;
+    if ( *s == '-' )     return 1 ;
+    if ( strchr( s, '=' ) != (char *)0 ) return 1 ;
+    return 0 ;
+}
+
+
+operate( option, i,  val )
+Options *option ;
+int      i ;
+char    *val ;
+{
+    if ( bitset( option[i].type, LATCH ) )            /* LATCH  */
+	*(option[i].val) = val ;
+
+    else if ( bitset( option[i].type, AND ) )         /* AND    */
+	*(option[i].val) = offstr ;
+
+    else if ( bitset( option[i].type, OR  ) )         /* OR     */
+	*(option[i].val) = onstr ;
+
+    else if ( bitset( option[i].type, TOGGLE ) ) {    /* TOGGLE */
+	if ( isempty( val ) ) {
+	    if ( ison( *(option[i].val) ) )
+		*(option[i].val) = offstr ;
+	    else
+		*(option[i].val) = onstr ;
+	}
+	else *(option[i].val) = val ;
+    }
+}
+
+
+/*
+Side-effects of options type specifiers.
+*/
+
+side_effect( option, j )
+Options *option ;
+int      j ;
+{
+    int   i ;
+    char *exstr ;
+
+    if ( bitset( option[j].type, EXCLUDE ) ) {  /* EXCLUDE */
+	if ( ison( *(option[j].val) ) )
+	    exstr = offstr ;
+	else
+	    exstr = onstr ;
+	for ( i=0; option[i].name != (char *)0 ; i++)
+	    if ( i != j && bitset( option[i].type, EXCLUDE ) )
+		    *(option[i].val) = exstr  ;
+    }
+}
+
+
+
+/*
+Separate an option value string `optval' into two string tokens at the first
+occurrence of a separator character `sep'. (Given as a string of one char).
+Return the tokens via the pointers `val1' and `val2' (which could be passed
+as the addresses of string pointers).
+Return BADVAL if the option value string is bad (meaning that either `optval' was
+null or empty, or the separator char was found but the 2nd token was missing).
+Return 1 if the option value string is good (meaning that either two tokens
+were found, or only the 1st token with no separator char, in which case `val2'
+will be a ptr to an empty string). (See routine strpsep()).
+*/
+
+int getvals( optval, val1, val2, sep )
+char  *optval ;
+char **val1, **val2 ;
+char  *sep ;
+{
+    *val1 = optval ;
+    if ( isnull( *val2 = strsep( optval, sep ) ) )
+	return BADVAL ;
+    return 1 ;
+}
+
+
+/*
+Parse a range selector of the form:  a[-b]
+Return 0 if bad selectors, otherwise return 1.
+Items are numbered 1,2,...,max, (where max is 0 by convention).
+When either limit is "min", then set the respective value to 1.
+When either limit is "max", then set the respective value to 0.
+When `b' is missing, then set b=a.
+
+If (a==0) then seek eof and process the final item.
+Else seek past (a-1) items, and then process the next (b-a+1) items
+(or all items until eof if (b==0)).
+Eg:
+    seekstart( a-1, bytes, fp ) ;
+    for ( i = 0 ; ( b == 0  ||  i < b-a+1 ) ; i++ )
+	do process
+
+*/
+
+int selector( s, a, b )
+char *s ;
+int  *a, *b ;
+{
+    char *val1, *val2 ;
+
+    if ( getvals( s, &val1, &val2, "-" ) == BADVAL )
+	return ( 0 ) ;
+    if      ( ismin( val1 ) ) *a = 1 ;           /* first object         */
+    else if ( ismax( val1 ) ) *a = 0 ;           /* last object          */
+    else if ( ( *a = atoi( val1 ) ) <= 0 ) {     /* intermediate object  */
+	if ( *a == 0 ) fprintf( stderr,"warning: selected items are numbered 1,...,max\n" ) ;
+	return ( 0 ) ;
+    }
+    if ( isempty( val2 ) )    *b = *a ;          /* single object        */
+    else if ( ismin( val2 ) ) *b = 1 ;
+    else if ( ismax( val2 ) ) *b = 0 ;
+    else if ( ( *b = atoi( val2 ) ) <= 0 ) {
+	return ( 0 ) ;
+    }
+    if ( *b > 0  && ( *a == 0 || *a > *b ) )
+	return ( 0 ) ;
+
+    return ( 1 ) ;
+}
+
+
+/*
+Parse a time range selector of the form:  a[-b]
+The range is returned as limits meaning: start==a  duration==b-a+1.
+(Note: when range=max or range=max-max then a==b==(-1) and duration==1).
+Return 0 if bad selectors, otherwise return 1.
+Time is numbered 0,2,...,max, (where max is (-1) by convention).
+When either limit is "min", then set the respective value to 0.
+When either limit is "max", then set the respective value to (-1).
+When `b' is missing, then set b=a.
+Time is specified as <number>[<units>], where <units> = {p, ms, s}.
+Empty units are interpreted as `p' (ie sample points).
+Convert `a' and `b' to sample points using the given samplerate.
+
+(Note: this is like selector() but using to_p() instead of atoi(), and
+numbering from 0 instead of 1).
+
+If (a<0) then seek eof and process the final item.
+Else seek past (a) items, and then process the next (b-a+1) items
+(or all items until eof if (b==-1)).
+Eg:
+    seekstart( a, bytes, fp ) ;
+    for ( i = 0 ; ( b < 0  ||  i < b-a+1 ) ; i++ )
+	do process
+
+*/
+
+int range( s, a, b, samplerate )
+char *s ;
+int  *a, *b ;
+int   samplerate ;
+{
+    char *val1, *val2 ;
+
+    if ( getvals( s, &val1, &val2, "-" ) == BADVAL )
+	return ( 0 ) ;
+    if      ( ismin( val1 ) ) *a = 0    ;       /* first object         */
+    else if ( ismax( val1 ) ) *a = (-1) ;       /* last object          */
+    else if ( ( *a = to_p( val1, samplerate ) ) < 0 ) {
+	return ( 0 ) ;
+    }
+    if ( isempty( val2 ) )    *b = *a   ;        /* single object        */
+    else if ( ismin( val2 ) ) *b = 0    ;
+    else if ( ismax( val2 ) ) *b = (-1) ;
+    else if ( ( *b = to_p( val2, samplerate ) ) < 0 ) {
+	return ( 0 ) ;
+    }
+    if ( *b >= 0  && ( *a < 0 || *a > *b ) )
+	return ( 0 ) ;
+
+    return ( 1 ) ;
+}
+
+
+/*
+Seek n items of size bytes from current position in stream.
+(Unlike fseek, this works even when fp is stdin).
+Return the number of items actually read.
+Example:  seekstart( n, sizeof(short), fp );
+Datatype "ASCII" is a special case for which 0 is returned by the databytes
+routine, so bytes==0 is taken to mean seek n ascii lines. In general use:
+    seekstart( n, databytes( typestr ), fp )
+*/
+
+seekstart( n, bytes, fp )
+int    n, bytes ;
+FILE  *fp ;
+{
+    int   i    ;
+    char *buf  ;
+    char *line ;
+
+    if ( bytes == 0 ) { /* special case meaning ascii lines */
+	line = (char *)malloc( LINE_LENGTH ) ;
+	for ( i = 0 ; i < n && fgets( line, LINE_LENGTH, fp ) != (char *)0 ; i++ )
+	    ;
+	free( line ) ;
+	return ( i ) ;
+    }
+
+    if ( fp != stdin ) {
+	if ( fseek( fp, (long)( n * bytes ), 1 ) == 0 )
+	    return n ;          /* if improper, look for any input */
+    }
+
+    if ( ( buf = (char *)malloc( bytes ) ) == (char *)0 ) {
+	fprintf( stderr, "seekstart: cannot allocate %d bytes\n", bytes ) ;
+	exit( 1 ) ;
+    }
+
+    for ( i = 0 ; i < n && fread( buf, bytes, 1, fp ) ; i++ )
+	;
+    free( buf ) ;
+
+    return ( i ) ;
+}
+
+
+/*
+Seek n items of of given type from current position in stream.
+This seekstart version takes a `type' arg instead of a size in `bytes'.
+The `type' is an index to the datatype list in options.h, obtained for
+example using: typeindex( typestr ).
+*/
+
+seektype( n, type, fp )
+int    n, type ;
+FILE  *fp ;
+{
+    return ( seekstart( n, typebytes( type ), fp ) ) ;
+}
+
+
+/*
+Read the next n items of `type' from the given stream.
+The `type' is an index to the datatype list in options.h, obtained for
+example using: typeindex( typestr ).
+Assign the item as a float in address `y', and return 1.
+Return 0 if eof or error.
+This can replace fread, eg:
+	fread( &p, sizeof(short), 1, fp )               ( with short p )
+becomes:
+	readitem( &y, typeindex( "short" ), 1, fp )     ( with float y )
+*/
+
+readitem( y, type, n, fp )
+float *y    ;
+int    type ;
+int    n    ;
+FILE  *fp   ;
+{
+    char c ; short s ; int i ; float f ; double d ;
+    int  j ;
+    static char *line ;
+    static int   first = 1 ;
+
+    switch ( type ) {
+	case   0  : for ( j = 0 ; j < n ; j++ ) {
+			if ( fread( &c, sizeof(char),   1, fp ) == 0 ) return 0 ;
+			*y++ = (float)c ;
+		    }
+		    break ;
+	case   1  : for ( j = 0 ; j < n ; j++ ) {
+			if ( fread( &s, sizeof(short),  1, fp ) == 0 ) return 0 ;
+			*y++ = (float)s ;
+		    }
+		    break ;
+	case   2  : for ( j = 0 ; j < n ; j++ ) {
+			if ( fread( &i, sizeof(int),    1, fp ) == 0 ) return 0 ;
+			*y++ = (float)i ;
+		    }
+		    break ;
+	case   3  : for ( j = 0 ; j < n ; j++ ) {
+			if ( fread( &f, sizeof(float),  1, fp ) == 0 ) return 0 ;
+			*y++ = (float)f ;
+		    }
+		    break ;
+	case   4  : for ( j = 0 ; j < n ; j++ ) {
+			if ( fread( &d, sizeof(double), 1, fp ) == 0 ) return 0 ;
+			*y++ = (float)d ;
+		    }
+		    break ;
+	case   5  :
+	case   6  : if ( first ) {
+			line = (char *)malloc( LINE_LENGTH ) ;
+			first = 0 ;
+		    }
+		    for ( j = 0 ; j < n ; j++ ) {
+			if ( fgets( line, LINE_LENGTH, fp ) == (char *)0 )      return 0 ;
+			*y++ = atof( line ) ;
+		    }
+		    break ;
+    }
+    return 1 ;
+}
+
+
+/*
+Write the given n items of `type' onto the given stream.
+The `type' is an index to the datatype list in options.h, (obtained for
+example using: typeindex( typestr ) ).
+*/
+
+writeitem( y, type, n, fp )
+float *y    ;
+int    type ;
+int    n    ;
+FILE  *fp   ;
+{
+    char c ; short s ; int i ; float f ; double d ;
+    int  j ;
+
+    switch ( type ) {
+	case   0  : for ( j = 0 ; j < n ; j++ ) {
+			c = (char)   *y++ ;
+			fwrite( &c, sizeof(char),   1, fp ) ;
+		    }
+		    break ;
+	case   1  : for ( j = 0 ; j < n ; j++ ) {
+			s = (short)  *y++ ;
+			fwrite( &s, sizeof(short),  1, fp ) ;
+		    }
+		    break ;
+	case   2  : for ( j = 0 ; j < n ; j++ ) {
+			i = (int)    *y++ ;
+			fwrite( &i, sizeof(int),    1, fp ) ;
+		    }
+		    break ;
+	case   3  : for ( j = 0 ; j < n ; j++ ) {
+			f = (float)  *y++ ;
+			fwrite( &f, sizeof(float),  1, fp ) ;
+		    }
+		    break ;
+	case   4  : for ( j = 0 ; j < n ; j++ ) {
+			d = (double) *y++ ;
+			fwrite( &d, sizeof(double), 1, fp ) ;
+		    }
+		    break ;
+	case   5  :
+	case   6  : for ( j = 0 ; j < n ; j++ )
+			fprintf( fp, "%*.*f\n", FIELDWIDTH, PRECISION, *y++ ) ;
+		    break ;
+    }
+}
+
+
+/*
+Read the next n items of `type' from the given stream within inclusive range
+limits `a' and `b', (found using, eg: range( rangestr, &a, &b, samplerate ) ).
+This is a version of readitem which incorporates the intial seek and handles
+range=max correctly.
+The `type' is an index to the datatype list in options.h, obtained for
+example using: typeindex( typestr ).
+Assign the item as a float in address `y', and return the number of items
+read. Return 0 if eof or error.
+*/
+
+nextitem( y, type, n, fp, a, b )
+float *y    ;
+int    type ;
+int    n    ;
+FILE  *fp   ;
+int    a, b ;
+{
+    static int count = 0 ;      /* total items read over all calls */
+    int    num ;                /* number items read this call     */
+    float  x   ;
+
+    if ( count == 0 ) {
+
+	if ( a == (-1) ) {      /* range=max or range=max-max */
+	    if ( n == 1 && readitem( &x, type, 1, fp ) ) {
+		*y = x ;
+		while ( readitem( &x, type, 1, fp ) )
+		    *y = x ;
+		num = 1 ;
+	    }
+	    else num = 0 ;
+	}
+
+	else {
+	    if ( seektype( a, type, fp ) < a )
+		num = 0 ;
+	    else {
+		if ( b >= 0 && n > b-a+1 )  /* n restricted by upper limit */
+		    n = b-a+1 ;
+		for ( num = 0 ; num < n && readitem( &x, type, 1, fp ) ; num++ )
+		    y[num] = x ;
+	    }
+	}
+
+	count += num ;
+    }
+
+    else {
+	if ( b >= 0 && count >= b-a+1 )
+	    num = 0 ;
+	else {
+	    if ( b >= 0 && n > b-a+1 - count )  /* n restricted by upper limit */
+		n = b-a+1 - count ;
+	    for ( num = 0 ; num < n && readitem( &x, type, 1, fp ) ; num++ )
+		y[num] = x ;
+	}
+
+	count += num ;
+    }
+
+    return num ;
+}
+
+
+
+
+/*
+Return the type index (to the datatype list in options.h) of the given type
+string. String matching allows for abbreviations.
+If the given type string is in error then return an error code (less than 0):
+    -1  type string not found in datatype list.
+    -2  type string is ambiguous.
+*/
+
+int typeindex( typestr )
+char   *typestr  ;
+{
+    return ( listindex( datatype, typestr ) ) ;
+}
+
+
+/*
+Return a number of bytes for a given type index (to the datatype list in
+options.h). Datatype "ASCII" is a special case for which 0 is returned.
+*/
+
+int typebytes( type )
+int type ;
+{
+    int  bytes ;
+
+    switch ( type ) {
+	case   0  : bytes = sizeof( char   ) ;  break ;
+	case   1  : bytes = sizeof( short  ) ;  break ;
+	case   2  : bytes = sizeof( int    ) ;  break ;
+	case   3  : bytes = sizeof( float  ) ;  break ;
+	case   4  : bytes = sizeof( double ) ;  break ;
+	case   5  :                                     /* ASCII */
+	case   6  : bytes = 0 ;                 break ; /* ascii */
+    }
+    return ( bytes ) ;
+}
+
+
+
+/*
+Return a number of bytes for a given type string.
+The string can be a number (of bytes), or a token from the `datatype' list,
+(see options.h) with which it is matched, allowing for abbreviations.
+Datatype "ASCII" or "ascii" is a special case for which 0 is returned.
+If the given type string is in error then return an error code (less than 0):
+    -1  type string not found in datatype list.
+    -2  type string is ambiguous.
+    -3  type string is a negative number.
+*/
+
+int databytes( typestr )
+char   *typestr  ;
+{
+    int  type, bytes ;
+
+    if ( isnumber( typestr ) ) {        /* case of bytes number string */
+	if ( ( bytes = atoi( typestr  ) ) < 0 )
+	    return ( -3 ) ;
+	else return bytes ;
+    }
+
+    if ( ( type = typeindex( typestr ) ) < 0 )
+	return type ;
+
+    return ( typebytes( type ) ) ;
+}
+
+
+/*
+Check for over or underflow when the  given float is scaled and cast into the
+given data type (an index to the datatype list in options.h).
+Return a more appropriate scale factor, or a scale factor of 1 if no over
+or underflow. The returned scale factor is the minimum scale factor over
+a succession of calls to check_overflow.
+*/
+
+float check_overflow( p, scale, type )
+float p, scale ;
+int   type ;
+{
+    float  f, p1 = p * scale  ;
+    static float first = 1 ;
+    static float max, newscale ;
+
+    if ( type >= 3 ) return ( 1. ) ;
+
+    if ( first ) {
+
+	switch ( type ) {
+	    case   0  : max = pow( 2., 8.*sizeof(char)-1  ) - 1 ;  break ;
+	    case   1  : max = pow( 2., 8.*sizeof(short)-1 ) - 1 ;  break ;
+	    case   2  : max = pow( 2., 8.*sizeof(int)-1   ) - 1 ;  break ;
+	}
+
+	newscale = 1. ;
+	first = 0 ;
+    }
+
+    if      ( p1 > max    ) f =    max / p   ;
+    else if ( p1 < (-max) ) f = -( max / p ) ;
+    else                    f = 1.           ;
+
+    if ( f < newscale )
+	newscale = f ;
+
+    return ( newscale ) ;
+}
+
+
+
+/*
+Some particular string tests.
+*/
+
+
+/*
+Test for "on" or any <number> string other than "0".
+*/
+
+int ison( s )
+char *s ;
+{
+    return ( strcmp( "on", s ) == 0 || ( isnumber( s ) && strcmp( "0", s ) != 0 ) ) ;
+}
+
+/*
+Test for "off" or "0".
+*/
+
+int isoff( s )
+char *s ;
+{
+    return ( strcmp( "off", s ) == 0 || strcmp( "0", s ) == 0 ) ;
+}
+
+/*
+Test for "min".
+*/
+
+int ismin( s )
+char *s ;
+{
+    return ( strcmp( "min", s ) == 0 ) ;
+}
+
+/*
+Test for "max".
+*/
+
+int ismax( s )
+char *s ;
+{
+    return ( strcmp( "max", s ) == 0 ) ;
+}
+
+
+
+
+/*************************************************************************/
+
+/*
+  Print help for user
+  help=on or -help gets standard help for all except SILENT options.
+  help=all gets standard help for all options.
+  help=syntax gets help with syntax instead of comment for all except SILENT.
+  help=<name> gets help for the named option (which can be abbreviated).
+*/
+
+
+/*
+  types of helpopts (see defines in options.h)
+
+helpopts   standard usage, exit when done
+helpopts1  standard usage, supplied function for exit or additional help
+helpopts2  supplied usage and function for exit or additional help
+helpopts3  supplied usage, exit when done
+*/
+
+
+gethelp( helpstr, prog, applic, usage, option, tail )
+char    *helpstr ;
+char    *prog    ;
+char    *applic  ;
+char    *usage   ;
+Options *option  ;
+int    (*tail)() ;      /* function for exit or additional help */
+{
+    int  i, index[64], span[64] ;
+
+    if ( isempty( helpstr ) || ison( helpstr ) || isstr( helpstr, "all" ) || isstr( helpstr, "syntax" ) )
+	help( prog, applic, usage, option, isstr( helpstr, "all" ), isstr( helpstr, "syntax" ) ) ;
+    else {
+	i = whichopt( option, helpstr, index, span ) ;
+	if ( i == 0 )
+	    fprintf(stderr,"%s: unknown option [%s]\n", prog, helpstr ) ;
+	else if ( i > 1 )
+	    fprintf(stderr,"%s: ambiguous option [%s]\n", prog, helpstr ) ;
+	else
+	    helpshot( option[*index] ) ; /* single-line help i'th option */
+    }
+    (*tail)() ;
+}
+
+
+
+help( prog, applic, usage, option, all, syntax )
+char    *prog, *applic, *usage ;
+Options *option ;
+int      all, syntax ;
+{
+    int  i ;
+    char *which_syntax();
+
+    if ( usage == (char *)0 )   /* a standard usage */
+	printf( "%s:  %s\nUsage: %s  [arguments]  [file]\n", prog, applic, prog );
+    else
+	printf( "%s:  %s\nUsage: %s\n", prog, applic, usage );
+
+    if ( num_printed_opts( option, all ) > 0 ) {
+	printf("name        default     comment\n");
+	printf("----------  ----------  --------.... \n");
+    }
+    for (i=0 ; option[i].name != (char *)0 ; i++) {
+	if ( !bitset( option[i].type, SILENT ) || all ) {
+	    if ( syntax )
+		syntaxline( option[i] ) ;
+	    else
+		helpline( option[i] ) ;
+	}
+    }
+}
+
+
+helpline( option )
+Options option ;
+{
+    printf("%-10s  ", option.name );
+    printf("%-10s  ", option.dflt );
+    printf("%s\n"   , option.help );
+}
+
+syntaxline( option )
+Options option ;
+{
+    char *which_syntax();
+
+    printf("%-10s  ", option.name );
+    printf("%-10s  ", option.dflt );
+    printf("%s\n"   , which_syntax( option.type ) );
+}
+
+
+helpshot( option )
+Options option ;
+{
+    char *which_syntax();
+
+    printf("name:    %s\n", option.name );
+    printf("default: %s\n", option.dflt );
+    printf("syntax:  %s\n", which_syntax( option.type ) );
+    printf("comment: %s\n", option.help );
+}
+
+
+/*
+Return the number of options which will get printed by help
+*/
+
+int num_printed_opts( option, all )
+Options *option ;
+int      all    ;
+{
+    int  i, j=0 ;
+
+    for (i=0 ; option[i].name != (char *)0 ; i++)
+	if ( !bitset( option[i].type, SILENT ) )
+	    j++ ;
+    if ( all ) return ( i ) ;   /* num all options        */
+    else       return ( j ) ;   /* num non-SILENT options */
+}
+
+
+char *which_syntax( type )
+int  type ;
+{
+    if ( bitsset( type, ALL_SYNTAX    ) ) return (char *)( All_Syntax    ) ;
+    if ( bitsset( type, VAL_SYNTAX    ) ) return (char *)( Val_Syntax    ) ;
+    if ( bitsset( type, TOGGLE_SYNTAX ) ) return (char *)( Toggle_Syntax ) ;
+    if ( bitsset( type, ONOFF_SYNTAX  ) ) return (char *)( Onoff_Syntax  ) ;
+    if ( bitsset( type, EQ_SYNTAX     ) ) return (char *)( Eq_Syntax     ) ;
+    if ( bitsset( type, ARG_SYNTAX    ) ) return (char *)( Arg_Syntax    ) ;
+    if ( bitsset( type, FLAG_SYNTAX   ) ) return (char *)( Flag_Syntax   ) ;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/options.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,217 @@
+/*
+The option type field controls the interpretation and syntax of individual args.
+Option types are specified by OR'ing bit patterns which define the syntax for
+the argument and the operation by which the argument is combined with the
+default value. Additional bits refer to side-effects which are effects a
+specific option may have which are not related to its syntax or its essential
+operation.
+
+Option syntax:
+    FLAG_SYNTAX          -<name>
+    ARG_SYNTAX           -<name>[=]<value>
+    EQ_SYNTAX           [-]<name>=<value>
+    ONOFF_SYNTAX         -<name>[[=]<value>]
+    VAL_SYNTAX           -<name>[=]<value>    |  [-]<name>=<value>
+    TOGGLE_SYNTAX        -<name>              |  [-]<name>=<value>
+    ALL_SYNTAX           -<name>[[=]<value>]  |  [-]<name>=<value>
+
+Option operations:
+    LATCH       Copy the argument value.
+    AND         Turn off, (arg effects default only when default is "on")
+    OR          Turn on,  (arg effects default only when default is "off")
+    TOGGLE      Invert the current default value (on/off), (unless forced by its value)
+
+Side effects:
+    SILENT      Don't print help line.
+    EXCLUDE     Invert all other EXCLUDE arguments with respect to the current one.
+
+Options of EXCLUSIVE type are a set in which one is "on" and the rest "off".
+The value is allowed to be empty or "on", so that an option <name> by itself
+can count as "on".
+
+Options of SILENT type are not printed by standard help, unless specifically
+named (eg help=<name>) or all options are asked for (eg help=all).
+
+
+Some combined option types:
+    FLAG        Command-line flag: -flag (toggle current default).
+    SETFLAG     Command-line flag: -flag (toggle current default) or flag=on/off.
+    ARG         Command-line argument: -argval (latch arg to val).
+    EQ          Command-line argument: arg=val (latch arg to val).
+    VAL         Command-line argument, combined style (latch arg to val).
+    EX_OR       Mutually exclusive option value. Set option value "on", and
+		all other EXCLUDE options "off".
+    EX_AND      Mutually exclusive option value. Set option value "off", and
+		all other EXCLUDE options "on".
+    EX_TOGGLE   Mutually exclusive option value. Set option to given value,
+		("on"/"off") and toggle all other EXCLUDE options ("off"/"on")
+    DEBUG       Silent toggle (synonymous with STOG).
+    STOG        Silent toggle.
+    SVAL        Silent argument (combined-style latch).
+
+
+Summary of main option types:
+
+------------------------------------------------------------
+Name        Operation   Side-effect     Purpose
+---------   ---------   -----------     --------------------
+
+(1) With syntax "-<name>"
+
+FLAG        toggle                      Toggle flag default value.
+EX_AND      and         exclude         Set flag off and all others on.
+
+(2) With syntax "-<name> | [-]<name>=on|off"
+
+SETFLAG     toggle                      Set flag on|off.
+EX_OR       or          exclude         Set flag on and all others off.
+EX_TOGGLE   toggle      exclude         Set flag on|off and all others off|on.
+DEBUG       toggle      silent          Set flag silently
+STOG        toggle      silent           "    "     "
+
+(3) With syntax "-<name>[=]<value> | [-]<name>=<value>"
+
+VAL         latch                       Latch arg to value.
+SVAL        latch       silent          Latch arg to value silently.
+
+*/
+
+/* option syntax (base types) */
+
+#define FLAG_SYNTAX     (  1   )    /*    -<name>           */
+#define ARG_SYNTAX      (  2   )    /*    -<name>[=]<value> */
+#define EQ_SYNTAX       (  4   )    /*   [-]<name>=<value>  */
+
+/* operations between vals */
+
+#define LATCH           (  8   )
+#define AND             (  16  )
+#define OR              (  32  )
+#define TOGGLE          (  64  )
+
+/* side-effects */
+
+#define SILENT          (  128 )
+#define EXCLUDE         (  256 )
+
+/* option syntax combinations */
+
+#define ONOFF_SYNTAX    ( FLAG_SYNTAX | ARG_SYNTAX              )
+#define TOGGLE_SYNTAX   ( FLAG_SYNTAX |              EQ_SYNTAX  )
+#define VAL_SYNTAX      (               ARG_SYNTAX | EQ_SYNTAX  )
+#define ALL_SYNTAX      ( FLAG_SYNTAX | ARG_SYNTAX | EQ_SYNTAX  )
+
+/* combined option types */
+
+#define FLAG            ( TOGGLE | FLAG_SYNTAX                  )
+#define SETFLAG         ( TOGGLE | TOGGLE_SYNTAX                )
+#define ARG             ( LATCH | ARG_SYNTAX                    )
+#define EQ              ( LATCH | EQ_SYNTAX                     )
+#define VAL             ( LATCH | VAL_SYNTAX                    )
+
+#define EX_OR           ( EXCLUDE | OR     | TOGGLE_SYNTAX      )
+#define EX_AND          ( EXCLUDE | AND    | FLAG_SYNTAX        )
+#define EX_TOGGLE       ( EXCLUDE | TOGGLE | TOGGLE_SYNTAX      )
+#define DEBUG           ( SILENT | SETFLAG                      )
+#define STOG            ( SILENT | SETFLAG                      )
+#define SVAL            ( SILENT | VAL                          )
+
+/* bit-testing operations */
+
+#define and(x1,x2)      ( (x1)&(x2) )
+#define bitset(x,bits)  ( and(x,bits) ? 1 : 0 )
+#define bitsset(x,bits) ( ( and(x,bits) == bits ) ? 1 : 0 )
+
+/* error flags */
+
+#define UNKNOWN         ( -1 )
+#define AMBIGUOUS       ( -2 )
+#define BADVAL          ( -3 )
+
+/* options structure */
+
+typedef struct {
+  char  *name ;         /* option name                                     */
+  char  *dflt ;         /* default value (string)                          */
+  char **val  ;         /* pointer to current value (string)               */
+  char  *help ;         /* help message (max 15 chars)                     */
+  unsigned int type ;   /* type of option (syntax, operation, side-effect) */
+} Options ;
+
+
+/* datatype list */
+
+static char *datatype[] = {
+	"char"  ,
+	"short" ,
+	"int"   ,
+	"float" ,
+	"double",
+	"ASCII" ,
+	"ascii" ,
+   ( char * ) 0 } ;
+
+
+
+
+/*
+  types of helpopts
+
+helpopts   standard usage, exit when done
+helpopts1  standard usage, supplied function for exit or additional help
+helpopts2  supplied usage and function for exit or additional help
+helpopts3  supplied usage, exit when done
+*/
+
+#define helpopts(helpstr,prog,applic,option)             gethelp( helpstr, prog, applic, (char *)0, option, exit )
+#define helpopts1(helpstr,prog,applic,option,tail)       gethelp( helpstr, prog, applic, (char *)0, option, tail )
+#define helpopts2(helpstr,prog,applic,usage,option,tail) gethelp( helpstr, prog, applic, usage,     option, tail )
+#define helpopts3(helpstr,prog,applic,usage,option)      gethelp( helpstr, prog, applic, usage,     option, exit )
+
+
+/* option syntax (for help messages) */
+
+static char Flag_Syntax[]   = "-<name>"                                 ;
+static char Arg_Syntax[]    = "-<name>[=]<value>"                       ;
+static char Eq_Syntax[]     = "[-]<name>=<value>"                       ;
+static char Onoff_Syntax[]  = "-<name>[[=]<value>]"                     ;
+static char Val_Syntax[]    = "-<name>[=]<value> | [-]<name>=<value>"   ;
+static char Toggle_Syntax[] = "-<name> | [-]<name>=on|off"              ;
+static char All_Syntax[]    = "-<name>[[=]<value>] | [-]<name>=<value>" ;
+
+static char onstr[]  = "on"  ;
+static char offstr[] = "off" ;
+
+
+/* External declarations for variables and functions defined in options.c */
+
+int   LINE_LENGTH   ;
+int   PRECISION     ;   /* for printf */
+int   FIELDWIDTH    ;   /* for printf */
+
+int   ison()        ;
+int   isoff()       ;
+int   ismin()       ;
+int   ismax()       ;
+
+int   isopt()       ;
+int   optindex()    ;
+int   whichopt()    ;
+char *optdflt()     ;
+char *checksyntax() ;
+
+int   getopts()     ;
+int   getvals()     ;
+int   selector()    ;
+int   range()       ;
+int   seekstart()   ;
+int   typeindex()   ;
+int   databytes()   ;
+
+float check_overflow() ;
+
+FILE *openopts()    ;
+FILE *fropen()      ;
+
+
+int   exit()        ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/pitch_strength.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,449 @@
+/***************************************************************************
+  pitch_strength.c      Pitch strength measure from spiral sector-weights contour.
+  ----------------
+			Michael Allerhand, 1992.
+
+	Read m binary shorts (default m=SECTORS) for each specified frame.
+	Compute the pitch-strength of the sector-weights by projecting onto
+	the direction in the sector-weights space (given by vector `vec')
+	which best explains the variation between weak and strong pitch,
+	as exemplified by training data generated from iterated rippled noise.
+
+	The sector weights are normalized with respect to angle (pitch) and
+	magnitude (loudness), and also by extracting features using the
+	method of Fourier descriptors.
+
+****************************************************************************/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[] = "Pitch-strength measure from spiral sector-weights contour.\n            (Input and output in binary shorts)." ;
+
+static char *helpstr, *debugstr, *fstr, *vstr, *mstr, *shiftstr, *scalestr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                  , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                      , DEBUG   },
+    {   "frames"    ,   "1-max"     ,  &fstr        ,   "select frames inclusively"             , VAL     },
+    {   "nsectors"  ,   "64"        ,  &mstr        ,   "number of sectors"                     , SVAL    },
+    {   "vector"    ,   "off"       ,  &vstr        ,   "file for alternative projection vector", SVAL    },
+    {   "shift"     ,   "212.0"     ,  &shiftstr    ,   "scale shifting by addition"            , SVAL    },
+    {   "scale"     ,   "0.7686"    ,  &scalestr    ,   "scaling by multiplication"             , SVAL    },
+   ( char * ) 0 } ;
+
+
+/* projection vector for 64-sector cntour */
+
+char *defvec[] = { "0.000",  "0.150", "-0.260", "-0.190", "-0.252", "-0.372", "-0.121",
+		  "-0.374", "-0.150", "-0.236", "-0.157", "-0.109", "-0.246", "-0.088",
+		  "-0.045", "-0.179", "-0.164", "-0.280", "-0.028", "-0.116", "-0.013",
+		  "-0.065", "-0.252", "-0.005", "-0.216", "-0.086",  "0.043", "-0.061",
+		  "-0.055",  "0.084", "-0.045", "-0.203", "211.670" } ;
+
+
+float shift, scale ;
+
+
+main (argc, argv)
+int     argc;
+char ** argv;
+{
+    FILE   *fp, *fp1 ;
+    int     m, n;               /* Number of sectors around spiral.         */
+    short  *sector;             /* Sector-weights contour.                  */
+    float  *vec;
+    int     i, a, b;
+    char   *val1, *val2 ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    shift = atof( shiftstr ) ;
+    scale = atof( scalestr ) ;
+
+    m = atoi( mstr ) ;
+    n = m>>1 ;
+
+    /* parse bounds on number of frames */
+
+    if ( getvals( fstr, &val1, &val2, "-" ) == BADVAL ) {
+	fprintf(stderr,"loudness: bad frame selector [%s]\n", fstr ) ;
+	exit( 1 ) ;
+    }
+    a = atoi( val1 ) ;
+    if ( isempty( val2 ) )    b = a ;
+    else if ( ismax( val2 ) ) b = 0 ;
+    else                      b = atoi( val2 ) ;
+
+    if (b<a && b>0) fprintf(stderr,"pitch_strength: warning, bad frame specifiers\n");
+
+    if ( ison( debugstr ) ) {
+	printf("a=%d b=%d m=%d vector=%s\n",
+		a, b, m, vstr );
+	exit(0);
+    }
+
+
+    /* Allocate space for sector-weights contour and discriminant vector */
+
+    if (( sector = (short *)malloc( m*sizeof(short) )) == NULL)
+	    fprintf(stderr,"pitch_strength: malloc out of space\n");
+    if (( vec = (float *)malloc( (n+1)*sizeof(float) )) == NULL)
+	fprintf(stderr,"pitch_strength: malloc out of space\n");
+
+
+    /* Assign discriminant vector */
+
+    if ( isoff( vstr) )                 /* copy internal (default) vector */
+	for (i=0 ; i<=n ; i++)
+	    vec[i] = atof( defvec[i] ) ;
+    else {                              /* read alternative vector from file */
+	if ((fp1 = fopen( vstr, "r" )) == NULL) {
+	    fprintf(stderr,"pitch_strength: can't open %s\n", vstr );
+	    exit(1);
+	}
+	if ( fread(vec, sizeof(float), n+1, fp1) == NULL ) {
+	    fprintf(stderr,"pitch_strength: empty discriminant vector\n");
+	    exit(1);
+	}
+	fclose(fp1);
+    }
+
+
+    /* Seek past a-1 frames, then read the next b-a+1 frames, or all    */
+    /* remaining frames if b==0.                                        */
+
+    if (a>0) {
+
+	for (i=1 ; i<a  && fread(sector,sizeof(short),m,fp) ; i++)
+	    ;
+	if (b > 0)
+	    for (  ; i<=b && fread(sector,sizeof(short),m,fp) ; i++)
+		pitch_strength( sector, m, n, vec );
+	else
+	    while ( fread(sector,sizeof(short),m,fp) )
+		pitch_strength( sector, m, n, vec );
+    }
+
+    fclose(fp);
+}
+
+
+pitch_strength( sector, m, n, vec )
+short  *sector;         /* Sector-weights contour.                  */
+int     m, n;           /* Number of sectors around spiral.         */
+float  *vec;
+{
+    float  inner_product();
+    short  w0;
+
+    normalize_scale(sector,m);
+    normalize_angle(sector,m);
+    Fd(sector,m,n);
+    sector[0] = 0;      /* normalize for translation */
+    sector[n] = 1;      /* Augment each data vector with 1 */
+    w0 = (short)( ( shift - inner_product( vec, sector, n+1 ) ) * scale ) ;
+    fwrite (&w0, sizeof(short), 1, stdout);
+}
+
+
+/****************************************************************************
+    Inner product (for projection).
+****************************************************************************/
+
+float inner_product(W,V,m)
+float *W;
+short *V;
+int    m;
+{
+    int   i;
+    float w0=0;
+
+    for (i=0 ; i<m ; i++)
+	w0 += W[i] * V[i];
+    return w0;
+}
+
+
+/****************************************************************************
+    Normalize Scale.
+****************************************************************************/
+
+/*
+Normalize for unit variance and zero mean, and then scale for MEAN and STDDEV.
+In general the stddev is scaled down to STDDEV, but if the stddev is already
+less than the target STDDEV, than it is left alone.
+*/
+
+#define MEAN    100
+#define STDDEV  32       /* Resulting variance will be this squared */
+
+normalize_scale(V,m)
+short *V;
+int    m;
+{
+    int   i;
+    float   mean, var;
+    float sum, sumsq, stddev, norm;
+
+    sum=0; sumsq=0;
+    for (i=0 ; i<m ; i++) {
+	sum   += V[i];
+	sumsq += V[i] * V[i];
+    }
+    mean = sum/m;
+    var  = sumsq/m - mean*mean;
+
+    if ((stddev = sqrt(var)) >= STDDEV)
+	for (i=0 ; i<m ; i++) {
+	    norm = ( (float)V[i] - mean ) / stddev;
+	    V[i] = norm * STDDEV + MEAN;
+	}
+    else
+	for (i=0 ;  i<m ; i++) {
+	    norm = (float)V[i]-mean;
+	    V[i] = norm + MEAN;
+	}
+
+    return (int)mean;
+}
+
+
+/****************************************************************************
+    Normalize Angle (orientation).
+****************************************************************************/
+
+/*
+  For a given spoke number k (where the primary spoke is number 1, and the
+  subsequent spokes are numbered 2,3,...,m), return the angle as a number of
+  sectors from the primary spoke.
+  In general, the angle between the primary spoke and the k'th spoke is
+  given by the fractional part of log2(2k-1). This angle is a fraction of
+  unity (the complete cycle), so in terms of m sectors, we simply multiply up
+  by m.
+*/
+
+#define log2(x)     (log((double)x)/log(2.0))
+
+angle(k,m)
+short k, m;
+{
+    double  theta, fptr, iptr;
+
+    if (k==0) return 0;
+    theta = log2(2*k-1);
+    fptr = modf(theta,&iptr);       /* find fractional part of log time */
+    /* scale up to given resolution, and round */
+    return ((int)(0.5+(fptr*m)));
+}
+
+
+/*
+ Normalize orientation.
+ Find the orientation by rotating a template of four sectors set at relative
+ angles appropriate to the first four spokes, (as the angle between spokes is
+ known). The angle at which the weighted sum of these sectors is a maximum,
+ as it is rotated, gives the orientation of the sector-weights contour.
+ This angle of orientation, phi, is returned.
+ The sector-weights contour is normalized by rotating, (ie sorting), so that
+ the principal spoke, (the first of the four), is in the datum position, (at
+ sector[0]).
+*/
+
+int normalize_angle(sector,m)
+short *sector;
+int    m;       /* number of sectors */
+{
+    int    i, k, phi;
+    float  q, max;
+    short *tmp; /* temporary array for sorting */
+
+    /* Find angle of orientation phi */
+
+    phi = 0; max = 0;
+    for (k=0 ; k<m ; k++) {
+	q = (float)sector[k] + 0.8*(float)sector[(k+angle(2,m))%m] +
+	    0.6*(float)sector[(k+angle(3,m))%m] + 0.4*(float)sector[(k+angle(4,m))%m] ;
+
+	if (q > max) {
+	    max = q;
+	    phi = k;
+	}
+    }
+
+    /* Sort sector array to rotate contour into normalized orientation */
+
+    if (( tmp = (short *)malloc(m*sizeof(short))) == NULL)
+	fprintf(stderr,"pitch_strength: malloc out of space\n");
+
+    for (i=0, k=phi ; k<m ; i++, k++)
+	tmp[i] = sector[k];
+    for (k=0 ; k<phi ; i++, k++)
+	tmp[i] = sector[k];
+    for (k=0 ; k<m ; k++)
+	sector[k] = tmp[k];
+
+    /* Return orientation, (angle increases clockwise from 0 to m-1) */
+
+    if (phi == 0) return 0;
+    else          return ( m-phi );
+
+}
+
+
+/****************************************************************************
+ Map m sector-weights onto m/2 Fourier descriptors.
+****************************************************************************/
+
+typedef struct {
+    float real;
+    float imag;
+} complex;
+
+#define PI              3.14159265
+#define TWOPI           6.2831853
+#define sq(x)           ((x)*(x))
+#define Re(C)           ( (C)->real )   /* cartesian form */
+#define Im(C)           ( (C)->imag )
+#define Mod(C)          ( (C)->real )   /* polar form     */
+#define Arg(C)          ( (C)->imag )
+#define cscalar_mod(C)  ( sqrt(sq(Re(C))+sq(Im(C))) )
+#define FFT_real(V,n)   ( realft((float *)(V)-1, n>>1 ,1) )
+
+
+Fd(sector,m,n)
+short *sector;
+int    m, n;
+{
+    static float   *V;
+    static char first=1;
+    int    i, j;
+
+    if (first) {        /* Allocate space first time only */
+	if (( V = (float *)  malloc( m*sizeof(float)   )) == NULL) {
+	    fprintf(stderr,"pitch_strength: malloc out of space\n");
+	    exit(1);
+	}
+	first=0;
+    }
+
+    for (i=0 ; i<m ; i++)
+	V[i] =  sector[i] ;
+    FFT_real(V,m);
+    cvector_mod( sector, (complex *)V, n ) ; /* magnitude spectrum */
+
+}
+
+cvector_mod(V,C,m)
+short   *V;
+complex *C;
+int      m;
+{
+    int   i;
+
+    for (i=0; i<m ; i++)
+	V[i] = (short)( cscalar_mod(&C[i]) ) ;
+}
+
+
+realft(data,n,isign)
+float data[];
+int n,isign;
+{
+	int i,i1,i2,i3,i4,n2p3;
+	float c1=0.5,c2,h1r,h1i,h2r,h2i;
+	double wr,wi,wpr,wpi,wtemp,theta;
+
+
+	theta=3.141592653589793/(double) n;
+	if (isign == 1) {
+		c2 = -0.5;
+		four1(data,n,1);
+	} else {
+		c2=0.5;
+		theta = -theta;
+	}
+	wtemp=sin(0.5*theta);
+	wpr = -2.0*wtemp*wtemp;
+	wpi=sin(theta);
+	wr=1.0+wpr;
+	wi=wpi;
+	n2p3=2*n+3;
+	for (i=2;i<=n/2;i++) {
+		i4=1+(i3=n2p3-(i2=1+(i1=i+i-1)));
+		h1r=c1*(data[i1]+data[i3]);
+		h1i=c1*(data[i2]-data[i4]);
+		h2r = -c2*(data[i2]+data[i4]);
+		h2i=c2*(data[i1]-data[i3]);
+		data[i1]=h1r+wr*h2r-wi*h2i;
+		data[i2]=h1i+wr*h2i+wi*h2r;
+		data[i3]=h1r-wr*h2r+wi*h2i;
+		data[i4] = -h1i+wr*h2i+wi*h2r;
+		wr=(wtemp=wr)*wpr-wi*wpi+wr;
+		wi=wi*wpr+wtemp*wpi+wi;
+	}
+	if (isign == 1) {
+		data[1] = (h1r=data[1])+data[2];
+		data[2] = h1r-data[2];
+	} else {
+		data[1]=c1*((h1r=data[1])+data[2]);
+		data[2]=c1*(h1r-data[2]);
+		four1(data,n,-1);
+	}
+}
+
+#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
+
+four1(data,nn,isign)
+float data[];
+int nn,isign;
+{
+	int n,mmax,m,j,istep,i;
+	double wtemp,wr,wpr,wpi,wi,theta;
+	float tempr,tempi;
+
+	n=nn << 1;
+	j=1;
+	for (i=1;i<n;i+=2) {
+		if (j > i) {
+			SWAP(data[j],data[i]);
+			SWAP(data[j+1],data[i+1]);
+		}
+		m=n >> 1;
+		while (m >= 2 && j > m) {
+			j -= m;
+			m >>= 1;
+		}
+		j += m;
+	}
+	mmax=2;
+	while (n > mmax) {
+		istep=2*mmax;
+		theta=6.28318530717959/(isign*mmax);
+		wtemp=sin(0.5*theta);
+		wpr = -2.0*wtemp*wtemp;
+		wpi=sin(theta);
+		wr=1.0;
+		wi=0.0;
+		for (m=1;m<mmax;m+=2) {
+			for (i=m;i<=n;i+=istep) {
+				j=i+mmax;
+				tempr=wr*data[j]-wi*data[j+1];
+				tempi=wr*data[j+1]+wi*data[j];
+				data[j]=data[i]-tempr;
+				data[j+1]=data[i+1]-tempi;
+				data[i] += tempr;
+				data[i+1] += tempi;
+			}
+			wr=(wtemp=wr)*wpr-wi*wpi+wr;
+			wi=wi*wpr+wtemp*wpi+wi;
+		}
+		mmax=istep;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ptrain.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,119 @@
+/*
+  ptrain.c    generate a pulse train of binary shorts.
+  --------
+    Generate samples of a pulse train at a given sample rate.
+    Specify pulse amplitude and width (in s, ms, or p (sample points) ),
+    and also the period of the waveform (in s, ms, or p (sample points) ).
+    The pulse amplitude is the pulse height above the zero level, which is
+    set by the offset option. The offset is "0" by default so that pulses
+    of any given amplitude are non-negative by default.
+
+    Output samples in binary shorts for the given waveform duration.
+
+    Non-fixed period pulse trains:
+    If a filename is given, then the period of the output pulse train is
+    taken from the file. Binary shorts read from the file are subsequent
+    periods in samples. Periods are output until the file is empty.
+
+
+Examples:
+
+1. A pulse train with period 100 samples and pulse width 1 sample:
+
+ptrain period=100p width=1p
+
+2. A pulse train with period 8ms at 20KHz and pulse width 4 samples
+
+ptrain -p8ms -s20000 -w4
+
+3. A square wave (pulse width = half period) of period 4ms, sampled at 10kHz
+
+ptrain period=4ms width=2ms samplerate=10kHz
+
+3. A square wave of period 4ms with zero mean value
+
+ptrain period=4ms width=2ms offset=0
+
+*/
+
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[]  = "generate a pulse train of binary shorts. " ;
+char usage[]   = "ptrain [options]" ;
+
+static char *helpstr, *debugstr, *sampstr, *pstr, *astr, *ostr, *wstr, *dstr, *phstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                     , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"         , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "              , VAL     },
+    {   "duration"  ,   "500ms"     ,  &dstr        ,   "duration of waveform"     , VAL     },
+    {   "period"    ,   "8ms"       ,  &pstr        ,   "period of pulse train"    , VAL     },
+    {   "amplitude" ,   "1024"      ,  &astr        ,   "pulse amplitude"          , VAL     },
+    {   "width"     ,   "4p"        ,  &wstr        ,   "pulse width"              , VAL     },
+    {   "offset"    ,   "0"         ,  &ostr        ,   "dc offset"                , VAL     },
+    {   "phase"     ,   "0"         ,  &phstr       ,   "phase offset"             , VAL     },
+   ( char * ) 0 } ;
+
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE   *fp, *fopen() ;
+    short  a, z = 0;   /* Zero */
+    int    i, j, samplerate ;
+    int    T, w, n, phase ;
+
+    i = getopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts3( helpstr, argv[0], applic, usage, option ) ;
+
+    samplerate = to_Hz( sampstr ) ;
+    T = (int)to_p( pstr, samplerate ) ; /* period */
+    w = (int)to_p( wstr, samplerate ) ; /* width */
+    n = to_p( dstr, samplerate ) ;      /* duration in points */
+
+    z = atoi( ostr ) ;      /* zero level set to the dc offset (default 0) */
+    a = atoi( astr ) + z ;  /* amplitude (pulse height above zero level)   */
+
+
+    if ( ( phase = (int)to_p( pstr, samplerate ) ) > 0 ) {   /* initial phase offset */
+	for (j=0 ; j<phase ; j++ )
+	    fwrite(&z, sizeof(short), 1, stdout);
+    }
+
+    /* Using given arg T to generate fixed periods */
+
+    if ( i == 0 ) {
+	for (i=0 ; i<n ;  ) {
+	    for (j=0 ; j<w && i<n ; j++, i++)
+		fwrite(&a, sizeof(short), 1, stdout);
+	    for ( ; j<T && i<n ; j++, i++)
+		fwrite(&z, sizeof(short), 1, stdout);
+	}
+    }
+
+
+    /* Reading periods T from file argv[argc-i] */
+
+    else {
+	if ( ( fp = fopen( argv[argc-i], "r" ) ) == NULL ) {
+	    fprintf(stderr,"can't open %s\n", argv[argc-i] );
+	    exit(1);
+	}
+	while ( fread( &T, sizeof(short), 1, fp ) ) {
+	    for (j=0 ; j<w ; j++)
+		fwrite(&a, sizeof(short), 1, stdout);
+	    for ( ; j<T ; j++)
+		fwrite(&z, sizeof(short), 1, stdout);
+	}
+	fclose( fp ) ;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/racf.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,321 @@
+/*
+  Autocorrelation function using recursive "leaky integrator" filter
+  ie. for the m'th lag, the n'th recursive update is:
+
+	y[n] = a.y[n-1] + (1-a).f[n].f[n-m]
+
+  where decay constant a = exp(-Ts/T)
+  and   Ts is sample interval in seconds
+	T  is decay time constant in seconds
+
+  The recursion computes the mean value of the product f[n].f[n-m]
+  within an exponential window which weights past values.
+  The window width parameter (eg. corresponding with the width of the
+  fft analysis window) is the time constant parameter.
+  The half life of the exponential window is given by -T.ln(0.5) = 0.693T
+  ie. for a given time constant, T secs, the window decays to half of its
+  current value in a period of 0.693T secs.
+  So T can be set to accomodate an expected period.
+  As a rough guide, in a period of 0.5T the window decays to about 0.6
+  (ie by 60%), so set T to twice the expected period of the waveform to
+  get 60% of the window over this period.
+  Eg. if the waveform has an expected period of t ms, then to set 60% of
+  the window to this period, set 0.5T = t ms, ie. T = 2t ms.
+
+  The routine generates the autocovariance function.
+  An optional normalization (dividing each coefficient by the zeroth
+  coefficient) produces the autocorrelation function,
+  (and this is then scaled up to the range [0-1000]).
+
+  The output framewidth is the given maximum acf lag.
+
+  Frames are selected from the input stream using the "frames" option,
+  which has syntax: [[-]frame=a[-b]]. Input frames  are numbered 1,2,...
+  For example:
+    frame=a      Select just the a'th frame.
+    frame=a-b    Select frames from the a'th to b'th inclusive.
+  The strings "min" and "max" can be used as specifiers, meaning eg:
+    frame=min    Select the first frame.
+    frame=max    Select the last frame.
+    frame=a-max  Select frames from the a'th to the last inclusive.
+    frame=min-b  Select frames from the first to the b'th inclusive.
+  The default selects all frames, (ie frame=min-max).
+
+
+  Examples:
+
+1. To print the input and output frame sizes in sample points, eg for a
+   subsequent plotting program, use the size option:
+
+acf ... size=on
+
+2. An acf of a waveform sampled at 10kHz, computed to a max lag of 12.8ms,
+   plotting the 2nd frame in a sequence of frames with frameshift 12.8ms.
+
+acf samp=10kHz frstep=12.8ms frame=2 lag=12.8ms file | x11plot
+
+3. An animated plot of successive acf's of a waveform sampled at 10kHz,
+   shifted by 2 sample points.
+
+acf samp=10kHz frstep=2p lag=12.8ms file | x11play -n128
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+#include "sigproc.h"
+
+char applic[]     = "autocorrelation function of contiguous frames.\n      i/p and o/p data in binary shorts." ;
+
+static char *helpstr, *debugstr, *sampstr,  *startstr, *shiftstr, *sizestr ;
+static char *lagstr,  *tcstr,    *scalestr, *normstr,  *framestr, *echostr ;
+static char *negstr,  *upstr,    *slopestr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                  , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                      , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "Samplerate "                           , VAL     },
+    {   "start"     ,   "0"         ,  &startstr    ,   "Start point in i/p file."              , VAL     },
+    {   "frames"    ,   "1-max"     ,  &framestr    ,   "Select frames inclusively"             , VAL     },
+    {   "frstep"    ,   "1ms"       ,  &shiftstr    ,   "Step between output frames."           , VAL     },
+    {   "lag"       ,   "32ms"      ,  &lagstr      ,   "Maximum acf lag (output frame width)." , VAL     },
+    {   "update"    ,   "1p"        ,  &upstr       ,   "Step between recursive updates."       , VAL     },
+    {   "timeconst" ,   "3ms"       ,  &tcstr       ,   "Decay time constant"                   , VAL     },
+    {   "normalize" ,   "off"       ,  &normstr     ,   "Normalized acf"                        , SETFLAG },
+    {   "scale"     ,   "0.003"     ,  &scalestr    ,   "scale output"                          , SVAL    },
+    {   "sigmoid"   ,   "off"       ,  &slopestr    ,   "Sigmoidal weighting slope parameter"   , SVAL    },
+    {   "size"      ,   "off"       ,  &sizestr     ,   "Print input/output frame size in samples"      , SETFLAG },
+    {   "echo"      ,   "off"       ,  &echostr     ,   "echo buffered input without processing", SVAL    },
+    {   "negative"  ,   "off"       ,  &negstr      ,   "write negative half of acf (zeroth lag on right)", SVAL    },
+   ( char * ) 0 } ;
+
+
+int     samplerate  ;
+int     framestep   ;
+int     updatestep  ;
+int     maxlag      ;
+double  scale       ;
+int     normalize   ;
+int     echo        ;
+int     negative    ;
+double  alpha       ;   /* decay constant */
+
+float  *vec   ;
+short  *obuf  ;
+
+main (argc, argv)
+int     argc;
+char  **argv;
+{
+    FILE     *fp  ;
+    int       a, b ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    samplerate = to_Hz( sampstr ) ;
+    normalize  = ison(  normstr ) ;
+    echo       = ison(  echostr ) ;
+    negative   = ison(  negstr  ) ;
+
+    framestep  = to_p( shiftstr, samplerate )  ;
+    updatestep = to_p( upstr   , samplerate )  ;
+    maxlag     = to_p( lagstr  , samplerate )  ;
+
+    scale      = atof( scalestr ) ;
+
+    alpha      = exp( -(double)( 1. / ( samplerate * to_s( tcstr, samplerate ) ) ) ) ;
+
+    if ( framestep % updatestep != 0 ) {
+	fprintf(stderr,"frstep [%dp] must be an integer multiple of update [%dp] \n", framestep, updatestep ) ;
+	exit( 1 ) ;
+    }
+
+    /* frame size printout */
+
+    if ( ison( sizestr ) ) {
+	fprintf(stderr,"acf sizes in sample points:\n" ) ;
+	fprintf(stderr,"    output frame size = %d \n", maxlag ) ;
+	exit( 0 ) ;
+    }
+
+    /* parse bounds on number of frames */
+
+    if ( selector( framestr, &a, &b ) == 0 ) {
+	fprintf(stderr,"acf: bad frame selector [%s]\n", framestr ) ;
+	exit( 1 ) ;
+    }
+
+    /* Allocate working space */
+
+    obuf  = (short *)malloc( maxlag * sizeof(short) ) ;
+    vec   = (float *)malloc( maxlag * sizeof(float) ) ;
+
+    /* Compute acf for each frame of width shorts in the input stream */
+
+    if ( seekbytes( fp, (int)( to_p( startstr, samplerate ) * sizeof(short) ) ) == 0 ) {
+	fprintf(stderr,"improper seek\n") ;
+	exit( 1 ) ;
+    }
+
+    if ( isoff( slopestr ) )
+	process( fp, a, b ) ;                   /* conventional acf recursion */
+    else
+	process2( fp, a, b, atof( slopestr) ) ; /* sigmoidally weighted recursion */
+						/* (recommend set sigmoid=.02)    */
+
+    fclose( fp ) ;
+}
+
+
+process( fp, a, b )
+FILE *fp ;
+int   a, b ;
+{
+    register  short  *buf, *bptr, *endptr ;
+    register  float  *vptr ;
+    register  double  beta ;
+    register  int     update_count = 0 ;
+    register  int     frame_count  = 0 ;
+
+    /* Initialize process with the first maxlag samples */
+
+    if ( ( buf = getframe( fp, 1, maxlag, updatestep ) ) != (short *)0 ) {
+	for ( endptr = buf ; endptr < buf + maxlag ; endptr++ ) {
+	    bptr = endptr ;
+	    vptr = vec ;
+	    beta = ( 1-alpha ) * *bptr ;
+	    while ( bptr >= buf )
+		*vptr++ =  alpha * *vptr + beta * *bptr-- ;
+	}
+
+	update_count = 1 ;
+	frame_count  = 1 ;
+
+	if ( frame_count >= a ) {
+	    if ( echo )
+		fwrite( buf, sizeof(short), maxlag, stdout ) ;
+	    else
+		writeframe() ;
+	}
+    }
+
+    /* Continue process with successive buffers of maxlag samples */
+
+    while ( ( buf = getframe( fp, ++update_count, maxlag, updatestep ) ) != (short *)0 && ( frame_count<=b || b==0 ) ) {
+	bptr = buf + maxlag - 1 ;
+	vptr = vec ;
+	beta = ( 1-alpha ) * *bptr ;
+
+	while ( bptr >= buf )     /* recursive update */
+	    *vptr++ =  alpha * *vptr + beta * *bptr-- ;
+
+	if ( update_count % framestep == 1 ) {
+	    if ( ++frame_count >= a && ( frame_count <= b || b == 0 ) ) {
+		if ( echo )
+		    fwrite( buf, sizeof(short), maxlag, stdout ) ;
+		else
+		    writeframe() ;
+	    }
+	}
+    }
+    if ( frame_count <= b && b > 0 )
+	fprintf(stderr,"warning: not enough frames for request\n");
+}
+
+
+writeframe()
+{
+    register  float  *vptr   = vec ;
+    register  short  *optr   = obuf ;
+    register  short  *endlag = obuf + maxlag ;
+
+    if ( normalize )
+	scale = 1000. / *vec ;
+
+    while ( optr < endlag )
+	*optr++ = (short)( scale * *vptr++ ) ;
+
+    if ( !negative )
+	fwrite( obuf, sizeof(short), maxlag, stdout ) ;
+    else {
+	for ( optr = endlag-1 ; optr >= obuf ; optr-- )
+	    fwrite( optr, sizeof(short), 1, stdout ) ;
+    }
+}
+
+
+/*************************************************************************/
+/*
+  same as `process', but with added sigmoidal weighting
+*/
+
+process2( fp, a, b, slope )
+FILE *fp ;
+int   a, b  ;
+float slope ;
+{
+    register  short  *buf, *bptr, *endptr ;
+    register  float  *vptr ;
+    register  double  beta ;
+    register  int     update_count = 0 ;
+    register  int     frame_count  = 0 ;
+    double    sigmoid() ;
+
+    /* Initialize process with the first maxlag samples */
+
+    if ( ( buf = getframe( fp, 1, maxlag, updatestep ) ) != (short *)0 ) {
+	for ( endptr = buf ; endptr < buf + maxlag ; endptr++ ) {
+	    bptr = endptr ;
+	    vptr = vec ;
+	    beta = ( 1-alpha ) * *bptr ;
+	    while ( bptr >= buf )
+		*vptr++ =  alpha * *vptr + beta * sigmoid( fabs((double)*endptr) - fabs((double)*bptr ), slope ) * *bptr-- ;
+	}
+
+	update_count = 1 ;
+	frame_count  = 1 ;
+
+	if ( frame_count >= a ) {
+	    if ( echo )
+		fwrite( buf, sizeof(short), maxlag, stdout ) ;
+	    else
+		writeframe() ;
+	}
+    }
+
+    /* Continue process with successive buffers of maxlag samples */
+
+    while ( ( buf = getframe( fp, ++update_count, maxlag, updatestep ) ) != (short *)0 && ( frame_count<=b || b==0 ) ) {
+	endptr = buf + maxlag - 1 ;
+	bptr   = endptr ;
+	vptr   = vec ;
+	beta   = ( 1-alpha ) * *bptr ;
+
+	while ( bptr >= buf )     /* recursive update */
+	    *vptr++ =  alpha * *vptr + beta * sigmoid( fabs((double)*endptr) - fabs((double)*bptr ), slope ) * *bptr-- ;
+
+	if ( update_count % framestep == 1 ) {
+	    if ( ++frame_count >= a && ( frame_count <= b || b == 0 ) ) {
+		if ( echo )
+		    fwrite( buf, sizeof(short), maxlag, stdout ) ;
+		else
+		    writeframe() ;
+	    }
+	}
+    }
+    if ( frame_count <= b && b > 0 )
+	fprintf(stderr,"warning: not enough frames for request\n");
+}
+
+
+double sigmoid( x, slope )
+double x ;
+float  slope ;
+{
+    return (double)( 1. / ( exp( -(double)( 4.595 + slope * x ) ) + 1. ) ) ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/ramp.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,162 @@
+/*
+  ramp.c    generate an exponential sawtooth waveform
+  ------    (in binary shorts or floats).
+
+    Generate samples of a sawtooth waveform at a given sample rate.
+
+    Decaying exponential:  A.exp(-t)    0<=t<=T
+    Growing exponential:   A.exp(t)    -T<=t<=0
+	  or (shifting):   A.exp(t-T)   0<=t<=T
+
+    To arrange for a decay factor to correspond to the half life, so that
+    the wave grows/decays to half the given amplitude in the given decay time,
+    the argument of the exponential must be calibrated to result in 0.5.
+    If  exp(-x) = 0.5, then we have -x = ln(0.5) = -0.693147
+    so that:  x = 0.693147
+    For a given decay factor, the damped exponential decays to half the given
+    amplitude in this time. The ramped exponential is a time-reversed damped
+    exponential.
+
+
+Examples:
+
+1. Growing exponentials
+
+ramp polarity=ramp dec=1ms | x11plot
+
+2. Decaying exponentials
+
+ramp polarity=damp dec=1ms | x11plot
+
+3. Half a cycle of an 8ms decaying exponential.
+
+ramp polarity=damp dec=1ms dur=4ms | x11plot
+
+4. Modulating a tone with a damped exponential.
+
+tone period=.5ms amp=500 type=float    > foo1
+ramp pol=damp dec=1ms amp=1 type=float > foo2
+merge op=mult type=float foo1 foo2  |  ftos | x11plot -n512
+
+5. Modulating a tone with a ramped exponential.
+
+tone period=.5ms amp=500 type=float    > foo1
+ramp pol=ramp dec=1ms amp=1 type=float > foo2
+merge op=mult type=float foo1 foo2  |  ftos | x11plot -n512
+
+6. Modulating a tone with a damped exponential, and half-wave rectifying to
+   generate damped pulses.
+
+tone period=.5ms amp=500 type=float    > foo1
+ramp pol=damp dec=1ms amp=1 type=float > foo2
+merge op=mult type=float foo1 foo2 | ftos | gate range=min-0 op=0 | x11plot -n512
+
+7. Modulating white noise with a ramped exponential.
+
+noise type=float  > foo1
+ramp pol=ramp dec=1ms amp=1 type=float > foo2
+merge op=mult type=float foo1 foo2 | ftos | x11plot -n512
+
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[]  = "generate an exponential sawtooth waveform. " ;
+char usage[]   = "ramp [options]" ;
+
+static char *helpstr, *debugstr, *sampstr, *perstr, *astr, *decstr, *polstr, *dstr, *datastr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                     , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"         , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "              , VAL     },
+    {   "period"    ,   "8ms"       ,  &perstr      ,   "period [s,ms,p] of ramp"  , VAL     },
+    {   "amplitude" ,   "1024"      ,  &astr        ,   "amplitude of waveform"    , VAL     },
+    {   "decay"     ,   "2ms"       ,  &decstr      ,   "half-life of ramp"        , VAL     },
+    {   "polarity"  ,   "ramp"      ,  &polstr      ,   "ramp (growing) / damp (decaying)", VAL },
+    {   "duration"  ,   "500ms"     ,  &dstr        ,   "duration of waveform"     , VAL     },
+    {   "type"      ,   "short"     ,  &datastr     ,   "o/p datatype (short/float)", VAL     },
+   ( char * ) 0 } ;
+
+
+#define DECAYFACTOR     ( 0.693147 )
+
+int     samplerate ;
+float   amplitude  ;
+int     duration   ;
+int     period     ;
+int     decay      ;
+double  decayrate  ;
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    int    i, n, t ;
+    short  s ;
+    float  f ;
+
+    getopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts3( helpstr, argv[0], applic, usage, option ) ;
+
+    samplerate = to_Hz( sampstr, 0 ) ;
+    amplitude  = atof( astr ) ;
+    period     = (int)to_p( perstr, samplerate ) ;
+    decay      = (int)to_p( decstr, samplerate ) ;
+    duration   = to_p( dstr, samplerate )   ;
+
+/*
+    if ( decay >= period ) {
+	fprintf(stderr,"ramp: half-life period [%dp] must be less than waveform period [%dp]\n", decay, period);
+	exit( 1 ) ;
+    }
+*/
+    decayrate  = DECAYFACTOR / (double)decay ;
+
+    if ( iststr( polstr, "damped" ) ) {
+
+	/* Decaying exponential */
+
+	if ( iststr( datastr, "short" ) )
+	    for ( i=0 ; i<duration ;  )
+		for ( t=0 ; t<period && i<duration ; t++, i++ ) {
+		    s = amplitude * exp( - (double)( t * decayrate ) ) ;
+		    fwrite( &s, sizeof(short), 1, stdout ) ;
+		}
+	else if ( iststr( datastr, "float" ) )
+	    for ( i=0 ; i<duration ;  )
+		for ( t=0 ; t<period && i<duration ; t++, i++ ) {
+		    f = amplitude * exp( - (double)( t * decayrate ) ) ;
+		    fwrite( &f, sizeof(float), 1, stdout ) ;
+		}
+	else
+	    fprintf(stderr,"unknown datatype [%s]\n", datastr) ;
+    }
+    else if ( iststr( polstr, "ramped" ) ) {
+
+	/* Growing exponential */
+
+	if ( iststr( datastr, "short" ) )
+	    for ( i=0 ; i<duration ;  )
+		for ( t=(-period) ; t<=0 && i<duration ; t++, i++ ) {
+		    s = amplitude * exp( (double)( t * decayrate ) ) ;
+		    fwrite( &s, sizeof(short), 1, stdout ) ;
+		}
+	else if ( iststr( datastr, "float" ) )
+	    for ( i=0 ; i<duration ;  )
+		for ( t=(-period) ; t<=0 && i<duration ; t++, i++ ) {
+		    f = amplitude * exp( (double)( t * decayrate ) ) ;
+		    fwrite( &f, sizeof(float), 1, stdout ) ;
+		}
+	else
+	    fprintf(stderr,"unknown datatype [%s]\n", datastr) ;
+    }
+    else
+	fprintf( stderr, "unknown polarity [%s]\n", polstr ) ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/saitonap.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,258 @@
+/*
+  saitonap.c            SAI to NAP format conversion.
+ ------------
+
+    Read a SAI header and a succession of frames.
+    Write a NAP header, (created from the SAI header).
+    Write each frame in NAP format.
+
+*/
+
+
+#include <stdio.h>
+#include <math.h>
+#include "header.h"
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[]     = "SAI to NAP format conversion. " ;
+
+static char *helpstr, *debugstr, *fstr, *headerstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                          , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"              , DEBUG   },
+    {   "frame"     ,   "min-max"   ,  &fstr        ,   "select frames inclusively"     , VAL     },
+    {   "header"    ,   "on"        ,  &headerstr   ,   "nap header"                    , VAL     },
+   ( char * ) 0 } ;
+
+
+int     frameheight, framewidth ;       /* Sai parameters read from header */
+int     frames ;
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE   *fp ;
+    int     i, framebytes, startbytes, frameshift;
+    char   *header, *napheader, *SaiHeader();
+    short  *frame  ;
+    char   *val1, *val2 ;
+    int     a,b ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    if ( (header = ReadHeader(fp)) == (char *) 0 ) {
+	fprintf(stderr,"saitonap: header not found\n");
+	exit(1);
+    }
+
+    frameheight = HeaderInt( header, "frameheight" );
+    framewidth =  HeaderInt( header, "framewidth"  );
+    frames =      HeaderInt( header, "frames"      );
+
+    framebytes = frameheight * framewidth * sizeof(short) ;
+
+
+    /* Get limits on specified number of frames */
+
+    if ( getvals( fstr, &val1, &val2, "-" ) == BADVAL ) {
+	fprintf(stderr,"saitonap: bad frame selector [%s]\n", fstr ) ;
+	exit( 1 ) ;
+    }
+    if      ( ismin( val1 ) ) a = 1 ;
+    else if ( ismax( val1 ) ) a = frames ;
+    else                      a = atoi( val1 ) ;
+
+    if ( isempty( val2 ) )    b = a ;
+    else if ( ismin( val2 ) ) b = 1 ;
+    else if ( ismax( val2 ) ) b = frames ;
+    else                      b = atoi( val2 ) ;
+
+    if (a<=0 || b>frames || a>b) {
+	fprintf(stderr,"saitonap: bad frame specifier \n" );
+	exit(1);
+    }
+
+
+    /* Allocate space for framebytes of sai data */
+
+    if ( ( frame = (short *)malloc( framebytes )) == NULL ) {
+	fprintf(stderr,"saitonap: malloc out of space\n");
+	exit(1);
+    }
+
+    if ( ison( headerstr ) )
+	napheader = SaiHeader(header) ;
+
+    /* Read and write framebytes of i/p sai data */
+
+    for (i=1 ; i<a  &&  fread( frame,framebytes,1,fp ) ; i++)
+	;
+
+    if ( i < a ) {
+	fprintf(stderr,"saitonap: insufficient data after header \n");
+	exit(1);
+    }
+
+    if (b > 0)
+	for (  ; i<=b && fread( frame,framebytes,1,fp ) ; i++)
+	    writeframe( frame, napheader ) ;
+    else
+	while ( fread( frame,framebytes,1,fp ) )
+	    writeframe( frame, napheader ) ;
+
+    fclose(fp);
+    fprintf(stderr,"saitonap done\n" ) ;
+
+}
+
+
+
+/* Write a frame in nap format */
+
+writeframe( frame, header )
+short  *frame ;
+char   *header ;
+{
+    int    i, row, col;
+
+    if ( ison( headerstr ) )
+	WriteHeader( header, stdout ) ;
+    for ( col=0 ; col < framewidth ; col++ )
+	for ( row=0, i=col ; row < frameheight ; row++, i+=framewidth )
+	    fwrite( &frame[i], sizeof(short), 1, stdout );
+}
+
+
+
+/*
+   Copy the original sai header to a new nap header, changing in order:
+     frames
+     frameshift
+     framewidth
+     frameheight
+     framebytes
+   Then change applic name [gensai] to [gennap] in the Version string.
+   Finally, update the new header_bytes, and return the new header.
+*/
+
+char *SaiHeader( SAIheader )
+char *SAIheader ;
+{
+    char *NAPheader;
+    char *p0, *p1, *p2, *s, str[64];
+
+    NAPheader = (char *)malloc( strlen(SAIheader) + 64 ) ;
+
+    p0 = NAPheader ;
+    p1 = SAIheader ;
+
+
+    /** copy up to frames **/
+
+    p2 = HeaderString( SAIheader , "frames" ) ;
+    while( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", framewidth);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to frameshift **/
+
+    p2 = HeaderString( SAIheader , "frameshift" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", 1 );
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to framewidth **/
+
+    p2 = HeaderString( SAIheader , "framewidth" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", 1 );
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to frameheight **/
+
+    p2 = HeaderString( SAIheader , "frameheight" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", frameheight);
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy up to framebytes **/
+
+    p2 = HeaderString( SAIheader , "framebytes" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    sprintf(str,"%d\n", frameheight * sizeof( short ) );
+    for (s = str ; *s != '\n' ; )
+	*p0++ = *s++;
+    *p0++ = *s;
+    while (*p1 != '\n')
+	*p1++;
+    *p1++;
+
+
+    /** copy rest of header **/
+
+    p2 = HeaderString( SAIheader , "Version" ) ;
+    while ( p1 < p2 )
+	*p0++ = *p1++ ;
+
+    while (*p1 != ']')          /* change applic name [gensai] to [gennap] */
+	*p0++ = *p1++ ;
+    *(p0-3) = 'n' ;
+    *(p0-2) = 'a' ;
+    *(p0-1) = 'p' ;
+    while (*p1 != '\n')
+	*p0++ = *p1++ ;
+    *p0++ = *p1++ ;
+
+
+    /** update header_bytes **/
+
+    sprintf(str, "%0*d", 7, p0-NAPheader);
+    p0 = HeaderString( NAPheader , "header_bytes" ) ;
+    s = str;
+    while(*p0 != '\n')
+	*p0++ = *s++ ;
+
+
+    return NAPheader;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/scale.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,271 @@
+/*
+  scale.c       shift and scale a data stream by given constants or to
+  -------       fit a given range (top - bottom).
+
+  Shifting and scaling is done for all input x using the formula:
+	y = ( x - shift ) * scale
+
+  If only a shift term   is given, then the default scale is 1.0
+  If only a scale factor is given, then the default shift is 0.
+
+  If neither shift nor scale are given, then appropriate values are
+  chosen so that the output fits the range specified by `top' and `bottom'.
+  For an input which ranges between extreme values of `max' and `min', the
+  shift and scale factors to give a required range between `top' and `bottom'
+  are found by simultaneously solving:
+	top    = ( max - shift ) * scale
+	bottom = ( min - shift ) * scale
+
+  If top < bottom then the input is inverted in the resulting range.
+
+  The input stream depends upon the `type' option. The output datatype is
+  the same as that selected for input.
+  With no filename arguments, data is expected on the stdin, and the
+  scaled result is written on the stdout. Otherwise each given filename is
+  processed in turn. When the `output' option is "off" output overwrites the
+  respective input file. (The respective output for the stdin is the stdout).
+  Otherwise all scaled input files are written to the given output file
+  (which is the stdout by default).
+
+  The `range' option sets the start and duration of the process.
+  Its arguments are of the form: range=a-b (where start=a and duration=b-a+1)
+			    or: range=a   (where start=a and duration=1    )
+  The arguments can be in time units (ms, s) or samples (no units), and both
+  "min" (start of file) and "max" (end of file) are recognised.
+  Samples in a file are numbered 0,1,2,...,max.
+
+  Examples:
+
+1. Invert the range of a given pulse train to obtain negative-going pulses.
+   (Two ways):
+
+ptrain amp=512 | scale top=-512 bot=0 | x11plot
+ptrain amp=512 | scale scale=-1       | x11plot
+
+*/
+
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[]     = "waveform shifting and scaling:  y = (x - shift) * scale" ;
+
+static char *helpstr,   *debugstr,  *sampstr,   *rangestr,  *outstr     ;
+static char *topstr,    *botstr,    *scalestr,  *typestr,   *sizestr    ;
+static char *shiftstr,  *normstr                                        ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                          , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"              , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "                   , VAL     },
+    {   "range"     ,   "0-max"     ,  &rangestr    ,   "start-finish limits in data"   , VAL     },
+    {   "top"       ,   "1000"      ,  &topstr      ,   "max of scaled data"            , VAL     },
+    {   "bottom"    ,   "-1000"     ,  &botstr      ,   "min of scaled data"            , VAL     },
+    {   "shift"     ,   "off"       ,  &shiftstr    ,   "shift term"                    , VAL     },
+    {   "scale"     ,   "off"       ,  &scalestr    ,   "scale factor"                  , VAL     },
+    {   "normalize" ,   "off"       ,  &normstr     ,   "set zero mean and unit std dev", VAL     },
+    {   "type"      ,   "short"     ,  &typestr     ,   "datatype"                      , VAL     },
+    {   "output"    ,   "stdout"    ,  &outstr      ,   "output filename (off = overwrite input)"   , VAL     },
+    {   "SIZE"      ,   "262144p"   ,  &sizestr     ,   "buffer size (s, ms, or p)"     , SVAL    },
+   ( char * ) 0 } ;
+
+
+int    samplerate  ;
+int    type        ;    /* datatype index */
+int    bytes       ;
+int    SIZE        ;    /* buffer size    */
+
+int    FIT_TO_RANGE = 0 ;
+int    NORMALIZE    = 0 ;
+
+float  shift, scale ;
+
+float *data  ;
+
+FILE  *ofp   ;
+
+main (argc, argv)
+int     argc;
+char  **argv;
+{
+    FILE   *fp ;
+    int     i, j, a, b, n ;
+
+    i = getopts( option, argc, argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    samplerate = to_Hz( sampstr ) ;
+    SIZE       = to_p( sizestr, samplerate ) ;
+
+    if ( ( type = typeindex( typestr ) ) < 0 ) {
+	fprintf( stderr, "scale: bad type [%s]\n", typestr ) ;
+	exit( 1 ) ;
+    }
+    bytes = typebytes( type ) ;
+
+    if ( range( rangestr, &a, &b, samplerate ) == 0 ) {
+	fprintf(stderr,"scale: bad range [%s]\n", rangestr ) ;
+	exit( 1 ) ;
+    }
+
+
+    if ( ison( normstr ) )  NORMALIZE = 1 ;
+    else if ( isoff( shiftstr ) && isoff( scalestr ) ) FIT_TO_RANGE = 1 ;
+    else if ( isoff( shiftstr ) ) {
+	shift = 0  ;
+	scale = atof( scalestr ) ;
+    }
+    else if ( isoff( scalestr ) ) {
+	shift = atof( shiftstr ) ;
+	scale = 1. ;
+    }
+    else {
+	shift = atof( shiftstr ) ;
+	scale = atof( scalestr ) ;
+    }
+
+    if ( ( data = (float *)malloc( SIZE * sizeof(float) ) ) == NULL ) {
+	fprintf( stderr, "malloc out of space\n" ) ;
+	exit( 1 ) ;
+    }
+
+
+    do {
+
+	if ( i == 0 ) fp = stdin ;
+	else if ( ( fp = fopen( argv[argc-i], "r" ) ) == (FILE *)0 ) {
+	    fprintf( stderr,"scale: can't open %s\n", argv[argc-i] ) ;
+	    exit( 1 ) ;
+	}
+
+	if ( seekstart( a, bytes, fp ) < a ) {
+	    fprintf( stderr,"scale: insufficient data in file\n" ) ;
+	    exit( 1 ) ;
+	}
+
+	for ( j = a, n = 0 ; ( j <= b || b == (-1) ) && n < SIZE && readitem( &data[n], type, 1, fp ) ; j++, n++ )
+	    ;
+	if ( n == SIZE )
+	    fprintf( stderr, "scale warning: file %s exceeded buffer size\n",  argv[argc-i] ) ;
+
+	fclose( fp ) ;
+
+
+	if ( NORMALIZE )
+	    getnorm( data, n, &shift, &scale ) ;
+	else if ( FIT_TO_RANGE )
+	    getrange( data, n, atof( topstr ), atof( botstr ), &shift, &scale ) ;
+
+
+	if ( isstr( outstr, "print" ) )
+	    printf( "%8.3f  %8.3f \n", shift, scale ) ;
+	else {
+	    open_output( argc, argv , i ) ;
+	    for ( j = 0 ; j < n ; j++ ) {
+		data[j] = ( data[j] - shift ) * scale ;
+		writeitem( &data[j], type, 1, ofp ) ;
+	    }
+	}
+
+    } while ( --i > 0 ) ;
+
+    fclose( ofp ) ;
+}
+
+
+/*
+Open ouput file pointer, ofp.
+Use the input filename (argv[argc-i]) if outstr is "off", otherwise use
+the given name outstr.
+*/
+
+open_output( argc, argv , i )
+int     argc ;
+char  **argv ;
+int     i    ;
+{
+    static int first = 1 ;
+
+    if ( first ) {
+
+	if ( isoff( outstr ) ) {
+	    if ( i == 0 ) ofp = stdout ;
+	    else if ( ( ofp = fopen( argv[argc-i], "w" ) ) == (FILE *)0 ) {
+		fprintf( stderr,"scale: can't create %s\n", argv[argc-i] ) ;
+		exit( 1 ) ;
+	    }
+	}
+	else if ( isstr( outstr, "stdout") ) ofp = stdout ;
+	else if ( ( ofp = fopen( outstr, "w" ) ) == (FILE *)0 ) {
+	    fprintf( stderr,"scale: can't create %s\n", outstr ) ;
+	    exit( 1 ) ;
+	}
+	first = 0 ;
+    }
+
+    else {
+	if ( isoff( outstr ) ) {
+	    fclose ( ofp ) ;
+	    if ( i == 0 ) ofp = stdout ;
+	    else if ( ( ofp = fopen( argv[argc-i], "w" ) ) == (FILE *)0 ) {
+		fprintf( stderr,"scale: can't create %s\n", argv[argc-i] ) ;
+		exit( 1 ) ;
+	    }
+	}
+    }
+}
+
+
+/*
+Return parameters `shift' and `scale' to normalize the data for zero mean
+and unit std dev:
+	shift = mean
+	scale = 1 / sqrt(variance)
+*/
+
+getnorm( data, n, shift, scale )
+float *data ;
+int    n    ;
+float *shift, *scale  ;
+{
+    int    i ;
+    float  sum = 0, sumsq = 0 ;
+
+    for ( i = 0 ; i < n ; i++ ) {
+	sum   += data[i] ;
+	sumsq += data[i] * data[i] ;
+    }
+
+    *shift = sum / n ;
+    *scale = 1. / sqrt( sumsq / n - *shift * *shift ) ;
+}
+
+
+/*
+Return parameters `shift' and `scale' to fit the given float data into the
+amplitude range delimited by `top' and `bottom'.
+*/
+
+getrange( data, n, top, bottom, shift, scale )
+float *data ;
+int    n    ;
+float  top,    bottom ;
+float *shift, *scale  ;
+{
+    float  min = 1e+8, max = (-1e+8) ;
+    int    i ;
+
+    for ( i = 0 ; i < n ; i++ ) {
+	if ( data[i] > max ) max = data[i] ;
+	if ( data[i] < min ) min = data[i] ;
+    }
+
+    *scale = ( top - bottom ) / ( max - min ) ;
+    *shift = ( min * top - max * bottom ) / ( top - bottom ) ;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/sigproc.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,830 @@
+#include <stdio.h>
+#include <math.h>
+#include "sigproc.h"
+
+
+/*
+  C is n complex numbers: (real,imag), (ie 2n floats).
+  Overwrite the first n floats with the modulus of the n complex numbers.
+*/
+
+Mod( C, n )
+complex *C ;
+int      n ;
+{
+    register complex *eptr = C+n ;
+    register float   *V    = (float *)C ;
+
+    for (  ; C < eptr ; C++ )
+	*V++ = mod(C) ;
+}
+
+/*
+  Return the modulus of the given complex number
+*/
+
+float mod( C )
+complex *C ;
+{
+    return ( sqrt( sq(Re(C)) + sq(Im(C)) ) ) ;
+}
+
+
+
+/*
+  C is n complex numbers: (real,imag), (ie 2n floats).
+  Overwrite the first n floats with the argument of the n complex numbers.
+*/
+
+Arg( C, n )
+complex *C ;
+int      n ;
+{
+    register complex *eptr = C+n ;
+    register float   *V    = (float *)C ;
+
+    for (  ; C < eptr ; C++ )
+	*V++ = arg(C) ;
+}
+
+/*
+  Return the argument of the given complex number
+*/
+
+float arg( C )
+complex *C;
+{
+    if (Im(C) >= 0) {
+	if (Re(C) >= 0) return (         atan(Im(C)/Re(C)) );   /* 1st quad */
+	else            return ( PI    + atan(Im(C)/Re(C)) );   /* 2nd quad */
+    }
+    else {
+	if (Re(C) <  0) return ( PI    + atan(Im(C)/Re(C)) );   /* 1st quad */
+	else            return ( TWOPI + atan(Im(C)/Re(C)) );   /* 2nd quad */
+    }
+}
+
+
+/*
+  C1 and C2 are both n complex numbers: (real,imag), (ie each 2n floats).
+  Overwrite the C1 with product of C1 and the complex conjugate of C2.
+  (When C1==C2, result is squared mod in the real parts, and 0 imag parts).
+*/
+
+conj( C1, C2, n )
+complex *C1, *C2 ;
+int   n ;
+{
+    register complex *eptr = C1+n ;
+    float    ReC1, ReC2 ;
+
+    for (  ; C1 < eptr ; C1++, C2++ ) {
+	Re(C1) = ( ReC1=Re(C1) ) * ( ReC2=Re(C2) ) + Im(C1) * Im(C2) ;
+	Im(C1) =   ReC2          *        Im(C1)   - ReC1   * Im(C2) ;
+    }
+}
+
+
+/*
+  Autocorrelation function via fft.
+  A complex fft (of real data) is multiplied by its conjugate, and also scaled
+  prior to the inverse fft.
+*/
+
+
+
+acf( V, m )
+float *V ;
+int    m ;
+{
+    register complex *C, *eptr ;
+    register int  n = m>>1 ;
+    float    tmp ;
+
+    fft( V, m, 1 ) ;
+    tmp = V[1] ; V[1] = 0 ;
+
+    for ( C=(complex *)V, eptr=C+n ; C<eptr ; C++ ) {
+	Re(C) = ( sq(Re(C)) + sq(Im(C)) ) / n ;
+	Im(C) = 0 ;
+    }
+    V[1] = sq( tmp ) / n ;
+
+    fft( V, m, -1 ) ;
+}
+
+
+/*
+  Test x: return 1 if x is a power of 2, otherwise return 0.
+*/
+
+int ispower( x )
+int  x ;
+{
+    return ( x > 1 && log2(x) == (int)log2(x) ) ;
+}
+
+
+/*
+  Return a power of 2, either equal to x (if x is already a power of 2), or
+  the next power of 2 larger than x.
+*/
+
+int getpower( x )
+int x ;
+{
+    if ( log2(x) > (int)log2(x) )
+	x = 1 << ( 1 + (int)log2(x) ) ;
+    return ( x ) ;
+}
+
+
+/*
+Copy float array x into short array y, both length n points.
+Scale each point using the given scale factor.
+Return 1 if no 16-bit over or underflow.
+Otherwise return a scale factor to replace the given scale factor.
+
+*/
+
+float ftos( x, y, n, scale )
+float *x ;
+short *y ;
+int    n ;
+float  scale ;
+{
+    float  p ;
+    float  min = MAXSHORT, fmin ;
+    float  max = MINSHORT, fmax ;
+    int    i ;
+
+    fmax = fmin = 1. ;
+
+    for ( i = 0 ; i < n ; i++ ) {
+	p = x[i] * scale ;
+
+	if ( p > max ) max = p ;
+	if ( p < min ) min = p ;
+
+	y[i] = (short)p ;
+    }
+
+    if ( max > MAXSHORT || min < MINSHORT ) {
+
+	if ( max > MAXSHORT )  fmax = MAXSHORT / max ;
+	if ( min < MINSHORT )  fmin = MINSHORT / min ;
+
+	if ( fmax < fmin ) return ( scale * fmax ) ;
+	else               return ( scale * fmin ) ;
+    }
+
+    return ( 1. ) ;
+}
+
+
+
+
+/*************************** convolution **********************************/
+
+/*
+Time-domain convolution. An input signal y of length n points is convolved
+with a window x of length m points (where m is assumed odd for symmetry).
+Return convolution signal z which must have allocated space of length n.
+
+Discrete convolution is defined:
+	z[i] = sum{j=-inf to inf}  x[i-j].y[j]          for i=-inf to inf
+But the signal y and window x are assumed to be zero for all time outside
+the given points so that:
+	z[i] = sum{j=-m/2 to m/2}  x[i-j].y[j]          for i=0,1,...,n-1
+
+Since the response of a linear filter to an arbitiary input signal is the
+convolution of the signal with the filter's impulse response, the window may
+be seen as the impulse response characterising the filter, and the return
+z is then the filter output in response to input y.
+
+Alternatively the convolution may be seen as a local averaging operation
+on y with weights obtained by time-reversing and shifting x.
+*/
+
+convolve_time( y, n, x, m, z )
+short  *y ;             /* input signal                                  */
+int     n ;             /* length of array y                             */
+float  *x ;             /* convolution window or filter impulse response */
+int     m ;             /* length of array x                             */
+float  *z ;             /* output signal of length n (same as input)     */
+{
+    register int  i, j, k, lim1, lim2 ;
+    register float sum ;
+
+    for ( i = 0 ; i < n ; i++ ) {
+
+	k = m - 1 ;
+	if ( ( lim1 = i - (m-1)/2 ) < 0 ) {
+	    k += lim1 ;
+	    lim1 = 0 ;
+	}
+	if ( ( lim2 = i + (m-1)/2 ) > n )
+	    lim2 = n - 1 ;
+
+	sum = 0 ;
+	for ( j = lim1 ; j <= lim2 ; j++, --k )
+	    sum += x[k] * y[j] ;
+
+	z[i] = sum ;
+    }
+}
+
+
+/*
+Frequency-domain convolution.
+*/
+
+convolve_freq( y, n, x, m, z )
+short  *y ;             /* input signal                                  */
+int     n ;             /* length of array y                             */
+float  *x ;             /* convolution window or filter impulse response */
+int     m ;             /* length of array x                             */
+float  *z ;             /* output signal of length n (same as input)     */
+{
+    int     i, j, n1 ;
+    float  *data, *respns, *ans ;
+
+    n1 = getpower( n + m ) ;    /* padded length of input signal */
+
+    data   = (float *)malloc( ( n1     + 1 ) * sizeof(float) ) ;
+    respns = (float *)malloc( ( n1     + 1 ) * sizeof(float) ) ;
+    ans    = (float *)malloc( ( n1 * 2 + 1 ) * sizeof(float) ) ;
+
+    /* copy and pad signal */
+
+    for ( i = 0 ; i < n ; i++ )
+	data[i] = y[i] ;
+    for (  ; i < n1 ; i++ )
+	data[i] = (float)0 ;
+
+    /* copy window into wrap-around order */
+
+    for ( i = m/2, j = 0 ; i < m ; i++, j++ )
+	respns[i] = x[j] ;
+    for ( i = 0 ; i < m/2 ; i++, j++ )
+	respns[i] = x[j] ;
+
+    /* Convolve and copy output */
+
+    convlv( data-1, n1, respns-1, m, 1, ans-1 ) ;
+
+    for ( i = 0 ; i < n ; i++ )
+	z[i] = ans[i] ;
+
+    free( data   ) ;
+    free( respns ) ;
+    free( ans    ) ;
+}
+
+
+/*
+Convolution of two functions. [See NR: pp407-413].
+Function 1 (the input signal) is in `data', length n, (n power of 2).
+Function 2 (the response function) is in `respns', length m, (m<=n and odd).
+(However respns must have n space available).
+The response file should be stored in respns in "wrap-around order", ie with
+its last half first and first half last in the array.
+Return is the first n numbers in `ans', (though ans must have 2*n space).
+Return convolution if isign==1, or deconvolution if isign==(-1).
+
+The data array should be padded with zeroes to a power of 2.
+The recommended amount of padding [NR: p411] is at least m/2, but need not be
+more than m.
+*/
+
+static float sqrarg;
+#define SQR(a) (sqrarg=(a),sqrarg*sqrarg)
+
+
+convlv( data, n, respns, m, isign, ans )
+float data[], respns[], ans[] ;
+int   n, m, isign ;
+{
+    int   i, no2 ;
+    float dum, mag2, *fftbuf ;
+
+    fftbuf = (float *)malloc( 2 * n * sizeof(float) ) ;
+
+    for (i=1;i<=(m-1)/2;i++)
+	respns[n+1-i]=respns[m+1-i];
+    for (i=(m+3)/2;i<=n-(m-1)/2;i++)
+	respns[i]=0.0;
+
+    twofft(data,respns,fftbuf,ans,n);
+    no2=n/2;
+    for (i=2;i<=n+2;i+=2) {
+	if (isign == 1) {
+	    ans[i-1]=(fftbuf[i-1]*(dum=ans[i-1])-fftbuf[i]*ans[i])/no2;
+	    ans[i]=(fftbuf[i]*dum+fftbuf[i-1]*ans[i])/no2;
+	} else if (isign == -1) {
+	    if ((mag2=SQR(ans[i-1])+SQR(ans[i])) == 0.0)
+		fprintf( stderr, "warning: deconvolving at response zero\n" ) ;
+	    ans[i-1]=(fftbuf[i-1]*(dum=ans[i-1])+fftbuf[i]*ans[i])/mag2/no2;
+	    ans[i]=(fftbuf[i]*dum-fftbuf[i-1]*ans[i])/mag2/no2;
+	}
+	else {
+	    fprintf( stderr, "No meaning for ISIGN in CONVLV\n" ) ;
+	    exit( 1 ) ;
+	}
+    }
+    ans[2]=ans[n+1];
+    realft(ans,no2,-1);
+
+    free( fftbuf ) ;
+}
+
+
+
+/************************ fft ********************************************/
+
+/*
+ In-place FFT/IFFT routine for real-valued data.
+ (Ref Numerical recipes, pp417).
+
+ Arguments:
+    data  = Input array of 2n floats,
+	      also output data array of n complex numbers.
+    n     = Number of data points, (must be a power of two).
+	      Input data is 2n real numbers.
+	      Output data is  n complex numbers.
+    isign = FFT when 1; IFFT when -1.
+
+ Each complex number occupies two consecutive locations: real and imag.
+ The output data is n real and imag parts which are the positive frequency
+ half of the symmetric Fourier transform.
+
+ Indexing conversion:
+
+ Both input and output data are indexed: 1,..,n.
+ where:       Input data is 2n real numbers.
+	      Output data is  n complex numbers, (ie 2n floats).
+ To convert to conventional indexing:    0,..,m-1
+ where:       Input data is m real numbers (eg. input framesize).
+	      Output data is m/2 complex numbers, (ie m floats).
+
+ allocated space for "data" of:
+
+	      (m+1)*sizeof(float).
+
+ call to routine "realft":
+
+	      realft( data-1, m/2, isign ) ;
+
+ for example via the define:
+
+#define fft(data,m,isign)  ( realft((float *)(data)-1, m>>1, isign) )
+
+ This works because the location (data-1) is never indexed in routine realft.
+ Output data will then be data[0] to data[m/2-1] complex numbers,
+ ie data[0] to data[m-1] floats, to be interpreted as m/2 (real,imag) pairs.
+
+ The first of the m/2 points of the magnitude spectrum is then:
+	      sqrt( sq( data[0] ) + sq( data[1] ) )
+
+
+ The results of the IFFT are not normalized by multplication by 1/N.
+ The user should multiply each returned element by 1/n.
+
+ Routine realft returns the first and last real components in data[1] and
+ data[2]. To make this correspond with the return from twofft, the mod below
+ sets data[2]=0.
+*/
+
+
+realft(data,n,isign)
+float data[];
+int n,isign;
+{
+	int i,i1,i2,i3,i4,n2p3;
+	float c1=0.5,c2,h1r,h1i,h2r,h2i;
+	double wr,wi,wpr,wpi,wtemp,theta;
+
+	theta=3.141592653589793/(double) n;
+	if (isign == 1) {
+		c2 = -0.5;
+		four1(data,n,1);
+	} else {
+		c2=0.5;
+		theta = -theta;
+	}
+	wtemp=sin(0.5*theta);
+	wpr = -2.0*wtemp*wtemp;
+	wpi=sin(theta);
+	wr=1.0+wpr;
+	wi=wpi;
+	n2p3=2*n+3;
+	for (i=2;i<=n/2;i++) {
+		i4=1+(i3=n2p3-(i2=1+(i1=i+i-1)));
+		h1r=c1*(data[i1]+data[i3]);
+		h1i=c1*(data[i2]-data[i4]);
+		h2r = -c2*(data[i2]+data[i4]);
+		h2i=c2*(data[i1]-data[i3]);
+		data[i1]=h1r+wr*h2r-wi*h2i;
+		data[i2]=h1i+wr*h2i+wi*h2r;
+		data[i3]=h1r-wr*h2r+wi*h2i;
+		data[i4] = -h1i+wr*h2i+wi*h2r;
+		wr=(wtemp=wr)*wpr-wi*wpi+wr;
+		wi=wi*wpr+wtemp*wpi+wi;
+	}
+	if (isign == 1) {
+		data[1] = (h1r=data[1])+data[2];
+		data[2] = h1r-data[2];
+	} else {
+		data[1]=c1*((h1r=data[1])+data[2]);
+		data[2]=c1*(h1r-data[2]);
+		four1(data,n,-1);
+	}
+}
+
+
+#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
+
+four1(data,nn,isign)
+float data[];
+int nn,isign;
+{
+	int n,mmax,m,j,istep,i;
+	double wtemp,wr,wpr,wpi,wi,theta;
+	float tempr,tempi;
+
+	n=nn << 1;
+	j=1;
+	for (i=1;i<n;i+=2) {
+		if (j > i) {
+			SWAP(data[j],data[i]);
+			SWAP(data[j+1],data[i+1]);
+		}
+		m=n >> 1;
+		while (m >= 2 && j > m) {
+			j -= m;
+			m >>= 1;
+		}
+		j += m;
+	}
+	mmax=2;
+	while (n > mmax) {
+		istep=2*mmax;
+		theta=6.28318530717959/(isign*mmax);
+		wtemp=sin(0.5*theta);
+		wpr = -2.0*wtemp*wtemp;
+		wpi=sin(theta);
+		wr=1.0;
+		wi=0.0;
+		for (m=1;m<mmax;m+=2) {
+			for (i=m;i<=n;i+=istep) {
+				j=i+mmax;
+				tempr=wr*data[j]-wi*data[j+1];
+				tempi=wr*data[j+1]+wi*data[j];
+				data[j]=data[i]-tempr;
+				data[j+1]=data[i+1]-tempi;
+				data[i] += tempr;
+				data[i+1] += tempi;
+			}
+			wr=(wtemp=wr)*wpr-wi*wpi+wr;
+			wi=wi*wpr+wtemp*wpi+wi;
+		}
+		mmax=istep;
+	}
+}
+
+
+twofft(data1,data2,fft1,fft2,n)
+float data1[],data2[],fft1[],fft2[];
+int n;
+{
+	int nn3,nn2,jj,j;
+	float rep,rem,aip,aim;
+
+	nn3=1+(nn2=2+n+n);
+	for (j=1,jj=2;j<=n;j++,jj+=2) {
+		fft1[jj-1]=data1[j];
+		fft1[jj]=data2[j];
+	}
+	four1(fft1,n,1);
+	fft2[1]=fft1[2];
+	fft1[2]=fft2[2]=0.0;
+	for (j=3;j<=n+1;j+=2) {
+		rep=0.5*(fft1[j]+fft1[nn2-j]);
+		rem=0.5*(fft1[j]-fft1[nn2-j]);
+		aip=0.5*(fft1[j+1]+fft1[nn3-j]);
+		aim=0.5*(fft1[j+1]-fft1[nn3-j]);
+		fft1[j]=rep;
+		fft1[j+1]=aim;
+		fft1[nn2-j]=rep;
+		fft1[nn3-j] = -aim;
+		fft2[j]=aip;
+		fft2[j+1] = -rem;
+		fft2[nn2-j]=aip;
+		fft2[nn3-j]=rem;
+	}
+}
+
+
+/*********************** windows *******************************************/
+
+/*
+Allocate space for and compute an n-point Hann or raised cosine window,
+returning array.
+*/
+
+float *raised_cosine( n )
+int  n ;
+{
+    float            *W ;
+    register int      i ;
+    register double   k ;
+
+    W = (float *)malloc( n * sizeof(float) ) ;
+
+    k = TWOPI/(double)(n-1);
+    for (i=0 ; i<n ; i++)
+	W[i] = 0.5 * ( 1.0 - cos(k*i) ) ;
+
+    return W ;
+}
+
+
+/*
+Allocate space for and compute an n-point Hamming window, returning array.
+*/
+
+float *hamming( n )
+int  n ;
+{
+    float            *W ;
+    register int      i ;
+    register double   k ;
+
+    W = (float *)malloc( n * sizeof(float) ) ;
+
+    k = TWOPI/(double)(n-1);
+    for (i=0 ; i<n ; i++)
+	W[i] = 0.54 - 0.46*cos(k*i) ;
+
+    return W ;
+}
+
+
+/*
+Allocate space for and compute a Gaussian window with given standard deviation
+`s' (samples) over a range of `n' standard deviations either side of a zero
+mean. The size of the returned window (returned via variable `num') will be:
+	2 * n * s  +  1   [points]
+(This is always odd as the window is symmetrical).
+*/
+
+float *gauss_window( s, n, num )
+float  s, n ;
+int   *num ;
+{
+    float  x, *y, var ;
+    int    i, points  ;
+
+    points = 2 * n * s + 1 ;
+    y = (float *)malloc( points * sizeof(float) ) ;
+
+    x   = ( - n * s ) ;
+    var = s * s ;
+    for ( i = 0 ; i < points ; i++, x++ )
+	y[i] = exp( -(double)( 0.5 * x * x / var ) ) ;
+
+    *num = points ;
+    return y ;
+}
+
+
+/*********************** frames *******************************************/
+
+/*
+Return a ptr to the n'th frame (numbered 1,2,3,...,n), with given
+framewidth (size) and frameshift (step). Return the null ptr if eof before
+the n'th frame. Frame number n=0 refers to the last frame before eof.
+Successive calls to getframe must request increasing frame numbers.
+
+Data (binary shorts) is buffered in an array of "blocksize" shorts,
+allocated internally, where:
+    blocksize = size + ( frames_per_block - 1 ) * step
+This means that the buffer can hold "frames_per_block" frames of the given
+size and step, and ensures that no frame crosses the boundary between
+successive buffers. At the buffer boundary, the overlap part
+(where overlap = size - step) of the last frame in the buffer must
+be shifted to the start of the buffer, and the step part of the next frame
+must be read so as to follow it in the buffer, completing the first frame of
+the next buffer.
+To protect the last frame (in the event that the next step part is actually
+the eof), the first frame of the next buffer must not corrupt the last frame
+of the previous buffer. This is ensured by arranging that:
+    size <= ( frames_per_block - 1 ) * step
+This constrains frames_per_block to be:
+    frames_per_block >= ( size / step ) + 1
+Therefore the minimum number of frames_per_block (when step = size, and there
+is no overlap) is 2.
+The actual value you give to frames_per_block is an efficiency issue, being
+a trade-off between space usage and the number of times a shift is necessary
+at a buffer boundary. A reasonable guess would be (see define below):
+    frames_per_block = ( size / step ) + 1 + FRAMES_PER_BLOCK
+
+An example of a shifting frame buffer, from frame a to b inclusive in steps
+of 1 frame, would be:
+
+    while ( ( buf = getframe( fp, a, size, step ) ) != (short *)0  && ( a<=b || b==0 ) ) {
+	process( buf, size ) ;
+	a++ ;
+    }
+    if ( a<=b && b>0 )
+	fprintf(stderr,"warning: not enough frames for request\n");
+
+*/
+
+#define FRAMES_PER_BLOCK    10
+
+short *getframe( fp, n, size, step )
+FILE *fp ;
+int   n, size, step ;
+{
+    static int    first = 1 ;
+    static short *buf, *endptr ;
+    static short *bptr = (short *) 0 ;
+    static int    blocksize, overlap, frames_per_block ;
+    static int    m = 0 ;       /* frame counter */
+    int           startsize, i ;
+
+    if ( n < m )                /* catches invalid calls and also case of n==0 */
+	return (short *) 0 ;
+
+    if ( first ) {
+	first = 0 ;
+	frames_per_block = ( size / step ) + 1 + FRAMES_PER_BLOCK ;
+	blocksize = size + ( frames_per_block - 1 ) * step ;
+	overlap   = size - step ;
+	bptr      = buf = (short *)malloc( blocksize * sizeof(short) ) ;
+	endptr    = buf + blocksize ;
+
+	if ( n > 0 ) {
+
+	    /* seek the n'th frame in blocks of blocksize. */
+
+	    startsize = ( n - 1 ) * step ;
+	    for ( i = blocksize ; i < startsize ; i += blocksize )
+		if ( fread( buf, sizeof(short), blocksize, fp ) < blocksize )
+		    return (short *) 0 ;
+	    if ( ( startsize -= ( i - blocksize ) ) > 0 )
+		if ( fread( buf, sizeof(short), startsize, fp ) < startsize )
+		    return (short *) 0 ;
+
+	    if ( ( fread( bptr, sizeof(short), size, fp ) ) < size )
+		return (short *) 0 ;
+	    m = n ;
+	}
+	else {
+
+	    /* seek the last frame in blocks of blocksize */
+
+	    if ( fread( buf, sizeof(short), size, fp ) < size )
+		return (short *) 0 ;
+	    startsize = blocksize - size ;
+	    for ( m = 1 ; ( i = fread( buf+size, sizeof(short), startsize, fp ) ) == startsize ; m += frames_per_block - 1 ) {
+		bptr = endptr-size ;
+		while ( bptr < endptr )
+		    *buf++ = *bptr++ ;
+		buf -= size ;
+	    }
+	    bptr = buf + ( i / step) * step ;
+	    m += i / step ;
+	}
+	return ( bptr ) ;
+    }
+
+    for (  ; m < n || n == 0 ; m++ ) {
+
+	if ( bptr + size >= endptr ) {  /* shift last overlap to buf start */
+	    while ( bptr < endptr )
+		*buf++ = *bptr++ ;
+	    buf -= overlap ;
+	    bptr = buf - step ;
+	}
+
+	if ( ( fread( bptr+size, sizeof(short), step, fp ) ) < step ) {
+	    if ( n == 0 ) {
+		if ( bptr < buf ) return ( endptr - size ) ;
+		else              return ( bptr          ) ;
+	    }
+	    return (short *) 0 ;
+	}
+	bptr += step ;
+    }
+    return ( bptr ) ;
+}
+
+
+/*************************************************************************/
+
+/*
+Seek past n frames in blocks of blocksize.
+Frames have width=size and shift=step.
+When step == size, the seek reads ( n * size ) shorts from the i/p stream.
+When step < size,  the seek reads ( size + ( n - 1 ) * step ) shorts.
+Return 1, or otherwise 0 for an improper seek (insufficient data in stream).
+*/
+
+seekframes( fp, n, size, step )
+FILE *fp ;
+int   n, size, step ;
+{
+    static short *buf ;
+    static int    first = 1 ;
+    static int    blocksize, frames_per_block ;
+    int           startsize = size + ( n - 1 ) * step ;
+    int           i ;
+
+    if ( first ) {
+	first = 0 ;
+	frames_per_block = ( size / step ) + 1 + FRAMES_PER_BLOCK ;
+	blocksize = size + ( frames_per_block - 1 ) * step ;
+	buf = (short *)malloc( blocksize * sizeof(short) ) ;
+    }
+    for ( i = blocksize ; i < startsize ; i += blocksize )
+	if ( fread( buf, sizeof(short), blocksize, fp ) < blocksize )
+	    return 0 ;
+    if ( (startsize -= (i - blocksize)) > 0 )
+	if ( fread( buf, sizeof(short), startsize, fp ) < startsize )
+	    return 0 ;
+
+    return 1 ;
+}
+
+/*************************************************************************/
+
+/*
+Seek past n bytes from current position in stream.
+Return 1, or otherwise 0 for an improper seek (insufficient data in stream).
+*/
+
+seekbytes( fp, n )
+FILE  *fp ;
+int    n  ;
+{
+    static char  *buf ;
+    static int    first = 1 ;
+
+    if ( n > 0 ) {
+	if ( first ) {
+	    first = 0 ;
+	    buf = (char *)malloc( n ) ;
+	}
+
+	if ( fread( buf, 1, n, fp ) < n )
+	    return 0 ;
+    }
+    return 1 ;
+}
+
+
+
+/*********************** normalizing **************************************/
+
+/*
+Normalize the n-array y so that the sum of the points (ie the area) is unity.
+*/
+
+normalize_area( y, n )
+float *y ;
+int    n ;
+{
+    float  sum = 0 ;
+    int    i ;
+
+    for ( i=0 ; i < n ; i++ )
+	sum += y[i] ;
+    for ( i=0 ; i < n ; i++ )
+	y[i] /= sum ;
+}
+
+
+/*
+Normalize the n-array y so that the range of y[i] is [0,1].
+*/
+
+normalize_range( y, n )
+float *y ;
+int    n ;
+{
+    int   i ;
+    float max = ( -256000. ) ;
+    float min =    256000.   ;
+
+    for ( i = 0 ; i < n ; i++ ) {       /* find max and min */
+	if ( y[i] > max ) max = y[i] ;
+	if ( y[i] < min ) min = y[i] ;
+    }
+
+    for ( i = 0 ; i < n ; i++ )
+	y[i] = ( y[i] - min ) / ( max - min ) ;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/sigproc.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,45 @@
+
+#define PI              3.14159265
+#define TWOPI           6.2831853
+
+#define MAXSHORT           32767.
+#define MINSHORT        ( -32767. )
+
+#define log2(x)         (log((double)x)/log(2.0))
+
+typedef struct {
+    float real;
+    float imag;
+} complex;
+
+#define sq(x)           ((x)*(x))
+#define Re(C)           (C)->real   /* cartesian form */
+#define Im(C)           (C)->imag
+
+
+/*
+  V is m floats interpreted as m/2 complex numbers: (real,imag).
+  mag: overwrite first m/2 floats with mod of m/2 complex numbers.
+  phase: overwrite first m/2 floats with arg of m/2 complex numbers.
+  fft: overwrite m floats with m/2 complex numbers (Fourier spectrum).
+*/
+
+#define mag(V,m)        Mod( (complex *)V, m>>1 )
+#define phase(V,m)      Arg( (complex *)V, m>>1 )
+#define fft(V,m,i)      realft( (float *)(V)-1, m>>1, i )
+
+
+float mod();
+float arg();
+
+
+int   ispower();
+int   getpower();
+
+float ftos() ;
+
+float *raised_cosine() ;
+float *hamming()  ;
+float *gauss_window() ;
+
+short *getframe() ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/smooth.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,221 @@
+/*
+  smooth.c      Low-pass filter by windowing in the time or frequency domain.
+  --------
+
+In the time domain the input is convolved with a unit area Gaussian window.
+In the frequency domain the spectrum is multiplied by a Gaussian mask which
+zeroes higher frequency components. The transform between domains uses the FFT.
+
+One parameter controls the amount of smoothing. This parameter controls the
+size of the window.
+
+Caveats for the frequency-domain approach are descibed in NR p436 (such as
+the damped ringing effect which results when when sharp edges are smoothed).
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+#include "sigproc.h"
+
+char applic[]     = "Data smoothing by convolution with Gaussian window." ;
+
+static char *helpstr, *debugstr, *sampstr, *lenstr, *varstr, *domstr  ;
+static char *ranstr,  *typestr,  *sizestr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                  , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                      , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "                           , VAL     },
+    {   "length"    ,   "max"       ,  &lenstr      ,   "Size of input."                        , VAL     },
+    {   "variance"  ,   "20"        ,  &varstr      ,   "Variance of Gaussian window"           , VAL     },
+    {   "range"     ,   "4"         ,  &ranstr      ,   "Range in standard deviations about mean", VAL     },
+    {   "domain"    ,   "time"      ,  &domstr      ,   "Convolve in time or frequency domain"  , VAL     },
+    {   "type"      ,   "short"     ,  &typestr     ,   "Data type input and output"            , VAL     },
+    {   "SIZE"      ,   "262144"    ,  &sizestr     ,   "buffer size (s, ms, samples)"          , SVAL    },
+   ( char * ) 0 } ;
+
+
+int     samplerate  ;
+int     length      ;
+
+float  *window ;
+int     points ;
+
+short  *buf1   ;
+float  *buf2   ;
+float  *out    ;
+FILE   *fp     ;
+
+
+
+main (argc, argv)
+int     argc;
+char  **argv;
+{
+    int   maxlen, i ;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    samplerate = to_Hz( sampstr ) ;
+
+    if ( ismax( lenstr ) )  maxlen = to_p( sizestr, samplerate ) ;
+    else                    maxlen = to_p( lenstr,  samplerate ) ;
+
+    out    = (float *)malloc( maxlen * sizeof(float) ) ;
+    window = gauss_window( to_p( sqrt_units( varstr ), samplerate ), atof( ranstr ), &points ) ;
+    normalize_area( window, points ) ;
+
+    if ( isstr( typestr, "short" ) ) {
+	buf1 = (short *)malloc( maxlen * sizeof(short) ) ;
+	length = fread( buf1, sizeof(short), maxlen, fp ) ;
+    }
+    else if ( isstr( typestr, "float" ) ) {
+	buf2 = (float *)malloc( maxlen * sizeof(float) ) ;
+	length = fread( buf2, sizeof(float), maxlen, fp ) ;
+    }
+    else {
+	fprintf( stderr,"smooth: unknown data type [%s]\n", typestr ) ;
+	exit( 1 ) ;
+    }
+
+
+    if ( length < maxlen ) {
+	if ( length == 0 ) {
+	    fprintf( stderr,"smooth: missing input data\n");
+	    exit( 1 ) ;
+	}
+	if ( !ismax( lenstr ) )
+	    fprintf( stderr,"smooth: warning: %d samples found\n", length ) ;
+    }
+    fclose( fp ) ;
+
+    if ( points <= 0 ) {
+	fprintf( stderr,"smooth: window size = %d\n", points ) ;
+	exit( 1 ) ;
+    }
+
+    if ( isstr( typestr, "short" ) ) {
+
+	if ( points == 1 )  /* no smoothing */
+	    fwrite( buf1, sizeof(short), length, stdout ) ;
+
+	else if ( iststr( domstr, "time" ) )
+	    convolve_time( buf1, length, window, points, out ) ;
+
+	else if ( iststr( domstr, "frequency" ) )
+	    convolve_freq( buf1, length, window, points, out ) ;
+
+	else {
+	    fprintf( stderr,"smooth: unknown domain [%s]\n", domstr ) ;
+	    exit( 1 ) ;
+	}
+
+	ftos( out, buf1, length, 1. ) ;
+	fwrite( buf1, sizeof(short), length, stdout ) ;
+    }
+
+    else {
+
+	if ( points == 1 )  /* no smoothing */
+	    fwrite( buf2, sizeof(float), length, stdout ) ;
+
+	else if ( iststr( domstr, "time" ) )
+	    convolve_time2( buf2, length, window, points, out ) ;
+
+	else if ( iststr( domstr, "frequency" ) )
+	    convolve_freq2( buf2, length, window, points, out ) ;
+
+	else {
+	    fprintf( stderr,"smooth: unknown domain [%s]\n", domstr ) ;
+	    exit( 1 ) ;
+	}
+
+	fwrite( out, sizeof(float), length, stdout ) ;
+    }
+
+
+}
+
+
+convolve_time2( y, n, x, m, z )
+float  *y ;             /* input signal                                  */
+int     n ;             /* length of array y                             */
+float  *x ;             /* convolution window or filter impulse response */
+int     m ;             /* length of array x                             */
+float  *z ;             /* output signal of length n (same as input)     */
+{
+    register int  i, j, k, lim1, lim2 ;
+    register float sum ;
+
+    for ( i = 0 ; i < n ; i++ ) {
+
+	k = m - 1 ;
+	if ( ( lim1 = i - (m-1)/2 ) < 0 ) {
+	    k += lim1 ;
+	    lim1 = 0 ;
+	}
+	if ( ( lim2 = i + (m-1)/2 ) > n )
+	    lim2 = n - 1 ;
+
+	sum = 0 ;
+	for ( j = lim1 ; j <= lim2 ; j++, --k )
+	    sum += x[k] * y[j] ;
+
+	z[i] = sum ;
+    }
+}
+
+
+/*
+Frequency-domain convolution.
+*/
+
+convolve_freq2( y, n, x, m, z )
+float  *y ;             /* input signal                                  */
+int     n ;             /* length of array y                             */
+float  *x ;             /* convolution window or filter impulse response */
+int     m ;             /* length of array x                             */
+float  *z ;             /* output signal of length n (same as input)     */
+{
+    int     i, j, n1 ;
+    float  *data, *respns, *ans ;
+
+    n1 = getpower( n + m ) ;    /* padded length of input signal */
+
+    data   = (float *)malloc( ( n1     + 1 ) * sizeof(float) ) ;
+    respns = (float *)malloc( ( n1     + 1 ) * sizeof(float) ) ;
+    ans    = (float *)malloc( ( n1 * 2 + 1 ) * sizeof(float) ) ;
+
+    /* copy and pad signal */
+
+    for ( i = 0 ; i < n ; i++ )
+	data[i] = y[i] ;
+    for (  ; i < n1 ; i++ )
+	data[i] = (float)0 ;
+
+    /* copy window into wrap-around order */
+
+    for ( i = m/2, j = 0 ; i < m ; i++, j++ )
+	respns[i] = x[j] ;
+    for ( i = 0 ; i < m/2 ; i++, j++ )
+	respns[i] = x[j] ;
+
+    /* Convolve and copy output */
+
+    convlv( data-1, n1, respns-1, m, 1, ans-1 ) ;
+
+    for ( i = 0 ; i < n ; i++ )
+	z[i] = ans[i] ;
+
+    free( data   ) ;
+    free( respns ) ;
+    free( ans    ) ;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/sp_weights.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,235 @@
+/*************************************************************************
+ sp_weights.c   Map auditory image onto spiral sector-weights contour.
+--------------
+
+    Read auditory image frames (gensai or genspl with output set) from a
+    file or the stdin. Input must have a pipes header, (for frame dimensions).
+
+    Note, you can use either gensai or genspl output, but remember that their
+    default options are different, (particularly pwidth, nwidth, and dencf).
+
+    For each frame, (of frameheight*framewidth binary shorts),
+    write a sector-weights contour, (of m binary shorts), on the stdout.
+
+    Arguments:
+	-m      The number of sectors (default SECTORS).
+	-fA-B   Process the A'th to B'th frame inclusive,
+		(or the A'th to the eof if b=='e'), (default -o1-e).
+	-fA     Process just the A'th frame.
+
+*************************************************************************/
+
+#include <stdio.h>
+#include <math.h>
+#include "header.h"
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[] = "Map auditory image frames onto spiral sector-weights contours.\n           (Input and output in binary shorts)." ;
+
+static char *helpstr, *debugstr, *infostr, *fstr, *mstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                        , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"            , DEBUG   },
+    {   "info"      ,   "off"       ,  &infostr     ,   "print frame size information", DEBUG   },
+    {   "frames"    ,   "1-max"     ,  &fstr        ,   "select frames inclusively"   , VAL     },
+    {   "nsectors"  ,   "64"        ,  &mstr        ,   "number of sectors"           , SVAL    },
+   ( char * ) 0 } ;
+
+
+#define log2(x)     (log((double)x)/log(2.0))
+#define round(x)    ((int)(x+0.5))
+
+int     frameheight, framewidth ;   /* Parameters read from header */
+int     frames;
+double  orig_spd ;
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE   *fp ;
+    char   *header, *val1, *val2 ;
+    char   *headeropt, *versionstr;
+    int     i, a, b;
+    int     m ;                 /* Number of sectors around spiral      */
+    int     framebytes;         /* Number of bytes in each frame        */
+    short  *frame;              /* Each frame                           */
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    m = atoi( mstr ) ;
+
+    /* parse bounds on number of frames */
+
+    if ( getvals( fstr, &val1, &val2, "-" ) == BADVAL ) {
+	fprintf(stderr,"loudness: bad frame selector [%s]\n", fstr ) ;
+	exit( 1 ) ;
+    }
+    a = atoi( val1 ) ;
+    if ( isempty( val2 ) )    b = a ;
+    else if ( ismax( val2 ) ) b = 0 ;
+    else                      b = atoi( val2 ) ;
+
+    if (b<a && b>0) fprintf(stderr,"sp_weights warning: bad frame specifiers\n");
+
+
+
+    /* Read header to find dimensions of auditory image */
+
+    if ((header = ReadHeader(fp)) == (char *) 0 ) {
+	fprintf(stderr,"sp_weights: header not found\n");
+	exit(1);
+    }
+
+    if ( (versionstr = HeaderString( header, "Version" )) == (char *)0 ) {
+	fprintf(stderr,"sp_weights: model version-number not found in header\n");
+	exit(1);
+    }
+
+    if ( (headeropt = HeaderString( header, "frameheight" )) == (char *)0) {
+	fprintf(stderr,"sp_weights: frameheight not found in header\n");
+	exit(1);
+    }
+    else  frameheight = atoi( headeropt );
+
+    if ( (headeropt = HeaderString( header, "framewidth" )) == (char *)0) {
+	fprintf(stderr,"sp_weights: framewidth not found in header\n");
+	exit(1);
+    }
+    else  framewidth = atoi( headeropt );
+
+    if ( (headeropt = HeaderString( header, "frames" )) == (char *)0) {
+	fprintf(stderr,"sp_weights: frames not found in header\n");
+	exit(1);
+    }
+    else  frames = atoi( headeropt );
+
+    if ( (headeropt = HeaderString( header, "orig_spd" )) == (char *)0) {
+	fprintf(stderr,"sp_weights: orig_spd not found in header\n");
+	exit(1);
+    }
+    else  orig_spd = atof( headeropt );
+
+    if ( ison( debugstr ) ) {
+	printf("a=%d b=%d m=%d \n", a, b, m );
+	printf("frames=%d  frameheight=%d  framewidth=%d orig_spd=%.2f\n", frames,frameheight,framewidth,orig_spd ) ;
+	exit(0);
+    }
+
+    if ( ison( infostr ) || a==0 ) {
+	printf("sp_weights input: %s", versionstr ) ;
+	printf("                  frames=%d  frameheight=%d  framewidth=%d\n", frames,frameheight,framewidth ) ;
+	exit(0);
+    }
+
+    if (frames<=0) {
+	if (frames==0)  fprintf(stderr,"sp_weights: zero frames input\n");
+	if (frames<0)   fprintf(stderr,"sp_weights: garbled number of frames, (start set too big?)\n");
+	exit(1);
+    }
+
+    if (a>frames || b>frames)
+	fprintf(stderr,"sp_weights warning: bad frame specifiers\n");
+
+    framebytes = frameheight * framewidth * sizeof(short) ;
+
+    /* Allocate space for an auditory image frame */
+
+    if (( frame = (short *)malloc( framebytes )) == NULL)
+	    fprintf(stderr,"sp_weights: malloc out of space\n");
+
+    /* Seek past a-1 frames, then read the next b-a+1 frames, or all    */
+    /* remaining frames if b==0.                                        */
+
+    for (i=1 ; i<a  && fread(frame,framebytes,1,fp) ; i++)
+	;
+    if (b > 0)
+	for (  ; i<=b && fread(frame,framebytes,1,fp) ; i++)
+	    write_weights(frame,m);
+    else
+	while ( fread(frame,framebytes,1,fp) )
+	    write_weights(frame,m);
+
+    fclose(fp);
+}
+
+
+
+/***************************************************************************
+  Spoke sector weight routines  (originally as src/src8/spoke.c)
+
+  Write m sector weights as binary shorts on the stdout.
+***************************************************************************/
+
+write_weights(frame,m)
+short *frame;
+int    m;       /* number of sectors around the spiral plane */
+{
+    static  short *sector;
+    static  int   *logtime;
+    int     i, k, t, col;
+    double  sum;
+    static  int    first=1;     /* flag for first-call of this routine */
+
+    /* Allocate space (first-time call only). */
+    if (first) {
+	first = 0;
+	/* Allocate space and compute base-2 log time for spoke detection */
+	if ( (sector  = (short *)malloc( m*sizeof(short) ) ) == NULL)
+	    fprintf(stderr,"sp_weights: malloc out of space\n");
+	if ( (logtime = (int *)malloc( framewidth*sizeof(int) ) ) == NULL )
+	    fprintf(stderr,"sp_weights: malloc out of space\n");
+	gen_logtime(logtime,m);
+    }
+    /* clear sector bins */
+    for (i=0 ; i<m ; i++)
+	sector[i]=0;
+    /* for each time point along the SAI frame (with time origin on right) */
+    /* (exclude time-origin bin to prevent overweighting by this sample)   */
+    for (t=round(pow(2.0,orig_spd)) ; t<framewidth ; t++)  {
+	col = (framewidth-1)-t;
+	/* sum frame column (ie across all frequency channels) */
+	for (i=0, k=0, sum=0 ; i<frameheight ; i++, k+=framewidth)
+	    sum += frame[col+k];
+	/* Normalize (divide by frameheight) for average magnitude */
+	sum /= frameheight;
+	/* Accumulate sum in log-time sector bin */
+	sector[logtime[t]] += sum;
+    }
+    /* write total sum activity in spokes around the spiral from the datum */
+    /* line in an anticlockwise direction. (ie in "natural order").        */
+    for (i=0 ; i<m ; i++)
+/*        printf("%d\n", sector[i]);    */
+	fwrite(&sector[i], sizeof(short), 1, stdout);
+}
+
+/****************************************************************************
+  List the sector numbers, 0,1,...,m-1, which correspond to each time
+  t=1,2,...,framewidth-1. The return array, "logtime", maps time index onto
+  a spiral sector number.
+  (Note that since the sector width increases with radius, there is an
+  increasing number of adjacent frame indices within the sector bin).
+****************************************************************************/
+gen_logtime(logtime, m)
+int  *logtime;
+int   m;
+{
+    int     t;
+    double  theta, fptr, iptr;
+
+    logtime[0] = 0; /* special case for log(0) */
+    for (t=1 ; t<framewidth ; t++)  {
+	theta = log2(t) - orig_spd;
+	fptr = modf(theta,&iptr);       /* find fractional part of log time */
+	/* scale up to given resolution, and round */
+	logtime[t] = (int)(0.5+(fptr*m));
+    }
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/stats.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,401 @@
+/*
+  stats.c      calculate some statistics (min, max, mean etc.)
+  -------
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[]     = "print statistics of input files" ;
+
+static char *helpstr, *debugstr, *typestr, *statstr ;
+static char *sampstr, *frstr,    *widstr,  *sizestr ;
+static char *linestr, *precstr,  *fieldstr          ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                          , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"              , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "                   , VAL     },
+    {   "frame"     ,   "1"         ,  &frstr       ,   "select frames inclusively"     , VAL     },
+    {   "width"     ,   "max"       ,  &widstr      ,   "frame width"                   , VAL     },
+    {   "type"      ,   "short"     ,  &typestr     ,   "data type"                     , VAL     },
+    {   "stat"      ,   "mean"      ,  &statstr     ,   "statistic list (comma separated)"      , VAL     },
+    {   "line"      ,   "off"       ,  &linestr     ,   "force ascii output"            , SETFLAG },
+    {   "fieldwidth",   "10"        ,  &fieldstr    ,   "field width for ascii printing", SVAL    },
+    {   "precision" ,   "3"         ,  &precstr     ,   "precision for ascii printing"  , SVAL    },
+    {   "SIZE"      ,   "262144p"   ,  &sizestr     ,   "buffer size (s, ms, or p)"     , SVAL    },
+   ( char * ) 0 } ;
+
+
+typedef float (*PF)() ; /* pointer-to-function type returning float */
+
+typedef struct {        /* a struct to hold both function name and pointer */
+    char  *name ;       /* string name of function */
+    PF     func ;       /* pointer to function     */
+    char  *help ;       /* explanation of use      */
+} Func ;
+
+
+float   num(),      sum(),      sumabs(),   sumsq(),    mean()      ;
+float   rms(),      variance(), stddev(),   min(),      max()       ;
+float   absmax(),   absrange(), pc()                                            ;
+
+float   call_by_name() ;
+
+Func  statistic[] = {
+    { "n"         ,     num         ,    "sample size (ie. frame width)"                        } ,
+    { "sum"       ,     sum         ,    "area"                                                 } ,
+    { "sa"        ,     sumabs      ,    "sum of absolute values"                               } ,
+    { "ss"        ,     sumsq       ,    "sum of squares"                                       } ,
+    { "mean"      ,     mean        ,    "sum/n"                                                } ,
+    { "rms"       ,     rms         ,    "root mean square: square root of ss/n"                } ,
+    { "variance"  ,     variance    ,    "computed with n-1 degrees of freedom"                 } ,
+    { "stddev"    ,     stddev      ,    "standard deviation: square root of variance"          } ,
+    { "min"       ,     min         ,    "minimum value"                                        } ,
+    { "max"       ,     max         ,    "maximum value"                                        } ,
+    { "absmax"    ,     absmax      ,    "maximum absolute value, ie. max( |max|, |min| )"      } ,
+    { "range"     ,     absrange    ,    "max-min"                                              } ,
+    { "pc_1of2"   ,     pc          ,    "percentage correct, ie. greater first of each pair"   } ,
+   ( char * ) 0 } ;
+
+
+int    samplerate ;
+int    bytes      ;
+int    type       ;     /* datatype index */
+int    nstat      ;     /* number of statistics required */
+int    width      ;
+int    SIZE       ;
+int    lineout    ;     /* flag for forcing ascii output */
+
+float *buf ;            /* args to every stat function */
+int    n   ;
+
+main (argc, argv)
+int    argc;
+char **argv;
+{
+    FILE   *fp   ;
+    char  **list ;
+    float   y    ;
+    int     i, j, k, a, b, helpstats() ;
+
+    i = getopts( option, argc, argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts1( helpstr, argv[0], applic, option, helpstats ) ;
+
+    if ( ( type = typeindex( typestr ) ) < 0 ) {
+	fprintf( stderr, "stats: bad type [%s]\n", typestr ) ;
+	exit( 1 ) ;
+    }
+    bytes = typebytes( type ) ;
+
+    if ( selector( frstr, &a, &b ) == 0 ) {
+	fprintf(stderr,"stats: bad frame selector [%s]\n", frstr ) ;
+	exit( 1 ) ;
+    }
+
+    PRECISION  = atoi( precstr ) ;
+    FIELDWIDTH = atoi( fieldstr ) ;
+    lineout    = ison( linestr ) ;
+    samplerate = to_Hz( sampstr, 0) ;
+    SIZE       = to_p( sizestr, samplerate ) ;
+    if ( ismax( widstr ) ) width = (-1) ;
+    else                   width = to_p( widstr, samplerate ) ;
+
+    nstat  = flistsize( statistic ) ;   /* max number of statistics */
+    list   = (char **)malloc( nstat * sizeof( char *) ) ;
+    if ( ( nstat  = tokens( statstr, list, nstat, ',' ) ) == 0 ) {
+	fprintf(stderr,"stats: incorrect stat list\n" ) ;
+	exit( 1 ) ;
+    }
+
+    do {
+
+	if ( i == 0 ) fp = stdin ;
+	else if ( ( fp = fopen( argv[argc-i], "r" ) ) == (FILE *)0 ) {
+	    fprintf( stderr,"stats: can't open %s\n", argv[argc-i] ) ;
+	    exit( 1 ) ;
+	}
+
+	if ( width > 0 ) buf = (float *)malloc( width * sizeof(float) ) ;
+	else             buf = (float *)malloc( SIZE  * sizeof(float) ) ;
+
+	if ( width > 0 && a > 1 )
+	    if ( seekstart( (a-1)*width, bytes, fp ) < (a-1)*width )
+		fprintf( stderr, "stats warning: insufficient input\n" ) ;
+
+	for ( j = a ; ( j <= b || b == 0 ) && ( n = Readitem( buf, type, width, fp, SIZE ) ) > 0 ; j++ ) {
+
+	    for ( k = 0 ; k < nstat ; k++ ) {
+
+		y = call_by_name( list[k], statistic ) ;
+
+		if ( lineout )
+		    printf( "%*.*f  ", FIELDWIDTH, PRECISION, y ) ;
+		else
+		    writeitem( &y, type, 1, stdout ) ;
+	    }
+	}
+
+	free( buf ) ;
+	fclose( fp ) ;
+	if ( lineout ) printf( "\n" ) ;
+
+    } while ( --i > 0 ) ;
+
+}
+
+
+/*
+Return the number of structs in the null-terminated array of Func structs.
+*/
+
+flistsize( flist )
+Func *flist ;
+{
+    int  i ;
+
+    for ( i = 0 ; flist[i].name != (char *)0 ; i++ )
+	;
+    return i ;
+}
+
+
+/*
+Call a function given its string name. The function's address is found against
+the matching name in the given `flist'.
+The function returns an float.
+Rather than return at the first matching name, search all the list for names
+which match the (possibly abbreviated) string name. Print a warning if
+ambiguity found.
+*/
+
+float call_by_name( str, flist )
+char  *str   ;
+Func  *flist ;
+{
+    int  i, j = (-1) ;
+
+    for ( i=0 ; flist[i].name != (char *)0 ; i++ ) {
+	if ( iststr( str, flist[i].name ) ) {
+	    if ( j >= 0 )
+		fprintf( stderr,"warning: ambiguous stat names (%s and %s)\n", flist[j].name, flist[i].name ) ;
+	    j = i ;
+	}
+    }
+    return ( (*flist[j].func)() ) ;
+}
+
+
+/*
+Read items of given type up to max of SIZE items (when n=-1).
+Return n or 0 if eof.
+*/
+
+Readitem( y, type, n, fp, SIZE )
+float  *y    ;
+int     type ;
+int     n    ;
+FILE   *fp   ;
+int     SIZE ;
+{
+    if ( n == (-1) ) {
+	for ( n = 0 ; n < SIZE && readitem( &y[n], type, 1, fp ) ; n++ )
+	    ;
+	if ( n == SIZE )
+	    fprintf( stderr, "stats warning: buffer full\n" ) ;
+    }
+    else if ( readitem( y, type, n, fp ) == 0 ) return 0 ;
+
+    return n ;
+}
+
+
+/*
+Print help on request
+*/
+
+helpstats()
+{
+    int  i ;
+
+    fprintf(stderr,"\nstatistics:       \n");
+
+    for ( i = 0 ; statistic[i].name != (char *)0 ; i++ )
+	fprintf(stderr,"            %-10s  %s\n", statistic[i].name, statistic[i].help ) ;
+
+    exit( 1 ) ;
+}
+
+
+/*************************** functions ************************************/
+/* The functions all take two args: char *buf; int n;                     */
+/* These are declared externally.                                         */
+
+
+float num()
+{
+    return n ;
+}
+
+
+float sum()
+{
+    int   i ;
+    float sum = 0 ;
+
+    for ( i = 0 ; i < n ; i++ )
+	sum += buf[i] ;
+
+    return ( sum ) ;
+}
+
+
+float sumabs()
+{
+    int   i ;
+    float sum = 0 ;
+
+    for ( i = 0 ; i < n ; i++ )
+	sum += fabs( (double)buf[i] ) ;
+
+    return ( sum ) ;
+}
+
+
+float sumsq()
+{
+    int   i ;
+    float sumsq = 0 ;
+
+    for ( i = 0 ; i < n ; i++ )
+	sumsq += ( buf[i] * buf[i] ) ;
+
+    return ( sumsq ) ;
+}
+
+
+float mean()
+{
+    int   i ;
+    float sum = 0 ;
+
+    for ( i = 0 ; i < n ; i++ )
+	sum += buf[i] ;
+
+    return ( sum / n ) ;
+}
+
+
+float rms()
+{
+    int   i ;
+    float sumsq = 0 ;
+
+    for ( i = 0 ; i < n ; i++ )
+	sumsq += ( buf[i] * buf[i] ) ;
+
+    return ( sqrt( sumsq / n ) ) ;
+}
+
+
+float variance()    /* computed with n-1 degrees of freedom */
+{
+    int   i ;
+    float sum = 0, sumsq = 0 ;
+
+    for ( i = 0 ; i < n ; i++ ) {
+	sum   += buf[i]   ;
+	sumsq += ( buf[i] * buf[i] ) ;
+    }
+
+    return ( ( sumsq - sum*sum/n ) / ( n - 1 ) ) ;  /* replace n-1 by n for n degrees of freedom */
+}
+
+
+float stddev()    /* computed with n-1 degrees of freedom */
+{
+    return ( sqrt( variance( buf, n ) ) ) ;
+}
+
+
+float min()
+{
+    int   i ;
+    float min = 99999999999. ;
+
+    for ( i = 0 ; i < n ; i++ )
+	if ( buf[i] < min ) min = buf[i] ;
+    return ( min ) ;
+}
+
+
+float max()
+{
+    int   i ;
+    float max = ( -99999999999. ) ;
+
+    for ( i = 0 ; i < n ; i++ )
+	if ( buf[i] > max ) max = buf[i] ;
+
+    return ( max ) ;
+}
+
+
+float absmax()
+{
+    int   i ;
+    float min =    99999999999.   ;
+    float max = ( -99999999999. ) ;
+
+    for ( i = 0 ; i < n ; i++ ) {
+	if ( buf[i] < min ) min = buf[i] ;
+	if ( buf[i] > max ) max = buf[i] ;
+    }
+
+    if ( ( max = fabs( (double)max ) ) < ( min = fabs( (double)min ) ) )
+	max = min ;
+
+    return ( max ) ;
+}
+
+
+float absrange()
+{
+    int   i ;
+    float min =    99999999999.   ;
+    float max = ( -99999999999. ) ;
+
+    for ( i = 0 ; i < n ; i++ ) {
+	if ( buf[i] < min ) min = buf[i] ;
+	if ( buf[i] > max ) max = buf[i] ;
+    }
+
+    return ( max - min ) ;
+}
+
+
+/*
+The buf contains n/2 pairs of numbers. Calculate how many of each pair have
+the first number greater than the last, and return this as a "percentage
+correct".
+*/
+
+float pc()
+{
+    int   i ;
+    float p = 0 ;
+
+    for ( i = 0 ; i < n ; i+=2 )
+	if ( buf[i] > buf[i+1] )
+	    p++ ;
+
+    return ( ( p / (n/2) ) * 100 ) ;
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/step.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,74 @@
+/*
+  step.c    generate a step up or down.
+  ------
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+char applic[]  = "generate a step waveform. " ;
+char usage[]   = "step [options]" ;
+
+static char *helpstr, *debugstr, *sampstr, *astr,  *dstr, *typestr ;
+static char *shiftstr, *polstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                              , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                  , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "                       , VAL     },
+    {   "amplitude" ,   "1"         ,  &astr        ,   "step height"                       , VAL     },
+    {   "shift"     ,   "10ms"      ,  &shiftstr    ,   "position of step relative to start", VAL     },
+    {   "polarity"  ,   "up"        ,  &polstr      ,   "step up or down"                   , VAL     },
+    {   "duration"  ,   "500ms"     ,  &dstr        ,   "duration of waveform"              , VAL     },
+    {   "type"      ,   "short"     ,  &typestr     ,   "output datatype"                   , VAL     },
+   ( char * ) 0 } ;
+
+
+int     samplerate ;
+float   amplitude  ;
+int     duration   ;
+int     shift      ;
+int     type       ;
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    int   i ;
+    float y0, y1 ;
+
+    getopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts3( helpstr, argv[0], applic, usage, option ) ;
+
+    samplerate = to_Hz( sampstr, 0 ) ;
+    amplitude  = atof( astr ) ;
+    shift      = to_p( shiftstr, samplerate ) ;
+    duration   = to_p( dstr, samplerate ) ;
+
+    if ( ( type = typeindex( typestr ) ) < 0 ) {
+	fprintf(stderr,"step: unknown datatype [%s]\n", typestr) ;
+	exit( 1 ) ;
+    }
+
+    if ( isstr( polstr, "up" ) ) {
+	y0 = 0 ;         y1 = amplitude ;
+    }
+    else if ( isstr( polstr, "down" ) ) {
+	y0 = amplitude ; y1 = 0 ;
+    }
+    else {
+	fprintf(stderr,"step: unknown polarity [%s]\n", polstr) ;
+	exit( 1 ) ;
+    }
+
+    for ( i = 0 ; i < shift ; i++ )
+	writeitem( &y0, type, 1, stdout ) ;
+    for (  ; i < duration ; i++ )
+	writeitem( &y1, type, 1, stdout ) ;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/stof.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,41 @@
+/*
+  stof.c        binary short-to-float conversion.
+ --------
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+
+char applic[]     = "short to float data-type conversion." ;
+
+static char *helpstr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"          ,  DEBUG     },
+   ( char * ) 0 } ;
+
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE  *fp ;
+    short  X;
+    float  Y;
+
+    fp = openopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    while ( fread( &X, sizeof(short), 1, fp ) ) {
+	Y = (float)X ;
+	fwrite( &Y, sizeof(float), 1, stdout);
+    }
+
+    fclose(fp);
+    exit(0);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/strmatch.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,613 @@
+/***************************************************************************
+
+strmatch.c      String matching routines to supplement those defined in
+----------      <strings.h>.
+
+
+Character classification macros defined in <ctype.h>
+These return truth values [0,1].
+
+
+     int isalpha(c)     c is a letter
+     int c;
+
+     int isupper(c)     c is an uppercase letter
+     int c;
+
+     int islower(c)     c is a lowercase letter
+     int c;
+
+     int isdigit(c)     c is a digit
+     int c;
+
+     int isxdigit(c)    c is a hexadecimal digit, by default [0-9], [A-F], or
+     int c;             [a-f].
+
+     int isalnum(c)     c is an alphanumeric character
+     int c;
+
+     int isspace(c)     c is a space, tab, carriage return, new line, or form
+     int c;             feed.
+
+     int ispunct(c)     c is a punctuation character (neither control,
+     int c;             alphanumeric, nor space)
+
+
+     int isprint(c)     c is a printing character, by default code 040(8)
+     int c;             (space) through 0176 (tilde)
+
+
+     int isgraph(c)     c is a printing character, like isprint except false
+     int c;             for space.
+
+     int iscntrl(c)     c is a delete character (0177) or ordinary control
+     int c;             character (less than 040) except for space characters
+
+
+     int isascii(c)     c is an ASCII character, code less than 0200
+     int c;
+
+
+Character translation macros defined in <ctype.h>
+
+
+     int toupper(c)     return upper-case letter corresponding to c.
+     int c;
+
+     int tolower(c)     return lower-case letter corresponding to c.
+     int c;
+
+     int toascii(c)     return ascii value corresponding to c.
+     int c;
+
+
+String handling routines defined in <strings.h>
+A `span' is the length of a segment of a string, ie a number of characters.
+
+
+     char *strcat(s1, s2)       Append a copy of string s2 to the end of
+     char *s1, *s2;             string s1. Return a ptr to s1.
+
+     char *strncat(s1, s2, n)   Append n chars of s2 to the end of string s1.
+     char *s1, *s2;             Return a ptr to s1.
+
+     int strcmp(s1, s2)         Compare strings. Return 0 if equal.
+     unsigned char *s1, *s2;    Otherwise return difference number of chars.
+
+     int strncmp(s1, s2, n)     Compare n chars of strings. Return 0 if equal.
+     unsigned char *s1, *s2;    Otherwise return difference number of chars.
+     int n
+
+     strcasecmp(s1, s2)         As strcmp, but case insensitive.
+     char *s1, *s2;
+
+     strncasecmp(s1, s2, n)     As strncmp, but case insensitive.
+     char *s1, *s2;
+
+     char *strcpy(s1, s2)       Copy s2 to s1, including null char.
+     char *s1, *s2;
+
+     char *strncpy(s1, s2, n)   Copy n chars of s2 to s1. Truncate or pad s2
+     char *s1, *s2;             with nulls to make up n chars. If s2 needs to
+     int n                      be truncated, s1 will not be null terminated.
+
+     int strlen(s)              Return number of chars in s, not including
+     char *s;                   the terminating null character.
+
+     char *strstr(s1, s2)       Return a ptr to the first occurrence of s2
+     char *s1, *s2;             in s1. Otherwise return a null ptr.
+
+     char *strchr(s, c)         Return a ptr to the first occurrence of c
+     char *s;                   in s. Otherwise return a null ptr.
+     int c;
+
+     char *strrchr(s, c)        Return a ptr to the last occurrence of c
+     char *s;                   in s. Otherwise return a null ptr.
+     int c;
+
+     char *strpbrk(s1, s2)      Return a ptr to the first occurrence of any
+     char *s1, *s2;             char in s2 in s1. Otherwise return a null ptr.
+
+     int strspn(s1, s2)         Return the span from the head of s1 which
+     char *s1, *s2;             consists of chars which are in s2.
+
+     int strcspn(s1, s2)        Return the span from the head of s1 which
+     char *s1, *s2;             consists of chars which are not in s2.
+
+     char *strtok(s1, s2)       See below:
+     char *s1, *s2;
+
+     The strtok	subroutine considers the string	s1 to consist of a sequence
+     of	zero or	more text tokens separated by spans of one or more characters
+     from the separator	string s2.  The	first call (with pointer s1 speci-
+     fied) returns a pointer to	the first character of the first token,	and
+     will have written a null character	into s1	immediately following the
+     returned token.  The function keeps track of its position in the string
+     between separate calls, so	that subsequent	calls (which must be made
+     with the first argument a NULL pointer) will work through the string s1
+     immediately following that	token.	In this	way, subsequent	calls will
+     work through the string s1	until no tokens	remain.	 The separator string
+     s2	may be different from call to call.  When no token remains in s1, a
+     NULL pointer is returned.
+
+
+***************************************************************************/
+
+
+
+#include <math.h>
+#include "strmatch.h"
+
+
+/*
+Test for a NULL pointer to a character or string
+*/
+
+int isnull( s )
+char *s ;
+{
+    if ( s == (char *)0 ) return 1 ;
+    else                  return 0 ;
+}
+
+/*
+Test for an empty string
+*/
+
+
+int isempty( s )
+char *s ;
+{
+    if ( *s == '\0' ) return 1 ;
+    else              return 0 ;
+}
+
+/*
+Test for NULL string pointer or empty string
+*/
+
+int isnullorempty( s )
+char *s ;
+{
+    if ( s == (char *)0 || *s == '\0' ) return 1 ;
+    else                                return 0 ;
+}
+
+
+/*
+Return a pointer to the terminator '\0' at the tail of string `s'.
+*/
+
+char *terminator( s )
+char *s ;
+{
+    return ( s + strlen( s ) ) ;
+}
+
+
+/*
+Test strings s1==s2. Return 1 if true, 0 otherwise.
+*/
+
+int isstr( s1, s2 )
+char *s1, *s2 ;
+{
+    return ( strcmp( s1, s2 ) == 0 ) ;
+}
+
+
+/*
+Test strings s1==s2 up to the length of string s1 (ie allowing truncation).
+Return 1 if true, 0 otherwise.
+*/
+
+int iststr( s1, s2 )
+char *s1, *s2 ;
+{
+    return ( strncmp( s1, s2, strlen( s1 ) ) == 0 ) ;
+}
+
+
+/*
+Copy s2 to s1 up to (but not including) the first occurrence of character c
+in s2. Ensure s1 is then null terminated.
+Return s1 or a null ptr if c is not found in s2.
+*/
+
+char *strccpy( s1, s2, c )
+char *s1, *s2 ;
+char  c ;
+{
+    char *s ;
+
+    if ( ( s = strchr( s2, c ) ) == (char *)0 ) return (char *)0 ;
+    strncpy( s1, s2, (int)( s - s2 ) ) ;
+    *( s1 +  ( s - s2 ) ) == '\0' ;
+    return ( s1 ) ;
+}
+
+
+/*
+Return a ptr to the first occurrence of any char in s1 which is not in s2.
+Otherwise return a null ptr. (This complements strpbrk() in the Unix string
+library).
+*/
+
+char *strcbrk(s1, s2)
+char *s1, *s2;
+{
+    int  spn ;
+
+    if ( ( spn = strspn( s1, s2 ) ) == strlen( s1 ) )
+	return ( (char *)0 ) ;
+    return ( (char *)( s1 + spn ) ) ;
+}
+
+
+
+/*
+Return the span from the head of s1 to the first occurrence of any char in s2.
+Otherwise (if no such char found) return -1.
+*/
+
+int strspnbrk(s1, s2)
+char *s1, *s2;
+{
+    int  spn ;
+
+    if ( ( spn = strcspn( s1, s2 ) ) == strlen( s1 ) )
+	return ( -1 ) ;
+    return ( spn ) ;
+}
+
+
+/*
+Return the span from the head of s1 to the first occurrence of any char not
+in s2. Otherwise (if no such char found) return -1.
+*/
+
+int strcspnbrk(s1, s2)
+char *s1, *s2;
+{
+    int  spn ;
+
+    if ( ( spn = strspn( s1, s2 ) ) == strlen( s1 ) )
+	return ( -1 ) ;
+    return ( spn ) ;
+}
+
+
+
+/*
+Compare the heads of strings s1 and s2 up to the length of string s1.
+Return 0 if equal, otherwise return difference number of chars.
+*/
+
+int strtcmp( s1, s2 )
+char *s1, *s2 ;
+{
+    return ( strncmp( s1, s2, strlen( s1 ) ) ) ;
+}
+
+
+/*
+Compare the tails of strings s1 and s2 back to the length of string s2.
+Return 0 if equal, otherwise return difference number of chars.
+*/
+
+int strtrcmp( s1, s2 )
+char *s1, *s2 ;
+{
+    int  i, j ;
+
+    if ( ( i = strlen( s1 ) ) >=  ( j = strlen( s2 ) ) )
+	return ( strcmp( s1+i-j, s2 ) ) ;
+    return ( i-j ) ;
+}
+
+
+/*
+Return the span (number of chars) over which the head of string s1 equals the
+head of string s2.
+*/
+
+int streqspn( s1, s2 )
+char *s1, *s2 ;
+{
+    int  spn=0 ;
+
+    while ( !isempty(s1) && *s1++ == *s2++ ) spn++ ;
+    return spn ;
+}
+
+
+/*
+Return the span (number of chars) of a <number> at the head of string s.
+   <number> = [-]<digits>[.]<digits>
+where either, but not both, of the digit strings may be empty.
+*/
+
+int strnumspn( s )
+char *s ;
+{
+    int j0=0, j1, j2 ;
+
+    if ( *s == '-' )  j0++ ;               /* span of '-'                   */
+    j1 = strspn( s+j0, "0123456789" ) ;    /* span of digits left  of point */
+    if ( *( s+j0+j1 ) == '.' ) j1++ ;      /* span of '.'                   */
+    j2 = strspn( s+j0+j1, "0123456789" ) ; /* span of digits right of point */
+    if ( *( s+j0+j1+j2 ) == '.' ) j2++ ;
+
+    if ( j1>0 || j2>0 )
+	return ( j0+j1+j2 ) ;
+    return 0 ;                             /* zero span means no number     */
+}
+
+
+/*
+Test for a <number>.
+*/
+
+int isnumber( s )
+char *s ;
+{
+    if ( strnumspn( s ) > 0 ) return 1 ;
+    else                      return 0 ;
+}
+
+
+/*
+Return a ptr to the first char after a <number> at the head of string s.
+*/
+
+char *strnumptr( s )
+char *s ;
+{
+    return ( s + strnumspn( s ) ) ;
+}
+
+
+/*
+Return a ptr to the first occurrence of any number char in s.
+(where a number char includes '-' and '.' as well as any digit).
+*/
+
+char *strpnum(s)
+char *s ;
+{
+    return ( strpbrk( s, "-.0123456789" ) ) ;
+}
+
+/*
+Return a ptr to the first occurrence of any char in s not a number char.
+(where a number char includes '-' and '.' as well as any digit).
+*/
+
+char *strcnum(s)
+char *s ;
+{
+    return ( strcbrk( s, "-.0123456789" ) ) ;
+}
+
+
+/*
+Separate string `s1' into two string tokens at the first occurrence of a
+separator character `s2'. (Given as a string of one char).
+Numbers at the head of `s1' are skipped. (This skips leading hyphens or points
+which are part of a number, and so allows negative numbers with splitting
+hyphens, real numbers with splitting decimal point, etc.).
+Four possible outcomes, depending upon form of `s1':
+1. Null or empty.           - return NULL ptr, (missing 1st and 2nd tokens).
+2. No separator char.       - return ptr to empty string, (empty 2nd token).
+3. Separator is last char.  - return NULL ptr, (missing 2nd token).
+4. Separator within `s1'.   - return ptr to 2nd token, (two correct tokens).
+String `s1' is unchanged at the end.
+*/
+
+char *strpsep( s1, s2 )
+char *s1, *s2 ;
+{
+    char *s ;
+
+    if ( isnullorempty( s1 ) )
+	return ( (char *)0 ) ;
+
+    s1 = strnumptr( s1 ) ;              /* skip leading numbers */
+
+    if ( ( s = strpbrk( s1, s2 ) ) == (char *)0 )
+	return ( s1 + strlen( s1 ) ) ;  /* ptr to empty string at end s1 */
+
+    if ( isempty( ( s2 = s+1 ) ) )
+	return ( (char *)0 ) ;          /* separator is last char */
+
+    return ( s2 ) ;
+}
+
+/* Replace above last 4 lines of routine, and also mod strsep, to get proper
+   string separator
+    if ( ( s2 = strcbrk( s, s2 ) ) == (char *)0 )
+	return ( (char *)0 ) ;
+    while ( --s2 > s && isnumber( s2 ) ) ;
+    return ( ++s2 ) ;
+*/
+
+/*
+Separate string `s1' into two string tokens.
+strsep() is the same as strpsep() except that, in the event of two correct
+tokens, insert '\0' at the separator.
+String `s1' is thus separated and becomes the first token.
+*/
+
+char *strsep( s1, s2 )
+char *s1, *s2 ;
+{
+    char *s = strpsep( s1, s2 ) ;       /* ptr to 2nd token */
+
+    if ( isnullorempty( s ) )
+	return s ;
+
+    *(s-1) = '\0' ;     /* insert '\0' and return 2nd token */
+    return ( s ) ;
+}
+
+
+/*
+Compare the head of string `s' with null-terminated list of strings `list'.
+Return the longest matching string from `list'.
+Return a NULL pointer if no match is found, or if the (possibly abbreviated)
+head of string `s' is ambiguous (ie. matches more than once in the list).
+*/
+
+char *listcmp( list, s )
+char **list ;
+char  *s  ;
+{
+    int  i, j = (-1) ;
+
+    for ( i=0; list[i] != (char *)0 ; i++)
+	if ( strtcmp( s, list[i] ) == 0 ) {
+	    if ( j >= 0 ) return (char *)0 ;    /* ambiguous match */
+	    else j = i;
+	}
+    if ( j < 0 ) return (char *)0 ;             /* match not found */
+    return ( list[j] ) ;
+}
+
+
+/*
+Compare the tail of string `s' with null-terminated list of strings `list'.
+Return the longest matching string from `list'.
+Return a NULL pointer if no match is found, or if the (possibly abbreviated)
+tail of string `s' is ambiguous (ie. matches more than once in the list).
+*/
+
+char *listrcmp( list, s )
+char **list ;
+char  *s ;
+{
+    int  i, j = (-1), k, maxlen = 0 ;
+
+    for ( i=0; list[i] != (char *)0 ; i++)
+	if ( strtrcmp( s, list[i] ) == 0 && ( k = strlen( list[i] ) ) > maxlen ) {
+	    maxlen = k ;
+	    j      = i ;
+	}
+    if ( j < 0 ) return (char *)0 ;             /* match not found */
+    return ( list[j] ) ;
+}
+
+
+/*
+Compare the head of string `s' with null-terminated list of strings `list'.
+Find the string in `list' having the longest matching span with the head of
+`s' (which is possibly abbreviated).
+Return the list index of the matching string.
+Return (-1) if there is no match in the list (all spans are zero).
+Return (-2) if the longest matching span is ambiguous (ie occurs more
+than once in the list).
+*/
+
+int listindex( list, s )
+char   **list ;
+char    *s    ;
+{
+    int  i, j, jmax = 0, index = (-1) ;
+
+    for ( i=0; list[i] != (char *)0 ; i++) {
+	if ( ( j = streqspn( s, list[i] ) ) > jmax ) {
+	    jmax   = j ;
+	    index  = i ;
+	}
+	else if ( j > 0 && j == jmax )
+		index = (-2) ;
+    }
+    return index ;
+}
+
+
+/*
+Return the length of the null-terminated list of strings `list', ie. the
+number of strings it contains.
+*/
+
+listsize( list )
+char **list ;
+{
+    int  i ;
+
+    for ( i = 0 ; list[i] != (char *)0 ; i++ )
+	;
+    return i ;
+}
+
+
+/*
+For each string in list1, find the index of the matching string in list2
+and store it in the index array, (which must be at least the size of list1).
+The string match allows for abbreviations in the list1 strings.
+Return the number of matching strings found. (If this is less than the size
+of list1 then list1 contains an unknown or an ambiguous string).
+*/
+
+mapindices( list1, list2, index )
+char **list1, **list2 ;
+int   *index ;
+{
+    int  i, j, n = 0 ;
+
+    for ( i = 0 ; list1[i] != (char *)0 ; i++ )
+	if ( ( j = listindex( list2, list1[i] ) ) >= 0 )
+	    index[n++] = j ;
+
+    return n ;
+}
+
+
+/*
+Split the given string `str' into tokens at occurrences of separator char c.
+Store pointers to each token in `list', and null-terminate each token
+by overwriting the separator char with null.
+The list must contain at most n pointers.
+Return the number of tokens, or 0 if an error.
+*/
+
+tokens( str, list, n, c )
+char  *str  ;
+char **list ;
+int    n    ;
+char   c    ;
+{
+    int   i ;
+    char *s ;
+
+    if ( isempty( str ) || *str == c || n <= 0 )  return 0 ;
+    list[0] = str ;
+
+    for ( i = 1 ; i < n && ( s = strchr( str, c ) ) != (char *)0 ; i++ ) {
+	*s = '\0' ;
+	str = s + 1 ;
+	if ( isempty( str ) || *str == c )  return 0 ;
+	list[i] = str ;
+    }
+
+    if ( i == n && strchr( str, c ) != (char *)0 ) return 0 ;
+
+    return i ;
+}
+
+
+
+/*
+Return ASCII string of integer i. (Inverse of atoi()).
+*/
+
+char *itoa( i )
+int  i ;
+{
+    char s[64], *s1 ;
+
+    sprintf( s, "%d", i ) ;
+    s1 = (char *)malloc( strlen( s ) + 1 ) ;
+    strcpy( s1, s ) ;
+    return s1 ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/strmatch.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,32 @@
+
+/* #include <strings.h> */
+#include <string.h>
+#include <ctype.h>
+
+
+int   isempty()       ;
+int   isnull()        ;
+int   isnullorempty() ;
+int   isstr()         ;
+int   iststr()        ;
+int   isnumber()      ;
+int   strspnbrk()     ;
+int   strcspnbrk()    ;
+int   strtcmp()       ;
+int   strtrcmp()      ;
+int   streqspn()      ;
+int   strnumspn()     ;
+
+char *terminator()    ;
+char *strnumptr()     ;
+char *strpnum()       ;
+char *strcnum()       ;
+char *strcbrk()       ;
+char *strpsep()       ;
+char *strsep()        ;
+
+char *listcmp()       ;
+char *listrcmp()      ;
+int   listindex()     ;
+
+char *itoa()          ;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/swab.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,97 @@
+/*
+    swab.c      swap bytes
+    ------
+
+  Read and write binary shorts (2-bytes).
+  With no filename arguments, data is expected on the stdin, and the
+  result is written on the stdout. Otherwise each given filename is
+  processed in turn. When the `output' option is "off" output overwrites the
+  respective input file. (The respective output for the stdin is the stdout).
+  Otherwise all results are written to the one given output file
+  (which is the stdout by default).
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+
+
+char applic[]     = "Swap byte order of binary 2-byte data." ;
+
+static char *helpstr,   *outstr,  *sizestr  ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                                      , DEBUG   },
+    {   "output"    ,   "stdout"    ,  &outstr      ,   "output filename (off = overwrite input)"   , VAL     },
+    {   "SIZE"      ,   "262144"    ,  &sizestr     ,   "buffer size in bytes"                      , SVAL    },
+   ( char * ) 0 } ;
+
+
+int    SIZE        ;    /* size of temp buffer for stdin data      */
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE *ifp, *ofp ;
+    int   i, j, n, doOpen, doCreate  ;
+    char *data, *Y ;
+
+    i = getopts( option, argc, argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts( helpstr, argv[0], applic, option ) ;
+
+    SIZE  = atoi( sizestr ) ;
+
+    doOpen = doCreate = 0 ;
+
+    if ( i == 0 ) ifp = stdin ;
+    else doOpen++ ;
+
+    if ( isoff( outstr ) ) {
+	if ( i == 0 )   ofp = stdout ;  /* o/p = i/p which is stdin   */
+	else            doCreate++ ;    /* o/p = i/p for current file */
+    }
+    else if ( isstr( outstr, "stdout") ) ofp = stdout ;
+    else if ( ( ofp = fopen( outstr, "w" ) ) == (FILE *)0 ) {
+	fprintf( stderr,"swab: can't create %s\n", outstr ) ;
+	exit( 1 ) ;
+    }
+
+    Y = (char *)malloc( sizeof( short ) ) ;
+    if ( ( data = (char *)malloc( SIZE ) ) == NULL ) {
+	fprintf( stderr, "malloc out of space\n" ) ;
+	exit( 1 ) ;
+    }
+
+    do {
+
+	if ( doOpen   && ( ifp = fopen( argv[argc-i], "r" ) ) == (FILE *)0 ) {
+	    fprintf( stderr,"swab: can't open %s\n", argv[argc-i] ) ;
+	    exit( 1 ) ;
+	}
+
+	for ( n = 0 ; n < SIZE && fread( &data[n], sizeof(short), 1, ifp ) ; n += 2 )
+	    ;
+	if ( n == SIZE ) fprintf( stderr, "warning: buffer out of space, increase SIZE\n" ) ;
+
+	if ( doOpen   ) fclose( ifp ) ;
+
+	if ( doCreate && ( ofp = fopen( argv[argc-i], "w" ) ) == (FILE *)0 ) {
+	    fprintf( stderr,"swab: can't create %s\n", argv[argc-i] ) ;
+	    exit( 1 ) ;
+	}
+
+	for ( j = 0 ; j < n ; j += 2 ) {
+	    *Y     = data[j+1] ;
+	    *(Y+1) = data[j]   ;
+	    fwrite( Y, sizeof(short), 1, ofp );
+	}
+
+	if ( doCreate ) fclose( ofp ) ;
+
+    } while ( --i > 0 ) ;
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/tone.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,114 @@
+/*
+  tone.c    generate a pure tone.
+  ------
+    Generate samples of a sine wave at a given sample rate.
+    Specify wave amplitude, and frequency (in Hz or kHz), or alternatively
+    period (in s, ms, or p (sample points) ). If both period and frequency
+    are specified, then the given period takes precedence.
+    If S is the samplerate, and Ts=1/S is the sample interval,
+    then each sample of a sine wave of period T samples is given by:
+	sin(n*(Ts/T)*TWOPI)  for  n=0,1,2,...
+    Output samples in the given datatype for the given waveform duration.
+
+
+Examples:
+
+1. Sine wave with period 10ms sampled at 10kHz, (100 sample points per period)
+
+tone period=10ms samplerate=10kHz | x11plot
+
+2. Sine wave with frequency 100Hz sampled at 20kHz
+
+tone frequency=100Hz | x11plot
+
+3. Sine wave with period 100 sample points, with dc-offset set equal to
+   amplitude of 500 so that waveform is just non-negative.
+
+tone period=100p amplitude=500 offset=500 | x11plot
+
+4. Quarter cycle of a sine wave with 8ms period.
+
+tone period=8ms duration=2ms | x11plot
+
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "options.h"
+#include "units.h"
+#include "strmatch.h"
+
+#define TWOPI   6.28318530717
+
+char applic[]  = "generate a pure tone. " ;
+char usage[]   = "tone [options]" ;
+
+static char *helpstr, *debugstr, *sampstr, *perstr, *freqstr, *astr, *ostr, *dstr, *typestr ;
+static char *phasestr ;
+
+static Options option[] = {
+    {   "help"      ,   "off"       ,  &helpstr     ,   "help"                              , DEBUG   },
+    {   "debug"     ,   "off"       ,  &debugstr    ,   "debugging switch"                  , DEBUG   },
+    {   "samplerate",   "20kHz"     ,  &sampstr     ,   "samplerate "                       , VAL     },
+    {   "period"    ,   "8ms"       ,  &perstr      ,   "period of waveform"                , VAL     },
+    {   "frequency" ,   "125Hz"     ,  &freqstr     ,   "frequency of waveform"             , VAL     },
+    {   "phase"     ,   "0"         ,  &phasestr    ,   "phase offset"                      , VAL     },
+    {   "amplitude" ,   "512"       ,  &astr        ,   "amplitude of waveform"             , VAL     },
+    {   "mean"      ,   "0"         ,  &ostr        ,   "mean value of waveform"            , VAL     },
+    {   "duration"  ,   "500ms"     ,  &dstr        ,   "duration of waveform"              , VAL     },
+    {   "type"      ,   "short"     ,  &typestr     ,   "output datatype"                   , VAL     },
+   ( char * ) 0 } ;
+
+
+int     samplerate ;
+float   amplitude  ;
+float   offset     ;
+int     type       ;    /* datatype index */
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    float  T=0, Tr, r, y ;
+    int    i, n ;
+
+    getopts( option,argc,argv ) ;
+    if ( !isoff( helpstr ) )
+	helpopts3( helpstr, argv[0], applic, usage, option ) ;
+
+    samplerate = to_Hz( sampstr, 0 ) ;
+    amplitude  = atof( astr ) ;
+    offset     = atof( ostr ) ;
+
+    if ( ( type = typeindex( typestr ) ) < 0 ) {
+	fprintf( stderr, "tone: bad type [%s]\n", typestr ) ;
+	exit( 1 ) ;
+    }
+
+    n  = to_p( dstr, samplerate ) ;
+
+    if ( isstr( perstr, optdflt( option, "period" ) ) )
+	T = 1.0 / to_Hz( freqstr, samplerate ) ;
+    else
+	T = to_s( perstr, samplerate ) ;
+
+    Tr = TWOPI / ( samplerate * T ) ;   /* period of max resolution */
+
+    if ( iststr( phasestr, "sine" ) )   /* start */
+	r = 0 ;
+    else if ( iststr( phasestr, "cosine" ) )
+	r = TWOPI / 4 ;
+    else if ( iststr( phasestr, "antisine" ) )
+	r = TWOPI / 2 ;
+    else if ( iststr( phasestr, "anticosine" ) )
+	r = 3 * TWOPI / 4 ;
+    else if ( isstr( phasestr + strlen( phasestr ) - 3, "deg" ) )
+	r = TWOPI * ( atof( phasestr ) / 360. ) ;
+    else
+	r = TWOPI * ( to_s( phasestr, samplerate ) / T ) ;
+
+    for ( i = 0  ; i < n ; i++, r += Tr ) {
+	y = amplitude * sin(r) + offset ;
+	writeitem( &y, type, 1, stdout ) ;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/units.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,230 @@
+/***************************************************************************
+  units.c
+ ---------
+  Return binary doubles for given string values, according to units.
+  Units are specified by the final char:
+    p   sample points.
+    s   seconds.
+    ms  milliseconds
+    Hz  Hertz.
+    kHz KiloHertz
+    erb equivalent rectangular bandwidth [Hz]
+
+***************************************************************************/
+
+#include <stdio.h>
+#include <math.h>
+#include <ctype.h>
+#include "units.h"
+#include "strmatch.h"
+
+
+/*
+Return the units index number of the best matching units at the tail of
+string `s'. Return -1 if no units are found.
+*/
+
+int unitindex( s )
+char *s ;
+{
+    int   i  ;
+
+    if ( ( i = strnumspn( s ) ) == 0 ) {        /* case of no digits found */
+	fprintf( stderr, "bad value [%s]\n", s ) ;
+	exit( 1 ) ;
+    }
+    if ( i == strlen( s ) )
+	return (-1) ;                           /* case of no units found  */
+
+    switch ( i = listindex( units, s+i ) ) {
+	case (-1) : fprintf(stderr,"unknown units [%s]\n", s ) ;
+		    exit( 1 ) ;
+	case (-2) : fprintf(stderr,"ambiguous units [%s]\n", s ) ;
+		    exit( 1 ) ;
+    }
+    return i ;                  /* index of units */
+}
+
+
+
+/*
+Return a ptr to the units string at the tail of string `s'.
+Otherwise return a ptr to the null terminator of `s' if no units are found.
+*/
+
+char  *unitstr( s )
+char *s ;
+{
+    unitindex( s ) ;    /* check for valid (or no) units */
+    return ( strnumptr( s ) ) ;
+}
+
+
+/*
+Search the end of the given string for units (such as ms, kHz, etc).
+Delete any units found by overwriting the start of the units string with '\0'.
+*/
+
+stripunits( s )
+char  *s ;
+{
+    *( unitstr( s ) ) = '\0' ;
+}
+
+
+/*
+Return an allocated string to the square root of the given value with original
+units appended.
+*/
+
+char *sqrt_units( s )
+char *s ;
+{
+    char s1[64] ;
+
+    sprintf( s1, "%.2f%s", sqrt( (double)atof( s ) ), unitstr( s ) ) ;
+    return ( strcpy( (char *)malloc( strlen( s1 ) + 1 ), s1 ) ) ;
+}
+
+
+/*
+Return the type of a <number>: INT, FLOAT, or 0 (if not a number).
+   <number> = [-]<digits>[.]<digits>
+where either, but not both, of the digit strings may be empty.
+*/
+
+int numbertype( str )
+char *str ;
+{
+    if ( strnumspn( str ) == 0 )           return 0     ;
+    if ( strchr( str, '.' ) == (char *)0 ) return INT   ;
+    else                                   return FLOAT ;
+}
+
+
+/*
+Return 1 if str is an int, otherwise return 0.
+*/
+
+int isint( str )
+char *str ;
+{
+    if ( numbertype( str ) == INT ) return 1 ;
+    return 0 ;
+}
+
+/*
+Return 1 if str is a float, otherwise return 0.
+*/
+
+int isfloat( str )
+char *str ;
+{
+    if ( numbertype( str ) == FLOAT ) return 1 ;
+    return 0 ;
+}
+
+
+/*
+  Units converters.
+  Generally called: to_<unit> where <unit> is the output units.
+  Input strings without units have `default' units.
+*/
+
+double to_Hz( str, samplerate ) /* default units Hz */
+char *str ;
+int   samplerate ;
+{
+    switch ( unitindex( str ) ) {
+	case (-1) : return   atof( str ) ;
+	case   0  : return   ( (double)samplerate / atof( str ) ) ;
+	case   1  : return   ( 1. / atof( str ) ) ;
+	case   2  : return   ( 1000. / atof( str ) ) ;
+	case   3  : return   atof( str ) ;
+	case   4  : return ( atof( str ) * 1000 ) ;
+	case   5  : return ( ( exp( (double)(atof( str ) / 9.265 )) - 1 ) * 9.265 * 24.7 ) ;
+	default   : fprintf(stderr, "can't convert [%s] to Hz\n", str ) ;
+		    exit( 1 ) ;
+    }
+}
+
+double to_kHz( str, samplerate )    /* default units Hz */
+char *str ;
+int   samplerate ;
+{
+    switch ( unitindex( str ) ) {
+	case (-1) : return ( atof( str ) * .001 ) ;
+	case   0  : return   ( ( (double)samplerate / atof( str ) ) * 0.001 ) ;
+	case   1  : return   ( ( 1. / atof( str ) ) * 0.001 ) ;
+	case   2  : return   ( 1. / atof( str ) ) ;
+	case   3  : return ( atof( str ) * .001 ) ;
+	case   4  : return   atof( str ) ;
+	case   5  : return ( ( exp( (double)(atof( str ) / 9.265 )) - 1 ) * 9.265 * 24.7 * .001 ) ;
+	default   : fprintf(stderr, "can't convert [%s] to kHz\n", str ) ;
+		    exit( 1 ) ;
+    }
+}
+
+double to_erb( str )    /* default units erb */
+char *str ;
+{
+    switch ( unitindex( str ) ) {
+	case (-1) : return   atof( str ) ;
+	case   3  : return ( 9.265 * log( (double)(1 + atof( str )/(9.265*24.7)) ) ) ;
+	case   4  : return ( 9.265 * log( (double)(1 + (1000*atof( str ))/(9.265*24.7)) ) ) ;
+	case   5  : return   atof( str ) ;
+	default   : fprintf(stderr, "can't convert [%s] to erb\n", str ) ;
+		    exit( 1 ) ;
+    }
+}
+
+double to_p( str, samplerate )  /* default units p */
+char *str ;
+int   samplerate ;
+{
+    switch ( unitindex( str ) ) {
+	case (-1) : return   atof( str ) ;
+	case   0  : return   atof( str ) ;
+	case   1  : return ( atof( str ) * samplerate ) ;
+	case   2  : return ( atof( str ) * samplerate * .001 ) ;
+	case   3  : return ( samplerate / atof( str ) ) ;
+	case   4  : return ( samplerate / ( 1000 * atof( str ) ) ) ;
+	default   : fprintf(stderr, "can't convert [%s] to samples\n", str ) ;
+		    exit( 1 ) ;
+    }
+}
+
+
+
+double to_s( str, samplerate )  /* default units p (sample points) */
+char *str ;
+int   samplerate ;
+{
+    switch ( unitindex( str ) ) {
+	case (-1) : return ( atof( str ) / samplerate ) ;
+	case   0  : return ( atof( str ) / samplerate ) ;
+	case   1  : return   atof( str ) ;
+	case   2  : return ( atof( str ) * .001 ) ;
+	case   3  : return ( 1. / atof( str ) ) ;
+	case   4  : return ( 1. / ( 1000 * atof( str ) ) ) ;
+	default   : fprintf(stderr, "can't convert [%s] to secs\n", str ) ;
+		    exit( 1 ) ;
+    }
+}
+
+
+double to_ms( str, samplerate )  /* default units p */
+char *str ;
+int   samplerate ;
+{
+    switch ( unitindex( str ) ) {
+	case (-1) : return ( atof( str ) * 1000 / samplerate ) ;
+	case   0  : return ( atof( str ) * 1000 / samplerate ) ;
+	case   1  : return ( atof( str ) * 1000 ) ;
+	case   2  : return   atof( str ) ;
+	case   3  : return ( 1000. / atof( str ) ) ;
+	case   4  : return ( 1. / atof( str ) ) ;
+	default   : fprintf(stderr, "can't convert [%s] to ms\n", str ) ;
+		    exit( 1 ) ;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/units.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,31 @@
+
+#define INT         ( -10 )
+#define FLOAT       ( -11 )
+
+
+/* units list */
+
+static char *units[] = {
+	"points"    ,   /* 0 */
+	"seconds"   ,   /* 1 */
+	"ms"        ,   /* 2 */
+	"Hz"        ,   /* 3 */
+	"kHz"       ,   /* 4 */
+	"erb"       ,   /* 5 */
+   ( char * ) 0 } ;
+
+
+int    unitindex()  ;
+char  *unitstr()    ;
+char  *sqrt_units() ;
+
+int    numbertype() ;
+int    isint()      ;
+int    isfloat()    ;
+
+double to_Hz()      ;   /* convert to Hz, assuming default units Hz */
+double to_kHz()     ;   /* convert to kHz, assuming default units Hz */
+double to_erb()     ;   /* convert to erb, assuming default units erb */
+double to_p()       ;   /* convert to p (samples), assuming default units p */
+double to_s()       ;   /* convert to s (seconds), assuming default units p */
+double to_ms()      ;   /* convert to ms, assuming default units p */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/x11coord.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,519 @@
+/****************************************************************************
+*       Routines for x11coord package.
+****************************************************************************/
+
+#include <stdio.h>
+#include <math.h>
+#include "x11coord.h"
+
+/****************************************************************************
+*   Set parameters for data-pixel conversion macros
+****************************************************************************/
+/* Initialize parameters for size and position of window on screen */
+set_window_parameters(xorg,yorg, width,height)
+int xorg,yorg;      /* Pixel coords of window origin wrt theDisplay origin */
+int width,height;   /* Size of window (in pixels) */
+{
+    _xorg   = xorg;
+    _yorg   = yorg;
+    _width  = width;
+    _height = height;
+    set_bordered_box((int)0);   /* defaults */
+    set_data_parameters((int)0,(int)0, (float)0,(float)0, (float)width,(float)height);
+}
+
+/* Initialize parameters for size and position of box in preset window */
+set_box_parameters(xorg,yorg, width,height)
+int xorg,yorg;      /* Pixel coords of box origin wrt bottom-left of window */
+int width,height;   /* Size of window (in pixels) */
+{
+    _Xp0    = xorg;
+    _Yp0    = _height - yorg;
+    _Xp1    = xorg + width;
+    _Yp1    = _height - (yorg + height);
+    _Wb     = _Xp1 - _Xp0;
+    _Hb     = _Yp0 - _Yp1;
+    set_data_parameters((int)0,(int)0, (float)0,(float)0, (float)width,(float)height);
+}
+
+
+/* Initialize parameters for size and position of box in preset window,   */
+/* given the width of the border as a %age of the window size on any side */
+set_bordered_box(bpc)
+int bpc;
+{
+    int  xborder, yborder, Wb, Hb;
+
+    xborder = (_width *  bpc) / 100;
+    yborder = (_height * bpc) / 100;
+    Wb      = _width -  2*xborder;
+    Hb      = _height - 2*yborder;
+    set_box_parameters(xborder,yborder, Wb,Hb);
+}
+
+/* Initialize parameters for area and location of data-space to appear in box */
+set_data_parameters(xp0,yp0, xd0,yd0, xrange,yrange)
+int   xp0,yp0;      /* Box origin shift as a percentage of box width,height */
+float xd0,yd0;      /* Data coord to appear under box origin.               */
+float xrange,yrange;/* Data ranges (corresponding to box width and height). */
+{
+    _xrange = xrange;
+    _yrange = yrange;
+    _xshift = (_Wb * xp0)/100;
+    _yshift = (_Hb * yp0)/100;
+    _xd0    = xd0;
+    _yd0    = yd0;
+    _Xd0    = xd0 - _xrange*((float)_xshift/_Wb);
+    _Yd0    = yd0 - _yrange*((float)_yshift/_Hb);
+    _Xd1    = xd0 + (_xrange - _xrange*((float)_xshift/_Wb));
+    _Yd1    = yd0 + (_yrange - _yrange*((float)_yshift/_Hb));
+
+    _xoffset = _Xp0       + _xshift - _xd0*_Wb/_xrange ;
+    _yoffset = _Yp1 + _Hb - _yshift + _yd0*_Hb/_yrange ;
+    _xscale  = _Wb/_xrange;
+    _yscale  = _Hb/_yrange;
+}
+
+
+/****************************************************************************
+*       Creating windows, initializing GC and Font,  etc..   (X11 specific)
+****************************************************************************/
+xopen()
+{
+
+    if ((char *)getenv("DISPLAY") == (char *)0 )  {
+	fprintf(stderr,"DISPLAY not set\n");
+	exit(1);
+    }
+    if ((theDisplay = XOpenDisplay(NULL)) == NULL)  {
+	fprintf(stderr,"Can't open display %s\n", getenv("DISPLAY"));
+	exit(1);
+    }
+    theScreen = XDefaultScreen(theDisplay);
+    theForeground = theBlack = XBlackPixel(theDisplay,theScreen);  /* Black lines, text, and borders */
+    theBackground = theWhite = XWhitePixel(theDisplay,theScreen);  /* White background */
+    theWidth = XDisplayWidth(theDisplay,theScreen);
+    theHeight = XDisplayHeight(theDisplay,theScreen);
+    theGC = initGC() ;
+}
+
+
+/*
+eg: xgc( 1, "times_roman14" ) ;
+*/
+
+xgc( linewidth, fontstr )
+int   linewidth ;
+char *fontstr   ;
+{
+    setLinewidth( linewidth ) ;
+    theFont = (XFontStruct *)0;
+    if ( setFont( fontstr ) == NULL ) {
+	fprintf( stderr,"can't load font %s\n", fontstr ) ;
+	exit( 1 ) ;
+    }
+}
+
+
+GC initGC()
+{
+    GC  gc;
+
+    gc = XDefaultGC(theDisplay, theScreen);
+    /* Set foreground and background pixel values (ie colours) */
+    XSetState(theDisplay, gc, theForeground, theBackground, GXcopy, AllPlanes);
+    return gc;
+}
+
+
+
+setLinewidth(width)     /* Set line width, used by XDrawLine commands */
+int  width;
+{
+    XGCValues  gcvalues;
+
+    gcvalues.line_width = width;
+    XChangeGC(theDisplay, theGC, GCLineWidth, &gcvalues);
+}
+
+
+setFont(fontname)   /* Free last theFont (unless null) and load new font */
+char *fontname;     /* return null if can't load font */
+{
+    if (theFont != (XFontStruct *)0) XFreeFont(theDisplay,theFont);
+    if ((theFont = XLoadQueryFont(theDisplay, fontname)) == NULL)
+	return 0 ;
+    XSetFont(theDisplay, theGC, theFont->fid);
+    return 1 ;
+}
+
+
+Window  xCreate(name, event_mask, xorg,yorg, width,height)
+char *name;
+long  event_mask;
+int   xorg,yorg, width,height;
+{
+    Window w;
+
+    if ((w = XCreateSimpleWindow(theDisplay, XDefaultRootWindow(theDisplay),
+			   xorg, yorg, (unsigned)width, (unsigned)height, 1,
+				     theForeground, theBackground)) == (Window)0 ) {
+	fprintf(stderr,"can't create window\n");
+	exit(1);
+    }
+    XStoreName(theDisplay, w, name);
+    XSelectInput(theDisplay, w, event_mask);
+    XMapWindow(theDisplay, w);
+    XFlush(theDisplay);
+    return w;
+}
+
+
+/****************************************************************************
+* Drawing axes and boxes in a given window w.
+****************************************************************************/
+axis(w, p0,p1, ploc,axis)
+Window w;
+int    p0,p1;   /* First and last axis pixel distances, relative to parent */
+int    ploc;    /* Location of axis (orthogonal pixel dist from parent org) */
+char   axis;    /* Orientation of axis ('x' or 'y') */
+{
+    if (axis=='x')  XDrawLine(theDisplay, w, theGC, p0,ploc, p1,ploc);
+    if (axis=='y')  XDrawLine(theDisplay, w, theGC, ploc,p0, ploc,p1);
+}
+
+box(w, x0,y0, x1,y1)    /* draw rectangular box */
+Window w;
+int    x0,y0, x1,y1;
+{
+    axis(w, y0,y1, x0,'y');
+    axis(w, y0,y1, x1,'y');
+    axis(w, x0,x1, y0,'x');
+    axis(w, x0,x1, y1,'x');
+}
+
+/****************************************************************************
+* Calibrating axes and boxes in a given window w.
+****************************************************************************/
+struct mark_struct {
+    int    type;        /* type= HALFMARK or FULLMARK */
+    int    position;    /* mark position on screen relative to the parent system */
+    char   label[16];   /* ASCII label of real plot value (FULLMARK only) */
+};
+
+#define NMARKS      150 /* size of array of calibration marks */
+#define FULLMARK    10  /* Box calibration marks */
+#define HALFMARK    5
+
+calibrate_Axis(w, p0,p1, d0,d1, ploc,axis)
+Window w;
+int    p0,p1;   /* First and last axis pixel distances, relative to parent */
+float  d0,d1;   /* First and last axis data values */
+int    ploc;    /* Location of axis (orthogonal pixel dist from parent org) */
+char   axis;    /* Orientation of axis ('x' or 'y') */
+{
+    int     n;
+    struct  mark_struct mark[NMARKS];
+
+    if ((n = calibrate(mark, p0,p1, d0,d1)) < 0) {
+	fprintf(stderr,"mark array out of space, increase NMARKS\n");
+	exit(1);
+    }
+    if (axis=='x')  plotX(w, ploc, mark, n);
+    if (axis=='y')  plotY(w, ploc, mark, n);
+}
+
+
+calibrate_Box(w, xp0,yp0, xp1,yp1, xd0,yd0, xd1,yd1)
+Window  w;
+int     xp0,yp0, xp1,yp1;
+float   xd0,yd0, xd1,yd1;
+{
+    calibrate_Axis(w, xp0,xp1, xd0,xd1, yp0,'x');
+    calibrate_Axis(w, yp0,yp1, yd0,yd1, xp0,'y');
+}
+
+
+plotX(w, Y, mark, n)    /* Plot calibration marks along an X axis */
+Window w;
+int    Y;
+struct mark_struct mark[];
+int    n;
+{
+    int   i, H, W;
+    int   X;
+
+    for (i = 0 ; i < n ; i++) {
+	X = mark[i].position;
+	XDrawLine(theDisplay, w, theGC, X, Y, X, Y+mark[i].type);
+	if (mark[i].type == FULLMARK)      /* Label calibration value */
+	{
+	    W = stringwidth(mark[i].label) / 2; /* Shift label left by half width */
+	    H=20;                               /* Shift label down a bit */
+	    XDrawString(theDisplay, w, theGC, X-W, Y+H, mark[i].label, strlen(mark[i].label));
+	}
+    }
+}
+
+plotY(w, X, mark, n)    /* Plot calibration marks along a Y axis */
+Window w;
+int    X;
+struct mark_struct mark[];
+int    n;
+{
+    int   i, H, W;
+    int   Y;
+
+    for (i = 0 ; i < n ; i++) {
+	Y = mark[i].position;
+	XDrawLine(theDisplay, w, theGC, X, Y, X-mark[i].type, Y);
+	if (mark[i].type == FULLMARK) {    /* Label calibration value */
+	    W = stringwidth(mark[i].label) + 10;/* Shift label left by width */
+	    H=5;                                /* Shift label down a bit */
+	    XDrawString(theDisplay, w, theGC, X-W, Y+H, mark[i].label, strlen(mark[i].label));
+	}
+    }
+}
+
+/****************************************************************************
+*       Macros used by calibration routines
+****************************************************************************/
+#define rem(x,y)    fabs((x) - (y)*(int)((x)/(y)))      /* real remainder */
+#define rem2(x,y)   fabs((x) - (y)*(int)((x)/(y)-0.5))  /* real remainder for -ve x */
+#define round(x)    ((x >= 0) ? ((int)(x+0.5)) : ((int)(x-0.5)))
+#define min(x,y)    ((x < y) ? x : y)
+#define EPS         1.0e-5
+
+/****************************************************************************
+* Calibrate one axis.
+* Fill the given array "mark" with mark structs, and return the number of
+*   marks, or -1 indicating that the mark array is full, (and NMARKS should
+*   be increased).
+* Each mark struct in the array gives the mark position (in pixels relative
+*   to the given first and last mark positions), the mark type (being HALFMARK
+*   or FULLMARK), and a label string (for each FULLMARK only).
+* Arguments are as follows:
+*   p0,p1   first and last screen positions in pixels, relative to the parent
+*           window, (used to calculate mark positions on the screen).
+*   d0,d1   first and last data values (used to calculate axis labels).
+*****************************************************************************/
+calibrate(mark, p0, p1, d0, d1)
+struct mark_struct mark[];
+int    p0,p1;   /* first and last axis pixel distances, relative to parent */
+float  d0,d1;   /* first and last axis data values */
+{
+    int   position, plotsize, nmarks=0;
+    float div, hdiv, offset, hoffset, value, hvalue;
+    float range, scalefactor, maxerror, nextvalue, lastvalue;
+    float label, real_division (), sig_figs ();
+    float tmp;
+
+    if (d0 > d1) {      /* swap to get +ve range */
+	tmp = d1; d1 = d0; d0 = tmp;
+	tmp = p1; p1 = p0; p0 = tmp;
+    }
+
+    plotsize = p1-p0;   /* screen size     */
+    range    = d1-d0;   /* real plot range */
+
+    div = real_division (range);
+    hdiv = div/10;      /* Halfmarks every 10th labelled division (fullmark) */
+
+    /* calculate real offset and hoffset of 1st fullmark and halfmark */
+    /* respectively, from first (ie min) real value d0.               */
+    if (d0 == 0)
+    {
+	offset = hoffset = 0;
+    }
+    else
+    {
+	if (d0 > 0)
+	{
+	    offset = div - rem(d0,div);
+	    hoffset = hdiv - rem(d0,hdiv);
+	}
+	else    /* (d0 < 0) */
+	{
+	    offset = rem2(d0,div);
+	    hoffset = rem2(d0,hdiv);
+	}
+    }
+
+    value = d0 + offset;       /* real value of 1st fullmark */
+    hvalue = d0 + hoffset;     /* real value of 1st halfmark */
+
+    scalefactor = (float)plotsize/range;    /* scale factor between real range and plotted range */
+    maxerror = hdiv/2;
+    lastvalue = d0+range+maxerror;
+    nextvalue = value-maxerror;
+
+    /* Plot halfmarks up to 1st fullmark */
+
+    for (  ; hvalue < nextvalue ; hvalue += hdiv)
+    {
+	position = (int)((hvalue-d0) * scalefactor);   /* actual plotted position (in plot range) */
+	setmark (&mark[nmarks], HALFMARK, p0+position, NULL);
+	if (++nmarks >= NMARKS) return -1;
+    }
+
+    /* Loop plotting fullmarks, with halfmarks between each */
+
+    for (  ; value < lastvalue ; value += div)
+    {
+	position = (int)((value-d0) * scalefactor);    /* actual plotted position */
+	label = sig_figs (value, range);
+	setmark (&mark[nmarks], FULLMARK, p0+position, label);
+	if (++nmarks >= NMARKS) return -1;
+
+	/* Loop plotting halfmarks between each fullmark */
+
+	nextvalue = value+div-maxerror;
+	if (nextvalue > lastvalue) nextvalue = lastvalue;
+	for (hvalue = value+hdiv ; hvalue < nextvalue ; hvalue += hdiv)
+	{
+	    position = (int)((hvalue-d0) * scalefactor);   /* actual plotted position */
+	    setmark (&mark[nmarks], HALFMARK, p0+position, NULL);
+	    if (++nmarks >= NMARKS) return -1;
+	}
+    }
+    return nmarks;
+}
+
+
+float
+real_division (range)   /* Return recomended division between fullmarks on real scale */
+float range;
+{
+    int   power;
+    float scalefactor, scaled_range, div;
+
+    if (range <= 0) {
+	fprintf(stderr,"range must be positive\n");
+	exit(1);
+    }
+
+    if (range >= 1.0)
+	power = -(int)(log10(range) + EPS);
+    else
+	power = -(int)(log10(range) - 1 + EPS);
+    scalefactor = pow (10.0, (float)power);
+
+    scaled_range = range * scalefactor; /* scaled_range is (1 <= range <= 9.9999) */
+
+    /* Set division size (in scaled_range) between given breaks in the scale */
+
+    if      (scaled_range < 1.5) div = 0.1;
+    else if (scaled_range < 2.5) div = 0.2;
+    else if (scaled_range < 5.0) div = 0.5;
+    else                         div = 1.0;
+
+    return (div/scalefactor);   /* return div scaled down to real range */
+}
+
+
+float
+sig_figs (value, range) /* Round value to 2 sig figs on the scale of the range */
+float value, range;
+{
+    int   power;
+    float scalefactor, scaled_value;
+
+    if (range >= 1.0)
+	power = 1-(int)(log10(range) + EPS);
+    else
+	power = 1-(int)(log10(range) - 1 + EPS);
+    scalefactor = pow (10.0, (float)power);
+
+    scaled_value = value * scalefactor; /* scaled_value is in range (10 <= range <= 99.999) */
+    value = round(scaled_value);
+
+    return (value/scalefactor);
+}
+
+/* Fill one mark struct with the mark position, type, and label */
+setmark (mark, mark_type, x, x1)
+struct mark_struct *mark;
+int   mark_type;
+int   x;                /* position */
+float x1;               /* value of label */
+{
+    if ((mark->type = mark_type) == FULLMARK)
+	labelstring(mark->label, x1);
+    mark->position = x;
+}
+
+/* Return with str containing an appropriate ASCII string of the given value */
+labelstring(str, value)
+char  *str;
+float  value;
+{
+    float decval;       /* decimal part of a number */
+
+    decval = value - (int)value;
+    if (value < 0) decval = -decval;
+    if (value > -EPS && value < EPS)    sprintf(str,"0"             );
+    else if (fabs(value) >= 10000)      sprintf(str,"%g",      value);
+    else if (decval <= EPS)             sprintf(str,"%d", (int)value);
+    else if (decval <= 0.001)           sprintf(str,"%.4f",    value);
+    else if (decval <= 0.01)            sprintf(str,"%.3f",    value);
+    else if (decval <= 0.1)             sprintf(str,"%.2f",    value);
+    else                                sprintf(str,"%.1f",    value);
+}
+
+/****************************************************************************
+	Text printing routines.
+****************************************************************************/
+/* The origin for a char is an x-value of `lbearing' to the left of the    */
+/*  left-most char ink, and a y-value between the `ascent' and the         */
+/*  `descent', (ie along an underline), (ref 6-20).                        */
+/* The `margin' is an ad-hoc idea.                                         */
+
+/* Return the width in pixels of the given string, using the current font */
+stringwidth(str)
+char *str;
+{
+    int width;
+
+    width = XTextWidth(theFont, str, strlen(str));
+    return width;
+}
+
+/* Return the height in pixels of the given string, using the current font */
+stringheight(str)
+char *str;
+{
+    XCharStruct stringinfo;     /* ref Xlib 6-17 */
+    int   dr, fa, fd;
+    short asc, desc, width;
+    int   height;
+
+    XTextExtents(theFont, str, strlen(str), &dr,&fa,&fd, &stringinfo);
+    asc   = stringinfo.ascent;          /* max of char ascents in string */
+    desc  = stringinfo.descent;         /* max of char descents in string */
+    width = stringinfo.width;           /* sum of char widths across string */
+    height = asc+desc;                  /* max height over all chars  */
+    return height;
+}
+
+
+/****************************************************************************
+	Misc routines.
+****************************************************************************/
+/* Plot a dot at data coord (x,y). Dotsize=0,1,2,3,.., and size 0 is empty */
+Dot(w,x,y,dotsize)
+Window w;
+float  x,y;
+int    dotsize;
+{
+    int d, X,Y;
+
+    if ((d=dotsize-1) >= 0) {
+	if (d==0)           /* dotsize = 1 */
+	    Point(w, x,y);
+	else {              /* dotsize > 1 */
+	    for (X=(-d) ; X<=d ; X++)
+		for (Y=(-d) ; Y<=d ; Y++)
+		    XDrawPoint(theDisplay,w,theGC,px(x)+X,py(y)+Y);
+	}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/x11coord.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,520 @@
+/*
+	Still to consider:
+
+    A structure for a box-object, containing a complete set of internal
+    variables for one box. A routine could allocate a structure, call the
+    routines set_box_parameters() and set_data_parameters(), and return a ptr
+    to the structure. Now a set of #defines could take a structure pointer
+    (just as they currently often take a window ptr), and could call the
+    appropriate sub-routines using the internal variables for that box.
+    (The window could be a member of the structute too).
+
+    With this, you could easily maintain a set of boxes, and plot anything
+    in any of them. But if you need ore than one window, then you'll need a
+    window structure too, (to hold window parameters for each window).
+    For example:
+
+    struct st_window {
+	Window          w;
+	int             x,y;            window origin wrt display
+	unsigned int    width,height;   window size
+	GC              gc;
+    };
+
+    struct st_box {
+	struct st_window * pt;          parent window
+	char *fname;                    file name for data
+	int   n, s;                     num points and start point in file
+	...all system variables...
+    };
+
+*/
+
+
+/****************************************************************************
+
+    x11coord.h    A file for inclusion into X11 plotting programs.
+    ----------    (See x11test.c for example).
+
+ ****************************************************************************
+
+User parameters:
+================
+1. Window parameters - Set size and position of a window on the display.
+    set_window_parameters(xorg,yorg, width,height)
+    int   xorg,yorg       Window origin (pixel coords of top-left wrt Display).
+    int   width,height    Window size (pixels).
+
+2. Box parameters -    Set size and position of a box in a preset window.
+ a) set_box_parameters(xorg,yorg, width,height)
+    int   xorg,yorg       Box origin (pixel coords of bottom-left wrt window).
+    int   width,height    Box size (pixels).
+ b) set_bordered_box(bpc)
+    int   bpc             Box border (constant width) as %age of window size.
+
+3. Data parameters -   Set area and location of data space to appear in box.
+    set_data_parameters(xp0,yp0, xd0,yd0, xrange,yrange)
+    int   xp0,yp0         Plot origin (as a %age of box size from box origin).
+    float xd0,yd0         Data origin (data coords to appear under plot origin).
+    float xrange,yrange   Data ranges (area of data space to appear under plot).
+
+Notes:
+1. Pixel coordinates and sizes are ints. Data coordinates and sizes are floats.
+2. Pixel coords refer to the X11 coord system which has origin (0,0) in the
+   top-left of each window. Data coords refer to the user coord system which
+   has its origin (0,0) in the bottom-left of each box.
+3. The parameter initialization routines must be called in order, (window,
+   box, data), and must be done first, otherwise macros which use the system
+   variables will not work. As a minimum, you MUST do set_window_parameters(),
+   and this will give you a box the same size as the window, with origin in
+   the bottom-left, with data origin at the box origin, and data ranges the
+   same as pixels.
+4. Although its true that set_window_parameters only sets window pixel sizes,
+   set_box_parameters only sets box pixel sizes, and set_data_parameters only
+   sets data sizes, the data sizes are somewhat dependent upon the pixel
+   sizes, and so if you change the window or box parameters during a program,
+   (eg, to resize a box), then you must re-initialize set_data_parameters at
+   the same time. (Call it again with the same initial arguments; it will
+   re-initialize internal parameters).
+
+User routines and macros:
+=========================
+Set system private parameters.
+-----------------------------
+	      set_window_parameters(xorg,yorg, width,height)
+	      set_box_parameters(xorg,yorg, width,height)
+	      set_bordered_box(bpc)
+	      set_data_parameters(xp0,yp0, xd0,yd0, xrange,yrange)
+Open connection and create window.
+---------------------------------
+	      xopen()
+Window        xcreate(name, event_mask)
+Convert coordinates.
+-------------------
+int           px(x)
+int           py(y)
+float         xp(p)
+float         yp(p)
+float         xpc(pc)
+float         ypc(pc)
+Return pixel coordinates.
+-----------------------
+int           pleft()
+int           pright()
+int           pbottom()
+int           ptop()
+int           pwidth()
+int           pheight()
+Return data coordinates.
+-----------------------
+float         xleft()
+float         xright()
+float         ybottom()
+float         ytop()
+float         xwidth()
+float         yheight()
+float         xcentre()
+float         ycentre()
+float         Xjitter(x,p)
+float         Yjitter(y,p)
+Test data coordinates.
+---------------------
+bool          Xinbox(x)
+bool          Yinbox(y)
+bool          inbox(x,y)
+Draw and calibrate boxes and axes.
+---------------------------------
+	      draw_Xaxis(w,yval)
+	      calibrate_Xaxis(w,yval)
+	      draw_Yaxis(w,xval)
+	      calibrate_Yaxis(w,xval)
+	      draw_box(w)
+	      calibrate_box(w)
+	      draw_calibrated_box(w)
+Draw points, lines, and strings, etc..
+-------------------------------------
+	      setLinewidth(width)
+	      Point(w,x,y)
+	      xPoint(w,x,y)
+	      Line(w,x1,y1,x2,y2)
+	      xLine(w,x1,y1,x2,y2)
+	      String(w,x,y,string)
+	      xString(w,x,y,string)
+	      Cross(w,x,y)
+	      xCross(w,x,y)
+	      Dot(w,x,y,dotsize)
+	      xDot(w,x,y,dotsize)
+Text string parameters.
+-----------------------
+	      setFont("fontname")
+int           nlines()
+int           ncols()
+Return pixel sizes based on current "theFont".
+----------------------------------------------
+int           max_charwidth()
+int           max_charheight()
+int           stringwidth(string)
+int           stringheight(string)
+int           linespacing()             white space between lines.
+int           lineheight()              total line (y-value) increment.
+int           colwidth()                total character (x-value) increment.
+int           margin()                  white space at sides of page.
+int           headroom()                white space at head and foot of page.
+Return pixel coordinates.
+-------------------------
+int           leftmargin()
+int           rightmargin()
+int           topmargin()
+int           bottommargin()
+int           line(i)
+int           col(j)
+Draw text strings.
+------------------
+	      topline(w,string)
+	      bottomline(w,string)
+	      lineString(w,string,i,j)
+	      leftString(w,string,i)
+	      rightString(w,string,i)
+	      centreString(w,string,i)
+	      supertopline(w,string)
+
+
+Notes:
+1. The user routines conventionally take data coordinate arguments.
+   To convert pixel coordinates to data, use the xp,yp macros.
+
+Development of coord system scaling transformations:
+====================================================
+Internal variables (initialized by the `set' routines and used by the `px'
+macros) are pixel coords and sizes, and refer to the X11 coord system:
+
+		|    _Xp0       |
+		+---------------+
+		|               |
+
+		|          _Xp1             |
+		+---------------------------+
+		|                           |
+	    (0,0)
+   -+-    -+-   +-------------------------------------------+
+    |      |    |Window                                     |
+    |  _Yp1|    |                                           |
+    |      |    |                    _Wb                    |
+_Yp0|     -+-   |   (_Xp0,_Yp1) +-----------+ (_Xp1,_Yp1)   |
+    |           |               |Box        |               |
+    |           |               |           |_Hb            |
+    |           |               |           |               |
+   -+-          |   (_Xp0,_Yp0) +-----------+ (_Xp1,_Yp0)   |
+		|                                           |
+		|                                           |
+		|                                           |
+		+-------------------------------------------+
+
+Consider a box of width Wb pixels (on horizontal axis) and height Hb pixels
+(on vertical axis). Let this box size represent data ranges xrange and yrange,
+(corresponding to Wb and Hb respectively). Let the pixel origin and the data
+origin be superimposed at (0,0) in the bottom-left corner. Then a data coord
+(x,y) is transformed into a pixel coord by the scaling:
+    px(x) = x * Wb/xrange
+    py(y) = y * Hb/yrange
+
+If the data coordinate which we wish to appear at the plot origin is actually
+(xd0,yd0), then the data origin must be shifted off the pixel origin, so that
+the data coord (xd0,yd0) is represented by pixel coord (0,0). Hence:
+    px(x) = (x-xd0) * Wb/xrange
+    py(y) = (y-yd0) * Hb/yrange
+
+It is necessary to invert the y-axis so that pixel coords are consistent with
+the X11 coord system, (with pixel origin in the top-left of a window and pixel
+y-values which increase down the window). Let the box be positioned in the
+top-left corner of its parent window, so that the X11 origin corresponds with
+the top-left corner of the box. Then the y-axis is inverted by:
+    px(x) =      (x-xd0) * Wb/xrange
+    py(y) = Hb - (y-yd0) * Hb/yrange
+
+In general, the box will be positioned within its parent window as in the
+diagram above. The box is shifted into the window by an x-value Xp0 and a
+y-value Yp1, and these must be added to any pixel coordinate:
+    px(x) = Xp0      + (x-xd0) * Wb/xrange
+    py(y) = Yp1 + Hb - (y-yd0) * Hb/yrange
+
+Although Yp0 is the y-value at the bottom of the box, at its default origin,
+note that Yp0>Yp1, since y-values increase down the window in the X11 pixel
+coordinate system.
+Finally, we may want the user origin of the box to be somewhere other than the
+bottom-left corner, (Eg, scatter plots often have the user origin in the
+centre of the plot; time-waveform plot often have the origin half-way up the
+left side of the plot). To place the user origin at a pixel coordinate of
+(xshift,yshift), we add xshift and subtract yshift from the transformed pixel
+coordinates. (We subtract yshift since the transformed pixel coord is in the
+X11 coord system). So we have:
+    px(x) = Xp0      + xshift + (x-xd0) * Wb/xrange
+    py(y) = Yp1 + Hb - yshift - (y-yd0) * Hb/yrange
+
+Grouping terms we have:
+    px(x) = Xp0      + xshift - xd0*Wb/xrange + x*Wb/xrange
+    py(y) = Yp1 + Hb - yshift + yd0*Hb/yrange - y*Hb/yrange
+
+Now substituting:
+      xoffset = Xp0      + xshift - xd0*Wb/xrange ;     xscale = Wb/xrange
+      yoffset = Yp1 + Hb - yshift + yd0*Hb/yrange ;     yscale = Hb/yrange
+We have:
+    px(x) = xoffset + x * xscale
+    py(y) = yoffset - y * yscale
+
+The inverse transformations xp(p) and yp(p) are just the inverse of these.
+
+A typical program might be as follows:
+-------------------------------------
+	------------------------------------------------------------------
+       |#include <stdio.h>                                                |
+       |#include <math.h>                                                 |
+       |                                                                  |
+       |#include "x11coord.h"                                             |
+       |                                                                  |
+       |                                                                  |
+       |main()                                                            |
+       |{                                                                 |
+       |    Window w;                                                     |
+       |        .....                                                     |
+       |                                                                  |
+       |    set_window_parameters(100,85, 775,775);                       |
+       |    set_bordered_box(10);                                         |
+       |    set_data_parameters(50,50, 0,0, 2.0,2.0);                     |
+       |                                                                  |
+       |    xopen();                                                      |
+       |    w = xcreate("test", ButtonPressMask | ExposureMask);          |
+       |    xevent_monitor(w);                                            |
+       |}                                                                 |
+       |                                                                  |
+       |                                                                  |
+       |xevent_monitor(w)                                                 |
+       |Window w;                                                         |
+       |{                                                                 |
+       |    XEvent event;                                                 |
+       |                                                                  |
+       |    for ( ; ; ) {                                                 |
+       |        XNextEvent(theDisplay,&event);                            |
+       |        switch (event.type) {                                     |
+       |            ....                                                  |
+       |            case ButtonPress:                                     |
+       |                switch(event.xbutton.button) {                    |
+       |                    case Button1:                                 |
+       |                        XDestroyWindow(theDisplay,w);             |
+       |                        return;                                   |
+       |                    case Button2:                                 |
+       |                        ....                                      |
+       |                }                                                 |
+       |                break;                                            |
+       |            case Expose:                                          |
+       |                if (event.xexpose.count == 0) {                   |
+       |                    draw_calibrated_box(w);                       |
+       |                    plot(w);                                      |
+       |                }                                                 |
+       |                break;                                            |
+       |            ....                                                  |
+       |        }                                                         |
+       |    }                                                             |
+       |}                                                                 |
+       |                                                                  |
+	------------------------------------------------------------------
+The purpose of the xevent_monitor is to loop endlessly and keep the program
+running while the window is displayed. The window vanishes when the monitor
+is quit using (in this example) the left mouse button.
+Note that you let all plotting routines be called when an expose-event has
+been caught. This is not just so that the screen re-draws itself when exposed,
+but also to avoid data at the start of the plot going missing.
+If you don't set up for expose-events, but try to plot data as soon as the
+window is created, then it turns out that you tend to lose the first few bytes
+of plot data. The correct way is to plot data when the window is exposed.
+The window-creation and mapping process generates an expose event
+automatically and, when caught by the event monitor, this causes the window to
+be first plotted.
+
+
+*****************************************************************************/
+#include <X11/X.h>      /*  /usr/include/X11/X.h     */
+#include <X11/Xlib.h>   /*  /usr/include/X11/Xlib.h  */
+
+
+static char defFontString[] = "fixed" ,  *theFontString = defFontString ;
+
+
+/****************************************************************************
+*       Defaults for some standard window sizes
+****************************************************************************/
+#define FULLXORG          5     /* Full screen size */
+#define FULLYORG         90
+#define FULLWIDTH      1000
+#define FULLHEIGHT      750
+
+#define A4XORG          190     /* A4 size */
+#define A4YORG           85
+#define A4WIDTH         620
+#define A4HEIGHT        760
+
+#define PLOTXORG        100     /* Rectangular plotting area */
+#define PLOTYORG        155
+#define PLOTWIDTH       800
+#define PLOTHEIGHT      600
+
+#define BOXXORG         100     /* Square box */
+#define BOXYORG          85
+#define BOXWIDTH        775
+#define BOXHEIGHT       775
+
+/****************************************************************************
+*       Macros for pixel-data transformation
+****************************************************************************/
+/* pixel coord from data coord */
+#define px(x)           ( (int)(_xoffset + (x) * _xscale) )
+#define py(y)           ( (int)(_yoffset - (y) * _yscale) )
+/* data coord from pixel coord */
+#define xp(p)           ( (float)(((p) - _xoffset) / _xscale) )
+#define yp(p)           ( (float)((_yoffset - (p)) / _yscale) )
+/* data coord from a %age of data range */
+#define xpc(pc)         ( ((xleft()+xright())*pc) / 100 )
+#define ypc(pc)         ( ((ybottom()+ytop())*pc) / 100 )
+/* data coord of box centre */
+#define xcentre()       xpc(50)
+#define ycentre()       ypc(50)
+/* pixel limits of box (note that ptop() < pbottom() ). */
+#define pleft()         (_Xp0)
+#define pright()        (_Xp1)
+#define pbottom()       (_Yp0)
+#define ptop()          (_Yp1)
+#define pwidth()        (_Wb)
+#define pheight()       (_Hb)
+/* data limits of box */
+#define xleft()         xp(_Xp0)
+#define xright()        xp(_Xp1)
+#define ybottom()       yp(_Yp0)
+#define ytop()          yp(_Yp1)
+#define xwidth()        xp(_Wb)
+#define yheight()       yp(_Hb)
+/* test if data argument is in box */
+#define Xinbox(x)       ( (xleft()<=x && x<=xright()) ? 1 : 0 )
+#define Yinbox(y)       ( (ybottom()<=y && y<=ytop()) ? 1 : 0 )
+#define inbox(x,y)      ( (Xinbox(x) && Yinbox(y)) ? 1 : 0 )
+/* jitter data value (ie move by a given pixel distance) */
+#define Xjitter(x,p)    ( xp(px(x)+(p)) )
+#define Yjitter(y,p)    ( yp(py(y)+(p)) )
+
+/****************************************************************************
+*       Macros for routines (using preset system parameters)
+****************************************************************************/
+/* Xaxes: yval is a data value at which to place a horizontal axis.        */
+/* For example: 0 (zero line), ybottom() (box-bottom), ytop() (box-top).   */
+#define draw_Xaxis(w,yval)      if (Yinbox(yval)) axis(w, _Xp0,_Xp1, py(yval),'x')
+#define calibrate_Xaxis(w,yval) calibrate_Axis(w, _Xp0,_Xp1, _Xd0,_Xd1, py(yval),'x')
+
+/* Yaxes: xval is a data value at which to place a vertical axis.          */
+/* For example: 0 (zero line), xleft() (box-left), xright() (box-right).   */
+#define draw_Yaxis(w,xval)      if (Xinbox(xval)) axis(w, _Yp0,_Yp1, px(xval),'y')
+#define calibrate_Yaxis(w,xval) calibrate_Axis(w, _Yp0,_Yp1, _Yd0,_Yd1, px(xval),'y')
+
+#define draw_box(w)             box(w, _Xp0,_Yp0, _Xp1,_Yp1)
+#define calibrate_box(w)        calibrate_Box(w, _Xp0,_Yp0, _Xp1,_Yp1, _Xd0,_Yd0, _Xd1,_Yd1)
+#define draw_calibrated_box(w)  draw_box(w); calibrate_box(w)
+
+#define xcreate(name,mask)      xCreate(name,mask, _xorg,_yorg, _width,_height)
+
+/****************************************************************************
+*       Macros for standard X11 commands
+****************************************************************************/
+#define Point(w,x,y)            XDrawPoint(theDisplay,w,theGC,px(x),py(y))
+#define Line(w,x1,y1,x2,y2)     XDrawLine(theDisplay,w,theGC,px(x1),py(y1),px(x2),py(y2))
+#define String(w,x,y,string)    XDrawString(theDisplay, w, theGC, px(x),py(y), string, strlen(string))
+
+#define Cross(w,x,y)            XDrawLine(theDisplay,w,theGC,px(x)-10,py(y),px(x)+10,py(y)); XDrawLine(theDisplay,w,theGC,px(x),py(y)-10,px(x),py(y)+10)
+
+#define xPoint(w,x,y)           if (inbox(x,y)) Point(w,x,y)
+#define xLine(w,x1,y1,x2,y2)    if (inbox(x1,y1) && inbox(x2,y2)) Line(w,x1,y1,x2,y2)
+#define xString(w,x,y,string)   if (inbox(x,y)) String(w,x,y,string)
+
+#define xCross(w,x,y)           if (inbox(x,y)) Cross(w,x,y)
+#define xDot(w,x,y,dotsize)     if (inbox(x,y)) Dot(w,x,y,dotsize)
+
+/* Max width and height (pixels) of chars in current font, (ref 6-17, 6-19) */
+#define max_charwidth()         ( theFont->max_bounds.rbearing - theFont->min_bounds.lbearing )
+#define max_charheight()        ( theFont->max_bounds.ascent + theFont->max_bounds.descent )
+/* Number of lines and cols (chars) of current font which fit into box */
+#define linespacing()           ( (theFont->max_bounds.descent)>>1 )
+#define lineheight()            ( max_charheight()+linespacing() )
+#define colwidth()              ( max_charwidth() )
+#define nlines()                ( pheight() / lineheight() )
+#define ncols()                 ( pwidth() / colwidth() )
+#define topline(w,string)       lineString(w,string,1,1)
+#define bottomline(w,string)    lineString(w,string,nlines(),1)
+#define margin()                ( theFont->max_bounds.lbearing + theFont->max_bounds.rbearing )
+#define headroom()              ( theFont->max_bounds.ascent )
+#define leftmargin()            ( pleft() + margin() )
+#define rightmargin()           ( pright() - margin() )
+#define topmargin()             ( ptop() + headroom() )
+#define bottommargin()          ( pbottom() - headroom() )
+#define line(i)                 ( topmargin() + (i-1)*lineheight() )
+#define col(j)                  ( leftmargin() + (j-1)*colwidth() )
+#define lineString(w,string,i,j) ( XDrawString(theDisplay,w,theGC,col(j),line(i),string,strlen(string)) )
+#define leftString(w,string,i)   ( XDrawString(theDisplay,w,theGC,leftmargin(),line(i),string,strlen(string)) )
+#define rightString(w,string,i)  ( XDrawString(theDisplay,w,theGC,rightmargin()-stringwidth(string),line(i),string,strlen(string)) )
+#define centreString(w,string,i) ( XDrawString(theDisplay,w,theGC,(pwidth()-stringwidth(string))>>1,line(i),string,strlen(string)) )
+#define supertopline(w,string)   ( XDrawString(theDisplay,w,theGC,col(1),ptop()-max_charheight()-headroom(),string,strlen(string)) )
+
+
+/****************************************************************************
+*       Window parameters   (X11-specific).
+****************************************************************************/
+Display        *theDisplay;
+int             theScreen;        /* screen_number */
+int             theWidth;         /* horizontal size, in pixels */
+int             theHeight;        /* vertical size, in pixels */
+unsigned long   theForeground;    /* lines, text, and border pixel value */
+unsigned long   theBackground;    /* background pixel value */
+GC              theGC;            /* graphics context */
+XFontStruct    *theFont;          /* current font used to print text */
+unsigned long   theBlack;         /* pixel value for black */
+unsigned long   theWhite;         /* pixel value for white */
+
+/****************************************************************************
+*       System (global) variables
+*****************************************************************************/
+int     _xorg,  _yorg;  /* Window origin (pixel coords top-left wrt Display)*/
+int     _width, _height;/* Window size (pixels).                            */
+
+int     _Xp0,   _Yp0;   /* Box origin (pixel coords at bottom-left)         */
+int     _Xp1,   _Yp1;   /* Box limits (pixel coords at top-right)           */
+int     _Wb,    _Hb;    /* Box size (pixels).                               */
+
+float   _Xd0,   _Yd0;   /* Box origin (data coords at bottom-left)          */
+float   _Xd1,   _Yd1;   /* Box limits (data coords at top-right)            */
+float   _xrange,_yrange;/* Box size (data ranges).                          */
+
+int     _xshift,_yshift;/* Plot origin (pixel coords from box origin)       */
+float   _xd0,   _yd0;   /* Data coords fixed at plot origin                 */
+
+float   _xoffset,_yoffset;
+float   _xscale, _yscale;
+
+/****************************************************************************
+*       Functions (in x11coord.c)
+*****************************************************************************/
+extern                  set_window_parameters();
+extern                  set_box_parameters();
+extern                  set_bordered_box();
+extern                  set_data_parameters();
+extern                  xopen();
+extern  GC              initGC();
+extern                  setLinewidth();
+extern                  setFont();
+extern  Window          xCreate();
+extern                  axis();
+extern                  box();
+extern                  calibrate_Axis();
+extern                  calibrate_Box();
+extern                  plotX();
+extern                  plotY();
+extern  int             stringwidth();
+extern  int             stringheight();
+extern                  calibrate();
+extern                  Dot();
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/x11fonts.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,246 @@
+/*
+    List font names in font style.
+
+    Usage: x11fonts  [options]  name_pattern
+
+    To enter name_patterns with wildcards, use forward quote,
+    (eg. x11fonts 'vt*' finds all font names beginning with vt).
+
+    Option -l      = list font names
+    Default option = display font names (X11).
+
+    The display format is:   "i/n  fontname"
+      where the displayed name is the i'th out of n names which match the
+      given name_pattern.
+    The name is displayed at the current cursor position.
+
+    The centre mouse button gets the next fontname in the list.
+    The left button exits.
+    The right button clears the display screen.
+*/
+
+#include <stdio.h>
+#include <math.h>
+#include "x11coord.h"
+
+#define FONTNAME_SIZE   256
+
+char printlist=0;
+char printcount=0;
+char printpath=0;
+
+char **list = (char **)0 ;
+char **pattern = (char **)0 ;
+int    num_patterns ;
+
+int  prompt_height ;
+int  Y0 = 0 ;
+int  Y = 0 ;
+
+char prompt[FONTNAME_SIZE] ;
+
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    Window w;
+    int    i, j, n;
+
+    /* Search args list while args are single chars to prevent fontnames */
+    /* which start with a `-' from being interpreted as args             */
+
+    while ( --argc > 0 && **++argv == '-' && strlen( *argv ) < 3 )
+	switch (*++*argv) {
+	    case 'l': ++printlist;         break;
+	    case 'n': ++printcount;        break;
+	    case 'P': ++printpath;         break;
+	    case 'h':
+	    case 'H': help();
+	}
+
+    if ( argc == 0 ) num_patterns = 1    ;
+    else             num_patterns = argc ;
+
+    pattern = (char **)malloc( num_patterns * sizeof(char *) ) ;
+    for ( i=0  ; i < num_patterns ; i++ )
+	pattern[i] = (char *)malloc( FONTNAME_SIZE * sizeof(char) ) ;
+
+    if ( argc == 0 )
+	sprintf( pattern[0], "*\0" );
+    else
+	for ( i=0  ; i < num_patterns ; i++ )
+	    sprintf( pattern[i], "%s\0", *argv++ ) ;
+
+
+    set_window_parameters(BOXXORG,BOXYORG, BOXWIDTH,BOXHEIGHT);
+    xopen();
+
+    if ( printpath ) {
+	list = XGetFontPath( theDisplay, &n ) ;
+	for ( j=0  ; j < n ; j++ )
+	    printf("%s\n", list[j]);
+	XFreeFontPath( list ) ;
+	exit( 0 ) ;
+    }
+
+    if ( printcount || printlist ) {
+	for ( i=0  ; i < num_patterns ; i++ ) {
+	    list = XListFonts(theDisplay, pattern[i], 1000, &n);
+	    if (n>0) {
+		if ( printcount )
+		    printf("%d of %s\n", n, pattern[i]);
+		else if ( printlist )
+		    for ( j=0 ; j < n ; j++ )
+			printf("%3d  %s\n", j+1, list[j]);
+	    }
+	    else
+		fprintf(stderr, "no font names found to match pattern = %s\n", pattern[i] ) ;
+
+	    XFreeFontNames(list);
+	}
+	exit( 0 ) ;
+    }
+
+    if ( setFont( theFontString ) == NULL ) {
+	fprintf( stderr,"x11fonts: no prompts as can't load default font \"%s\"\n", theFontString ) ;
+	prompt_height = 0 ;
+    }
+    else
+	prompt_height = line(1) ;
+
+    w = xcreate("fonts", ButtonPressMask | ExposureMask);
+    xevent_monitor(w);
+
+    if ( list != (char **)0 ) XFreeFontNames(list);
+    XCloseDisplay( theDisplay ) ;
+}
+
+
+xevent_monitor(w)
+Window w;
+{
+    XEvent event;
+    int    n, i = 0, j = 0 ;
+
+    for ( ; ; ) {
+	XNextEvent(theDisplay,&event); switch (event.type) {
+	    case ButtonPress:
+		switch(event.xbutton.button) {
+		    case Button1:               /* Left   */
+			Y = Y0 ;
+			if ( j < n ) {
+			    XClearArea( theDisplay, w, 0, Y+2*prompt_height, BOXWIDTH, BOXHEIGHT-Y, 0 ) ;
+			    print_alphabet(w, list, j++, n);
+			}
+			break ;
+		    case Button2:               /* Middle */
+			Y0 = Y ;
+			if (j<n) print_alphabet(w, list, j++, n);
+			break;
+		    case Button3:               /* Right  */
+			if ( ++i >= num_patterns ) return ;
+			j = 0 ;
+			if ( list != (char **)0 ) XFreeFontNames(list);
+			list = XListFonts(theDisplay, pattern[i], 1000, &n);
+			if ( prompt_height ) {
+			    setFont( theFontString ) ;
+			    XClearArea( theDisplay, w, 0, 0, BOXWIDTH, 2*prompt_height, 0 ) ;
+			    if ( n > 0 ) {
+				sprintf( prompt, "pattern  =  %s", pattern[i]);
+				topline(w,prompt);
+			    }
+			    else {
+				sprintf( prompt, "no font names found to match pattern  =  %s", pattern[i] ) ;
+				topline(w,prompt);
+			    }
+			}
+			break;
+		    default:
+			fprintf(stderr,"button %d not used\n", event.xbutton.button);
+		}
+		break;
+	    case Expose:
+		if ( event.xexpose.count == 0 ) {
+		    list = XListFonts(theDisplay, pattern[i], 1000, &n);
+		    if ( prompt_height ) {
+			setFont( theFontString ) ;
+			if (n>0) {
+			    sprintf( prompt, "pattern  =  %s", pattern[i]);
+			    topline(w,prompt);
+			}
+			else {
+			    sprintf( prompt, "no font names found to match pattern  =  %s", pattern[i] ) ;
+			    topline(w,prompt);
+			}
+		    }
+		    if ( n > 0 ) {
+			Y = Y0 ;
+			print_alphabet(w, list, j++, n);
+		    }
+		}
+		break;
+	    default:
+		fprintf(stderr,"event type %d not found\n", event.type);
+	}
+    }
+}
+
+
+
+char alphabet[] = "abcdefghijklmnopqrstuvwxyz\
+ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
+
+print_alphabet(w, fontlist, m, n)
+Window w;
+char **fontlist;
+int    m,n;
+{
+    int  i,j,k, x,y;
+    char str[128];
+
+    if ( prompt_height ) {
+
+	setFont( theFontString ) ;
+	sprintf(str, "[%d/%d]        %s", m+1, n, fontlist[m]);
+
+	Y += line(3) ;
+	XDrawString(theDisplay,w,theGC,0,Y,str,strlen(str)) ;
+
+	y = line(2);
+    }
+    else y = 0 ;
+
+    setFont( fontlist[m] );
+    if (y < line(2)) Y += line(2); /* set to start of larger font */
+    else             Y += y ;
+
+    y = Y ;
+    for (i=0, k=0 ; i<nlines() && k<62; i++) {
+	x = leftmargin();
+	for (j=0 ; j<(ncols())-1 && k<62; j++) {
+	    XDrawString(theDisplay, w, theGC, x,y, &alphabet[k++], 1);
+	    x += colwidth();
+	}
+	y += lineheight();
+    }
+    Y = y ;
+
+
+    if ( Y > BOXHEIGHT ) {
+	Y = Y0 = 0 ;
+	XClearArea( theDisplay, w, 0, 2*prompt_height, BOXWIDTH, BOXHEIGHT-prompt_height, 0 ) ;
+	print_alphabet(w, fontlist, m, n) ;
+    }
+}
+
+
+help()
+{
+    fprintf(stderr,"Usage: x11fonts  [options]  [name_patterns]\n");
+    fprintf(stderr,"(name_patterns containing wild-cards must be quoted. Default = \"*\") \n");
+    fprintf(stderr,"options: \n");
+    fprintf(stderr,"      -n      = print count of matching font names found in search path\n");
+    fprintf(stderr,"      -l      = list matching font names \n");
+    fprintf(stderr,"      -P      = print the current font search path\n");
+    exit(1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/x11gram.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,228 @@
+/****************************************************************************
+*
+*   compilation:    cc -o xgram xgram.c -lX11
+*
+*   "profile" is an array with an element for each pixel across the window.
+*
+****************************************************************************/
+
+#include <stdio.h>
+#include <math.h>
+#include "x11coord.h"
+
+char   DEFNAME[]=     "stdin";          /* window name */
+char   *name =        DEFNAME;
+
+/****************************************************************************
+*   Defaults for plot
+****************************************************************************/
+#define DEFn            128             /* number of data points on a plot line */
+#define DEFln           FULLWIDTH>>1    /* length of plot line in pixels */
+#define DEFl            1000            /* max number of lines to plot */
+#define DEFs            0               /* number of plot lines offset from start of file */
+#define DEFf            0.2             /* scale factor for plot y-values */
+
+#define DEFdx           2               /* origin increments for successive lines, in pixels */
+#define DEFdy           2
+
+/****************************************************************************
+*   Arguments
+****************************************************************************/
+int    s=DEFs;              /* start position in file */
+short  n=DEFn;              /* number of data points on a plot line */
+short  l=DEFl;              /* max number of lines to plot */
+short  ln=DEFln;            /* length of plot line in pixels */
+short  dx=DEFdx,dy=DEFdy;   /* increments for successive lines, in pixels */
+double f=DEFf;              /* scale factor for each y-value */
+
+/****************************************************************************
+*       main
+****************************************************************************/
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE   *fp, *fopen();
+    Window  w;
+    short   p;
+    int     i;
+
+
+    while (--argc > 0 && **++argv == '-')
+	switch (*++*argv) {
+	    case 'n':   n       = atoi(++*argv); break;
+	    case 'l':   l       = atoi(++*argv); break;
+	    case 's':   s       = atoi(++*argv); break;
+	    case 'f':   f      *= atof(++*argv); break;
+	    case 'x':   dx      = atoi(++*argv); break;
+	    case 'y':   dy      = atoi(++*argv); break;
+	    case 'h':
+	    case 'H':
+	    default:    help();
+	}
+    /* Open data file */
+    if (argc) {
+	name = *argv;
+	if ((fp = fopen(name, "r")) == NULL) {
+	    fprintf(stderr,"can't open %s\n", *argv);
+	    exit(1);
+	}
+    }
+    else fp = stdin;
+    /* Seek start of data in file */
+    if (s > 0) {
+	s *= n;         /* convert number of lines to number of points */
+	for (i=0 ; i<s && fread(&p, sizeof(short), 1, fp) ; i++)
+	    ;
+	if (i<s) error("seek overshot end-of-file\n");
+    }
+
+    set_window_parameters(FULLXORG,FULLYORG, FULLWIDTH,FULLHEIGHT);
+    set_bordered_box(1);
+
+    /** set data so that points fill window ?? **/
+
+    xopen();
+    w = xcreate(name, ButtonPressMask | ExposureMask);
+    xevent_monitor(w,fp);
+    fclose(fp);
+    XDestroyWindow(theDisplay,w);
+}
+
+
+/****************************************************************************
+*       X11 Event Monitor.
+****************************************************************************/
+xevent_monitor(w,fp)
+Window w;
+FILE *fp;
+{
+    XEvent event;
+
+    for ( ; ; ) {
+	XNextEvent(theDisplay,&event);
+	switch (event.type) {
+	    case ButtonPress:
+		switch(event.xbutton.button) {
+		    case Button1:   return;     /* Left   */
+		    case Button2:   return;     /* Middle */
+		    case Button3:   return;     /* Right  */
+		    default:
+			fprintf(stderr,"button %d not used\n", event.xbutton.button);
+		}
+		break;
+	    case Expose:
+		if (event.xexpose.count == 0) {
+		    draw_box(w);
+		    draw_gram(w,FULLWIDTH,FULLHEIGHT,fp);
+		}
+		break;
+	    default:
+		fprintf(stderr,"event type %d not found\n", event.type);
+	}
+    }
+}
+
+
+
+/****************************************************************************
+*       Draw line (spectro)-gram with hidden-line removal.
+****************************************************************************/
+#define     VISIBLE     0
+#define     HIDDEN      1
+#define     X0          10              /* origin of plot within window */
+#define     Y0          10
+#define     move(x,y)   X=x;Y=y
+#define     cont(x,y)   XDrawLine(theDisplay, w, theGC, X+X0,height-Y-Y0, x+X0,height-y-Y0);move(x,y)
+
+draw_gram(w,width,height,fp)
+Window w;
+int    width,height;    /* window size, in pixels */
+FILE   *fp;             /* i/p data file */
+{
+    int    i;
+    short  p, *profile;
+    short  X, Y;        /* current active position */
+    short  x, y, x0, y0, y1;
+    short  xorg=0, yorg=0;
+    float  index, res;
+    short  rres;
+    char   stat;
+
+    profile = (short*) malloc(width * sizeof(short));
+    for (i=0 ; i<width ; i++)
+	profile[i] = 0;
+
+    res = (float)ln/n;
+    rres = (int)(res+0.5);      /* rounded resolution */
+    /* plot l lines, or until eof */
+    while (l-->0 && fread(&p, sizeof(short), 1, fp)) {
+	/* draw vertical to start of line */
+	x = xorg;
+	y = yorg + p*f;
+	if (y >= (y0=profile[x])) {
+	    profile[x] = y;
+	    move(x,y0);
+	    cont(x,y);
+	    stat = VISIBLE;
+	}
+	else stat = HIDDEN;
+	y0 = y;
+
+	/* draw rest of line */
+	index = xorg;
+	for (i=1 ; i<n && fread(&p, sizeof(short), 1, fp) ; i++) {
+	    /* interpolate y-values for each pixel along line */
+	    for (x0=1, y1=yorg+p*f ; x0<=rres && x0+x<width ; x0++) {
+		y = (short)( ((float)x0/res) * (y1-y0) + y0 );
+		/* a Hidden line becomes Visible */
+		if (y >= profile[x+x0]) {
+		    profile[x+x0] = y;
+		    if (stat == HIDDEN) {
+			move(x+x0,y);
+			stat = VISIBLE;
+		    }
+		}
+		/* a Visible line becomes Hidden */
+		else {
+		    if (stat == VISIBLE) {
+			cont(x+x0,y);
+			stat = HIDDEN;
+		    }
+		}
+	    }
+	    y0 = y1;
+	    index += res;
+	    x = (int)(index+0.5);       /* rounded index */
+	    if (stat == VISIBLE)
+		cont(x,y);
+	}
+	cont(x,yorg);
+	xorg += dx;
+	yorg += dy;
+    }
+}
+
+
+/****************************************************************************
+*       Misc.
+****************************************************************************/
+error(s)
+{
+    fprintf(stderr,"%s",s);
+    exit(1);
+}
+
+help ()
+{
+    printf ("\nUsage: a) xgram  [options]  filename\n");
+    printf ("       b) cat filename  |  xgram  [options]\n");
+    printf ("    where filename is an input stream of 16-bit binary numbers\n");
+    printf ("Options:\n");
+    printf ("-n [int]      = Number of points per plotted line (default=%d).\n", DEFn);
+    printf ("-l [int]      = Max number of lines plotted (default=%d).\n", DEFl);
+    printf ("-s [int]      = Offset lines (of n points) from start of file (default=%d).\n", DEFs);
+    printf ("-f [float]    = Scale factor (default=1).\n");
+    printf ("-x-y[ints]    = dx/dy changes for successive lines (defaults %d,%d)\n", DEFdx,DEFdy);
+    exit (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/x11play.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,475 @@
+/****************************************************************************
+*
+*   x11play    -Animate successive plots of n points.
+		The points are read as binary shorts.
+*               Like x11plot, but plots successive blocks of n points
+*               on top of each other, rubbing out the previous plot, so
+*               as to form an "animated" sequence of plots.
+*
+*              -Help:  x11play -H
+*              -Usage, EG:
+*                      fft -n128 -o120 file | x11play -n64 -y0 -c5000
+*                      Quit program with left mouse button.
+*             -Step-mode
+*                      With a -S flag, single-step through frames using
+*                      the mouse as follows:
+*
+*                      left -   quit
+*                      centre - freeze animation (successive centre
+*                               buttons give single successive frames).
+*                      right  - continue animation
+*
+*                      Note: animation is slower in step-mode because
+*                      XSynchronise has to be on.
+****************************************************************************/
+#include <stdio.h>
+#include <math.h>
+#include "x11coord.h"
+
+/****************************************************************************
+*   Defaults
+****************************************************************************/
+#define UNSET        (-9999)
+
+#define DEFAMPL        1000
+#define DEFSCALE        256
+
+float   argXd0=UNSET,   argYd0=UNSET;
+float   argXd1=UNSET,   argYd1=UNSET;
+
+/****************************************************************************
+*   Input-file arguments
+****************************************************************************/
+int     n =      DEFSCALE;      /* num points to read from file */
+int     s =      0;             /* start position in file */
+short   summary= 0;             /* Flag for method of block summary in downsample */
+short   z =      1;             /* Flag for drawing zero line */
+short   stepmode=0;             /* Flag for single-step mode */
+short   overplot=0;             /* Flag for overplot mode */
+short   stepcount=0;
+char    DEFNAME[]="stdin";
+char    *name=DEFNAME;
+short   *data;
+XPoint  *points;
+
+FILE    *fp, *fopen();
+
+/****************************************************************************
+*       main
+*   The window is plotted when an expose event is (automatically) generated.
+*   The plotting routines are called from within the event monitor.
+****************************************************************************/
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    Window  w;
+    int     npoints;
+
+    while (--argc > 0 && **++argv == '-')
+	switch (*++*argv) {
+	    case 'n':   n       = atoi(++*argv); break;
+	    case 's':   s       = atoi(++*argv); break;
+	    case 'x':   argXd0  = atof(++*argv); break;
+	    case 'y':   argYd0  = atof(++*argv); break;
+	    case 'c':   argXd1  = atof(++*argv); break;
+	    case 'a':   argYd1  = atof(++*argv); break;
+	    case 'b':   summary = atoi(++*argv); break;
+	    case 'z':   z       = 0;             break;
+	    case 'S':   stepmode++;              break;
+	    case 'O':   overplot++;              break;
+	    case 'F':   theFontString = ++*argv; break;
+	    case 'H':
+	    default:    help();
+	}
+
+    if (argXd0==UNSET)  argXd0 = s;
+    if (argXd1==UNSET)  argXd1 = n;
+    else                argXd1 = argXd1-argXd0; /* ie, a range */
+    if (argYd0==UNSET) {
+	if (argYd1==UNSET)  argYd1 = 2*DEFAMPL;
+	else                argYd1 = 2*argYd1;
+	argYd0 = argYd1/2;
+    }
+    else {
+	if (argYd1==UNSET)  argYd1 = DEFAMPL+argYd0;
+	else                argYd1 = argYd1+argYd0;
+    }
+    argYd0 = (-argYd0);
+
+    if ((data = (short*) malloc(n * sizeof(short))) == NULL)
+	error("malloc out of space\n");
+    if ((points = (XPoint*)malloc(n * sizeof(XPoint))) == NULL)
+	error("malloc out of space\n");
+
+    if (argc) {
+	/* Open data file */
+	name = *argv;
+	if ((fp = fopen(name, "r")) == NULL) {
+	    fprintf(stderr,"can't open %s\n", *argv);
+	    exit(1);
+	}
+    }
+    else fp = stdin;
+
+    /* Seek start of data in file */
+    if (s > 0) seekstart(s,fp);
+
+    set_window_parameters(PLOTXORG,PLOTYORG, PLOTWIDTH,PLOTHEIGHT);
+    set_bordered_box(10);
+    set_data_parameters(0,0, argXd0,argYd0, argXd1,argYd1);
+    xopen();
+    xgc( 1, theFontString ) ;
+    w = xcreate(name, ButtonPressMask | ExposureMask);
+    init_xevent(w);
+}
+
+
+/****************************************************************************
+*   Seek s points from current position in stream.
+*   This general seek works even when fp is stdin, unlike fseek.
+****************************************************************************/
+seekstart(s,fp)
+int   s;
+FILE  *fp;
+{
+    int   i;
+    short p;
+
+    for (i=0 ; i<s && fread(&p, sizeof(short), 1, fp) ; i++)
+	;
+    if (i<s) error("seek overshot end-of-file\n");
+}
+
+
+/****************************************************************************
+*       X11 Event Monitor.
+*   The window is plotted when an expose event is (automatically) generated.
+*   This routine catches the initial expose event to first draw the window.
+*   After this, the xevent_monitor is called from upsample, which is called
+*   from draw_plot.
+****************************************************************************/
+init_xevent(w)  /* to catch initial expose event and draw first plot */
+Window w;
+{
+    XEvent event;
+
+    for ( ; ; ) {
+	XNextEvent(theDisplay,&event);
+	switch (event.type) {
+	    case ButtonPress:
+		switch(event.xbutton.button) {
+		    case Button1:           /* Left   */
+			XDestroyWindow(theDisplay,w);
+			exit(0);
+		    case Button2:           /* Middle */
+		    case Button3: break;    /* Right */
+		    default:
+			fprintf(stderr,"button %d not used\n", event.xbutton.button);
+		}
+		break;
+	    case Expose:
+		if (event.xexpose.count == 0) {
+		    draw_calibrated_box(w);
+		    draw_plot(w);
+		}
+		break;
+	    default:
+		fprintf(stderr,"event type %d not found\n", event.type);
+	}
+    }
+}
+
+
+xevent_monitor(w)
+Window w;
+{
+    XEvent event;
+    static short  wait=1;
+
+    if (!stepmode) wait=0;
+    do {
+	/* get next event provided one is on queue; don't wait otherwise */
+	if (wait || XEventsQueued(theDisplay,QueuedAlready) > 0) {
+	    XNextEvent(theDisplay,&event);
+	    switch (event.type) {
+		case ButtonPress:
+		    switch(event.xbutton.button) {
+			case Button1:               /* Left   */
+			    XDestroyWindow(theDisplay,w);
+			    exit(0);
+			case Button2: /* Middle */
+			    if (stepmode) {
+			       if (wait) single_shot(w,fp);
+			       else wait=1;
+			    }
+			    break;
+			case Button3: if (stepmode) wait=0; break;/* Right */
+			default:
+			    fprintf(stderr,"button %d not used\n", event.xbutton.button);
+		    }
+		    break;
+		default:
+		    fprintf(stderr,"event type %d not found\n", event.type);
+	    }
+	}
+    } while (wait);
+}
+
+
+/****************************************************************************
+*   Draw a calibrated box in a window and plot data inside it.
+****************************************************************************/
+draw_plot(w)
+Window  w;
+{
+    int i, npoints;
+
+    if (z) draw_Xaxis(w,0);     /* Draw zero line */
+    if (!overplot) XSetFunction(theDisplay,theGC,GXinvert);
+    if (stepmode) XSynchronize(theDisplay,True);
+    if (n <= pwidth()) npoints = upsample(w,fp);
+    else  fprintf(stderr,"successive downsampling not implemented yet!\n");
+    /*    npoints = downsample(w,fp);   */
+}
+
+
+/****************************************************************************
+*       Up and Down sampling.
+****************************************************************************/
+char stepcountstr[128];
+
+upsample (w,fp)
+Window  w;
+FILE   *fp;
+{
+    int    i, x, j=0;
+    int    lastx,lasty, X,Y;
+    short  y, notfirst=0;
+    float  res, incr, carry;
+
+    res = (float)pwidth()/(n-1);                /* resolution of plot */
+    incr = res;                                 /* x-value increment */
+    x = 0;                                      /* initial x-value */
+    while (fread(&y, sizeof(short), 1, fp)) {
+	if (stepmode) {
+	    if (stepcount > 0) supertopline(w,stepcountstr);
+	    sprintf(stepcountstr,"%d", ++stepcount);
+	    supertopline(w,stepcountstr);
+	}
+	lastx=pleft(); lasty=py(y);
+	carry = res - (int)res;
+	incr = res + carry;
+	x = (int)incr;
+	for (i=1 ; i<n  && fread(&y, sizeof(short), 1, fp) ; i++) {
+	    X = x+pleft();
+	    Y = py(y);
+	    /* Plot only inside y-limits of box */
+	    if (Y > pbottom()) Y = pbottom();
+	    if (Y < ptop())    Y = ptop();
+
+	    /* rub-out a segment of last plot */
+	    if (notfirst)
+		XDrawLine(theDisplay, w, theGC, points[i-1].x, points[i-1].y, points[i].x, points[i].y);
+	    else  notfirst=1;
+	    /* draw a new segment for current plot */
+	    XDrawLine(theDisplay, w, theGC, lastx, lasty, X, Y);
+
+	    points[i-1].x = lastx;
+	    points[i-1].y = lasty;
+	    lastx = X;
+	    lasty = Y;
+
+	    carry = incr - (int)incr;
+	    incr = res + carry;
+	    x += (int)incr;
+	}
+	points[i-1].x = lastx;
+	points[i-1].y = lasty;
+/*        if (XEventsQueued(theDisplay,QueuedAlready) > 0)      */
+	    xevent_monitor(w);
+    }
+}
+
+
+single_shot (w,fp)
+Window  w;
+FILE   *fp;
+{
+    int    i, x, j=0;
+    int    lastx,lasty, X,Y;
+    short  y, notfirst=0;
+    float  res, incr, carry;
+
+    res = (float)pwidth()/(n-1);                /* resolution of plot */
+    incr = res;                                 /* x-value increment */
+    x = 0;                                      /* initial x-value */
+    if (fread(&y, sizeof(short), 1, fp)) {
+	if (stepmode) {
+	    if (stepcount > 0) supertopline(w,stepcountstr);
+	    sprintf(stepcountstr,"%d", ++stepcount);
+	    supertopline(w,stepcountstr);
+	}
+	lastx=pleft(); lasty=py(y);
+	carry = res - (int)res;
+	incr = res + carry;
+	x = (int)incr;
+	for (i=1 ; i<n  && fread(&y, sizeof(short), 1, fp) ; i++) {
+	    X = x+pleft();
+	    Y = py(y);
+	    /* Plot only inside y-limits of box */
+	    if (Y > pbottom()) Y = pbottom();
+	    if (Y < ptop())    Y = ptop();
+
+	    /* rub-out a segment of last plot */
+	    if (notfirst)
+		XDrawLine(theDisplay, w, theGC, points[i-1].x, points[i-1].y, points[i].x, points[i].y);
+	    else  notfirst=1;
+	    /* draw a new segment for current plot */
+	    XDrawLine(theDisplay, w, theGC, lastx, lasty, X, Y);
+
+	    points[i-1].x = lastx;
+	    points[i-1].y = lasty;
+	    lastx = X;
+	    lasty = Y;
+
+	    carry = incr - (int)incr;
+	    incr = res + carry;
+	    x += (int)incr;
+	}
+	points[i-1].x = lastx;
+	points[i-1].y = lasty;
+    }
+}
+
+
+#define BLOCK   256
+float block;            /* for averaging in downsample */
+
+
+downsample (w,fp)
+Window  w;
+FILE   *fp;
+{
+    int   i, x, j = 0;
+    short y;
+    float rate;
+    float res;
+    float incr;
+    float carry;
+
+    rate = (float)n/pwidth();
+    if ((block = rate) >= BLOCK)
+	error ("excessive downsampling; re-define BLOCK\n");
+
+    res = (float)pwidth()/(n-1);                /* resolution of plot */
+    incr = res;                                 /* x-value increment */
+    x = 0;                                      /* initial x-value */
+    for (i=0 ; i<n ; i++) {
+	if (incr >= 1.0) {
+	    if (sample(&y, i, rate)) {
+		points[j].x = x+pleft();
+		points[j].y = py(y);
+
+		/* Plot only inside y-limits of box */
+		if (points[j].y > pbottom()) points[j].y = pbottom();
+		if (points[j].y < ptop())    points[j].y = ptop();
+		j++;
+	    }
+	}
+	carry = incr - (int)incr;
+	incr = res + carry;
+	x += (int)incr;
+    }
+    return j;
+}
+
+sample (y, i, rate)
+short  *y;
+int     i;
+float   rate;
+{
+    short average();
+    float carry;
+
+    if (block <= n-i) {
+	*y = average ((int)block, &data[i]);
+	carry = block - (int)block;
+	block = rate + carry;
+	return 1;
+    }
+    else
+	return 0;
+}
+
+/*
+short
+average (block, p)
+int block;
+short p[];
+{
+    int   i;
+    float sum = 0;
+
+    for (i = 0 ; i < block ; i++)
+	sum += p[i];
+    return (short)(sum / block);
+}
+*/
+
+short
+average (block, p)
+int block;
+short p[];
+{
+    int   i;
+    float sum = 0;
+    short MIN = 32000, MAX = 0;
+
+    for (i = 0 ; i < block ; i++) {
+	sum += p[i];
+	if (p[i] < MIN) MIN = p[i];
+	if (p[i] > MAX) MAX = p[i];
+    }
+    if (summary==0) {                   /* summary of block is largest extremal value */
+	if (MAX >= (-MIN)) return MAX;     /* summary of block is MAX value */
+	else               return MIN;     /* summary of block is MIN value */
+    }
+    if (summary == 1) return (p[0]);    /* summary of block is sample value */
+    return (short)(sum / block);        /* summary of block is mean value */
+}
+
+
+/****************************************************************************
+*       Miscellaneous
+****************************************************************************/
+error(s)
+{
+    fprintf(stderr,"%s",s);
+    exit(1);
+}
+
+
+help ()
+{
+    printf ("\nx11play: animated plot of sets of n points, read as binary shorts.\n");
+    printf ("Usage: a) x11play  [options]  filename\n");
+    printf ("       b) cat filename  |  x11play  [options]\n");
+    printf ("    where filename is an input stream of 16-bit binary numbers (shorts)\n");
+    printf ("Options:\n");
+    printf ("-n [int]      = Number of points plotted (default=%d).\n", DEFSCALE);
+    printf ("-s [int]      = Offset points from start of file (default=0).\n");
+    printf ("-a [float]    = Amplitude between zero-line and top of box (default=%d).\n", DEFAMPL);
+    printf ("-y [int]      = Amplitude between zero-line and bottom of box (default=a).\n");
+    printf ("-c [float]    = Calibration at right end of x-axis (default=n+s).\n");
+    printf ("-x [int]      = Calibration at left end of x-axis (default=s).\n");
+    printf ("-z            = Suppress zero-line.\n");
+    printf ("-b [0,1,2]    = Method of block summary for down-sampling.\n");
+    printf ("                0=MAX, 1=SAMPLE, 2=MEAN, (default=MAX).\n");
+    printf ("-S            = Step-mode, (centre-button=single-step, right-button=play).\n");
+    printf ("-O            = Over-plot successive plots of n points.\n");
+    printf ("-F [font]     = Font name (default=%s)\n", theFontString);
+    exit (0);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/x11plot.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,392 @@
+/****************************************************************************
+*
+*   x11plot  - a no-scale plot for X11 windows.   Mike Allerhand, March 1989.
+*               Also for overplotting multiple files.
+*
+*   usage:  x11plot [options] filename1 [filename2 ...]
+*       where filename is a stream of binary shorts.
+*       Alternatively, input can be piped, as in:
+*           cat filename | x11plot [options]
+*
+*   mouse:
+*       left button   = print pointer coordinates.
+*       centre button = re-draw plot (but not any printed coordinates).
+*       right button  = exit program (destroy windows).
+*
+****************************************************************************/
+#include <stdio.h>
+#include <math.h>
+#include "x11coord.h"
+
+
+/****************************************************************************
+*   Defaults
+****************************************************************************/
+#define UNSET        (-9999)
+
+#define DEFAMPL        1000
+#define DEFSCALE        256
+#define DEFSAMPLERATE 20000
+
+char    DEFUNITS[] = "p"  ;
+
+
+#define SAMPLES         0
+#define SECONDS         1
+#define MILLISECONDS    2
+
+int   xscale_units ;
+char *unitstr = DEFUNITS ;
+
+
+float   argXd0=UNSET,   argYd0=UNSET;
+float   argXd1=UNSET,   argYd1=UNSET;
+
+int     Yincr=0;        /* Increment y-origin for successive files */
+
+int     plotxorg   = PLOTXORG   ;
+int     plotyorg   = PLOTYORG   ;
+int     plotheight = PLOTHEIGHT ;
+int     plotwidth  = PLOTWIDTH  ;
+
+
+/****************************************************************************
+*   Input-file arguments
+****************************************************************************/
+int     m;                      /* num files to read */
+int     n;                      /* length read from file */
+int     s;                      /* start position in file */
+short   z = 1;                  /* Flag for drawing zero line */
+short   v = 1;                  /* Flag for calibrating box   */
+
+int     samplerate = DEFSAMPLERATE  ;
+
+short   **data    ;             /* data values for each file */
+XPoint  **point   ;             /* XPoints (pixel coords) for each file */
+int      *npoints ;             /* number of points actually read in from each file */
+
+/****************************************************************************
+*       main
+*   The window is plotted when an expose event is (automatically) generated.
+*   The plotting routines are called from within the event monitor.
+****************************************************************************/
+main(argc, argv)
+int   argc ;
+char *argv[] ;
+{
+    FILE   *fp, *fopen();
+    Window  w ;
+    float   n0=DEFSCALE, s0=0 ;
+    int     i ;
+
+    while (--argc > 0 && **++argv == '-')
+	switch (*++*argv) {
+	    case 'n':   n0      = atof(++*argv); break;
+	    case 's':   s0      = atof(++*argv); break;
+	    case 'y':   argYd0  = atof(++*argv); break;
+	    case 'a':   argYd1  = atof(++*argv); break;
+	    case 'z':   z       = 0;             break;
+	    case 'v':   v       = 0;             break;
+	    case 'Y':   Yincr   = atoi(++*argv); break;
+	    case 'S':   samplerate = atoi(++*argv); break;
+	    case 'u':   unitstr = ++*argv ;      break;
+	    case 'F':   theFontString = ++*argv ;   break;
+	    case 'H':
+	    default:    help();
+	}
+
+    if (argc==0) m=1;       /* 1 file from stdin.     */
+    else         m=argc;    /* m files given as args. */
+
+    if ( strcmp( unitstr, "p" ) == 0 )       xscale_units = SAMPLES ;
+    else if ( strcmp( unitstr, "s" ) == 0 )  xscale_units = SECONDS ;
+    else if ( strcmp( unitstr, "ms" ) == 0 ) xscale_units = MILLISECONDS ;
+    else {
+	fprintf( stderr, "x11plot: unknown x-axis units\n" );
+	exit( 1 );
+    }
+
+    n = to_samples( n0 ) ;
+    s = to_samples( s0 ) ;
+
+
+    /* Allocate a data and an XPoint matrix for m files, each of n points */
+    if ( (data    = (short  **) malloc(m * sizeof(short  *)) ) == NULL ||
+	 (point   = (XPoint **) malloc(m * sizeof(XPoint *)) ) == NULL ||
+	 (npoints = (int     *) malloc(m * sizeof( int    )) ) == NULL    ) {
+	fprintf( stderr, "x11plot: malloc out of space\n");
+	exit( 1 ) ;
+    }
+
+    /* For each of m files ... */
+    for ( i=0 ; i<m ; i++, argv++ ) {
+
+	/* Allocate space for data and XPoints */
+	if ( (data[i]  = (short  *) malloc(n * sizeof(short )) ) == NULL ||
+	     (point[i] = (XPoint *) malloc(n * sizeof(XPoint)) ) == NULL    ) {
+	    fprintf( stderr,"x11plot: malloc out of space\n");
+	    exit( 1 ) ;
+	}
+
+	/* Open file, seek start of data in file and read data in*/
+	if (argc==0) fp=stdin;
+	else  if ((fp = fopen(*argv, "r")) == NULL) {
+		fprintf(stderr,"can't open %s\n", *argv);
+		exit(1);
+	}
+	if (s > 0) seekstart(s,fp);
+
+	if ( ( npoints[i] = fread( data[i], sizeof(short), n, fp ) ) < n ) {
+	    if (argc==0)
+		fprintf(stderr,"Warning: %d points read from stdin.\n", npoints[i]);
+	    else
+		fprintf(stderr,"Warning: %d points read from input stream %s.\n", npoints[i], *argv);
+	}
+
+	fclose(fp);
+    }
+
+    /* Set argument defaults etc. */
+
+    if (argXd0==UNSET)  argXd0 = 0 ;
+    if (argXd1==UNSET)  argXd1 = (float) n ;
+
+    if (argYd0==UNSET) {
+	if (argYd1==UNSET)  argYd1 = 2*DEFAMPL;
+	else                argYd1 = 2*argYd1;
+	argYd0 = argYd1/2;
+    }
+    else {
+	if (argYd1==UNSET)  argYd1 = DEFAMPL+argYd0;
+	else                argYd1 = argYd1+argYd0;
+    }
+    argYd0 = (-argYd0);
+
+    mapwaves() ;
+    xopen();
+    xgc( 1, theFontString ) ;
+    w = xcreate("x11plot", ButtonPressMask | ExposureMask | StructureNotifyMask  ) ;
+
+    xevent_monitor(w);
+}
+
+
+/****************************************************************************
+*   Seek s points from current position in stream.
+*   This general seek works even when fp is stdin, unlike fseek.
+****************************************************************************/
+seekstart(s,fp)
+int   s;
+FILE  *fp;
+{
+    int   i;
+    short p;
+
+    for (i=0 ; i<s && fread(&p, sizeof(short), 1, fp) ; i++)
+	;
+    if (i<s) {
+	fprintf(stderr,"seek overshot end-of-file\n");
+	exit( 1 ) ;
+    }
+}
+
+
+/****************************************************************************
+*       X11 Event Monitor.
+*   The window is plotted when an expose event is (automatically) generated.
+*   The plotting routines are called from within the event monitor.
+****************************************************************************/
+xevent_monitor(w)
+Window w;
+{
+    XEvent event;
+    XWindowAttributes attribs ;
+
+    for ( ; ; ) {
+	XNextEvent(theDisplay,&event);
+	switch (event.type) {
+	    case ButtonPress:
+		switch(event.xbutton.button) {
+		    case Button1 :              /* Left   */
+			report(w, event);
+			break;
+		    case Button2 :              /* Centre */
+			clearplot( w, plotwidth, plotheight ) ;
+			drawwaves( w ) ;
+			break;
+		    case Button3 :              /* Right  */
+			XDestroyWindow(theDisplay,w);
+			return;
+		    default:
+			fprintf(stderr,"button %d not used\n", event.xbutton.button);
+		}
+		break;
+	    case ConfigureNotify :
+		plotwidth  = event.xconfigure.width  ;
+		plotheight = event.xconfigure.height ;
+		mapwaves() ;
+		clearplot( w, plotwidth, plotheight ) ;
+/*                drawwaves( w ) ;      */
+		break;
+	    case Expose:
+		if (event.xexpose.count == 0) {
+		    drawwaves( w ) ;
+		}
+		break;
+	}
+    }
+}
+
+
+
+/****************************************************************************
+*   Set the parameters for mapping data coords onto pixel coords.
+*   For each data file, map the data onto pixel coords in the corresponding
+*   XPoints array.
+****************************************************************************/
+mapwaves()
+{
+    int     i, j, n ;
+    short  *dat ;
+    XPoint *pix ;
+
+    set_window_parameters( plotxorg, plotyorg, plotwidth, plotheight );
+    set_bordered_box(10);
+    set_data_parameters(0,0, argXd0,argYd0, argXd1,argYd1);
+
+    for ( i = 0 ; i < m ; i++ ) {
+	dat = data[i]    ;
+	pix = point[i]   ;
+	n   = npoints[i] ;
+	for ( j = 0 ; j < n ; j++ ) {
+	    pix[j].x = px(j) ;
+	    if ( ( pix[j].y = py(dat[j]) ) > pbottom() ) pix[j].y = pbottom();
+	    else if ( pix[j].y < ptop() )                pix[j].y = ptop();
+	}
+	if ( Yincr > 0 ) /* Increment Y-origin for successive files (Y decreases upwards) */
+	    set_data_parameters(0,0, argXd0,argYd0-((i+1)*Yincr), argXd1,argYd1);
+    }
+
+    if ( Yincr > 0 ) /* Reset original values so that "report" works for first file */
+	set_data_parameters(0,0, argXd0,argYd0, argXd1,argYd1);
+}
+
+
+
+clearplot( w, width, height )   /* clear the plot window */
+Window w;
+int    width, height ;
+{
+    XClearArea( theDisplay, w, 0, 0, width, height, 0 ) ;
+}
+
+drawwaves( w )                  /* draw the mapped data for all files */
+Window w;
+{
+    int     i   ;
+
+    draw_box(w);
+    if (v) draw_calibration( w );
+    if (z) draw_Xaxis(w,0);     /* Draw zero line */
+
+    for ( i = 0 ; i < m ; i++ )
+	XDrawLines(theDisplay, w, theGC, point[i], npoints[i], CoordModeOrigin ) ;
+
+    XFlush(theDisplay);
+}
+
+
+draw_calibration( w )
+Window w ;
+{
+    float d0, d1 ;
+
+    switch ( xscale_units ) {
+	case SAMPLES      :     d0 = (float) s ;
+				d1 = d0 + (float) n ;
+				break ;
+	case SECONDS      :     d0 = (float) s / samplerate ;
+				d1 = d0 + (float) n / samplerate ;
+				break ;
+	case MILLISECONDS :     d0 = (float) s * 1000. / samplerate ;
+				d1 = d0 + (float) n * 1000. / samplerate ;
+				break ;
+    }
+
+    calibrate_Axis( w,  pleft(),pright(),  d0,d1,     pbottom(),  'x' ) ;
+    calibrate_Axis( w,  pbottom(),ptop(),  _Yd0,_Yd1, pleft(),    'y' ) ;
+}
+
+
+
+/****************************************************************************
+*       Report position of cursor on screen.
+****************************************************************************/
+report(w, event)
+Window  w;
+XEvent event;
+{
+    char  str[32];
+    int   x, y;                 /* pixel coords of cursor, wrt window origin */
+    int   X, Y;                 /* data system coords */
+    float xscale;
+    int   XCALIBSPACE = 100;    /* Space for calib value labels for X axis (ie in Y direction) */
+    int   YCALIBSPACE = 190;    /* Space for calib value labels for Y axis (ie in X direction) */
+
+    x = event.xbutton.x;
+    y = event.xbutton.y;
+    xscale = (float)pwidth()/n;
+/*    X = s + (x-Xp0)/xscale;   */   /* addition of s offset assumes time scale only */
+    X = xp(x);
+    Y = yp(y);
+    sprintf(str,"(%d,%d)", X, Y);
+    XDrawLine(theDisplay, w, theGC, x-10, y, x+10, y);
+    XDrawLine(theDisplay, w, theGC, x, y-10, x, y+10);
+    XDrawString(theDisplay, w, theGC, x+5, y-5, str, strlen(str));
+}
+
+
+/****************************************************************************
+*       Convert length to samples according to given xscale_units.
+****************************************************************************/
+
+to_samples( x )
+float x ;
+{
+    int  samples ;
+
+    switch ( xscale_units ) {
+	case SAMPLES      :     samples = x ;
+				break ;
+	case SECONDS      :     samples = x * samplerate  ;
+				break ;
+	case MILLISECONDS :     samples = x * samplerate * 0.001 ;
+				break ;
+    }
+    return samples ;
+}
+
+
+help ()
+{
+    printf ("\nx11plot: plot n points, read as binary shorts.\n");
+    printf ("Usage: a) x11plot  [options]  filename1  [filename2 ... ]\n");
+    printf ("       b) cat filename  |  x11plot  [options]\n");
+    printf ("    where filename is an input stream of 16-bit binary numbers (shorts)\n");
+    printf ("Options:\n");
+    printf ("-S [int]      = Samplerate in Hz (default 20000).\n");
+    printf ("-u [string]   = Units (s, ms, or default p (samples)).\n");
+    printf ("\n");
+    printf ("-n [int]      = Length plotted (default=%d samples).\n", DEFSCALE);
+    printf ("-s [int]      = Offset from start of file (default=0 samples).\n");
+    printf ("\n");
+    printf ("-a [float]    = Amplitude between zero-line and top of box (default=%d).\n", DEFAMPL);
+    printf ("-y [int]      = Amplitude between zero-line and bottom of box (default=a).\n");
+    printf ("-Y [int]      = Increment Y-origin for successive files (default=0).\n");
+    printf ("\n");
+    printf ("-v            = Suppress calibration.\n");
+    printf ("-z            = Suppress zero-line.\n");
+    printf ("-F [font]     = Font name (default=%s)\n", theFontString);
+    exit (0);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/bank_tl.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,499 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1994
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    bank_tl.c
+    ===========================================================
+
+    Design of cochlear transmission line filterbank (TLF) with
+    coupled outer ear and middle ear (EAR) filter.
+
+    Author        : Christian Giguere
+    First written : 01st April, 1991
+    Last edited   : 07th March, 1994
+    
+    Reference:
+    (1) C.Giguere and P.C.Woodland (1994). JASA 95(1): 331-342.
+    ===========================================================
+*/
+
+/***** includes *****/
+
+#include <math.h>
+#include <stdio.h>
+#include "stitch.h"
+#include "source.h"
+#include "calc.h"
+#include "calc_tl.h"
+#include "wdf_tl.h"
+#include "formulae.h"
+#include "formulae_tl.h"
+#include "scales.h"
+#include "scales_tl.h"
+#include "bank.h"
+#include "bank_tl.h"
+#include "ear.h"     
+#include "wdf_ear.h"
+     
+/***** defines *****/
+
+#if 0
+#define  _DEBUG_ 
+#endif
+
+#define   MIN_CF        (     16.0 )     /* Minimum BM segment CF allowed (Hz) */
+#define   MAX_CF        (  15000.0 )     /* Maximum BM segment CF allowed (Hz) */
+#define   REF_CF        (   1000.0 )     /* Reference CF (Hz) for scaling BM output and Q factor */
+#define   L             (      3.5 )     /* Length of BM (cm) */
+#define   MinLength     (   1.0E-6 )     /* Mininum length of each BM segment (cm) */
+#define   B0            (    0.015 )     /* BM width at basal end (cm) */
+#define   B_exp         (     0.30 )     /* Exponential constant for BM width (1/cm) */
+#define   A0            (     0.03 )     /* Cross-sectional area of each scala at basal end (cm2) */
+#define   A_exp         (    -0.60 )     /* Exponential constant for scalea cross-sectional area (1/cm) */
+#define   RHO_fluid     (      1.0 )     /* Density of cochlear fluids [g/cm3] */
+#define   MASS_PER_AREA (    0.015 )     /* Transerval mass per area of basilar membrane (g/cm2) */
+#define   Q_CHANNEL     (        0 )     /* Introduce channel-dependent Q factor */
+#define   RATIO         (     30.0 )     /* Transformer ratio between oval window and eardrum */
+#define   WARPING       (        0 )     /* Compensate frequency warping of bilinear transform */
+
+
+/***** externals */
+
+extern Source InterpSource() ;
+
+/***** functions *****/
+
+/**************************************************************************
+* name:                    function:
+*
+* tlf_bank_callback()      Callable procedure returning pointer to filtered
+*                          data (BM velocity or displacement).
+*
+* TLF_GenBank()            Set-up and initialization function for the design 
+*                          of the cochlear filterbank. Returns pointer to
+*                          a new source.  
+***************************************************************************/
+
+typedef struct _bank_segment  BankSegment ;
+
+struct _bank_segment {
+  double  center_frequency ;
+  double  seglength, position ;
+  int     active ;
+  } ;
+
+struct _tlf_bank_state {
+  struct           _fillable_source parent ;
+  Source           source ; 
+  Pointer          input ; 
+  int              inout_size ;
+  void             (*proc)(), (*closeEar)(), (*closeTLF)() ;
+  int              total_chans, display_chans ;
+  TLF_BankInfo     *bank ;
+  WDFilterState    **states ;
+  int              Ntube ;
+  WaveWDFstate     *wave_states ;
+  EartubeWDFstate  **eartube_states ;
+  EarmiddleWDFstate *earmiddle_states ;
+  } ;
+
+
+/************************* tlf_bank_callback() ****************************/
+
+static Pointer tlf_bank_callback( state, bytes, buffer )
+struct _tlf_bank_state *state ;
+ByteCount *bytes ;
+Pointer   buffer ;
+{
+    register TLF_BankInfo *bankInfo = state->bank ;
+    register int          last = *bytes == 0 ;
+    register int          points ;
+    register ByteCount    bytecount ;
+
+   /***** process *****/
+    if( !last ) {
+
+	points = *bytes * bankInfo->decimate_factor / 
+		 ( state->display_chans * state->inout_size ) ;
+
+	state->input = Pull( state->source, points * state->inout_size ) ;
+
+	state->proc( bankInfo, state->states, state->input, buffer, points, 
+		     state->total_chans, state->wave_states, state->eartube_states,
+		     state->earmiddle_states, state->Ntube ) ;
+
+	return ( buffer ) ;
+    }
+
+   /***** close *****/
+    else {
+
+	Pull( state->source, 0 ) ;
+	state->closeEar( state->wave_states, state->eartube_states, state->earmiddle_states, state->Ntube ) ;
+	state->closeTLF( state->states, state->total_chans, state->bank ) ;
+
+	return ( DeleteFillableSource( state ) ) ;  
+     }
+}
+
+
+/************************** TLF_GenBank() *****************************/
+
+Source TLF_GenBank( source, interps, info, chans, decimate_factor, samplerate, center_frequencies, 
+		    output_gain, outdens, qbase, OHC_gain, OHC_sat, motionstr, concha, canal )
+Source source ;
+int    interps, info, *chans, *decimate_factor ;
+double samplerate, *center_frequencies, output_gain, outdens ;
+double qbase, OHC_gain, OHC_sat ;
+char   *motionstr ;
+TubeInfo *concha, *canal ;
+{
+    DeclareNew( struct _tlf_bank_state *, state ) ;
+    BankSegment      **bankSeg, *segmentPointer, **GenerateBankSegments() ;
+    double           density, freq, scale_disp, scale_vel ;
+    double           qfactor, bn, xn, delta_xn, an, Lt, zov ;
+    double           length, diam, attn ;
+    Source           outputSource ;
+    int              chan, total_chans, segment, counter = 0 ;
+
+   /***** initialise input-related parameters *****/
+     state->inout_size = sizeof ( DataType ) ;
+     state->input  = ( char * ) 0 ;
+     state->source = source ;
+
+   /***** set WDF-TLF filterbank parameters *****/
+     density = DensityOnScale( ErbScale( center_frequencies[ 0 ]), ErbScale( center_frequencies[ *chans - 1]),
+			       *chans ) ;
+     if( density == 0. ) {
+	if( outdens <= 0. )
+	   density = 1. ;   /* arbitrary */
+	else
+	   density = outdens ;
+     }
+
+     if( interps > 0 )
+	interps = MIN( interps, ( int ) floor( log( ( double ) *chans ) / log( 2. ) ) ) ;
+
+     bankSeg = GenerateBankSegments( interps, samplerate, center_frequencies, &density, &outdens, 
+				     chans, &total_chans ) ;
+     state->display_chans = *chans ;
+     state->total_chans  = total_chans ;
+     state->states = NewArray( WDFilterState *, state->total_chans, "bank_tl.c for states" ) ;
+
+     if( info )
+        fprintf( stderr, "\nTLF filterbank information:\n" ) ; 
+
+     xn = bankSeg[0]->position ;    
+     delta_xn = bankSeg[0]->seglength ;    
+     Lt = -2. * RHO_fluid / ( A0 * A_exp ) * ( exp( -A_exp * L ) - exp( -A_exp * ( xn + delta_xn ) ) ) ;
+
+     for( chan = 0 ; chan < state->total_chans  ; chan++ ) {
+	  segmentPointer = bankSeg[ chan ] ;
+	  freq = segmentPointer->center_frequency ;
+	  xn = segmentPointer->position ;       
+	  delta_xn = MAX( segmentPointer->seglength, MinLength ) ;
+
+	/*** channel-dependent scalea cross-sectional area ***/
+	  an = A0 * exp( A_exp * xn ) ;        
+
+	/*** channel-dependent BM width ***/
+	  bn = B0 * exp( B_exp * xn ) ;
+
+	/*** channel-dependent Q-factor ***/
+	  if ( Q_CHANNEL != 0 )          
+	       qfactor = qbase * ( freq / REF_CF ) * ( Erb( REF_CF ) / Erb(freq) ) ;
+	  else
+	       qfactor = qbase ;
+
+	 /*** print filterbank configuration ***/
+          if( info ) {
+            counter += 1 * segmentPointer->active ;
+	    fprintf( stderr, "%3d -- active=%3d -- cf:%7.1f Hz =%6.2f ERBs -- x=%.3fcm  delta=%.3fcm  b=%.3fcm  A=%.3fcm2\n",
+		   state->total_chans - chan, counter * segmentPointer->active, freq, ErbScale( freq ), xn, delta_xn, bn, an ) ; 
+	  }
+
+	/*** scale output ***/
+	 scale_vel  = output_gain * FILTERBANK_SCALE ;
+	 scale_disp = TwoPi * REF_CF * scale_vel ;
+
+	/*** get filter states ***/
+	 state->states[ chan ] = WDFilter( samplerate, freq, scale_vel, scale_disp, RHO_fluid, an, bn, 
+					   qfactor, MASS_PER_AREA, delta_xn, Lt, WARPING, 
+					   segmentPointer->active, &zov, OHC_gain, OHC_sat ) ;
+
+	 Delete( segmentPointer ) ;
+     }
+   
+     Delete( bankSeg ) ;
+
+ 
+     /*** set parameters common to all channels ***/
+
+     state->bank = New( TLF_BankInfo * ) ;
+     state->bank->output_chans = state->display_chans ;
+
+     /* set decimation parameters */
+     state->bank->decimateCount = 0 ;
+     *decimate_factor = MAX( 1, *decimate_factor ) ;
+     state->bank->decimate_factor = *decimate_factor ;    
+    
+
+     /***** set output and nonlinearity variables, and filter procedure *****/
+
+     if( strncmp( motionstr, "velocity", 3 ) == 0 ) {
+	state->proc = DoWDFdataArray ;
+	state->bank->output_var = VELOCITY ;
+	state->bank->nl_var = DISPLACEMENT ;
+     }
+     else {
+	state->proc = DoWDFdataArray ;
+	state->bank->output_var = DISPLACEMENT ;
+	state->bank->nl_var = DISPLACEMENT ;
+     } 
+
+
+   /***** Set WDF-EAR filter design parameters *****/
+    state->wave_states = FreefieldWDF( samplerate, RHO_air, C, As, concha->diameter/2. ) ;
+
+    state->Ntube = concha->Nsegments + canal->Nsegments ;
+    state->eartube_states = NewArray( EartubeWDFstate *, state->Ntube, "ear.c for eartube states" ) ;
+
+    length = concha->length / concha->Nsegments ;
+    diam   = concha->diameter ;
+    attn   = concha->att_factor ;
+    for( segment = 0 ; segment < concha->Nsegments ; segment++ ) 
+	state->eartube_states[ segment ] = EartubeWDF( samplerate, RHO_air, C, diam, length, attn ) ;
+
+    length = canal->length / canal->Nsegments ;
+    diam   = canal->diameter ;
+    attn   = canal->att_factor ;
+    for( ; segment < state->Ntube ; segment++ ) 
+	state->eartube_states[ segment ] = EartubeWDF( samplerate, RHO_air, C, diam, length, attn ) ;
+
+    state->earmiddle_states = EarmiddleWDF( samplerate, zov, 1.0, RATIO ) ;
+
+
+   /***** specify procedures upon closing *****/
+    state->closeEar = CloseEarWDF ;
+    state->closeTLF = CloseWDF ;
+
+   /***** initialise output-related parameters and return *****/
+    outputSource = SetFillableSource( state, tlf_bank_callback, "bank_tl.c filter" ) ;
+
+    for( *chans = state->display_chans ; interps-- > 0 ; *chans = *chans * 2 - 1, density = density * 2. )
+	outputSource = InterpSource( outputSource, *chans ) ;
+
+    return ( outputSource ) ;
+}
+
+
+/************************** lower level functions *************************/
+
+BankSegment **GenerateBankSegments( interps, samplerate, display_frequencies, display_dens, 
+				    out_dens, display_chans, total_chans )
+int    interps ;
+double samplerate ;
+double *display_frequencies ;
+double *display_dens, *out_dens ;
+int    *display_chans, *total_chans ;
+{
+    BankSegment **bankSeg, *segmentPointer ;
+    double      min_cf, max_cf ;
+    double      apical_cf, basal_cf ;
+    double      *apical_frequencies, *basal_frequencies ;
+    double      apical_dens, basal_dens, central_dens ;
+    int         apical_chans, basal_chans, central_chans ;
+    int         ichan, chan ;
+    int         remainder ; 
+    double      cm_per_CB = GetERBscaling ( ) / 10. ;
+
+
+   /***** set number and density of central channels *****/
+    if( interps >= 0 ) {
+
+	central_chans = *display_chans = *display_chans >> interps ;
+	central_dens  = *display_dens  = ldexp( *display_dens, -interps ) ;
+	min_cf        = FofErbScale( ErbScale( display_frequencies[0] ) - 1. / central_dens ) ;      
+	max_cf        = display_frequencies[ ( central_chans - 1 ) << interps ] ;
+    }
+
+    else {
+	central_chans = *display_chans << -interps ;
+	central_dens  = ldexp( *display_dens, -interps ) ;
+	min_cf        = FofErbScale( ErbScale( display_frequencies[0] ) 
+				     - ( 1 << -interps ) / central_dens ) ;
+	max_cf        = display_frequencies[*display_chans - 1] ; 
+    }
+
+
+   /***** set number and density of apical and basal channels outside display range *****/ 
+
+    if( *out_dens <= 0. ) {
+
+	apical_cf = min_cf ;
+	apical_dens  = 0. ;
+	basal_cf = max_cf ;
+	basal_dens = 0. ;
+    }
+    else {
+	apical_cf = adjustCF( MIN_CF, samplerate ) ;
+	apical_dens = *out_dens ;
+	basal_cf  = adjustCF( MAX_CF, samplerate ) ;
+	basal_dens = *out_dens ;
+    }
+
+	apical_chans = 0 ;
+	basal_chans = 0 ;
+    
+
+   /***** generate apical and basal center frequencies outside display range *****/ 
+
+    apical_frequencies = GenerateFrequencies( apical_cf, min_cf, min_cf, &apical_dens, &apical_chans ) ;
+    basal_frequencies = GenerateFrequencies( max_cf, basal_cf, max_cf, &basal_dens, &basal_chans ) ;
+
+   /***** fill in array of BanKSegment structures with BM segment info *****/
+    *total_chans = apical_chans + central_chans + basal_chans - 2 ;   
+    bankSeg = NewArray( BankSegment *, *total_chans + 1, "tl_bank.c for segments" ) ;
+
+    ichan = 0 ;
+    for( chan = 1 ; chan < apical_chans ; chan++ ) {
+
+	 bankSeg[ ichan++ ] = segmentPointer = New( BankSegment * ) ; 
+	 segmentPointer->center_frequency = apical_frequencies[ chan ] ;
+	 segmentPointer->seglength = cm_per_CB / apical_dens ;  
+	 segmentPointer->position = L - cm_per_CB * ErbScale( segmentPointer->center_frequency ) ; 
+	 segmentPointer->active = 0 ;
+    }
+
+    for( chan = 0 ; chan < central_chans ; chan++ ) {
+
+	 bankSeg[ ichan++ ] = segmentPointer = New( BankSegment * ) ;         
+
+	 if( interps >= 0 ) {
+	     segmentPointer->center_frequency = display_frequencies[ chan << interps ] ;
+	     segmentPointer->active = 1 ;
+	 }
+	 else {
+	     remainder =  chan % ( 1 << -interps ) ;
+	     segmentPointer->center_frequency = FofErbScale( ErbScale( display_frequencies[ chan >> -interps ] )
+						+ ( remainder - ( 1 << -interps ) + 1 ) / central_dens ) ;
+	     segmentPointer->active = ( remainder == ( ( 1 << -interps ) - 1 ) ) ;
+	 }
+
+	 segmentPointer->seglength = cm_per_CB / central_dens ;  
+	 segmentPointer->position = L - cm_per_CB * ErbScale( segmentPointer->center_frequency ) ; 
+    }
+
+
+    for( chan = 1 ; chan < basal_chans ;  chan++ ) {
+
+	 bankSeg[ ichan++ ] = segmentPointer = New( BankSegment * ) ;
+	 segmentPointer->center_frequency = basal_frequencies[ chan ] ;
+	 segmentPointer->seglength = cm_per_CB / basal_dens ;  
+	 segmentPointer->position = L - cm_per_CB * ErbScale( segmentPointer->center_frequency ) ; 
+	 segmentPointer->active = 0 ;
+    }
+
+    segmentPointer = bankSeg[ 0 ] ;
+    if( ( segmentPointer->position + segmentPointer->seglength ) > L ) 
+	segmentPointer->seglength = L - MIN( L, segmentPointer->position ) ;
+
+   /***** return and deallocate dynamic memory *****/
+    Delete( apical_frequencies ) ;
+    Delete(  basal_frequencies ) ;
+
+    return( bankSeg ) ;
+}
+
+
+double *GenerateFrequencies( min_cf, max_cf, base_cf, density, channels )
+double  min_cf, max_cf, base_cf ;
+double  *density ;
+int     *channels ;
+{
+    double freq, *frequencies ;
+
+   /*** map characteristic frequencies onto specified scale ***/ 
+    min_cf = ErbScale( min_cf ) ;
+    max_cf = ErbScale( max_cf ) ;
+    max_cf = MAX( min_cf, max_cf ) ;                 /* max_cf cannot be smaller than min_cf */ 
+    base_cf = ErbScale( base_cf ) ;
+
+
+   /*** call appropriate generating functions ***/
+    if( *channels <= 0 ) {
+
+       if( *density <= 0. ) {
+	  *channels = 1 ;                           /* there must be at least one channel */
+	  freq = FofErbScale( min_cf ) ;            /* arbitrary */
+	  frequencies = &freq ;
+	  *density = 1. ;                           /* arbitrary */
+
+       }
+       else {
+	  frequencies = GenerateScale( min_cf, max_cf, *density, base_cf, FofErbScale ) ;
+	  *channels   = NumberOnScale( min_cf, max_cf, *density, base_cf ) ;
+       }
+    }
+
+    else {
+       frequencies = NumberedScale( min_cf, max_cf, *channels, FofErbScale ) ;
+       *density    = DensityOnScale( min_cf, max_cf, *channels ) ;
+       if( *density == 0. )
+	  *density = 1. ;    /* arbitrary */
+    }
+
+   /*** return pointer to array of center frequencies ***/
+    return ( frequencies ) ;
+}
+
+
+double adjustCF( cf, samplerate )
+double cf, samplerate ;
+{
+    cf = MAX( cf, MIN_CF ) ;                      
+    cf = MAX( cf, FofErbScale( 0. ) ) ;                    
+
+    cf = MIN( cf, samplerate / 2. ) ;
+    cf = MIN( cf, MAX_CF ) ;
+    cf = MIN( cf, FofErbScale( 10. * L / GetERBscaling() ) );
+
+    return ( cf ) ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/bank_tl.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,80 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    bank_tl.h
+    ===========================================================
+
+    Design of cochlear transmission line filterbank (TLF) with
+    coupled outer and middle ear (EAR) filter.
+
+    Author        : Christian Giguere
+    First written : 28th March, 1991
+    Last edited   : 07th March, 1994
+    ===========================================================
+*/
+
+#ifndef _BANK_TL_H_
+
+
+/***** defines *****/
+
+#define _BANK_TL_H_
+
+#define  FILTERBANK_SCALE  (      4.0 )      /* Arbitrary output scaling factor */
+
+
+/***** private data structure for TL filterbank information common to all channels *****/
+
+typedef struct _tlf_filterbank_info  TLF_BankInfo ;
+
+struct _tlf_filterbank_info {
+  int       output_chans ;                   /* nb of channels active for display */
+  int       decimate_factor, decimateCount ; /* output decimation management */
+  int       output_var, nl_var ;             /* BM motion for output and nonlinearity (0=disp 1=vel) */
+  } ;
+
+
+/***** externals *****/
+
+extern Source TLF_GenBank() ;
+extern double *GenerateFrequencies(), adjustCF() ;
+
+#endif 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/calc_tl.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,86 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    calc_tl.h
+    ===========================================================
+
+    Supplements "calc.h"
+    (for use with files in directory wdf)
+
+    Author        : Christian Giguere
+    First written : 01st June, 1991
+    Last edited   : 20th September, 1991
+    ===========================================================
+*/
+
+#ifndef  _CALC_TL_H_
+
+
+/***** defines *****/
+
+#define  _CALC_TL_H_
+
+#ifndef  Pi
+#define  Pi                      ( atan( 1. ) * 4. )
+#endif
+
+#ifndef  TwoPi
+#define  TwoPi                   (         2. * Pi ) 
+#endif
+
+#define  ABS( X )  ( ( X ) < ( 0 ) ? (-X ) : ( X ) )
+#define  MIN(A,B)  ( ( A ) < ( B ) ? ( A ) : ( B ) )
+#define  MAX(A,B)  ( ( A ) > ( B ) ? ( A ) : ( B ) )
+
+#ifdef FLOAT                     /* defined in calc.h */
+#define  _MaxOutput_             (         1.0E+37 )
+#define  _MinOutput_             (        -1.0E-37 )
+#else 
+#define  _MaxOutput_             (           32767 )
+#define  _MinOutput_             (          -32767 )
+#endif
+
+/***** typedefs *****/
+
+typedef double StateType ;
+typedef double CoeffType ;
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/ear.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,180 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    ear.c 
+    ===========================================================
+
+    Design of outer and middle ear (EAR) filter.
+    (uncoupled version)
+            
+    Author        : Christian Giguere
+    First written : 01st June, 1991
+    Last edited   : 07th March, 1994
+    ===========================================================
+*/
+
+
+/***** includes *****/
+
+#include <math.h>
+#include <stdio.h>
+#include "stitch.h"
+#include "source.h"
+#include "calc.h"
+#include "calc_tl.h"
+#include "wdf_ear.h"
+#include "ear.h"
+
+
+/***** defines *****/
+
+#if 0
+#define   _DEBUG_
+#endif
+
+/***** functions *****/
+
+
+/**************************************************************************
+* name:                    function:
+*
+* ear_callback()           Callable procedure returning pointer to filtered
+*                          data (stapes velocity).
+*
+* Ear()                    Set-up and initialization function for the design 
+*                          of the outer and middle ear filter (this filter is 
+*                          not coupled to the cochlea).  Returns pointer to
+*                          a new source.
+***************************************************************************/
+
+struct _ear_state {
+  struct _fillable_source parent ;
+  Source  source ; 
+  Pointer input ; 
+  int     inout_size ;
+  void    (*proc)(), (*close)() ;
+  int     Ntube ;
+  WaveWDFstate      *wave_states ;
+  EartubeWDFstate   **eartube_states ;
+  EarmiddleWDFstate *earmiddle_states ;
+  } ;
+
+
+/******************************** ear_callback() *************************************/
+
+static Pointer ear_callback( state, bytes, buffer )
+  struct _ear_state  *state ;
+  ByteCount *bytes ;
+  Pointer   buffer ;
+{
+  register int last = *bytes == 0 ;
+  register int points ;
+
+ /***** process *****/
+  if( !last ) {
+
+     /*** get input data ***/
+      Fill(state->source, *bytes, buffer ) ;
+
+     /*** process data ***/
+      points = *bytes / state->inout_size ;
+      state->proc( state->wave_states, state->eartube_states, state->earmiddle_states, 
+                   state->Ntube, buffer, points ) ; 
+           
+      return ( buffer ) ;
+  }
+
+ /***** close *****/
+  else {
+
+      Fill( state->source, 0, buffer ) ;
+      state->close( state->wave_states, state->eartube_states, state->earmiddle_states, state->Ntube ) ;
+
+      return ( DeleteFillableSource( state ) ) ;
+  }
+
+}
+
+
+/************************************ Ear() *******************************************/
+
+Source Ear( source, samplerate, output_gain, concha, canal )
+  Source    source ;
+  double    samplerate, output_gain ;
+  TubeInfo  *concha, *canal ;
+{
+  DeclareNew( struct _ear_state *, state ) ;
+  double    length, diam, attn ;
+  int       segment ;
+
+ /***** initialise input-related parameters *****/
+  state->inout_size = sizeof ( DataType ) ;
+  state->input  = ( Pointer ) 0 ;
+  state->source = source ;
+
+ /***** Specify WDF filter design parameters *****/
+  state->wave_states = FreefieldWDF( samplerate, RHO_air, C, As, concha->diameter/2. ) ;
+
+  state->Ntube = canal->Nsegments + concha->Nsegments ;
+  state->eartube_states = NewArray( EartubeWDFstate *, state->Ntube, "ear.c for eartube states" ) ;
+
+  length = concha->length / concha->Nsegments ;
+  diam   = concha->diameter ;
+  attn   = concha->att_factor ;
+  for( segment = 0 ; segment < concha->Nsegments ; segment++ ) 
+       state->eartube_states[ segment ] = EartubeWDF( samplerate, RHO_air, C, diam, length, attn ) ;
+
+  length = canal->length / canal->Nsegments ;
+  diam   = canal->diameter ;
+  attn   = canal->att_factor ;
+  for( ; segment < state->Ntube ; segment++ ) 
+       state->eartube_states[ segment ] = EartubeWDF( samplerate, RHO_air, C, diam, length, attn ) ;
+
+  state->earmiddle_states = EarmiddleWDF( samplerate, 0.0, output_gain, 1.0 ) ;
+
+  state->proc = DoEarWDF ;
+  state->close = CloseEarWDF ;
+
+ /***** return *****/
+  source = SetFillableSource( state, ear_callback, "ear filter stage" ) ;
+  return ( source ) ;
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/ear.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,81 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    ear.h 
+    ===========================================================
+
+    Design of outer and middle ear (EAR) filter.
+    (uncoupled version)
+
+    Author        : Christian Giguere
+    First written : 01st June, 1991
+    Last edited   : 07th March, 1994
+    ===========================================================
+*/
+
+#ifndef _EAR_H_
+
+
+/***** defines *****/
+
+#define _EAR_H_
+
+#define   RHO_air        (   1.14e-03 )       /* air density (g/cm3) */ 
+#define   C              (     3.5e04 )       /* sound velocity in air (cm/s) */
+#define   As             (       25.0 )       /* effective diffraction radius of head-torso (cm) */
+
+
+/***** data structure *****/
+ 
+typedef struct _tube_info  TubeInfo ;
+
+struct _tube_info {
+  int    Nsegments ;           /* number of tube segments */
+  double length ;              /* total length of tube (cm) */
+  double diameter ;            /* diameter of tube  (cm2) */
+  double att_factor ;          /* attn. constant for backward/forward waves (1/cm) */ 
+  } ;
+
+/***** externals *****/
+
+extern Source Ear() ;
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/fir.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,188 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    fir.c
+    ===========================================================
+
+    Finite Impulse Response (FIR) filtering module.
+    
+    Author        : Christian Giguere
+    First written : 12th November, 1990
+    Last edited   : 22nd September, 1991
+    
+    Reference:
+    (1) A.V.Oppenheim and R.W.Schafer (1975). Digital Signal
+        Processing (Prentice-Hall), Sections 4.5.5 and 5.5.
+    ===========================================================
+*/
+
+
+/***** includes *****/
+
+#include <math.h>
+#include <stdio.h>
+#include "stitch.h"
+#include "calc.h"
+#include "calc_tl.h"
+#include "fir.h"
+
+
+/***** defines *****/
+
+#define NUMBER_OF_COEFFS     (               51 )                 /* odd order */
+#define NUMBER_OF_STATES     ( NUMBER_OF_COEFFS ) 
+
+
+/***** functions *****/
+
+/*******************************************************************************
+* name:                 function:  
+*
+* NewLpFIRfilter()      Design of LowPass FIR filter using windowing technique
+*                       (Hamming window). It generates the multiplier coefficients
+*                       and initializes the states of the filter. It returns a 
+*                       pointer to a structure containing all relevant information 
+*                       for the realisation of the filter.
+*
+* DoFIRfilter()         Direct form realisation for FIR filter of odd order linear
+*                       phase. It is called by function ``upsample_callback()'' 
+*                       in file ``upsample.c'' once for a specified number of input 
+*                       points.  It computes the filter output for each input point
+*                       and keeps track of the filter states. 
+*
+* CloseFIRfilter()      Deletes all private data structures and arrays of the FIR 
+*                       filter upon comletion of filtering.  It is called by function
+*                       ``upsample_callback()'' in file ``upsample.c''. 
+********************************************************************************/
+
+
+/************************* NewLpFIRfilter() *******************************/
+
+FIRfilterState *NewLpFIRfilter( wc, upsample_factor, delay )
+  double wc ;
+  int    upsample_factor, *delay ;
+{
+  DeclareNew( FIRfilterState *, filter_state ) ;
+  CoeffType *hn ;
+  double    filterGain, hamming() ;
+  int       n ;
+
+ /***** generate and store FIR filter coefficients (linear phase, odd order, window desing technique) *****/
+  filter_state->number_of_coeffs = ( NUMBER_OF_COEFFS + 1 ) / 2 ;  
+  filter_state->coeffs = ( char * ) NewArray( CoeffType, filter_state->number_of_coeffs, "fir.c for coefficients\n" ) ;
+
+  *delay = ( NUMBER_OF_COEFFS - 1 ) / 2 ;
+  hn = ( CoeffType * ) filter_state->coeffs ;
+  filterGain = ( double ) upsample_factor ;
+
+  for( n = 0 ; n < filter_state->number_of_coeffs - 1 ; n++ ) 
+      *hn++ = sin( wc * ( n - *delay ) ) / ( Pi * ( n - *delay ) ) * hamming( n, NUMBER_OF_COEFFS ) * filterGain ;
+  *hn = wc / Pi * filterGain ;
+    
+
+ /***** initialise filter states *****/
+  filter_state->number_of_states = NUMBER_OF_STATES ;
+  filter_state->states = ( char * ) NewZeroedArray( StateType, NUMBER_OF_STATES, "fir.c for filter states\n" ) ;
+
+
+ /***** return *****/   
+  return( filter_state ) ;
+}
+
+
+/****************************** DoFIRfilter() *******************************/
+
+void DoFIRfilter( filter_state, inoutput, points )
+  FIRfilterState *filter_state ;
+  DataType       *inoutput ;
+  int            points ;
+{
+  register StateType  *st = ( StateType * ) filter_state->states ;
+  register CoeffType  *cf = ( CoeffType * ) filter_state->coeffs ;
+  register DataType   *inout_ptr = inoutput ;
+  register double     acc ;
+  register int        n, Ns = filter_state->number_of_states ;
+  register int        Nc = filter_state->number_of_coeffs ;
+
+ /***** for all points *****/
+  for( ; points > 0 ; points-- ) {
+      acc = 0. ;
+
+     /*** shift the states ***/
+      for( n = Ns - 1 ; n > 0 ; n-- ) 
+          st[n] = st[n-1] ;
+      st[0] = *inout_ptr ;
+   
+     /*** filter current point ***/
+      for( n = 0  ; n < Nc - 1 ; n++ ) 
+          acc += cf[n] * ( st[n] + st[Ns-1-n] ) ; 
+      acc += cf[n] * st[n] ;
+
+     /*** store output point ***/
+      *inout_ptr++ = acc ;
+  }  
+
+ /***** return *****/
+  return ;
+
+}
+
+/************************* CloseFIRfilter() *******************************/
+
+void CloseFIRfilter( filter_state )
+  FIRfilterState *filter_state ;
+{
+  Delete( filter_state->states ) ;
+  Delete( filter_state->coeffs ) ;
+  Delete( filter_state ) ;
+
+  return ;
+
+}
+
+
+/*********************** low level functions ***********************/
+
+double hamming( n, N )
+  int n, N ;
+{ 
+  return ( 0.54 - 0.46 * cos( TwoPi * n / ( N - 1. ) ) ) ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/fir.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,78 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    fir.h 
+    ===========================================================
+
+    Finite Impulse Response (FIR) filtering module.
+    
+    Author        : Christian Giguere
+    First written : 12th November, 1990
+    Last edited   : 22nd September, 1991
+    ===========================================================
+*/
+
+#ifndef _FIR_H_
+
+
+/***** defines *****/
+
+#define _FIR_H_
+
+
+/****** private data structure for FIR filters *****/
+
+typedef struct _fir_filter_state FIRfilterState ;
+
+struct _fir_filter_state {
+  char *states ;                              /* FIR state vector */ 
+  int  number_of_states ;                     /* number of states */
+  char *coeffs ;                              /* FIR coefficient vector */
+  int  number_of_coeffs ;                     /* number of coefficients */
+  } ;
+
+
+/***** externals *****/
+
+extern FIRfilterState *NewLpFIRfilter() ;
+extern void            DoFIRfilter(), CloseFIRfilter() ;
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/formulae_tl.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,95 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    formulae_tl.c
+    ===========================================================
+
+    Supplements "formulae.c" 
+    (for use with WDF-TLF cochlear filterbank)
+
+    Author        : Christian Giguere
+    First written : 30th March, 1991 
+    Last edited   : 17th December, 1993
+    
+    References:
+    (1) B.R.Glasberg and B.C.J.Moore (1990). Hear Res 47: 103-138.
+    (2) D.D.Greenwood (1990). JASA 87(6): 2592-2605.
+    ===========================================================
+*/
+
+
+/***** includes *****/
+
+#include  <math.h>
+#include  "formulae_tl.h"
+
+/***** functions *****/
+
+/****************************************************************************
+* name:             comments:
+*
+* SetERBscaling()   Stores a new value for the length of one critical-band
+*                   unit, i.e. the distance along the basilar membrane 
+*                   corresponding to one critical band. 
+*
+*                   Use:
+*                   0.89 mm for ERB function of Glasberg and Moore (1990)
+*                   1.00 mm for frequency-position function of Greenwood (1990)
+*
+* GetERBscaling()   Returns the length of one critical-band unit.
+****************************************************************************/
+
+static double mmperERB = 0.89 ;      /* millimeters per critical band */
+                                     /* Default = 0.89 (ERB) */
+
+void SetERBscaling( new_mmperERB )
+double new_mmperERB ;
+{
+    mmperERB = new_mmperERB ;
+
+    return ;
+}
+
+
+double GetERBscaling( )
+{
+    return ( mmperERB ) ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/formulae_tl.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,66 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    formulae_tl.h
+    ===========================================================
+
+    Supplements "formulae.h"
+    (for use with WDF-TLF cochlear filterbank)
+
+    Author        : Christian Giguere
+    First written : 05th March, 1991
+    Last edited   : 17th December, 1993
+    ===========================================================
+*/
+
+#ifndef _FORMULAE_TL_H_
+
+
+/***** defines *****/
+
+#define _FORMULAE_TL_H_
+
+/***** externals *****/
+
+extern void   SetERBscaling() ;
+extern double GetERBscaling() ;
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/makefile	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,70 @@
+###########################################################################
+#
+#  Makefile for AIM filterbank library (WDF-TLF version):  libwdf.a
+#
+#   (For convenience, this makefile directly calls the root makefile).
+#
+#   @(#)makefile        1.35 J. Holdsworth, (MRC-APU)  6/6/91
+#                            M. Allerhand,  (MRC-APU) 26/1/93
+#                            C. Giguere,              10/3/94
+#
+###########################################################################
+
+
+default : install
+
+MDIR = ../model
+SDIR = ../stitch
+FDIR = ../filter
+
+WLIB = libwdf.a
+
+INCLUDES  =  -I$(MDIR) -I$(SDIR) -I$(FDIR)
+
+.c.o :
+	$(CC) $(CFLAGS) $(INCLUDES) -c $<
+
+
+############################################################################
+# Make filterbank library (WDF-TLF version).
+
+OBJS = upsample.o fir.o ear.o wdf_ear.o bank_tl.o wdf_tl.o \
+       formulae_tl.o scales_tl.o meddis.o
+
+lib $(WLIB) : $(OBJS)
+	ar rc $@ $? ; $(RANLIB) $@
+
+
+############################################################################
+# dependencies
+
+upsample.o:     $(SDIR)/stitch.h $(SDIR)/source.h $(MDIR)/calc.h calc_tl.h \
+                fir.h upsample.h
+fir.o:          $(SDIR)/stitch.h $(MDIR)/calc.h calc_tl.h fir.h
+ear.o:          $(SDIR)/stitch.h $(SDIR)/source.h $(MDIR)/calc.h calc_tl.h \
+		wdf_ear.h ear.h
+wdf_ear.o:      $(SDIR)/stitch.h $(MDIR)/calc.h calc_tl.h wdf_ear.h
+bank_tl.o:      $(SDIR)/stitch.h $(SDIR)/source.h $(MDIR)/calc.h calc_tl.h \
+		$(FDIR)/formulae.h $(FDIR)/scales.h formulae_tl.h scales_tl.h \
+		wdf_tl.h wdf_ear.h ear.h $(MDIR)/bank.h bank_tl.h
+wdf_tl.o:       $(SDIR)/stitch.h $(SDIR)/source.h $(MDIR)/calc.h calc_tl.h \
+		bank_tl.h wdf_ear.h wdf_tl.h
+formulae_tl.o:  formulae_tl.h
+scales_tl.o:    scales_tl.h
+meddis.o:       $(SDIR)/stitch.h $(SDIR)/source.h $(MDIR)/calc.h calc_tl.h \
+		meddis.h
+
+############################################################################
+# Make targets in root makefile.
+
+TARGETS   = main        install     all         sources \
+	    links       alllinks    demo        tar     \
+	    ftp         tape        mail        clean   \
+	    sccslinks   cleansccs   help        noplot
+
+$(TARGETS) : FORCE
+	@ cd .. ; make $@
+FORCE:
+
+
+############################################################################
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/meddis.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,491 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    meddis.c
+    ===========================================================
+
+    Implementation of Ray Meddis haircell model.
+
+    Author        : Christian Giguere
+    First written : 10th September, 1991
+    Last edited   : 07th March, 1994
+
+    References:
+    (1) C.Giguere and P.C.Woodland (1994). JASA 95(1): 331-342.
+    (2) R.Meddis et al. (1990). JASA 87(4): 1813-1816.
+    (3) R.Meddis (1988). JASA 83(3): 1056-1063.
+
+    Note - This is a complete re-write of the original file 
+	   "haircell.c" Release 3 (20th September 1988) from  
+	   J. Holdsworth and the Applied Psychology Unit. 
+    ============================================================
+*/
+
+
+/***** includes *****/
+
+#include <math.h>
+#include <stdio.h>
+#include "stitch.h"
+#include "source.h"
+#include "calc.h"
+#include "calc_tl.h"
+#include "meddis.h"
+
+
+/***** defines *****/
+
+#if 0
+#define   _DEBUG_
+#define   _OVERFLOW_
+#endif
+
+#if 1                                                /* define numerical implementation */
+#define   _WDF_                                      /* Giguere and Woodland (1994) */
+#else
+#define   _FORWARD_DIFFERENCE_                       /* Meddis et al. (1990) */
+#endif
+
+#if 0  
+#define   _CLAMPING_                                 /* clamping of reservoirs */
+#endif
+ 
+#define   NUMBER_OF_COEFFS     (           12 )
+#define   NUMBER_OF_STATES     (           12 )
+
+
+/* Feedback parameter */
+
+#define   InputGain_max        (         24.0 )      /* max coupling gain in dB */
+
+
+/* Meddis et al. (1990) model parameters */
+
+#define   A_medium             (         10.0 )      /* medium-spontaneous rate fibre  */
+#define   B_medium             (       3000.0 )
+#define   g_medium             (       1000.0 )
+
+#define   A_high               (          5.0 )      /* high-spontaneous rate fibre */
+#define   B_high               (        300.0 )
+#define   g_high               (       2000.0 )
+
+#define   y_value              (         5.05 )      /* replenishment rate */
+#define   l_value              (         2500 )      /* rate of loss from the cleft */
+#define   r_value              (         6580 )      /* rate of return from the cleft */
+#define   x_value              (        66.31 )      /* rate of release from w store */ 
+#define   m_value              (          1.0 )      /* max number of quanta */
+#define   h_value              (       50000. )      /* firing-rate factor */
+
+
+/***** private data structures *****/
+
+typedef struct _haircell_info HaircellInfo ;
+typedef struct _haircell_bank HaircellBank ;
+
+struct _haircell_info {
+  int        number_of_states ;  
+  double     output_gain ;
+  StateType  *states ;
+  } ;
+
+struct _haircell_bank {
+  int           channels ;
+  double        *inputGain_ratio ;
+  double        (*update_proc)() ;                  /* procedure to update cells input gain */
+  int           number_of_coeffs ;
+  CoeffType     *coeffs ;
+  HaircellInfo  **cells ;
+  } ;
+
+
+/***** external variables *****/
+
+double *InputGain_ratio ;
+
+
+/***** functions *****/
+
+/*******************************************************************************
+* name:                 function:
+*
+* NewHaircells()        Set-up function for the implementation of a bank of inner
+*                       haircells based on the model of Ray Meddis. It generates the 
+*                       multiplier coefficients for each haircell filter and 
+*                       initializes the filter states. It is called by function 
+*                       ``Meddis()'' in file ``model.c''. It returns a pointer to a 
+*                       structure containing all the relevant information for the 
+*                       computation of the haircell filters. 
+*
+*                       The choice of the haircell type (medium or high-spontaneous
+*                       rate fibre) is made at run time using options ``fibre_med''.
+*
+*                       The choice of the numerical implementation (Wave Digital 
+*                       Filtering or Forward Difference algorithm) is made at 
+*                       compile time using a macro substitution ``#define'' (see above).
+*
+*                       The choice of clamping the reservoirs' contents to non-
+*                       negative values is made at compile time using a macro
+*                       substitution ``#define'' (see above).
+*
+* DoHaircells()         Realization of the bank of haircell filters. It computes the
+*                       output for each haircell for a specified number of input 
+*                       points and keeps track of the filters' states. It returns
+*                       the size of the output data in bytes (per point).
+*
+* CloseHaircells()      Deletes all private data structures and arrays of the Haircell 
+*                       filters upon comletion of filtering.
+********************************************************************************/
+
+
+/*************************** NewHaircells() *********************************/
+
+Pointer NewHaircells( channels, samplerate, output_gain, coupling, fibreType )
+    int    channels ;
+    double samplerate, output_gain ;
+    double coupling ;
+    char   *fibreType ;
+{
+    DeclareNew( HaircellBank *, bank ) ;
+    HaircellInfo  *cell_info ;
+    CoeffType     *cf ;
+    StateType     *st ;  
+    double        ydt, ldt, rdt, xdt, gdt ; 
+    double        kdt_init, q_init, c_init, w_init, cell_scaling ; 
+    double        A_value, B_value, g_value ;
+    double        r1, r2, r3, r4, r03 ;
+    double        update_inputGain() ;
+    int           channel ;
+
+   /*** scaling of input data ***/
+    cell_scaling = coupling ;
+
+   /*** allocate fibre-dependent haircell parameters ***/
+    if( strncmp( fibreType, "high", 3 ) == 0 ) {
+	A_value = A_high ;
+	B_value = B_high ;
+	g_value = g_high ;
+    }
+     else {
+	A_value = A_medium ;
+	B_value = B_medium ;
+	g_value = g_medium ;
+    }
+
+#ifdef _DEBUG_
+    fprintf( stderr, "Meddis Haircell fibre type=%s\n", fibreType ) ;
+    fprintf( stderr, "A=%.2f B=%.2f g=%.2f\n", A_value, B_value, g_value ) ;
+    fprintf( stderr, "Input scaling factor=%.4f\n", cell_scaling ) ;
+#endif
+
+
+   /*** scale model parameters for difference equations ***/ 
+    ydt = y_value / samplerate ;
+    ldt = l_value / samplerate ;
+    rdt = r_value / samplerate ;
+    xdt = x_value / samplerate ;
+    gdt = g_value / samplerate ;
+
+
+   /*** calculate initial values for infinite history of silence ***/
+    kdt_init = gdt * A_value / ( A_value + B_value ) ;
+    q_init   = m_value / ( 1. + kdt_init / ydt * ( 1. - rdt / ( ldt + rdt ) ) ) ;
+    c_init   = q_init * kdt_init / ( ldt + rdt ) ;
+    w_init   = rdt / xdt * c_init ;    
+
+
+   /*** allocate and store multiplier coefficients ***/
+    bank->number_of_coeffs = NUMBER_OF_COEFFS ;  
+    cf = bank->coeffs = NewArray( CoeffType, bank->number_of_coeffs, 
+				  "haircell_tl.c for coefficients" ) ;
+#ifdef _WDF_
+    output_gain = MEDDIS_SCALE * output_gain * h_value / ( 2. * r_value ) ;
+    cf[0] = m_value * y_value * output_gain ;                     /* M/Zy (normalized) */
+    cf[1] = A_value / cell_scaling ;
+    cf[2] = ( A_value + B_value ) / cell_scaling ; 
+    cf[3] = g_value ;
+
+    /* Adaptor B0 */ 
+    r1 = y_value ;                                                /* ( 1/Zy ) */
+    r2 = 2. * samplerate ;                                        /* ( 1/Zcq ) */
+    r3 = r03 = r1 + r2 ;
+    cf[5] = r1 / r3 ;                                             /* gamma01 */
+    cf[4] = r3 / cf[3] ;                                          /* needed to update gamma11 */
+
+    /* Adaptor B1*/ 
+    r1 = kdt_init * samplerate ;                                  /* ( 1/Zk ) initial value only */
+    r2 = r03 ;
+    r3 = r1 + r2 ;
+    cf[6] = 2. * r1 / r3 ;                                        /* gamma11 updated at each sample */
+
+    /* Adaptor B2 */ 
+    r1 = l_value ;                                                /* ( 1/Zl ) */
+    r2 = r_value ;                                                /* ( 1/Zr ) */
+    r3 = 2. * samplerate ;                                        /* ( 1/Zcc ) */
+    r4 = r1 + r2 + r3 ;
+    cf[7] = r1 / r4 ;                                             /* gamma21 */
+    cf[8] = r2 / r4 ;                                             /* gamma22 */
+
+    /* Adaptor B3 */
+    r1 = x_value ;                                                /* ( 1/Zx ) */
+    r2 = 2. * samplerate ;                                        /* ( 1/Zcw ) */
+    r3 = r1 + r2 ;
+    cf[9] = 0.5 * r1 / r3 ;                                       /* 0.5 * gamma31 */
+
+#else
+    output_gain = MEDDIS_SCALE * output_gain * h_value ;
+    cf[0] = m_value * output_gain ;
+    cf[1] = A_value / cell_scaling ;
+    cf[2] = ( A_value + B_value ) / cell_scaling ;
+    cf[3] = gdt ;
+    cf[4] = ydt ;
+    cf[5] = ldt ;
+    cf[6] = rdt ;
+    cf[7] = xdt ;
+#endif
+
+
+   /*** loop through each haircell ***/
+    bank->channels = channels ;
+    bank->cells = NewArray( HaircellInfo *, bank->channels, "haircell.c for cell states" ) ;
+    bank->inputGain_ratio = InputGain_ratio = NewArray( double, bank->channels, 
+							"haircell_tl.c for cells input gain ratio" ) ;
+    bank->update_proc = update_inputGain ;
+
+    for( channel = 0 ; channel < bank->channels ; channel++ ) {
+	 bank->inputGain_ratio[ channel ] = 0.5 ;            /* in absence of feedback, Gain = 1 */
+	 cell_info = bank->cells[ channel ] = New( HaircellInfo * ) ;
+
+	/*** allocate and initialise states ***/
+	 cell_info->number_of_states = NUMBER_OF_STATES ;
+	 st = cell_info->states = NewZeroedArray( StateType, cell_info->number_of_states, 
+						  "haircell_tl.c for states" ) ;
+
+#ifdef _WDF_
+	st[1] =  x_value * w_init * output_gain ;               /* Ixn (normalized) */
+	st[2] =  2. * q_init * samplerate * output_gain ;       /* Ixn(t-T)-b02 (normalized) */
+	st[3] = -2. * c_init * samplerate * output_gain ;       /* b23 (normalized) */
+	st[4] = -2. * w_init * samplerate * output_gain ;       /* b33 (normalized) */
+	cell_info->output_gain = output_gain ;                  /* obsolete */
+
+#else
+	st[0] = kdt_init ;
+	st[1] = q_init * output_gain ;
+	st[2] = c_init * output_gain ;
+	st[3] = w_init * output_gain ;
+	cell_info->output_gain = output_gain ;                  /* obsolete */
+#endif
+
+    }
+
+    return( ( Pointer ) bank ) ;
+}
+
+
+/************************** DoHaircells() *********************************/
+
+int DoHaircells( bank_ptr, bytes, output_ptr, end_output_ptr, input_ptr ) 
+    Pointer    *bank_ptr ;
+    ByteCount  *bytes ;
+    DataType   *output_ptr, *end_output_ptr, *input_ptr ;
+{
+    register HaircellBank *bank = ( HaircellBank * ) bank_ptr ;
+    register HaircellInfo *cell_info ;
+    register DataType     *input, *output ;
+    register StateType    *st ;
+    register StateType    in, out ;
+    register CoeffType    *cf ;
+    register double       inputGain ;
+    register int          channel = bank->channels ;
+    register int          point, npoints = ( end_output_ptr - output_ptr ) / bank->channels ;
+#ifdef _WDF_
+    register StateType    an, a0 ;
+#else
+    register StateType    replenish, eject, loss, reuptake, reprocess ;
+#endif
+
+    /*** for all channels ***/
+
+#ifdef _DEBUG_
+     fprintf( stderr, "DoHaircells() = %d points X %d channels\n", npoints, bank->channels ) ;
+#endif
+
+     cf = bank->coeffs ;
+
+     while( channel-- ) {
+
+	cell_info = bank->cells[ channel ] ;
+	st = cell_info->states ;
+	input = input_ptr + channel ;                
+	output = output_ptr + channel ;
+	inputGain = bank->update_proc( bank->inputGain_ratio[ channel ] ) ; 
+	cf[10] = cf[1] / inputGain ;                                    /* (A/p) */
+	cf[11] = cf[2] / inputGain ;                                    /* (A+B)/p */
+
+       /*** for each channel ***/
+
+	point = npoints ;  
+	while( point-- ) { 
+
+#ifdef _WDF_
+	  /*** compute compressive permeability function k ***/
+	   in = ( StateType ) *input ;                                  /* (BM vibration) */
+	   if( in > -cf[10] )
+	      st[0] = ( in + cf[10] ) / ( in + cf[11] ) ;               /* kn(t) / g */ 
+	   else
+	      st[0] = 0. ;
+
+	  /*** update gamma11 ***/
+	   cf[6] = st[0] / ( st[0] + cf[4] ) ;
+	   cf[6] += cf[6] ;                                             /* gamma11 */
+
+	  /*** compute wdf ***/
+
+	  /* Adaptor  B0 */
+	  st[5] = cf[0] + st[1] + st[2] ;                               /* -b03=a12 (normalized) */
+
+	  /* Adaptor B1 */
+	  st[6] = cf[6] * st[5] ;                                       /* -b11=2Ikn (normalized) */
+	  st[7] = st[6] - st[5] ;                                       /* b12=-a03 (normalized) */
+
+	  /* Adaptor B0 */
+	  st[2] = cf[0] + st[1] - st[7] + cf[5] * ( st[7] - st[5] ) ;   /* Ixn(t-T)-b02 (normalized) */
+
+	  /* Adaptor B2 */
+	  an = st[6] - st[3] ;                                          /* a24 (normalized) */ 
+	  a0 = an - st[3] ;                                             /* a20 (normalized) */
+	  st[8] = cf[8] * a0 ;                                          /* -b22=2Irn (normalized) */
+	  st[3] = cf[7] * a0 + st[8] - an ;                             /* b23 (normalized) */
+
+	  /* Adaptor B3 */
+	  an = st[8] - st[4] ;                                          /* a33 (normalized) */ 
+	  st[1] = cf[9] * ( an - st[4] ) ;                              /* Ixn(t)=-0.5*b31 (normalized) */
+	  st[4] = st[1] + st[1] - an ;                                  /* b32 (normalized) */
+
+#ifdef _CLAMPING_
+	  /*** clamping of reservoirs to non-negative quantities ***/
+	  /*** not available yet ***/
+#endif     
+
+	  /*** output ***/
+	   out = st[8] ;
+
+#else
+
+	  /*** compute change quantities ***/
+	   replenish = cf[4] * ( cf[0] - st[1] ) ;                     /* y(M-q) */
+	   eject     = st[0] * st[1] ;                                 /* kq */
+	   loss      = cf[5] * st[2] ;                                 /* lc */ 
+	   reuptake  = cf[6] * st[2] ;                                 /* rc */
+	   reprocess = cf[7] * st[3] ;                                 /* xw */
+
+	  /*** compute compressive permeability function kn_1dt ***/
+	   in = ( StateType ) *input ;                                 /* (BM vibration) */
+	   if( in > -cf[10] )
+	      st[0] = cf[3] * ( in + cf[10] ) / ( in + cf[11] ) ;      /* kn_1(t)dt */ 
+	   else
+	      st[0] = 0. ;
+
+	  /*** update reservoir quantities ***/
+	   st[1] += replenish - eject + reprocess ;                    /* q */
+	   st[2] += eject - loss - reuptake ;                          /* c */
+	   st[3] += reuptake - reprocess ;                             /* w */
+ 
+#ifdef _CLAMPING_
+	  /*** clamping of reservoirs to non-negative quantities ***/
+	   if( st[1] < 0 )
+	      st[1] = 0 ;
+	   if( st[2] < 0 )
+	      st[2] = 0 ;
+#endif
+
+	  /*** output ***/
+	   out = st[2] ; 
+
+#endif
+
+	  /*** output ***/
+#ifdef _OVERFLOW_  
+	   if( out > _MaxOutput_ ) 
+	      fprintf( stderr, "Overflow error in Meddis Haircell output\%e\n", ( double ) out ) ;
+#endif
+
+	   *output = ( DataType ) out ;
+
+	   output += bank->channels ;
+	   input  += bank->channels ;
+	}
+
+    }
+
+    return( npoints ) ;
+ }
+
+
+/************************** CloseHaircells() *********************************/
+
+void CloseHaircells( bank_ptr )
+    Pointer bank_ptr ;
+{
+    HaircellBank *bank = ( HaircellBank * ) bank_ptr ;
+    HaircellInfo *cell_info ;
+    int          channel ;
+
+    for( channel = 0 ; channel < bank->channels ; channel++) {
+       Delete( bank->cells[ channel ]->states ) ;
+       Delete( bank->cells[ channel ] ) ;
+    }
+    
+    Delete( bank->cells ) ;
+    Delete( bank->coeffs ) ;
+    Delete( bank->inputGain_ratio ) ; 
+    Delete( bank ) ;
+
+    return ;
+}
+
+
+/********** low level functions ************/
+
+double update_inputGain( ratio ) 
+  double ratio ;
+{
+  return( pow( 10., ( ratio - 0.5 ) * InputGain_max / 20. ) ) ; 
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/meddis.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,74 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    meddis.h 
+    ===========================================================
+
+    Implementation of Ray Meddis haircell model.
+
+    Author        : Christian Giguere
+    First written : 10th September, 1991
+    Last edited   : 07th March, 1994
+
+    Note - This is a complete re-write of the original file 
+	   "haircell.h" Release 3 (20th September 1988) from 
+	   J. Holdsworth and the Applied Psychology Unit.
+    ============================================================
+*/
+
+#ifndef _MEDDIS_H_
+
+
+/***** defines *****/
+
+#define _MEDDIS_H_
+
+#define  MEDDIS_dB               (         30.0 )      /* Meddis et al. (1990 ) scaling */
+#define  MEDDIS_RMS              (          1.0 )
+#define  MEDDIS_SCALE            (         20.0 )      /* Arbitrary output scaling factor */
+
+/***** externals *****/
+
+extern  char *NewHaircells() ; 
+extern  int   DoHaircells() ; 
+extern  void  CloseHaircells() ;
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/scales_tl.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,92 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    scales_tl.c
+    ===========================================================
+
+    Supplements "scales.c"
+    (for use with WDF-TLF cochlear filterbank)
+
+    Author        : Christian Giguere
+    First written : 29th March, 1991 
+    Last edited   :
+    ===========================================================
+*/
+
+
+/***** includes *****/
+
+#include "scales_tl.h"
+
+
+/***** defines *****/
+
+
+/***** functions *****/
+
+/*************************************************************************
+* DensityOnScale()
+*
+* Returns the density of channels of a filterbank (# per CB-rate unit).
+*
+* argument-name:      comments:
+*   minOnScale          minimum channel freq. on arbitrary linear scale 
+*   maxOnScale          maximum channel freq. on arbitrary linear scale  
+*   channels            total number of channels
+**************************************************************************/
+
+double DensityOnScale( minOnScale, maxOnScale, channels )
+double minOnScale, maxOnScale ;
+int    channels ;
+{
+    if( channels == 1 ) {
+         
+       if( maxOnScale ==  minOnScale ) {
+
+           return ( 0. ) ;                           /* arbitrary */
+       }
+       else 
+          return ( 1. / ( maxOnScale - minOnScale ) ) ;
+    }
+    
+    else
+       return ( ( channels - 1. ) / ( maxOnScale - minOnScale ) ) ;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/scales_tl.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,66 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    scales_tl.h 
+    ===========================================================
+
+    Supplements "scales.h"
+    (for use with WDF-TLF filterbank)
+
+    Author        : Christian Giguere
+    First written : 05th March, 1991 
+    Last edited   :
+    ===========================================================
+*/
+
+#ifndef _SCALES_TL_H_
+
+
+/***** defines *****/
+
+#define _SCALES_TL_H_
+
+
+/***** externals *****/
+
+extern double DensityOnScale() ;
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/upsample.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,203 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    upsample.c
+    ===========================================================
+
+    Upsampling module (FIR filter interpolation method).
+
+    Author        : Christian Giguere
+    First written : 23rd November, 1990 
+    Last edited   : 09th February, 1994
+
+    Reference:
+    (1) L.R.Rabiner and R.W.Schafer (1978). Digital Processing of
+	Speech Signals (Prentice-Hall), Section 2.4.2.
+    ===========================================================
+*/
+
+/***** includes *****/
+
+#include <math.h>
+#include <stdio.h>
+#include "stitch.h"
+#include "source.h"
+#include "calc.h"
+#include "calc_tl.h"
+#include "fir.h"
+#include "upsample.h"
+
+
+/***** defines *****/
+
+#define   SEGMENT    ( 2048 )    /* number of new points allocated and retained */
+				 /* on each call to input source */
+
+
+/***** functions *****/
+
+/*******************************************************************************
+* name:                  function:
+*
+* upsample_callback()    Callable procedure returning pointer to upsampled data.  
+* 
+* UpSample()             Setup and initialization function for the design of an
+*                        FIR interpolation filter. Returns pointer to a new source.
+********************************************************************************/
+
+struct _upsample_state {
+  struct _fillable_source parent ;
+  Source  source ; 
+  Pointer input ; 
+  int     iptr, inout_size ;
+  int     zerocount, upsample_factor, sample_delay, active ;
+  void    (*proc)(), (*close)() ;  
+  FIRfilterState *states ;  
+  } ;
+
+
+/************************* upsample_callback() ******************************/
+
+static Pointer upsample_callback( state, bytes, buffer )
+  struct _upsample_state  *state ;
+  ByteCount *bytes ;
+  Pointer   buffer ;
+{
+  register DataType *optr, *eptr, *pstart ;
+  register int      last = *bytes == 0 ;
+  register int      points, bytecount ;   
+
+ /***** process *****/
+  if( !last ) {
+
+     for( bytecount=0 ; bytecount<*bytes ; ) {
+
+	/*** get input data ***/
+	 points = ( *bytes - bytecount ) / state->inout_size ;
+	 points = MIN( points, state->upsample_factor * SEGMENT ) ;
+
+	 if( !state->active ) {
+
+	     if( state->sample_delay == 0 )
+		 state->active = 1 ;
+
+	     else if( state->sample_delay > points )
+		      state->sample_delay -= points ;
+
+		  else {
+		      points = state->sample_delay ;
+		      state->sample_delay = 0 ;
+		  }
+	 }
+
+	 if( state->iptr + ( points - 1 ) / state->upsample_factor >= SEGMENT ) {
+	     state->input = Pull( state->source, SEGMENT * state->inout_size ) ;
+	     state->iptr -= SEGMENT ;
+	 }
+
+	/*** fill output buffer with input points interspaced with zeros prior to FIR filtering ***/
+	 pstart =  ( DataType * ) state->input ;       
+	 optr = ( DataType * ) ( buffer + bytecount ) ;
+	 eptr = optr + points ;
+
+	 while( optr < eptr ) {
+       
+	     if( ( state->zerocount %= state->upsample_factor ) > 0 ) 
+		 *optr++ = 0 ;
+
+	     else
+		 *optr++ = pstart[state->iptr++] ; 
+
+	     state->zerocount++ ; 
+	 }
+
+	/*** filter data ***/
+	 state->proc( state->states, buffer+bytecount, points ) ; 
+	    
+	/*** loop counts ***/ 
+	 bytecount += points * state->inout_size * state->active ;
+     }
+
+     return ( buffer ) ;
+  }
+
+
+ /***** close *****/
+  else {
+     Pull( state->source, 0 ) ;
+     state->close( state->states ) ;
+
+     return ( DeleteFillableSource( state ) ) ;
+  }
+
+}
+
+
+/****************************** UpSample() **********************************/
+
+Source UpSample( source, oldsamplerate, cutoff_freq, upsample_factor )
+  Source source ;
+  double oldsamplerate, cutoff_freq ;
+  int    upsample_factor ;
+{
+  DeclareNew( struct _upsample_state *, state ) ;
+  double filterGain, wc ;
+
+ /***** initialise input-related parameters *****/
+  state->inout_size = sizeof ( DataType ) ;
+  state->input  = ( Pointer ) 0 ;
+  state->iptr = SEGMENT ;
+  state->source = NewRetainingSource( source, SEGMENT * state->inout_size ) ;
+  state->zerocount = 0 ;
+  state->upsample_factor = upsample_factor ;    
+
+ /***** Specify FIR filter design parameters *****/
+  wc = cutoff_freq / ( state->upsample_factor * oldsamplerate ) * TwoPi ;
+  state->states = NewLpFIRfilter( wc, upsample_factor, &state->sample_delay ) ; 
+  state->active = 0 ;
+  state->proc = DoFIRfilter ;
+  state->close = CloseFIRfilter ;
+
+ /***** return *****/
+  source = SetFillableSource( state, upsample_callback, "upsample buffering" ) ;
+  return ( source ) ;
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/upsample.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,68 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    upsample.h
+    ===========================================================
+
+    Upsampling module (FIR interpolation method).
+
+    Author        : Christian Giguere
+    First written : 11th November, 1990
+    Last edited   : 07th February, 1994
+    ============================================================
+*/
+
+#ifndef _UPSAMPLE_H_
+
+
+/***** defines *****/
+
+#define _UPSAMPLE_H_
+
+#define AUTO            (          4 )
+#define MAXSIGNALFREQ   (      20000 )
+
+
+/***** externals *****/
+
+extern Source UpSample() ;
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/wdf_ear.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,844 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    wdf_ear.c 
+    ===========================================================
+
+    Wave digital filter (WDF) implementation of the outer and 
+    middle ear (EAR) electroacoustic networks.
+
+    Author        : Christian Giguere
+    First written : 01st June, 1991
+    Last edited   : 18th February, 1994
+    
+    References:
+    (1) C.Giguere and P.C.Woodland (1992). Technical Report
+	CUED/F-INFENG/TR.93, University of Cambridge.
+    (2) C.Giguere and P.C.Woodland (1994). JASA 95(1): 331-342.
+    (3) M.E.Lutman and A.M.Martin (1979). J.Sound.Vib. 64(1): 133-157
+    (4) A.Fettweis (1986). Proceedings IEEE 74(2): 270-327.
+
+    Note: Ref (1) describes an implementation where the outer 
+	  ear and middle ear module is _UNCOUPLED_ to the cochlea. 
+	  In this case, the middle ear network is that of Lutman 
+	  and Martin (1979) unmodified.
+
+	  Ref (2) describes an implementation where the outer
+	  ear and middle ear module is _COUPLED_ to the cochlea.
+	  In this case, the middle ear network is a modified
+	  version of Lutman and Martin (1979) network (See Fig.2)
+    ===========================================================
+*/
+
+
+/***** includes *****/
+
+#include <math.h>
+#include <stdio.h>
+#include "stitch.h"
+#include "calc.h"
+#include "calc_tl.h"
+#include "wdf_ear.h"
+
+/***** defines *****/
+
+#define   N_OF_FREEFIELD_STATES    (           12 )
+#define   N_OF_EARTUBE_STATES      (           16 )      /* per segment */
+#define   N_OF_EARMIDDLE_STATES    (           48 )  
+
+#if 0
+#define   _DEBUG_   
+#define   _OVERFLOW_
+#endif
+
+#if 0
+#define   _IMPULSE_     	   /* bypasses input wave with a delta impulse */
+#endif
+
+#if 0
+#define   _EARDRUM_		   /* outputs eardrum pressure instead of stapes velocity */
+#endif
+
+/* Middle ear circuit elements in CGS units (From Lutman and Martin (1979) */
+
+#define   La                       (     14.0e-03 )      /* Middle ear cavities */
+#define   Cp                       (      5.1e-06 )     
+#define   Ra                       (         10.0 )    
+#define   Rm                       (        390.0 )    
+#define   Ct                       (     0.35e-06 )    
+#define   Rd1                      (        200.0 )      /* Eardrum losses */
+#define   Cd1                      (      0.8e-06 )    
+#define   Cd2                      (      0.4e-06 )    
+#define   Rd2                      (        220.0 )    
+#define   Ld                       (     15.0e-03 )    
+#define   Rd3                      (       5900.0 )    
+#define   Cd3                      (      0.2e-06 )    
+#define   Lo                       (     40.0e-03 )      /* Eardrum, mallus, incus */
+#define   Co                       (      1.4e-06 )    
+#define   Ro                       (         70.0 )    
+#define   Cs                       (     0.25e-06 )      /* Incudo-stapedial joint */
+#define   Rs                       (       3000.0 )    
+#define   Lc                       (     45.0e-03 )      /* Stapes and cochlea */
+#define   Cc                       (      0.6e-06 )    
+#define   Rc                       (        550.0 )    
+
+/* Additional middle ear circuit elements in CGS units (From Giguere and Woodland (1994) */
+
+#define   Ral                      (        100.0 )      /* annular ligaments */
+#define   Kst_max                  (   1./0.1e-06 )      /* max. Stapedius stiffness */
+#define   Kst_min_ratio            (       0.0001 )      /* min value of Kst_ratio */
+
+
+/***** external variables *****/
+
+double Kst_ratio = Kst_min_ratio ;                       /* initial fraction of Kst_max */
+							 /* updated by feedback module */
+static double rn_1 ; 
+
+
+/***** functions *****/
+
+/******************************* WDF set-up functions ************************************
+* name:                 function:
+*
+* FreefieldWDF()        Set-up function for the WDF implementation of the external ear network
+*                       (Giguere and Woodland, 1994, Figs. 1 and 8). It generates the multiplier 
+*                       coefficients and initializes the states of the filter. 
+*
+*                       In the case of the _UNCOUPLED_ ear version, it is called by the 
+*                       function ``Ear()'' in file ``ear.c''.
+*                       In the case of the _COUPLED_ ear version, it is called by the 
+*                       function ``TLF_GenBank()'' in file ``bank_tl.c''.
+*
+*                       It returns a pointer to a structure containing all the relevant 
+*                       information for the computation of the whole filter.
+*
+* EartubeWDF()          Set-up function for the WDF implementation of the concha and auditory
+*                       canal transmission lines (Giguere and Woodland, 1994, Figs. 1 and 8). 
+*                       It generates the multiplier coefficients and initializes the states 
+*                       of the filter.
+*
+*                       In the case of the _UNCOUPLED_ ear version, it is called by the 
+*                       function ``Ear()'' in file ``ear.c'' once for each segment of the 
+*                       transmission lines starting from the outermost segment.
+*                       In the case of the _COUPLED_ ear version, it is called by the 
+*                       function ``TLF_GenBank()'' in file ``bank_tl.c'' once for each segment 
+*                       of the transmission lines starting from the outermost segment.
+*
+*                       It returns a pointer to a structure containing all the relevant 
+*                       information for the current filter segment.
+*
+* EarmiddleWDF()        Set-up function for the WDF implementation of the middle ear network
+*                       (Giguere and Woodland, 1994, Figs. 2 and 9). It generates the multiplier 
+*                       coefficients and initializes the states of the filter. 
+*
+*                       In the case of the _UNCOUPLED_ ear version, it is called by the 
+*                       function ``Ear()'' in file ``ear.c''.
+*                       In the case of the _COUPLED_ ear version, it is called by the 
+*                       function ``TLF_GenBank()'' in file ``bank_tl.c''.
+*
+*                       It returns a pointer to a structure containing all the relevant 
+*                       information for the computation of the whole filter.
+******************************************************************************************/
+
+/************************** FreefieldWDF() *****************************/
+
+WaveWDFstate *FreefieldWDF( samplerate, rho, velocity, diffraction_radius, radiation_radius )
+    double  samplerate ;
+    double  rho, velocity ;
+    double  diffraction_radius, radiation_radius ;
+{
+    DeclareNew( WaveWDFstate *, filter_state ) ;
+    double  fs2 ;
+    double  r1, r2, r3, g1, g2, g3 ;
+    double  zh, zr ;
+    double  Lh, Rh, Lr, Rr ;
+ 
+   /*** electrical circuit elements (CGS) ***/
+    Rh = rho * velocity / ( Pi * diffraction_radius * diffraction_radius ) ;
+    Lh = 0.5 * rho / ( Pi * diffraction_radius ) ;
+    Rr = rho * velocity / ( Pi * radiation_radius * radiation_radius ) ;
+    Lr = 0.7 * rho / ( Pi * radiation_radius ) ;
+
+   /*** sampling frequency ***/
+    fs2 = samplerate * 2. ;
+ 
+   /*** WDF-port resistances and multiplier coefficients ***/
+ 
+    /* Adaptor 0 */
+    g1 = 1. / ( fs2 * Lh ) ;                                    /* (1 / Zlh) */
+    g2 = 1. / Rh ;                                              /* (1 / Zrh) */
+    g3 = g1 + g2 ;
+    zh = 1. / g3 ;
+    filter_state->gamma01 = g1 / g3 ;
+
+    /* Adaptor 2 */
+    g1 = 1. / ( fs2 * Lr ) ;                                    /* (1 / Zlr) */
+    g2 = 1. / Rr ;                                              /* (1 / Zrr) */
+    g3 = g1 + g2 ;
+    zr = 1. / g3 ;
+    filter_state->gamma21 = g1 / g3 ;
+
+    /* Adaptor 1 */
+    r1 = zh ;
+    r2 = zr ;
+    r3 = rn_1 = r1 + r2 ;
+    filter_state->gamma11 = r1 / r3 ;
+
+#ifdef _DEBUG_
+    fprintf( stderr, "Rh=%e  Lh=%e  Rr=%e  Lr=%e\n", Rh, Lh, Rr, Lr ) ;
+    fprintf( stderr, "gamma01=%f\n", filter_state->gamma01 ) ;
+    fprintf( stderr, "gamma11=%f\n", filter_state->gamma11 ) ;
+    fprintf( stderr, "gamma21=%f\n", filter_state->gamma21 ) ;                                            
+#endif
+
+   /*** initialise filter states ***/
+    filter_state->Nstates = N_OF_FREEFIELD_STATES ;
+    filter_state->states = ( char * ) NewZeroedArray( StateType, filter_state->Nstates,
+						      "wdf_ear.c for freefield states\n" ) ;
+
+   /*** return ***/
+    return( filter_state ) ;
+}
+
+/************************** EartubeWDF() *****************************/
+
+EartubeWDFstate *EartubeWDF( samplerate, rho, velocity, diam, seglength, attn )
+    double  samplerate ;
+    double  rho, velocity ;
+    double  diam, seglength ;
+    double  attn ;
+{
+    DeclareNew( EartubeWDFstate *, filter_state ) ;
+    double  an, d, c, k, alpha, fs2 ;
+    double  Ln, Cn, Gn, Zn ;
+    double  r1, r2, r3, g1, g2, g3, r33, g43, g53 ;
+
+   /*** acoustic tube parameters for current segment ***/
+    an = Pi * diam * diam / 4. ;                /* cross-sectional area of tube (cm2) */
+    d = seglength;                              /* length of tube (cm) */ 
+    c = velocity ;                              /* sound velocity in air (cm/s) */
+    alpha = attn ;                              /* attenuation constant of travelling waves (1/cm) */
+
+   /*** sampling frequency ***/
+    fs2 = samplerate * 2. ;
+
+   /*** electrical circuit elements (CGS units) for current segment ***/
+    Ln = ( rho * d ) / an ;                     /* series inductor (either Lch or Lcl) */
+    Cn = ( an * d ) / ( rho * c * c ) ;         /* shunt capacitor (either Cch or Ccl) */
+    Zn = sqrt( Ln / Cn ) ;                      /* characteristic impedance ( either Zch or Zcl) */
+    Gn = 2. / Zn * alpha * d ;                  /* shunt conductance (either Gch or Gcl) */
+
+   /*** WDF multiplier coefficients for current tube segment ***/
+
+    /* Adaptor 3 */
+    r1 = fs2 * Ln / 2. ;                                        /* 0.5 Zl */
+    r2 = rn_1 ;
+    r3 = r33 = r1 + r2 ;
+    filter_state->gamma31 = r1 / r3 ;
+
+    /* Adaptor 5 */
+    g1 = Gn ;                                                   /* (1 / Zg ) */
+    g2 = fs2 * Cn ;                                             /* (1 / Zc ) */
+    g3 = g53 = g1 + g2 ;
+    filter_state->gamma51 = g1 / g3 ;
+
+    /* Adaptor 4 */
+    g1 = 1 / r33 ;
+    g2 = g53 ;
+    g3 = g43 = g1 + g2 ;
+    filter_state->gamma41 = g1 / g3 ;
+
+    /* Adaptor 6 */
+    r1 = 1 / g43 ;
+    r2 = fs2 * Ln / 2. ;                                        /* 0.5 Zl */
+    r3 = rn_1 = r1 + r2 ;
+    filter_state->gamma61 = r1 / r3 ;
+
+#ifdef _DEBUG_
+    fprintf( stderr, "gamma31=%f ", filter_state->gamma31 ) ;
+    fprintf( stderr, "gamma41=%f ", filter_state->gamma41 ) ;
+    fprintf( stderr, "gamma51=%f ", filter_state->gamma51 ) ;                                            
+    fprintf( stderr, "gamma61=%f\n", filter_state->gamma61 ) ;  
+#endif
+
+   /*** initialise filter states ***/
+    filter_state->Nstates = N_OF_EARTUBE_STATES ;
+    filter_state->states =  ( char * ) NewZeroedArray( StateType, filter_state->Nstates,
+						       "wdf_ear.c for earcanal states\n" ) ;
+
+   /*** return ***/
+    return( filter_state ) ;
+}
+
+
+/********************** EarmiddleWDF() ***************************/
+
+EarmiddleWDFstate *EarmiddleWDF( samplerate, zov, output_scale, ratio )
+    double  samplerate, zov, output_scale, ratio ;
+{
+    DeclareNew( EarmiddleWDFstate *, filter_state ) ;
+    double  fs2 ;
+    double  r1, r2, r3, r4, g1, g2, g3, g4 ;
+    double  r73, r84, r94, r103, r114, r123, r133, r143, r153 ;
+    double  r163, r174, r183, r193, r204, r214 ;
+    void    update_earmiddle_init(), update_earmiddle() ;
+
+   /*** sampling frequency ***/
+    fs2 = samplerate * 2. ;
+
+   /*** WDF-port resistances and multiplier coefficients ***/
+ 
+    /* Adaptor 9 */
+    r1 = 1. / ( fs2 * Cp ) ;                                    /* Zcp */
+    r2 = Ra ;                                                   /* Zra */
+    r3 = fs2 * La ;                                             /* Zla */
+    r4 = r94 = r1 + r2 + r3 ;
+    filter_state->gamma91 = r1 / r4 ;
+    filter_state->gamma92 = r2 / r4 ;
+
+    /* Adaptor 8 */
+    g1 = 1. / r94 ;
+    g2 = 1. / Rm ;                                              /* (1 / Zrm) */
+    g3 = fs2 * Ct ;                                             /* (1 / Zct) */
+    g4 = g1 + g2 + g3 ;
+    r84 = 1. /g4 ;
+    filter_state->gamma81 = g1 / g4 ;
+    filter_state->gamma82 = g2 / g4 ;
+
+    /* Adaptor 7 */
+    r1 = r84 ;
+    r2 = rn_1 ;
+    r3 = r73 = r1 + r2 ;
+    filter_state->gamma71 = r1 / r3 ;
+
+    /* Adaptor 13 */
+    r1 = 1. / ( fs2 * Cd2 ) ;                                   /* Zcd2 */
+    r2 = Rd2 ;                                                  /* Zrd2 */
+    r3 = r133 = r1 + r2 ;
+    filter_state->gamma131 = r1 / r3 ;
+
+    /* Adaptor 12 */
+    g1 = 1. / ( fs2 * Ld ) ;                                    /* (1 / Zld) */
+    g2 = 1. / r133 ;
+    g3 = g1 + g2 ;
+    r123 = 1. / g3 ;
+    filter_state->gamma121 = g1 / g3 ;
+
+    /* Adaptor 14 */
+    g1 = 1. / Rd3 ;                                             /* (1 / Zrd3) */
+    g2 = fs2 * Cd3 ;                                            /* (1 / Zcd3) */
+    g3 = g1 + g2 ;
+    r143 = 1. / g3 ;
+    filter_state->gamma141 = g1 / g3 ;
+
+    /* Adaptor 15 */
+    r1 = 1. / ( fs2 * Cd1 ) ;                                   /* Zcd1 */
+    r2 = Rd1 ;                                                  /* Zrd1 */
+    r3 = r153 = r1 + r2 ;
+    filter_state->gamma151 = r1 / r3 ;
+
+    /* Adaptor 11 */
+    r1 = r143 ;
+    r2 = r123 ;
+    r3 = r153 ;
+    r4 = r114 = r1 + r2 + r3 ;
+    filter_state->gamma111 = r1 / r4 ;
+    filter_state->gamma112 = r2 / r4 ;
+
+    /* Adaptor 10 */
+    g1 = 1. / r114 ;
+    g2 = 1. / r73 ;
+    g3 = g1 + g2 ;
+    r103 = 1. /g3 ;
+    filter_state->gamma101 = g1 / g3 ;
+ 
+    /* Adaptor 17 */
+    r1 = 1. / ( fs2 * Co ) ;                                    /* Zco */
+    r2 = Ro ;                                                   /* Zro */
+    r3 = fs2 * Lo ;                                             /* Zlo */
+    r4 = r174 = r1 + r2 + r3 ;
+    filter_state->gamma171 = r1 / r4 ;
+    filter_state->gamma172 = r2 / r4 ;
+
+    /* Adaptor 16 */
+    r1 = r103 ;
+    r2 = r174 ;
+    r3 = r163 = r1 + r2 ;
+    filter_state->gamma161 = r1 / r3 ;
+
+    /* Adaptor 19 */
+    r1 = 1. / ( fs2 * Cs ) ;                                    /* Zcs */
+    r2 = Rs ;                                                   /* Zrs */
+    r3 = r193 = r1 + r2 ;
+    filter_state->gamma191 = r1 / r3 ;
+
+    /* Adaptor 18 */
+    g1 = 1. / r163 ;
+    g2 = 1. / r193 ;
+    g3 = g1 + g2 ;
+    r183 = 1. / g3 ;
+    filter_state->gamma181 = g1 / g3 ;
+
+    /* Adaptor 20 */
+#ifdef _DEBUG_
+    fprintf( stderr, "Zov=%e\n", zov ) ;
+#endif
+    if( zov != 0. ) {                                           /* coupled version ? */
+      r1 = Ral ;                                                /* Zral */
+      r2 = zov / ( ratio * ratio ) ;                            /* Zov / (r*r) */
+    }
+    else {                                                      /* uncoupled version */
+      r1 = 0.0 ;
+      r2 = Rc ;                                                 /* Zrc */
+    }
+    r3 = r183 ;
+    r4 = r204 = r1 + r2 +r3 ;
+    filter_state->gamma201 = r1 / r4 ;
+    filter_state->gamma202 = r2 / r4 ;
+    filter_state->ratio = ratio ;
+
+    /* Adaptor 21 */
+    r1 = 1. / ( fs2 * Cc ) ;                                    /* Zcc */
+    r2 = r204 ;
+    if( zov != 0. )                                             /* coupled version ? */
+      r3 = 0.0 ;
+    else                                                        /* uncoupled version */
+      r3 = fs2 * Lc ;                                           /* Zlc */
+    r4 = r214 = r1 + r2 + r3 ;
+    filter_state->gamma211 = r1 / r4 ;
+    filter_state->gamma212 = r2 / r4 ;
+    
+    /* Adaptor 22 */
+    r1 = Kst_ratio * Kst_max / fs2 ;                            /* Zcst (initial value only) */
+    r2 = r214 ;
+    r3 = r1 + r2 ;
+    filter_state->gamma221 = 2. * r1 / r3 ;
+
+#ifdef _DEBUG_
+    fprintf ( stderr, "gamma71 =%f            \n", filter_state->gamma71  ) ;
+    fprintf ( stderr, "gamma81 =%f gamma82 =%f\n", filter_state->gamma81
+						 , filter_state->gamma82  ) ;
+    fprintf ( stderr, "gamma91 =%f gamma92 =%f\n", filter_state->gamma91
+						 , filter_state->gamma92  ) ;
+    fprintf ( stderr, "gamma101=%f            \n", filter_state->gamma101 ) ;
+    fprintf ( stderr, "gamma111=%f gamma112=%f\n", filter_state->gamma111
+						 , filter_state->gamma112 ) ;
+    fprintf ( stderr, "gamma121=%f            \n", filter_state->gamma121 ) ;
+    fprintf ( stderr, "gamma131=%f            \n", filter_state->gamma131 ) ;
+    fprintf ( stderr, "gamma141=%f            \n", filter_state->gamma141 ) ;
+    fprintf ( stderr, "gamma151=%f            \n", filter_state->gamma151 ) ;
+    fprintf ( stderr, "gamma161=%f            \n", filter_state->gamma161 ) ;
+    fprintf ( stderr, "gamma171=%f gamma172=%f\n", filter_state->gamma171
+						 , filter_state->gamma172 ) ;
+    fprintf ( stderr, "gamma181=%f            \n", filter_state->gamma181 ) ;
+    fprintf ( stderr, "gamma191=%f            \n", filter_state->gamma191 ) ;
+    fprintf ( stderr, "gamma201=%f gamma202=%f\n", filter_state->gamma201
+						 , filter_state->gamma202 ) ;
+    fprintf ( stderr, "gamma211=%f gamma212=%f\n", filter_state->gamma211
+						 , filter_state->gamma212 ) ;
+    fprintf ( stderr, "gamma221=%f            \n", filter_state->gamma221 ) ;
+#endif  
+
+   /*** specify and initialise coefficient update procedure ***/
+    filter_state->update_proc = update_earmiddle ; 
+    ( void ) update_earmiddle_init( fs2, r214 ) ;
+
+   /*** output scaling ***/ 
+    filter_state->out_scale = output_scale ;
+
+   /*** initialise filter states ***/
+    filter_state->Nstates = N_OF_EARMIDDLE_STATES ;
+    filter_state->states = ( char * ) NewZeroedArray( StateType, filter_state->Nstates, 
+						      "wdf_ear.c for middle ear states\n" ) ;
+
+   /*** return ***/
+    return( filter_state ) ;
+}
+
+
+/*********************************** WDF procedures ***************************************
+* name:                 function:
+*
+* DoEarWDF()            WDF realization of the _UNCOUPLED_ version of the outer ear and 
+*                       middle ear networks. It is called by function ``ear_callback()'' 
+*                       in file ``ear.c'' once for a specified number of input points. 
+*                       It computes the stapes velocity for each input point and keeps 
+*                       track of the filter states.  
+*
+*                       Note: The code for the realization of the _COUPLED_ ear version         
+*                             is located in file ``wdf_tl.c''.
+*
+*
+* CloseEarWDF()         Deletes all private data structures and arrays of the outer and 
+*                       middle ear filter upon completion of filtering. 
+*                       In the case of the _UNCOUPLED_ ear version, it is called by the 
+*                       function ``ear_callback()'' in file ``ear.c''.
+*                       In the case of the _COUPLED_ ear version, it is called by the 
+*                       function ``tlf_bank_callbank()'' in file ``bank_tl.c''.
+******************************************************************************************/
+
+/******************************* DoEarWDF() **************************************/
+
+void DoEarWDF( ws, eartube_states, ms, tube_segments, inout_ptr, points )
+    register WaveWDFstate       *ws ;
+    register EartubeWDFstate    **eartube_states ;
+    register EarmiddleWDFstate  *ms ;
+    register int                tube_segments ;
+    register DataType           *inout_ptr ;
+    register int                points ;
+{
+    register EartubeWDFstate    *ts ;
+    register StateType          *st, in, out ;
+    register StateType          a0, an_1, b1, b2, b3, b161, b202, b212, bn ;
+    register int                tube_segment = -1 ;
+#ifdef _IMPULSE_
+    static   int                impulse = 10000 ;
+#endif
+
+
+    /***** update stapedial muscle state *****/
+
+     ( void ) ms->update_proc( ms ) ;
+
+    /***** for all points *****/
+
+     while( points-- > 0 ) {
+
+     /*** input point ***/
+
+	in = ( StateType ) *inout_ptr ;
+
+#ifdef _IMPULSE_
+	if( impulse != 0 )  {
+	   in = ( StateType ) impulse ;
+	   impulse = 0 ;
+	}
+	else 
+	   in = ( StateType ) 0 ;
+#endif
+
+     /*** computation in FORWARD direction for current input point ***/
+
+     /* freefield - external ear */
+
+	/* get states */
+	st = ( StateType * ) ws->states ;      
+
+	/* Adaptor 0 */
+	st[4] = ws->gamma01 * ( st[3] - in ) ;                /* b00 */
+	st[5] = st[4] + in + in ;                             /* b03 = -a11 */
+
+	/* Adaptor 2 */
+	st[1] = -ws->gamma21 * st[0] ;                        /* b20 */
+	st[2] = st[1] ;                                       /* b23 = a12 */
+
+	/* Adaptor 1 */
+	st[6] = st[5] - st[2] ;                               /* b13 = a32 */
+	an_1 = st[6] ;
+
+     /* concha and auditory canal */
+
+	while( ++tube_segment < tube_segments ) {
+
+	   /* get states */
+	   ts = *eartube_states++ ;
+	   st = ( StateType * ) ts->states ;
+
+	   /* Adaptor 3 */
+	   st[3] = st[4] - an_1 ;                             /* b33 = a41 */
+
+	   /* Adaptor 5 */
+	   st[0] = -ts->gamma51 * st[1] ;                     /* b50 */
+	   st[2] = st[0] + st[1] ;                            /* b53 = a42 */
+ 
+	   /* Adaptor 4 */
+	   st[5] = st[3] - st[2] ;                            /* -a42+a41 */
+	   st[6] = ts->gamma41 * st[5] ;                      /* b40 */
+	   st[7] = st[6] + st[2] ;                            /* b43 = a61 */
+
+	   /* Adaptor 6 */
+	   st[8] = st[9] - st[7] ;                            /* b63 = a32 */
+	   an_1 = st[8] ;
+	}
+
+     /* middle ear */
+
+	/* get states */
+	st = ( StateType * ) ms->states ;      
+
+	/* Adaptor 9 */
+	st[31] = st[30] - st[29] ;                           /* b94 = a81 */
+
+	/* Adaptor 8 */
+	st[32] = st[35] - st[31] ;                           /* a83-a81 */
+	st[33] = -ms->gamma81 * st[32] - ms->gamma82 * st[35] ;   /* b80 */ 
+	st[34] = st[33] + st[35] ;                           /* b84 = a71 */
+
+	/* Adaptor 7 */
+	st[36] = -st[34] - an_1 ;                            /* b73 = a102 */
+
+	/* Adaptor 13 */
+	st[15] = -st[14] ;                                   /* b133 = a122 */
+
+	/* Adaptor 12 */
+	st[16] = st[15] + st[18] ;                           /* a122-a121 */
+	st[17] = -ms->gamma121 * st[16] ;                    /* b120 */
+	st[19] = st[17] + st[15] ;                           /* b123 = a112 */
+
+	/* Adaptor 14 */
+	st[21] = -ms->gamma141 * st[20] ;                    /* b140 */
+	st[22] = st[21] + st[20] ;                           /* b143 = a111 */
+
+	/* Adaptor 15 */
+	st[23] = -st[24] ;                                   /* b153 = a113 */
+
+	/* Adaptor 11 */
+	st[25] = -st[22] - st[19] - st[23] ;                 /* b114 = a101 */
+
+	/* Adaptor 10 */
+	st[26] = st[25] - st[36] ;                           /* -a102+a101 */
+	st[27] = ms->gamma101 * st[26] ;                     /* b100 */
+	st[28] = st[27] + st[36] ;                           /* b103 = a161 */
+
+	/* Adaptor 17 */
+	st[10] = st[12] - st[11] ;                           /* b174 = a162 */
+	
+	/* Adaptor 16 */
+	st[13] = -st[28] - st[10] ;                          /* b163 = a181 */
+
+	/* Adaptor 19 */
+	st[5] = -st[6] ;                                     /* b193 = a182 */
+
+	/* Adaptor 18 */
+	st[7] = st[13] - st[5] ;                             /* -a182+a181 */
+	st[8] = ms->gamma181 * st[7] ;                       /* b180 */
+	st[9] = st[8] + st[5] ;                              /* b183 = a203 */
+
+	/* Adaptor 20 */
+	st[3] = -st[9] ;                                     /* b204 = a212 */
+
+	/* Adaptor 21 */
+	st[0] = st[2] - st[1] - st[3] ;                      /* b214 = a222 */
+
+
+     /*** computation in BACKWARD direction for current input point ***/
+
+     /* middle ear */
+
+	/* Adaptor 22 */
+	a0 = st[4] + st[0] ;                                  /* a220 */
+	st[4] = st[4] - ms->gamma221 * a0 ;                   /* b221 */
+	b2 = -st[4] - a0 ;                                    /* b222 = a214 */
+
+	/* Adaptor 21 */
+	a0 = b2 - st[0] ;                                     /* a210 */
+	st[1] = st[1] - ms->gamma211 * a0 ;                   /* b211 */
+	b212 = st[3] - ms->gamma212 * a0 ;                    /* b212 = a204 */
+	st[2] = -st[1] - b212 - b2 ;                          /* b213 */
+
+	/* Adaptor 20 */
+	a0 = b212 - st[3] ;                                   /* a200 */
+	b202 = - ms->gamma202 * a0 ;                          /* b202 */
+	b3 = ms->gamma201 * a0 - b202 - b212 ;                /* b203 = a183 */
+
+	/* Adaptor 18 */
+	b2 = st[8] + b3 ;                                     /* b182 = a193 */
+	b1 = b2 - st[7] ;                                     /* b181 = a163 */
+
+	/* Adaptor 19 */
+	st[6] = st[6] + ms->gamma191 * ( st[5] - b2 ) ;       /* b191 */
+
+	/* Adaptor 16 */
+	b161 = st[28] + ms->gamma161 * ( st[13] - b1 ) ;      /* b161 = a103 */
+	b2 = -b161 - b1 ;                                     /* b162 = a174 */
+
+	/* Adaptor 17 */
+	a0 = b2 - st[10] ;                                    /* a170 */
+	st[11] = st[11] - ms->gamma171 * a0 ;                 /* b171 */
+	st[12] = ms->gamma172 * a0 - b2 - st[11] ;            /* b173 */
+ 
+	/* Adaptor 10 */
+	st[37] = st[27] + b161 ;                              /* b102 = a73 */
+	st[38] = st[37] - st[26] ;                            /* b101 = a114 */
+
+	/* Adaptor 11 */
+	a0 = st[38] - st[25] ;                                /* a110 */
+	b1 = st[22] - ms->gamma111 * a0 ;                     /* b111 = a143 */
+	b2 = st[19] - ms->gamma112 * a0 ;                     /* b112 = a123 */
+	b3 = -b1 -b2 - st[38] ;                               /* b113 = a153 */
+
+	/* Adaptor 15 */
+	st[24] = st[24] + ms->gamma151 * ( st[23] - b3 ) ;    /* b151 */
+
+	/* Adaptor 14 */
+	st[20] = st[21] + b1 ;                                /* b142 */
+
+	/* Adaptor 12 */
+	b2 = st[17] + b2 ;                                    /* b122 = a133 */
+	st[18] = b2 + st[16] ;                                /* b121 */
+
+	/* Adaptor 13 */
+	st[14] = st[14] + ms->gamma131 * ( st[15] - b2 ) ;    /* b131 */
+
+	/* Adaptor 7 */
+	b1 = st[34] + ms->gamma71 * ( st[36] - st[37] ) ;     /* b71 = a84 */
+	st[39] = -b1 - st[37] ;                               /* b72 = a63 */
+
+	/* Adaptor 8 */
+	st[35] = st[33] + b1 ;                                /* b83 */
+	b1 = st[35] + st[32] ;                                /* b81 = a94 */
+
+	/* Adaptor 9 */
+	a0 = b1 - st[31] ;                                    /* a90 */
+	st[29] = st[29] - ms->gamma91 * a0 ;                  /* b91 */
+	st[30] = -st[29] + ms->gamma92 * a0 - b1 ;            /* b93 */
+
+     bn = st[39] ;
+
+     /* concha and auditory canal */
+
+	while( tube_segment-- > 0 ) {
+
+	   /* get states */
+	   ts = *--eartube_states ;
+	   st = ( StateType * ) ts->states ;
+
+	   /* Adaptor 6 */
+	   b1 = st[7] - ts->gamma61 * ( bn - st[8] ) ;        /* b61 = a43 */
+	   st[9] = -b1 - bn ;                                 /* b62 */
+
+	   /* Adaptor 4 */
+	   b2 = st[6] + b1 ;                                  /* b42 = a53 */
+	   b1 = b2 - st[5] ;                                  /* b41 = a33 */
+
+	   /* Adaptor 5 */
+	   st[1] = st[0] + b2 ;                               /* b52 */
+
+	   /* Adaptor 3 */
+	   st[4] = ts->gamma31 * ( st[3] - b1 ) - st[4] ;     /* b31 */
+	   bn = -st[4] - b1 ;                                 /* b32 = a63 */
+	}
+
+     /* freefield - external ear */
+
+	/* get states */
+	st = ( StateType * ) ws->states ;      
+
+	/* Adaptor 1 */
+	b1 = ws->gamma11 * ( st[6] - bn ) - st[5] ;           /* b11 = -a03 */
+	b2 = -b1 - bn ;                                       /* b12 = a23 */
+
+	/* Adaptor 2 */
+	st[0] = st[1] + b2 + st[0] ;                          /* b61 */
+
+	/* Adaptor 0 */
+	st[3] = b1 - st[4] + st[3] ;                          /* -b01 + p */
+
+     /*** output ***/
+#ifdef _EARDRUM_
+	st = ( StateType * ) ms->states ;      
+	out = 0.5 * ( st[39] + an_1 ) * ms->out_scale ; 
+#else
+	out = -0.5 * b202 * ms->out_scale ; 
+#endif
+
+#ifdef _OVERFLOW_
+        if( out > _MaxOutput_ || out < _MinOutput_ )
+	   fprintf( stderr, "Overflow error in Outer/Middle ear output=%e\n", ( double ) out ) ;
+#endif     
+	*inout_ptr++ = out ; 
+
+    }
+    return ;
+}
+
+
+/******************************* CloseEarWDF() *************************************/
+
+void CloseEarWDF( wave_states, eartube_states, earmiddle_states, tube_segments )
+  register WaveWDFstate       *wave_states ;
+  register EartubeWDFstate    **eartube_states ;
+  register EarmiddleWDFstate  *earmiddle_states ;
+  register int                tube_segments ;
+{
+  Delete( earmiddle_states->states ) ;
+  Delete( earmiddle_states ) ;
+
+  for( ; --tube_segments < 0 ; ) {
+     Delete( eartube_states[ tube_segments ]->states ) ;
+     Delete( eartube_states[ tube_segments ] ) ;
+  }
+  Delete( eartube_states ) ; 
+
+  Delete( wave_states->states ) ;
+  Delete( wave_states ) ;
+
+  return ;
+
+}
+
+/************** low level functions **************/
+
+static double den221 ;
+static double Kst_old_ratio ; 
+
+void update_earmiddle_init( rate, z )
+  double rate, z ;
+{
+  Kst_old_ratio = Kst_ratio ; 
+  den221 = rate * z / Kst_max ;
+  return ;
+}
+
+void update_earmiddle( ms )
+  EarmiddleWDFstate *ms ;
+{
+  if( Kst_ratio < Kst_min_ratio )
+    Kst_ratio = Kst_min_ratio ;
+
+  ms->gamma221 = 2. * Kst_ratio / ( Kst_ratio + den221 ) ;
+  ms->states[4] = ms->states[4] * Kst_ratio / Kst_old_ratio ;
+
+  Kst_old_ratio = Kst_ratio ;
+ 
+  return ;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/wdf_ear.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,117 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    ===========================================================
+    wdf_ear.h 
+    ===========================================================
+
+    Wave digital filter (WDF) implementation of the outer and
+    middle ear (EAR) electroacoustic networks.
+ 
+    Author        : Christian Giguere
+    First written : 01st July, 1991 
+    Last edited   : 17th February, 1994
+    ===========================================================
+*/
+
+#ifndef _WDF_EAR_H_
+
+
+/***** defines *****/
+
+#define _WDF_EAR_H_
+
+
+/***** private data structures for WDF-EAR module *****/
+
+typedef struct _wave_wdf_state      WaveWDFstate ;
+typedef struct _eartube_wdf_state   EartubeWDFstate ;
+typedef struct _earmiddle_wdf_state EarmiddleWDFstate ;
+
+struct _wave_wdf_state {
+  double gamma01 ;                        /* WDF multiplier coefficients (Adaptors 0-2) */
+  double gamma11 ;
+  double gamma21 ;
+  int    Nstates ;                        /* number of states stored */
+  char   *states ;                        /* WDF state vector */
+  } ;
+
+struct _eartube_wdf_state {
+  double gamma31 ;                        /* WDF multiplier coefficients (Adaptors 3-6) */
+  double gamma41 ;
+  double gamma51 ;
+  double gamma61 ;
+  int    Nstates ;                        /* number of states stored */
+  char   *states ;                        /* WDF state vector */
+  } ;
+
+struct _earmiddle_wdf_state {
+  double gamma71 ;                        /* WDF multiplier coefficients (Adaptors 7-22) */
+  double gamma81,  gamma82  ;
+  double gamma91,  gamma92  ;
+  double gamma101 ;
+  double gamma111, gamma112 ;
+  double gamma121 ;
+  double gamma131 ;
+  double gamma141 ;
+  double gamma151 ;
+  double gamma161 ;
+  double gamma171, gamma172 ;
+  double gamma181 ;
+  double gamma191 ;
+  double gamma201, gamma202 ;
+  double gamma211, gamma212 ;
+  double gamma221 ;
+  double ratio ;                          /* transformer ratio between oval window and eardrum */
+  void   (*update_proc)() ;               /* procedure to update time-varying coeff gamma221 */
+  int    Nstates ;                        /* number of states stored */
+  char   *states ;                        /* WDF state vector */
+  double out_scale ;                      /* output gain */
+  } ;
+
+
+/***** externals *****/
+
+extern WaveWDFstate      *FreefieldWDF() ;
+extern EartubeWDFstate   *EartubeWDF() ;
+extern EarmiddleWDFstate *EarmiddleWDF() ;
+extern void               DoEarWDF(), CloseEarWDF() ;
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/wdf_tl.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,637 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    =============================================================
+    wdf_tl.c
+    =============================================================
+
+    Wave digital filter (WDF) implementation of the cochlear 
+    transmission line (TL) network.
+
+    Author        : Christian Giguere
+    First written : 01st April, 1991
+    Last edited   : 18th February, 1994
+
+    References:
+    (1) C.Giguere and P.C.Woodland (1994). JASA 95(1): 331-342.
+    (2) A.Fettweis (1986). Proceedings IEEE 74(2): 270-327.
+    =============================================================
+*/
+
+/***** includes *****/
+
+#include <math.h>
+#include <stdio.h>
+#include "stitch.h"
+#include "source.h"
+#include "calc.h"
+#include "calc_tl.h"
+#include "bank_tl.h" 
+#include "wdf_tl.h"
+#include "wdf_ear.h"
+     
+/***** defines *****/
+
+#if 0
+#define   _DEBUG_
+#define   _OVERFLOW_
+#endif
+
+#if 0
+#define   _IMPULSE_            /* bypasses input wave with a delta impulse */
+#endif
+
+#if 0			       /* bypasses input wave with a pure tone and dumps  */
+#define   _BMCURVES_           /* the rms value of basilar membrane velocity on stdout */
+#endif			       /* (see below for other parameters to set) */
+
+#if 0
+#define   _EAR_                /* dumps stapes velocity and eardrum pressure on stdout */
+#endif
+
+#define   NUMBER_OF_STATES     (           14 )           /* per TLF segment */
+#define   NUMBER_OF_COEFFS     (            0 )           /* per TLF segment */
+
+
+/***** functions *****/
+
+/******************************** WDF set-up function *************************************
+* name:                 function:
+*
+* WDFilterState()       Set-up function for the WDF implementation of the cochlear network 
+*                       (Giguere and Woodland, 1994, Figs. 3 and 10). It generates the 
+*                       multiplier coefficients and initializes the states of the filter.
+*                       It is called by function ``TLF_GenBank()'' in file ``bank_tl.c'' 
+*                       once for each segment of the transmission line starting from the most 
+*                       apical segment. It returns a pointer to a structure containing all 
+*                       the relevant information for the computation of the current filter 
+*                       segment.
+*
+*                       Note: The code that sets up the WDF implementation of the outer ear 
+*                             and middle ear is located in file ``wdf_ear.c''.
+******************************************************************************************/
+
+/************************************ WDFilterState() ************************************/
+
+WDFilterState *WDFilter( samplerate, center_frequency, scale_vel, scale_disp, rho, scala_area, 
+			 width, qfactor, mass_per_area, seglength, Lt, warping, active, zov, 
+			 OHC_gain, OHC_sat )
+
+double  samplerate, center_frequency, scale_vel, scale_disp ;
+double  rho, scala_area, width, qfactor, mass_per_area, seglength, Lt ;
+int     warping, active ;
+double  *zov, OHC_gain, OHC_sat ;
+{
+    static int  apex = 1 ;
+    DeclareNew( WDFilterState *, filter_state ) ;
+    CoeffType *cf ;
+    double  an, bn, mn, d, fs, fn ; 
+    double  Lsn, Ln, Cn, Rn ;
+    double  r1, r2, r3, r4, g1, g2, g3, zn, zcn ;
+
+   /***** cochlear parameters for current BM segment *****/
+    an = scala_area ;                       /* cross-sectional area of each scala (cm2) */
+    bn = width ;                            /* BM width (cm) */
+    mn = mass_per_area ;                    /* transversal mass-per-area-of-BM (g/cm2) */
+    d = seglength ;                         /* BM segment length (cm) */ 
+
+   /***** frequency warping compensation due to bilinear transform *****/
+    fs = samplerate ;
+    if ( warping == 0 )
+	 fn = center_frequency ;
+    else
+	 fn = fs / Pi * tan( Pi * center_frequency / fs ) ;
+
+   /***** electrical circuit elements (CGS units) for current segment *****/
+    Ln = mn / ( bn * d ) ;                                      /* shunt inductor */
+    Cn = 1. / ( ( TwoPi * TwoPi * fn * fn ) * Ln ) ;            /* shunt capacitor */
+    Rn = sqrt( Ln / Cn ) / qfactor ;                            /* shunt resistor */
+    Lsn =  ( 2. * rho * d ) / an ;                              /* series inductor */
+
+
+   /***** WDF multiplier coefficients for current TL segment *****/
+
+   /*** initialise filter coeffs ***/
+    filter_state->coeffs = ( char * ) NewZeroedArray( CoeffType, NUMBER_OF_COEFFS, 
+						      "wdf_tl.c for filter coeffs\n" ) ;
+    cf = ( CoeffType * ) filter_state->coeffs ;
+    
+    /* Adaptor 25 */
+    r1 = zcn = 1. / (2. * fs * Cn ) ;                           /* Zcn */
+    r2 = Rn ;                                                   /* Zrn */
+    r3 = 2. * fs * Ln ;                                         /* Zln */
+    r4 = zn = r1 + r2 + r3 ;
+    filter_state->gamma251 = r1 / r4 ;
+    filter_state->gamma252 = r2 / r4 ;
+
+    /* Adaptor 24 */
+    g1 = 1. / zn ;
+    if( apex ) {
+	g2 = 1. / ( 2. * fs * Lt ) ;                            /* (1 / Zlt) */
+	apex = 0 ; 
+    }
+    else
+	g2 = 1. / *zov ;                                        /* Zov (at the base) */     
+    g3 = g1 + g2 ;
+    filter_state->gamma241 = g1 / g3 ;
+
+    /* Adaptor 23 */
+    r1 = 2. * fs * Lsn ;                                        /* Zlsn */
+    r2 = 1. / g3 ;
+    r3 = *zov = r1 + r2 ;                                       /* Zov */
+    filter_state->gamma231 = r1 / r3 ; 
+
+#ifdef _DEBUG_
+    fprintf( stderr, "gamma251=%f gamma252=%f\n", filter_state->gamma251
+						, filter_state->gamma252 ) ;
+    fprintf( stderr, "gamma241=%f            \n", filter_state->gamma241 ) ; 
+    fprintf( stderr, "gamma231=%f            \n", filter_state->gamma231 ) ;
+#endif
+
+   /***** scaling to convert output to transversal motion of BM segment *****/ 
+    filter_state->out_scale_disp = scale_disp * Cn / ( 2. * bn * d ) ;
+    filter_state->out_scale_vel = scale_vel / ( 2. * zcn * bn * d ) ;
+   
+   /***** multiplier coefficients for OHC source *****/
+    filter_state->OHC_sat = OHC_sat * scale_disp / filter_state->out_scale_disp ;
+    filter_state->OHC_gain = - OHC_gain * Rn * filter_state->OHC_sat / ( 2. * zcn ) ;
+
+#ifdef _BMCURVES_
+   /***** initialise rms detection *****/
+    filter_state->rms = 0.0 ;
+    filter_state->sample = 0 ;
+#endif
+
+   /***** initialise filter states *****/
+    filter_state->states = ( char * ) NewZeroedArray( StateType, NUMBER_OF_STATES, 
+						      "wdf_tl.c for filter states\n" ) ;
+    
+   /***** is channel active for display ? *****/
+    filter_state->active = active ;
+
+   /***** return *****/
+    return( filter_state ) ;
+}
+
+
+/*********************************** WDF procedures ***************************************
+* name:                 function:
+*
+* DoWDFdataArray()      WDF realization of the outer ear, middle ear and cochlear networks. 
+*                       It is called by function ``tlf_bank_callback()'' in file ``bank_tl.c'' 
+*                       once for a specified number of input points. It computes the BM 
+*                       displacement or velocity for each segment and keeps track of the 
+*                       filter states. 
+*
+* CloseWDF()            Deletes all private data structures and arrays of the cochlear 
+*                       transmission line filter upon completion of filtering. It is called 
+*                       by function ``tlf_bank_callbank()'' in file ``bank_tl.c''.
+******************************************************************************************/
+
+/********************************** DoWDFdataArray() **********************************/
+
+void DoWDFdataArray( bankInfo, filter_states, input, output, points, channels,
+		     ws, eartube_states, ms, tube_segments )
+register TLF_BankInfo     *bankInfo ;
+register WDFilterState    **filter_states ;
+register DataType         *input ;
+register DataType         *output ;
+register int              points, channels ;
+register WaveWDFstate       *ws ;
+register EartubeWDFstate    **eartube_states ;
+register EarmiddleWDFstate  *ms ;
+register int              tube_segments ;
+{
+    register WDFilterState  *fs ;
+    register EartubeWDFstate *ts ;
+    register StateType   *st ;   
+    register StateType   dn, in, out ; 
+    register StateType   a0, an_1, b1, b2, b3, b63, b161, b202, b212 ;
+    static   StateType   bn = 0. ;
+    register CoeffType   *cf ;
+    register int         decimateCount = bankInfo->decimateCount ;
+    register int         decimate_factor = bankInfo->decimate_factor ;
+    register int         channelActive, pointActive, motion = bankInfo->output_var ;
+    register int         channel = -1, tube_segment = -1 ;
+#ifdef _BMCURVES_
+    static   long        sample = -1 ;
+	     int         period = 48 ;                        /* in samples */
+	     double      samplerate = 48000. ;                /* samples per sec */
+	     double      rise_time = 2.0 ;                    /* sec */
+	     double      start_time = 4.0 ;                   /* sec */
+#endif
+#ifdef _IMPULSE_
+    static   int         impulse = 10000 ;
+#endif
+
+    /***** update stapedial muscle state *****/
+
+     ( void ) ms->update_proc( ms ) ; 
+
+    /***** for all points ******/
+
+#ifdef _DEBUG_     
+     fprintf( stderr, "DoWDFdataArray() = %d points X %d channels\n", points, channels ) ;
+#endif     
+
+     while( points-- > 0 ) {
+
+	if( decimateCount == decimate_factor )
+	   decimateCount = 0 ;
+	pointActive = !decimateCount ;
+	decimateCount++ ;
+
+	output += bankInfo->output_chans * pointActive ; 
+
+       /*** for all TL channels in BACKWARD direction for current input point ***/
+
+	while( ++channel < channels ) {
+  
+	  /* get states and coefficients */
+	  fs = *filter_states++ ;   
+	  st = ( StateType * ) fs->states ;
+	  cf = ( CoeffType * ) fs->coeffs ; 
+
+	  /* Adaptor 25 */
+	  st[10] = st[1] ;                                    /* a251 */
+	  st[3] = st[2] - st[4] - st[1] ;                     /* b254 = a221 */
+
+	  /* Adaptor 24 */ 
+	  st[9] = bn ;                                        /* -a242 */
+	  st[5] = fs->gamma241 * ( st[3] + st[9] ) ;          /* b240 */
+	  st[6] = st[5] - st[9] ;                             /* b243 = a232 */
+
+	  /* Adaptor 23 */
+	  st[7] = st[8] - st[6] ;                             /* b233 */
+	  bn = st[7] ;
+	}
+
+     /*** input  point ***/
+
+	in = ( StateType ) *input++ ;  
+
+#ifdef _IMPULSE_
+	if( impulse != 0 )  {
+	   in = ( StateType ) impulse ;
+	   impulse = 0 ;
+	}
+	else 
+	   in = ( StateType ) 0 ;
+#endif
+
+#ifdef _BMCURVES_
+	if( ++sample < ( long ) ( samplerate * rise_time ) )
+	    in = 0.28284 * ( double ) sample / ( samplerate * rise_time ) * 
+		 sin( TwoPi * ( double ) ( sample % period ) / ( double ) period ) ;
+	else
+	    in = 0.28284 * sin( TwoPi * ( double ) ( sample % period ) / ( double ) period ) ;
+#endif
+
+     /*** computation of outer and middle ear in FORWARD direction for current input point ***/
+
+     /* freefield - external ear */
+
+	/* get states */
+	st = ( StateType * ) ws->states ;      
+
+	/* Adaptor 0 */
+	st[4] = ws->gamma01 * ( st[3] - in ) ;                /* b00  */
+	st[5] = st[4] + in + in ;                             /* b03 = -a11 */ 
+
+	/* Adaptor 2 */
+	st[1] = -ws->gamma21 * st[0] ;                        /* b20 */
+	st[2] = st[1] ;                                       /* b23 = a12 */
+
+	/* Adaptor 1 */
+	st[6] = st[5] - st[2] ;                               /* b13 = a32 */
+	an_1 = st[6] ;
+
+     /* concha and auditory canal */
+
+	while( ++tube_segment < tube_segments ) {
+
+	   /* get states */
+	   ts = *eartube_states++ ;  
+	   st = ( StateType * ) ts->states ;
+ 
+	   /* Adaptor 3 */
+	   st[3] = st[4] - an_1 ;                             /* b33 = a41 */
+
+	   /* Adaptor 5 */
+	   st[0] = -ts->gamma51 * st[1] ;                     /* b50 */
+	   st[2] = st[0] + st[1] ;                            /* b53 = a42 */
+ 
+	   /* Adaptor 4 */
+	   st[5] = st[3] - st[2] ;                            /* -a42+a41 */
+	   st[6] = ts->gamma41 * st[5] ;                      /* b40 */
+	   st[7] = st[6] + st[2] ;                            /* b43 = a61 */
+
+	   /* Adaptor 6 */
+	   st[8] = st[9] - st[7] ;                            /* b63 = a32 */
+	   an_1 = b63 = st[8] ;
+	}
+
+     /* middle ear */
+
+	/* get states */
+	st = ( StateType * ) ms->states ;      
+
+	/* Adaptor 9 */
+	st[31] = st[30] - st[29] ;                           /* b94 = a81 */
+
+	/* Adaptor 8 */
+	st[32] = st[35] - st[31] ;                           /* a83-a81 */
+	st[33] = -ms->gamma81 * st[32] - ms->gamma82 * st[35] ;   /* b80 */ 
+	st[34] = st[33] + st[35] ;                           /* b84 = a71 */
+
+	/* Adaptor 7 */
+	st[36] = -st[34] - an_1 ;                            /* b73 = a102 */
+
+	/* Adaptor 13 */
+	st[15] = -st[14] ;                                   /* b133 = a122 */
+
+	/* Adaptor 12 */
+	st[16] = st[15] + st[18] ;                           /* a122-a121 */
+	st[17] = -ms->gamma121 * st[16] ;                    /* b120 */
+	st[19] = st[17] + st[15] ;                           /* b123 = a112 */
+
+	/* Adaptor 14 */
+	st[21] = -ms->gamma141 * st[20] ;                    /* b140 */
+	st[22] = st[21] + st[20] ;                           /* b143 = a111 */
+
+	/* Adaptor 15 */
+	st[23] = -st[24] ;                                   /* b153 = a113 */
+
+	/* Adaptor 11 */
+	st[25] = -st[22] - st[19] - st[23] ;                 /* b114 = a101 */
+
+	/* Adaptor 10 */
+	st[26] = st[25] - st[36] ;                           /* -a102+a101 */
+	st[27] = ms->gamma101 * st[26] ;                     /* b100 */
+	st[28] = st[27] + st[36] ;                           /* b103 = a161 */
+
+	/* Adaptor 17 */
+	st[10] = st[12] - st[11] ;                           /* b174 = a162 */
+	
+	/* Adaptor 16 */
+	st[13] = -st[28] - st[10] ;                          /* b163 = a181 */
+
+	/* Adaptor 19 */
+	st[5] = -st[6] ;                                     /* b193 = a182 */
+
+	/* Adaptor 18 */
+	st[7] = st[13] - st[5] ;                             /* -a182+a181 */
+	st[8] = ms->gamma181 * st[7] ;                       /* b180 */
+	st[9] = st[8] + st[5] ;                              /* b183 = a203 */
+
+	/* Adaptor 20 */
+	st[40] =  - bn / ms->ratio ;                         /* a202 */
+	st[3] = -st[40] - st[9] ;                            /* b204 = a212 */
+
+	/* Adaptor 21 */
+	st[0] = st[2] - st[1] - st[3] ;                      /* b214 = a222 */
+
+
+     /*** computation of outer and middle ear in BACKWARD direction for current input point ***/
+
+     /* middle ear */
+
+	/* Adaptor 22 */
+	a0 = st[4] + st[0] ;                                  /* a220 */
+	st[4] = st[4] - ms->gamma221 * a0 ;                   /* b221 */
+	b2 = -st[4] - a0 ;                                    /* b222 = a214 */
+
+	/* Adaptor 21 */
+	a0 = b2 - st[0] ;                                     /* a210 */
+	st[1] = st[1] - ms->gamma211 * a0 ;                   /* b211 */
+	b212 = st[3] - ms->gamma212 * a0 ;                    /* b212 = a204 */
+	st[2] = -st[1] - b212 - b2 ;                          /* b213 */
+
+	/* Adaptor 20 */
+	a0 = b212 - st[3] ;                                   /* a200 */
+	b202 = st[40] - ms->gamma202 * a0 ;                   /* b202 */
+	b3 = ms->gamma201 * a0 - b202 - b212 ;                /* b203 = a183 */
+
+	/* Adaptor 18 */
+	b2 = st[8] + b3 ;                                     /* b182 = a193 */
+	b1 = b2 - st[7] ;                                     /* b181 = a163 */
+
+	/* Adaptor 19 */
+	st[6] = st[6] + ms->gamma191 * ( st[5] - b2 ) ;       /* b191 */
+
+	/* Adaptor 16 */
+	b161 = st[28] + ms->gamma161 * ( st[13] - b1 ) ;      /* b161 = a103 */
+	b2 = -b161 - b1 ;                                     /* b162 = a174 */
+
+	/* Adaptor 17 */
+	a0 = b2 - st[10] ;                                    /* a170 */
+	st[11] = st[11] - ms->gamma171 * a0 ;                 /* b171 */
+	st[12] = ms->gamma172 * a0 - b2 - st[11] ;            /* b173 */
+ 
+	/* Adaptor 10 */
+	st[37] = st[27] + b161 ;                              /* b102 = a73 */
+	st[38] = st[37] - st[26] ;                            /* b101 = a114 */
+
+	/* Adaptor 11 */
+	a0 = st[38] - st[25] ;                                /* a110 */
+	b1 = st[22] - ms->gamma111 * a0 ;                     /* b111 = a143 */
+	b2 = st[19] - ms->gamma112 * a0 ;                     /* b112 = a123 */
+	b3 = -b1 -b2 - st[38] ;                               /* b113 = a153 */
+
+	/* Adaptor 15 */
+	st[24] = st[24] + ms->gamma151 * ( st[23] - b3 ) ;    /* b151 */
+
+	/* Adaptor 14 */
+	st[20] = st[21] + b1 ;                                /* b142 */
+
+	/* Adaptor 12 */
+	b2 = st[17] + b2 ;                                    /* b122 = a133 */
+	st[18] = b2 + st[16] ;                                /* b121 */
+
+	/* Adaptor 13 */
+	st[14] = st[14] + ms->gamma131 * ( st[15] - b2 ) ;    /* b131 */
+
+	/* Adaptor 7 */
+	b1 = st[34] + ms->gamma71 * ( st[36] - st[37] ) ;     /* b71 = a84 */
+	st[39] = -b1 - st[37] ;                               /* b72 = a63 */
+
+	/* Adaptor 8 */
+	st[35] = st[33] + b1 ;                                /* b83 */
+	b1 = st[35] + st[32] ;                                /* b81 = a94 */
+
+	/* Adaptor 9 */
+	a0 = b1 - st[31] ;                                    /* a90 */
+	st[29] = st[29] - ms->gamma91 * a0 ;                  /* b91 */
+	st[30] = -st[29] + ms->gamma92 * a0 - b1 ;            /* b93 */
+
+     bn = st[39] ;
+
+     /* concha and auditory canal */
+
+	while( tube_segment-- > 0 ) {
+
+	   /* get states */
+	   ts = *--eartube_states ;   
+	   st = ( StateType * ) ts->states ;
+
+	   /* Adaptor 6 */
+	   b1 = st[7] - ts->gamma61 * ( bn - st[8] ) ;        /* b61 = a43 */
+	   st[9] = -b1 - bn ;                                 /* b62 */
+
+	   /* Adaptor 4 */
+	   b2 = st[6] + b1 ;                                  /* b42 = a53 */
+	   b1 = b2 - st[5] ;                                  /* b41 = a33 */
+
+	   /* Adaptor 5 */
+	   st[1] = st[0] + b2 ;                               /* b52 */
+
+	   /* Adaptor 3 */
+	   st[4] = ts->gamma31 * ( st[3] - b1 ) - st[4] ;     /* b31 */
+	   bn = -st[4] - b1 ;                                 /* b32 = a63 */
+	}
+
+     /* freefield - external ear */
+
+	/* get states */
+	st = ( StateType * ) ws->states ;      
+
+	/* Adaptor 1 */
+	b1 = ws->gamma11 * ( st[6] - bn ) - st[5] ;           /* b11 = -a03 */
+	b2 = -b1 - bn ;                                       /* b12 = a23 */
+
+	/* Adaptor 2 */
+	st[0] = st[1] + b2 + st[0] ;                          /* b61 */
+
+	/* Adaptor 0 */
+	st[3] = b1 - st[4] + st[3] ;                          /* -b01 + p */
+
+     an_1 = - b202 * ms->ratio ;    
+
+
+	/* for all channels in FORWARD direction for current input point */
+
+	 while( channel-- > 0 ) {
+
+	   /* get states and coefficients */
+	   fs = *--filter_states ;   
+	   st = ( StateType * ) fs->states ;
+	   cf = ( CoeffType * ) fs->coeffs ;
+	   channelActive = fs->active ;
+
+	   /* Adaptor 23 */
+	   st[8] = fs->gamma231 * ( st[7] - an_1 ) - st[8] ;    /* b231 */
+	   b2 = an_1 + st[8] ;                                  /* -b232 = -a243 */
+
+	   /* Adaptor 24 */
+	   an_1 = b2 - st[5] ;                                  /* -b242 */
+	   b1 = -an_1 - st[3] - st[9] ;                         /* b241 = a254 */
+	  
+	   /* Adaptor 25 */
+	   a0 = b1 - st[3] ;                                    /* a250 */
+	   st[1] = st[10] - fs->gamma251 * a0 ;                 /* b251 */
+	   st[2] = fs->gamma252 * a0 - st[4] - st[1] - b1 ;     /* b253 */
+	   dn = st[1] + st[10] ; 
+	   in = st[1] - st[10] ;
+
+	   /* output storage */
+	   if( channelActive * pointActive ) {
+
+	      if( motion == DISPLACEMENT ) 
+		 out = fs->out_scale_disp * dn ;
+	      else 
+		 out = fs->out_scale_vel * in ;
+#ifdef _OVERFLOW_
+	      if( out > _MaxOutput_ || out < _MinOutput_ )
+		 fprintf( stderr, "Overflow error in BMM output=%e\n", ( double ) out ) ;     
+#endif
+	      *(--output) = ( DataType ) ( out ) ; 
+	   }
+
+	   /* OHC nonlinear voltage source */
+	      if( dn < 0. )
+		 dn = -dn ;
+	      st[4] = fs->OHC_gain * in / ( fs->OHC_sat + dn ) ;  /* -Vn(ohc) */
+
+#ifdef _BMCURVES_
+	   if( sample > ( long ) ( start_time * samplerate ) ) { 
+	      in = fs->out_scale_vel * in ;                     
+	      fs->rms = fs->rms + in*in ; 
+	      fs->sample++ ;
+	   }
+#endif
+
+	}
+	bn = -an_1 ;                                     /* apical boundary condition */
+	output += bankInfo->output_chans * pointActive ;
+
+#ifdef _EAR_
+	st = ( StateType * ) ms->states ;
+	printf( "stapes=%e  eardrum=%e\n", 0.5 * ( st[40] - b202 ), 0.5 * ( st[39] + b63 ) ) ; 
+#endif
+
+    }
+
+    return ;
+}
+
+
+/******************************* CloseWDF() *************************************/
+
+void CloseWDF( states, channels, bank )
+  register WDFilterState      **states ;
+  register int                channels ;
+  register TLF_BankInfo       *bank ;
+{
+  int channel ;
+
+  for( channel = 0 ; channel < channels ; channel++ ) {
+#ifdef _BMCURVES_
+     printf( "%d  %e\n", channel+1, sqrt(states[channel]->rms / states[channel]->sample) ) ;
+#endif
+     Delete( states[channel]->states ) ;
+     Delete( states[channel]->coeffs ) ;
+  }
+  Delete( states ) ;
+  
+  Delete( bank ) ;
+
+  return ;
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wdf/wdf_tl.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,90 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1988, 1989
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal shipping 
+    charge). Anyone wanting to incorporate all or part of this software in a
+    commercial product must obtain a license from the Medical Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or implied 
+    warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE
+    A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY 
+    DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*  
+    Acknowledgment:
+    ==============
+
+    The source code provided in this file was originally developed by 
+    Christian Giguere as part of a Ph.D degree at the Department of
+    Engineering of the University of Cambridge from April 1990 to
+    November 1993. The code was subsequently adapted under a grant
+    from the Hearing Research Trust for full compatibility with 
+    AIM Release 6.15.
+
+    Christian Giguere 25/03/94
+
+*/
+
+/*
+    =============================================================
+    wdf_tl.h 
+    =============================================================
+
+    Wave digital filter (WDF) implementation of the cochlear 
+    transmission line (TL) network.
+    
+    Author        : Christian Giguere
+    First written : 19th March, 1991
+    Last edited   : 18th February, 1994
+    =============================================================
+*/
+
+#ifndef _WDF_TL_H_
+
+
+/***** defines *****/
+
+#define _WDF_TL_H_
+
+#define  DISPLACEMENT       (         0 )
+#define  VELOCITY           (         1 ) 
+
+
+/***** private data structure for WDF-TL module *****/
+
+typedef struct _wdf_filter_state WDFilterState ;
+
+struct _wdf_filter_state {
+    double gamma231 ;                     /* WDF multiplier coefficients (Adaptors 23-25) */
+    double gamma241 ;
+    double gamma251, gamma252 ;
+    char   *states;                       /* WDF state vector */
+    char   *coeffs ;                      /* WDF coefficient vector (not used) */
+    double out_scale_disp ;               /* scaling to convert output to BM displacement */
+    double out_scale_vel ;                /* scaling to convert output to BM velocity */
+    double OHC_gain ;                     /* normalized OHC feedback gain */
+    double OHC_sat ;                      /* normalized OHC half-saturation displacement */
+    int    active ;                       /* is channel active for display ? (0=no, 1=yes) */
+    double rms ;                          /* BM rms vibration amplitude */
+    long   sample ;                       /* sample size in rms computation */
+    } ;
+
+
+/***** externals *****/
+
+extern WDFilterState *WDFilter() ;
+extern void           DoWDFdataArray(), CloseWDF() ;
+
+#endif 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xaim/buttons.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,322 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+/* 
+*   buttons.c
+*   ---------
+*  Defines the size, position, and input-option-possibilites of the buttons
+*  that appear on the Controls Window.
+*
+*  M. Akeroyd.  July 1993. version 1.10
+*  Revisions: MAA: Christmas 1993. 
+*
+*/
+
+
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+#include <stdio.h>
+
+#include "xreview.h"
+
+
+
+
+/* X .......................*/
+
+extern Display *display;
+extern int screen_num;
+extern Screen *screen_ptr;
+
+extern toplevelWindow control;
+extern Pixmap stipple_pixmap;
+
+extern buttonWindow button_quit, button_close;
+extern buttonWindow button_animate;
+extern buttonWindow button_startf, button_startb, button_stopf, button_stopb;
+extern buttonWindow button_skipf, button_skipb, button_faster, button_slower;
+extern buttonWindow button_firstframe, button_lastframe, button_middle;
+extern buttonWindow button_stepf, button_stepff, button_stepb, button_stepbb;
+
+extern buttonWindow info_speed, info_start, info_stop, info_skip;
+extern buttonWindow info_title, info_frame;
+extern buttonWindow info_time, info_freq, info_frstep;
+
+extern GC button_gc;
+extern XFontStruct *font_info;
+
+extern int button_borderwidth ;
+
+
+/* Command line .............*/
+
+extern double scale;                /* scale factor of Controls Window size */
+
+
+
+
+
+
+/*-------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
+
+
+
+
+
+Window create_button(int x, int y, int width, int height)
+{
+  return (Window) XCreateSimpleWindow(display, control.win, \
+				      x, y, width, height, \
+				      button_borderwidth, \
+				      BlackPixel(display, screen_num),\
+				      WhitePixel(display, screen_num));
+}
+
+
+
+
+
+
+/*-------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
+
+
+
+
+
+void initialise_buttons()
+{
+  button_gc = XCreateGC(display, RootWindow(display, screen_num),\
+			control.valuemask, &control.values);
+  XSetForeground(display, button_gc, BlackPixel(display, screen_num));
+  XSetFillStyle(display, button_gc, FillSolid);
+  XSetFont(display, button_gc, font_info->fid);
+
+/*------------------------------*/
+/* Button Positions: all relative to top-left Controls corner. 
+*  All in pixels */
+
+  button_quit.x       =  20 * scale; button_quit.y       = 10 * scale; 
+  button_close.x      =  20 * scale; button_close.y      = 44 * scale;
+
+  button_animate.x    = 500 * scale; button_animate.y    = 90 * scale; 
+  button_startf.x     =  64 * scale; button_startf.y     = 124 * scale;  
+  button_startb.x     =  14 * scale; button_startb.y     = 124 * scale;  
+  button_stopf.x      = 184 * scale; button_stopf.y      = 124 * scale;  
+  button_stopb.x      = 134 * scale; button_stopb.y      = 124 * scale;  
+  button_skipf.x      = 304 * scale; button_skipf.y      = 124 * scale;  
+  button_skipb.x      = 254 * scale; button_skipb.y      = 124 * scale;  
+  button_faster.x     = 372 * scale; button_faster.y     = 124 * scale; 
+  button_slower.x     = 422 * scale; button_slower.y     = 124 * scale; 
+
+  button_firstframe.x =  10 * scale; button_firstframe.y = 174 * scale; 
+  button_stepbb.x     =  80 * scale; button_stepbb.y     = 174 * scale; 
+  button_stepb.x      = 150 * scale; button_stepb.y      = 174 * scale; 
+  button_middle.x     = 220 * scale; button_middle.y     = 174 * scale; 
+  button_stepf.x      = 290 * scale; button_stepf.y      = 174 * scale; 
+  button_stepff.x     = 360 * scale; button_stepff.y     = 174 * scale; 
+  button_lastframe.x  = 430 * scale; button_lastframe.y  = 174 * scale; 
+
+/* Button sizes: also in pixels */
+
+  button_quit.width       =  60 * scale; button_quit.height      = 25 * scale; 
+  button_close.width      =  60 * scale; button_close.height     = 25 * scale;
+  button_animate.width    = 100 * scale; button_animate.height   = 60 * scale; 
+  button_startf.width     =  40 * scale; button_startf.height    = 25 * scale; 
+  button_startb.width     =  40 * scale; button_startb.height    = 25 * scale; 
+  button_stopf.width      =  40 * scale; button_stopf.height     = 25 * scale; 
+  button_stopb.width      =  40 * scale; button_stopb.height     = 25 * scale; 
+  button_skipf.width      =  40 * scale; button_skipf.height     = 25 * scale; 
+  button_skipb.width      =  40 * scale; button_skipb.height     = 25 * scale;
+  button_faster.width     = 45 * scale; button_faster.height     = 25 * scale;
+  button_slower.width     = 45 * scale; button_slower.height     = 25 * scale; 
+  button_lastframe.width  = 60 * scale; button_lastframe.height  = 25 *scale; 
+  button_firstframe.width = 60 * scale; button_firstframe.height = 25 *scale; 
+  button_middle.width     = 60 * scale; button_middle.height     = 25 * scale; 
+  button_stepf.width      = 60 * scale; button_stepf.height      = 25 * scale; 
+  button_stepff.width     = 60 * scale; button_stepff.height     = 25 * scale; 
+  button_stepb.width      = 60 * scale; button_stepb.height      = 25 * scale; 
+  button_stepbb.width     = 60 * scale; button_stepbb.height     = 25 * scale; 
+
+/*------------------------------*/
+/* make the things */
+
+  button_quit.win = create_button(button_quit.x, button_quit.y, \
+				  button_quit.width, button_quit.height);
+  button_close.win = create_button(button_close.x, button_close.y, \
+				   button_close.width, button_close.height);
+  button_animate.win = create_button(button_animate.x, button_animate.y, \
+			         button_animate.width, button_animate.height);
+  button_startf.win = create_button(button_startf.x, button_startf.y, \
+             		         button_startf.width, button_startf.height);
+  button_startb.win = create_button(button_startb.x, button_startb.y, \
+				 button_startb.width, button_startb.height);
+  button_stopf.win = create_button(button_stopf.x, button_stopf.y, \
+				   button_stopf.width, button_stopf.height);
+  button_stopb.win = create_button(button_stopb.x, button_stopb.y, \
+				   button_stopb.width, button_stopb.height);
+  button_skipf.win = create_button(button_skipf.x, button_skipf.y, \
+				   button_skipf.width, button_skipf.height);
+  button_skipb.win = create_button(button_skipb.x, button_skipb.y, \
+				   button_skipb.width, button_skipb.height);
+  button_faster.win = create_button(button_faster.x, button_faster.y, \
+				  button_faster.width, button_faster.height);
+  button_slower.win = create_button(button_slower.x, button_slower.y, \
+				  button_slower.width, button_slower.height);
+  button_lastframe.win =create_button(button_lastframe.x, button_lastframe.y,\
+		             button_lastframe.width, button_lastframe.height);
+  button_firstframe.win=create_button(button_firstframe.x,button_firstframe.y,\
+			   button_firstframe.width, button_firstframe.height);
+  button_middle.win =create_button(button_middle.x, button_middle.y, \
+		             button_middle.width, button_middle.height);
+  button_stepf.win = create_button(button_stepf.x, button_stepf.y, \
+				   button_stepf.width, button_stepf.height);
+  button_stepff.win = create_button(button_stepff.x, button_stepff.y, \
+				   button_stepff.width, button_stepff.height);
+  button_stepb.win = create_button(button_stepb.x, button_stepb.y, \
+				   button_stepb.width, button_stepb.height);
+  button_stepbb.win = create_button(button_stepbb.x, button_stepbb.y, \
+				   button_stepbb.width, button_stepbb.height);
+
+/*---------------------------*/
+/* Info positions and sizes. */
+
+  info_speed.x  = 370 * scale; info_speed.y  = 94 * scale;
+  info_start.x  =  10 * scale; info_start.y  = 94 * scale;
+  info_stop.x   = 130 * scale; info_stop.y   = 94 * scale;
+  info_skip.x   = 250 * scale; info_skip.y   = 94 * scale;
+  info_frame.x  = 500 * scale; info_frame.y  = 174 * scale;
+  info_title.x  = 100 * scale; info_title.y  = 10 * scale;
+  info_freq.x   = 100 * scale; info_freq.y   = 44 * scale;
+  info_time.x   = 275 * scale; info_time.y   = 44 * scale;
+  info_frstep.x = 475 * scale; info_frstep.y = 44 * scale;
+
+  info_speed.width  = 100 * scale; info_speed.height  = 25 * scale;
+  info_start.width  = 100 * scale; info_start.height  = 25 * scale;
+  info_stop.width   = 100 * scale; info_stop.height   = 25 * scale;
+  info_skip.width   = 100 * scale; info_skip.height   = 25 * scale;
+  info_frame.width  = 100 * scale; info_frame.height  = 25 * scale;
+  info_title.width  = 500 * scale; info_title.height  = 25 * scale;
+  info_freq.width   = 175 * scale; info_freq.height   = 25 * scale;
+  info_time.width   = 175 * scale; info_time.height   = 25 * scale;
+  info_frstep.width = 115 * scale; info_frstep.height = 25 * scale;
+
+  info_speed.win = create_button(info_speed.x, info_speed.y, \
+				 info_speed.width, info_speed.height);
+  info_start.win = create_button(info_start.x, info_start.y, \
+				 info_start.width, info_start.height);
+  info_stop.win = create_button(info_stop.x, info_stop.y, \
+				info_stop.width, info_stop.height);
+  info_skip.win = create_button(info_skip.x, info_skip.y, \
+				info_skip.width, info_skip.height);
+  info_frame.win = create_button(info_frame.x, info_frame.y, \
+				 info_frame.width, info_frame.height);
+  info_title.win = create_button(info_title.x, info_title.y, \
+				 info_title.width, info_title.height);
+  info_freq.win = create_button(info_freq.x, info_freq.y, \
+				info_freq.width, info_freq.height);
+  info_time.win = create_button(info_time.x, info_time.y, \
+				info_time.width, info_time.height);
+  info_frstep.win = create_button(info_frstep.x, info_frstep.y, \
+				  info_frstep.width, info_frstep.height);
+  
+  
+/*------------------------------*/
+/* Define the allowed inputs to the buttons.
+*/
+  XSelectInput(display, button_quit.win, ButtonPressMask );
+  XSelectInput(display, button_close.win, ButtonPressMask );
+  XSelectInput(display, button_animate.win, ButtonPressMask );
+  XSelectInput(display, button_startf.win, ButtonPressMask );
+  XSelectInput(display, button_startb.win, ButtonPressMask );
+  XSelectInput(display, button_stopf.win, ButtonPressMask );
+  XSelectInput(display, button_stopb.win, ButtonPressMask );
+  XSelectInput(display, button_skipf.win, ButtonPressMask );
+  XSelectInput(display, button_skipb.win, ButtonPressMask );
+  XSelectInput(display, button_faster.win, ButtonPressMask );
+  XSelectInput(display, button_slower.win, ButtonPressMask );
+  XSelectInput(display, button_lastframe.win, ButtonPressMask );
+  XSelectInput(display, button_firstframe.win, ButtonPressMask );
+  XSelectInput(display, button_middle.win, ButtonPressMask );
+  XSelectInput(display, button_stepf.win, ButtonPressMask );
+  XSelectInput(display, button_stepff.win, ButtonPressMask );
+  XSelectInput(display, button_stepb.win, ButtonPressMask );
+  XSelectInput(display, button_stepbb.win, ButtonPressMask );
+
+  XSelectInput(display, info_speed.win, ButtonPressMask);
+  XSelectInput(display, info_start.win, ButtonPressMask);
+  XSelectInput(display, info_stop.win, ButtonPressMask);
+  XSelectInput(display, info_skip.win, ButtonPressMask);
+  XSelectInput(display, info_frame.win, ButtonPressMask);
+  XSelectInput(display, info_title.win, ButtonPressMask);
+  XSelectInput(display, info_freq.win, ButtonPressMask);
+  XSelectInput(display, info_time.win, ButtonPressMask);
+  XSelectInput(display, info_frstep.win, ButtonPressMask);
+
+/* Define the backgrounds. */
+
+  XSetWindowBackgroundPixmap(display, button_quit.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_close.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_animate.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_startf.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_startb.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_stopf.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_stopb.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_skipf.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_skipb.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_faster.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_slower.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_lastframe.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_firstframe.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_middle.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_stepf.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_stepff.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_stepb.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, button_stepbb.win, stipple_pixmap);
+
+  XSetWindowBackgroundPixmap(display, info_speed.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, info_start.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, info_stop.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, info_skip.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, info_frame.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, info_title.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, info_freq.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, info_time.win, stipple_pixmap);
+  XSetWindowBackgroundPixmap(display, info_frstep.win, stipple_pixmap);
+}
+
+
+
+
+/* The End */
+/*------------------------------------------------------------------------*/
+/*------------------------------------------------------------------------*/
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xaim/cartoon.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,406 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/*
+* cartoon.c 
+* ----------
+*
+*
+* M. Akeroyd. July 1993. version 1.10
+* (ReadHeader is August 30, 1993)
+*
+* Revisions: MAA: Christmas 1993. 
+*/
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "xreview.h"
+
+
+
+/* General Parameters */
+
+extern char progname[MAX_STRING_LENGTH];
+extern int verboseflag;
+
+extern char *data_pointer;
+extern long location[MAX_FRAMES];
+extern int reviewimage_bitmap_pad;
+extern int reviewimage_bytesperline;
+
+
+/* .ctn parameters */
+
+extern char header[MAX_LINES_HEADER][MAX_LINE_LENGTH];
+extern int header_lines;        
+extern int no_frames;
+extern int depth;
+extern long samplerate;
+extern int frameheight;         
+extern int framewidth_samples;  
+extern int frameshift_samples;  
+extern double frstep_aid;
+extern double pwidth;
+extern double nwidth;
+extern int mincf;
+extern int maxcf;       
+
+/* X .... */
+
+extern int width_ctn; 
+extern int height_ctn;
+extern int x_ctn;
+extern int y_ctn;
+
+
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+
+
+int readheader(FILE *inputfp, char inputfn[]) 
+{ 
+  /* August 30, 1993 
+   * Most of the effort went into getting it to load the exact number of
+   * bytes, because the bitmap info follows on continously from the header.
+   * This version adds-up the number of bytes it actually has loaded, and if
+   * it needs anymore, gratutiously loads them.
+   * It seems to work with:
+   *  DECstation cartoon displayed on DECstation server
+   *  DECstation     ...      ...     Sun         ...
+   *  Sun   ...      ...      ...     DECstation  ...
+   *  Sun   ...      ...      ...     Sun         ...		
+   *  DECstation     ...      ...     Linux 386 PC server.
+   */
+
+  /* Assumed necessary conditions of a .ctn file:
+   * first line says "header_bytes= ... "
+   * last line says "Version= ..."
+   */
+
+  char tempstring[MAX_STRING_LENGTH];         
+  char *p_equal=" ";       /* pointer to where the '=' is in the headerline */
+  int bytes_required = 0;  /* num of bytes in header, as in "header_bytes=...
+			    * This is RETURNed */
+  int bytes_loaded = 0;    /* number actually loaded */
+  int counter;
+  int status;
+
+
+  /* Get first line */
+  header_lines = 0;
+  fgets(header[0], MAX_LINE_LENGTH, inputfp);
+
+  /* If the First Line ISN'T "header_bytes ...", add another ".ctn" to the end 
+   * and try again. tempstring holds the original name, before ".ctn" got
+   * added. 
+   */
+
+  strcpy(tempstring, inputfn);
+
+  if(strspn(header[0], "header_bytes") == 0) {
+    fclose(inputfp);
+    strcat(inputfn, INPUT_EXT);
+    inputfp = fopen(inputfn, "rb");
+    if (inputfp == NULL) {  
+      fprintf(stderr, "xreview : unable to open file %s\n", tempstring);
+      exit(-1);}
+    fgets(header[0], MAX_LINE_LENGTH, inputfp);
+    if(strspn(header[0], "header_bytes") == 0) {
+      fprintf(stderr, "xreview: is %s a .ctn file? \n", inputfn);
+      exit(-1);}}
+
+  /* Find out how many bytes there SHOULD be */
+  p_equal = strchr(header[0], '=');
+  bytes_required = atoi(++p_equal); 
+
+
+/*----------------------------------------*/
+
+
+  /* Loop on remaining lines, saving important information as required 
+   * Last line has "Version" in it.
+   */
+
+  while (strncmp(fgets(header[++header_lines], MAX_LINE_LENGTH, inputfp),
+		 "Version=", 8)  != 0) {
+
+    if (strncmp(header[header_lines], "frames=", 7) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      no_frames = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "samplerate", 11) == 0 ) {
+      /* For some unknown reason, the samplerate has a "." at the
+       * end of it. Well, sometimes it does.
+       */
+      strncpy(tempstring, header[header_lines], 
+	      (strlen(header[header_lines])-0));
+      p_equal = strchr(tempstring, '=');
+      samplerate = atol(++p_equal); } 
+
+    if (strncmp(header[header_lines], "frameheight=", 12) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      frameheight = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "framewidth=", 11) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      framewidth_samples = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "frameshift=", 11) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      frameshift_samples = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "frstep_aid=", 11) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      frstep_aid = atof(++p_equal);}
+
+    if (strncmp(header[header_lines], "pwidth_aid=", 11) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      pwidth = atof(++p_equal); }
+
+    if (strncmp(header[header_lines], "nwidth_aid=", 11) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      nwidth = atof(++p_equal); }
+
+    if (strncmp(header[header_lines], "mincf_afb=", 10) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      mincf = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "maxcf_afb=", 10) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      maxcf = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "width_win=", 10) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      width_ctn = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "height_win=", 11) == 0 ) {
+      p_equal = strchr(header[header_lines], '=');
+      height_ctn = atoi(++p_equal); }
+
+    if (strncmp(header[header_lines], "x0_win=", 7) == 0 ) {
+      if (strncmp(header[header_lines], "x0_win=center", 13) == 0 ) {
+	/* -1 is used to mean 'center' */
+	x_ctn = -1;}
+      else {
+	p_equal = strchr(header[header_lines], '=');
+	x_ctn = atoi(++p_equal); } }
+
+    if (strncmp(header[header_lines], "y0_win=", 7) == 0 ) {
+      if (strncmp(header[header_lines], "y0_win=center", 13) == 0 ) {
+	/* -1 is used to mean 'center' */
+	y_ctn = -1;}
+      else {
+	p_equal = strchr(header[header_lines], '=');
+	y_ctn = atoi(++p_equal); } }
+
+  }
+
+/*---------------------------------*/
+
+  /* Some checks */
+
+  if (width_ctn == 0) {
+    if (verboseflag == ON)  fprintf(stderr, "\n");
+    fprintf(stderr, "xreview : width of cartoon window = 0. Stopping. \n");
+    exit(-1);}
+
+  if (height_ctn == 0) {
+    if (verboseflag == ON)  fprintf(stderr, "\n");
+    fprintf(stderr, "xreview : height of cartoon window = 0. Stopping. \n");
+    exit(-1);}
+
+  if (no_frames == 0) {
+    if (verboseflag == ON)  fprintf(stderr, "\n");
+    fprintf(stderr, "xreview : total frames = 0. Stopping. \n");
+    exit(-1);}
+
+  if (frameheight == 0) {
+    if (verboseflag == ON)  fprintf(stderr, "\n");
+    fprintf(stderr, "xreview : frameheight of cartoon = 0. Stopping. \n");
+    exit(-1);}
+
+/*-----------------------------------------------*/
+
+  /* how many bytes have we loaded ? */
+  for (counter=0; counter<=header_lines; counter++) 
+    bytes_loaded += strlen(header[counter]);
+  
+  /* read some more bytes, till we are at the end of the header */
+  for (counter = 1; counter <= (bytes_required - bytes_loaded); counter++) {
+    status = fgetc(inputfp);
+    if (status == EOF) {
+      if (verboseflag == ON)  fprintf(stderr, "\n");
+      fprintf(stderr, "xreview : unable to finish loading of header. \n");
+      exit(-1);}}
+
+  return bytes_required; 
+  }
+
+
+
+
+
+/*------------------------------------------------------------------------*/
+/*------------------------------------------------------------------------*/
+
+
+
+
+FILE *open_file(char filefn[],  FILE *dir_default, int streamtype)
+{
+  /* Opens a file stream associated with filefn[].
+   * If that's null, then the stream is a copy of the dir_default:
+   *    stdin / stdout / stderr.
+   * 'streamtype' is either READ (for "rb") or WRITE ("wb")
+   * 
+   * If it doesn't work, put ".ctn" on the end and try again.
+   */
+
+  FILE *filefp = NULL;
+
+  if (strcmp(filefn, "") == 0) 
+    filefp = dir_default;
+  else {
+    if (streamtype == READ) 
+      filefp = fopen(filefn, "rb");
+    else 
+      filefp = fopen(filefn, "wb");}
+
+  if (filefp == NULL) {  
+    strcat(filefn, INPUT_EXT);
+    if (streamtype == READ) 
+      filefp = fopen(filefn, "rb");
+    else 
+      filefp = fopen(filefn, "wb");
+    if (filefp == NULL) {  
+      fprintf(stderr, "xreview : unable to open file %s\n", filefn);
+      exit(-1);}
+  }
+  return filefp;
+	
+}
+
+
+
+
+/*---------------------------------------------------------------------*/
+/*---------------------------------------------------------------------*/
+
+
+
+
+
+void close_files(FILE *fp)
+{
+
+  fclose(fp);
+ 
+  if ( ferror(fp) != 0) {
+    if (verboseflag == ON)  fprintf(stderr, "\n");
+    fprintf(stderr, "xreview : error closing file.\n");
+    exit(-1);}
+}
+
+
+
+
+
+/*---------------------------------------------------------------------*/
+/*---------------------------------------------------------------------*/
+
+
+
+
+
+void loaddata(FILE *inputfp)
+{
+  int required_bytes;
+  int frame;
+  long status;
+
+/*-----------------------------*/  
+
+  if  (verboseflag==ON) { 
+    fprintf(stderr, " loading frame ");
+    fflush(stderr);}
+  
+  required_bytes = (long) height_ctn*reviewimage_bytesperline*depth; 
+
+  if (no_frames >= MAX_FRAMES) {
+    if (verboseflag == ON)  fprintf(stderr, "\n");
+    fprintf(stderr, "xreview : too many frames (%i) \n", no_frames);
+    exit(-1);}
+
+/*-----------------------------*/
+
+  for (frame=1; frame <= no_frames; frame++) {
+
+    if  (verboseflag==ON) { 
+      fprintf(stderr, "%i ", frame);
+      fflush(stderr);}
+
+    location[frame] = (long) data_pointer;
+
+    clearerr(inputfp);
+    status = (long) fread (data_pointer, (size_t) 1, (size_t) required_bytes, inputfp);
+
+    if ((status != required_bytes) && frame == 1){
+      if (verboseflag == ON)  fprintf(stderr, "\n");
+      fprintf(stderr, "xreview : error reading first frame: wanted %li bytes, got %li\n", required_bytes, status);
+      exit(-1);}
+
+    if ((status != required_bytes) && frame != 1){
+      if (verboseflag == ON)  fprintf(stderr, "\n");
+      fprintf(stderr, "xreview : frame %i: wanted %li bytes, got %li. Continuing with %i frames.\n", frame, required_bytes, status, frame-1);
+      frame--;
+      no_frames=frame;}
+
+    if ((int) ferror(inputfp) != 0) {
+      if (verboseflag == ON)  fprintf(stderr, "\n");
+      fprintf(stderr, "xreview :  error reading frame %i\n", frame);
+      exit(-1);}
+
+    data_pointer = data_pointer + required_bytes;
+
+  } /* frame */
+
+/*-----------------------------*/  
+
+  data_pointer = (char *) location[1];
+
+}
+
+
+
+
+
+
+/* The End */
+/*---------------------------------------------------------------------*/
+/*---------------------------------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xaim/disclaimer.text	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,24 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xaim/graphics.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,373 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/* 
+*   graphics.c
+*   ----------
+*  Draws things ...
+*
+*  NB: The method used for timing the animations (display a frame, wait until
+*      the clock has got above some threshold, display the next frame) doesn't
+*      seem to work on the linux 396 pc. Thus, it is ALL removed. This means
+*      you can't change the speed of that's animations. 
+*      The 'flashtime' of the Control Buttons is also removed.
+*      For speed reasons, the bit that keeps the frame-nbumber in sync with
+*      the animations is also removed from the linux version (in animate_image)
+*
+*  M. Akeroyd.  July 1993. version 1.10
+*  Revisions: MAA Christmas 1993.
+*
+*/
+
+
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+#include <stdio.h>
+
+#include "xreview.h"
+
+#define FLASHTIME 200         /* how long to flash a button for, in msecs.
+                              * 200 works very well on a Sparc or DECStation.
+                              * The linux 386 pc  doesn't like counting times,
+                              * so is therefore 0. */
+#ifdef HOST_SPARC
+  #define FLASHTIME 200
+#endif
+#ifdef HOST_DECSTATION
+  #define FLASHTIME 200
+#endif
+#ifdef HOST_LINUXPC
+  #define FLASHTIME 0
+#endif
+
+
+
+void drawtext(buttonWindow win, GC gc, XFontStruct *font_info_local, char *text);
+
+
+
+/* General variables ....*/
+
+extern char progname[MAX_STRING_LENGTH];
+
+extern char *data_pointer;
+extern char *data_pointer_sideways;
+extern long location[MAX_FRAMES];
+extern FILE *inputfp;
+extern char inputfn[MAX_STRING_LENGTH];
+
+extern int sidewaysflag;
+
+
+/* X ....................*/
+
+extern char display_name[MAX_STRING_LENGTH];
+extern char fontname[MAX_STRING_LENGTH];
+
+extern Display *display;
+extern int screen_num;
+extern Screen *screen_ptr;
+extern int depth;
+extern unsigned int display_width, display_height;
+
+extern toplevelWindow control;
+extern toplevelWindow axes;
+extern buttonWindow info_frame;
+extern XImage *reviewimage;
+
+extern XFontStruct *font_info;
+extern GC button_gc;
+
+
+/* .ctn ..................*/
+
+extern int no_frames;
+extern int frame;
+extern long waittime_millisecs;
+extern long waittime_microsecs;
+
+
+/* Command line ..........*/
+
+extern int verboseflag;
+
+
+
+
+
+/*--------------------------------------------------------------------*/
+/*--------------------------------------------------------------------*/
+
+
+
+
+void animate_image(int start, int stop, int skip)
+{
+  long localtime;
+  char tempstring[100];
+  long address;
+  int reviewimage_bytesperline;
+  int x, y;
+  int tempy, tempx;
+  long frameconst, framesize;
+  int counter, counter2, counter3;
+  long framestop= 100000;
+  long limit;
+  long ylimit;
+  long newaddress;
+  long delta;
+  long required_bytes;
+  long lframe;
+  int framenth=1;
+
+  waittime_microsecs = (long) waittime_millisecs * 1000;
+  
+  reviewimage_bytesperline = (int) ((int) ((axes.width -1) / 32) +1) *4;
+
+  if (sidewaysflag == ON) {
+    framesize = reviewimage_bytesperline * axes.height *depth;
+    frameconst = framesize;
+    counter =-1;
+    counter2 = 0;
+    ylimit = axes.height*reviewimage_bytesperline*depth;
+    limit= (long) ylimit + no_frames*(frameconst);
+    
+    address=(long) location[start];
+    delta = axes.height*0;
+    
+    for (lframe=1; lframe <=framestop; lframe++) {
+      if ((ylimit+(framenth*framesize)) >= limit){
+	lframe=framestop+10;
+	continue;}
+      counter+=1;
+      for (y=0; y<axes.height; y++){
+	tempy = y * reviewimage_bytesperline;
+	for (x=0; x<=(reviewimage_bytesperline-2); x+=1)
+	  data_pointer[tempy+x] = data_pointer[tempy+x+1];
+	x=reviewimage_bytesperline-1;
+	data_pointer[tempy+x] = data_pointer[tempy+frameconst+counter];}
+      if (counter == reviewimage_bytesperline-1){
+	counter = -1;
+	frameconst += framesize;
+	framenth++;}
+      reviewimage->data = (char *) address;
+      counter2++;
+      if (counter2 == skip) {
+	counter2=0;
+	XPutImage(display, axes.win, axes.gc, reviewimage, \
+		  0, 0, 0, 0, axes.width, axes.height);}
+      if ((lframe % 100) == 0) {
+	XClearWindow(display, info_frame.win);
+	sprintf(tempstring, "%i (%i)", framenth, no_frames);
+	drawtext(info_frame, button_gc, font_info, tempstring);}}
+    
+    required_bytes = no_frames*axes.height*reviewimage_bytesperline*depth;
+    for (x=location[0]; x<=location[0]+required_bytes-1; x++)
+      data_pointer[x] = data_pointer_sideways[x];
+    XClearWindow(display, info_frame.win);
+    sprintf(tempstring, "%i (%i)", no_frames, no_frames);
+    drawtext(info_frame, button_gc, font_info, tempstring);}
+    
+  else {
+    for (frame=start; frame<=stop; frame += skip){
+      reviewimage->data = (char *) location[frame];
+      XPutImage(display, axes.win, axes.gc, reviewimage, \
+		0, 0, 0, 0, axes.width, axes.height); 
+      /* Since this next bit only seems to work on a Sparc or DECstation, leave
+       * it out if we're on a 386 pc
+       */
+#ifndef HOST_LINUXPC
+      if (waittime_millisecs > 0) {
+	XClearWindow(display, info_frame.win);
+	sprintf(tempstring, "%i of %i", frame, no_frames);
+	drawtext(info_frame, button_gc, font_info, tempstring);}
+      localtime = (long) clock();
+      while (clock() - localtime <= waittime_microsecs) 
+	;
+#endif 
+    } 
+    frame=stop;
+    XClearWindow(display, info_frame.win);
+    sprintf(tempstring, "%i of %i", frame, no_frames);
+    drawtext(info_frame, button_gc, font_info, tempstring);
+  }
+}
+
+
+
+
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+
+
+
+void drawimage(int frame)
+{
+  reviewimage->data = (char *) location[frame];
+
+  XPutImage(display, axes.win, axes.gc, reviewimage, 0, 0, 0, 0, axes.width, axes.height);  
+} 
+
+
+
+/*-------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
+
+
+
+
+void drawtext(buttonWindow win, GC gc, XFontStruct *font_info_local, char *text)
+{
+  /*
+   * Copied off basicwindow.c: place_text ()
+   * Draws 'text' centered horizontally and vertically in the Window.
+   * Well, vertically ish. It looks reasonably centered.
+   *
+   */
+
+  int len_text, width_text;
+  int width = win.width;
+  int height = win.height;
+			
+  len_text = strlen(text);
+  width_text = XTextWidth(font_info_local, text, len_text);
+
+  XDrawString(display, win.win, gc, (width  - width_text)/2, \
+	      (height + font_info_local->ascent -1)/2, text, len_text);
+
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------*/
+
+
+
+
+void drawtext_xy(buttonWindow win, GC gc, XFontStruct *font_info_local, char text[], int width, int height)
+{
+  /* x, y specified version of drawtext()
+   *
+   */
+
+  int len_text, width_text;
+
+  len_text = strlen(text);
+  width_text = XTextWidth(font_info_local, text, len_text);
+
+  XDrawString(display, win.win, gc, (width  - width_text)/2, \
+	      (height + font_info_local->ascent-1)/2, text, len_text);
+
+}
+
+
+
+
+/*-------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
+
+
+
+
+void drawbutton(toplevelWindow top_win, buttonWindow button_local, GC *button_local_gc, char *text, int fill_colour, int border_colour)
+{
+  int width = button_local.width;
+  int height = button_local.height;
+
+  /* Draw shadow */
+  XSetForeground(display, *button_local_gc, border_colour);  
+  XmuDrawRoundedRectangle(display, button_local.win, *button_local_gc, 1, 1, 
+			  width-2, height-2, 5, 5); 
+  XmuFillRoundedRectangle(display, button_local.win, *button_local_gc, 1, 1,
+			  width-2, height-2, 5, 5); 
+
+  /* Draw button */
+  XSetForeground(display, *button_local_gc, fill_colour);  
+  XmuFillRoundedRectangle(display, button_local.win, *button_local_gc, 0, 0, 
+			  width-2, height-2, 5, 5); 
+  XSetForeground(display, *button_local_gc, border_colour);  
+  XmuDrawRoundedRectangle(display, button_local.win, *button_local_gc, 0, 0, 
+			  width-2, height-2, 5, 5); 
+  
+  /* Draw text: border_colour */
+  drawtext(button_local, *button_local_gc, font_info, text);
+
+  XFlush(display);
+}
+
+
+
+
+/*-------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
+
+
+
+
+void flashbutton(toplevelWindow top_win, buttonWindow button_local, GC *button_local_gc, char *text)
+{
+  int width = button_local.width;
+  int height = button_local.height;
+  long starttime;
+  int flashtime = FLASHTIME;          /* msecs */
+
+  /* Redraw button where the shadow used to be */
+  XClearWindow(display, button_local.win);
+  XSetForeground(display, *button_local_gc, WhitePixel(display, screen_num));  
+  XmuFillRoundedRectangle(display, button_local.win, *button_local_gc, 1, 1, 
+			  width-2, height-2, 5, 5); 
+  XSetForeground(display, *button_local_gc, BlackPixel(display, screen_num));  
+  XmuDrawRoundedRectangle(display, button_local.win, *button_local_gc, 1, 1, 
+			  width-2, height-2, 5, 5); 
+
+  /* Redraw the text */
+  drawtext_xy(button_local, *button_local_gc, font_info, \
+	      text, width+2, height+2);
+  XFlush(display);
+
+  /* Wait ... */
+  starttime = (long) clock();
+  while ((clock() - starttime) <= (flashtime * 1000)) 
+    ;
+
+  /* Draw the old button */
+  drawbutton(top_win, button_local, button_local_gc, text,\
+	     WhitePixel(display, screen_num), BlackPixel(display, screen_num));
+
+}
+
+
+
+/* The end.*/
+/*-------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xaim/initialise.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,400 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+/* 
+*   initailise.c
+*   ---------
+*  Initialises lots of X things.
+*
+*  M. Akeroyd.  July 1993. version 1.10
+*  Revisions: MAA: Christmas 1993.
+*
+*/
+
+
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+#include <stdio.h>
+
+#include "xreview.h"
+#include "./xreview.bitmap"
+#include <X11/cursorfont.h>
+
+
+
+/* General variables ....*/
+
+extern char progname[MAX_STRING_LENGTH];
+
+extern char *data_pointer;
+extern long location[MAX_FRAMES];
+
+
+
+/* X ....................*/
+
+extern char display_name[MAX_STRING_LENGTH];
+extern char fontname[MAX_STRING_LENGTH];
+
+extern Display *display;
+extern int screen_num;
+extern Screen *screen_ptr;
+extern int depth;
+extern unsigned int display_width, display_height;
+
+extern toplevelWindow control;
+extern toplevelWindow axes;
+extern Pixmap stipple_pixmap;
+extern XImage *reviewimage;
+extern Cursor cursor;
+
+extern GC button_gc;
+extern XFontStruct *font_info;
+extern int planemask;
+
+
+/* .ctn ..................*/
+
+extern int no_frames;
+extern int width_ctn, height_ctn;
+extern int x_ctn, y_ctn;
+extern int reviewimage_bytesperline;
+extern int reviewimage_bitmap_pad;
+
+
+/* Command line ..........*/
+extern double scale;
+extern int new_axes_x, new_axes_y;
+extern int new_control_x, new_control_y;
+
+extern int axes_xflag, axes_yflag;
+extern int controls_xflag, controls_yflag;
+extern int verboseflag;
+extern int titleflag;
+extern int depthflag;
+extern int reversevideoflag;
+extern int byteorderflag;
+
+
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+
+
+
+void initialise_X_screen()
+{
+  display = XOpenDisplay(display_name);
+  if (display == NULL) {
+    fprintf(stderr, "xreview : cannot connect to X server %s\n", XDisplayName(display_name));
+    exit(-1);}
+
+  screen_num = DefaultScreen(display);
+  screen_ptr = DefaultScreenOfDisplay(display);
+
+  display_width = DisplayWidth(display, screen_num);
+  display_height = DisplayHeight(display, screen_num);
+}  
+
+
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+
+
+void  initialise_axes_window(char *inputfn, char *titlestring, FILE *inputfp, char *argv[], int argc)
+{
+  char tempstring[MAX_STRING_LENGTH];
+  int status;
+
+/*-----------------------------------*/
+
+ /* Set title to either the filename, "stdin", ot the -title option. */
+  if (inputfp == stdin){
+    strcpy(tempstring, "stdin");
+    axes.window_name = tempstring;
+    axes.icon_name = tempstring;}
+  else {
+    axes.window_name = inputfn;
+    axes.icon_name = inputfn;}
+
+  if (titleflag == ON){
+    axes.window_name = titlestring;
+    axes.icon_name = titlestring; }
+    
+  /* Copy size off .ctn header */
+  axes.width = width_ctn;
+  axes.height = height_ctn;
+ 
+  /* Copy position off header  */
+  axes.x = x_ctn;
+  axes.y = y_ctn; 
+  if (x_ctn == -1)
+    axes.x = display_width/2 - axes.width/2;
+  if (y_ctn == -1)
+    axes.y = display_height/2 - axes.height/2;
+
+  /* If user requests new position, honour it */
+  if (axes_xflag == ON)
+    axes.x = new_axes_x;
+  if (axes_yflag == ON)
+    axes.y = new_axes_y;
+   
+/*---------------------------------*/
+
+  axes.win = XCreateSimpleWindow(display, RootWindow(display, screen_num), \
+				 axes.x, axes.y, axes.width, axes.height,\
+				 axes.border_width, \
+				 BlackPixel(display, screen_num), \
+				 WhitePixel(display, screen_num));
+  
+  axes.icon_pixmap = XCreateBitmapFromData(display, axes.win, xreview_bits, \
+					   xreview_width, xreview_height);
+  axes.gc = XCreateGC(display, axes.win, axes.valuemask, &axes.values);
+
+  axes.line_width = LINE_WIDTH_X;
+  axes.line_style = LINE_STYLE_X;
+  axes.cap_style = CAP_STYLE_X;
+  axes.join_style = JOIN_STYLE_X;
+  axes.foreground  = BlackPixel(display, screen_num);
+  
+  XSelectInput(display, axes.win, ExposureMask | KeyPressMask | \
+	       ButtonPressMask | StructureNotifyMask);
+  XSetFont(display, axes.gc, font_info->fid);
+  if (reversevideoflag == OFF) {
+    XSetForeground(display, axes.gc, axes.foreground);
+    XSetBackground(display, axes.gc, WhitePixel(display, screen_num));}
+  else{
+    XSetBackground(display, axes.gc, axes.foreground);
+    XSetForeground(display, axes.gc, WhitePixel(display, screen_num));}
+
+  XSetLineAttributes(display, axes.gc, axes.line_width, axes.line_style,\
+		     axes.cap_style, axes.join_style);
+  XSetPlaneMask(display, axes.gc, planemask);
+  XDefineCursor(display, axes.win, cursor);
+
+  axes.window_size = BIG_ENOUGH_X;
+
+/*---------------------------------*/  
+/* Window Manager bits. Assume R4. */
+
+  axes.size_hints.flags = PPosition | PSize | PMinSize | PMaxSize;
+  axes.size_hints.min_width = axes.width;
+  axes.size_hints.max_width = axes.width;
+  axes.size_hints.min_height = axes.height;
+  axes.size_hints.max_height = axes.height;
+
+  axes.wm_hints.initial_state = NormalState;
+  axes.wm_hints.input = True;
+  axes.wm_hints.icon_pixmap = axes.icon_pixmap;
+  axes.wm_hints.flags = StateHint | IconPixmapHint | InputHint;
+
+  axes.class_hints.res_name = progname;
+  axes.class_hints.res_class = "Xreview";
+
+  status = XStringListToTextProperty(&axes.window_name, 1, &axes.windowName);
+  if (status == 0) {
+    if (verboseflag == ON) fprintf(stderr, "\n");
+    fprintf(stderr,"xreview : structure allocation for cartoon windowName failed.\n");
+    exit(-1); }
+  
+  status = XStringListToTextProperty(&axes.icon_name, 1, &axes.iconName);
+  if (status == 0) {
+    if (verboseflag == ON) fprintf(stderr, "\n");
+    fprintf(stderr,"xreview : structure allocation for cartoon iconName failed.\n");
+    exit(-1); }
+
+  XSetWMProperties(display, axes.win, &axes.windowName, &axes.iconName, \
+		   argv, argc, \
+		   &axes.size_hints, &axes.wm_hints, &axes.class_hints);
+
+}
+
+
+
+/*----------------------------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+
+
+void  initialise_control_window(char *inputfn, char *titlestring, FILE *inputfp,  char *argv[], int argc)
+{
+  char tempstring[MAX_STRING_LENGTH];
+  int status;
+
+/*----------------------------------*/
+
+  control.window_name = "xreview controls";
+  control.icon_name = "Controls";
+
+  control.width = (int) CONTROL_WIDTH * scale;
+  control.height = (int) CONTROL_HEIGHT * scale;
+
+  control.x = CONTROL_X;
+  control.y = CONTROL_Y;
+
+  /* If user requests new position, honour it */
+  if (controls_xflag == ON)
+    control.x = new_control_x;
+  if (controls_yflag == ON)
+    control.y = new_control_y;
+
+/*---------------------------------*/
+   
+  control.win = XCreateSimpleWindow(display, RootWindow(display, screen_num), \
+                            control.x, control.y, control.width, \
+			    control.height, control.border_width, \
+                            BlackPixel(display, screen_num), \
+                            WhitePixel(display, screen_num));
+
+  control.icon_pixmap = XCreateBitmapFromData(display, control.win, \
+					      xreview_bits, \
+					      xreview_width, xreview_height);
+  control.gc = XCreateGC(display, control.win, \
+			 control.valuemask, &control.values);
+  
+  control.line_width = LINE_WIDTH_X;
+  control.line_style = LINE_STYLE_X;
+  control.cap_style = CAP_STYLE_X;
+  control.join_style = JOIN_STYLE_X;
+  control.foreground  = BlackPixel(display, screen_num);
+
+  XSelectInput(display, control.win, \
+	       ExposureMask | KeyPressMask | \
+	       ButtonPressMask | StructureNotifyMask);
+  XSetFont(display, control.gc, font_info->fid);
+  XSetForeground(display, control.gc, control.foreground);
+  XSetLineAttributes(display, control.gc, control.line_width, \
+		     control.line_style,control.cap_style, control.join_style);
+  XDefineCursor(display, control.win, cursor);
+  XSetWindowBackgroundPixmap(display, control.win, stipple_pixmap); 
+
+  control.window_size = BIG_ENOUGH_X;
+
+/*---------------------------------*/  
+/* Window Manager bits. Assume R4. */
+
+  control.size_hints.flags = PPosition | PSize | PMinSize | PMaxSize;
+  control.size_hints.min_width = control.width;
+  control.size_hints.min_height = control.height;
+  control.size_hints.max_width = control.width;
+  control.size_hints.max_height = control.height;
+
+  control.wm_hints.initial_state = NormalState;
+  control.wm_hints.input = True;
+  control.wm_hints.icon_pixmap = control.icon_pixmap;
+  control.wm_hints.flags = StateHint | IconPixmapHint | InputHint;
+
+  control.class_hints.res_name = "xreview controls";
+  control.class_hints.res_class = "Xreview";
+
+  status = XStringListToTextProperty(&control.window_name, 1, &control.windowName);
+  if (status == 0) {
+    if (verboseflag == ON) fprintf(stderr, "\n");
+    fprintf(stderr,"xreview : structure allocation for Controls windowName failed.\n");
+    exit(-1); }
+
+  status = XStringListToTextProperty(&control.icon_name, 1, &control.iconName);
+  if (status == 0) {
+    if (verboseflag == ON) fprintf(stderr, "\n");
+    fprintf(stderr,"xreview : structure allocation for Controls iconName failed.\n");
+    exit(-1); }
+
+  XSetWMProperties(display, control.win,&control.windowName,&control.iconName,\
+		   argv, argc, \
+		   &control.size_hints,&control.wm_hints,&control.class_hints);
+
+}
+
+
+
+/*--------------------------------------------------------------------*/
+/*--------------------------------------------------------------------*/
+
+
+
+void initialise_image()
+{
+  int offset = 0;
+  
+  if (depthflag == MONO)
+    reviewimage = XCreateImage(display, DefaultVisual(display, screen_num),\
+	 	     depth, XYBitmap, \
+		     offset, data_pointer, axes.width, axes.height,\
+		     reviewimage_bitmap_pad, reviewimage_bytesperline);
+  else
+    reviewimage = XCreateImage(display, DefaultVisual(display, screen_num),\
+	 	     depth, XYPixmap, \
+		     offset, data_pointer, axes.width, axes.height,\
+		     reviewimage_bitmap_pad, reviewimage_bytesperline);
+
+  if (byteorderflag == DEC) {
+    (*reviewimage).byte_order = LSBFirst;
+    (*reviewimage).bitmap_bit_order = LSBFirst;
+    (*reviewimage).bitmap_pad = 32;}
+  
+  if (byteorderflag == SUN) {
+    (*reviewimage).byte_order = MSBFirst;
+    (*reviewimage).bitmap_bit_order = MSBFirst;
+    (*reviewimage).bitmap_pad = 32;}
+  
+}
+
+
+
+
+/*----------------------------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+
+
+
+void exit_xreview()
+{
+  reviewimage->data = (char *) location[1];
+  XDestroyImage(reviewimage);
+  XUnloadFont(display, font_info->fid);
+  XFreeGC(display, axes.gc);
+  XFreeGC(display, control.gc);
+  XFreeGC(display, button_gc);
+  XCloseDisplay(display);
+  if (verboseflag==ON) fprintf(stderr, "\n");
+  exit(1);
+}
+
+
+
+/* The end.*/
+/*-------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xaim/makefile	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,134 @@
+#-------------------------------------------------------------------------
+#
+#   Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+#   ===========================================================================
+#   Permission to use, copy, modify, and distribute this software without fee 
+#   is hereby granted for research purposes, provided that this copyright 
+#   notice appears in all copies and in all supporting documentation, and that 
+#   the software is not redistributed for any fee (except for a nominal 
+#   shipping charge). Anyone wanting to incorporate all or part of this 
+#   software in a commercial product must obtain a license from the Medical 
+#   Research Council.
+#
+#   The MRC makes no representations about the suitability of this 
+#   software for any purpose.  It is provided "as is" without express or 
+#   implied warranty.
+# 
+#   THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+#   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+#   THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+#   OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+#   WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+#   ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+#   SOFTWARE.
+#
+#-------------------------------------------------------------------------
+#
+# makefile for xreview
+#
+# M.Akeroyd. Christmas 1993.
+#
+# Revisions: MAA & mitch d'souza: autumn 1993: 
+#            changed the definition of 'CC' so that it would work on 
+#            Sparc/Openwindows/gcc: seems the -Bstatic gest rid of a 
+#            well-known Sun bug, and the -Xlinker stops it looking in
+#            the default lib location /usr/local/lib
+#            Also added lots of extra libs (Xext, Xt, m), again so as
+#            to work under Sparc/Openwindows/gcc.
+# 
+#--------------------------------------------------------------------------
+
+# linux 386 pc 
+#CC = gcc
+#CFLAGS= -DHOST_LINUXPC -O -I/usr/local/X386/include -L/usr/local/X386/lib 
+#LIBS = -lXmu -lX11
+
+# Sparc (NOT openwindows)
+#CC = gcc 
+###CFLAGS=  -O -I/usr/local2/include -L/usr/local2/lib 
+#LIBS =  -lXmu -lX11
+
+# Sparc & Openwindows 
+#CC = gcc -Xlinker -Bstatic
+#CFLAGS = -O -s -I/usr/openwin/include -L/usr/openwin/lib
+#LIBS = -lXt -lXext -lXmu -lX11 -lm
+
+# DECstation 3100
+#CC = gcc
+#CFLAGS= -DHOST_DECSTATION -O -I/usr/local2/include -L/usr/local2/lib 
+#LIBS = -lXmu -lX11
+
+#--------------------------------------------------------------------------
+
+TARFILE = xreview.tar
+
+all: synthirn xreview
+
+clean:
+	rm -f *.o xreview $(TARFILE)
+
+tidy: 
+	rm -f *.o
+
+tar: 
+	tar cvf $(TARFILE) cartoon.c initialise.c buttons.c graphics.c \
+	switch_control.c switch_axes.c switch_buttons.c xreview.c \
+	xreview.h xreview.bitmap stipple_a disclaimer.text releasenotes.text \
+	makefile synthirn.c
+
+#--------------------------------------------------------------------------
+synthirn: synthirn.o
+	  $(CC) -o synthirn synthirn.o -lm
+
+synthirn.o: synthirn.c
+	    $(CC) -c synthirn.c
+
+synthdramp: synthdramp.o
+	  $(CC) -o synthdramp synthdramp.o -lm
+
+synthdramp.o: synthdramp.c
+	    $(CC) -c synthdramp.c
+
+xreview: cartoon.o initialise.o buttons.o  graphics.o \
+	switch_control.o switch_axes.o switch_buttons.o \
+	xreview.h xreview.bitmap stipple_a \
+	xreview.o
+	$(CC) $(CFLAGS) -o xreview \
+	cartoon.o initialise.o buttons.o graphics.o \
+	switch_control.o switch_axes.o switch_buttons.o  \
+	xreview.o  $(LDFLAGS)
+
+cartoon.o: cartoon.c xreview.h
+	$(CC) $(CFLAGS) -c cartoon.c
+
+initialise.o: initialise.c xreview.h xreview.bitmap stipple_a
+	$(CC) $(CFLAGS) -c initialise.c
+
+buttons.o: buttons.c xreview.h
+	$(CC) $(CFLAGS) -c buttons.c
+
+graphics.o: graphics.c xreview.h
+	$(CC) $(CFLAGS) -c graphics.c
+
+switch_control.o: switch_control.c xreview.h
+	$(CC) $(CFLAGS) -c switch_control.c
+
+switch_axes.o: switch_axes.c xreview.h
+	$(CC) $(CFLAGS) -c switch_axes.c
+
+switch_buttons.o: switch_buttons.c xreview.h
+	$(CC) $(CFLAGS) -c switch_buttons.c
+
+xreview.o: xreview.c xreview.h
+	$(CC) $(CFLAGS) -c xreview.c
+
+#--------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xaim/releasenotes.text	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,24 @@
+xreview.  Christmas 1993. 
+
+1. compilation
+The makefile has flag settings for a linux 386 PC, Sun/OpenWindows, 
+Sun/X, and DECStation. The default values are for DEC; if you need a 
+different architecture, comment them out.
+
+2. Known bugs.
+a. 'Previous' and 'Next' (keyboard options) do not work on a DEC
+b. ALL timing functions are removed in the Linux version. This means that
+   it is not possible to control the animation speed.
+
+3. Byte-Swapping
+Suns have a different byte-swapping to DECs and Linux PCs (well, my PC
+anyway). Because AIM cartoons are simply a copy of the screen memory, their
+byte-order is determined by the SCREEN they were generated on, NOT the
+cpu used. 'xreview' will display anything in either byte-swapping format,
+by using '-dec' or '-sun' options (which are aliases for '-rv', '-msb', -'lsb).
+If what you get is gunk, try using them (the default is the current cpu
+byte-order).
+
+4. Colour
+Not tested; you get to play with the colour masks ...
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xaim/stipple_a	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,32 @@
+/*
+   Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+   ===========================================================================
+   Permission to use, copy, modify, and distribute this software without fee 
+   is hereby granted for research purposes, provided that this copyright 
+   notice appears in all copies and in all supporting documentation, and that 
+   the software is not redistributed for any fee (except for a nominal 
+   shipping charge). Anyone wanting to incorporate all or part of this 
+   software in a commercial product must obtain a license from the Medical 
+   Research Council.
+
+   The MRC makes no representations about the suitability of this 
+   software for any purpose.  It is provided "as is" without express or 
+   implied warranty.
+ 
+   THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+   THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+   OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+   WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+   ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+   SOFTWARE.
+*/
+
+/* stipple_a: background for the Control window buttons.
+*  M.Akeroyd. July 1993. 
+*/
+
+#define stipple_a_width 8
+#define stipple_a_height 8
+static char stipple_a_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xaim/switch_axes.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,222 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/* 
+*   switch_axes.c
+*   -------------
+*  'switch' code for the axes (=cartoon image) window.
+*
+*  M. Akeroyd.  July 1993. version 1.10
+*  Revisions: MAA: Christmas 1993. 
+*/
+
+
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+#include <stdio.h>
+
+#include "xreview.h"
+
+
+
+/* General .................*/
+
+
+/* X ........................*/
+
+extern Display *display;
+extern int screen_num;
+extern Screen *screen_ptr;
+
+extern toplevelWindow control;
+extern toplevelWindow axes;
+extern buttonWindow info_speed, info_frame;
+extern XFontStruct font_info;
+
+extern XEvent report;
+extern GC button_gc;
+
+
+/* .ctn .....................*/
+
+extern int frame;
+extern int no_frames;
+
+extern int animate_start;
+extern int animate_stop;
+extern int animate_skip;
+
+extern long waittime_millisecs;
+
+
+/* extras for the pcroy version */
+extern int animate_start;
+extern int animate_stop;
+extern int animate_skip;
+
+/*--------------------------------------------------------------------*/
+/*--------------------------------------------------------------------*/
+
+
+
+
+
+void switch_axes()
+{
+  char tempstring[MAX_STRING_LENGTH];
+  char buffer[20];
+  int bufsize = 20;
+  int charcount;
+  XComposeStatus compose_X;
+  KeySym keysym_X;
+
+  switch(report.type) {
+    
+/*---------------------------------------------*/
+
+  case Expose:
+    if (report.xexpose.count != 0)
+      break;
+	
+    if ((axes.window_size == TOO_SMALL_X) ||
+	(axes.window_size == TOO_BIG_X))
+      break;
+
+    drawimage(frame); 
+    break;
+    
+/*---------------------------------------------*/
+	
+  case ConfigureNotify:
+    axes.width = report.xconfigure.width;
+    axes.height = report.xconfigure.height;
+
+    /* No resizing allowed */
+    axes.window_size = BIG_ENOUGH_X;
+    if ((axes.width < axes.size_hints.min_width) || \
+	(axes.height < axes.size_hints.min_height))
+      axes.window_size = TOO_SMALL_X;
+    if ((axes.width > axes.size_hints.max_width) || \
+	(axes.height > axes.size_hints.max_height))
+      axes.window_size = TOO_BIG_X;
+    break;
+	
+/*---------------------------------------------*/
+
+  case ButtonPress:
+    
+    /* if button 1, animate */
+    if (report.xbutton.button == Button1)  {
+      animate_image(animate_start, animate_stop, animate_skip);
+      break;}
+
+    /* if button 2, map control window */
+    if (report.xbutton.button == Button2)  {
+      XMapWindow(display, control.win); 
+      break;}
+    
+    /* If button 3, quit. */
+    if (report.xbutton.button == Button3)  {
+      exit_xreview(); 
+    }
+    
+    break;
+
+/*---------------------------------------------*/
+	
+  case KeyPress:
+    
+    charcount = XLookupString(&report.xkey, buffer, bufsize, &keysym_X, &compose_X);
+    
+    if ((keysym_X == XK_space) || (keysym_X == XK_Return)) {
+      animate_image(animate_start, animate_stop, animate_skip);
+      break;}
+
+    if ((keysym_X == XK_N) || (keysym_X == XK_n)) {
+      frame++;
+      if (frame > no_frames) 
+        frame = no_frames;
+      drawimage(frame);
+      XClearWindow(display, info_frame.win);
+      sprintf(tempstring, "%i of %i", frame, no_frames);
+      drawtext(info_frame, button_gc, font_info, tempstring);
+      XFlush(display);}
+
+    if ((keysym_X == XK_p) || (keysym_X == XK_p)) {
+      frame--;
+      if (frame < 1) 
+        frame = 1;
+      drawimage(frame);
+      XClearWindow(display, info_frame.win);
+      sprintf(tempstring, "%i of %i", frame, no_frames);
+      drawtext(info_frame, button_gc, font_info, tempstring);
+      XFlush(display);}
+
+    if ((keysym_X == XK_F)|| (keysym_X == XK_f)){
+      waittime_millisecs = (long) waittime_millisecs / 2;
+#ifndef HOST_LINUXPC
+      if (waittime_millisecs < 1)
+	waittime_millisecs = 1;
+#endif
+      sprintf(tempstring, "Speed: %li", waittime_millisecs);
+      XClearWindow(display, info_speed.win);
+      drawtext(info_speed, button_gc, font_info, tempstring);
+      XFlush(display);
+      break;}
+
+    if ((keysym_X == XK_S)|| (keysym_X == XK_s)){
+#ifndef HOST_LINUXPC
+      waittime_millisecs = (long) waittime_millisecs * 2;
+#endif
+      sprintf(tempstring, "Speed: %li", waittime_millisecs);
+      XClearWindow(display, info_speed.win);
+      drawtext(info_speed, button_gc, font_info, tempstring);
+      XFlush(display);
+      break;}
+   
+    if ((keysym_X == XK_q) || (keysym_X == XK_Q)) {
+      exit_xreview(); }
+       
+    break;
+
+/*---------------------------------------------*/
+    
+  default:
+    break;
+
+    
+  } /* switch */
+
+}
+
+
+
+
+/* The End */
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xaim/switch_buttons.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,280 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/* 
+*   switch_buttons.c
+*   ----------------
+* The 'switch' code for all the Control Window buttons.
+*
+*  M. Akeroyd.  July 1993. version 1.10
+*  Revisions: MAA: Christmas 1993.
+*
+*/
+
+
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+#include <stdio.h>
+
+#include "xreview.h"
+
+
+/* General ................*/
+
+extern char *data_pointer;
+extern long location[MAX_FRAMES];
+
+
+/* X ......................*/
+
+extern Display *display;
+extern int screen_num;
+extern Screen *screen_ptr;
+
+extern toplevelWindow control;
+extern toplevelWindow axes;
+extern XImage *reviewimage;
+
+extern buttonWindow button_quit, button_close;
+extern buttonWindow button_animate;
+extern buttonWindow button_startf, button_startb, button_stopf, button_stopb;
+extern buttonWindow button_skipf, button_skipb, button_faster, button_slower;
+extern buttonWindow button_firstframe, button_lastframe, button_middle;
+extern buttonWindow button_stepf, button_stepff, button_stepb, button_stepbb;
+
+extern buttonWindow info_speed, info_start, info_stop, info_skip;
+extern buttonWindow info_title, info_frame;
+extern buttonWindow info_time, info_freq, info_frstep;
+
+extern GC button_gc;
+extern int button_borderwidth;
+
+extern XFontStruct *font_info;
+extern XEvent report;
+
+
+/* .ctn ......................*/
+
+extern int animate_start;
+extern int animate_stop;
+extern int animate_skip;
+extern int frame;
+extern int no_frames;
+extern long waittime_millisecs;
+
+
+
+
+/*-------------------------------------------------------------------*/
+/*-------------------------------------------------------------------*/
+
+
+
+
+void switch_buttons()
+{
+  char tempstring[MAX_STRING_LENGTH];
+
+  /*--------------------------------------------------------*/    
+
+  if (report.xbutton.button != Button1)  
+    return ;
+
+  if (report.xany.window == button_quit.win) {
+    flashbutton(control, button_quit, &button_gc, "Quit");
+    exit_xreview();}
+
+
+  if (report.xany.window == button_close.win) {
+    flashbutton(control, button_close, &button_gc, "Close");
+    XUnmapWindow(display, control.win);}
+
+  
+  if (report.xany.window == button_animate.win){ 
+    flashbutton(control, button_animate, &button_gc, "Animate");
+    animate_image(animate_start, animate_stop, animate_skip);}
+
+
+  if (report.xany.window == button_startf.win) {
+    flashbutton(control, button_startf, &button_gc, "+1");
+    animate_start++;
+    if (animate_start == no_frames)
+      animate_start = no_frames-1;
+    sprintf(tempstring, "Start: %i", animate_start);
+    XClearWindow(display, info_start.win);
+    drawtext(info_start, button_gc, font_info, tempstring);}
+
+
+  if (report.xany.window == button_startb.win) {
+    flashbutton(control, button_startb, &button_gc, "-1");
+    animate_start--;
+    if (animate_start == 0)
+      animate_start = 1;
+    sprintf(tempstring, "Start: %i", animate_start);
+    XClearWindow(display, info_start.win);
+    drawtext(info_start, button_gc, font_info, tempstring);}
+
+
+  if (report.xany.window == button_stopf.win) {
+    flashbutton(control, button_stopf, &button_gc, "+1");
+    animate_stop++;
+    if (animate_stop == no_frames +1)
+      animate_stop = no_frames;
+    sprintf(tempstring, "Stop: %i", animate_stop);
+    XClearWindow(display, info_stop.win);
+    drawtext(info_stop, button_gc, font_info, tempstring);}
+
+
+  if (report.xany.window == button_stopb.win) {
+    flashbutton(control, button_stopb, &button_gc, "-1");
+    animate_stop--;
+    if (animate_stop == 1)
+      animate_stop = 2;
+    sprintf(tempstring, "Stop: %i", animate_stop);
+    XClearWindow(display, info_stop.win);
+    drawtext(info_stop, button_gc, font_info, tempstring);}
+  
+
+  if (report.xany.window == button_skipf.win) {
+    flashbutton(control, button_skipf, &button_gc, "+1");
+    animate_skip++;
+    if (animate_skip == no_frames)
+      animate_start = no_frames-1;
+    sprintf(tempstring, "Skip: %i", animate_skip);
+    XClearWindow(display, info_skip.win);
+    drawtext(info_skip, button_gc, font_info, tempstring);}
+
+
+  if (report.xany.window == button_skipb.win) {
+    flashbutton(control, button_skipb, &button_gc, "-1");
+    animate_skip--;
+    if (animate_skip == 0)
+      animate_skip = 1;
+    sprintf(tempstring, "Skip: %i", animate_skip);
+    XClearWindow(display, info_skip.win);
+    drawtext(info_skip, button_gc, font_info, tempstring);}
+
+  
+  if (report.xany.window == button_faster.win) {
+    flashbutton(control, button_faster, &button_gc, "Fast");
+    waittime_millisecs = (long) waittime_millisecs / 2;
+    if (waittime_millisecs < 1)
+      waittime_millisecs = 1;
+    sprintf(tempstring, "Speed: %li", waittime_millisecs);
+    XClearWindow(display, info_speed.win);
+    drawtext(info_speed, button_gc, font_info, tempstring);}
+  
+
+  if (report.xany.window == button_slower.win) {
+    flashbutton(control, button_slower, &button_gc, "Slow");
+    waittime_millisecs = (long) waittime_millisecs * 2;
+    sprintf(tempstring, "Speed: %li", waittime_millisecs);
+    XClearWindow(display, info_speed.win);
+    drawtext(info_speed, button_gc, font_info, tempstring);}
+    
+
+  if (report.xany.window == button_lastframe.win) {
+    flashbutton(control, button_lastframe, &button_gc, "Last"); 
+    frame=no_frames;
+    drawimage(frame);
+    XClearWindow(display, info_frame.win);
+    sprintf(tempstring, "%i of %i", frame, no_frames);
+    drawtext(info_frame, button_gc, font_info, tempstring);}
+  
+  
+  if (report.xany.window == button_firstframe.win) {
+    flashbutton(control, button_firstframe, &button_gc, "First"); 
+    frame=1;
+    drawimage(frame);
+    XClearWindow(display, info_frame.win);
+    sprintf(tempstring, "%i of %i", frame, no_frames);
+    drawtext(info_frame, button_gc, font_info, tempstring);}
+
+
+  if (report.xany.window == button_middle.win) {
+    flashbutton(control, button_middle, &button_gc, "Middle"); 
+    frame=no_frames/2;
+    if (frame == 0)
+      frame = 1;
+    drawimage(frame);
+    XClearWindow(display, info_frame.win);
+    sprintf(tempstring, "%i of %i", frame, no_frames);
+    drawtext(info_frame, button_gc, font_info, tempstring);}
+  
+
+  if (report.xany.window == button_stepf.win) {
+    flashbutton(control, button_stepf, &button_gc, ">");
+    frame++;
+    if (frame > no_frames) 
+      frame = no_frames;
+    drawimage(frame);
+    XClearWindow(display, info_frame.win);
+    sprintf(tempstring, "%i of %i", frame, no_frames);
+    drawtext(info_frame, button_gc, font_info, tempstring);}
+
+  
+  if (report.xany.window == button_stepff.win) {
+    flashbutton(control, button_stepff, &button_gc, ">>");
+    frame+=10;
+    if (frame > no_frames) 
+      frame = no_frames;
+    drawimage(frame);
+    XClearWindow(display, info_frame.win);
+    sprintf(tempstring, "%i of %i", frame, no_frames);
+    drawtext(info_frame, button_gc, font_info, tempstring);}
+
+  
+  if (report.xany.window == button_stepb.win) {
+    flashbutton(control, button_stepb, &button_gc, "<"); 
+    frame--;
+    if (frame < 1) 
+      frame = 1;
+    drawimage(frame);
+    XClearWindow(display, info_frame.win);
+    sprintf(tempstring, "%i of %i", frame, no_frames);
+    drawtext(info_frame, button_gc, font_info, tempstring);}
+
+
+  if (report.xany.window == button_stepbb.win) {
+    flashbutton(control, button_stepbb, &button_gc, "<<"); 
+    frame-=10;
+    if (frame < 1) 
+      frame = 1;    
+    drawimage(frame);
+    XClearWindow(display, info_frame.win);
+    sprintf(tempstring, "%i of %i", frame, no_frames);
+    drawtext(info_frame, button_gc, font_info, tempstring);}
+
+}
+  
+  
+
+
+/* The End */
+/*-------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xaim/switch_control.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,267 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/* 
+*   switch_control.c
+*   ----------------
+*  the 'switch' for the Controls Window.
+*
+*  M. Akeroyd.  July 1993. version 1.10
+*  Revisions: MAA: Christmas 1993.
+*
+*/
+
+
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+#include <stdio.h>
+
+#include "xreview.h"
+
+
+/* General ..................*/
+
+char progname[MAX_STRING_LENGTH];
+
+
+/* X ........................*/
+
+extern Display *display;
+extern int screen_num;
+extern Screen *screen_ptr;
+
+extern toplevelWindow control;
+extern toplevelWindow axes;
+
+extern buttonWindow button_quit, button_close;
+extern buttonWindow button_animate;
+extern buttonWindow button_startf, button_startb, button_stopf, button_stopb;
+extern buttonWindow button_skipf, button_skipb, button_faster, button_slower;
+extern buttonWindow button_firstframe, button_lastframe, button_middle;
+extern buttonWindow button_stepf, button_stepff, button_stepb, button_stepbb;
+
+extern buttonWindow info_speed, info_start, info_stop, info_skip;
+extern buttonWindow info_title, info_frame;
+extern buttonWindow info_time, info_freq, info_frstep;
+
+extern XFontStruct *font_info;
+extern GC button_gc;
+extern XEvent report;
+
+extern int button_borderwidth;
+
+
+/* .ctn .......................*/
+
+extern int frame;
+extern int no_frames;
+extern double frstep_aid;
+extern double pwidth; 
+extern double nwidth; 
+extern int mincf;
+extern int maxcf;     
+
+extern int waittime_millisecs;
+extern int animate_start;
+extern int animate_stop;
+extern int animate_skip;
+
+
+/* Command line ...............*/
+extern double scale;
+
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------*/
+
+
+
+
+void switch_control()
+{
+  char tempstring[MAX_STRING_LENGTH];
+  int whitepixel = WhitePixel(display, screen_num);
+  int blackpixel = BlackPixel(display, screen_num);
+
+  
+  switch(report.type) {
+    
+/*----------------------------------*/
+    
+  case Expose:
+    if (report.xexpose.count != 0)
+      break;
+
+    if ((control.window_size == TOO_SMALL_X) ||
+	(control.window_size == TOO_BIG_X))
+      break;
+
+    XDrawLine(display, control.win, control.gc, \
+	      0, 80*scale, control.width, 80*scale);
+    XDrawLine(display, control.win, control.gc, \
+	      0, 162*scale, control.width, 162*scale);
+    
+    XMapWindow(display, button_quit.win);
+    XMapWindow(display, button_close.win);
+    XMapWindow(display, button_animate.win);
+    XMapWindow(display, button_startf.win);
+    XMapWindow(display, button_startb.win);
+    XMapWindow(display, button_stopf.win);
+    XMapWindow(display, button_stopb.win);
+    XMapWindow(display, button_skipf.win);
+    XMapWindow(display, button_skipb.win);
+    XMapWindow(display, button_faster.win);
+    XMapWindow(display, button_slower.win);
+    XMapWindow(display, button_lastframe.win);
+    XMapWindow(display, button_firstframe.win);
+    XMapWindow(display, button_middle.win);
+    XMapWindow(display, button_stepf.win);
+    XMapWindow(display, button_stepff.win);
+    XMapWindow(display, button_stepb.win);
+    XMapWindow(display, button_stepbb.win);
+
+    drawbutton(control, button_quit, &button_gc, "Quit",\
+	       whitepixel, blackpixel);
+    drawbutton(control, button_close, &button_gc, "Close", \
+	       whitepixel, blackpixel);
+
+    drawbutton(control, button_animate, &button_gc, "Animate", \
+	       whitepixel, blackpixel);
+    drawbutton(control, button_startf, &button_gc, "+1", \
+	       whitepixel, blackpixel);
+    drawbutton(control, button_startb, &button_gc, "-1", \
+	       whitepixel,  blackpixel);
+    drawbutton(control, button_stopf, &button_gc, "+1", \
+	       whitepixel, blackpixel);
+    drawbutton(control, button_stopb, &button_gc, "-1", \
+	       whitepixel, blackpixel);
+    drawbutton(control, button_skipf, &button_gc, "+1", \
+	       whitepixel, blackpixel);
+    drawbutton(control, button_skipb, &button_gc, "-1", \
+	       whitepixel, blackpixel);
+    drawbutton(control, button_faster, &button_gc, "Fast", \
+	       whitepixel, blackpixel);
+    drawbutton(control, button_slower, &button_gc, "Slow", \
+	       whitepixel, blackpixel);
+
+    drawbutton(control, button_lastframe, &button_gc, "Last", \
+	       whitepixel, blackpixel);
+    drawbutton(control, button_firstframe, &button_gc, "First", \
+	       whitepixel, blackpixel);
+    drawbutton(control, button_middle, &button_gc, "Middle", \
+	       whitepixel, blackpixel);
+    drawbutton(control, button_stepf, &button_gc, ">", \
+	       whitepixel, blackpixel);
+    drawbutton(control, button_stepff, &button_gc, ">>", \
+	       whitepixel, blackpixel);
+    drawbutton(control, button_stepb, &button_gc, "<", \
+	       whitepixel, blackpixel);
+    drawbutton(control, button_stepbb, &button_gc, "<<", \
+	       whitepixel, blackpixel);
+    
+
+
+    XMapWindow(display, info_speed.win);
+    sprintf(tempstring, "Speed: %i", waittime_millisecs);
+    drawtext(info_speed, button_gc, font_info, tempstring);
+
+    XMapWindow(display, info_start.win);
+    sprintf(tempstring, "Start: %i", animate_start);
+    drawtext(info_start, button_gc, font_info, tempstring);
+
+    XMapWindow(display, info_stop.win);
+    sprintf(tempstring, "Stop: %i", animate_stop);
+    drawtext(info_stop, button_gc, font_info, tempstring);
+
+    XMapWindow(display, info_skip.win);
+    sprintf(tempstring, "Skip: %i", animate_skip);
+    drawtext(info_skip, button_gc, font_info, tempstring);
+    
+    XMapWindow(display, info_frame.win);
+    sprintf(tempstring, "%i of %i", frame, no_frames);
+    drawtext(info_frame, button_gc, font_info, tempstring);
+    
+    XMapWindow(display, info_title.win);
+    sprintf(tempstring, "%s", axes.window_name);
+    drawtext(info_title, button_gc, font_info, tempstring);
+    
+    XMapWindow(display, info_freq.win);
+    sprintf(tempstring, "Freq %i-%iHz", mincf, maxcf);
+    drawtext(info_freq, button_gc, font_info, tempstring);
+    
+    XMapWindow(display, info_time.win);
+    sprintf(tempstring, "Interval %.1f...%.1fms", pwidth, nwidth);
+    drawtext(info_time, button_gc, font_info, tempstring);
+    
+    XMapWindow(display, info_frstep.win);
+    sprintf(tempstring, "frstep: %.1fms", frstep_aid);
+    drawtext(info_frstep, button_gc, font_info, tempstring);
+    
+    
+    break;
+	
+
+/*--------------------------------------*/	
+
+
+  case ConfigureNotify:
+    if (report.xconfigure.window != control.win)
+      break;
+    
+    control.width = report.xconfigure.width;
+    control.height = report.xconfigure.height;
+    
+    control.window_size = BIG_ENOUGH_X;
+    if ((control.width < control.size_hints.min_width) || \
+	(control.height < control.size_hints.min_height))
+      control.window_size = TOO_SMALL_X;
+    if ((control.width > control.size_hints.max_width) || \
+	(control.height > control.size_hints.max_height))
+      control.window_size = TOO_BIG_X;
+    break;
+
+/*--------------------------------------*/
+
+  default:
+    break;
+
+  } /* switch */
+    
+}
+
+
+
+
+
+
+/* The End */
+/*-------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xaim/synthdramp.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,288 @@
+/*  synthdramp
+*   ------------
+*
+*   (A tidied-up version of makeping)
+*    
+*   original:   M. Akeroyd. Autumn 1992.
+*
+*   revisions:  roy: 3dec92: decay parameter is now half-life.
+*               MAA:  sep93: tidied up the code, got rid of the .h file
+*
+*               MAA: February 1994: added floor values.
+*               MAA: March 1994: Added initial offsets, and 'steps'
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+/* the following used to be in "makeping.h" */
+
+#define PulseFreqDef 40                 /* Hz */
+#define SinFreqDef 800                  /* carrier freq: Hz */
+#define SampRateDef 20000               /* sampling rate: samples per sec */
+#define SinPhaseDef 0.0                 /* of carrier wrt to pulse: degrees */
+#define AmpMaxDef 10000                 /* max amplitude */
+#define NoOfPulsesDef 20                /* how many to make */
+#define MaxNoSamplesPerWave 882000      /* limit on array size */
+#define DampCoefDef 5.0                 /* half-life; msecs */
+#define FileNameDef "nofilespecified"    
+#define FORWARD 2                       /* "forward" == damp, */
+#define BACKWARD 3        		/* "backward" == ramp. 
+					 * (for historical reasons).
+					 */
+#define ON 1
+#define OFF 0
+#define PI 3.141592654
+
+
+
+
+/*---------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------*/
+
+
+main(int argc, char *argv[])
+{
+  int x = 1;
+  int helpflag = OFF;
+  int gateoption = OFF;
+  int toneflag = OFF;
+  int floorflag = OFF;
+  long pulsefreq = PulseFreqDef;   
+  long sinfreq = SinFreqDef;       
+  long samprate = SampRateDef;     
+  long ampmax = AmpMaxDef;         
+  double sinphase = SinPhaseDef;   
+  long noofpulses = NoOfPulsesDef;               
+  double dampcoef = (double) DampCoefDef;
+  int directionflag = FORWARD;
+  short sample_short[MaxNoSamplesPerWave];         /* the array of data ... */
+
+  char *filename = FileNameDef;
+  FILE *filepointer;
+
+  long sampleno, localsampleno,  lengthwave_samples;
+  double lengthpulse_samples;
+  double phaserad;
+  double expfactor;
+  double temp;
+  double lengthwave;
+  double sinfreqrad;
+  
+  int floor = 0;
+  int offset_ms = 0;
+  int phase_deg = 0;
+  long offset_samples = 0;
+  double fraction = 0.0;
+  long temp_samples = 0;
+  int delay_ms = 0;
+  long delay_samples = 0;
+
+/*---------------------------------------------------------*/
+
+/* Options handler. Hack but it works.
+*  ....................................
+*/
+
+  /* special hack for '-h' */
+  if ((argc ==2) && (!strcmp(argv[1], "-h"))) {
+    argc=1;      /* to bypass the upcoming 'while' */
+    helpflag=ON;}
+
+  while (x < argc )
+    {
+      if (!strcmp(argv[x], "-p")) { pulsefreq=atol(argv[x+1]); x += 2;}
+      else if (!strcmp(argv[x], "-f")) { sinfreq=atol(argv[x+1]); x += 2; }
+      else if (!strcmp(argv[x], "-s")) { samprate=atol(argv[x+1]); x += 2;}
+      else if (!strcmp(argv[x], "-w")) { sinphase=atof(argv[x+1]); x += 2;}
+      else if (!strcmp(argv[x], "-m")) { ampmax=atol(argv[x+1]); x += 2;}
+      else if (!strcmp(argv[x], "-n")) { noofpulses=atof(argv[x+1]); x += 2;}
+      else if (!strcmp(argv[x], "-h")) { dampcoef=atof(argv[x+1]); x += 2;}
+      else if (!strcmp(argv[x], "-floor")) { floorflag=ON; floor=atoi(argv[x+1]); x += 2;}
+      else if (!strcmp(argv[x], "-offset")) { offset_ms=atoi(argv[x+1]); x += 2;}
+      else if (!strcmp(argv[x], "-delay")) { delay_ms=atoi(argv[x+1]); x += 2;}
+      else if (!strcmp(argv[x], "-phase")) { phase_deg=atoi(argv[x+1]); x += 2;}
+      else if (!strcmp(argv[x], "-frac")) { fraction=atof(argv[x+1]); x += 2;}
+      else if (!strcmp(argv[x], "-t")) { toneflag=ON; x += 1;}
+      else if (!strcmp(argv[x], "-o")) { filename=argv[x+1]; x+=2;}
+      else if (!strcmp(argv[x], "-d")) { directionflag=FORWARD; x+=1;}
+      else if (!strcmp(argv[x], "-r")) { directionflag=BACKWARD; x+=1;}
+      else if (!strcmp(argv[x], "-help")) { helpflag=ON; x+=1;}
+      else if (!strcmp(argv[x], "-g")) { gateoption=ON; x+=1;}
+      else { printf("\nUnknown Option : %s \n", argv[x]);
+               return 1;}
+    }
+
+  if ((helpflag == ON) || (argc == 1))
+    {printf("\n   ----------        synthdramp (Winter 1994)     --------------\n");
+     printf("\n");
+     printf("Tone options : \n");
+     printf(" -w <flt>      phase of sin wave, wrt begining of pulse  default: %3.3f degs\n", SinPhaseDef);
+     printf(" -f <int>      carrier frequency                         default: %d Hz\n", SinFreqDef);
+     printf("\n");
+     printf("Gate options : \n");
+     printf(" -d            damped sinusoid (default)\n");
+     printf(" -r            ramped sinusoid          \n");
+     printf(" -s <int>      sampling rate                             default: %d samp/sec\n", SampRateDef);
+     printf(" -m <int>      max amplitude                             default: %d \n", AmpMaxDef);
+     printf(" -n <int>      number of cycles in train                 default: %d \n", NoOfPulsesDef);
+     printf(" -h <flt>      half-life                                 default: %3.3f \n", DampCoefDef);
+     printf(" -p <int>      repitition rate                           default: %d Hz\n", PulseFreqDef);
+     printf(" -floor <int>  floor value                               default: %d \n", floor);
+     printf(" -delay <int>  delay at begining (ms)                    default: %d \n", delay_ms);
+     printf("\n");
+     printf("'Step' options (only work if just gate is created): \n");
+     printf(" -offset <int> offset time to step (ms)                  default: %d \n", offset_ms);
+     printf(" -phase <int>  offset, measured as phase delay           default: %d degrees\n", phase_deg);
+     printf(" -frac  <flt>  fractional height of step                 default: 3.3f \n", fraction);
+     printf("\n");
+     printf("Output options : \n");
+     printf(" -g            gate only : no tone\n");
+     printf(" -t            tone only : no gate\n");
+     printf(" -o ''         output filename \n");
+     printf("\n");
+     exit(-1);
+   }
+
+  if (!strcmp(FileNameDef, filename))
+    {
+      fprintf(stderr, "\n No file has been specified. Stopping. \n\n");
+      exit(-1);
+    }
+
+
+/*---------------------------------------------------------*/
+
+  /* convert the damping coeeficent from a half-life to whatever the internal
+   * value is.
+   * roy 23-11-92 thru 3-12-92) */
+  dampcoef = 0.693147/(dampcoef/1000) ;
+
+  /* define useful things: 
+   * lengthwave: overall length of wave, in seconds.
+   * lengthwave_samples: overlall length of wave, in samples.
+   * lengthpulse_samples: length of each pulse, in samples.
+   * phaserad: the phase angle, in radians as against degrees.
+   * sinfreqrad: constant to speed the code up.
+   */
+  lengthwave = (double) noofpulses / pulsefreq;       
+  lengthwave_samples = (long) samprate * noofpulses / pulsefreq;       
+  lengthpulse_samples = (double) samprate / pulsefreq;
+
+  phaserad = sinphase * PI / 180;
+  sinfreqrad = (double) 2 * PI * sinfreq;
+
+  /* error-check */
+  if (lengthwave_samples >= MaxNoSamplesPerWave) {
+    fprintf(stderr, "Wave too long for internal arrays. \n");
+    exit(-1);}
+  
+/*---------------------------------------------------------*/
+
+
+/* delay */
+
+  for (sampleno=0; sampleno < lengthwave_samples; sampleno++) 
+    sample_short[sampleno] = (short) 0;
+
+  filepointer = fopen(filename, "w"); 
+
+  if (delay_ms != 0) {
+    delay_samples = (long) samprate * delay_ms / 1000;
+    fwrite(sample_short, 2, delay_samples, filepointer);}
+
+  for (sampleno=0; sampleno < lengthwave_samples; sampleno++) 
+	sample_short[sampleno] = (short) 0;
+
+
+/*---------------------------------------------------------*/
+
+  /* for each sample, from 0 to the end, work out its value by (1) taking the 
+   * value of the carrier, and (2) multiplying it by the exp factor.
+   * if the "-g" option has been called, then in effect make the exp "gate"
+   * only ...
+   * The results go into sample_short[].
+   */
+
+/*---------------------------*/
+  for (sampleno=0; sampleno < lengthwave_samples; sampleno++) {
+
+      temp = (double) (fmod(sampleno, lengthpulse_samples)) / samprate; 
+      expfactor = exp( -1 * dampcoef * temp ) ; /* * samprate  roy */
+
+      if (directionflag == FORWARD)
+	localsampleno = sampleno;
+      else
+	localsampleno = lengthwave_samples -2  - sampleno;         
+        /* -2 seems to work */
+      
+      sample_short[localsampleno]= ampmax * sin(sinfreqrad * temp + phaserad) * expfactor;
+      if (gateoption == ON)
+	sample_short[localsampleno] = ampmax * expfactor;
+     if (floorflag == ON)  
+      if (sample_short[localsampleno] <= floor )
+	sample_short[localsampleno] = (short) floor;
+    }
+
+  if (toneflag == ON) {
+    for (sampleno=0; sampleno < lengthwave_samples; sampleno++) {
+      temp = (double) (sampleno) / samprate; 
+      expfactor=1;
+      sample_short[sampleno]= ampmax * sin(sinfreqrad * temp + phaserad) * expfactor;}}
+
+
+/*---------------------------*/
+
+
+
+/* Only do this is step specified: ie, offset or phase ! = 0 */
+
+  offset_samples = (long) 0;
+
+  if (offset_ms != 0) 
+    offset_samples = (long) samprate * offset_ms / 1000;
+  if (phase_deg != 0) 
+    offset_samples = (long) lengthpulse_samples * phase_deg / 360;
+
+  if (offset_samples != 0) {
+    for (sampleno=0; sampleno < lengthwave_samples; sampleno++) {
+      
+      temp = (double) (fmod(sampleno, lengthpulse_samples)) / samprate; 
+      expfactor = exp( -1 * dampcoef * temp ) ; /* * samprate  roy */
+      
+      if (directionflag == FORWARD)
+	localsampleno = sampleno;
+      else
+	localsampleno = lengthwave_samples -2  - sampleno;         
+      /* -2 seems to work */
+
+      temp_samples = (long) fmod(sampleno, lengthpulse_samples);
+      if (temp_samples <= offset_samples)
+	sample_short[localsampleno] = sample_short[localsampleno];
+      else
+/*	sample_short[localsampleno]= fraction * ampmax * sin(sinfreqrad * temp + phaserad) * expfactor + sample_short[localsampleno];
+*
+*      if (gateoption == ON)*/
+	sample_short[localsampleno] = fraction * ampmax * expfactor + sample_short[localsampleno];  
+
+    
+    }}
+
+/*---------------------------------------------------------*/
+
+  fwrite(sample_short, 2, lengthwave_samples, filepointer);        
+  fclose(filepointer);
+  
+  exit(0);
+
+}
+
+
+/* the end */
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xaim/synthirn.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,319 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1994
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/*      synthirn.c
+*      -----------
+* 
+* Makes iterated ripple noise.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#define ON 1
+#define OFF 0
+#define MAXSAMPLES 882000             /* 10 seconds, cd rates */
+#define SAME 4
+#define ORIGINAL 5
+#define SAMPLERATE 20000
+#define DURATION 1000 /* ms */
+#define DELAY 8
+#define GAIN 1.0
+#define ITERATION 4
+
+
+short input[MAXSAMPLES];
+float y[MAXSAMPLES];
+float temp[MAXSAMPLES];
+short output[MAXSAMPLES]; 
+short sample[2];
+
+
+/*----------------------------------------------------------------------*/
+/*----------------------------------------------------------------------*/
+
+
+
+main(int argc, char *argv[])
+{
+  long samplerate = SAMPLERATE;
+  long length=DURATION;
+  long datatype = 0;
+  int counter = 0;
+  int msec = 0;
+
+  int max_iterations = ITERATION;
+  float delay = DELAY;
+  long delay_samples;
+  long arraydelay;
+  double gain =GAIN;
+  double den_gain=GAIN;
+
+  char inputfn[255];
+  char outputfn[256];
+  FILE *inputfp = NULL;
+  FILE *outputfp = NULL;
+
+  int helpflag = OFF;
+  int inputflag = OFF;
+  int outputflag = OFF;
+  int verboseflag = OFF;
+  int x=1;
+  int divideflag = OFF;
+  float dividevalue = 1.0;
+  int typeflag = SAME;
+  long outputlength = DURATION;
+  long outputlength_samples = 0;
+
+
+/*  outputfn=(char *)calloc(255, sizeof(char ));
+  outputfn="IRN-Default-File"; */
+
+  /* Parse command line options. */
+
+  if (argc == 1) 
+    helpflag = ON;
+
+  while (x < argc) {
+    if      (!strcmp(argv[x], "-sample")) { samplerate = atol(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-s")) { samplerate = atol(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-Time")) { outputlength = atol(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-T")) { outputlength = atol(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-help")) { helpflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-h")) { helpflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-verbose")) { verboseflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-v")) { verboseflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-same")) { typeflag = SAME; x+=1;}
+    else if (!strcmp(argv[x], "-S")) { typeflag = SAME; x+=1;}
+    else if (!strcmp(argv[x], "-original")) { typeflag = ORIGINAL; x+=1;}
+    else if (!strcmp(argv[x], "-O")) { typeflag = ORIGINAL; x+=1;}
+    else if (!strcmp(argv[x], "-i")) { max_iterations = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-d")) { delay = atof(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-l")) { delay = atof(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-divide")) { divideflag = ON; dividevalue  = atof(argv[x+1]);x+=2;}
+    else if (!strcmp(argv[x], "-div")) { divideflag = ON; dividevalue  = atof(argv[x+1]);x+=2;}
+    else if (!strcmp(argv[x], "-gain")) { gain = atof(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-g")) { gain = atof(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-input")) { inputflag = ON; strcpy(inputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-in")) { inputflag = ON; strcpy(inputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-output")) { outputflag=ON; strcpy(outputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-out")) { outputflag=ON; strcpy(outputfn, argv[x+1]); x+=2;}
+    else {fprintf(stderr, "synthirn: unknown option %s\n", argv[x]);
+	  exit(-1);}
+  }
+
+
+  if (helpflag == ON) {
+    fprintf(stderr, "\n-------------     synthirn    --------------\n");
+    fprintf(stderr, "Makes an iterated ripple noise. Up to 10 seconds long. \n");
+    fprintf(stderr, "NB:   sample rate < 32767.\n");
+    fprintf(stderr, "\n");
+    fprintf(stderr, "options: \n");
+    fprintf(stderr, "-s    <long>        sampling rate         :Default 20000\n");
+    fprintf(stderr, "-d    <float>       delay (ms)            :Default 8ms\n");
+    fprintf(stderr, "-g    <float>       gain (>=-1.0, <=1.0)  :Default 1.0 \n");
+    fprintf(stderr, "-i    <int>         number of iterations  :Default 4\n");
+    fprintf(stderr, "-T    <long>        length of output (ms) :Default 1000ms \n");
+/*    fprintf(stderr, "-div  <float>    divide input by <float>  \n");  */
+    fprintf(stderr, "\n");
+    fprintf(stderr, "-S                  Make 'Add-Same' IRN   :Default\n");
+    fprintf(stderr, "-O                  Make 'Add-Original' IRN \n");
+
+    fprintf(stderr, "-in  <filename>     input noise \n");
+    fprintf(stderr, "-out <filename>     output-filename \n");
+    fprintf(stderr, "-v                  verbose information\n");
+    fprintf(stderr, "\n");
+    exit(1);
+  }
+
+  if (samplerate == 0) {
+    fprintf(stderr, "synthirn: unspecified sampling rate. \n");
+    exit(-1);
+  }
+
+/* INPUT --------------------------------------*/
+
+  /* Attempt to load input file. */
+  if (inputflag == OFF ) {
+    fprintf(stderr, "synthirn: no input file specified. \n");
+    exit(-1);}
+  if (outputflag == OFF ) {
+    fprintf(stderr, "synthirn: no output file specified.\n");
+    exit(-1);}
+  
+  inputfp = fopen(inputfn, "rb");
+  if (inputfp == NULL) {
+    fprintf(stderr, "synthirn: unable to open file %s.\n", inputfn);
+    exit(-1); }
+
+  /* Clear the arrays */
+  if (verboseflag == ON){
+    fprintf(stderr, "clearing ... ");
+    fflush(stderr);}
+
+  for (x=0; x<MAXSAMPLES; x++){
+    input[x] = 0;
+    }
+
+  /* load input */
+  if (verboseflag == ON){
+    fprintf(stderr, "loading ... ");
+    fflush(stderr);}
+  x=0;
+  while( feof(inputfp) ==0) {
+    fread(sample, 2, 1, inputfp);
+    input[x++] = (int) sample[0];}
+  length = x - 1;
+
+  /* close input */
+  fclose(inputfp);
+
+  
+
+/*----------------------------------------------*/
+
+  /* convert into samples */
+  delay_samples = (long) (delay  * samplerate) / 1000;
+  outputlength_samples = (long) (outputlength  * samplerate) / 1000;
+
+  if (verboseflag == ON){
+    fprintf(stderr, "floats ... ");
+    fflush(stderr);}
+
+  for (x=0; x<length; x++) {
+    if (divideflag == ON) 
+      y[x] = (float) ((float) input[x] )/ dividevalue;
+    else
+      y[x] = (float) input[x];}
+
+
+  /* Do the iterations .... */
+  
+  if (verboseflag == ON){
+    fprintf(stderr, "Gain is %f\n", gain);
+    den_gain=fabs(gain);
+    fprintf(stderr, "Den Gain is %f\n", den_gain);
+    fprintf(stderr, "n: ");
+    fflush(stderr);}
+
+  for (counter = 1; counter <= max_iterations; counter ++) {
+    if (verboseflag == ON){
+      fprintf(stderr, "%i ", counter);
+      fflush(stderr);}
+    
+    /*---------------------------------*/
+
+    if (typeflag == SAME) {
+      arraydelay = delay_samples;
+
+      for (x = 0; x < length;  x++) 
+	temp[x] = (float) y[x];
+
+      for (x = 0; x < arraydelay;  x++) 
+	y[x] = (float) temp[x] + (gain * temp[length - arraydelay + x]) ;
+
+      for (x = arraydelay; x < length;  x++) 
+	y[x] = (float) temp[x] + (gain * temp[x - arraydelay]) ;
+
+      for (x = 0; x < length;  x++) 
+	y[x] = (float) y[x] / (1.0 + den_gain);}
+    
+    /*---------------------------------*/
+
+    else if (typeflag == ORIGINAL) {
+      arraydelay =  delay_samples;
+
+      for (x = 0; x < length;  x++) 
+	temp[x] = (float) y[x];
+
+      for (x = 0; x < arraydelay;  x++)
+	if (divideflag == ON) 
+	  y[x] = (float) ((float) input[x] )/ dividevalue + (den_gain * temp[length -  arraydelay + x]) ;
+	else
+	  y[x] = (float) input[x] + (gain * temp[length - arraydelay + x]); /* div by pow */
+
+      for (x = arraydelay; x < length;  x++)
+	if (divideflag == ON) 
+	  y[x] = (float) ((float) input[x] )/ dividevalue + (den_gain * temp[x -  arraydelay]) ;
+	else
+	  y[x] = (float) input[x] + (gain * temp[x - arraydelay]); 
+        
+     /*   for (x=0; x < length; x++)
+           y[x] = (float) y[x] / (1. + den_gain*temp[x])  ;  */ }
+
+    /*   Not used; makes noisy IRN's . Wrong divisor   */
+
+    /*---------------------------------*/
+
+    else {
+      fprintf(stderr, "synthirn: must specify either 'Same' or 'Original' noise.\n");
+      exit(-1);}
+  }
+
+  if (verboseflag == ON){
+    fprintf(stderr, "normalising ... ");
+    fflush(stderr);}
+
+  /* Normalise */
+  if (typeflag == ORIGINAL) 
+    for (x=0; x<length; x++)
+  /*    output[x] = (short) y[x]; */ 
+      output[x] = (short) (y[x] /((max_iterations*den_gain)+1));  
+  else if (typeflag == SAME)
+    for (x=0; x<length; x++) 
+      output[x] = (short) y[x]; 
+
+  /* reset output positions */
+  arraydelay =  max_iterations * delay_samples;
+
+/* OUTPUT ------------------------------------- */
+  
+  
+  outputfp = fopen(outputfn, "wb");
+  if (outputfn == NULL){
+    fprintf(stderr, "synthirn: unable to open output file %s.\n", outputfn);
+    exit(-1); }
+
+  /* write data */
+  if (verboseflag == ON){
+    fprintf(stderr, "saving ");
+    fflush(stderr);}
+
+  fwrite(output, 2, outputlength_samples, outputfp);
+
+  fclose(outputfp);
+
+  if (verboseflag == ON){
+    fprintf(stderr, "\n");
+    fflush(stderr);}
+}
+
+
+/* The End */
+/*-----------------------------------------------------------------------*/
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xaim/xreview.bitmap	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,58 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+#define xreview_width 50
+#define xreview_height 50
+static char xreview_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x3c, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xce, 0x03, 0x00, 0x00,
+   0x00, 0x00, 0x7e, 0xfe, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xfe, 0x3f,
+   0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0xff,
+   0xff, 0xff, 0x13, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x37, 0x00, 0x00,
+   0x87, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x80, 0xbf, 0xff, 0xff, 0xff, 0x7f,
+   0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x80, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xc0, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0x01, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
+   0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0x03, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xf0, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0x03, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfe, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0x03, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfe, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0x03, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0x03};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xaim/xreview.c	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,614 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/*
+*     xreview
+*    ----------
+* 
+* A program for animating an AIM 'cartoon bitmap'.
+* Requires X windows, but most varieties, r4, r5, Sun OpenWindows
+* (but see also the makefile)
+*
+* The underlying algorithm is:
+*   1. load the entire cartoon into memory, as one contiguos block.
+*   2. compute, and save, the memory locations of each frame's start.
+*   3. Set the memory pointer of an XImage structure to the first one, and draw
+*   4. Reset the pointer to the next frame, and redraw ...
+*   5. Continue for however many frames there are.
+*
+*
+*
+* A large proportion of this was inspired by the "basic window" 
+* program of the O'Reilly X manuals, vol 1. More inspiritaion came from
+* John Holdsworth's code.
+*
+*
+* M.Akeroyd  July 1993.  version 1.00
+*  
+* revisions: MAA: Christmas 1993. rewrites for public release, also some
+*                                 bug fixes.
+*                                 Includes the linux hacks.
+*/
+
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+#include <X11/Xmu/Xmu.h>
+#include <X11/keysym.h>
+#include <X11/cursorfont.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+
+#include "xreview.h"
+#include "./stipple_a"               /* for the Control Window background */
+
+
+
+
+/* Function declarations */
+/*-------------------------------------------------------------------------*/
+
+void parsecommandline (int argc, char *argv[], char inputfn[], char titlestring[], char fontname[]);
+int readheader(FILE *inputfp, char filefn[]); 
+FILE *open_file (char filefn[], FILE *dir_default, int streamtype);
+void close_files (FILE *fp);
+
+
+void initialise_control_window(char *inputfn, char *titlestring, FILE *inputfp, char *argv[], int argc);
+void initialise_axes_window(char *inputfn, char *titlestring, FILE *inputfp, char *argv[], int argc);
+void initialise_buttons();
+void initialise_image();
+
+
+void drawimage(int frame);
+void drawtext(Window win, GC gc, XFontStruct *font_info, unsigned int width, \
+	      unsigned int height, char *text);
+void drawbutton(Window control_win, Window button_local, GC *button_local_gc,\
+		int width, int height, char *text, int fill_ground, \
+		int text_ground);
+void flashbutton(Window top_win, Window button_local, GC *button_local_gc, \
+		 int width, int height, char *text);
+
+void initialise_X_screen();
+void load_font();
+
+
+
+/* Data arrays: global */
+/*-------------------------------------------------------------------------*/
+
+char *data_pointer;
+char *data_pointer_sideways;
+long location[MAX_FRAMES];             /* frames: a reasonably big number */
+int frame = 1;                         /* start frame */
+FILE *inputfp;		
+char inputfn[MAX_STRING_LENGTH];
+
+/* .ctn header */
+/*-------------------------------------------------------------------------*/
+
+char header[MAX_LINES_HEADER][MAX_LINE_LENGTH];
+int header_lines;
+
+int no_frames;
+int frameheight;                       /* number of channels */
+int framewidth_samples;                /* pwidth + nwidth * samplerate */
+int frameshift_samples;                /* frstep_aid * samplerate */
+double frstep_aid;                     /* msecs */
+double pwidth;                         /* msecs */
+double nwidth;                         /* msecs: NEGATIVE */
+int width_ctn;                         /* pixels */
+int height_ctn;                        /* pixels */
+int x_ctn;                             /* pixels */
+int y_ctn;                             /* pixels */
+long samplerate;                       /* samples per sec */
+int mincf;                             /* Hz */
+int maxcf;                             /* Hz */
+
+
+/* misc */
+/*-------------------------------------------------------------------------*/
+
+char progname[MAX_STRING_LENGTH];
+char fontname[MAX_STRING_LENGTH];
+char display_name[MAX_STRING_LENGTH];
+
+int verboseflag = OFF;                 /* -v option */
+int axes_xflag = OFF;                  /* -image_x option */
+int axes_yflag = OFF;                  /* -image_y option */
+int controls_xflag = OFF;              /* -controls_x option */
+int controls_yflag = OFF;              /* -controls_y option */
+int titleflag = OFF;                   /* -title option */
+int bytesflag = OFF;                   /* -lsb, -msb options */
+int bitmap_pad_flag = OFF;             /* ditto */
+int new_axes_x, new_axes_y;      
+int new_control_x, new_control_y;
+int controlwindowflag = OFF;           /* -controls option */
+double scale = 1.0;
+
+long waittime_millisecs = 1;           /* time to wait imbetween frames */
+long waittime_microsecs ;
+
+int animate_start = 1;              /* animation start frame */
+int animate_stop = 9999;            /* animation end frame: gets set to EOF */
+int animate_skip = 1;                /* animation skip */
+
+int sidewaysflag = OFF;
+
+
+
+/* X variables */
+/*-------------------------------------------------------------------------*/
+/* There are 3 classes of window:
+*   "axes window": where the cartoon itself is. Called "axes" for historical
+*                  reasons. Button presses cause (1) animations, or (2) mapping
+*                  of the Controls Window, or (3) exit. This window CANNOT
+*                  be resized.
+*                  Used, reasonably interchangealby, with 'image' 
+*   "controls window": where the Animation Control buttons are. Button presses
+*                       --- if not on a 'button' --- do nothing. This window
+*                      can't be resized either.
+*   "buttons": there are lots of them. eg button_startf. These are subwindows
+*              of the Controls Window. Pressing the left mouse button causes
+*              something exciting to happen.
+*              There are also 'information buttons', which say things
+*              like the filename, number of frames, etc. Pressing one of these
+*              doesn't do anything.
+*/
+
+Display *display;
+int screen_num;
+Screen *screen_ptr;
+int depth = 1;
+unsigned int display_width_X, display_height_X;
+unsigned int display_width, display_height;
+
+Pixmap stipple_pixmap;
+
+
+/* Windows */
+
+toplevelWindow axes;
+toplevelWindow control;
+
+buttonWindow button_quit, button_close;
+buttonWindow button_animate;
+buttonWindow button_startf, button_startb, button_stopf, button_stopb;
+buttonWindow button_skipf, button_skipb, button_faster, button_slower;
+buttonWindow button_firstframe, button_lastframe, button_middle;
+buttonWindow button_stepb, button_stepbb;
+buttonWindow button_stepf, button_stepff;
+buttonWindow info_speed, info_start, info_stop, info_skip;
+buttonWindow info_title, info_frame;
+buttonWindow info_time, info_freq, info_frstep;
+
+XFontStruct *font_info;
+int pointsize = DEFAULT_POINTSIZE;
+GC button_gc;
+int button_borderwidth = 0;
+
+XImage *reviewimage;
+int reviewimage_bytesperline = BYTES_PER_LINE;
+int reviewimage_bitmap_pad = BITMAP_PAD;
+
+Cursor cursor;
+
+XEvent report;
+int depthflag = MONO;                       /* assume a monochrome screen */
+int planemask = 0x1;                        /* works with my colour sparc */
+int xsyncflag = OFF;
+int reversevideoflag = OFF;                 /* gets set to ON if DECstation */
+int byteorderflag = SERVER;                 /* ie, the physical screen */	
+
+
+
+
+
+/* ......................         Main        ..............................*/
+/* .........................................................................*/
+/* .........................................................................*/
+
+
+
+
+void main (int argc, char *argv[])
+{
+  int n; 
+  int header_bytes = 0;
+  int alreadydrawnflag = OFF;
+  
+  char titlestring[MAX_STRING_LENGTH];
+  char tempstring[MAX_STRING_LENGTH];
+
+
+  int required_bytes;
+  long status;
+  long starttime, localtime;
+  long x;
+
+
+/*-----------------------------*/
+  
+  strcpy(progname, argv[0]);
+  strcpy(fontname, "");
+  strcpy(inputfn, "");
+  strcpy(titlestring, "");
+
+  /* Machine specific defaults */
+#ifdef HOST_SPARC
+  byteorderflag = SUN;
+  reversevideoflag = OFF;	
+#endif
+#ifdef HOST_DECSTATION
+  byteorderflag = DEC;
+  reversevideoflag = ON;
+#endif
+#ifdef HOST_LINUXPC
+  byteorderflag = DEC;
+  reversevideoflag = ON;
+#endif
+
+  parsecommandline(argc, argv, inputfn, titlestring, fontname);
+
+/*-----------------------------*/
+
+  /* Open Display: this also finds the screen size */
+  initialise_X_screen();
+
+/*-----------------------------*/
+
+
+  if (xsyncflag == ON) {
+    XSynchronize(display, True);
+    fprintf(stderr, "XSynchronize on \n");}
+
+  inputfp = open_file(inputfn, stdin, READ);
+  header_bytes = readheader(inputfp, inputfn);
+
+/*-----------------------------*/
+
+  /*  define bytes_per_line of the XImage. This seems to be, at least on a 
+   *  Colour SS-10, to be 
+   *        (width-1)
+   *     (  --------- +1 )  *4
+   *            32  
+   *  where the INTEGER part of the division is all that is needed.
+   *
+   *  Examples:
+   *      width=100 to 128  bytes=16  (100 is the smallest AIM window allowed.-
+   *            129 -- 160        20
+   *            161 -- 192        24
+   *            193 -- 224        28
+   */
+
+  reviewimage_bytesperline = (int) ((int) ((width_ctn -1) / 32) +1) *4;
+
+/*-----------------------------*/
+
+  /* Allocate lots of space:
+   * no of frames by .ctn size 
+   */
+
+  if (depthflag == MONO)
+    depth = 1;
+  else 
+    depth = DefaultDepth(display, screen_num);
+  
+  required_bytes = no_frames*height_ctn*reviewimage_bytesperline*depth;
+  
+  if (verboseflag == ON) {
+    fprintf(stderr, "xreview : reserving %i * %i * %i = %i bytes.\n", no_frames, (height_ctn*reviewimage_bytesperline), depth, required_bytes); }
+
+  data_pointer = (char *) malloc((size_t) required_bytes);
+  if (data_pointer == NULL) {
+    fprintf(stderr, "xreview : unable to allocate %i bytes for XImage.\n", required_bytes);
+    fclose(inputfp);
+    exit(-1);}
+
+  /* sideways scroll */
+  if (sidewaysflag == ON) {
+    required_bytes = no_frames*height_ctn*reviewimage_bytesperline*depth;
+    if (verboseflag == ON) {
+      fprintf(stderr, "xreview : reserving %i * %i = %i bytes.\n", (no_frames*height_ctn*reviewimage_bytesperline), depth, required_bytes); }
+    data_pointer_sideways = (char *) malloc((size_t) required_bytes);
+    if (data_pointer_sideways == NULL) {
+      fprintf(stderr, "xreview : unable to allocate %i bytes for XImage.\n", required_bytes);
+      fclose(inputfp);
+      exit(-1);}}
+
+/*-----------------------------*/
+
+  /* load .ctn data */
+  loaddata(inputfp);
+  close_files(inputfp);
+  if (animate_stop == 9999)
+    animate_stop = no_frames;
+
+  if (sidewaysflag == ON) {
+    for (x=location[0]; x<=location[0]+required_bytes-1; x++)
+      data_pointer_sideways[x] = data_pointer[x];}
+
+/*-----------------------------*/  
+
+  /* Find a font, in this order:
+   *   1. command-line
+   *   2. Times family
+   *   3. Lucida family.
+   * If can't find any, should crash. 
+   */
+
+  font_info = NULL;
+
+  if ((strcmp(fontname, "") == 0 ) ||
+      ((font_info = XLoadQueryFont(display, fontname)) == NULL)) {
+    sprintf(fontname, "-adobe-times-medium-r-normal--%i-*-*-*-*-*-*-*", pointsize);
+    if ((font_info = XLoadQueryFont(display, fontname)) == NULL) {
+      sprintf(fontname, "-b&h-lucida-medium-r-normal-sans-%i-*-*-*-*-*-*-*", pointsize);
+      if ((font_info = XLoadQueryFont(display, fontname)) == NULL) {
+	fprintf(stderr, "xreview : unable to find fonts.\n");
+	exit(-1); }}}
+
+/*-----------------------------*/
+
+  /* define a cursor */
+  cursor = XCreateFontCursor(display, XC_top_left_arrow);
+
+/*-----------------------------*/
+  
+  initialise_axes_window(inputfn, titlestring, inputfp, argv, argc);
+  XMapWindow(display, axes.win);
+
+  /* define the background pixmap */
+  stipple_pixmap = XCreatePixmapFromBitmapData(display, \
+			   RootWindow(display, screen_num), stipple_a_bits, \
+			   stipple_a_width, stipple_a_height, \
+			   BlackPixel(display, screen_num), \
+                           WhitePixel(display, screen_num), \
+			   DefaultDepth(display, screen_num));
+
+  initialise_control_window(inputfn, titlestring, inputfp, argv, argc); 
+  if (controlwindowflag == ON)
+    XMapWindow(display, control.win);
+
+  initialise_buttons();
+
+  initialise_image();
+
+/*------------------------------*/
+
+  
+
+/*-----------------------------
+ * EVENT LOOP 
+ *-----------------------------
+ */
+
+
+
+  while (1) {
+    XNextEvent(display, &report);
+
+    if (report.xany.window == axes.win) 
+      switch_axes();
+    else if (report.xany.window == control.win) 
+      switch_control();
+    else 
+      switch_buttons();
+
+  } /* while */
+
+
+  /*---------------------------------------------------------*/
+
+    
+} /* main */
+      
+      
+
+
+
+/*......................................................................*/
+/*......................................................................*/
+
+
+
+
+
+void parsecommandline(int argc, char *argv[], char inputfn[], char titlestring[], char fontname[])
+{
+  int x=1, helpflag = OFF;
+  int control_width =0;
+  char control_size[MAX_STRING_LENGTH];
+
+  strcpy(control_size, "");
+
+  while (x < argc){
+    if      (!strcmp(argv[x], "-input")) {strcpy(inputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-inp")) {strcpy(inputfn, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-i")) {strcpy(inputfn, argv[x+1]); x+=2;}
+
+    else if (!strcmp(argv[x], "-help")) {helpflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-h")) {helpflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-verbose")) {verboseflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-ver")) {verboseflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-v")) {verboseflag = ON; x+=1;}
+
+    else if (!strcmp(argv[x], "-side")) {sidewaysflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-sideways")) {sidewaysflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-controls")) {controlwindowflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-con")) {controlwindowflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-c")) {controlwindowflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-controls_x")) {controls_xflag = ON; new_control_x = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-cx")) {controls_xflag = ON; new_control_x = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-controls_y")) {controls_yflag = ON; new_control_y = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-cy")) {controls_yflag = ON; new_control_y = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-image_x")) {axes_xflag = ON; new_axes_x = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-ix")) {axes_xflag = ON; new_axes_x = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-image_y")) {axes_yflag = ON; new_axes_y = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-iy")) {axes_yflag = ON; new_axes_y = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-controls_scale")) {scale = atof(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-cscale")) {scale = atof(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-controls_width")) {control_width = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-cw")) {control_width = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-controls_size")) {strcpy(control_size, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-csize")) {strcpy(control_size, argv[x+1]); x+=2;}
+
+    else if (!strcmp(argv[x], "-display")) {strcpy(display_name, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-d")) {strcpy(display_name, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-font")) {strcpy(fontname, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-fn")) {strcpy(fontname, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-point")) {pointsize = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-p")) {pointsize = atoi(argv[x+1]); x+=2;}
+
+    else if (!strcmp(argv[x], "-wait")) {waittime_millisecs = atol(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-w")) {waittime_millisecs = atol(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-speed")) {waittime_millisecs = atol(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-start")) {animate_start = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-stop")) {animate_stop = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-skip")) {animate_skip = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-frame")) {frame = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-fra")) {frame = atoi(argv[x+1]); x+=2;}
+
+    else if (!strcmp(argv[x], "-title")) {titleflag = ON; strcpy(titlestring, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-tit")) {titleflag = ON; strcpy(titlestring, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-t")) {titleflag = ON; strcpy(titlestring, argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-mono")) {depthflag = MONO;  x+=1;}
+    else if (!strcmp(argv[x], "-colour")) {depthflag = COLOUR;  planemask = AllPlanes; x+=1; }
+    else if (!strcmp(argv[x], "-planemask")) {planemask = atoi(argv[x+1]); x+=2;}
+    else if (!strcmp(argv[x], "-xsync")) {xsyncflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-rv")) {if (reversevideoflag == ON) 
+	                                  reversevideoflag = OFF;
+                                       else
+                                          reversevideoflag = ON;
+                                       x+=1;}
+    else if (!strcmp(argv[x], "-lsb")) {byteorderflag = DEC; x+=1;}
+    else if (!strcmp(argv[x], "-msb")) {byteorderflag = SUN; x+=1;}
+    else if (!strcmp(argv[x], "-dec")) {byteorderflag = DEC; reversevideoflag = ON; x+=1;}
+    else if (!strcmp(argv[x], "-sun")) {byteorderflag = SUN; reversevideoflag = OFF; x+=1;}
+    else if (x = (argc-1)) {strcpy(inputfn, argv[x]); x+=1;}
+
+    else {fprintf(stderr, "xreview: unknown option %s\n", argv[x]);
+          exit(-1);}
+
+  }
+  
+  if (helpflag == ON)
+    {
+      fprintf(stderr, "\n");
+      fprintf(stderr, "--------------------------------------------------------------------------------\n");
+      fprintf(stderr, "                              xreview\n");
+      fprintf(stderr, "--------------------------------------------------------------------------------\n\n");
+      fprintf(stderr, " usage: xreview -input 'filename.ctn' <options> \n");
+      fprintf(stderr, "  or    xreview <options> 'filename.ctn' \n");
+      fprintf(stderr, "  or    cat 'filename.ctn' | xreview <options>  \n\n\n");
+      fprintf(stderr, "                       Command line options                              Abbrev.\n");
+      fprintf(stderr, "--------------------------------------------------------------------------------\n");
+      fprintf(stderr, "-input <.ctn file>    Input file  (default = stdin).                     -i\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, "-controls             Map Controls window.                               -con\n");
+      fprintf(stderr, "-controls_x <int>     Controls window position (pixels).                 -cx\n");
+      fprintf(stderr, "-controls_y <int>     Controls window position (pixels).                 -cy\n");
+      fprintf(stderr, "-controls_width <int> Controls window width (pixels).                    -cw\n");
+      fprintf(stderr, "-controls_scale <flt> Scale factor for size of Controls Window.          -cscale\n");
+      fprintf(stderr, "-controls_size        Controls Window size: 'tiny', 'small' or 'normal'. -csize\n");
+      fprintf(stderr, "-image_x <int>        Image position (pixels).                           -ix\n");
+      fprintf(stderr, "-image_y <int>        Image position (pixels).                           -iy\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, "-display <string>     X Display server to use.                           -d\n");
+      fprintf(stderr, "-font <string>        Font.                                              -fn\n");
+      fprintf(stderr, "-point <int>          Point-size of default font (Times, medium weight). -p\n");
+      fprintf(stderr, "-title <string>       Title of Image window & icon.                      -t\n");
+      fprintf(stderr, "-mono                 Assume Monochrome (single-plane) cartoons. (default)  \n");
+      fprintf(stderr, "-colour               Assume Colour (multiplane) cartoons.                  \n");
+      fprintf(stderr, "-planemask <int>      Value of PlaneMask for copying XImage (default=1)     \n");  
+      fprintf(stderr, "-rv                   Reverse-video the cartoon window colours.             \n");
+      fprintf(stderr, "-lsb                  Assume cartoon's bit & byte orders are LSBFirst (ie, DEC).\n");
+      fprintf(stderr, "-msb                  Assume cartoon's bit & byte orders are MSBFirst (ie, Sun).\n");
+      fprintf(stderr, "-dec                  Alias for -lsb -rv \n");
+      fprintf(stderr, "-sun                  Alias for -msb \n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, "-speed <int>          Wait-time between frames (msecs) (default = %i).    -speed\n", waittime_millisecs); 
+      fprintf(stderr, "-start <int>          Animation start (frames) (default=1).              -start\n"); 
+      fprintf(stderr, "-stop <int>           Animation stop (frames) (default=last frame).      -stop\n"); 
+      fprintf(stderr, "-skip <int>           Animation skip (frames) (default=1).               -skip\n"); 
+      fprintf(stderr, "-frame <int>          Initial display frame (default=1).                 -fra\n"); 
+      fprintf(stderr, "-sideways             Scroll cartoon sideways (right->left)              -side\n");
+      fprintf(stderr, "\n");
+      fprintf(stderr, "-verbose              Print some running information (to stderr).        -v\n");
+      fprintf(stderr, "-help                 Print this page (to stderr).                       -h\n");
+      fprintf(stderr, "\n\n" );
+      fprintf(stderr, "                       Image Window Controls \n");
+      fprintf(stderr, "--------------------------------------------------------------------------------\n");
+      fprintf(stderr, " Left button          Animate cartoon. \n");
+      fprintf(stderr, " Middle button        Map Controls window. \n");
+      fprintf(stderr, " Right button         Quit. \n\n");
+      fprintf(stderr, " SPACE or RET         Animate cartoon. \n");
+      fprintf(stderr, " F or f               Set speed faster by x2. \n");
+      fprintf(stderr, " S or s               Set speed slower by x2. \n");
+      fprintf(stderr, " N or n               Next frame. \n");
+      fprintf(stderr, " P or p               Previous frame. \n");
+      fprintf(stderr, " Q or q               Quit. \n");
+      fprintf(stderr, "\n\n");
+      exit(-1);}
+
+  if (strcmp(control_size, "") != 0){
+    if (strcmp(control_size, "normal") == 0) {
+      scale=1.00;
+      pointsize=18;}
+    else if (strcmp(control_size, "small") == 0) {
+      scale=0.80;
+      pointsize=14;}
+    else if (strcmp(control_size, "tiny") == 0) {
+      scale=0.60;
+      pointsize=10;}
+    else {
+      fprintf(stderr, "xreview : illegal control_size value.\n");
+      exit(-1);}
+  }
+
+  if (control_width != 0)
+    scale = (double) control_width /  CONTROL_WIDTH;
+
+
+}  
+
+
+/* The end.*/
+
+
+/*-------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xaim/xreview.h	Fri May 20 15:19:45 2011 +0100
@@ -0,0 +1,127 @@
+/*
+    Copyright (c) Applied Psychology Unit, Medical Research Council. 1993
+    ===========================================================================
+
+    Permission to use, copy, modify, and distribute this software without fee 
+    is hereby granted for research purposes, provided that this copyright 
+    notice appears in all copies and in all supporting documentation, and that 
+    the software is not redistributed for any fee (except for a nominal 
+    shipping charge). Anyone wanting to incorporate all or part of this 
+    software in a commercial product must obtain a license from the Medical 
+    Research Council.
+
+    The MRC makes no representations about the suitability of this 
+    software for any purpose.  It is provided "as is" without express or 
+    implied warranty.
+ 
+    THE MRC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 
+    ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
+    THE A.P.U. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES 
+    OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 
+    WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 
+    SOFTWARE.
+*/
+
+/* 
+*   xreview.h
+*   ---------
+*
+*
+*  M. Akeroyd.  July 1993. version 1.00
+*
+*/
+
+
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+#include <X11/Xmu/Xmu.h>
+#include <X11/keysym.h>
+
+#define BITMAPDEPTH 1
+#define TOO_SMALL_X 0
+#define BIG_ENOUGH_X 1
+#define TOO_BIG_X 2
+#define MIN_WIDTH_XWINDOW 200            /* in pixels */
+#define MIN_HEIGHT_XWINDOW 200           /* in pixels */
+
+#define LINE_WIDTH_X 0
+#define LINE_STYLE_X LineSolid
+#define CAP_STYLE_X CapButt
+#define JOIN_STYLE_X JoinRound
+
+#define DEFAULT_POINTSIZE 18             /* of the font */   
+
+#define BYTES_PER_LINE 64
+#define BITMAP_PAD 8
+
+#define CONTROL_WIDTH 610                 /* pixels */
+#define CONTROL_HEIGHT 210                /* pixels */
+#define CONTROL_X 100                     /* pixels */
+#define CONTROL_Y 600                     /* pixels */
+
+
+#define MAX_LINES_HEADER       100        /* 69 is what .ctns are */
+#define MAX_LINE_LENGTH         80        /* of a header : width of an xterm */
+#define MAX_FRAMES 1000
+
+#define MAX_STRING_LENGTH 255             /* of a filename, etc */
+#define NULL_STRING ""
+
+#define OFF 0
+#define ON 1
+
+#define READ             31               /* used in fopen as "rb" */
+#define WRITE            32               /* used in fopen as "wb" */
+
+#define INPUT_EXT ".ctn"
+
+#define MONO 10
+#define COLOUR 11
+#define SERVER 12
+#define DEC 13
+#define SUN 14
+
+/* WARNING: fonts are left out */
+
+typedef struct top_level_Window {
+  Window win;
+  unsigned int width;
+  unsigned int height;
+  int x;
+  int y;
+  unsigned int border_width;
+  int window_size;
+  char *window_name;
+  char *icon_name;
+  Pixmap icon_pixmap;
+  XSizeHints size_hints;
+  XEvent report;
+  GC gc;
+  XWMHints wm_hints;
+  XClassHint class_hints;
+  XTextProperty windowName;
+  XTextProperty iconName;
+  unsigned long valuemask;
+  XGCValues values;
+  unsigned int line_width;
+  unsigned int line_style;
+  unsigned int cap_style;
+  unsigned int join_style;
+  unsigned int foreground;
+} toplevelWindow;
+
+
+typedef struct button_window {
+  Window win;
+  unsigned int width;
+  unsigned int height;
+  int x;
+  int y;
+} buttonWindow;
+
+
+